⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 _snmp.c

📁 This directory contains source code for tcpdump, a tool for network monitoring and data acquisition
💻 C
📖 第 1 页 / 共 4 页
字号:
/*
 * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996, 1997
 *      The Regents of the University of California.  All rights reserved.
 *
 * Redistribution and use in source and binary forms are permitted
 * provided that the above copyright notice and this paragraph are
 * duplicated in all such forms and that any documentation,
 * advertising materials, and other materials related to such
 * distribution and use acknowledge that the software was developed
 * by John Robert LoVerso.
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 *
 * 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
 */

#if 0
static const char rcsid[] =
"@(#) $Header: /tcpdump/master/tcpdump/print-snmp.c,v 1.39 1999/12/22 06:27:22 itojun Exp $ (LBL)";
#endif

#include <ctype.h>
#include <stdio.h>
#include <string.h>

#include <sys/param.h>
#include <sys/time.h>

#ifdef HAVE_SMI_H
#include <smi.h>
#endif

#include "interfac.h"
#include "a2name.h"

/*
 * Universal ASN.1 types
 * (we only care about the tag values for those allowed in the Internet SMI)
 */
static 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
 */
static 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
 */
static 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
 */
static 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
 */
static char *Private[] = {
  "P-0"
};

/*
 * error-status values for any SNMP PDU
 */
static 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 && e < DIM(ErrorStatus) ? ErrorStatus[e] : \
         (sprintf(errbuf, "err=%lu", e), errbuf))

/*
 * generic-trap values in the SNMP Trap-PDU
 */
static char *GenericTrap[] = {
  "coldStart",
  "warmStart",
  "linkDown",
  "linkUp",
  "authenticationFailure",
  "egpNeighborLoss",
  "enterpriseSpecific"
#define GT_ENTERPRISE 7
};

#define DECODE_GenericTrap(t) \
        ( t >= 0 && t < DIM(GenericTrap) \
        ? GenericTrap[t] : (sprintf(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, DIM(x) }    /* not ANSI-C */
static struct {
       char  *name;
       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
 */
static 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.
 */
static struct obj {
       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.
 */
static struct obj_abrev {
       char       *prefix;        /* prefix for this abrev */
       struct obj *node;          /* pointer into object table */
       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
 */
static 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 */

/*
 * truncated==1 means the packet was complete, but we don't have all of
 * it to decode.
 */
static int truncated;

#define ifNotTruncated if (truncated) PUTS("[|snmp]"); else

/*
 * 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 (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)
  {
    ifNotTruncated PUTS ("[nothing to parse]");

    return -1;
  }

  /*
   * 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;
  if (vflag)
    PRINTF ("|%.2x", *p);
  p++;
  len--;
  hdr = 1;
  /* extended tag field */
  if (id == ASN_ID_EXT)
  {
    for (id = 0; *p & ASN_BIT8 && len > 0; len--, hdr++, p++)
    {
      if (vflag)
        PRINTF ("|%.2x", *p);
      id = (id << 7) | (*p & ~ASN_BIT8);
    }
    if (len == 0 && *p & ASN_BIT8)
    {
      ifNotTruncated PUTS ("[Xtagfield?]");

      return -1;
    }
    elem->id = id = (id << 7) | *p;
    --len;
    ++hdr;
    ++p;
  }
  if (len < 1)
  {
    ifNotTruncated PUTS ("[no asnlen]");

    return -1;
  }
  elem->asnlen = *p;
  if (vflag)
    PRINTF ("|%.2x", *p);
  p++;
  len--;
  hdr++;
  if (elem->asnlen & ASN_BIT8)
  {
    int noct = elem->asnlen % ASN_BIT8;

    elem->asnlen = 0;
    if (len < noct)
    {
      ifNotTruncated PRINTF ("[asnlen? %d<%d]", len, noct);

      return -1;
    }
    for (; noct-- > 0; len--, hdr++)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -