MibIter::MibIter(Snmp* snmp, Pdu& pdu, UdpTarget *target): snmp_(snmp), target_(target), pdu_(pdu), first_(0), valid_(0) { // verify we have a valid oid to begin iterating with Oid oid; Vb vb; pdu.get_vb(vb, 0); vb.get_oid(oid); if (oid.valid()) valid_ = 1; }
int wpdu::set_trap_info(snmp_pdu *raw_pdu, const Pdu& pdu) const { Oid enterprise; Oid trapid; // validate caller has set this correctly pdu.get_notify_id( trapid); if ( !trapid.valid() || trapid.length() < 2 ) { cmu_snmp::free_pdu( raw_pdu); return SNMP_CLASS_INVALID_NOTIFYID; } raw_pdu->specific_type=0; // TODO: object should emit numeric instead of this kind of mess... if ( trapid == coldStart) raw_pdu->trap_type = V1_COLD_START; // cold start else if ( trapid == warmStart) raw_pdu->trap_type = V1_WARM_START; // warm start else if( trapid == linkDown) raw_pdu->trap_type = V1_LINK_DOWN; // link down else if ( trapid == linkUp) raw_pdu->trap_type = V1_LINK_UP; // link up else if ( trapid == authenticationFailure ) raw_pdu->trap_type = V1_AUTH_FAILURE; // authentication failure else if ( trapid == egpNeighborLoss) raw_pdu->trap_type = V1_EGP_NEIGHBOR_LOSS; // egp neighbor loss else { raw_pdu->trap_type = V1_ENT_SPECIFIC; // enterprise specific // last oid subid is the specific value // if 2nd to last subid is "0", remove it // enterprise is always the notify oid prefix raw_pdu->specific_type = (int) trapid[(int) (trapid.length() - 1)]; trapid.trim(1); if ( trapid[(int)(trapid.length() - 1)] == 0 ) trapid.trim(1); enterprise = trapid; } if ( raw_pdu->trap_type != V1_ENT_SPECIFIC) pdu.get_notify_enterprise( enterprise); if ( enterprise.length() > 0) { // note!! To the contrary, enterprise OID val is // copied here and raw_pdu->enterprise is freed in free_pdu // as it should be (HDN) // these are hooks into an SNMP++ oid // and therefor the raw_pdu enterprise // should not free them. null them out!! SmiLPOID rawOid; rawOid = enterprise.oidval(); // HDN - enterprise is a local object, cannot simply assign pointer //raw_pdu->enterprise = rawOid->ptr; raw_pdu->enterprise_length = (int) rawOid->len; ACE_NEW_RETURN(raw_pdu->enterprise, oid[raw_pdu->enterprise_length],-1); ACE_OS::memcpy((char *)raw_pdu->enterprise,(char *)rawOid->ptr, raw_pdu->enterprise_length * sizeof(oid)); } TimeTicks timestamp; pdu.get_notify_timestamp( timestamp); raw_pdu->time = ( unsigned long) timestamp; // HDN - set agent addr using the local hostname if possible char localHostName[MAXHOSTNAMELEN]; Snmp::get_host_name(localHostName, MAXHOSTNAMELEN); if (ACE_OS::strlen(localHostName) > 0) { GenAddress addr(localHostName); OctetStr octet; addr.to_octet(octet); ACE_OS::memcpy(&(raw_pdu->agent_addr.sin_addr), octet.data(), octet.length()); } return 0; }
set::set(int argc, char *argv[]): valid_(0) { Vb vb; // construct a Vb object Oid req; if ( argc < 2) return; target_.get_write_community(community_); address_ = argv[argc - 1]; if ( !address_.valid()) { cout << "ERROR: Invalid IPv4 address or DNS hostname: " \ << argv[argc] << "\n"; return; } ACE_Get_Opt get_opt (argc, argv, "o:c:r:t:I:U:C:G:T:O:S:P:"); for (int c; (c = get_opt ()) != -1; ) switch (c) { case 'o': req = get_opt.optarg; if (req.valid() == 0) cout << "ERROR: oid value: " <<get_opt.optarg \ << "is not valid. using default.\n"; break; case 'c': community_ = get_opt.optarg; target_.set_write_community(community_); break; case 'r': target_.set_retry(ACE_OS::atoi (get_opt.optarg)); break; case 't': target_.set_timeout(ACE_OS::atoi (get_opt.optarg)); break; case 'I': // Integer32 { SnmpInt32 o(ACE_OS::atoi(get_opt.optarg)); vb.set_value(o); pdu_ += vb; } break; case 'U': // Unsigned32 { SnmpUInt32 o(ACE_OS::atoi(get_opt.optarg)); vb.set_value(o); pdu_ += vb; } break; case 'C': // Counter32 { Counter32 o(ACE_OS::atoi(get_opt.optarg)); vb.set_value(o); pdu_ += vb; } break; case 'G': // Gauge32 { Gauge32 o(ACE_OS::atoi(get_opt.optarg)); vb.set_value(o); pdu_ += vb; } break; case 'T': // TimeTicks { TimeTicks o(ACE_OS::atoi(get_opt.optarg)); vb.set_value(o); pdu_ += vb; } break; case 'O': // Oid as a variable identifier { oid_ = get_opt.optarg; vb.set_oid(oid_); // when value is set, pdu updated } break; case 'S': // Octet String { OctetStr o(get_opt.optarg); vb.set_value(o); // set the Oid portion of the Vb pdu_ += vb; } break; case 'P': // Oid String as a value { Oid o(get_opt.optarg); vb.set_value(o); // set the Oid portion of the Vb pdu_ += vb; } break; default: break; } // if user didn't set anything use defaults if (pdu_.get_vb_count() == 0) { Oid def_oid("1.3.6.1.2.1.1.4.0"); // defualt is sysName OctetStr def_value("sysName.0 updated by ASNMP set command"); vb.set_oid(def_oid); vb.set_value(def_value); pdu_ += vb; cout << "INFO: using defaults, setting sysName to : " << \ def_value.to_string() << endl; } valid_ = 1; }
int SnmpMessage::load(const Pdu &cpdu, const OctetStr &community, const snmp_version version, const OctetStr* engine_id, const OctetStr* security_name, const int security_model) { int status; const Pdu *pdu = &cpdu; Pdu temppdu; // make sure pdu is valid if ( !pdu->valid()) return SNMP_CLASS_INVALID_PDU; // create a raw pdu snmp_pdu *raw_pdu; raw_pdu = snmp_pdu_create( (int) pdu->get_type()); Oid enterprise; // load it up raw_pdu->reqid = pdu->get_request_id(); #ifdef _SNMPv3 raw_pdu->msgid = pdu->get_message_id(); #endif raw_pdu->errstat= (unsigned long) pdu->get_error_status(); raw_pdu->errindex= (unsigned long) pdu->get_error_index(); // if its a V1 trap then load up other values // for v2, use normal pdu format if (raw_pdu->command == sNMP_PDU_V1TRAP) { // DON'T forget about the v1 trap agent address (changed by Frank Fock) GenAddress gen_addr; IpAddress ip_addr; int addr_set = FALSE; if (pdu->get_v1_trap_address(gen_addr)) { /* User did set the v1 trap address */ if ((gen_addr.get_type() != Address::type_ip) && (gen_addr.get_type() != Address::type_udp) ) { LOG_BEGIN(ERROR_LOG | 4); LOG("SNMPMessage: Bad v1 trap address type in pdu"); LOG(gen_addr.get_type()); LOG_END; snmp_free_pdu( raw_pdu); return SNMP_CLASS_INVALID_PDU; } ip_addr = gen_addr; if (!ip_addr.valid()) { LOG_BEGIN(ERROR_LOG | 1); LOG("SNMPMessage: Copied v1 trap address not valid"); LOG_END; snmp_free_pdu( raw_pdu); return SNMP_CLASS_RESOURCE_UNAVAIL; } addr_set = TRUE; } else { /* User did not set the v1 trap address */ char addrString[256]; if (gethostname(addrString, 255) == 0) { ip_addr = addrString; addr_set = TRUE; } } struct sockaddr_in agent_addr; // agent address socket struct // prepare the agent address memset(&agent_addr, 0, sizeof(agent_addr)); agent_addr.sin_family = AF_INET; if (addr_set) { agent_addr.sin_addr.s_addr = inet_addr(((IpAddress &)ip_addr).IpAddress::get_printable()); LOG_BEGIN(INFO_LOG | 7); LOG("SNMPMessage: Setting v1 trap address"); LOG(((IpAddress &)ip_addr).IpAddress::get_printable()); LOG_END; } raw_pdu->agent_addr = agent_addr; //-----[ compute generic trap value ]------------------------------- // determine the generic value // 0 - cold start // 1 - warm start // 2 - link down // 3 - link up // 4 - authentication failure // 5 - egpneighborloss // 6 - enterprise specific Oid trapid; pdu->get_notify_id( trapid); if ( !trapid.valid() || trapid.len() < 2 ) { snmp_free_pdu( raw_pdu); return SNMP_CLASS_INVALID_NOTIFYID; } raw_pdu->specific_type=0; if ( trapid == coldStart) raw_pdu->trap_type = 0; // cold start else if ( trapid == warmStart) raw_pdu->trap_type = 1; // warm start else if( trapid == linkDown) raw_pdu->trap_type = 2; // link down else if ( trapid == linkUp) raw_pdu->trap_type = 3; // link up else if ( trapid == authenticationFailure ) raw_pdu->trap_type = 4; // authentication failure else if ( trapid == egpNeighborLoss) raw_pdu->trap_type = 5; // egp neighbor loss else { raw_pdu->trap_type = 6; // enterprise specific // last oid subid is the specific value // if 2nd to last subid is "0", remove it // enterprise is always the notify oid prefix raw_pdu->specific_type = (int) trapid[(int) (trapid.len()-1)]; trapid.trim(1); if ( trapid[(int)(trapid.len()-1)] == 0 ) trapid.trim(1); enterprise = trapid; } if ( raw_pdu->trap_type !=6) pdu->get_notify_enterprise( enterprise); if ( enterprise.len() >0) { // note!! // these are hooks into an SNMP++ oid // and therefor the raw_pdu enterprise // should not free them. null them out!! SmiLPOID rawOid; rawOid = enterprise.oidval(); raw_pdu->enterprise = rawOid->ptr; raw_pdu->enterprise_length = (int) rawOid->len; } // timestamp TimeTicks timestamp; pdu->get_notify_timestamp( timestamp); raw_pdu->time = ( unsigned long) timestamp; } // if its a v2 trap then we need to make a few adjustments // vb #1 is the timestamp // vb #2 is the id, represented as an Oid if (( raw_pdu->command == sNMP_PDU_TRAP) || ( raw_pdu->command == sNMP_PDU_INFORM)) { Vb tempvb; temppdu = *pdu; temppdu.trim(temppdu.get_vb_count()); // vb #1 is the timestamp TimeTicks timestamp; tempvb.set_oid(SNMP_MSG_OID_SYSUPTIME); // sysuptime pdu->get_notify_timestamp( timestamp); tempvb.set_value ( timestamp); temppdu += tempvb; // vb #2 is the id Oid trapid; tempvb.set_oid(SNMP_MSG_OID_TRAPID); pdu->get_notify_id( trapid); tempvb.set_value( trapid); temppdu += tempvb; // append the remaining vbs for (int z=0; z<pdu->get_vb_count(); z++) { pdu->get_vb( tempvb,z); temppdu += tempvb; } pdu = &temppdu; // reassign the pdu to the temp one } // load up the payload // for all Vbs in list, add them to the pdu int vb_count; Vb tempvb; Oid tempoid; SmiLPOID smioid; SmiVALUE smival; vb_count = pdu->get_vb_count(); for (int z=0;z<vb_count;z++) { pdu->get_vb( tempvb,z); tempvb.get_oid( tempoid); smioid = tempoid.oidval(); // clear the value portion, in case its // not already been done so by the app writer // only do it in the case its a get,next or bulk if ((raw_pdu->command == sNMP_PDU_GET) || (raw_pdu->command == sNMP_PDU_GETNEXT) || (raw_pdu->command == sNMP_PDU_GETBULK)) tempvb.set_null(); status = convertVbToSmival( tempvb, &smival ); if ( status != SNMP_CLASS_SUCCESS) { snmp_free_pdu( raw_pdu); return status; } // add the vb to the raw pdu snmp_add_var( raw_pdu, smioid->ptr, (int) smioid->len, &smival); freeSmivalDescriptor( &smival); } // ASN1 encode the pdu #ifdef _SNMPv3 if (version == version3) { if ((!engine_id) || (!security_name)) { LOG_BEGIN(ERROR_LOG | 4); LOG("SNMPMessage: Need security name and engine id for v3 message"); LOG_END; // prevention of SNMP++ Enterprise Oid death if ( enterprise.len() >0) { raw_pdu->enterprise = 0; raw_pdu->enterprise_length=0; } snmp_free_pdu( raw_pdu); return SNMP_CLASS_INVALID_TARGET; } status = v3MP::I->snmp_build(raw_pdu, databuff, (int *)&bufflen, *engine_id, *security_name, security_model, pdu->get_security_level(), pdu->get_context_engine_id(), pdu->get_context_name()); if (status == SNMPv3_MP_OK) { if ((pdu->get_type() == sNMP_PDU_RESPONSE) && ((int)pdu->get_maxsize_scopedpdu() < pdu->get_asn1_length())) { LOG_BEGIN(ERROR_LOG | 1); LOG("SNMPMessage: *BUG*: Serialized response pdu is too big (len) (max)"); LOG(pdu->get_asn1_length()); LOG(pdu->get_maxsize_scopedpdu()); LOG_END; // prevention of SNMP++ Enterprise Oid death if ( enterprise.len() >0) { raw_pdu->enterprise = 0; raw_pdu->enterprise_length=0; } snmp_free_pdu( raw_pdu); return SNMP_ERROR_TOO_BIG; } } } else #endif status = snmp_build( raw_pdu, databuff, (int *) &bufflen, version, community.data(), (int) community.len()); LOG_BEGIN(DEBUG_LOG | 4); LOG("SNMPMessage: return value for build message"); LOG(status); LOG_END; if ((status != 0) #ifdef _SNMPv3 && ((version != version3) || (status != SNMPv3_MP_OK)) #endif ) { valid_flag = false; // prevention of SNMP++ Enterprise Oid death if ( enterprise.len() >0) { raw_pdu->enterprise = 0; raw_pdu->enterprise_length=0; } snmp_free_pdu( raw_pdu); #ifdef _SNMPv3 if (version == version3) return status; else #endif // NOTE: This is an assumption - in most cases during normal // operation the reason is a tooBig - another could be a // damaged variable binding. return SNMP_ERROR_TOO_BIG; } valid_flag = true; // prevention of SNMP++ Enterprise Oid death if ( enterprise.len() >0) { raw_pdu->enterprise = 0; raw_pdu->enterprise_length=0; } snmp_free_pdu( raw_pdu); return SNMP_CLASS_SUCCESS; }