29dd72270a046dcf5af17381db4892b0b7892fe4
[public/netxms.git] / src / server / drivers / ntws / ntws.cpp
1 /*
2 ** NetXMS - Network Management System
3 ** Driver for Nortel WLAN Security Switch series
4 ** Copyright (C) 2013 Raden Solutions
5 **
6 ** This program is free software; you can redistribute it and/or modify
7 ** it under the terms of the GNU Lesser General Public License as published by
8 ** the Free Software Foundation; either version 3 of the License, or
9 ** (at your option) any later version.
10 **
11 ** This program is distributed in the hope that it will be useful,
12 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 ** GNU General Public License for more details.
15 **
16 ** You should have received a copy of the GNU Lesser General Public License
17 ** along with this program; if not, write to the Free Software
18 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 **/
20
21 #include "ntws.h"
22 #include <math.h>
23
24 /**
25 * Static data
26 */
27 static TCHAR s_driverName[] = _T("NTWS");
28 static TCHAR s_driverVersion[] = NETXMS_VERSION_STRING;
29
30 /**
31 * Get driver name
32 */
33 const TCHAR *NtwsDriver::getName()
34 {
35 return s_driverName;
36 }
37
38 /**
39 * Get driver version
40 */
41 const TCHAR *NtwsDriver::getVersion()
42 {
43 return s_driverVersion;
44 }
45
46 /**
47 * Check if given device can be potentially supported by driver
48 *
49 * @param oid Device OID
50 */
51 int NtwsDriver::isPotentialDevice(const TCHAR *oid)
52 {
53 return (_tcsncmp(oid, _T(".1.3.6.1.4.1.45.6.1.3.1."), 24) == 0) ? 127 : 0;
54 }
55
56 /**
57 * Check if given device is supported by driver
58 *
59 * @param snmp SNMP transport
60 * @param oid Device OID
61 */
62 bool NtwsDriver::isDeviceSupported(SNMP_Transport *snmp, const TCHAR *oid)
63 {
64 TCHAR buffer[1024];
65 return SnmpGet(snmp->getSnmpVersion(), snmp, _T(".1.3.6.1.4.1.45.6.1.4.2.1.1.0"), NULL, 0, buffer, sizeof(buffer), 0) == SNMP_ERR_SUCCESS;
66 }
67
68 /**
69 * Do additional checks on the device required by driver.
70 * Driver can set device's custom attributes from within
71 * this function.
72 *
73 * @param snmp SNMP transport
74 * @param attributes Node's custom attributes
75 */
76 void NtwsDriver::analyzeDevice(SNMP_Transport *snmp, const TCHAR *oid, StringMap *attributes, DriverData **driverData)
77 {
78 }
79
80 /**
81 * Get cluster mode for device (standalone / active / standby)
82 *
83 * @param snmp SNMP transport
84 * @param attributes Node custom attributes
85 * @param driverData optional pointer to user data
86 */
87 int NtwsDriver::getClusterMode(SNMP_Transport *snmp, StringMap *attributes, DriverData *driverData)
88 {
89 return CLUSTER_MODE_UNKNOWN;
90 }
91
92 /*
93 * Check switch for wireless capabilities
94 *
95 * @param snmp SNMP transport
96 * @param attributes Node custom attributes
97 * @param driverData optional pointer to user data
98 */
99 bool NtwsDriver::isWirelessController(SNMP_Transport *snmp, StringMap *attributes, DriverData *driverData)
100 {
101 return true;
102 }
103
104 /**
105 * Handler for access point enumeration - unadopted
106 */
107 static UINT32 HandlerAccessPointListUnadopted(UINT32 version, SNMP_Variable *var, SNMP_Transport *transport, void *arg)
108 {
109 ObjectArray<AccessPointInfo> *apList = (ObjectArray<AccessPointInfo> *)arg;
110
111 TCHAR model[128];
112 AccessPointInfo *info = new AccessPointInfo(0, (const BYTE *)"\x00\x00\x00\x00\x00\x00", InetAddress::INVALID, AP_UNADOPTED, NULL, NULL, var->getValueAsString(model, 128), NULL);
113 apList->add(info);
114
115 return SNMP_ERR_SUCCESS;
116 }
117
118 /**
119 * Handler for access point enumeration - adopted
120 */
121 static UINT32 HandlerAccessPointListAdopted(UINT32 version, SNMP_Variable *var, SNMP_Transport *transport, void *arg)
122 {
123 int ret = SNMP_ERR_SUCCESS;
124
125 ObjectArray<AccessPointInfo> *apList = (ObjectArray<AccessPointInfo> *)arg;
126
127 SNMP_ObjectId *name = var->getName();
128 size_t nameLen = name->getLength();
129
130 UINT32 oid[128];
131 memcpy(oid, name->getValue(), nameLen * sizeof(UINT32));
132
133 // get serial number - it's encoded in OID as <length>.<serial>
134 TCHAR serial[128];
135 UINT32 slen = oid[16];
136 for(UINT32 i = 0; i < slen; i++)
137 serial[i] = oid[i + 17];
138 serial[slen] = 0;
139
140 SNMP_PDU *request = new SNMP_PDU(SNMP_GET_REQUEST, SnmpNewRequestId(), version);
141
142 oid[15] = 6; // ntwsApStatApStatusModel
143 request->bindVariable(new SNMP_Variable(oid, nameLen));
144
145 oid[15] = 8; // ntwsApStatApStatusApName
146 request->bindVariable(new SNMP_Variable(oid, nameLen));
147
148 oid[15] = 10; // ntwsApStatApStatusIpAddress
149 request->bindVariable(new SNMP_Variable(oid, nameLen));
150
151 oid[15] = 13; // ntwsApStatApStatusManufacturerId
152 request->bindVariable(new SNMP_Variable(oid, nameLen));
153
154 oid[15] = 19; // ntwsApStatApStatusApNum
155 request->bindVariable(new SNMP_Variable(oid, nameLen));
156
157 SNMP_PDU *response;
158 if (transport->doRequest(request, &response, g_snmpTimeout, 3) == SNMP_ERR_SUCCESS)
159 {
160 if (response->getNumVariables() >= 5)
161 {
162 TCHAR model[256], name[256], vendor[256], ipAddr[32];
163 AccessPointInfo *ap =
164 new AccessPointInfo(
165 response->getVariable(4)->getValueAsUInt(),
166 var->getValue(),
167 ntohl(_t_inet_addr(response->getVariable(2)->getValueAsString(ipAddr, 32))),
168 AP_ADOPTED,
169 response->getVariable(1)->getValueAsString(name, 256),
170 response->getVariable(3)->getValueAsString(vendor, 256),
171 response->getVariable(0)->getValueAsString(model, 256),
172 serial);
173 apList->add(ap);
174 }
175 delete response;
176 }
177 delete request;
178
179 return ret;
180 }
181
182 /**
183 * Handler for radios enumeration
184 */
185 static UINT32 HandlerRadioList(UINT32 version, SNMP_Variable *var, SNMP_Transport *transport, void *arg)
186 {
187 AccessPointInfo *ap = (AccessPointInfo *)arg;
188
189 SNMP_ObjectId *name = var->getName();
190 size_t nameLen = name->getLength();
191
192 UINT32 oid[128];
193 memcpy(oid, name->getValue(), nameLen * sizeof(UINT32));
194
195 RadioInterfaceInfo rif;
196 memcpy(rif.macAddr, var->getValue(), MAC_ADDR_LENGTH);
197 rif.index = (int)oid[nameLen - 1];
198 _sntprintf(rif.name, sizeof(rif.name) / sizeof(TCHAR), _T("Radio%d"), rif.index);
199
200 SNMP_PDU *request = new SNMP_PDU(SNMP_GET_REQUEST, SnmpNewRequestId(), version);
201
202 oid[15] = 6; // ntwsApStatRadioStatusCurrentPowerLevel
203 request->bindVariable(new SNMP_Variable(oid, nameLen));
204
205 oid[15] = 7; // ntwsApStatRadioStatusCurrentChannelNum
206 request->bindVariable(new SNMP_Variable(oid, nameLen));
207
208 SNMP_PDU *response;
209 if (transport->doRequest(request, &response, g_snmpTimeout, 3) == SNMP_ERR_SUCCESS)
210 {
211 if (response->getNumVariables() >= 2)
212 {
213 rif.powerDBm = response->getVariable(0)->getValueAsInt();
214 rif.powerMW = (int)pow(10.0, (double)rif.powerDBm / 10.0);
215 rif.channel = response->getVariable(1)->getValueAsUInt();
216 ap->addRadioInterface(&rif);
217 }
218 delete response;
219 }
220 delete request;
221 return SNMP_ERR_SUCCESS;
222 }
223
224 /*
225 * Get access points
226 *
227 * @param snmp SNMP transport
228 * @param attributes Node custom attributes
229 * @param driverData optional pointer to user data
230 */
231 ObjectArray<AccessPointInfo> *NtwsDriver::getAccessPoints(SNMP_Transport *snmp, StringMap *attributes, DriverData *driverData)
232 {
233 ObjectArray<AccessPointInfo> *apList = new ObjectArray<AccessPointInfo>(0, 16, true);
234
235 // Adopted
236 if (SnmpWalk(snmp->getSnmpVersion(), snmp, _T(".1.3.6.1.4.1.45.6.1.4.5.1.1.2.1.2"),
237 HandlerAccessPointListAdopted, apList, FALSE) == SNMP_ERR_SUCCESS)
238 {
239 // Read radios by walking .1.3.6.1.4.1.45.6.1.4.5.1.1.4.1.3.<ap serial> (ntwsApStatRadioStatusBaseMac)
240 for(int i = 0; i < apList->size(); i++)
241 {
242 AccessPointInfo *ap = apList->get(i);
243
244 UINT32 oid[256] = { 1, 3, 6, 1, 4, 1, 45, 6, 1, 4, 5, 1, 1, 4, 1, 3 };
245 const TCHAR *serial = ap->getSerial();
246 oid[16] = (UINT32)_tcslen(serial);
247 for(UINT32 i = 0; i < oid[16]; i++)
248 oid[i + 17] = (UINT32)serial[i];
249 TCHAR rootOid[1024];
250 SNMPConvertOIDToText(oid[16] + 17, oid, rootOid, 1024);
251 SnmpWalk(snmp->getSnmpVersion(), snmp, rootOid, HandlerRadioList, ap, FALSE);
252 }
253 }
254 else
255 {
256 delete apList;
257 return NULL;
258 }
259
260 // Unadopted
261 if (SnmpWalk(snmp->getSnmpVersion(), snmp, _T(".1.3.6.1.4.1.45.6.1.4.15.1.2.1.2"),
262 HandlerAccessPointListUnadopted, apList, FALSE) != SNMP_ERR_SUCCESS)
263 {
264 delete apList;
265 return NULL;
266 }
267
268 return apList;
269 }
270
271 /**
272 * Handler for mobile units enumeration
273 */
274 static UINT32 HandlerWirelessStationList(UINT32 version, SNMP_Variable *var, SNMP_Transport *transport, void *arg)
275 {
276 int ret = SNMP_ERR_SUCCESS;
277
278 ObjectArray<WirelessStationInfo> *wsList = (ObjectArray<WirelessStationInfo> *)arg;
279
280 SNMP_ObjectId *name = var->getName();
281 size_t nameLen = name->getLength();
282 const UINT32 *value = name->getValue();
283
284 UINT32 oid[32];
285 memcpy(oid, value, nameLen * sizeof(value[0]));
286
287 UINT32 ipAddr;
288 oid[14] = 6; // wsCcRfMuIpAddr
289 ret = SnmpGet(version, transport, NULL, oid, sizeof(oid) / sizeof(oid[0]), &ipAddr, sizeof(ipAddr), 0);
290 UINT32 vlanInfex;
291 if (ret == SNMP_ERR_SUCCESS)
292 {
293 oid[14] = 4; // wsCcRfMuVlanIndex
294 ret = SnmpGet(version, transport, NULL, oid, sizeof(oid) / sizeof(oid[0]), &vlanInfex, sizeof(vlanInfex), 0);
295 }
296
297 UINT32 wlanInfex;
298 if (ret == SNMP_ERR_SUCCESS)
299 {
300 oid[14] = 2; // wsCcRfMuWlanIndex
301 ret = SnmpGet(version, transport, NULL, oid, sizeof(oid) / sizeof(oid[0]), &wlanInfex, sizeof(vlanInfex), 0);
302 }
303
304 UINT32 rfIndex;
305 if (ret == SNMP_ERR_SUCCESS)
306 {
307 oid[14] = 3; // wsCcRfMuRadioIndex
308 ret = SnmpGet(version, transport, NULL, oid, sizeof(oid) / sizeof(oid[0]), &rfIndex, sizeof(rfIndex), 0);
309 }
310
311 TCHAR ssid[MAX_OBJECT_NAME];
312 if (ret == SNMP_ERR_SUCCESS)
313 {
314 UINT32 wlanOid[] = { 1, 3, 6, 1, 4, 1, 388, 14, 3, 2, 1, 14, 1, 1, 4, 0 };
315 wlanOid[(sizeof(wlanOid) / sizeof(wlanOid[0])) - 1] = wlanInfex;
316
317 ret = SnmpGet(version, transport, NULL, wlanOid, sizeof(wlanOid) / sizeof(wlanOid[0]), ssid, sizeof(ssid), 0);
318 }
319
320 if (ret == SNMP_ERR_SUCCESS)
321 {
322 WirelessStationInfo *info = new WirelessStationInfo;
323 memset(info, 0, sizeof(WirelessStationInfo));
324
325 memcpy(info->macAddr, var->getValue(), MAC_ADDR_LENGTH);
326 info->ipAddr = ipAddr;
327 info->vlan = vlanInfex;
328 nx_strncpy(info->ssid, ssid, MAX_OBJECT_NAME);
329 info->rfIndex = rfIndex;
330 info->apMatchPolicy = AP_MATCH_BY_RFINDEX;
331
332 wsList->add(info);
333 }
334
335 return ret;
336 }
337
338 /*
339 *
340 * @param snmp SNMP transport
341 * @param attributes Node custom attributes
342 * @param driverData optional pointer to user data
343 */
344 ObjectArray<WirelessStationInfo> *NtwsDriver::getWirelessStations(SNMP_Transport *snmp, StringMap *attributes, DriverData *driverData)
345 {
346 ObjectArray<WirelessStationInfo> *wsList = new ObjectArray<WirelessStationInfo>(0, 16, true);
347
348 if (SnmpWalk(snmp->getSnmpVersion(), snmp, _T(".1.3.6.1.4.1.388.14.3.2.1.12.3.1.1"), // wsCcRfMuMac
349 HandlerWirelessStationList, wsList, FALSE) != SNMP_ERR_SUCCESS)
350 {
351 delete wsList;
352 wsList = NULL;
353 }
354
355 return wsList;
356 }
357
358 /**
359 * Driver entry point
360 */
361 DECLARE_NDD_ENTRY_POINT(s_driverName, NtwsDriver);
362
363 /**
364 * DLL entry point
365 */
366 #ifdef _WIN32
367
368 BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
369 {
370 if (dwReason == DLL_PROCESS_ATTACH)
371 {
372 DisableThreadLibraryCalls(hInstance);
373 }
374
375 return TRUE;
376 }
377
378 #endif