3 #include <boost/lexical_cast.hpp>
5 #include "snmp_pp/snmp_pp.h"
9 #include "subscriber.h"
12 #include "snmptable.h"
16 using SSMD::SNMPTable;
18 Switch::Switch(const Settings & settings,
20 const std::string & ip,
21 const std::string & readCommunity,
22 const std::string & writeCommunity,
24 : _settings(settings),
27 _readCommunity(readCommunity),
28 _writeCommunity(writeCommunity),
29 _uplinkPort(uplinkPort),
36 Switch::Switch(const Switch & rvalue)
37 : _settings(rvalue._settings),
40 _readCommunity(rvalue._readCommunity),
41 _writeCommunity(rvalue._writeCommunity),
42 _uplinkPort(rvalue._uplinkPort),
43 _nextUpACL(rvalue._nextUpACL),
44 _nextDownACL(rvalue._nextDownACL),
46 _aclsCreated(rvalue._aclsCreated)
53 IpAddress addr(_ip.c_str());
55 logger << "Switch::~Switch() - ivalid switch ip: '" << _ip << "'" << std::endl;
59 CTarget target(addr, _readCommunity.c_str(), _writeCommunity.c_str());
60 if (!target.valid()) {
61 logger << "Switch::~Switch() - failed to create target for the switch '" << _ip << "'" << std::endl;
65 target.set_version(version2c);
67 if (!checkProfiles(target)) {
68 logger << "Switch::~Switch() - no upload and download profiles defined for the switch '" << _ip << "'" << std::endl;
72 if (!dropACLs(target, std::cerr)) {
73 logger << "Switch::~Switch() - failed to drop ACLs for the switch '" << _ip << "'" << std::endl;
79 Switch & Switch::operator=(const Switch & rvalue)
82 _readCommunity = rvalue._readCommunity;
83 _writeCommunity = rvalue._writeCommunity;
84 _uplinkPort = rvalue._uplinkPort;
85 _nextUpACL = rvalue._nextUpACL;
86 _nextDownACL = rvalue._nextDownACL;
88 _aclsCreated = rvalue._aclsCreated;
93 void Switch::addSubscriber(const Subscriber & subscriber)
95 _acls.push_back(ACL(_nextUpACL++,
96 _settings.upProfileId(),
99 subscriber.getUpShape(),
100 subscriber.getUpBurst(),
102 _acls.push_back(ACL(_nextDownACL++,
103 _settings.downProfileId(),
106 subscriber.getDownShape(),
107 subscriber.getDownBurst(),
113 IpAddress addr(_ip.c_str());
115 logger << "Switch::sync() - ivalid switch ip: '" << _ip << "'" << std::endl;
119 CTarget target(addr, _readCommunity.c_str(), _writeCommunity.c_str());
120 if (!target.valid()) {
121 logger << "Switch::sync() - failed to create target for the switch '" << _ip << "'" << std::endl;
125 target.set_version(version2c);
127 if (!checkProfiles(target)) {
128 logger << "Switch::sync() - no upload and download profiles defined for the switch '" << _ip << "'" << std::endl;
133 std::ostream * stream = NULL;
134 std::string fileName(_settings.scriptBase() + "/" + _ip + ".sh");
135 std::string newFileName(fileName + ".new");
137 if (_settings.dumpScripts()) {
138 stream = new std::ofstream(newFileName.c_str());
139 *stream << "#!/bin/sh\n";
141 stream = new std::stringstream;
144 if (!dropACLs(target, *stream)) {
145 logger << "Switch::sync() - failed to drop ACLs for the switch '" << _ip << "'" << std::endl;
150 if (!createACLs(target, *stream)) {
151 logger << "Switch::sync() - failed to create ACLs for the switch '" << _ip << "'" << std::endl;
157 if (_settings.dumpScripts())
158 rename(newFileName.c_str(), fileName.c_str());
161 if (_settings.isDebug()) {
162 logger << "Switch::sync() - switch '" << _ip << "' synchronized successfully, ACLs: " << _acls.size() << std::endl;
166 bool Switch::checkProfiles(const CTarget & target)
168 SNMPTable table(_snmp, target, Oid(swACLEtherRuleProfileID));
169 if (!table.valid()) {
170 logger << "Switch::checkProfiles() - profiles SNMPTable is invalid for the switch '" << _ip << "'" << std::endl;
174 // Ok, just an empty table
177 if (table.valueExists(
178 static_cast<int>(_settings.upProfileId())
181 static_cast<int>(_settings.downProfileId())
188 bool Switch::dropACLs(const CTarget & target, std::ostream & stream)
190 std::string upOidValue(swACLEtherRuleAccessID);
192 upOidValue += boost::lexical_cast<std::string>(_settings.upProfileId());
193 std::string downOidValue(swACLEtherRuleAccessID);
195 downOidValue += boost::lexical_cast<std::string>(_settings.downProfileId());
196 SNMPTable aclsUpTable(_snmp, target, Oid(upOidValue.c_str()));
197 SNMPTable aclsDownTable(_snmp, target, Oid(downOidValue.c_str()));
198 if (!aclsUpTable.valid()) {
199 logger << "Switch::dropACLs() - upload profile acls SNMPTable is invalid for the switch '" << _ip << "'" << std::endl;
202 if (!aclsDownTable.valid()) {
203 logger << "Switch::dropACLs() - download profile acls SNMPTable is invalid for the switch '" << _ip << "'" << std::endl;
206 if (!aclsUpTable.empty()) {
207 if (!dropACLsByTable(target, _settings.upProfileId(), aclsUpTable, stream)) {
208 logger << "Switch::dropACLs() - failed to drop acls from upload table for the switch '" << _ip << "'" << std::endl;
212 if (!aclsDownTable.empty()) {
213 if (!dropACLsByTable(target, _settings.downProfileId(), aclsDownTable, stream)) {
214 logger << "Switch::dropACLs() - failed to drop acls from download table for the switch '" << _ip << "'" << std::endl;
221 bool Switch::dropACLsByTable(const CTarget & target, unsigned profileId, const SNMPTable & table, std::ostream & stream)
223 std::string dropACLOidPrefix(swACLEtherRuleRowStatus);
224 dropACLOidPrefix += ".";
225 dropACLOidPrefix += boost::lexical_cast<std::string>(profileId);
226 SNMPList aclsList(table.getList());
227 SNMPList::const_iterator it(aclsList.begin());
228 size_t chunks = aclsList.size() / _settings.maxACLPerPDU() + 1;
229 for (size_t i = 0; i < chunks && it != aclsList.end(); ++i) {
231 if (_settings.dumpScripts())
232 stream << "snmpset -v2c -c" << _writeCommunity << " " << _ip;
233 for (size_t j = 0; j < _settings.maxACLPerPDU() && it != aclsList.end(); ++j, ++it) {
235 if (int c = it->get_value(id) != SNMP_CLASS_SUCCESS) {
236 logger << "Switch::dropACLsByTable() - failed to get ACL id for the switch '" << _ip << "'. Error message: '" << Snmp::error_msg(c) << "'" << std::endl;
239 std::string dropACLOid(dropACLOidPrefix);
241 dropACLOid += boost::lexical_cast<std::string>(id);
242 Vb vb(Oid(dropACLOid.c_str()));
243 vb.set_value(int(6));
245 if (_settings.dumpScripts())
246 stream << " " << dropACLOid << " i 6";
248 if (_settings.dumpScripts())
250 if (int c = _snmp.set(pdu, target) != SNMP_CLASS_SUCCESS) {
251 if (c != SNMP_ERROR_TOO_BIG) {
252 logger << "Switch::dropACLsByTable() - failed to invoke Snmp::set for the switch '" << _ip << "'. Error message: '" << Snmp::error_msg(c) << "'" << std::endl;
260 bool Switch::createACLs(const CTarget & target, std::ostream & stream)
262 std::vector<ACL>::const_iterator it;
264 for (it = _acls.begin(); it != _acls.end(); ++it) {
267 if (int c = _snmp.set(pdu, target) != SNMP_CLASS_SUCCESS) {
268 if (c != SNMP_ERROR_TOO_BIG) {
269 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;
270 logger << "Switch::createACLs() - ACL dump: " << *it << std::endl;
277 if (_settings.dumpScripts())
278 stream << "snmpset -v2c -c" << _writeCommunity << " " << _ip << " " << *it << "\n";