]> git.stg.codes - ssmd.git/blob - src/switch.cpp
Extra error messages added
[ssmd.git] / src / switch.cpp
1 #include <boost/lexical_cast.hpp>
2
3 #include "snmp_pp/snmp_pp.h"
4
5 #include "switch.h"
6 #include "settings.h"
7 #include "subscriber.h"
8 #include "acl.h"
9 #include "logger.h"
10 #include "snmptable.h"
11 #include "oids.h"
12
13 using GTS::Switch;
14 using GTS::SNMPTable;
15
16 Switch::Switch(const Settings & settings,
17                Snmp & snmp,
18                const std::string & ip,
19                const std::string & readCommunity,
20                const std::string & writeCommunity,
21                unsigned uplinkPort)
22     : _settings(settings),
23       _snmp(snmp),
24       _ip(ip),
25       _readCommunity(readCommunity),
26       _writeCommunity(writeCommunity),
27       _uplinkPort(uplinkPort),
28       _nextUpACL(1),
29       _nextDownACL(1)
30 {
31 }
32
33 Switch::Switch(const Switch & rvalue)
34     : _settings(rvalue._settings),
35       _snmp(rvalue._snmp),
36       _ip(rvalue._ip),
37       _readCommunity(rvalue._readCommunity),
38       _writeCommunity(rvalue._writeCommunity),
39       _uplinkPort(rvalue._uplinkPort),
40       _nextUpACL(rvalue._nextUpACL),
41       _nextDownACL(rvalue._nextDownACL),
42       _acls(rvalue._acls)
43 {
44 }
45
46 Switch::~Switch()
47 {
48 }
49
50 Switch & Switch::operator=(const Switch & rvalue)
51 {
52     _ip = rvalue._ip;
53     _readCommunity = rvalue._readCommunity;
54     _writeCommunity = rvalue._writeCommunity;
55     _uplinkPort = rvalue._uplinkPort;
56     _nextUpACL = rvalue._nextUpACL;
57     _nextDownACL = rvalue._nextDownACL;
58     _acls = rvalue._acls;
59
60     return *this;
61 }
62
63 void Switch::addSubscriber(const Subscriber & subscriber)
64 {
65     _acls.push_back(ACL(_nextUpACL++,
66                         _settings.upProfileId(),
67                         subscriber.getMAC(),
68                         subscriber.getPort(),
69                         subscriber.getUpShape(),
70                         subscriber.getUpBurst(),
71                         true));
72     _acls.push_back(ACL(_nextDownACL++,
73                         _settings.downProfileId(),
74                         subscriber.getMAC(),
75                         _uplinkPort,
76                         subscriber.getDownShape(),
77                         subscriber.getDownBurst(),
78                         false));
79 }
80
81 void Switch::sync()
82 {
83     IpAddress addr(_ip.c_str());
84     if (!addr.valid()) {
85         logger << "Switch::sync() - ivalid switch ip: '" << _ip << "'" << std::endl;
86         return;
87     }
88
89     CTarget target(addr, _readCommunity.c_str(), _writeCommunity.c_str());
90     if (!target.valid()) {
91         logger << "Switch::sync() - failed to create target for the switch '" << _ip << "'" << std::endl;
92         return;
93     }
94
95     target.set_version(version2c);
96
97     if (!checkProfiles(target)) {
98         logger << "Switch::sync() - no upload and download profiles defined for the switch '" << _ip << "'" << std::endl;
99         return;
100     }
101
102     if (!dropACLs(target)) {
103         logger << "Switch::sync() - failed to drop ACLs for the switch '" << _ip << "'" << std::endl;
104         return;
105     }
106
107     if (!createACLs(target)) {
108         logger << "Switch::sync() - failed to create ACLs for the switch '" << _ip << "'" << std::endl;
109     }
110
111     if (_settings.isDebug()) {
112         logger << "Switch::sync() - switch '" << _ip << "' synchronized successfully, ACLs: " << _acls.size() << std::endl;
113     }
114 }
115
116 bool Switch::checkProfiles(const CTarget & target)
117 {
118     SNMPTable table(_snmp, target, Oid(swACLEtherRuleProfileID));
119     if (!table.valid()) {
120         logger << "Switch::checkProfiles() - profiles SNMPTable is invalid for the switch '" << _ip << "'" << std::endl;
121         return false;
122     }
123     if (table.empty()) {
124         // Ok, just an empty table
125         return false;
126     }
127     if (table.valueExists(
128             static_cast<int>(_settings.upProfileId())
129         ) &&
130         table.valueExists(
131             static_cast<int>(_settings.downProfileId())
132         )) {
133         return true;
134     }
135     return false;
136 }
137
138 bool Switch::dropACLs(const CTarget & target)
139 {
140     std::string upOidValue(swACLEtherRuleAccessID);
141     upOidValue += ".";
142     upOidValue += boost::lexical_cast<std::string>(_settings.upProfileId());
143     std::string downOidValue(swACLEtherRuleAccessID);
144     downOidValue += ".";
145     downOidValue += boost::lexical_cast<std::string>(_settings.downProfileId());
146     SNMPTable aclsUpTable(_snmp, target, Oid(upOidValue.c_str()));
147     SNMPTable aclsDownTable(_snmp, target, Oid(downOidValue.c_str()));
148     if (!aclsUpTable.valid()) {
149         logger << "Switch::dropACLs() - upload profile acls SNMPTable is invalid for the switch '" << _ip << "'" << std::endl;
150         return false;
151     }
152     if (!aclsDownTable.valid()) {
153         logger << "Switch::dropACLs() - download profile acls SNMPTable is invalid for the switch '" << _ip << "'" << std::endl;
154         return false;
155     }
156     if (!aclsUpTable.empty()) {
157         if (!dropACLsByTable(target, _settings.upProfileId(), aclsUpTable)) {
158             logger << "Switch::dropACLs() - failed to drop acls from upload table for the switch '" << _ip << "'" << std::endl;
159             return false;
160         }
161     }
162     if (!aclsDownTable.empty()) {
163         if (!dropACLsByTable(target, _settings.downProfileId(), aclsDownTable)) {
164             logger << "Switch::dropACLs() - failed to drop acls from download table for the switch '" << _ip << "'" << std::endl;
165             return false;
166         }
167     }
168     return true;
169 }
170
171 bool Switch::dropACLsByTable(const CTarget & target, unsigned profileId, const SNMPTable & table)
172 {
173     std::string dropACLOidPrefix(swACLEtherRuleRowStatus);
174     dropACLOidPrefix += ".";
175     dropACLOidPrefix += boost::lexical_cast<std::string>(profileId);
176     SNMPList aclsList(table.getList());
177     Pdu pdu;
178     SNMPList::const_iterator it;
179     for (it = aclsList.begin(); it != aclsList.end(); ++it) {
180         int id;
181         if (int c = it->get_value(id) != SNMP_CLASS_SUCCESS) {
182             logger << "Switch::dropACLsByTable() - failed to get ACL id for the switch '" << _ip << "'. Error message: '" << Snmp::error_msg(c) << "'" << std::endl;
183             return false;
184         }
185         std::string dropACLOid(dropACLOidPrefix);
186         dropACLOid += ".";
187         dropACLOid += boost::lexical_cast<std::string>(id);
188         Vb vb(Oid(dropACLOid.c_str()));
189         vb.set_value(int(6));
190         pdu += vb;
191     }
192     if (int c = _snmp.set(pdu, target) != SNMP_CLASS_SUCCESS) {
193         logger << "Switch::dropACLsByTable() - failed to invoke Snmp::set for the switch '" << _ip << "'. Error message: '" << Snmp::error_msg(c) << "'" << std::endl;
194         return false;
195     }
196     return true;
197 }
198
199 bool Switch::createACLs(const CTarget & target)
200 {
201     std::vector<ACL>::const_iterator it;
202     for (it = _acls.begin(); it != _acls.end(); ++it) {
203         Pdu pdu;
204         it->appendPdu(pdu);
205         if (int c = _snmp.set(pdu, target) != SNMP_CLASS_SUCCESS) {
206             logger << "Switch::createACLs() - failed to invoke Snmp::set for the switch '" << _ip << "'. Error message: '" << Snmp::error_msg(c) << "'" << std::endl;
207             return false;
208         }
209     }
210     return true;
211 }