X-Git-Url: https://git.stg.codes/ssmd.git/blobdiff_plain/ae26516a8828d54ab7c0e0bca92031a54a15ed62..25dd1ac0696ca47e586e58d4309fc4c36e11d1dc:/src/switch.cpp diff --git a/src/switch.cpp b/src/switch.cpp index 43c83da..444324b 100644 --- a/src/switch.cpp +++ b/src/switch.cpp @@ -1,3 +1,5 @@ +#include +#include #include #include "snmp_pp/snmp_pp.h" @@ -10,8 +12,8 @@ #include "snmptable.h" #include "oids.h" -using GTS::Switch; -using GTS::SNMPTable; +using SSMD::Switch; +using SSMD::SNMPTable; Switch::Switch(const Settings & settings, Snmp & snmp, @@ -26,7 +28,8 @@ Switch::Switch(const Settings & settings, _writeCommunity(writeCommunity), _uplinkPort(uplinkPort), _nextUpACL(1), - _nextDownACL(1) + _nextDownACL(1), + _aclsCreated(false) { } @@ -39,12 +42,38 @@ Switch::Switch(const Switch & rvalue) _uplinkPort(rvalue._uplinkPort), _nextUpACL(rvalue._nextUpACL), _nextDownACL(rvalue._nextDownACL), - _acls(rvalue._acls) + _acls(rvalue._acls), + _aclsCreated(rvalue._aclsCreated) { } Switch::~Switch() { + if (_aclsCreated) { + IpAddress addr(_ip.c_str()); + if (!addr.valid()) { + logger << "Switch::~Switch() - ivalid switch ip: '" << _ip << "'" << std::endl; + return; + } + + CTarget target(addr, _readCommunity.c_str(), _writeCommunity.c_str()); + if (!target.valid()) { + logger << "Switch::~Switch() - failed to create target for the switch '" << _ip << "'" << std::endl; + return; + } + + target.set_version(version2c); + + if (!checkProfiles(target)) { + logger << "Switch::~Switch() - no upload and download profiles defined for the switch '" << _ip << "'" << std::endl; + return; + } + + if (!dropACLs(target, std::cerr)) { + logger << "Switch::~Switch() - failed to drop ACLs for the switch '" << _ip << "'" << std::endl; + return; + } + } } Switch & Switch::operator=(const Switch & rvalue) @@ -56,6 +85,7 @@ Switch & Switch::operator=(const Switch & rvalue) _nextUpACL = rvalue._nextUpACL; _nextDownACL = rvalue._nextDownACL; _acls = rvalue._acls; + _aclsCreated = rvalue._aclsCreated; return *this; } @@ -99,13 +129,22 @@ void Switch::sync() return; } - if (!dropACLs(target)) { - logger << "Switch::sync() - failed to drop ACLs for the switch '" << _ip << "'" << std::endl; - return; - } + { + std::string fileName(_ip + ".sh"); + std::string newFileName(fileName + ".new"); + std::ofstream script(newFileName.c_str()); + script << "#!/bin/sh\n"; + if (!dropACLs(target, script)) { + logger << "Switch::sync() - failed to drop ACLs for the switch '" << _ip << "'" << std::endl; + return; + } - if (!createACLs(target)) { - logger << "Switch::sync() - failed to create ACLs for the switch '" << _ip << "'" << std::endl; + if (!createACLs(target, script)) { + logger << "Switch::sync() - failed to create ACLs for the switch '" << _ip << "'" << std::endl; + return; + } + script.close(); + rename(newFileName.c_str(), fileName.c_str()); } if (_settings.isDebug()) { @@ -135,7 +174,7 @@ bool Switch::checkProfiles(const CTarget & target) return false; } -bool Switch::dropACLs(const CTarget & target) +bool Switch::dropACLs(const CTarget & target, std::ostream & stream) { std::string upOidValue(swACLEtherRuleAccessID); upOidValue += "."; @@ -154,13 +193,13 @@ bool Switch::dropACLs(const CTarget & target) return false; } if (!aclsUpTable.empty()) { - if (!dropACLsByTable(target, _settings.upProfileId(), aclsUpTable)) { + if (!dropACLsByTable(target, _settings.upProfileId(), aclsUpTable, stream)) { logger << "Switch::dropACLs() - failed to drop acls from upload table for the switch '" << _ip << "'" << std::endl; return false; } } if (!aclsDownTable.empty()) { - if (!dropACLsByTable(target, _settings.downProfileId(), aclsDownTable)) { + if (!dropACLsByTable(target, _settings.downProfileId(), aclsDownTable, stream)) { logger << "Switch::dropACLs() - failed to drop acls from download table for the switch '" << _ip << "'" << std::endl; return false; } @@ -168,43 +207,60 @@ bool Switch::dropACLs(const CTarget & target) return true; } -bool Switch::dropACLsByTable(const CTarget & target, unsigned profileId, const SNMPTable & table) +bool Switch::dropACLsByTable(const CTarget & target, unsigned profileId, const SNMPTable & table, std::ostream & stream) { std::string dropACLOidPrefix(swACLEtherRuleRowStatus); dropACLOidPrefix += "."; dropACLOidPrefix += boost::lexical_cast(profileId); SNMPList aclsList(table.getList()); - Pdu pdu; - SNMPList::const_iterator it; - for (it = aclsList.begin(); it != aclsList.end(); ++it) { - int id; - if (it->get_value(id) != SNMP_CLASS_SUCCESS) { - return false; + SNMPList::const_iterator it(aclsList.begin()); + size_t chunks = aclsList.size() / _settings.maxACLPerPDU() + 1; + for (size_t i = 0; i < chunks && it != aclsList.end(); ++i) { + Pdu pdu; + stream << "snmpset -v2c -cgts_community_w " << _ip; + for (size_t j = 0; j < _settings.maxACLPerPDU() && it != aclsList.end(); ++j, ++it) { + int id; + if (int c = it->get_value(id) != SNMP_CLASS_SUCCESS) { + logger << "Switch::dropACLsByTable() - failed to get ACL id for the switch '" << _ip << "'. Error message: '" << Snmp::error_msg(c) << "'" << std::endl; + return false; + } + std::string dropACLOid(dropACLOidPrefix); + dropACLOid += "."; + dropACLOid += boost::lexical_cast(id); + Vb vb(Oid(dropACLOid.c_str())); + vb.set_value(int(6)); + pdu += vb; + stream << " " << dropACLOid << " i 6"; + } + stream << "\n"; + if (int c = _snmp.set(pdu, target) != SNMP_CLASS_SUCCESS) { + if (c != SNMP_ERROR_TOO_BIG) { + logger << "Switch::dropACLsByTable() - failed to invoke Snmp::set for the switch '" << _ip << "'. Error message: '" << Snmp::error_msg(c) << "'" << std::endl; + return false; + } } - std::string dropACLOid(dropACLOidPrefix); - dropACLOid += "."; - dropACLOid += boost::lexical_cast(id); - Vb vb(Oid(dropACLOid.c_str())); - vb.set_value(int(6)); - pdu += vb; - } - if (_snmp.set(pdu, target) != SNMP_CLASS_SUCCESS) { - logger << "Switch::dropACLsByTable() - failed to invoke Snmp::set for the switch '" << _ip << "'" << std::endl; - return false; } return true; } -bool Switch::createACLs(const CTarget & target) +bool Switch::createACLs(const CTarget & target, std::ostream & stream) { std::vector::const_iterator it; + size_t pos = 0; for (it = _acls.begin(); it != _acls.end(); ++it) { Pdu pdu; it->appendPdu(pdu); - if (_snmp.set(pdu, target) != SNMP_CLASS_SUCCESS) { - logger << "Switch::createACLs() - failed to invoke Snmp::set for the switch '" << _ip << "'" << std::endl; - return false; + if (int c = _snmp.set(pdu, target) != SNMP_CLASS_SUCCESS) { + if (c != SNMP_ERROR_TOO_BIG) { + logger << "Switch::createACLs() - failed to invoke Snmp::set for the switch '" << _ip << "'. Error message: '" << Snmp::error_msg(c) << "'. Error occured at creation of " << (pos + 1) << " from " << _acls.size() << " ACL's" << std::endl; + logger << "Switch::createACLs() - ACL dump: " << *it << std::endl; + return false; + } } + pdu.clear(); + _aclsCreated = true; + ++pos; + stream << "snmpset -v2c -cgts_community_w " << _ip << " " << *it << "\n"; } return true; }