?? print-snmp.c
字號:
/* * 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 lintstatic const char rcsid[] _U_ = "@(#) $Header: /tcpdump/master/tcpdump/print-snmp.c,v 1.64 2005-05-06 07:56:53 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 intasn1_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;
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -