]> The Tcpdump Group git mirrors - tcpdump/commitdiff
From: Juergen Schoenwaelder <[email protected]>
authormcr <mcr>
Mon, 13 Dec 1999 18:06:13 +0000 (18:06 +0000)
committermcr <mcr>
Mon, 13 Dec 1999 18:06:13 +0000 (18:06 +0000)
Here is a new version of the libsmi patch for tcpdump. It provides
some bug fixes and some enhancements such as access checking and
better range checking. The patch also fixed a few bugs in the
print_snmp.c module of tcpdump itself (unrelated to the usage of
libsmi).

config.h.in
configure.in
interface.h
print-snmp.c
tcpdump.1
tcpdump.c

index dbe589bcb8b53480d81a1a7987cde2d8e2509854..b4291f3a1c295b6f2862b10c7da7f4ec0061cd74 100644 (file)
 #undef ENABLE_IPV6
 #undef INET6
 
+/* Define if you enable support for the libsmi. */
+#undef LIBSMI
+
+/* Define if you have the <smi.h> header file.  */
+#undef HAVE_SMI_H
+
 /* Is T_AAAA predefined? */
 #undef HAVE_AAAA
 
index e7a68f08696fcedcc73ed1728cf92fd1da77adb6..94aa9e9673bb9c820ca397eeda31c0a0bec26d2c 100644 (file)
@@ -1,4 +1,4 @@
-dnl @(#) $Header: /tcpdump/master/tcpdump/configure.in,v 1.84 1999-12-04 19:30:04 mcr Exp $ (LBL)
+dnl @(#) $Header: /tcpdump/master/tcpdump/configure.in,v 1.85 1999-12-13 18:06:14 mcr Exp $ (LBL)
 dnl
 dnl Copyright (c) 1994, 1995, 1996, 1997
 dnl    The Regents of the University of California.  All rights reserved.
@@ -41,11 +41,22 @@ linux*)
        ;;
 esac
 
+
+AC_ARG_ENABLE(libsmi,
+       [  --enable-libsmi         enable libsmi support],
+       [libsmi=$enableval], [libsmi=no])
+if test "$libsmi" = "yes"; then
+       AC_CHECK_HEADERS(smi.h)
+       AC_CHECK_LIB(smi, main)
+       AC_DEFINE(LIBSMI)
+fi
+
+
 CFLAGS="$CFLAGS -Dss_family=__ss_family -Dss_len=__ss_len"
 AC_MSG_CHECKING([whether to enable ipv6])
 AC_ARG_ENABLE(ipv6,
-[  --enable-ipv6               Enable ipv6 (with ipv4) support
-  --disable-ipv6               Disable ipv6 support],
+[  --enable-ipv6           enable ipv6 (with ipv4) support
+  --disable-ipv6          disable ipv6 support],
 [ case "$enableval" in
 yes)   AC_MSG_RESULT(yes)
        AC_DEFINE(ENABLE_IPV6)
@@ -59,7 +70,7 @@ yes)   AC_MSG_RESULT(yes)
        ;;
   esac ],
 
-  AC_TRY_RUN([ /* AF_INET6 avalable check */
+  AC_TRY_RUN([ /* AF_INET6 available check */
 #include <sys/types.h>
 #include <sys/socket.h>
 main()
index 7befb734a778f51a1b82e67e00bb0d1692625402..aa1dbed000e5eebec566383b033fdd154846dfa1 100644 (file)
@@ -18,7 +18,7 @@
  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  *
- * @(#) $Header: /tcpdump/master/tcpdump/interface.h,v 1.112 1999-11-22 07:25:26 fenner Exp $ (LBL)
+ * @(#) $Header: /tcpdump/master/tcpdump/interface.h,v 1.113 1999-12-13 18:06:14 mcr Exp $ (LBL)
  */
 
 #ifndef tcpdump_interface_h
@@ -42,6 +42,7 @@ extern int nflag;             /* leave addresses as numbers */
 extern int Nflag;              /* remove domains from printed host names */
 extern int qflag;              /* quick (shorter) output */
 extern int Rflag;              /* print sequence # field in AH/ESP*/
+extern int sflag;              /* use the libsmi to translate OIDs */
 extern int Sflag;              /* print raw TCP sequence numbers */
 extern int tflag;              /* print packet arrival time */
 extern int vflag;              /* verbose */
index 15a0892bcd558ba9a6e33ee885fbc3f5482a64df..a546d5d722fc94a6e672a2eea4c653cd80130cb0 100644 (file)
@@ -21,6 +21,9 @@
  * 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.
  *
@@ -42,7 +45,7 @@
 
 #ifndef lint
 static const char rcsid[] =
-    "@(#) $Header: /tcpdump/master/tcpdump/print-snmp.c,v 1.37 1999-11-21 09:37:01 fenner Exp $ (LBL)";
+    "@(#) $Header: /tcpdump/master/tcpdump/print-snmp.c,v 1.38 1999-12-13 18:06:14 mcr Exp $ (LBL)";
 #endif
 
 #ifdef HAVE_CONFIG_H
@@ -59,6 +62,10 @@ static const char rcsid[] =
 #include <stdio.h>
 #include <string.h>
 
+#ifdef HAVE_SMI_H
+#include <smi.h>
+#endif
+
 #include "interface.h"
 #include "addrtoname.h"
 
@@ -129,6 +136,12 @@ char *Context[] = {
 #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
  */
@@ -651,7 +664,7 @@ asn1_print(struct be *elem)
        case BE_OID: {
        int o = 0, first = -1, i = asnlen;
 
-               if (!nflag && asnlen > 2) {
+               if (!sflag && !nflag && asnlen > 2) {
                        struct obj_abrev *a = &obj_abrev_list[0];
                        for (; a->node; a++) {
                                if (!memcmp(a->oid, (char *)p,
@@ -665,11 +678,12 @@ asn1_print(struct be *elem)
                                }
                        }
                }
-               for (; i-- > 0; p++) {
+
+               for (; !sflag && i-- > 0; p++) {
                        o = (o << ASN_SHIFT7) + (*p & ~ASN_BIT8);
                        if (*p & ASN_LONGLEN)
-                               continue;
-
+                               continue;
+                       
                        /*
                         * first subitem encodes two items with 1st*OIDMUX+2nd
                         */
@@ -693,7 +707,7 @@ asn1_print(struct be *elem)
                break;
 
        case BE_UNS:
-               printf("%d", elem->data.uns);
+               printf("%u", elem->data.uns);
                break;
 
        case BE_UNS64: {        /* idea borrowed from by Marshall Rose */
@@ -751,18 +765,13 @@ asn1_print(struct be *elem)
                printf("Seq(%u)", elem->asnlen);
                break;
 
-       case BE_INETADDR: {
-               char sep;
+       case BE_INETADDR:
                if (asnlen != ASNLEN_INETADDR)
                        printf("[inetaddr len!=%d]", ASNLEN_INETADDR);
-               sep='[';
                for (i = asnlen; i-- > 0; p++) {
-                       printf("%c%u", sep, *p);
-                       sep='.';
+                       printf((i == asnlen-1) ? "%u" : ".%u", *p);
                }
-               putchar(']');
                break;
-       }
 
        case BE_NOSUCHOBJECT:
        case BE_NOSUCHINST:
@@ -818,6 +827,274 @@ asn1_decode(u_char *p, u_int length)
 }
 #endif
 
+#ifdef LIBSMI
+
+struct smi2be {
+    SmiBasetype basetype;
+    int be;
+};
+
+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 void smi_decode_oid(struct be *elem, unsigned int *oid,
+                          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++) {
+               o = (o << ASN_SHIFT7) + (*p & ~ASN_BIT8);
+               if (*p & ASN_LONGLEN)
+                   continue;
+           
+               /*
+                * first subitem encodes two items with 1st*OIDMUX+2nd
+                */
+               if (first < 0) {
+                       first = 0;
+                       oid[(*oidlen)++] = o/OIDMUX;
+                       o %= OIDMUX;
+               }
+               oid[(*oidlen)++] = o;
+               o = 0;
+       }
+}
+
+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;
+    
+    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;
+    }
+
+    return ok;
+}
+
+static int smi_check_range(SmiType *smiType, struct be *elem)
+{
+        SmiRange *smiRange;
+       int ok = 1;
+
+       for (smiRange = smiGetFirstRange(smiType->module, smiType->name);
+            smiRange;
+            smiRange = smiGetNextRange(smiRange)) {
+
+           ok = smi_check_a_range(smiType, smiRange, elem);
+           
+           if (ok) {
+               smiFreeRange(smiRange);
+               break;
+           }
+       }
+
+       if (ok && smiType->parentmodule && smiType->parentname) {
+           SmiType *parentType;
+           parentType = smiGetType(smiType->parentmodule,
+                                   smiType->parentname);
+           if (parentType) {
+               ok = smi_check_range(parentType, elem);
+               smiFreeType(parentType);
+           }
+       }
+
+       return ok;
+}
+
+static SmiNode *smi_print_variable(struct be *elem)
+{
+       unsigned int oid[128], oidlen;
+       SmiNode *smiNode = NULL;
+       int i;
+
+       smi_decode_oid(elem, oid, &oidlen);
+       smiNode = smiGetNodeByOID(oidlen, oid);
+       if (! smiNode) {
+               asn1_print(elem);
+               return NULL;
+       }
+       if (vflag) {
+               fputs(smiNode->module, stdout);
+               fputs("::", stdout);
+       }
+       fputs(smiNode->name, stdout);
+       if (smiNode->oidlen < oidlen) {
+               for (i = smiNode->oidlen; i < oidlen; i++) {
+                       printf(".%u", oid[i]);
+               }
+       }
+       return smiNode;
+}
+
+static void smi_print_value(SmiNode *smiNode, u_char pduid, struct be *elem)
+{
+       unsigned int oid[128], oidlen;
+       SmiType *smiType;
+       SmiNamedNumber *nn;
+       int i, done = 0;
+
+       if (! smiNode || ! (smiNode->nodekind
+                           & (SMI_NODEKIND_SCALAR | SMI_NODEKIND_COLUMN))) {
+           asn1_print(elem);
+           return;
+       }
+
+       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);
+       }
+
+       if (! smi_check_type(smiNode->basetype, elem->type)) {
+           fputs("[wrongType]", stdout);
+       }
+
+       smiType = smiGetType(smiNode->typemodule, smiNode->typename);
+       if (! smiType) {
+           asn1_print(elem);
+           return;
+       }
+
+       if (! smi_check_range(smiType, elem)) {
+           fputs("[wrongLength]", 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 (smiNode->basetype == SMI_BASETYPE_BITS
+                   && smiNode->typemodule && smiNode->typename) {
+                       /* print bit labels */
+               } else {
+                       smi_decode_oid(elem, oid, &oidlen);
+                       smiNode = smiGetNodeByOID(oidlen, oid);
+                       if (smiNode) {
+                               if (vflag) {
+                                       fputs(smiNode->module, 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 (smiNode->basetype == SMI_BASETYPE_ENUM
+                   && smiNode->typemodule && smiNode->typename) {
+                       for (nn = smiGetFirstNamedNumber(smiNode->typemodule,
+                                                        smiNode->typename);
+                            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) {
+               asn1_print(elem);
+       }
+
+       if (smiType) {
+               smiFreeType(smiType);
+       }
+}
+#endif
+
 /*
  * General SNMP header
  *     SEQUENCE {
@@ -855,10 +1132,13 @@ asn1_decode(u_char *p, u_int length)
  * Decode SNMP varBind
  */
 static void
-varbind_print(u_char pduid, const u_char *np, u_int length, int error)
+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
 
        /* Sequence of varBind */
        if ((count = asn1_parse(np, length, &elem)) < 0)
@@ -878,8 +1158,7 @@ varbind_print(u_char pduid, const u_char *np, u_int length, int error)
                const u_char *vbend;
                u_int vblength;
 
-               if (!error || ind == error)
-                       fputs(" ", stdout);
+               fputs(" ", stdout);
 
                /* Sequence */
                if ((count = asn1_parse(np, length, &elem)) < 0)
@@ -903,13 +1182,16 @@ varbind_print(u_char pduid, const u_char *np, u_int length, int error)
                        asn1_print(&elem);
                        return;
                }
-               if (!error || ind == error)
-                       asn1_print(&elem);
+#ifdef LIBSMI
+               smiNode = smi_print_variable(&elem);
+#else
+               asn1_print(&elem);
+#endif
                length -= count;
                np += count;
 
                if (pduid != GETREQ && pduid != GETNEXTREQ
-                   && pduid != GETBULKREQ && !error)
+                   && pduid != GETBULKREQ)
                                fputs("=", stdout);
 
                /* objVal (ANY) */
@@ -921,12 +1203,16 @@ varbind_print(u_char pduid, const u_char *np, u_int length, int error)
                                fputs("[objVal!=NULL]", stdout);
                                asn1_print(&elem);
                        }
-               } else
-                       if (error && ind == error && elem.type != BE_NULL)
-                               fputs("[err objVal!=NULL]", stdout);
-                       if (!error || ind == error)
+               } else {
+                       if (elem.type != BE_NULL) {
+#ifdef LIBSMI
+                               smi_print_value(smiNode, pduid, &elem);
+                               smiFreeNode(smiNode);
+#else
                                asn1_print(&elem);
-
+#endif
+                       }
+               }
                length = vblength;
                np = vbend;
        }
@@ -1008,7 +1294,7 @@ snmppdu_print(u_char pduid, const u_char *np, u_int length)
        length -= count;
        np += count;
 
-       varbind_print(pduid, np, length, error);
+       varbind_print(pduid, np, length);
        return;
 }
 
@@ -1095,7 +1381,7 @@ trappdu_print(const u_char *np, u_int length)
        length -= count;
        np += count;
 
-       varbind_print (TRAP, np, length, 0);
+       varbind_print (TRAP, np, length);
        return;
 }
 
index 3d544e705e018f18366320763c73a5916d49ef23..7170a935e8040e423d00162d539a82f397b088f0 100644 (file)
--- a/tcpdump.1
+++ b/tcpdump.1
@@ -1,4 +1,4 @@
-.\" @(#) $Header: /tcpdump/master/tcpdump/Attic/tcpdump.1,v 1.70 1999-11-21 15:57:50 assar Exp $ (LBL)
+.\" @(#) $Header: /tcpdump/master/tcpdump/Attic/tcpdump.1,v 1.71 1999-12-13 18:06:15 mcr Exp $ (LBL)
 .\"
 .\" Copyright (c) 1987, 1988, 1989, 1990, 1991, 1992, 1994, 1995, 1996, 1997
 .\"    The Regents of the University of California.  All rights reserved.
@@ -40,16 +40,21 @@ tcpdump \- dump traffic on a network
 [
 .B \-i
 .I interface
-] [
+]
+[
+.B \-m
+.I module
+]
+[
 .B \-r
 .I file
 ]
+.br
+.ti +8
 [
 .B \-s
 .I snaplen
 ]
-.br
-.ti +8
 [
 .B \-T
 .I type
@@ -58,6 +63,8 @@ tcpdump \- dump traffic on a network
 .B \-w
 .I file
 ]
+.br
+.ti +8
 [
 .I expression
 ]
@@ -146,6 +153,10 @@ Don't print domain name qualification of host names.  E.g.,
 if you give this flag then \fItcpdump\fP will print ``nic''
 instead of ``nic.ddn.mil''.
 .TP
+.B \-m
+Load SMI MIB module definitions from file \fImodule\fR. This option 
+can be used several times to load several MIB modules into tcpdump.
+.TP
 .B \-O
 Do not run the packet-matching code optimizer.  This is useful only
 if you suspect a bug in the optimizer.
@@ -184,6 +195,7 @@ specified \fItype\fR. Currently known types are
 \fBrpc\fR (Remote Procedure Call),
 \fBrtp\fR (Real-Time Applications protocol),
 \fBrtcp\fR (Real-Time Applications control protocol),
+\fBsnmp\fR (Simple Network Management Protocol),
 \fBvat\fR (Visual Audio Tool),
 and
 \fBwb\fR (distributed White Board).
index 7676185881151cc17872337afb376a0251e04dd1..f331cf8ca0af592bad29815d2dc4c44730504269 100644 (file)
--- a/tcpdump.c
+++ b/tcpdump.c
@@ -24,7 +24,7 @@ static const char copyright[] =
     "@(#) Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997\n\
 The Regents of the University of California.  All rights reserved.\n";
 static const char rcsid[] =
-    "@(#) $Header: /tcpdump/master/tcpdump/tcpdump.c,v 1.135 1999-11-21 09:37:04 fenner Exp $ (LBL)";
+    "@(#) $Header: /tcpdump/master/tcpdump/tcpdump.c,v 1.136 1999-12-13 18:06:15 mcr Exp $ (LBL)";
 #endif
 
 /*
@@ -70,6 +70,7 @@ int Oflag = 1;                        /* run filter code optimizer */
 int pflag;                     /* don't go promiscuous */
 int qflag;                     /* quick (shorter) output */
 int Rflag = 1;                 /* print sequence # field in AH/ESP*/
+int sflag = 0;                 /* use the libsmi to translate OIDs */
 int Sflag;                     /* print raw TCP sequence numbers */
 int tflag = 1;                 /* print packet arrival time */
 int vflag;                     /* verbose */
@@ -167,9 +168,13 @@ main(int argc, char **argv)
        if (abort_on_misalignment(ebuf) < 0)
                error("%s", ebuf);
 
+#ifdef LIBSMI
+       smiInit("tcpdump");
+#endif
+       
        opterr = 0;
        while (
-           (op = getopt(argc, argv, "ac:deE:fF:i:lnNOpqr:Rs:StT:vw:xY")) != EOF)
+           (op = getopt(argc, argv, "ac:deE:fF:i:lnNm:Opqr:Rs:StT:vw:xY")) != EOF)
                switch (op) {
 
                case 'a':
@@ -234,6 +239,18 @@ main(int argc, char **argv)
                        ++Nflag;
                        break;
 
+               case 'm':
+#ifdef LIBSMI
+                       if (smiLoadModule(optarg) == 0) {
+                               error("could not load MIB module %s", optarg);
+                       }
+                       sflag = 1;
+#else
+                       (void)fprintf(stderr, "%s: ignoring option `-m %s' ",
+                                     program_name, optarg);
+                       (void)fprintf(stderr, "(no libsmi support)\n");
+#endif
+                       
                case 'O':
                        Oflag = 0;
                        break;