summaryrefslogtreecommitdiffstats
path: root/contrib/tcpdump/print-snmp.c
diff options
context:
space:
mode:
authorrpaulo <rpaulo@FreeBSD.org>2009-03-20 13:27:51 +0000
committerrpaulo <rpaulo@FreeBSD.org>2009-03-20 13:27:51 +0000
commit04b1d6babecbe3eed463c150b6e933a2b6d342a9 (patch)
tree36afae3dff76dde8d1cee5971ff7f1bc4922ad0f /contrib/tcpdump/print-snmp.c
parent3b74598d7ea581deadb14ec8ba1c77c14295a7c8 (diff)
downloadFreeBSD-src-04b1d6babecbe3eed463c150b6e933a2b6d342a9.zip
FreeBSD-src-04b1d6babecbe3eed463c150b6e933a2b6d342a9.tar.gz
Flatten vendor/tcpdump and remove keyword expansion.
Diffstat (limited to 'contrib/tcpdump/print-snmp.c')
-rw-r--r--contrib/tcpdump/print-snmp.c1904
1 files changed, 0 insertions, 1904 deletions
diff --git a/contrib/tcpdump/print-snmp.c b/contrib/tcpdump/print-snmp.c
deleted file mode 100644
index 0686b62..0000000
--- a/contrib/tcpdump/print-snmp.c
+++ /dev/null
@@ -1,1904 +0,0 @@
-/*
- * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996, 1997
- * John Robert LoVerso. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *
- * This implementation has been influenced by the CMU SNMP release,
- * by Steve Waldbusser. However, this shares no code with that system.
- * Additional ASN.1 insight gained from Marshall T. Rose's _The_Open_Book_.
- * Earlier forms of this implementation were derived and/or inspired by an
- * awk script originally written by C. Philip Wood of LANL (but later
- * heavily modified by John Robert LoVerso). The copyright notice for
- * that work is preserved below, even though it may not rightly apply
- * to this file.
- *
- * Support for SNMPv2c/SNMPv3 and the ability to link the module against
- * the libsmi was added by J. Schoenwaelder, Copyright (c) 1999.
- *
- * This started out as a very simple program, but the incremental decoding
- * (into the BE structure) complicated things.
- *
- # Los Alamos National Laboratory
- #
- # Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996, 1997
- # This software was produced under a U.S. Government contract
- # (W-7405-ENG-36) by Los Alamos National Laboratory, which is
- # operated by the University of California for the U.S. Department
- # of Energy. The U.S. Government is licensed to use, reproduce,
- # and distribute this software. Permission is granted to the
- # public to copy and use this software without charge, provided
- # that this Notice and any statement of authorship are reproduced
- # on all copies. Neither the Government nor the University makes
- # any warranty, express or implied, or assumes any liability or
- # responsibility for the use of this software.
- # @(#)snmp.awk.x 1.1 (LANL) 1/15/90
- */
-
-#ifndef lint
-static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-snmp.c,v 1.62.2.2 2005/05/06 07:57:19 guy Exp $ (LBL)";
-#endif
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <tcpdump-stdinc.h>
-
-#include <stdio.h>
-#include <string.h>
-
-#ifdef HAVE_SMI_H
-#include <smi.h>
-#endif
-
-#include "interface.h"
-#include "addrtoname.h"
-
-#undef OPAQUE /* defined in <wingdi.h> */
-
-/*
- * Universal ASN.1 types
- * (we only care about the tag values for those allowed in the Internet SMI)
- */
-const char *Universal[] = {
- "U-0",
- "Boolean",
- "Integer",
-#define INTEGER 2
- "Bitstring",
- "String",
-#define STRING 4
- "Null",
-#define ASN_NULL 5
- "ObjID",
-#define OBJECTID 6
- "ObjectDes",
- "U-8","U-9","U-10","U-11", /* 8-11 */
- "U-12","U-13","U-14","U-15", /* 12-15 */
- "Sequence",
-#define SEQUENCE 16
- "Set"
-};
-
-/*
- * Application-wide ASN.1 types from the Internet SMI and their tags
- */
-const char *Application[] = {
- "IpAddress",
-#define IPADDR 0
- "Counter",
-#define COUNTER 1
- "Gauge",
-#define GAUGE 2
- "TimeTicks",
-#define TIMETICKS 3
- "Opaque",
-#define OPAQUE 4
- "C-5",
- "Counter64"
-#define COUNTER64 6
-};
-
-/*
- * Context-specific ASN.1 types for the SNMP PDUs and their tags
- */
-const char *Context[] = {
- "GetRequest",
-#define GETREQ 0
- "GetNextRequest",
-#define GETNEXTREQ 1
- "GetResponse",
-#define GETRESP 2
- "SetRequest",
-#define SETREQ 3
- "Trap",
-#define TRAP 4
- "GetBulk",
-#define GETBULKREQ 5
- "Inform",
-#define INFORMREQ 6
- "V2Trap",
-#define V2TRAP 7
- "Report"
-#define REPORT 8
-};
-
-#define NOTIFY_CLASS(x) (x == TRAP || x == V2TRAP || x == INFORMREQ)
-#define READ_CLASS(x) (x == GETREQ || x == GETNEXTREQ || x == GETBULKREQ)
-#define WRITE_CLASS(x) (x == SETREQ)
-#define RESPONSE_CLASS(x) (x == GETRESP)
-#define INTERNAL_CLASS(x) (x == REPORT)
-
-/*
- * Context-specific ASN.1 types for the SNMP Exceptions and their tags
- */
-const char *Exceptions[] = {
- "noSuchObject",
-#define NOSUCHOBJECT 0
- "noSuchInstance",
-#define NOSUCHINSTANCE 1
- "endOfMibView",
-#define ENDOFMIBVIEW 2
-};
-
-/*
- * Private ASN.1 types
- * The Internet SMI does not specify any
- */
-const char *Private[] = {
- "P-0"
-};
-
-/*
- * error-status values for any SNMP PDU
- */
-const char *ErrorStatus[] = {
- "noError",
- "tooBig",
- "noSuchName",
- "badValue",
- "readOnly",
- "genErr",
- "noAccess",
- "wrongType",
- "wrongLength",
- "wrongEncoding",
- "wrongValue",
- "noCreation",
- "inconsistentValue",
- "resourceUnavailable",
- "commitFailed",
- "undoFailed",
- "authorizationError",
- "notWritable",
- "inconsistentName"
-};
-#define DECODE_ErrorStatus(e) \
- ( e >= 0 && (size_t)e < sizeof(ErrorStatus)/sizeof(ErrorStatus[0]) \
- ? ErrorStatus[e] \
- : (snprintf(errbuf, sizeof(errbuf), "err=%u", e), errbuf))
-
-/*
- * generic-trap values in the SNMP Trap-PDU
- */
-const char *GenericTrap[] = {
- "coldStart",
- "warmStart",
- "linkDown",
- "linkUp",
- "authenticationFailure",
- "egpNeighborLoss",
- "enterpriseSpecific"
-#define GT_ENTERPRISE 6
-};
-#define DECODE_GenericTrap(t) \
- ( t >= 0 && (size_t)t < sizeof(GenericTrap)/sizeof(GenericTrap[0]) \
- ? GenericTrap[t] \
- : (snprintf(buf, sizeof(buf), "gt=%d", t), buf))
-
-/*
- * ASN.1 type class table
- * Ties together the preceding Universal, Application, Context, and Private
- * type definitions.
- */
-#define defineCLASS(x) { "x", x, sizeof(x)/sizeof(x[0]) } /* not ANSI-C */
-struct {
- const char *name;
- const char **Id;
- int numIDs;
- } Class[] = {
- defineCLASS(Universal),
-#define UNIVERSAL 0
- defineCLASS(Application),
-#define APPLICATION 1
- defineCLASS(Context),
-#define CONTEXT 2
- defineCLASS(Private),
-#define PRIVATE 3
- defineCLASS(Exceptions),
-#define EXCEPTIONS 4
-};
-
-/*
- * defined forms for ASN.1 types
- */
-const char *Form[] = {
- "Primitive",
-#define PRIMITIVE 0
- "Constructed",
-#define CONSTRUCTED 1
-};
-
-/*
- * A structure for the OID tree for the compiled-in MIB.
- * This is stored as a general-order tree.
- */
-struct obj {
- const char *desc; /* name of object */
- u_char oid; /* sub-id following parent */
- u_char type; /* object type (unused) */
- struct obj *child, *next; /* child and next sibling pointers */
-} *objp = NULL;
-
-/*
- * Include the compiled in SNMP MIB. "mib.h" is produced by feeding
- * RFC-1156 format files into "makemib". "mib.h" MUST define at least
- * a value for `mibroot'.
- *
- * In particular, this is gross, as this is including initialized structures,
- * and by right shouldn't be an "include" file.
- */
-#include "mib.h"
-
-/*
- * This defines a list of OIDs which will be abbreviated on output.
- * Currently, this includes the prefixes for the Internet MIB, the
- * private enterprises tree, and the experimental tree.
- */
-struct obj_abrev {
- const char *prefix; /* prefix for this abrev */
- struct obj *node; /* pointer into object table */
- const char *oid; /* ASN.1 encoded OID */
-} obj_abrev_list[] = {
-#ifndef NO_ABREV_MIB
- /* .iso.org.dod.internet.mgmt.mib */
- { "", &_mib_obj, "\53\6\1\2\1" },
-#endif
-#ifndef NO_ABREV_ENTER
- /* .iso.org.dod.internet.private.enterprises */
- { "E:", &_enterprises_obj, "\53\6\1\4\1" },
-#endif
-#ifndef NO_ABREV_EXPERI
- /* .iso.org.dod.internet.experimental */
- { "X:", &_experimental_obj, "\53\6\1\3" },
-#endif
-#ifndef NO_ABBREV_SNMPMODS
- /* .iso.org.dod.internet.snmpV2.snmpModules */
- { "S:", &_snmpModules_obj, "\53\6\1\6\3" },
-#endif
- { 0,0,0 }
-};
-
-/*
- * This is used in the OID print routine to walk down the object tree
- * rooted at `mibroot'.
- */
-#define OBJ_PRINT(o, suppressdot) \
-{ \
- if (objp) { \
- do { \
- if ((o) == objp->oid) \
- break; \
- } while ((objp = objp->next) != NULL); \
- } \
- if (objp) { \
- printf(suppressdot?"%s":".%s", objp->desc); \
- objp = objp->child; \
- } else \
- printf(suppressdot?"%u":".%u", (o)); \
-}
-
-/*
- * This is the definition for the Any-Data-Type storage used purely for
- * temporary internal representation while decoding an ASN.1 data stream.
- */
-struct be {
- u_int32_t asnlen;
- union {
- caddr_t raw;
- int32_t integer;
- u_int32_t uns;
- const u_char *str;
- struct {
- u_int32_t high;
- u_int32_t low;
- } uns64;
- } data;
- u_short id;
- u_char form, class; /* tag info */
- u_char type;
-#define BE_ANY 255
-#define BE_NONE 0
-#define BE_NULL 1
-#define BE_OCTET 2
-#define BE_OID 3
-#define BE_INT 4
-#define BE_UNS 5
-#define BE_STR 6
-#define BE_SEQ 7
-#define BE_INETADDR 8
-#define BE_PDU 9
-#define BE_UNS64 10
-#define BE_NOSUCHOBJECT 128
-#define BE_NOSUCHINST 129
-#define BE_ENDOFMIBVIEW 130
-};
-
-/*
- * SNMP versions recognized by this module
- */
-const char *SnmpVersion[] = {
- "SNMPv1",
-#define SNMP_VERSION_1 0
- "SNMPv2c",
-#define SNMP_VERSION_2 1
- "SNMPv2u",
-#define SNMP_VERSION_2U 2
- "SNMPv3"
-#define SNMP_VERSION_3 3
-};
-
-/*
- * Defaults for SNMP PDU components
- */
-#define DEF_COMMUNITY "public"
-
-/*
- * constants for ASN.1 decoding
- */
-#define OIDMUX 40
-#define ASNLEN_INETADDR 4
-#define ASN_SHIFT7 7
-#define ASN_SHIFT8 8
-#define ASN_BIT8 0x80
-#define ASN_LONGLEN 0x80
-
-#define ASN_ID_BITS 0x1f
-#define ASN_FORM_BITS 0x20
-#define ASN_FORM_SHIFT 5
-#define ASN_CLASS_BITS 0xc0
-#define ASN_CLASS_SHIFT 6
-
-#define ASN_ID_EXT 0x1f /* extension ID in tag field */
-
-/*
- * This decodes the next ASN.1 object in the stream pointed to by "p"
- * (and of real-length "len") and stores the intermediate data in the
- * provided BE object.
- *
- * This returns -l if it fails (i.e., the ASN.1 stream is not valid).
- * O/w, this returns the number of bytes parsed from "p".
- */
-static int
-asn1_parse(register const u_char *p, u_int len, struct be *elem)
-{
- u_char form, class, id;
- int i, hdr;
-
- elem->asnlen = 0;
- elem->type = BE_ANY;
- if (len < 1) {
- fputs("[nothing to parse]", stdout);
- return -1;
- }
- TCHECK(*p);
-
- /*
- * it would be nice to use a bit field, but you can't depend on them.
- * +---+---+---+---+---+---+---+---+
- * + class |frm| id |
- * +---+---+---+---+---+---+---+---+
- * 7 6 5 4 3 2 1 0
- */
- id = *p & ASN_ID_BITS; /* lower 5 bits, range 00-1f */
-#ifdef notdef
- form = (*p & 0xe0) >> 5; /* move upper 3 bits to lower 3 */
- class = form >> 1; /* bits 7&6 -> bits 1&0, range 0-3 */
- form &= 0x1; /* bit 5 -> bit 0, range 0-1 */
-#else
- form = (u_char)(*p & ASN_FORM_BITS) >> ASN_FORM_SHIFT;
- class = (u_char)(*p & ASN_CLASS_BITS) >> ASN_CLASS_SHIFT;
-#endif
- elem->form = form;
- elem->class = class;
- elem->id = id;
- p++; len--; hdr = 1;
- /* extended tag field */
- if (id == ASN_ID_EXT) {
- /*
- * The ID follows, as a sequence of octets with the
- * 8th bit set and the remaining 7 bits being
- * the next 7 bits of the value, terminated with
- * an octet with the 8th bit not set.
- *
- * First, assemble all the octets with the 8th
- * bit set. XXX - this doesn't handle a value
- * that won't fit in 32 bits.
- */
- for (id = 0; *p & ASN_BIT8; len--, hdr++, p++) {
- if (len < 1) {
- fputs("[Xtagfield?]", stdout);
- return -1;
- }
- TCHECK(*p);
- id = (id << 7) | (*p & ~ASN_BIT8);
- }
- if (len < 1) {
- fputs("[Xtagfield?]", stdout);
- return -1;
- }
- TCHECK(*p);
- elem->id = id = (id << 7) | *p;
- --len;
- ++hdr;
- ++p;
- }
- if (len < 1) {
- fputs("[no asnlen]", stdout);
- return -1;
- }
- TCHECK(*p);
- elem->asnlen = *p;
- p++; len--; hdr++;
- if (elem->asnlen & ASN_BIT8) {
- u_int32_t noct = elem->asnlen % ASN_BIT8;
- elem->asnlen = 0;
- if (len < noct) {
- printf("[asnlen? %d<%d]", len, noct);
- return -1;
- }
- TCHECK2(*p, noct);
- for (; noct-- > 0; len--, hdr++)
- elem->asnlen = (elem->asnlen << ASN_SHIFT8) | *p++;
- }
- if (len < elem->asnlen) {
- printf("[len%d<asnlen%u]", len, elem->asnlen);
- return -1;
- }
- if (form >= sizeof(Form)/sizeof(Form[0])) {
- printf("[form?%d]", form);
- return -1;
- }
- if (class >= sizeof(Class)/sizeof(Class[0])) {
- printf("[class?%c/%d]", *Form[form], class);
- return -1;
- }
- if ((int)id >= Class[class].numIDs) {
- printf("[id?%c/%s/%d]", *Form[form], Class[class].name, id);
- return -1;
- }
-
- switch (form) {
- case PRIMITIVE:
- switch (class) {
- case UNIVERSAL:
- switch (id) {
- case STRING:
- elem->type = BE_STR;
- elem->data.str = p;
- break;
-
- case INTEGER: {
- register int32_t data;
- elem->type = BE_INT;
- data = 0;
-
- TCHECK2(*p, elem->asnlen);
- if (*p & ASN_BIT8) /* negative */
- data = -1;
- for (i = elem->asnlen; i-- > 0; p++)
- data = (data << ASN_SHIFT8) | *p;
- elem->data.integer = data;
- break;
- }
-
- case OBJECTID:
- elem->type = BE_OID;
- elem->data.raw = (caddr_t)p;
- break;
-
- case ASN_NULL:
- elem->type = BE_NULL;
- elem->data.raw = NULL;
- break;
-
- default:
- elem->type = BE_OCTET;
- elem->data.raw = (caddr_t)p;
- printf("[P/U/%s]",
- Class[class].Id[id]);
- break;
- }
- break;
-
- case APPLICATION:
- switch (id) {
- case IPADDR:
- elem->type = BE_INETADDR;
- elem->data.raw = (caddr_t)p;
- break;
-
- case COUNTER:
- case GAUGE:
- case TIMETICKS: {
- register u_int32_t data;
- TCHECK2(*p, elem->asnlen);
- elem->type = BE_UNS;
- data = 0;
- for (i = elem->asnlen; i-- > 0; p++)
- data = (data << 8) + *p;
- elem->data.uns = data;
- break;
- }
-
- case COUNTER64: {
- register u_int32_t high, low;
- TCHECK2(*p, elem->asnlen);
- elem->type = BE_UNS64;
- high = 0, low = 0;
- for (i = elem->asnlen; i-- > 0; p++) {
- high = (high << 8) |
- ((low & 0xFF000000) >> 24);
- low = (low << 8) | *p;
- }
- elem->data.uns64.high = high;
- elem->data.uns64.low = low;
- break;
- }
-
- default:
- elem->type = BE_OCTET;
- elem->data.raw = (caddr_t)p;
- printf("[P/A/%s]",
- Class[class].Id[id]);
- break;
- }
- break;
-
- case CONTEXT:
- switch (id) {
- case NOSUCHOBJECT:
- elem->type = BE_NOSUCHOBJECT;
- elem->data.raw = NULL;
- break;
-
- case NOSUCHINSTANCE:
- elem->type = BE_NOSUCHINST;
- elem->data.raw = NULL;
- break;
-
- case ENDOFMIBVIEW:
- elem->type = BE_ENDOFMIBVIEW;
- elem->data.raw = NULL;
- break;
- }
- break;
-
- default:
- printf("[P/%s/%s]",
- Class[class].name, Class[class].Id[id]);
- TCHECK2(*p, elem->asnlen);
- elem->type = BE_OCTET;
- elem->data.raw = (caddr_t)p;
- break;
- }
- break;
-
- case CONSTRUCTED:
- switch (class) {
- case UNIVERSAL:
- switch (id) {
- case SEQUENCE:
- elem->type = BE_SEQ;
- elem->data.raw = (caddr_t)p;
- break;
-
- default:
- elem->type = BE_OCTET;
- elem->data.raw = (caddr_t)p;
- printf("C/U/%s", Class[class].Id[id]);
- break;
- }
- break;
-
- case CONTEXT:
- elem->type = BE_PDU;
- elem->data.raw = (caddr_t)p;
- break;
-
- default:
- elem->type = BE_OCTET;
- elem->data.raw = (caddr_t)p;
- printf("C/%s/%s",
- Class[class].name, Class[class].Id[id]);
- break;
- }
- break;
- }
- p += elem->asnlen;
- len -= elem->asnlen;
- return elem->asnlen + hdr;
-
-trunc:
- fputs("[|snmp]", stdout);
- return -1;
-}
-
-/*
- * Display the ASN.1 object represented by the BE object.
- * This used to be an integral part of asn1_parse() before the intermediate
- * BE form was added.
- */
-static int
-asn1_print(struct be *elem)
-{
- u_char *p = (u_char *)elem->data.raw;
- u_int32_t asnlen = elem->asnlen;
- u_int32_t i;
-
- switch (elem->type) {
-
- case BE_OCTET:
- TCHECK2(*p, asnlen);
- for (i = asnlen; i-- > 0; p++)
- printf("_%.2x", *p);
- break;
-
- case BE_NULL:
- break;
-
- case BE_OID: {
- int o = 0, first = -1, i = asnlen;
-
- if (!sflag && !nflag && asnlen > 2) {
- struct obj_abrev *a = &obj_abrev_list[0];
- size_t a_len = strlen(a->oid);
- for (; a->node; a++) {
- TCHECK2(*p, a_len);
- if (memcmp(a->oid, (char *)p, a_len) == 0) {
- objp = a->node->child;
- i -= strlen(a->oid);
- p += strlen(a->oid);
- fputs(a->prefix, stdout);
- first = 1;
- break;
- }
- }
- }
-
- for (; !sflag && i-- > 0; p++) {
- TCHECK(*p);
- o = (o << ASN_SHIFT7) + (*p & ~ASN_BIT8);
- if (*p & ASN_LONGLEN)
- continue;
-
- /*
- * first subitem encodes two items with 1st*OIDMUX+2nd
- * (see X.690:1997 clause 8.19 for the details)
- */
- if (first < 0) {
- int s;
- if (!nflag)
- objp = mibroot;
- first = 0;
- s = o / OIDMUX;
- if (s > 2) s = 2;
- OBJ_PRINT(s, first);
- o -= s * OIDMUX;
- }
- OBJ_PRINT(o, first);
- if (--first < 0)
- first = 0;
- o = 0;
- }
- break;
- }
-
- case BE_INT:
- printf("%d", elem->data.integer);
- break;
-
- case BE_UNS:
- printf("%u", elem->data.uns);
- break;
-
- case BE_UNS64: { /* idea borrowed from by Marshall Rose */
- double d;
- int j, carry;
- char *cpf, *cpl, last[6], first[30];
- if (elem->data.uns64.high == 0) {
- printf("%u", elem->data.uns64.low);
- break;
- }
- d = elem->data.uns64.high * 4294967296.0; /* 2^32 */
- if (elem->data.uns64.high <= 0x1fffff) {
- d += elem->data.uns64.low;
-#if 0 /*is looks illegal, but what is the intention?*/
- printf("%.f", d);
-#else
- printf("%f", d);
-#endif
- break;
- }
- d += (elem->data.uns64.low & 0xfffff000);
-#if 0 /*is looks illegal, but what is the intention?*/
- snprintf(first, sizeof(first), "%.f", d);
-#else
- snprintf(first, sizeof(first), "%f", d);
-#endif
- snprintf(last, sizeof(last), "%5.5d",
- elem->data.uns64.low & 0xfff);
- for (carry = 0, cpf = first+strlen(first)-1, cpl = last+4;
- cpl >= last;
- cpf--, cpl--) {
- j = carry + (*cpf - '0') + (*cpl - '0');
- if (j > 9) {
- j -= 10;
- carry = 1;
- } else {
- carry = 0;
- }
- *cpf = j + '0';
- }
- fputs(first, stdout);
- break;
- }
-
- case BE_STR: {
- register int printable = 1, first = 1;
- const u_char *p = elem->data.str;
- TCHECK2(*p, asnlen);
- for (i = asnlen; printable && i-- > 0; p++)
- printable = isprint(*p) || isspace(*p);
- p = elem->data.str;
- if (printable) {
- putchar('"');
- if (fn_printn(p, asnlen, snapend)) {
- putchar('"');
- goto trunc;
- }
- putchar('"');
- } else
- for (i = asnlen; i-- > 0; p++) {
- printf(first ? "%.2x" : "_%.2x", *p);
- first = 0;
- }
- break;
- }
-
- case BE_SEQ:
- printf("Seq(%u)", elem->asnlen);
- break;
-
- case BE_INETADDR:
- if (asnlen != ASNLEN_INETADDR)
- printf("[inetaddr len!=%d]", ASNLEN_INETADDR);
- TCHECK2(*p, asnlen);
- for (i = asnlen; i-- != 0; p++) {
- printf((i == asnlen-1) ? "%u" : ".%u", *p);
- }
- break;
-
- case BE_NOSUCHOBJECT:
- case BE_NOSUCHINST:
- case BE_ENDOFMIBVIEW:
- printf("[%s]", Class[EXCEPTIONS].Id[elem->id]);
- break;
-
- case BE_PDU:
- printf("%s(%u)",
- Class[CONTEXT].Id[elem->id], elem->asnlen);
- break;
-
- case BE_ANY:
- fputs("[BE_ANY!?]", stdout);
- break;
-
- default:
- fputs("[be!?]", stdout);
- break;
- }
- return 0;
-
-trunc:
- fputs("[|snmp]", stdout);
- return -1;
-}
-
-#ifdef notdef
-/*
- * This is a brute force ASN.1 printer: recurses to dump an entire structure.
- * This will work for any ASN.1 stream, not just an SNMP PDU.
- *
- * By adding newlines and spaces at the correct places, this would print in
- * Rose-Normal-Form.
- *
- * This is not currently used.
- */
-static void
-asn1_decode(u_char *p, u_int length)
-{
- struct be elem;
- int i = 0;
-
- while (i >= 0 && length > 0) {
- i = asn1_parse(p, length, &elem);
- if (i >= 0) {
- fputs(" ", stdout);
- if (asn1_print(&elem) < 0)
- return;
- if (elem.type == BE_SEQ || elem.type == BE_PDU) {
- fputs(" {", stdout);
- asn1_decode(elem.data.raw, elem.asnlen);
- fputs(" }", stdout);
- }
- length -= i;
- p += i;
- }
- }
-}
-#endif
-
-#ifdef LIBSMI
-
-struct smi2be {
- SmiBasetype basetype;
- int be;
-};
-
-static struct smi2be smi2betab[] = {
- { SMI_BASETYPE_INTEGER32, BE_INT },
- { SMI_BASETYPE_OCTETSTRING, BE_STR },
- { SMI_BASETYPE_OCTETSTRING, BE_INETADDR },
- { SMI_BASETYPE_OBJECTIDENTIFIER, BE_OID },
- { SMI_BASETYPE_UNSIGNED32, BE_UNS },
- { SMI_BASETYPE_INTEGER64, BE_NONE },
- { SMI_BASETYPE_UNSIGNED64, BE_UNS64 },
- { SMI_BASETYPE_FLOAT32, BE_NONE },
- { SMI_BASETYPE_FLOAT64, BE_NONE },
- { SMI_BASETYPE_FLOAT128, BE_NONE },
- { SMI_BASETYPE_ENUM, BE_INT },
- { SMI_BASETYPE_BITS, BE_STR },
- { SMI_BASETYPE_UNKNOWN, BE_NONE }
-};
-
-static int
-smi_decode_oid(struct be *elem, unsigned int *oid,
- unsigned int oidsize, unsigned int *oidlen)
-{
- u_char *p = (u_char *)elem->data.raw;
- u_int32_t asnlen = elem->asnlen;
- int o = 0, first = -1, i = asnlen;
-
- for (*oidlen = 0; sflag && i-- > 0; p++) {
- TCHECK(*p);
- o = (o << ASN_SHIFT7) + (*p & ~ASN_BIT8);
- if (*p & ASN_LONGLEN)
- continue;
-
- /*
- * first subitem encodes two items with 1st*OIDMUX+2nd
- * (see X.690:1997 clause 8.19 for the details)
- */
- if (first < 0) {
- first = 0;
- if (*oidlen < oidsize) {
- oid[*oidlen] = o / OIDMUX;
- if (oid[*oidlen] > 2) oid[*oidlen] = 2;
- }
- o -= oid[*oidlen] * OIDMUX;
- if (*oidlen < oidsize) (*oidlen)++;
- }
- if (*oidlen < oidsize) {
- oid[(*oidlen)++] = o;
- }
- o = 0;
- }
- return 0;
-
-trunc:
- fputs("[|snmp]", stdout);
- return -1;
-}
-
-static int smi_check_type(SmiBasetype basetype, int be)
-{
- int i;
-
- for (i = 0; smi2betab[i].basetype != SMI_BASETYPE_UNKNOWN; i++) {
- if (smi2betab[i].basetype == basetype && smi2betab[i].be == be) {
- return 1;
- }
- }
-
- return 0;
-}
-
-static int smi_check_a_range(SmiType *smiType, SmiRange *smiRange,
- struct be *elem)
-{
- int ok = 1;
-
- switch (smiType->basetype) {
- case SMI_BASETYPE_OBJECTIDENTIFIER:
- case SMI_BASETYPE_OCTETSTRING:
- if (smiRange->minValue.value.unsigned32
- == smiRange->maxValue.value.unsigned32) {
- ok = (elem->asnlen == smiRange->minValue.value.unsigned32);
- } else {
- ok = (elem->asnlen >= smiRange->minValue.value.unsigned32
- && elem->asnlen <= smiRange->maxValue.value.unsigned32);
- }
- break;
-
- case SMI_BASETYPE_INTEGER32:
- ok = (elem->data.integer >= smiRange->minValue.value.integer32
- && elem->data.integer <= smiRange->maxValue.value.integer32);
- break;
-
- case SMI_BASETYPE_UNSIGNED32:
- ok = (elem->data.uns >= smiRange->minValue.value.unsigned32
- && elem->data.uns <= smiRange->maxValue.value.unsigned32);
- break;
-
- case SMI_BASETYPE_UNSIGNED64:
- /* XXX */
- break;
-
- /* case SMI_BASETYPE_INTEGER64: SMIng */
- /* case SMI_BASETYPE_FLOAT32: SMIng */
- /* case SMI_BASETYPE_FLOAT64: SMIng */
- /* case SMI_BASETYPE_FLOAT128: SMIng */
-
- case SMI_BASETYPE_ENUM:
- case SMI_BASETYPE_BITS:
- case SMI_BASETYPE_UNKNOWN:
- ok = 1;
- break;
-
- default:
- ok = 0;
- break;
- }
-
- return ok;
-}
-
-static int smi_check_range(SmiType *smiType, struct be *elem)
-{
- SmiRange *smiRange;
- int ok = 1;
-
- for (smiRange = smiGetFirstRange(smiType);
- smiRange;
- smiRange = smiGetNextRange(smiRange)) {
-
- ok = smi_check_a_range(smiType, smiRange, elem);
-
- if (ok) {
- break;
- }
- }
-
- if (ok) {
- SmiType *parentType;
- parentType = smiGetParentType(smiType);
- if (parentType) {
- ok = smi_check_range(parentType, elem);
- }
- }
-
- return ok;
-}
-
-static SmiNode *smi_print_variable(struct be *elem, int *status)
-{
- unsigned int oid[128], oidlen;
- SmiNode *smiNode = NULL;
- unsigned int i;
-
- *status = smi_decode_oid(elem, oid, sizeof(oid)/sizeof(unsigned int),
- &oidlen);
- if (*status < 0)
- return NULL;
- smiNode = smiGetNodeByOID(oidlen, oid);
- if (! smiNode) {
- *status = asn1_print(elem);
- return NULL;
- }
- if (vflag) {
- fputs(smiGetNodeModule(smiNode)->name, stdout);
- fputs("::", stdout);
- }
- fputs(smiNode->name, stdout);
- if (smiNode->oidlen < oidlen) {
- for (i = smiNode->oidlen; i < oidlen; i++) {
- printf(".%u", oid[i]);
- }
- }
- *status = 0;
- return smiNode;
-}
-
-static int
-smi_print_value(SmiNode *smiNode, u_char pduid, struct be *elem)
-{
- unsigned int i, oid[128], oidlen;
- SmiType *smiType;
- SmiNamedNumber *nn;
- int done = 0;
-
- if (! smiNode || ! (smiNode->nodekind
- & (SMI_NODEKIND_SCALAR | SMI_NODEKIND_COLUMN))) {
- return asn1_print(elem);
- }
-
- if (elem->type == BE_NOSUCHOBJECT
- || elem->type == BE_NOSUCHINST
- || elem->type == BE_ENDOFMIBVIEW) {
- return asn1_print(elem);
- }
-
- if (NOTIFY_CLASS(pduid) && smiNode->access < SMI_ACCESS_NOTIFY) {
- fputs("[notNotifyable]", stdout);
- }
-
- if (READ_CLASS(pduid) && smiNode->access < SMI_ACCESS_READ_ONLY) {
- fputs("[notReadable]", stdout);
- }
-
- if (WRITE_CLASS(pduid) && smiNode->access < SMI_ACCESS_READ_WRITE) {
- fputs("[notWritable]", stdout);
- }
-
- if (RESPONSE_CLASS(pduid)
- && smiNode->access == SMI_ACCESS_NOT_ACCESSIBLE) {
- fputs("[noAccess]", stdout);
- }
-
- smiType = smiGetNodeType(smiNode);
- if (! smiType) {
- return asn1_print(elem);
- }
-
- if (! smi_check_type(smiType->basetype, elem->type)) {
- fputs("[wrongType]", stdout);
- }
-
- if (! smi_check_range(smiType, elem)) {
- fputs("[outOfRange]", stdout);
- }
-
- /* resolve bits to named bits */
-
- /* check whether instance identifier is valid */
-
- /* apply display hints (integer, octetstring) */
-
- /* convert instance identifier to index type values */
-
- switch (elem->type) {
- case BE_OID:
- if (smiType->basetype == SMI_BASETYPE_BITS) {
- /* print bit labels */
- } else {
- smi_decode_oid(elem, oid,
- sizeof(oid)/sizeof(unsigned int),
- &oidlen);
- smiNode = smiGetNodeByOID(oidlen, oid);
- if (smiNode) {
- if (vflag) {
- fputs(smiGetNodeModule(smiNode)->name, stdout);
- fputs("::", stdout);
- }
- fputs(smiNode->name, stdout);
- if (smiNode->oidlen < oidlen) {
- for (i = smiNode->oidlen;
- i < oidlen; i++) {
- printf(".%u", oid[i]);
- }
- }
- done++;
- }
- }
- break;
-
- case BE_INT:
- if (smiType->basetype == SMI_BASETYPE_ENUM) {
- for (nn = smiGetFirstNamedNumber(smiType);
- nn;
- nn = smiGetNextNamedNumber(nn)) {
- if (nn->value.value.integer32
- == elem->data.integer) {
- fputs(nn->name, stdout);
- printf("(%d)", elem->data.integer);
- done++;
- break;
- }
- }
- }
- break;
- }
-
- if (! done) {
- return asn1_print(elem);
- }
- return 0;
-}
-#endif
-
-/*
- * General SNMP header
- * SEQUENCE {
- * version INTEGER {version-1(0)},
- * community OCTET STRING,
- * data ANY -- PDUs
- * }
- * PDUs for all but Trap: (see rfc1157 from page 15 on)
- * SEQUENCE {
- * request-id INTEGER,
- * error-status INTEGER,
- * error-index INTEGER,
- * varbindlist SEQUENCE OF
- * SEQUENCE {
- * name ObjectName,
- * value ObjectValue
- * }
- * }
- * PDU for Trap:
- * SEQUENCE {
- * enterprise OBJECT IDENTIFIER,
- * agent-addr NetworkAddress,
- * generic-trap INTEGER,
- * specific-trap INTEGER,
- * time-stamp TimeTicks,
- * varbindlist SEQUENCE OF
- * SEQUENCE {
- * name ObjectName,
- * value ObjectValue
- * }
- * }
- */
-
-/*
- * Decode SNMP varBind
- */
-static void
-varbind_print(u_char pduid, const u_char *np, u_int length)
-{
- struct be elem;
- int count = 0, ind;
-#ifdef LIBSMI
- SmiNode *smiNode = NULL;
-#endif
- int status;
-
- /* Sequence of varBind */
- if ((count = asn1_parse(np, length, &elem)) < 0)
- return;
- if (elem.type != BE_SEQ) {
- fputs("[!SEQ of varbind]", stdout);
- asn1_print(&elem);
- return;
- }
- if ((u_int)count < length)
- printf("[%d extra after SEQ of varbind]", length - count);
- /* descend */
- length = elem.asnlen;
- np = (u_char *)elem.data.raw;
-
- for (ind = 1; length > 0; ind++) {
- const u_char *vbend;
- u_int vblength;
-
- fputs(" ", stdout);
-
- /* Sequence */
- if ((count = asn1_parse(np, length, &elem)) < 0)
- return;
- if (elem.type != BE_SEQ) {
- fputs("[!varbind]", stdout);
- asn1_print(&elem);
- return;
- }
- vbend = np + count;
- vblength = length - count;
- /* descend */
- length = elem.asnlen;
- np = (u_char *)elem.data.raw;
-
- /* objName (OID) */
- if ((count = asn1_parse(np, length, &elem)) < 0)
- return;
- if (elem.type != BE_OID) {
- fputs("[objName!=OID]", stdout);
- asn1_print(&elem);
- return;
- }
-#ifdef LIBSMI
- smiNode = smi_print_variable(&elem, &status);
-#else
- status = asn1_print(&elem);
-#endif
- if (status < 0)
- return;
- length -= count;
- np += count;
-
- if (pduid != GETREQ && pduid != GETNEXTREQ
- && pduid != GETBULKREQ)
- fputs("=", stdout);
-
- /* objVal (ANY) */
- if ((count = asn1_parse(np, length, &elem)) < 0)
- return;
- if (pduid == GETREQ || pduid == GETNEXTREQ
- || pduid == GETBULKREQ) {
- if (elem.type != BE_NULL) {
- fputs("[objVal!=NULL]", stdout);
- if (asn1_print(&elem) < 0)
- return;
- }
- } else {
- if (elem.type != BE_NULL) {
-#ifdef LIBSMI
- status = smi_print_value(smiNode, pduid, &elem);
-#else
- status = asn1_print(&elem);
-#endif
- }
- if (status < 0)
- return;
- }
- length = vblength;
- np = vbend;
- }
-}
-
-/*
- * Decode SNMP PDUs: GetRequest, GetNextRequest, GetResponse, SetRequest,
- * GetBulk, Inform, V2Trap, and Report
- */
-static void
-snmppdu_print(u_short pduid, const u_char *np, u_int length)
-{
- struct be elem;
- int count = 0, error;
-
- /* reqId (Integer) */
- if ((count = asn1_parse(np, length, &elem)) < 0)
- return;
- if (elem.type != BE_INT) {
- fputs("[reqId!=INT]", stdout);
- asn1_print(&elem);
- return;
- }
- if (vflag)
- printf("R=%d ", elem.data.integer);
- length -= count;
- np += count;
-
- /* errorStatus (Integer) */
- if ((count = asn1_parse(np, length, &elem)) < 0)
- return;
- if (elem.type != BE_INT) {
- fputs("[errorStatus!=INT]", stdout);
- asn1_print(&elem);
- return;
- }
- error = 0;
- if ((pduid == GETREQ || pduid == GETNEXTREQ || pduid == SETREQ
- || pduid == INFORMREQ || pduid == V2TRAP || pduid == REPORT)
- && elem.data.integer != 0) {
- char errbuf[20];
- printf("[errorStatus(%s)!=0]",
- DECODE_ErrorStatus(elem.data.integer));
- } else if (pduid == GETBULKREQ) {
- printf(" N=%d", elem.data.integer);
- } else if (elem.data.integer != 0) {
- char errbuf[20];
- printf(" %s", DECODE_ErrorStatus(elem.data.integer));
- error = elem.data.integer;
- }
- length -= count;
- np += count;
-
- /* errorIndex (Integer) */
- if ((count = asn1_parse(np, length, &elem)) < 0)
- return;
- if (elem.type != BE_INT) {
- fputs("[errorIndex!=INT]", stdout);
- asn1_print(&elem);
- return;
- }
- if ((pduid == GETREQ || pduid == GETNEXTREQ || pduid == SETREQ
- || pduid == INFORMREQ || pduid == V2TRAP || pduid == REPORT)
- && elem.data.integer != 0)
- printf("[errorIndex(%d)!=0]", elem.data.integer);
- else if (pduid == GETBULKREQ)
- printf(" M=%d", elem.data.integer);
- else if (elem.data.integer != 0) {
- if (!error)
- printf("[errorIndex(%d) w/o errorStatus]",
- elem.data.integer);
- else {
- printf("@%d", elem.data.integer);
- error = elem.data.integer;
- }
- } else if (error) {
- fputs("[errorIndex==0]", stdout);
- error = 0;
- }
- length -= count;
- np += count;
-
- varbind_print(pduid, np, length);
- return;
-}
-
-/*
- * Decode SNMP Trap PDU
- */
-static void
-trappdu_print(const u_char *np, u_int length)
-{
- struct be elem;
- int count = 0, generic;
-
- putchar(' ');
-
- /* enterprise (oid) */
- if ((count = asn1_parse(np, length, &elem)) < 0)
- return;
- if (elem.type != BE_OID) {
- fputs("[enterprise!=OID]", stdout);
- asn1_print(&elem);
- return;
- }
- if (asn1_print(&elem) < 0)
- return;
- length -= count;
- np += count;
-
- putchar(' ');
-
- /* agent-addr (inetaddr) */
- if ((count = asn1_parse(np, length, &elem)) < 0)
- return;
- if (elem.type != BE_INETADDR) {
- fputs("[agent-addr!=INETADDR]", stdout);
- asn1_print(&elem);
- return;
- }
- if (asn1_print(&elem) < 0)
- return;
- length -= count;
- np += count;
-
- /* generic-trap (Integer) */
- if ((count = asn1_parse(np, length, &elem)) < 0)
- return;
- if (elem.type != BE_INT) {
- fputs("[generic-trap!=INT]", stdout);
- asn1_print(&elem);
- return;
- }
- generic = elem.data.integer;
- {
- char buf[20];
- printf(" %s", DECODE_GenericTrap(generic));
- }
- length -= count;
- np += count;
-
- /* specific-trap (Integer) */
- if ((count = asn1_parse(np, length, &elem)) < 0)
- return;
- if (elem.type != BE_INT) {
- fputs("[specific-trap!=INT]", stdout);
- asn1_print(&elem);
- return;
- }
- if (generic != GT_ENTERPRISE) {
- if (elem.data.integer != 0)
- printf("[specific-trap(%d)!=0]", elem.data.integer);
- } else
- printf(" s=%d", elem.data.integer);
- length -= count;
- np += count;
-
- putchar(' ');
-
- /* time-stamp (TimeTicks) */
- if ((count = asn1_parse(np, length, &elem)) < 0)
- return;
- if (elem.type != BE_UNS) { /* XXX */
- fputs("[time-stamp!=TIMETICKS]", stdout);
- asn1_print(&elem);
- return;
- }
- if (asn1_print(&elem) < 0)
- return;
- length -= count;
- np += count;
-
- varbind_print (TRAP, np, length);
- return;
-}
-
-/*
- * Decode arbitrary SNMP PDUs.
- */
-static void
-pdu_print(const u_char *np, u_int length, int version)
-{
- struct be pdu;
- int count = 0;
-
- /* PDU (Context) */
- if ((count = asn1_parse(np, length, &pdu)) < 0)
- return;
- if (pdu.type != BE_PDU) {
- fputs("[no PDU]", stdout);
- return;
- }
- if ((u_int)count < length)
- printf("[%d extra after PDU]", length - count);
- if (vflag) {
- fputs("{ ", stdout);
- }
- if (asn1_print(&pdu) < 0)
- return;
- fputs(" ", stdout);
- /* descend into PDU */
- length = pdu.asnlen;
- np = (u_char *)pdu.data.raw;
-
- if (version == SNMP_VERSION_1 &&
- (pdu.id == GETBULKREQ || pdu.id == INFORMREQ ||
- pdu.id == V2TRAP || pdu.id == REPORT)) {
- printf("[v2 PDU in v1 message]");
- return;
- }
-
- if (version == SNMP_VERSION_2 && pdu.id == TRAP) {
- printf("[v1 PDU in v2 message]");
- return;
- }
-
- switch (pdu.id) {
- case TRAP:
- trappdu_print(np, length);
- break;
- case GETREQ:
- case GETNEXTREQ:
- case GETRESP:
- case SETREQ:
- case GETBULKREQ:
- case INFORMREQ:
- case V2TRAP:
- case REPORT:
- snmppdu_print(pdu.id, np, length);
- break;
- }
-
- if (vflag) {
- fputs(" } ", stdout);
- }
-}
-
-/*
- * Decode a scoped SNMP PDU.
- */
-static void
-scopedpdu_print(const u_char *np, u_int length, int version)
-{
- struct be elem;
- int i, count = 0;
-
- /* Sequence */
- if ((count = asn1_parse(np, length, &elem)) < 0)
- return;
- if (elem.type != BE_SEQ) {
- fputs("[!scoped PDU]", stdout);
- asn1_print(&elem);
- return;
- }
- length = elem.asnlen;
- np = (u_char *)elem.data.raw;
-
- /* contextEngineID (OCTET STRING) */
- if ((count = asn1_parse(np, length, &elem)) < 0)
- return;
- if (elem.type != BE_STR) {
- fputs("[contextEngineID!=STR]", stdout);
- asn1_print(&elem);
- return;
- }
- length -= count;
- np += count;
-
- fputs("E= ", stdout);
- for (i = 0; i < (int)elem.asnlen; i++) {
- printf("0x%02X", elem.data.str[i]);
- }
- fputs(" ", stdout);
-
- /* contextName (OCTET STRING) */
- if ((count = asn1_parse(np, length, &elem)) < 0)
- return;
- if (elem.type != BE_STR) {
- fputs("[contextName!=STR]", stdout);
- asn1_print(&elem);
- return;
- }
- length -= count;
- np += count;
-
- printf("C=%.*s ", (int)elem.asnlen, elem.data.str);
-
- pdu_print(np, length, version);
-}
-
-/*
- * Decode SNMP Community Header (SNMPv1 and SNMPv2c)
- */
-static void
-community_print(const u_char *np, u_int length, int version)
-{
- struct be elem;
- int count = 0;
-
- /* Community (String) */
- if ((count = asn1_parse(np, length, &elem)) < 0)
- return;
- if (elem.type != BE_STR) {
- fputs("[comm!=STR]", stdout);
- asn1_print(&elem);
- return;
- }
- /* default community */
- if (!(elem.asnlen == sizeof(DEF_COMMUNITY) - 1 &&
- strncmp((char *)elem.data.str, DEF_COMMUNITY,
- sizeof(DEF_COMMUNITY) - 1) == 0))
- /* ! "public" */
- printf("C=%.*s ", (int)elem.asnlen, elem.data.str);
- length -= count;
- np += count;
-
- pdu_print(np, length, version);
-}
-
-/*
- * Decode SNMPv3 User-based Security Message Header (SNMPv3)
- */
-static void
-usm_print(const u_char *np, u_int length)
-{
- struct be elem;
- int count = 0;
-
- /* Sequence */
- if ((count = asn1_parse(np, length, &elem)) < 0)
- return;
- if (elem.type != BE_SEQ) {
- fputs("[!usm]", stdout);
- asn1_print(&elem);
- return;
- }
- length = elem.asnlen;
- np = (u_char *)elem.data.raw;
-
- /* msgAuthoritativeEngineID (OCTET STRING) */
- if ((count = asn1_parse(np, length, &elem)) < 0)
- return;
- if (elem.type != BE_STR) {
- fputs("[msgAuthoritativeEngineID!=STR]", stdout);
- asn1_print(&elem);
- return;
- }
- length -= count;
- np += count;
-
- /* msgAuthoritativeEngineBoots (INTEGER) */
- if ((count = asn1_parse(np, length, &elem)) < 0)
- return;
- if (elem.type != BE_INT) {
- fputs("[msgAuthoritativeEngineBoots!=INT]", stdout);
- asn1_print(&elem);
- return;
- }
- if (vflag)
- printf("B=%d ", elem.data.integer);
- length -= count;
- np += count;
-
- /* msgAuthoritativeEngineTime (INTEGER) */
- if ((count = asn1_parse(np, length, &elem)) < 0)
- return;
- if (elem.type != BE_INT) {
- fputs("[msgAuthoritativeEngineTime!=INT]", stdout);
- asn1_print(&elem);
- return;
- }
- if (vflag)
- printf("T=%d ", elem.data.integer);
- length -= count;
- np += count;
-
- /* msgUserName (OCTET STRING) */
- if ((count = asn1_parse(np, length, &elem)) < 0)
- return;
- if (elem.type != BE_STR) {
- fputs("[msgUserName!=STR]", stdout);
- asn1_print(&elem);
- return;
- }
- length -= count;
- np += count;
-
- printf("U=%.*s ", (int)elem.asnlen, elem.data.str);
-
- /* msgAuthenticationParameters (OCTET STRING) */
- if ((count = asn1_parse(np, length, &elem)) < 0)
- return;
- if (elem.type != BE_STR) {
- fputs("[msgAuthenticationParameters!=STR]", stdout);
- asn1_print(&elem);
- return;
- }
- length -= count;
- np += count;
-
- /* msgPrivacyParameters (OCTET STRING) */
- if ((count = asn1_parse(np, length, &elem)) < 0)
- return;
- if (elem.type != BE_STR) {
- fputs("[msgPrivacyParameters!=STR]", stdout);
- asn1_print(&elem);
- return;
- }
- length -= count;
- np += count;
-
- if ((u_int)count < length)
- printf("[%d extra after usm SEQ]", length - count);
-}
-
-/*
- * Decode SNMPv3 Message Header (SNMPv3)
- */
-static void
-v3msg_print(const u_char *np, u_int length)
-{
- struct be elem;
- int count = 0;
- u_char flags;
- int model;
- const u_char *xnp = np;
- int xlength = length;
-
- /* Sequence */
- if ((count = asn1_parse(np, length, &elem)) < 0)
- return;
- if (elem.type != BE_SEQ) {
- fputs("[!message]", stdout);
- asn1_print(&elem);
- return;
- }
- length = elem.asnlen;
- np = (u_char *)elem.data.raw;
-
- if (vflag) {
- fputs("{ ", stdout);
- }
-
- /* msgID (INTEGER) */
- if ((count = asn1_parse(np, length, &elem)) < 0)
- return;
- if (elem.type != BE_INT) {
- fputs("[msgID!=INT]", stdout);
- asn1_print(&elem);
- return;
- }
- length -= count;
- np += count;
-
- /* msgMaxSize (INTEGER) */
- if ((count = asn1_parse(np, length, &elem)) < 0)
- return;
- if (elem.type != BE_INT) {
- fputs("[msgMaxSize!=INT]", stdout);
- asn1_print(&elem);
- return;
- }
- length -= count;
- np += count;
-
- /* msgFlags (OCTET STRING) */
- if ((count = asn1_parse(np, length, &elem)) < 0)
- return;
- if (elem.type != BE_STR) {
- fputs("[msgFlags!=STR]", stdout);
- asn1_print(&elem);
- return;
- }
- if (elem.asnlen != 1) {
- printf("[msgFlags size %d]", elem.asnlen);
- return;
- }
- flags = elem.data.str[0];
- if (flags != 0x00 && flags != 0x01 && flags != 0x03
- && flags != 0x04 && flags != 0x05 && flags != 0x07) {
- printf("[msgFlags=0x%02X]", flags);
- return;
- }
- length -= count;
- np += count;
-
- fputs("F=", stdout);
- if (flags & 0x01) fputs("a", stdout);
- if (flags & 0x02) fputs("p", stdout);
- if (flags & 0x04) fputs("r", stdout);
- fputs(" ", stdout);
-
- /* msgSecurityModel (INTEGER) */
- if ((count = asn1_parse(np, length, &elem)) < 0)
- return;
- if (elem.type != BE_INT) {
- fputs("[msgSecurityModel!=INT]", stdout);
- asn1_print(&elem);
- return;
- }
- model = elem.data.integer;
- length -= count;
- np += count;
-
- if ((u_int)count < length)
- printf("[%d extra after message SEQ]", length - count);
-
- if (vflag) {
- fputs("} ", stdout);
- }
-
- if (model == 3) {
- if (vflag) {
- fputs("{ USM ", stdout);
- }
- } else {
- printf("[security model %d]", model);
- return;
- }
-
- np = xnp + (np - xnp);
- length = xlength - (np - xnp);
-
- /* msgSecurityParameters (OCTET STRING) */
- if ((count = asn1_parse(np, length, &elem)) < 0)
- return;
- if (elem.type != BE_STR) {
- fputs("[msgSecurityParameters!=STR]", stdout);
- asn1_print(&elem);
- return;
- }
- length -= count;
- np += count;
-
- if (model == 3) {
- usm_print(elem.data.str, elem.asnlen);
- if (vflag) {
- fputs("} ", stdout);
- }
- }
-
- if (vflag) {
- fputs("{ ScopedPDU ", stdout);
- }
-
- scopedpdu_print(np, length, 3);
-
- if (vflag) {
- fputs("} ", stdout);
- }
-}
-
-/*
- * Decode SNMP header and pass on to PDU printing routines
- */
-void
-snmp_print(const u_char *np, u_int length)
-{
- struct be elem;
- int count = 0;
- int version = 0;
-
- putchar(' ');
-
- /* initial Sequence */
- if ((count = asn1_parse(np, length, &elem)) < 0)
- return;
- if (elem.type != BE_SEQ) {
- fputs("[!init SEQ]", stdout);
- asn1_print(&elem);
- return;
- }
- if ((u_int)count < length)
- printf("[%d extra after iSEQ]", length - count);
- /* descend */
- length = elem.asnlen;
- np = (u_char *)elem.data.raw;
-
- /* Version (INTEGER) */
- if ((count = asn1_parse(np, length, &elem)) < 0)
- return;
- if (elem.type != BE_INT) {
- fputs("[version!=INT]", stdout);
- asn1_print(&elem);
- return;
- }
-
- switch (elem.data.integer) {
- case SNMP_VERSION_1:
- case SNMP_VERSION_2:
- case SNMP_VERSION_3:
- if (vflag)
- printf("{ %s ", SnmpVersion[elem.data.integer]);
- break;
- default:
- printf("[version = %d]", elem.data.integer);
- return;
- }
- version = elem.data.integer;
- length -= count;
- np += count;
-
- switch (version) {
- case SNMP_VERSION_1:
- case SNMP_VERSION_2:
- community_print(np, length, version);
- break;
- case SNMP_VERSION_3:
- v3msg_print(np, length);
- break;
- default:
- printf("[version = %d]", elem.data.integer);
- break;
- }
-
- if (vflag) {
- fputs("} ", stdout);
- }
-}
OpenPOWER on IntegriCloud