int trapapp::run() { if ( snmp_.valid() != SNMP_CLASS_SUCCESS) { cout << "\nASNMP:ERROR:Create session failed: "<< snmp_.error_string()<< "\n"; return 1; } if (address_.get_port() == 0) address_.set_port(DEF_TRAP_PORT); target_.set_address( address_); // make a target using the address //-------[ issue the request, blocked mode ]----------------------------- cout << "\nASNMP:INFO:SNMP Version " << (target_.get_version()+ 1) << \ " TRAP GENERATOR SAMPLE PROGRAM \nOID: " << oid_.to_string() << "\n"; target_.get_address(address_); // target updates port used int rc; const char *name = address_.resolve_hostname(rc); cout << "Device: " << address_ << " "; cout << (rc ? "<< did not resolve via gethostbyname() >>" : name) << "\n"; cout << "[ Community=" << community_.to_string() << " ]"<< endl; if (snmp_.trap( pdu_, target_) == SNMP_CLASS_SUCCESS) { cout << "Trap was written to network...\n"; } else { const char *ptr = snmp_.error_string(); cout << "ASNMP:ERROR: trap command failed reason: " << ptr << endl; } cout << "ASNMP:INFO:command completed normally.\n"<< endl; return 0; }
// Get the engine_id of the SNMP entity at the given host/port. int v3MP::EngineIdTable::get_entry(OctetStr &engine_id, const OctetStr &hostport) const { int port; char host[MAX_HOST_NAME_LENGTH + 1]; char *ptr; /* Check length */ if (hostport.len() > MAX_HOST_NAME_LENGTH) return SNMPv3_MP_ERROR; /* split up port from hostport */ strcpy(host, hostport.get_printable()); ptr = strstr((char*)host,"/"); if (!ptr) return SNMPv3_MP_ERROR; *ptr = '\0'; port = atol(ptr + 1); /* Check for IPv6 address with [] */ if (host[0] == '[') { if (*(ptr -1) == ']') { *(ptr-1) = '\0'; return get_entry(engine_id, &(host[1]), port); } else return SNMPv3_MP_ERROR; } return get_entry(engine_id, host, port); }
int CSVBaseSNMP::InitUTarget() { int nResult = 0; m_Utarget = address; //construct UTarger By address Class m_Utarget.set_version(version); // set the SNMP version SNMPV1 or V2 or V3 m_Utarget.set_retry(m_nRetries); // set the number of auto retries m_Utarget.set_timeout(m_nTimeout); // set timeout m_Utarget.set_security_model(m_lSecurityModel); //Set Security Model m_Utarget.set_security_name(m_szSecurityName); //Set Security Name (Auth Name) OctetStr EgID;//Engine ID //Get Engine ID // if(m_pSnmp) // nResult = m_pSnmp->unicast_discovery(EgID, (m_nTimeout + 99) / 100, address, version, &m_szCommunity); if(EgID.len() > 0) {//Engine ID Length Big Than 0 m_Utarget.set_engine_id(EgID); //Set Engine ID } else {//Less Than 0 return 1; //return Failed } return 0; //retrun Successed }
//=======[ create an octet string from a hex string ]=================== OctetStr OctetStr::from_hex_string(const OctetStr &hex_string) { OctetStr val; unsigned int p; unsigned int hex_len = 0; // make sure the string has at least one byte if (hex_string.len() == 0) return val; // allocate max needed space for copy without spaces unsigned char *hex, *hex_ptr; hex = hex_ptr = new unsigned char[hex_string.len()]; if (!hex) return val; // delete spaces const unsigned char *ptr = hex_string.smival.value.string.ptr; for (p = hex_string.len(); p > 0; p--) { unsigned char c = *ptr++; if (c != ' ') { *hex_ptr++ = c; ++hex_len; } } // leading 0 may be omitted if (hex_len % 2) { unsigned char c = hex[0]; ATOI(c); val += c; p = 1; } else { p = 0; } while (p < hex_len) { unsigned char c = hex[p++]; unsigned char d = hex[p++]; ATOI(c); ATOI(d); val += (c*16 + d); } delete[] hex; return val; }
int agentppTestSparseCol3::prepare_set_request(Request* req, int& ind) { int status; if ((status = MibLeaf::prepare_set_request(req, ind)) != SNMP_ERROR_SUCCESS) return status; Vb vb(req->get_value(ind)); OctetStr v; vb.get_value(v); if (!(((v.len() >= 0) && (v.len() <= 255)))) return SNMP_ERROR_WRONG_LENGTH; //--AgentGen BEGIN=agentppTestSparseCol3::prepare_set_request //--AgentGen END return SNMP_ERROR_SUCCESS; }
// Get the engineID of the SNMP entity at the given host/port. int v3MP::EngineIdTable::get_entry(OctetStr &engine_id, const OctetStr &host, int port) const { if (!table) return SNMPv3_MP_NOT_INITIALIZED; BEGIN_REENTRANT_CODE_BLOCK_CONST; int i, found = 0; for (i = 0; i < entries; i++) if ((table[i].port == port) && (table[i].host == host)) { found=1; break; } if (!found) { LOG_BEGIN(loggerModuleName, INFO_LOG | 4); LOG("v3MP::EngineIdTable: Dont know engine id for (host) (port)"); LOG(host.get_printable()); LOG(port); LOG_END; return SNMPv3_MP_ERROR; } engine_id = table[i].engine_id; return SNMPv3_MP_OK; }
//===============[ not equivlence operator overloaded ]=============== int operator!=(const OctetStr &lhs, const char *rhs) { OctetStr to(rhs); if (lhs.smival.value.string.len != to.smival.value.string.len) return true; return (lhs.nCompare(to.smival.value.string.len, to) != 0); }
//===============[ greater than >= operator overloaded ]============== int operator>=(const OctetStr &lhs, const char *rhs) { OctetStr to(rhs); int maxlen = lhs.smival.value.string.len > to.smival.value.string.len ? lhs.smival.value.string.len : to.smival.value.string.len; return (lhs.nCompare(maxlen, to) >= 0); }
//===============[ greater than > overloaded ]======================== bool operator>( const OctetStr &lhs, const OctetStr &rhs) { if( lhs.left_comparison( rhs.smival.value.string.len, rhs)>0) return true; else return false; }
// Remove the entry for the given address/port from the table. int v3MP::EngineIdTable::delete_entry(const OctetStr &host, int port) { if (!table) return SNMPv3_MP_NOT_INITIALIZED; int i, found = 0; BEGIN_REENTRANT_CODE_BLOCK; for (i = 0; i < entries; i++) if ((table[i].port == port) && (table[i].host == host)) { found=1; break; } if (!found) { LOG_BEGIN(loggerModuleName, WARNING_LOG | 4); LOG("v3MP::EngineIdTable: cannot remove nonexisting entry (host) (port)"); LOG(host.get_printable()); LOG(port); LOG_END; return SNMPv3_MP_ERROR; } /* i is the entry to remove */ if (i != entries - 1) table[i] = table[entries-1]; entries--; return SNMPv3_MP_OK; }
//==============[ less than <= overloaded ]=========================== bool operator<=( const OctetStr &lhs, const OctetStr &rhs) { if(( lhs.left_comparison( rhs.smival.value.string.len, rhs)<0) || ( lhs.left_comparison( rhs.smival.value.string.len, rhs)==0)) return true; else return false; }
//===============[ greater than > operator overloaded ]=============== bool operator>( const OctetStr &lhs,const char *rhs) { OctetStr to( rhs); if ( lhs.left_comparison( to.smival.value.string.len,to)>0) return true; else return false; }
//===============[ less than <= operator overloaded ]================= bool operator<=( const OctetStr &lhs,char *rhs) { OctetStr to( rhs); if (( lhs.left_comparison( to.smival.value.string.len,to)<0) || ( lhs.left_comparison( to.smival.value.string.len,to)==0)) return true; else return false; }
int getapp::run() { //----------[ create a ASNMP session ]----------------------------------- if ( snmp_.valid() != SNMP_CLASS_SUCCESS) { cout << "\nASNMP:ERROR:Create session failed: "<< snmp_.error_string()<< "\n"; return 1; } //--------[ build up ASNMP object needed ]------------------------------- if (address_.get_port() == 0) address_.set_port(DEF_AGENT_PORT); target_.set_address( address_); // make a target using the address //-------[ issue the request, blocked mode ]----------------------------- cout << "\nASNMP:INFO:SNMP Version " << (target_.get_version()+ 1) << \ " GET SAMPLE PROGRAM \nOID: " << oid_.to_string() << "\n"; target_.get_address(address_); // target updates port used int rc; const char *name = address_.resolve_hostname(rc); cout << "Device: " << address_ << " "; //FUZZ: disable check_for_lack_ACE_OS cout << (rc ? "<< did not resolve via gethostbyname() >>" : name) << "\n"; //FUZZ: enable check_for_lack_ACE_OS cout << "[ Retries=" << target_.get_retry() << " \ Timeout=" << target_.get_timeout() <<" ms " << "Community=" << \ community_.to_string() << " ]"<< endl; if (snmp_.get( pdu_, target_) == SNMP_CLASS_SUCCESS) { Vb vb; // check to see if there are any errors if (pdu_.get_error_status()) { cout << "ERROR: agent replied as follows\n"; cout << pdu_.agent_error_reason() << endl; } else { VbIter iter(pdu_); while (iter.next(vb)) { cout << "\tOid = " << vb.to_string_oid() << "\n"; cout << "\tValue = " << vb.to_string_value() << "\n"; } } } else { const char *ptr = snmp_.error_string(); cout << "ASNMP:ERROR: get command failed reason: " << ptr << endl; } cout << "\nASNMP:INFO: command completed normally.\n"<< endl; return 0; }
// Initialize the v3MP. v3MP::v3MP(const OctetStr& snmpEngineID, unsigned int engineBoots, int &construct_status) : own_engine_id(0), usm(0) { if (I) { debugprintf(0, "v3MP: You must not create two objects of this class!"); construct_status = SNMPv3_MP_ERROR; return; } I = this; snmpUnknownSecurityModels = 0; snmpInvalidMsgs = 0; snmpUnknownPDUHandlers = 0; int length = snmpEngineID.len(); if (length > MAXLENGTH_ENGINEID) length = MAXLENGTH_ENGINEID; own_engine_id = v3strcpy(snmpEngineID.data(), length); own_engine_id_len = length; own_engine_id_oct = snmpEngineID; int result; usm = new USM(engineBoots, snmpEngineID, this, &cur_msg_id, result); if (cur_msg_id >= MAX_MPMSGID) cur_msg_id = 1; if ((!own_engine_id) || (!usm) || (result != SNMPv3_USM_OK)) { construct_status = SNMPv3_MP_ERROR; return; } cache.set_usm(usm); construct_status = SNMPv3_MP_OK; }
int walkapp::run() { //----------[ create a ASNMP session ]----------------------------------- if ( snmp_.valid() != SNMP_CLASS_SUCCESS) { cout << "\nASNMP:ERROR:Create session failed: "<< snmp_.error_string()<< "\n"; return 1; } //--------[ build up ASNMP object needed ]------------------------------- if (address_.get_port() == 0) address_.set_port(DEF_AGENT_PORT); target_.set_address( address_); // make a target using the address //-------[ issue the request, blocked mode ]----------------------------- cout << "\nASNMP:INFO:SNMP Version " << (target_.get_version()+ 1) << \ " WALK SAMPLE PROGRAM \nOID: " << oid_.to_string() << "\n"; target_.get_address(address_); // target updates port used int rc; const char *name = address_.resolve_hostname(rc); cout << "Device: " << address_ << " "; //FUZZ: disable check_for_lack_ACE_OS cout << (rc ? "<< did not resolve via gethostbyname() >>" : name) << "\n"; //FUZZ: enable check_for_lack_ACE_OS cout << "[ Retries=" << target_.get_retry() << " \ Timeout=" << target_.get_timeout() <<" ms " << "Community=" << \ community_.to_string() << " ]"<< endl; MibIter iter(&snmp_, pdu_, &target_); char *err_str = 0; Vb vb; unsigned ctr = 0; while (iter.next(vb, err_str)) { cout << "\tOid = " << vb.to_string_oid() << "\n"; cout << "\tValue = " << vb.to_string_value() << "\n"; ctr++; } if (!err_str) { cout << "ERROR: walk: " << err_str << endl; return 0; } cout << "ASNMP:INFO:command completed normally. ACE Rocks...\n"<< endl; return 0; }
///////////////////////////////////////////////////////////////////////////// // 函数:InitUTarget // // 说明:当SNMP版本是3时,初始化Utarget // // 参数: // // 无 // // 返回: // // 成功返回0,否则返回1 // ///////////////////////////////////////////////////////////////////////////// int BasicSNMP::InitUTarget() { int nResult = 0; utarget = address;//construct UTarger By address Class utarget.set_version(version); // set the SNMP version SNMPV1 or V2 or V3 utarget.set_retry(retries); // set the number of auto retries utarget.set_timeout(timeout); // set timeout utarget.set_security_model(m_nSecurityModel);//Set Security Model utarget.set_security_name( securityName);//Set Security Name (Auth Name) OctetStr EgID;//Engine ID //Get Engine ID nResult = pSnmp->unicast_discovery(EgID, (timeout + 99) / 100, address, version, &community); if(EgID.len()>0) {//Engine ID Length Big Than 0 utarget.set_engine_id(EgID);//Set Engine ID } else {//Less Than 0 return 1;//return Failed } return 0;//retrun Successed }
int getapp::run() { //----------[ create a ASNMP session ]----------------------------------- if ( snmp_.valid() != SNMP_CLASS_SUCCESS) { cout << "\nASNMP:ERROR:Create session failed: "<< snmp_.error_string()<< "\n"; return 1; } //--------[ build up ASNMP object needed ]------------------------------- if (address_.get_port() == 0) address_.set_port(DEF_AGENT_PORT); target_.set_address( address_); // make a target using the address //-------[ issue the request, blocked mode ]----------------------------- cout << "\nASNMP:INFO:SNMP Version " << (target_.get_version()+ 1) << \ " GET SAMPLE PROGRAM \nOID: " << oid_.to_string() << "\n"; target_.get_address(address_); // target updates port used int rc; const char *name = address_.resolve_hostname(rc); cout << "Device: " << address_ << " "; //FUZZ: disable check_for_lack_ACE_OS cout << (rc ? "<< did not resolve via gethostbyname() >>" : name) << "\n"; //FUZZ: enable check_for_lack_ACE_OS cout << "[ Retries=" << target_.get_retry() << " \ Timeout=" << target_.get_timeout() <<" ms " << "Community=" << \ community_.to_string() << " ]"<< endl; if (snmp_.get( pdu_, target_, this) != SNMP_CLASS_SUCCESS) { const char *ptr = snmp_.error_string(); cout << "ASNMP:ERROR: get command failed reason: " << ptr << endl; } else { ACE_Reactor::instance()->run_reactor_event_loop(); } return 0; }
// Send a report message. int v3MP::send_report(unsigned char* scopedPDU, int scopedPDULength, struct snmp_pdu *pdu, int errorCode, int sLevel, int sModel, OctetStr &sName, UdpAddress &destination, Snmp *snmp_session) { debugprintf(2, "v3MP::send_report: Sending report message."); unsigned char *data; int dataLength; int pdu_type = 0; unsigned char cEngineID[MAXLENGTH_ENGINEID+1]; unsigned char cName[MAXLENGTH_CONTEXT_NAME+1]; int cEngineIDLength = MAXLENGTH_ENGINEID+1; int cNameLength = MAXLENGTH_CONTEXT_NAME+1; debugprintf(2, "v3MP::send_report: securityLevel %d",sLevel); if (scopedPDULength != MAX_SNMP_PACKET) { // try to get scopedPDU and PDU data = asn1_parse_scoped_pdu(scopedPDU, &scopedPDULength, cEngineID, &cEngineIDLength, cName, &cNameLength); if (data == NULL) { debugprintf(1, "mp: Error while trying to parse scopedPDU!"); cEngineID[0] = '\0'; cEngineIDLength = 0; cName[0] = '\0'; cNameLength = 0; // Dont send encrypted report if decryption failed: //if (sLevel == SNMP_SECURITY_LEVEL_AUTH_PRIV) // sLevel = SNMP_SECURITY_LEVEL_AUTH_NOPRIV; } else { // data != NULL dataLength = scopedPDULength; // parse data of scopedPDU snmp_parse_data_pdu(pdu, data, dataLength); pdu_type = pdu->command; if (!data) { debugprintf(0, "mp: Error while trying to parse PDU!"); } } // end of: if (data == NULL) } // end if (scopedPDULength != MAX_SNMP_PACKET) else { // scopedPDULength == MAX_SNMP_PACKET cEngineID[0] = '\0'; cEngineIDLength = 0; cName[0] = '\0'; cNameLength = 0; pdu->reqid = 0; } clear_pdu(pdu); // Clear pdu and free all content debugprintf(4, "pdu->reqid = %ld",pdu->reqid); pdu->errstat = 0; pdu->errindex = 0; pdu->command = REPORT_MSG; Vb counterVb; Oid counterOid; SmiLPOID smioid; SmiVALUE smival; switch (errorCode) { case SNMPv3_MP_INVALID_MESSAGE: case SNMPv3_USM_PARSE_ERROR: { counterVb.set_oid(oidSnmpInvalidMsgs); counterVb.set_value(Counter32(get_stats_invalid_msgs())); break; } case SNMPv3_USM_NOT_IN_TIME_WINDOW: case SNMPv3_MP_NOT_IN_TIME_WINDOW: { counterVb.set_oid(oidUsmStatsNotInTimeWindows); counterVb.set_value(Counter32(usm->get_stats_not_in_time_windows())); break; } case SNMPv3_USM_DECRYPTION_ERROR: { counterVb.set_oid(oidUsmStatsDecryptionErrors); counterVb.set_value(Counter32(usm->get_stats_decryption_errors())); //sLevel = SNMP_SECURITY_LEVEL_NOAUTH_NOPRIV; break; } case SNMPv3_USM_AUTHENTICATION_ERROR: case SNMPv3_USM_AUTHENTICATION_FAILURE: { counterVb.set_oid(oidUsmStatsWrongDigests); counterVb.set_value(Counter32(usm->get_stats_wrong_digests())); //sLevel = SNMP_SECURITY_LEVEL_NOAUTH_NOPRIV; break; } case SNMPv3_USM_UNKNOWN_ENGINEID: case SNMPv3_MP_INVALID_ENGINEID: { //sLevel = SNMP_SECURITY_LEVEL_NOAUTH_NOPRIV; counterVb.set_oid(oidUsmStatsUnknownEngineIDs); counterVb.set_value(Counter32(usm->get_stats_unknown_engine_ids())); break; } case SNMPv3_MP_UNSUPPORTED_SECURITY_MODEL: { counterVb.set_oid(oidSnmpUnknownSecurityModels); counterVb.set_value(Counter32(get_stats_unknown_security_models())); sModel = SNMP_SECURITY_MODEL_USM; sLevel = SNMP_SECURITY_LEVEL_NOAUTH_NOPRIV; break; } case SNMPv3_USM_UNKNOWN_SECURITY_NAME: { counterVb.set_oid(oidUsmStatsUnknownUserNames); counterVb.set_value(Counter32(usm->get_stats_unknown_user_names())); sLevel = SNMP_SECURITY_LEVEL_NOAUTH_NOPRIV; debugprintf(2, "Report: SecurityName: %s",sName.get_printable()); break; } case SNMPv3_USM_UNSUPPORTED_SECURITY_LEVEL: { counterVb.set_oid(oidUsmStatsUnsupportedSecLevels); counterVb.set_value(Counter32(usm->get_stats_unsupported_sec_levels())); sLevel = SNMP_SECURITY_LEVEL_NOAUTH_NOPRIV; break; } default: { counterVb.set_oid(oidSnmpInvalidMsgs); counterVb.set_value(Counter32(get_stats_invalid_msgs())); sModel = SNMP_SECURITY_MODEL_USM; sLevel = SNMP_SECURITY_LEVEL_NOAUTH_NOPRIV; sName.set_data(0, 0); debugprintf(2, "ErrorCode was %i in snmp_parse", errorCode); } } // end switch counterVb.get_oid(counterOid); smioid = counterOid.oidval(); int status = convertVbToSmival(counterVb, &smival); if (status != SNMP_CLASS_SUCCESS) { return SNMPv3_MP_ERROR; } snmp_add_var(pdu, smioid->ptr, (int) smioid->len, &smival); freeSmivalDescriptor(&smival); Buffer<unsigned char> sendbuffer(MAX_SNMP_PACKET); int sendbufferlen= MAX_SNMP_PACKET; status = snmp_build( pdu, sendbuffer.get_ptr(), &sendbufferlen, own_engine_id_oct, sName, sModel, sLevel, OctetStr(cEngineID, cEngineIDLength), OctetStr(cName, cNameLength)); if (status != SNMPv3_MP_OK) { debugprintf(2, "v3MP::send_report: error serializing message (mpSnmpBuild returns: %i).", status); return SNMPv3_MP_ERROR; } SnmpSocket send_fd = INVALID_SOCKET; if (pdu_type == sNMP_PDU_INFORM) { debugprintf(4, "Received a snmpInform pdu."); if (snmp_session->get_eventListHolder()->notifyEventList()) send_fd = snmp_session->get_eventListHolder()->notifyEventList()->get_notify_fd(); } status = snmp_session->send_raw_data(sendbuffer.get_ptr(), (size_t)sendbufferlen,// pdu to send destination, // target address send_fd); // the fd to use if ( status != 0) { debugprintf(1, "v3MP::send_report: error sending message (%i)", status); return SNMPv3_MP_ERROR; } debugprintf(3, "v3MP::send_report: Report sent."); return SNMPv3_MP_OK; }
//------------[ convert SNMP++ VB to WinSNMP smiVALUE ]---------------- int convertVbToSmival( const Vb &tempvb, SmiVALUE *smival ) { smival->syntax = tempvb.get_syntax(); switch ( smival->syntax ) { // case sNMP_SYNTAX_NULL case sNMP_SYNTAX_NULL: case sNMP_SYNTAX_NOSUCHOBJECT: case sNMP_SYNTAX_NOSUCHINSTANCE: case sNMP_SYNTAX_ENDOFMIBVIEW: break; // case sNMP_SYNTAX_INT32: case sNMP_SYNTAX_INT: tempvb.get_value(smival->value.sNumber); break; // case sNMP_SYNTAX_UINT32: case sNMP_SYNTAX_GAUGE32: case sNMP_SYNTAX_CNTR32: case sNMP_SYNTAX_TIMETICKS: // case sNMP_SYNTAX_UINT32: tempvb.get_value(smival->value.uNumber); break; // case Counter64 case sNMP_SYNTAX_CNTR64: { Counter64 c64; tempvb.get_value(c64); smival->value.hNumber.hipart = c64.high(); smival->value.hNumber.lopart = c64.low(); } break; case sNMP_SYNTAX_BITS: case sNMP_SYNTAX_OCTETS: case sNMP_SYNTAX_OPAQUE: case sNMP_SYNTAX_IPADDR: { OctetStr os; tempvb.get_value(os); smival->value.string.ptr = NULL; smival->value.string.len = os.len(); if ( smival->value.string.len > 0 ) { smival->value.string.ptr = (SmiLPBYTE) new unsigned char [smival->value.string.len]; if ( smival->value.string.ptr ) { for (int i=0; i<(int) smival->value.string.len ; i++) smival->value.string.ptr[i] = os[i]; } else { smival->syntax = sNMP_SYNTAX_NULL; // invalidate the smival return SNMP_CLASS_RESOURCE_UNAVAIL; } } } break; case sNMP_SYNTAX_OID: { Oid oid; tempvb.get_value(oid); smival->value.oid.ptr = NULL; smival->value.oid.len = oid.len(); if ( smival->value.oid.len > 0 ) { smival->value.oid.ptr = (SmiLPUINT32) new unsigned long [ smival->value.oid.len]; if ( smival->value.oid.ptr ) { for (int i=0; i<(int)smival->value.oid.len ; i++) smival->value.oid.ptr[i] = oid[i]; } else { smival->syntax = sNMP_SYNTAX_NULL; // invalidate the smival return SNMP_CLASS_RESOURCE_UNAVAIL; } } } break; default: return SNMP_CLASS_INTERNAL_ERROR; } return SNMP_CLASS_SUCCESS; }
// Read the bootCounter of the given engineID stored in the given file. int getBootCounter(const char *fileName, const OctetStr &engineId, unsigned int &boot) { char line[MAX_LINE_LEN]; char encoded[MAXLENGTH_ENGINEID * 2 + 2]; int len = engineId.len(); FILE *file; boot = 0; file = fopen(fileName, "r"); if (!file) { LOG_BEGIN(ERROR_LOG | 1); LOG("getBootCounter: Could not open (file)"); LOG(fileName); LOG_END; return SNMPv3_FILEOPEN_ERROR; } if (len > MAXLENGTH_ENGINEID) { LOG_BEGIN(ERROR_LOG | 3); LOG("getBootCounter: engine id too long, ignoring last bytes (len) (max)"); LOG(len); LOG(MAXLENGTH_ENGINEID); LOG_END; len = MAXLENGTH_ENGINEID; } encodeString(engineId.data(), len, encoded); encoded[2*len]=' '; encoded[2*len + 1] = 0; while (fgets(line, MAX_LINE_LEN, file)) { line[MAX_LINE_LEN - 1] = 0; /* ignore comments */ if (line[0]=='#') continue; if (!strncmp(encoded, line, len*2 + 1)) { /* line starts with engineId */ char* ptr = line; /* skip until first space */ while (*ptr != 0 && *ptr != ' ') ptr++; if (*ptr == 0) { fclose(file); LOG_BEGIN(ERROR_LOG | 3); LOG("getBootCounter: Illegal line: (file) (line)"); LOG(fileName); LOG(line); LOG_END; return SNMPv3_FILE_ERROR; } boot = atoi(ptr); fclose(file); LOG_BEGIN(DEBUG_LOG | 3); LOG("getBootCounter: found entry (file) (engine id) (boot counter)"); LOG(fileName); LOG(engineId.get_printable()); LOG(boot); LOG_END; return SNMPv3_OK; } } fclose(file); LOG_BEGIN(WARNING_LOG | 3); LOG("getBootCounter: No entry found (file) (engine id)"); LOG(fileName); LOG(engineId.get_printable()); LOG_END; return SNMPv3_NO_ENTRY_ERROR; }
// Store the bootCounter of the given engineID in the given file. int saveBootCounter(const char *fileName, const OctetStr &engineId, const unsigned int boot) { char line[MAX_LINE_LEN]; char tmpFileName[MAXLENGTH_FILENAME]; char encoded[MAXLENGTH_ENGINEID * 2 + 2]; int found = FALSE; int len = engineId.len(); FILE *file_in, *file_out; tmpFileName[0] = 0; sprintf(tmpFileName, "%s.tmp",fileName); if (len > MAXLENGTH_ENGINEID) { LOG_BEGIN(ERROR_LOG | 3); LOG("saveBootCounter: engine id too long, ignoring last bytes (len) (max)"); LOG(len); LOG(MAXLENGTH_ENGINEID); LOG_END; len = MAXLENGTH_ENGINEID; } file_in = fopen(fileName, "r"); if (!file_in) { file_in = fopen(fileName, "w"); if (!file_in) { LOG_BEGIN(ERROR_LOG | 3); LOG("saveBootCounter: could not create new file (file)"); LOG(fileName); LOG_END; return SNMPv3_FILECREATE_ERROR; } LOG_BEGIN(INFO_LOG | 3); LOG("saveBootCounter: created new file (file)"); LOG(fileName); LOG_END; fputs("# \n",file_in); fputs("# This file was created by an SNMP++v3 application,\n", file_in); fputs("# it is used to store the snmpEngineBoots counters.\n", file_in); fputs("# \n",file_in); fputs("# Lines starting with '#' are comments.\n", file_in); fputs("# The snmpEngineBoots counters are stored as\n", file_in); fputs("# <encoded snmpEngineId> <bootCounter>\n", file_in); fputs("# \n", file_in); fclose(file_in); file_in = fopen(fileName, "r"); } file_out = fopen(tmpFileName, "w"); if ((file_in) && (file_out)) { encodeString(engineId.data(), len, encoded); encoded[len*2] = ' '; encoded[len*2 + 1] = 0; while (fgets(line, MAX_LINE_LEN, file_in)) { line[MAX_LINE_LEN - 1] = 0; if (!strncmp(encoded, line, len*2 + 1)) { if (found) { LOG_BEGIN(WARNING_LOG | 3); LOG("saveBootCounter: Removing doubled entry (file) (line)"); LOG(fileName); LOG(line); LOG_END; continue; } sprintf(line,"%s%i\n", encoded, boot); fputs(line, file_out); found = TRUE; continue; } fputs(line, file_out); } if (!found) { sprintf(line, "%s%i\n", encoded, boot); fputs(line, file_out); } fclose(file_in); fclose(file_out); #ifdef WIN32 _unlink(fileName); #endif if (rename(tmpFileName, fileName)) { LOG_BEGIN(ERROR_LOG | 1); LOG("saveBootCounter: Failed to rename temporary file (tmp file) (file)"); LOG(tmpFileName); LOG(fileName); LOG_END; return SNMPv3_FILERENAME_ERROR; } LOG_BEGIN(INFO_LOG | 5); LOG("saveBootCounter: Saved counter (file) (engine id) (boot)"); LOG(fileName); LOG(engineId.get_printable()); LOG(boot); LOG_END; return SNMPv3_OK; } LOG_BEGIN(ERROR_LOG | 1); LOG("saveBootCounter: Failed to open both files (file) (tmp file)"); LOG(fileName); LOG(tmpFileName); LOG_END; return SNMPv3_FILEOPEN_ERROR; }
int CNotifyEventQueue::AddEntry(Snmp *snmp, const OidCollection &trapids, const TargetCollection &targets) { SnmpSynchronize _synchronize(*this); // instead of REENTRANT() if (snmp != m_snmpSession) { debugprintf(0, "WARNING: Adding notification event for other Snmp object"); } if (!m_msgCount) { m_notify_addr = snmp->get_listen_address(); m_notify_addr.set_port(m_listen_port); int status = SNMP_CLASS_SUCCESS; // This is the first request to receive notifications // Set up the socket for the snmp trap port (162) or the // specified port through set_listen_port() bool is_v4_address = (m_notify_addr.get_ip_version() == Address::version_ipv4); if (is_v4_address) { struct sockaddr_in mgr_addr; // open a socket to be used for the session if ((m_notify_fd = socket(AF_INET, SOCK_DGRAM,0)) < 0) { #ifdef WIN32 int werr = WSAGetLastError(); if (EMFILE == werr ||WSAENOBUFS == werr || ENFILE == werr) status = SNMP_CLASS_RESOURCE_UNAVAIL; else if (WSAEHOSTDOWN == werr) status = SNMP_CLASS_TL_FAILED; else status = SNMP_CLASS_TL_UNSUPPORTED; #else if (EMFILE == errno || ENOBUFS == errno || ENFILE == errno) status = SNMP_CLASS_RESOURCE_UNAVAIL; else if (EHOSTDOWN == errno) status = SNMP_CLASS_TL_FAILED; else status = SNMP_CLASS_TL_UNSUPPORTED; #endif cleanup(); return status; } // set up the manager socket attributes unsigned long inaddr = inet_addr(IpAddress(m_notify_addr).get_printable()); memset(&mgr_addr, 0, sizeof(mgr_addr)); mgr_addr.sin_family = AF_INET; mgr_addr.sin_addr.s_addr = inaddr; // was htonl( INADDR_ANY); mgr_addr.sin_port = htons(m_notify_addr.get_port()); #ifdef CYGPKG_NET_OPENBSD_STACK mgr_addr.sin_len = sizeof(mgr_addr); #endif // bind the socket if (bind(m_notify_fd, (struct sockaddr *) &mgr_addr, sizeof(mgr_addr)) < 0) { #ifdef WIN32 int werr = WSAGetLastError(); if (WSAEADDRINUSE == werr) status = SNMP_CLASS_TL_IN_USE; else if (WSAENOBUFS == werr) status = SNMP_CLASS_RESOURCE_UNAVAIL; else if (werr == WSAEAFNOSUPPORT) status = SNMP_CLASS_TL_UNSUPPORTED; else if (werr == WSAENETUNREACH) status = SNMP_CLASS_TL_FAILED; else if (werr == EACCES) status = SNMP_CLASS_TL_ACCESS_DENIED; else status = SNMP_CLASS_INTERNAL_ERROR; #else if (EADDRINUSE == errno) status = SNMP_CLASS_TL_IN_USE; else if (ENOBUFS == errno) status = SNMP_CLASS_RESOURCE_UNAVAIL; else if (errno == EAFNOSUPPORT) status = SNMP_CLASS_TL_UNSUPPORTED; else if (errno == ENETUNREACH) status = SNMP_CLASS_TL_FAILED; else if (errno == EACCES) status = SNMP_CLASS_TL_ACCESS_DENIED; else { debugprintf(0, "Uncatched errno value %d, returning internal error.", errno); status = SNMP_CLASS_INTERNAL_ERROR; } #endif debugprintf(0, "Fatal: could not bind to %s", m_notify_addr.get_printable()); cleanup(); return status; } debugprintf(3, "Bind to %s for notifications, fd %d.", m_notify_addr.get_printable(), m_notify_fd); } // is_v4_address else { // not is_v4_address #ifdef SNMP_PP_IPv6 // open a socket to be used for the session if ((m_notify_fd = socket(AF_INET6, SOCK_DGRAM,0)) < 0) { #ifdef WIN32 int werr = WSAGetLastError(); if (EMFILE == werr ||WSAENOBUFS == werr || ENFILE == werr) status = SNMP_CLASS_RESOURCE_UNAVAIL; else if (WSAEHOSTDOWN == werr) status = SNMP_CLASS_TL_FAILED; else status = SNMP_CLASS_TL_UNSUPPORTED; #else if (EMFILE == errno || ENOBUFS == errno || ENFILE == errno) status = SNMP_CLASS_RESOURCE_UNAVAIL; else if (EHOSTDOWN == errno) status = SNMP_CLASS_TL_FAILED; else status = SNMP_CLASS_TL_UNSUPPORTED; #endif cleanup(); return status; } #ifdef NOTIFY_SET_IPV6_V6ONLY int on = 1; if (setsockopt(m_notify_fd, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&on, sizeof(on)) == -1) { LOG_BEGIN(loggerModuleName, WARNING_LOG | 1); LOG("Could not set option IPV6_V6ONLY on notify socket (errno)"); LOG(errno); LOG_END; } else { LOG_BEGIN(loggerModuleName, INFO_LOG | 3); LOG("Have set IPV6_V6ONLY option on notify socket"); LOG_END; } #endif // set up the manager socket attributes struct sockaddr_in6 mgr_addr; memset(&mgr_addr, 0, sizeof(mgr_addr)); unsigned int scope = 0; OctetStr addrstr = ((IpAddress &)m_notify_addr).IpAddress::get_printable(); if (m_notify_addr.has_ipv6_scope()) { scope = m_notify_addr.get_scope(); int y = addrstr.len() - 1; while ((y>0) && (addrstr[y] != '%')) { addrstr.set_len(addrstr.len() - 1); y--; } if (addrstr[y] == '%') addrstr.set_len(addrstr.len() - 1); } if (inet_pton(AF_INET6, addrstr.get_printable(), &mgr_addr.sin6_addr) < 0) { LOG_BEGIN(loggerModuleName, ERROR_LOG | 1); LOG("Notify transport: inet_pton returns (errno) (str)"); LOG(errno); LOG(strerror(errno)); LOG_END; cleanup(); return SNMP_CLASS_INVALID_ADDRESS; } mgr_addr.sin6_family = AF_INET6; mgr_addr.sin6_port = htons(m_notify_addr.get_port()); mgr_addr.sin6_scope_id = scope; // bind the socket if (bind(m_notify_fd, (struct sockaddr *) &mgr_addr, sizeof(mgr_addr)) < 0) { #ifdef WIN32 int werr = WSAGetLastError(); if (WSAEADDRINUSE == werr) status = SNMP_CLASS_TL_IN_USE; else if (WSAENOBUFS == werr) status = SNMP_CLASS_RESOURCE_UNAVAIL; else if (werr == WSAEAFNOSUPPORT) status = SNMP_CLASS_TL_UNSUPPORTED; else if (werr == WSAENETUNREACH) status = SNMP_CLASS_TL_FAILED; else if (werr == EACCES) status = SNMP_CLASS_TL_ACCESS_DENIED; else status = SNMP_CLASS_INTERNAL_ERROR; #else if (EADDRINUSE == errno) status = SNMP_CLASS_TL_IN_USE; else if (ENOBUFS == errno) status = SNMP_CLASS_RESOURCE_UNAVAIL; else if (errno == EAFNOSUPPORT) status = SNMP_CLASS_TL_UNSUPPORTED; else if (errno == ENETUNREACH) status = SNMP_CLASS_TL_FAILED; else if (errno == EACCES) status = SNMP_CLASS_TL_ACCESS_DENIED; else { debugprintf(0, "Uncatched errno value %d, returning internal error.", errno); status = SNMP_CLASS_INTERNAL_ERROR; } #endif debugprintf(0, "Fatal: could not bind to %s", m_notify_addr.get_printable()); cleanup(); return status; } debugprintf(3, "Bind to %s for notifications, fd %d.", m_notify_addr.get_printable(), m_notify_fd); #else debugprintf(0, "User error: Enable IPv6 and recompile snmp++."); cleanup(); return SNMP_CLASS_TL_UNSUPPORTED; #endif } // not is_v4_address } CNotifyEvent *newEvent = new CNotifyEvent(snmp, trapids, targets); /*---------------------------------------------------------*/ /* Insert entry at head of list, done automagically by the */ /* constructor function, so don't use the return value. */ /*---------------------------------------------------------*/ (void) new CNotifyEventQueueElt(newEvent, m_head.GetNext(), &m_head); m_msgCount++; return SNMP_CLASS_SUCCESS; }
//===============[ greater than >= overloaded ]======================= int operator>=(const OctetStr &lhs, const OctetStr &rhs) { int maxlen = lhs.smival.value.string.len > rhs.smival.value.string.len ? lhs.smival.value.string.len : rhs.smival.value.string.len; return (lhs.nCompare(maxlen, rhs) >=0); }
//==============[ not equivlence operator overloaded ]================ int operator!=(const OctetStr &lhs, const OctetStr &rhs) { if (lhs.smival.value.string.len != rhs.smival.value.string.len) return true; return (lhs.nCompare(rhs.smival.value.string.len, rhs) != 0); }
int wpdu::convert_vb_to_smival( Vb &tempvb, SmiVALUE *smival ) { smival->syntax = tempvb.get_syntax(); switch ( smival->syntax ) { case sNMP_SYNTAX_NULL: break; // case sNMP_SYNTAX_INT32: case sNMP_SYNTAX_INT: { SnmpInt32 tmp; tempvb.get_value(tmp); smival->value.sNumber = tmp; } break; // case sNMP_SYNTAX_UINT32: case sNMP_SYNTAX_GAUGE32: case sNMP_SYNTAX_CNTR32: case sNMP_SYNTAX_TIMETICKS: { SnmpUInt32 tmp; tempvb.get_value(tmp); smival->value.uNumber = tmp; } break; // case Counter64 case sNMP_SYNTAX_CNTR64: { Counter64 c64; tempvb.get_value(c64); smival->value.hNumber.hipart = c64.high(); smival->value.hNumber.lopart = c64.low(); } break; // OID syntax case sNMP_SYNTAX_OID: { Oid tmpoid; tmpoid.oidval(); tempvb.get_value(tmpoid); SmiLPOID smi = tmpoid.oidval(); smival->value.oid.len = tmpoid.length(); ACE_NEW_RETURN(smival->value.oid.ptr, SmiUINT32 [smival->value.oid.len], 1); ACE_OS::memcpy(smival->value.oid.ptr, smi->ptr, smival->value.oid.len *sizeof(SmiUINT32)); } break; case sNMP_SYNTAX_BITS: case sNMP_SYNTAX_OCTETS: case sNMP_SYNTAX_IPADDR: { OctetStr os; tempvb.get_value(os); smival->value.string.ptr = 0; smival->value.string.len = os.length(); if ( smival->value.string.len > 0 ) { ACE_NEW_RETURN(smival->value.string.ptr, SmiBYTE [smival->value.string.len], 1); if ( smival->value.string.ptr ) { for (int i=0; i<(int) smival->value.string.len ; i++) smival->value.string.ptr[i] = os[i]; } else { smival->syntax = sNMP_SYNTAX_NULL; // invalidate the smival return SNMP_CLASS_RESOURCE_UNAVAIL; } } } break; default: ACE_DEBUG((LM_DEBUG, "wpdu::convert_vb_to_smival did not convert vb\n")); // ACE_ASSERT(0); } // switch return 0; }
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; }
// Add an entry to the table. int v3MP::EngineIdTable::add_entry(const OctetStr &engine_id, const OctetStr &host, int port) { if (!table) return SNMPv3_MP_NOT_INITIALIZED; LOG_BEGIN(loggerModuleName, INFO_LOG | 9); LOG("v3MP::EngineIdTable: adding new entry (id) (host) (port)"); LOG(engine_id.get_printable()); LOG(host.get_printable()); LOG(port); LOG_END; BEGIN_REENTRANT_CODE_BLOCK; for (int i = 0; i < entries; i++) if (((table[i].port == port) && (table[i].host == host)) || (table[i].engine_id == engine_id)) { LOG_BEGIN(loggerModuleName, INFO_LOG | 2); LOG("v3MP::EngineIdTable: replace entry (old id) (old host) (old port) (id) (host) (port)"); LOG(table[i].engine_id.get_printable()); LOG(table[i].host.get_printable()); LOG(table[i].port); LOG(engine_id.get_printable()); LOG(host.get_printable()); LOG(port); LOG_END; table[i].engine_id = engine_id; table[i].host = host; table[i].port = port; return SNMPv3_MP_OK; // host is in table } table[entries].engine_id = engine_id; table[entries].host = host; table[entries].port = port; entries++; if (entries == max_entries) { // resize Table struct Entry_T *tmp; tmp = new struct Entry_T[2 * max_entries]; if (!tmp) { entries--; return SNMPv3_MP_ERROR; } for (int i = 0; i < entries; i++) tmp[i] = table[i]; delete [] table; table = tmp; max_entries *= 2; } return SNMPv3_MP_OK; }
// Parse the given buffer as a SNMPv3-Message. int v3MP::snmp_parse(Snmp *snmp_session, struct snmp_pdu *pdu, unsigned char *inBuf, int inBufLength, OctetStr &securityEngineID, OctetStr &securityName, OctetStr &contextEngineID, OctetStr &contextName, long &securityLevel, long &msgSecurityModel, snmp_version &spp_version, UdpAddress from_address) { debugprintf(3, "mp is parsing incoming message:"); debughexprintf(25, inBuf, inBufLength); if (inBufLength > MAX_SNMP_PACKET) return SNMPv3_MP_ERROR; unsigned char type; long version; int origLength = inBufLength; unsigned char *inBufPtr = inBuf; long msgID, msgMaxSize; unsigned char msgFlags; Buffer<unsigned char> msgSecurityParameters(MAX_SNMP_PACKET); Buffer<unsigned char> msgData(MAX_SNMP_PACKET); int msgSecurityParametersLength = inBufLength, msgDataLength = inBufLength; Buffer<unsigned char> scopedPDU(MAX_SNMP_PACKET); int scopedPDULength = MAX_SNMP_PACKET; long maxSizeResponseScopedPDU = 0; struct SecurityStateReference *securityStateReference = NULL; int securityParametersPosition; int rc; int errorCode = 0; // get the type inBuf = asn_parse_header( inBuf, &inBufLength, &type); if (inBuf == NULL){ debugprintf(0, "snmp_parse: bad header"); return SNMPv3_MP_PARSE_ERROR; } if (type != (ASN_SEQ_CON)){ debugprintf(0, "snmp_parse: wrong auth header type"); return SNMPv3_MP_PARSE_ERROR; } if (origLength != inBufLength + (inBuf - inBufPtr)) { debugprintf(0, "snmp_parse: wrong length of received packet"); return SNMPv3_MP_PARSE_ERROR; } // get the version inBuf = asn_parse_int(inBuf, &inBufLength, &type, &version); if (inBuf == NULL){ debugprintf(0, "snmp_parse: bad parse of version"); return SNMPv3_MP_PARSE_ERROR; } debugprintf(3, "Parsed length(%x), version(0x%lx)", inBufLength, version); if ( version != SNMP_VERSION_3 ) return SNMPv3_MP_PARSE_ERROR; spp_version = (snmp_version) version; inBuf = asn1_parse_header_data(inBuf, &inBufLength, &msgID, &msgMaxSize, &msgFlags, &msgSecurityModel); if (inBuf == NULL){ debugprintf(0, "snmp_parse: bad parse of msgHeaderData"); return SNMPv3_MP_PARSE_ERROR; } pdu->msgid = msgID; if ((msgMaxSize < 484) || (msgMaxSize > 0x7FFFFFFF)) { debugprintf(0, "snmp_parse: bad parse of msgMaxSize"); return SNMPv3_MP_PARSE_ERROR; } // do not allow larger messages than this entity can handle if (msgMaxSize > MAX_SNMP_PACKET) msgMaxSize = MAX_SNMP_PACKET; pdu->maxsize_scopedpdu = msgMaxSize; inBuf = asn_parse_string( inBuf, &inBufLength, &type, msgSecurityParameters.get_ptr(), &msgSecurityParametersLength); if (inBuf == NULL){ debugprintf(0, "snmp_parse: bad parse of msgSecurityParameters"); return SNMPv3_MP_PARSE_ERROR; } securityParametersPosition= SAFE_INT_CAST(inBuf - inBufPtr) - msgSecurityParametersLength; // the rest of the message is passed directly to the security module msgDataLength = origLength - SAFE_INT_CAST(inBuf - inBufPtr); memcpy(msgData.get_ptr(), inBuf, msgDataLength); debugprintf(3, "Parsed msgdata length(0x%x), " "msgSecurityParameters length(0x%x)", msgDataLength, msgSecurityParametersLength); switch (msgFlags & 0x03) { case 3: { securityLevel = SNMP_SECURITY_LEVEL_AUTH_PRIV; break;} case 0: { securityLevel = SNMP_SECURITY_LEVEL_NOAUTH_NOPRIV; break;} case 1: { securityLevel = SNMP_SECURITY_LEVEL_AUTH_NOPRIV; break;} default: { securityLevel = SNMP_SECURITY_LEVEL_NOAUTH_NOPRIV; snmpInvalidMsgs++; // do not send back report return SNMPv3_MP_INVALID_MESSAGE; break; } } bool reportableFlag; if (msgFlags & 0x04) reportableFlag = true; else reportableFlag = false; securityStateReference = usm->get_new_sec_state_reference(); if (!securityStateReference) return SNMPv3_MP_ERROR; switch (msgSecurityModel) { case SNMP_SECURITY_MODEL_USM: { rc = usm->process_msg( msgMaxSize, msgSecurityParameters.get_ptr(), msgSecurityParametersLength, securityParametersPosition, securityLevel, inBufPtr, origLength, //wholeMsg msgData.get_ptr(), msgDataLength, securityEngineID, securityName, scopedPDU.get_ptr(), &scopedPDULength, &maxSizeResponseScopedPDU, securityStateReference, from_address); pdu->maxsize_scopedpdu = maxSizeResponseScopedPDU; if (rc != SNMPv3_USM_OK) { if (rc == SNMPv3_USM_NOT_IN_TIME_WINDOW) { errorCode = SNMPv3_MP_NOT_IN_TIME_WINDOW; } else { // error handling! rfc2262 page 31 debugprintf(0, "mp: error while executing USM::process_msg"); errorCode = rc; } } if (errorCode != SNMPv3_USM_PARSE_ERROR) if (securityEngineID.len() == 0) errorCode = SNMPv3_MP_INVALID_ENGINEID; break; } default: { snmpUnknownSecurityModels++; usm->delete_sec_state_reference(securityStateReference); debugprintf(0, "SecurityModel of incomming Message not supported!"); // Message should be dropped without a report return SNMPv3_MP_UNSUPPORTED_SECURITY_MODEL; } } // process scopedPDU debughexcprintf(21, "scoped PDU", scopedPDU.get_ptr(), scopedPDULength); unsigned char *scopedPDUPtr= scopedPDU.get_ptr(); unsigned char tmp_contextEngineID[MAXLENGTH_ENGINEID]; unsigned char tmp_contextName[MAXLENGTH_CONTEXT_NAME]; int tmp_contextEngineIDLength = MAXLENGTH_ENGINEID; int tmp_contextNameLength = MAXLENGTH_CONTEXT_NAME; unsigned char *data; int dataLength; debugprintf(1,"ErrorCode is %i",errorCode); if (!errorCode) { data = asn1_parse_scoped_pdu(scopedPDUPtr, &scopedPDULength, tmp_contextEngineID, &tmp_contextEngineIDLength, tmp_contextName, &tmp_contextNameLength); if (data == NULL) { debugprintf(0, "mp: Error Parsing scopedPDU!"); usm->delete_sec_state_reference(securityStateReference); return SNMPv3_MP_PARSE_ERROR; } dataLength = scopedPDULength; contextEngineID.set_data(tmp_contextEngineID, tmp_contextEngineIDLength); contextName.set_data(tmp_contextName, tmp_contextNameLength); // parse data of scopedPDU if (snmp_parse_data_pdu(pdu, data, dataLength) != SNMP_CLASS_SUCCESS) { debugprintf(0, "mp: Error parsing PDU!"); usm->delete_sec_state_reference(securityStateReference); return SNMPv3_MP_PARSE_ERROR; } if (SNMP_CLASS_SUCCESS != snmp_parse_vb(pdu, data, dataLength)) { debugprintf(0, "mp: Error parsing Vb"); usm->delete_sec_state_reference(securityStateReference); return SNMPv3_MP_PARSE_ERROR; } if ((tmp_contextEngineIDLength == 0) && ((pdu->command == GET_REQ_MSG) || (pdu->command == GETNEXT_REQ_MSG) || (pdu->command == SET_REQ_MSG) || (pdu->command == GETBULK_REQ_MSG) || (pdu->command == TRP_REQ_MSG) || (pdu->command == INFORM_REQ_MSG) || (pdu->command == TRP2_REQ_MSG))) { // RFC 2572 � 4.2.2.1 (2a) debugprintf(2, "mp: received request message with zero length" " contextEngineID -> unknownPduHandlers."); inc_stats_unknown_pdu_handlers(); errorCode = SNMPv3_MP_UNKNOWN_PDU_HANDLERS; } } if (errorCode) { if ((reportableFlag) && (errorCode != SNMPv3_USM_PARSE_ERROR)) { // error occured: prepare reportpdu in agent cache.add_entry(msgID, pdu->reqid, securityEngineID, msgSecurityModel, securityName, securityLevel, "", "", securityStateReference, errorCode, CACHE_REMOTE_REQ); send_report(scopedPDUPtr, scopedPDULength, pdu, errorCode, securityLevel, msgSecurityModel, securityName, from_address, snmp_session); clear_pdu(pdu, true); // Clear pdu and free all content AND IDs! } else { usm->delete_sec_state_reference(securityStateReference); } return errorCode; } struct Cache::Entry_T centry; if ((pdu->command == GET_RSP_MSG) || (pdu->command == REPORT_MSG)) { rc = cache.get_entry(msgID, true, ¢ry); if (rc != SNMPv3_MP_OK) { // RFC 2572 � 4 debugprintf(2, "Received rspMsg without outstanding request." " -> SnmpUnknownPduHandler"); usm->delete_sec_state_reference(securityStateReference); inc_stats_unknown_pdu_handlers(); return SNMPv3_MP_UNKNOWN_PDU_HANDLERS; } if (((pdu->reqid == 0) || (pdu->reqid == 0x7fffffff)) && (pdu->command == REPORT_MSG)) pdu->reqid = centry.req_id; #ifdef BUGGY_REPORT_REQID if ((pdu->reqid != centry.req_id) && (pdu->command == REPORT_MSG)) { debugprintf(0, "WARNING: setting reqid of REPORT PDU (from) (to): (%ld) (%ld)", pdu->reqid, centry.req_id); pdu->reqid = centry.req_id; } #endif } if (pdu->command == REPORT_MSG) { // !! rfc2262 page 33 debugprintf(2, "*** Receiving a ReportPDU ***"); if (/*((securityEngineID != centry.sec_engine_id) && (centry.sec_engine_id.len() != 0)) ||*/ ((msgSecurityModel != centry.sec_model) && (msgSecurityModel != SNMP_SECURITY_MODEL_USM)) || ((securityName != centry.sec_name) && (securityName.len() != 0))) { debugprintf(0, "Received report message doesn't match sent message!"); usm->delete_sec_state_reference(securityStateReference); return SNMPv3_MP_MATCH_ERROR; } usm->delete_sec_state_reference(securityStateReference); cache.delete_content(centry); debugprintf(1, "mp finished (OK)"); return SNMPv3_MP_OK; } if (pdu->command == GET_RSP_MSG) { if (((securityEngineID != centry.sec_engine_id) && (centry.sec_engine_id.len() != 0)) || (msgSecurityModel != centry.sec_model) || (securityName != centry.sec_name) || (securityLevel != centry.sec_level) || ((contextEngineID != centry.context_engine_id) && (centry.context_engine_id.len() != 0))|| ((contextName != centry.context_name) && (centry.context_name.len() != 0))) { debugprintf(0, "Received response message doesn't match sent message!"); usm->delete_sec_state_reference(securityStateReference); cache.delete_content(centry); return SNMPv3_MP_MATCH_ERROR; } usm->delete_sec_state_reference(securityStateReference); cache.delete_content(centry); debugprintf(1, "mp finished (OK)"); return SNMPv3_MP_OK; } if ((pdu->command == GET_REQ_MSG) || (pdu->command == GETNEXT_REQ_MSG) || (pdu->command == SET_REQ_MSG) || (pdu->command == GETBULK_REQ_MSG) || (pdu->command == INFORM_REQ_MSG)) { if (securityEngineID.len() == 0) { debugprintf(2, "Received Message with engineID = 0."); } else { if (!(unsignedCharCompare(securityEngineID.data(), securityEngineID.len(), own_engine_id, own_engine_id_len))) { debugprintf(0, "snmp_parse: securityEngineID doesn't match own_engine_id."); /* we are authoritative but engine id of message is wrong if discovery in USM is enabled: - remove automatically added illegal engine id from USM tables - send a report */ if (usm->is_discovery_enabled()) { // TODO: try to remove engine id from USM if (reportableFlag) { cache.add_entry(msgID, pdu->reqid, securityEngineID, msgSecurityModel, securityName, securityLevel, "", "", securityStateReference, SNMPv3_MP_INVALID_ENGINEID, CACHE_REMOTE_REQ); send_report(0, MAX_SNMP_PACKET, pdu, SNMPv3_MP_INVALID_ENGINEID, SNMP_SECURITY_LEVEL_NOAUTH_NOPRIV, msgSecurityModel, securityName, from_address, snmp_session); clear_pdu(pdu, true); // Clear pdu and free all content AND IDs! } else { usm->delete_sec_state_reference(securityStateReference); } return SNMPv3_MP_INVALID_ENGINEID; } usm->delete_sec_state_reference(securityStateReference); return SNMPv3_MP_MATCH_ERROR; } } int ret = cache.add_entry(msgID, pdu->reqid, securityEngineID, msgSecurityModel, securityName, securityLevel, contextEngineID, contextName, securityStateReference, SNMPv3_MP_OK, CACHE_REMOTE_REQ); if (ret == SNMPv3_MP_DOUBLED_MESSAGE) { debugprintf(0, "*** received doubled message ***"); // message will be ignored so return OK usm->delete_sec_state_reference(securityStateReference); } debugprintf(1, "mp: parsing finished (ok)."); return SNMPv3_MP_OK; } if ((pdu->command == TRP_REQ_MSG) || (pdu->command == TRP2_REQ_MSG)) { usm->delete_sec_state_reference(securityStateReference); return SNMPv3_MP_OK; } debugprintf(0, "mp error: This line should not be executed."); usm->delete_sec_state_reference(securityStateReference); return SNMPv3_MP_ERROR; }
// Do the complete process of encoding the given values into the buffer // ready to send to the target. int v3MP::snmp_build(struct snmp_pdu *pdu, unsigned char *packet, int *out_length, // maximum Bytes in packet const OctetStr &securityEngineID, const OctetStr &securityName, int securityModel, int securityLevel, const OctetStr &contextEngineID, const OctetStr &contextName) { Buffer<unsigned char> scopedPDU(MAX_SNMP_PACKET); unsigned char *scopedPDUPtr = scopedPDU.get_ptr(); unsigned char globalData[MAXLENGTH_GLOBALDATA]; int globalDataLength = MAXLENGTH_GLOBALDATA; int scopedPDULength, maxLen = *out_length; Buffer<unsigned char> buf(MAX_SNMP_PACKET); unsigned char *bufPtr = buf.get_ptr(); long bufLength = 0, rc; int msgID; int cachedErrorCode = SNMPv3_MP_OK; struct SecurityStateReference *securityStateReference = NULL; int isRequestMessage = 0; if ((pdu->command == GET_REQ_MSG) || (pdu->command == GETNEXT_REQ_MSG) || (pdu->command == SET_REQ_MSG) || (pdu->command == GETBULK_REQ_MSG) || (pdu->command == TRP_REQ_MSG) || (pdu->command == INFORM_REQ_MSG) || (pdu->command == TRP2_REQ_MSG)) isRequestMessage = 1; if (isRequestMessage) { if (securityEngineID.len() == 0) { // First Contact => use user noAuthNoPriv and USM securityLevel = SNMP_SECURITY_LEVEL_NOAUTH_NOPRIV; securityModel = SNMP_SECURITY_MODEL_USM; } cur_msg_id_lock.lock(); msgID = cur_msg_id; cur_msg_id++; if (cur_msg_id >= MAX_MPMSGID) cur_msg_id = 1; cur_msg_id_lock.unlock(); #ifdef INVALID_MSGID LOG_BEGIN(loggerModuleName, ERROR_LOG | 1); LOG("*** WARNING: Using constant MessageID! ***"); LOG_END; msgID = 0xdead; #endif if (securityEngineID.len() == 0) { // length==0 => SecurityLevel == noAuthNoPriv // => we do not send any management information // => delete VariableBinding clear_pdu(pdu); } } else { // it is a response => search for request debugprintf(3, "Looking up cache"); msgID = pdu->msgid; rc = cache.get_entry(msgID, CACHE_REMOTE_REQ, &cachedErrorCode, &securityStateReference); if (rc != SNMPv3_MP_OK) { debugprintf(0, "mp: Cache lookup error"); return SNMPv3_MP_MATCH_ERROR; } } LOG_BEGIN(loggerModuleName, DEBUG_LOG | 5); LOG("v3MP: Building message with (SecurityEngineID) (securityName) (securityLevel) (contextEngineID) (contextName)"); LOG(securityEngineID.get_printable()); LOG(securityName.get_printable()); LOG(securityLevel); LOG(contextEngineID.get_printable()); LOG(contextName.get_printable()); LOG_END; // encode vb in buf scopedPDUPtr = build_vb(pdu, scopedPDUPtr, &maxLen); if (!scopedPDUPtr) { LOG_BEGIN(loggerModuleName, WARNING_LOG | 1); LOG("v3MP: Error encoding vbs into buffer"); LOG_END; return SNMPv3_MP_BUILD_ERROR; } scopedPDULength = SAFE_INT_CAST(scopedPDUPtr - scopedPDU.get_ptr()); //build dataPDU in buf maxLen = *out_length; scopedPDUPtr = scopedPDU.get_ptr(); bufPtr = build_data_pdu(pdu, bufPtr, &maxLen, scopedPDUPtr, scopedPDULength); if (!bufPtr) { LOG_BEGIN(loggerModuleName, WARNING_LOG | 1); LOG("v3MP: Error encoding data pdu into buffer"); LOG_END; return SNMPv3_MP_BUILD_ERROR; } bufLength = SAFE_INT_CAST(bufPtr - buf.get_ptr()); // serialize scopedPDU maxLen = *out_length; scopedPDUPtr = asn1_build_scoped_pdu(scopedPDUPtr, &maxLen, contextEngineID.data(), contextEngineID.len(), contextName.data(), contextName.len(), buf.get_ptr(), bufLength); if (!scopedPDUPtr) { LOG_BEGIN(loggerModuleName, WARNING_LOG | 1); LOG("v3MP: Error encoding scoped pdu into buffer"); LOG_END; return SNMPv3_MP_BUILD_ERROR; } scopedPDULength = SAFE_INT_CAST(scopedPDUPtr - scopedPDU.get_ptr()); // build msgGlobalData unsigned char *globalDataPtr = (unsigned char *)&globalData; unsigned char msgFlags; switch (securityLevel) { case SNMP_SECURITY_LEVEL_NOAUTH_NOPRIV: { msgFlags = 0 ; break;} case SNMP_SECURITY_LEVEL_AUTH_NOPRIV: { msgFlags = SNMPv3_AUTHFLAG; break;} case SNMP_SECURITY_LEVEL_AUTH_PRIV: { msgFlags = SNMPv3_AUTHFLAG | SNMPv3_PRIVFLAG; break;} default: { LOG_BEGIN(loggerModuleName, WARNING_LOG | 1); LOG("v3MP: Unknown security level requested, will use authPriv"); LOG(securityLevel); LOG_END; msgFlags = SNMPv3_AUTHFLAG | SNMPv3_PRIVFLAG; } } if ((pdu->command == GET_REQ_MSG) || (pdu->command == GETNEXT_REQ_MSG) || (pdu->command == SET_REQ_MSG) || (pdu->command == GETBULK_REQ_MSG) || (pdu->command == INFORM_REQ_MSG)) msgFlags = msgFlags | SNMPv3_REPORTABLEFLAG; globalDataPtr = asn1_build_header_data(globalDataPtr, &globalDataLength, msgID, *out_length, // maxMessageSize msgFlags, securityModel); if (!globalDataPtr) { LOG_BEGIN(loggerModuleName, ERROR_LOG | 1); LOG("v3MP: Error building header data"); LOG_END; return SNMPv3_MP_BUILD_ERROR; } globalDataLength = SAFE_INT_CAST(globalDataPtr - (unsigned char *)&globalData); switch (securityModel) { case SNMP_SECURITY_MODEL_USM: { int use_own_engine_id = 0; if ((pdu->command == TRP_REQ_MSG) || (pdu->command == GET_RSP_MSG) || (pdu->command == REPORT_MSG) || (pdu->command == TRP2_REQ_MSG)) { use_own_engine_id = 1; } rc = usm->generate_msg(globalData, globalDataLength, *out_length, (use_own_engine_id ? own_engine_id_oct : securityEngineID), securityName, securityLevel, scopedPDU.get_ptr(), scopedPDULength, securityStateReference, packet, out_length); if ( rc == SNMPv3_USM_OK ) { // build cache if (!((pdu->command == TRP_REQ_MSG) || (pdu->command == GET_RSP_MSG) || (pdu->command == REPORT_MSG) || (pdu->command == TRP2_REQ_MSG))) cache.add_entry(msgID, pdu->reqid, securityEngineID, securityModel, securityName, securityLevel, contextEngineID, contextName, securityStateReference, SNMPv3_MP_OK, CACHE_LOCAL_REQ); LOG_BEGIN(loggerModuleName, INFO_LOG | 3); LOG("v3MP: Message built OK"); LOG_END; return SNMPv3_MP_OK; } else { LOG_BEGIN(loggerModuleName, WARNING_LOG | 1); LOG("v3MP: Returning error for building message"); LOG(rc); LOG_END; return rc; } } default: { LOG_BEGIN(loggerModuleName, WARNING_LOG | 1); LOG("v3MP: Should build message with unsupported securityModel"); LOG(securityModel); LOG_END; return SNMPv3_MP_UNSUPPORTED_SECURITY_MODEL; } } }