// unload the data into SNMP++ objects int SnmpMessage::unload(Pdu &pdu, // Pdu object OctetStr &community, // community object snmp_version &version, // SNMP version # OctetStr *engine_id, // optional v3 OctetStr *security_name, // optional v3 long int *security_model, UdpAddress *from_addr, Snmp *snmp_session) { pdu.clear(); if (!valid_flag) return SNMP_CLASS_INVALID; snmp_pdu *raw_pdu; raw_pdu = snmp_pdu_create(0); // do a "snmp_free_pdu( raw_pdu)" before return int status; #ifdef _SNMPv3 OctetStr context_engine_id; OctetStr context_name; long int security_level = SNMP_SECURITY_LEVEL_NOAUTH_NOPRIV; if ((security_model) && (security_name) && (engine_id) && (snmp_session)) { status = v3MP::I->snmp_parse(snmp_session, raw_pdu, databuff, (int)bufflen, *engine_id, *security_name, context_engine_id, context_name, security_level, *security_model, version, *from_addr); if (status != SNMPv3_MP_OK) { pdu.set_request_id( raw_pdu->reqid); pdu.set_type( raw_pdu->command); snmp_free_pdu( raw_pdu); return status; } pdu.set_context_engine_id(context_engine_id); pdu.set_context_name(context_name); pdu.set_security_level(security_level); pdu.set_message_id(raw_pdu->msgid); pdu.set_maxsize_scopedpdu(raw_pdu->maxsize_scopedpdu); } else { #endif unsigned char community_name[MAX_LEN_COMMUNITY + 1]; int community_len = MAX_LEN_COMMUNITY + 1; status = snmp_parse(raw_pdu, databuff, (int) bufflen, community_name, community_len, version); if (status != SNMP_CLASS_SUCCESS) { snmp_free_pdu(raw_pdu); return status; } community.set_data( community_name, community_len); #ifdef _SNMPv3 } #endif // load up the SNMP++ variables pdu.set_request_id(raw_pdu->reqid); pdu.set_error_status((int) raw_pdu->errstat); pdu.set_error_index((int) raw_pdu->errindex); pdu.set_type( raw_pdu->command); // deal with traps a little different if ( raw_pdu->command == sNMP_PDU_V1TRAP) { // timestamp TimeTicks timestamp; timestamp = raw_pdu->time; pdu.set_notify_timestamp( timestamp); // set the agent address IpAddress agent_addr(inet_ntoa(raw_pdu->agent_addr.sin_addr)); if (agent_addr != "0.0.0.0") { pdu.set_v1_trap_address(agent_addr); LOG_BEGIN(DEBUG_LOG | 4); LOG("SNMPMessage: Trap address of received v1 trap"); LOG(agent_addr.get_printable()); LOG_END; } // set enterprise, notifyid Oid enterprise; if (raw_pdu->enterprise_length >0) { for (int i=0; i< raw_pdu->enterprise_length; i++) { enterprise += (int) (raw_pdu->enterprise[i]); } pdu.set_notify_enterprise(enterprise); } switch (raw_pdu->trap_type) { case 0: pdu.set_notify_id(coldStart); break; case 1: pdu.set_notify_id(warmStart); break; case 2: pdu.set_notify_id(linkDown); break; case 3: pdu.set_notify_id(linkUp); break; case 4: pdu.set_notify_id(authenticationFailure); break; case 5: pdu.set_notify_id(egpNeighborLoss); break; case 6: { // enterprise specific // base id + specific # Oid eOid = enterprise; eOid += 0ul; eOid += raw_pdu->specific_type; pdu.set_notify_id( eOid); break; } default: { LOG_BEGIN(WARNING_LOG | 3); LOG("SNMPMessage: Received trap with illegal trap type"); LOG(raw_pdu->trap_type); LOG_END; } } } // vbs Vb tempvb; Oid tempoid; struct variable_list *vp; int vb_nr = 1; for(vp = raw_pdu->variables; vp; vp = vp->next_variable, vb_nr++) { // extract the oid portion tempoid.set_data( (unsigned long *)vp->name, ( unsigned int) vp->name_length); tempvb.set_oid( tempoid); // extract the value portion switch(vp->type){ // octet string case sNMP_SYNTAX_OCTETS: { OctetStr octets( (unsigned char *) vp->val.string, (unsigned long) vp->val_len); tempvb.set_value( octets); } break; case sNMP_SYNTAX_OPAQUE: { OpaqueStr octets( (unsigned char *) vp->val.string, (unsigned long) vp->val_len); tempvb.set_value( octets); } break; // object id case sNMP_SYNTAX_OID: { Oid oid( (unsigned long*) vp->val.objid, (int) vp->val_len); tempvb.set_value( oid); if ((vb_nr == 2) && ((raw_pdu->command == sNMP_PDU_TRAP) || (raw_pdu->command == sNMP_PDU_INFORM)) && (tempoid == SNMP_MSG_OID_TRAPID)) { // set notify_id pdu.set_notify_id(oid); continue; // don't add vb to pdu } } break; // timeticks case sNMP_SYNTAX_TIMETICKS: { TimeTicks timeticks( (unsigned long) *(vp->val.integer)); tempvb.set_value( timeticks); if ((vb_nr == 1) && ((raw_pdu->command == sNMP_PDU_TRAP) || (raw_pdu->command == sNMP_PDU_INFORM)) && (tempoid == SNMP_MSG_OID_SYSUPTIME)) { // set notify_timestamp pdu.set_notify_timestamp( timeticks); continue; // don't add vb to pdu } } break; // 32 bit counter case sNMP_SYNTAX_CNTR32: { Counter32 counter32( (unsigned long) *(vp->val.integer)); tempvb.set_value( counter32); } break; // 32 bit gauge case sNMP_SYNTAX_GAUGE32: { Gauge32 gauge32( (unsigned long) *(vp->val.integer)); tempvb.set_value( gauge32); } break; // ip address case sNMP_SYNTAX_IPADDR: { char buffer[42]; if (vp->val_len == 16) sprintf( buffer, "%02x%02x:%02x%02x:%02x%02x:%02x%02x:" "%02x%02x:%02x%02x:%02x%02x:%02x%02x", vp->val.string[ 0], vp->val.string[ 1], vp->val.string[ 2], vp->val.string[ 3], vp->val.string[ 4], vp->val.string[ 5], vp->val.string[ 6], vp->val.string[ 7], vp->val.string[ 8], vp->val.string[ 9], vp->val.string[10], vp->val.string[11], vp->val.string[12], vp->val.string[13], vp->val.string[14], vp->val.string[15]); else sprintf( buffer,"%d.%d.%d.%d", vp->val.string[0], vp->val.string[1], vp->val.string[2], vp->val.string[3]); IpAddress ipaddress( buffer); tempvb.set_value( ipaddress); } break; // 32 bit integer case sNMP_SYNTAX_INT: { SnmpInt32 int32( (long) *(vp->val.integer)); tempvb.set_value( int32); } break; // 32 bit unsigned integer /* Not distinguishable from Gauge32 case sNMP_SYNTAX_UINT32: { SnmpUInt32 uint32( (unsigned long) *(vp->val.integer)); tempvb.set_value( uint32); } break; */ // v2 counter 64's case sNMP_SYNTAX_CNTR64: { // Frank Fock (was empty before) Counter64 c64(((counter64*)vp->val.counter64)->high, ((counter64*)vp->val.counter64)->low); tempvb.set_value( c64); break; } case sNMP_SYNTAX_NULL: tempvb.set_null(); break; // v2 vb exceptions case sNMP_SYNTAX_NOSUCHOBJECT: case sNMP_SYNTAX_NOSUCHINSTANCE: case sNMP_SYNTAX_ENDOFMIBVIEW: tempvb.set_exception_status(vp->type); break; default: tempvb.set_null(); } // end switch // append the vb to the pdu pdu += tempvb; } snmp_free_pdu( raw_pdu); return SNMP_CLASS_SUCCESS; }
int main(int argc, char **argv) { //---------[ check the arg count ]---------------------------------------- if ( argc < 2) { cout << "Usage:\n"; cout << "snmpTraps IpAddress | DNSName [Id] [options]\n"; cout << "Id = default is 1.3.6.1.6.3.1.1.5.1 = ColdStart"; cout << "options: -vN , use SNMP version 1, 2 or 3, default is 1\n"; cout << " -PPort , remote port to use\n"; cout << " -CCommunity_name, specify community default is 'public' \n"; #ifdef _SNMPv3 cout << " -snSecurityName, " << endl; cout << " -slN , securityLevel to use, default N = 3 = authPriv" << endl; cout << " -smN , securityModel to use, only default N = 3 = USM possible\n"; cout << " -cnContextName, default empty string" << endl; cout << " -ceContextEngineID, as hex e.g. 800007E580, default empty string" << endl; cout << " -authPROT, use authentication protocol NONE, SHA or MD5\n"; cout << " -privPROT, use privacy protocol NONE, DES, 3DESEDE, IDEA, AES128, AES192 or AES256\n"; cout << " -uaAuthPassword\n"; cout << " -upPrivPassword\n"; #endif return 1; } Snmp::socket_startup(); // Initialize socket subsystem //---------[ make a GenAddress and Oid object to retrieve ]--------------- UdpAddress address( argv[1]); // make a SNMP++ Generic address if ( !address.valid()) { // check validity of address cout << "Invalid Address or DNS Name, " << argv[1] << "\n"; return 1; } Oid oid( COLDSTART); // default is ColdStart if ( argc >= 3) { // if 3 args, then use the callers Oid if ( strstr( argv[2],"-")==0) { oid = argv[2]; if ( !oid.valid()) { // check validity of user oid cout << "Invalid Oid, " << argv[2] << "\n"; return 1; } } } //---------[ determine options to use ]----------------------------------- snmp_version version=version1; // default is v1 u_short port=161; // default snmp port is 161 OctetStr community("public"); // community name Oid ent(ENTERPRISE); // default enterprise #ifdef _SNMPv3 OctetStr privPassword(""); OctetStr authPassword(""); OctetStr securityName(""); int securityModel = SecurityModel_USM; int securityLevel = SecurityLevel_authPriv; OctetStr contextName(""); OctetStr contextEngineID(""); long authProtocol = SNMPv3_usmNoAuthProtocol; long privProtocol = SNMPv3_usmNoPrivProtocol; v3MP *v3_MP; #endif char *ptr; for(int x=1; x<argc; x++) { // parse for version if ( strstr( argv[x],"-v2")!= 0) { version = version2c; continue; } if ( strstr( argv[x],"-C")!=0) { ptr = argv[x]; ptr++; ptr++; community = ptr; continue; } if ( strstr( argv[x],"-P")!=0) { ptr = argv[x]; ptr++; ptr++; sscanf(ptr, "%hu", &port); continue; } #ifdef _SNMPv3 if ( strstr( argv[x],"-v3")!= 0) { version = version3; continue; } if ( strstr( argv[x],"-auth") != 0) { ptr = argv[x]; ptr+=5; if (strcasecmp(ptr, "SHA") == 0) authProtocol = SNMP_AUTHPROTOCOL_HMACSHA; else if (strcasecmp(ptr, "MD5") == 0) authProtocol = SNMP_AUTHPROTOCOL_HMACMD5; else authProtocol = SNMP_AUTHPROTOCOL_NONE; continue; } if ( strstr( argv[x],"-priv") != 0) { ptr = argv[x]; ptr+=5; if (strcasecmp(ptr, "DES") == 0) privProtocol = SNMP_PRIVPROTOCOL_DES; else if (strcasecmp(ptr, "3DESEDE") == 0) privProtocol = SNMP_PRIVPROTOCOL_3DESEDE; else if (strcasecmp(ptr, "IDEA") == 0) privProtocol = SNMP_PRIVPROTOCOL_IDEA; else if (strcasecmp(ptr, "AES128") == 0) privProtocol = SNMP_PRIVPROTOCOL_AES128; else if (strcasecmp(ptr, "AES192") == 0) privProtocol = SNMP_PRIVPROTOCOL_AES192; else if (strcasecmp(ptr, "AES256") == 0) privProtocol = SNMP_PRIVPROTOCOL_AES256; else privProtocol = SNMP_PRIVPROTOCOL_NONE; printf("\n\nPrivProt : %ld\n", privProtocol); continue; } if ( strstr( argv[x],"-sn")!=0) { ptr = argv[x]; ptr+=3; securityName = ptr; continue; } if ( strstr( argv[x], "-sl")!=0) { ptr = argv[x]; ptr+=3; securityLevel = atoi( ptr); if (( securityLevel < SecurityLevel_noAuthNoPriv) || ( securityLevel > SecurityLevel_authPriv)) securityLevel = SecurityLevel_authPriv; continue; } if ( strstr( argv[x], "-sm")!=0) { ptr = argv[x]; ptr+=3; securityModel = atoi( ptr); if (( securityModel < SecurityModel_v1) || ( securityModel > SecurityModel_USM)) securityModel = SecurityModel_USM; continue; } if ( strstr( argv[x],"-cn")!=0) { ptr = argv[x]; ptr+=3; contextName = ptr; continue; } if ( strstr( argv[x],"-ce")!=0) { ptr = argv[x]; ptr+=3; contextEngineID = OctetStr::from_hex_string(ptr); continue; } if ( strstr( argv[x],"-ua")!=0) { ptr = argv[x]; ptr+=3; authPassword = ptr; continue; } if ( strstr( argv[x],"-up")!=0) { ptr = argv[x]; ptr+=3; privPassword = ptr; continue; } #endif } //----------[ create a SNMP++ session ]----------------------------------- int status; Snmp *snmp; if (address.get_ip_version() == Address::version_ipv4) snmp = new Snmp(status, "0.0.0.0"); else snmp = new Snmp(status, "::"); if ( status != SNMP_CLASS_SUCCESS) { cout << "SNMP++ Session Create Fail, " << snmp->error_msg(status) << "\n"; return 1; } //---------[ init SnmpV3 ]-------------------------------------------- #ifdef _SNMPv3 if (version == version3) { char *engineId = "TrapSender"; char *filename = "snmpv3_boot_counter"; unsigned int snmpEngineBoots = 0; int status; status = getBootCounter(filename, engineId, snmpEngineBoots); if ((status != SNMPv3_OK) && (status < SNMPv3_FILEOPEN_ERROR)) { cout << "Error loading snmpEngineBoots counter: " << status << endl; return 1; } snmpEngineBoots++; status = saveBootCounter(filename, engineId, snmpEngineBoots); if (status != SNMPv3_OK) { cout << "Error saving snmpEngineBoots counter: " << status << endl; return 1; } int construct_status; v3_MP = new v3MP(engineId, snmpEngineBoots, construct_status); USM *usm = v3_MP->get_usm(); usm->add_usm_user(securityName, authProtocol, privProtocol, authPassword, privPassword); } else { // MUST create a dummy v3MP object if _SNMPv3 is enabled! int construct_status; v3_MP = new v3MP("dummy", 0, construct_status); } #endif //--------[ build up SNMP++ object needed ]------------------------------- Pdu pdu; // construct a Pdu object Vb vb; // variable binding object to use vb.set_oid(PAYLOADID); // example oid for trap payload vb.set_value(PAYLOAD); // example string for payload pdu += vb; // append the vb to the pdu pdu.set_notify_id( oid); // set the id of the trap pdu.set_notify_enterprise( ent); // set up the enterprise of the trap address.set_port(port); CTarget ctarget( address); // make a target using the address #ifdef _SNMPv3 UTarget utarget( address); if (version == version3) { utarget.set_version( version); // set the SNMP version SNMPV1 or V2 or V3 utarget.set_security_model( securityModel); utarget.set_security_name( securityName); pdu.set_security_level( securityLevel); pdu.set_context_name (contextName); pdu.set_context_engine_id(contextEngineID); } else { #endif ctarget.set_version( version); // set the SNMP version SNMPV1 or V2 ctarget.set_readcommunity( community); // set the read community name #ifdef _SNMPv3 } #endif //-------[ Send the trap ]------------------------------------------------ cout << "SNMP++ Trap to " << argv[1] << " SNMPV" #ifdef _SNMPv3 << ((version==version3) ? (version) : (version+1)); #else << (version+1);