/* snmp.c
**
** Glen Wiley <gwiley@ieee.org>
**
** this provides the means to decompose an snmp v1 packet (pdu)
**
** NOTE: I am relying on the ucd snmp library for much of the heavy
** lifting
**
** $Id: snmp.c,v 1.10 2001/09/07 20:59:11 mborella Exp $
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU Library General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
**
*/
#include "ipgsnmp.h"
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#ifdef HAVE_STRING_H
# include <string.h>
#else
# ifdef HAVE_STRINGS_H
# include <strings.h>
# endif
#endif
/* these are taken from the source dist. of ucd-libsnmp */
#ifdef HAVE_ASN1_H
# include "asn1.h"
#endif
#ifdef HAVE_SNMP_H
# include "snmp.h"
#endif
extern struct arg_t *my_args;
#if !defined(HAVE_LIBSNMP) || !defined(HAVE_ASN1_H)
/*---------------------------------------- dump_snmp */
void
dump_snmp(packet_t *pkt)
{
return;
} /* dump_snmp */
#else /* HAVE_LIBSNMP */
/* we pull this many bytes for the community string (max) */
#define COMMUNITY_LENGTH 40
int snmp_dumpheader(u_char **, u_int32_t *, int *);
int snmp_dumpv1pdu(u_char *, u_int32_t, int);
const int npdutypes = 9;
const char *pdutypes[] =
{
"get request"
, "get-next request"
, "response"
, "set request"
, "v1 trap"
, "get-bulk request"
, "v2 inform"
, "v2 trap"
, "report"
};
/*---------------------------------------- dump_snmp */
void
dump_snmp(packet_t *pkt)
{
/* we will keep the storage we allocate and grow it as needed
* this will be more efficient than repeated malloc/free */
static u_int8_t *pktdata = NULL;
static u_int32_t pktdatasz = 0;
u_char *data;
int snmpver = -1;
u_int32_t nbytes;
/* Set the layer */
set_layer(LAYER_APPLICATION);
/* get all of the remaining data from the packet so that we can
* pass it on to the asn parse api */
nbytes = get_packet_apparentbytesleft(pkt);
if(nbytes > pktdatasz)
{
pktdata = (u_int8_t *) realloc(pktdata, nbytes);
pktdatasz = nbytes;
if(pktdata == NULL)
{
fprintf(stderr, "realloc error, %d: %s", errno, strerror(errno));
exit(1);
}
}
if(get_packet_bytes(pktdata, pkt, nbytes) == 0)
{
return;
}
/* break out the SNMP version, community and pdu */
if (my_args->m)
{
display_minimal_string("| SNMPv");
}
else
{
display_header_banner("SNMP");
}
data = pktdata;
if(snmp_dumpheader(&data, &nbytes, &snmpver) == 0)
{
if(snmpver == SNMP_VERSION_1 || snmpver == SNMP_VERSION_2c)
{
snmp_dumpv1pdu(data, nbytes, snmpver);
}
else if(snmpver == SNMP_VERSION_3)
{
}
else
{
/* TODO: notify user that we can not stomach this pdu */
}
}
else
{
/* TODO: notify the user that the pdu type is either not supported
* or contains format errors
*/
}
return;
} /* dump_snmp */
/*---------------------------------------- snmp_dumpheader
* parses and dumps the snmp header
* the values pointed to by datap, nbytesp and snmpver are updated
* as a side-effect of this function
* return 0 on success, 1 if errors occurred in the header
*/
int
snmp_dumpheader(u_char **datap, u_int32_t *nbytesp, int *snmpver)
{
u_char type;
int retval = 1;
int length;
long version;
char *verstr;
char community[COMMUNITY_LENGTH + 1];
/*-------------------- first try to get the snmp version */
*datap = asn_parse_sequence(*datap, nbytesp, &type
, (ASN_SEQUENCE | ASN_CONSTRUCTOR), "version");
if(*datap)
{
*datap = asn_parse_int(*datap, nbytesp, &type, &version, sizeof(version));
if(*datap)
{
*snmpver = version;
switch(*snmpver)
{
case SNMP_VERSION_1:
verstr = "1";
break;
case SNMP_VERSION_2c:
verstr = "2c";
break;
case SNMP_VERSION_sec: /* not supported */
verstr = "sec";
break;
case SNMP_VERSION_2p:
verstr = "2p";
break;
case SNMP_VERSION_2star: /* not supported */
verstr = "2star";
break;
case SNMP_VERSION_2u: /* not supported */
verstr = "2u";
break;
case SNMP_VERSION_3:
verstr = "3";
break;
default:
verstr = "<invalid>";
*snmpver = -1;
break;
}
/* get community */
} /* if(*datap) */
else
{
verstr = "<invalid>";
}
if(*snmpver != -1)
retval = 0;
if (my_args->m)
{
display_minimal_string(verstr);
display_minimal_string(" ");
}
else
{
display_string("version", verstr);
}
} /* if(*datap) */
/*-------------------- get community if version is ok */
/* TODO: community only shows up here for some versions */
if(*snmpver == SNMP_VERSION_1 || *snmpver == SNMP_VERSION_2c)
{
length = COMMUNITY_LENGTH;
*datap = asn_parse_string(*datap, nbytesp, &type, community, &length);
if(*datap)
{
community[length] = '\0';
}
else
{
retval = 1;
strcpy(community, "<indeterminate>");
}
if (my_args->m)
{
display_minimal_string(community);
display_minimal_string(" ");
}
else
{
display_string("community", community);
}
}
return retval;
} /* snmp_dumpheader */
/*---------------------------------------- snmp_dumpv1pdu
* return 0 on success
*/
int
snmp_dumpv1pdu(u_char *data, u_int32_t nbytes, int snmpver)
{
int retval = 0;
return retval;
} /* snmp_dumpv1pdu */
#endif /* HAVE_LIBSNMP */
/* snmp.c */
syntax highlighted by Code2HTML, v. 0.9.1