/* snmp.c ** ** Glen Wiley ** ** 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 #include #include #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # 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 = ""; *snmpver = -1; break; } /* get community */ } /* if(*datap) */ else { verstr = ""; } 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, ""); } 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 */