+#include <cstdio>
+#include <fstream>
#include <boost/lexical_cast.hpp>
#include "snmp_pp/snmp_pp.h"
#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,
_writeCommunity(writeCommunity),
_uplinkPort(uplinkPort),
_nextUpACL(1),
- _nextDownACL(1)
+ _nextDownACL(1),
+ _aclsCreated(false)
{
}
_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)
_nextUpACL = rvalue._nextUpACL;
_nextDownACL = rvalue._nextDownACL;
_acls = rvalue._acls;
+ _aclsCreated = rvalue._aclsCreated;
return *this;
}
return;
}
- if (!dropACLs(target)) {
- logger << "Switch::sync() - failed to drop ACLs for the switch '" << _ip << "'" << std::endl;
- return;
- }
+ {
+ std::ostream * stream = NULL;
+ std::string fileName(_settings.scriptBase() + "/" + _ip + ".sh");
+ std::string newFileName(fileName + ".new");
+
+ if (_settings.dumpScripts()) {
+ stream = new std::ofstream(newFileName.c_str());
+ *stream << "#!/bin/sh\n";
+ } else {
+ stream = new std::stringstream;
+ }
+
+ if (!dropACLs(target, *stream)) {
+ logger << "Switch::sync() - failed to drop ACLs for the switch '" << _ip << "'" << std::endl;
+ delete stream;
+ return;
+ }
- if (!createACLs(target)) {
- logger << "Switch::sync() - failed to create ACLs for the switch '" << _ip << "'" << std::endl;
+ if (!createACLs(target, *stream)) {
+ logger << "Switch::sync() - failed to create ACLs for the switch '" << _ip << "'" << std::endl;
+ delete stream;
+ return;
+ }
+
+ delete stream;
+ if (_settings.dumpScripts())
+ rename(newFileName.c_str(), fileName.c_str());
}
if (_settings.isDebug()) {
return false;
}
-bool Switch::dropACLs(const CTarget & target)
+bool Switch::dropACLs(const CTarget & target, std::ostream & stream)
{
std::string upOidValue(swACLEtherRuleAccessID);
upOidValue += ".";
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;
}
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<std::string>(profileId);
SNMPList aclsList(table.getList());
- Pdu pdu;
- SNMPList::const_iterator it;
- for (it = aclsList.begin(); it != aclsList.end(); ++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;
+ 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;
+ if (_settings.dumpScripts())
+ stream << "snmpset -v2c -c" << _writeCommunity << " " << _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<std::string>(id);
+ Vb vb(Oid(dropACLOid.c_str()));
+ vb.set_value(int(6));
+ pdu += vb;
+ if (_settings.dumpScripts())
+ stream << " " << dropACLOid << " i 6";
+ }
+ if (_settings.dumpScripts())
+ 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<std::string>(id);
- Vb vb(Oid(dropACLOid.c_str()));
- vb.set_value(int(6));
- pdu += vb;
- }
- if (int c = _snmp.set(pdu, target) != SNMP_CLASS_SUCCESS) {
- logger << "Switch::dropACLsByTable() - failed to invoke Snmp::set for the switch '" << _ip << "'. Error message: '" << Snmp::error_msg(c) << "'" << std::endl;
- return false;
}
return true;
}
-bool Switch::createACLs(const CTarget & target)
+bool Switch::createACLs(const CTarget & target, std::ostream & stream)
{
std::vector<ACL>::const_iterator it;
+ size_t pos = 0;
for (it = _acls.begin(); it != _acls.end(); ++it) {
Pdu pdu;
it->appendPdu(pdu);
if (int c = _snmp.set(pdu, target) != SNMP_CLASS_SUCCESS) {
- logger << "Switch::createACLs() - failed to invoke Snmp::set for the switch '" << _ip << "'. Error message: '" << Snmp::error_msg(c) << "'" << std::endl;
- return false;
+ 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;
+ if (_settings.dumpScripts())
+ stream << "snmpset -v2c -c" << _writeCommunity << " " << _ip << " " << *it << "\n";
}
return true;
}