/*
* Copyright (c) 1990, by John Robert LoVerso.
* 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 MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
* This implementaion 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 implemention 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.
*
* This started out as a very simple program, but the incremental decoding
* (into the BE structure) complicated things.
*
# Los Alamos National Laboratory
#
# Copyright, 1990. The Regents of the University of California.
# 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 char rcsid[] =
"@(#) $Id: detail-snmp.c,v 1.1 1993/04/22 20:17:17 martinh Exp $ (UW)";
#endif
#include <sys/param.h>
#include <sys/types.h>
#include <stdio.h>
#include <ctype.h>
#ifdef TCPVIEW
#include "tcpview.h"
#endif
#include "interface.h"
#include "addrtoname.h"
#include "snmp.h"
/*
* truncated==1 means the packet was complete, but we don't have all of
* it to decode.
*/
static int truncated;
/*
* Decode SNMP varBind
*/
static void varbind_print (pduid, np, length, err)
u_char pduid, *np;
int length, err;
{
struct be elem;
int count = 0, index;
/* Sequence of varBind */
if ((count = asn1_parse(np, length, &elem)) < 0)
return;
hex(0,count-1);
if (elem.type != BE_SEQ) {
printf("ERROR: expected Sequence of variables\n");
return;
}
printf("Sequence of VarBind (%d bytes)",count);
if (count < length)
printf(" [%d extra after Sequence]", length - count);
putchar('\n');
/* descend */
length = elem.asnlen;
Offset += (u_long)elem.data.raw - (u_long)np;
np = (u_char *)elem.data.raw;
for (index = 1; length > 0; index++) {
u_char *vbend;
int vblength;
/* Sequence (VarBind) */
if ((count = asn1_parse(np, length, &elem)) < 0)
return;
hex(0,count-1);
if (elem.type != BE_SEQ) {
printf(" ERROR: expected VarBind\n");
return;
}
vbend = np + count;
vblength = length - count;
printf(" VarBind (%d bytes)\n",elem.asnlen);
/* descend */
length = elem.asnlen;
Offset += (u_long)elem.data.raw - (u_long)np;
np = (u_char *)elem.data.raw;
/* objName (OID) */
if ((count = asn1_parse(np, length, &elem)) < 0)
return;
hex(0,count-1);
if (elem.type != BE_OID) {
printf(" ERROR: expected OBJECT ID\n");
return;
}
if (err && index == err)
printf("UNKNOWN ");
printf(" OBJECT: ");
asn1_print(&elem);
putchar('\n');
length -= count;
np += count;
Offset += count;
/* objVal (ANY) */
if ((count = asn1_parse(np, length, &elem)) < 0)
return;
hex(0,count-1);
printf(" VALUE: ");
if( elem.type == BE_NULL )
printf("NULL");
else
asn1_print(&elem);
putchar('\n');
length = vblength;
np = vbend;
Offset += count;
}
}
/*
* Decode SNMP PDUs: GetRequest, GetNextRequest, GetResponse, and SetRequest
*/
static void snmppdu_print (pduid, np, length)
u_char pduid, *np;
int length;
{
struct be elem;
int count = 0, error, index;
/* reqId (Integer) */
if ((count = asn1_parse(np, length, &elem)) < 0)
return;
hex(0,count-1);
if (elem.type != BE_INT) {
printf("ERROR: expected INTEGER\n");
return;
}
printf("Request ID: %d\n",elem.data.integer);
length -= count;
np += count;
Offset += count;
/* errorStatus (Integer) */
if ((count = asn1_parse(np, length, &elem)) < 0)
return;
hex(0,count-1);
if (elem.type != BE_INT) {
printf("ERROR: expected INTEGER\n");
return;
}
error = elem.data.integer;
printf("Error Status = %d (%s)\n", error, DECODE_ErrorStatus(error));
length -= count;
np += count;
Offset += count;
/* errorIndex (Integer) */
if ((count = asn1_parse(np, length, &elem)) < 0)
return;
hex(0,count-1);
if (elem.type != BE_INT) {
printf("ERROR: expected INTEGER\n");
return;
}
printf("Error Index = %d\n", elem.data.integer);
length -= count;
np += count;
Offset += count;
if( error )
index = elem.data.integer;
else
index = 0;
varbind_print(pduid, np, length, index);
return;
}
/*
* Decode SNMP Trap PDU
*/
static void trap_print (np, length)
u_char *np;
int length;
{
struct be elem;
int count = 0, generic;
/* enterprise (oid) */
if ((count = asn1_parse(np, length, &elem)) < 0)
return;
hex(0,count-1);
if (elem.type != BE_OID) {
printf("ERROR: Expected enterprise OID\n");
return;
}
printf("Enterprise = ");
asn1_print(&elem);
putchar('\n');
length -= count;
np += count;
Offset += count;
/* agent-addr (inetaddr) */
if ((count = asn1_parse(np, length, &elem)) < 0)
return;
hex(0,count-1);
if (elem.type != BE_INETADDR) {
printf("ERROR: expected NetworkAddress\n");
return;
}
printf("Agent Address = ");
asn1_print(&elem);
putchar('\n');
length -= count;
np += count;
Offset += count;
/* generic-trap (Integer) */
if ((count = asn1_parse(np, length, &elem)) < 0)
return;
hex(0,count-1);
if (elem.type != BE_INT) {
printf("ERROR: expected INTEGER\n");
return;
}
generic = elem.data.integer;
printf("Generic Trap Type = %d (%s)\n", generic, DECODE_GenericTrap(generic));
length -= count;
np += count;
Offset += count;
/* specific-trap (Integer) */
if ((count = asn1_parse(np, length, &elem)) < 0)
return;
hex(0,count-1);
if (elem.type != BE_INT) {
printf("ERROR: expected INTEGER\n");
return;
}
printf("Specific Trap = %d\n", elem.data.integer);
length -= count;
np += count;
Offset += count;
/* time-stamp (TimeTicks) */
if ((count = asn1_parse(np, length, &elem)) < 0)
return;
hex(0,count-1);
if (elem.type != BE_UNS) { /* XXX */
printf("ERROR: expected TimeTicks\n");
return;
}
printf("TimeStamp = ");
asn1_print(&elem);
putchar('\n');
length -= count;
np += count;
Offset += count;
varbind_print (TRAP, np, length, 0);
return;
}
/*
* Decode SNMP header and pass on to PDU printing routines
*/
void detail_snmp (np, length)
u_char *np;
int length;
{
struct be elem, pdu;
int count = 0;
truncated = 0;
/* truncated packet? */
if (length > Phdr->caplen-Offset) {
truncated = 1;
length = Phdr->caplen-Offset;
printf("*** SNMP (truncated) ***\n\n");
} else
printf("----- SNMP -----\n\n");
hex( 0, length-1 );
hex( -1, -1 ); /* blank line */
/* initial Sequence */
if ((count = asn1_parse(np, length, &elem)) < 0)
return;
if (elem.type != BE_SEQ) {
printf("ERROR: expected SEQUENCE\n");
hex(0,count-1);
return;
}
printf("Message Sequence (%d bytes)",count);
if (count < length)
printf(" [%d extra after SEQ]", length - count);
hex(0,count-1);
putchar('\n');
/* descend */
Offset += ((u_long)elem.data.raw - (u_long)np);
length = elem.asnlen;
np = (u_char *)elem.data.raw;
/* Version (Integer) */
if ((count = asn1_parse(np, length, &elem)) < 0)
return;
hex(0,count-1);
if (elem.type != BE_INT) {
printf("ERROR: expected INTEGER\n");
return;
}
/* only handle version==0 */
printf("Version: %d",elem.data.integer);
if (elem.data.integer != DEF_VERSION) {
printf("\t[should have been 0]");
return;
}
putchar('\n');
length -= count;
np += count;
Offset += count;
/* Community (String) */
if ((count = asn1_parse(np, length, &elem)) < 0)
return;
hex(0,count-1);
if (elem.type != BE_STR) {
printf("ERROR: expected STRING\n");
return;
}
/* default community */
printf("Community = \"%.*s\"\n", elem.asnlen,elem.data.str);
length -= count;
np += count;
Offset += count;
/* PDU (Context) */
if ((count = asn1_parse(np, length, &pdu)) < 0)
return;
hex(0,count-1);
if (pdu.type != BE_PDU) {
printf("ERROR: expected PDU\n");
return;
}
asn1_print(&pdu);
if (count < length)
printf(" [%d extra after PDU]", length - count);
putchar('\n');
/* descend into PDU */
length = pdu.asnlen;
Offset += (u_long)pdu.data.raw -(u_long)np;
np = (u_char *)pdu.data.raw;
switch (pdu.id) {
case TRAP:
trap_print(np, length);
break;
case GETREQ:
case GETNEXTREQ:
case GETRESP:
case SETREQ:
snmppdu_print(pdu.id, np, length);
break;
}
return;
}
syntax highlighted by Code2HTML, v. 0.9.1