Fixed java methode description
[public/netxms.git] / src / server / core / node.cpp
CommitLineData
4d2c3a54 1/*
5039dede 2** NetXMS - Network Management System
a2d1dcb1 3** Copyright (C) 2003-2017 Raden Solutions
5039dede
AK
4**
5** This program is free software; you can redistribute it and/or modify
6** it under the terms of the GNU General Public License as published by
7** the Free Software Foundation; either version 2 of the License, or
8** (at your option) any later version.
9**
10** This program is distributed in the hope that it will be useful,
11** but WITHOUT ANY WARRANTY; without even the implied warranty of
12** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13** GNU General Public License for more details.
14**
15** You should have received a copy of the GNU General Public License
16** along with this program; if not, write to the Free Software
17** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18**
19** File: node.cpp
20**
21**/
22
23#include "nxcore.h"
24
7aad6641 25/**
ba756b1a
VK
26 * Externals
27 */
28extern UINT64 g_syslogMessagesReceived;
29extern UINT64 g_snmpTrapsReceived;
30
31/**
c50f77f7
VK
32 * Node class default constructor
33 */
6fd6de0a 34Node::Node() : DataCollectionTarget()
5039dede 35{
5f8890c1 36 m_primaryName[0] = 0;
db091a1f 37 m_status = STATUS_UNKNOWN;
e980db40
VK
38 m_type = NODE_TYPE_UNKNOWN;
39 m_subType[0] = 0;
5039dede 40 m_dwDynamicFlags = 0;
52c31148 41 m_zoneId = 0;
c42b4551
VK
42 m_agentPort = AGENT_LISTEN_PORT;
43 m_agentAuthMethod = AUTH_NONE;
9708eff4 44 m_agentCacheMode = AGENT_CACHE_DEFAULT;
5039dede
AK
45 m_szSharedSecret[0] = 0;
46 m_iStatusPollType = POLL_ICMP_PING;
5d2c5741 47 m_snmpVersion = SNMP_VERSION_1;
296ae03d 48 m_snmpPort = SNMP_DEFAULT_PORT;
5f8890c1 49 m_snmpSecurity = new SNMP_SecurityContext("public");
5039dede 50 m_szObjectId[0] = 0;
8573e935
VK
51 m_lastDiscoveryPoll = 0;
52 m_lastStatusPoll = 0;
53 m_lastConfigurationPoll = 0;
805171de 54 m_lastInstancePoll = 0;
5f8890c1 55 m_lastTopologyPoll = 0;
8573e935 56 m_lastRTUpdate = 0;
5f8890c1 57 m_downSince = 0;
71e4ed3a 58 m_bootTime = 0;
0ab347c0 59 m_agentUpTime = 0;
5039dede
AK
60 m_hPollerMutex = MutexCreate();
61 m_hAgentAccessMutex = MutexCreate();
1d0d82b3 62 m_hSmclpAccessMutex = MutexCreate();
5039dede 63 m_mutexRTAccess = MutexCreate();
5f8890c1
AK
64 m_mutexTopoAccess = MutexCreate();
65 m_snmpProxyConnectionLock = MutexCreate();
83191808
VK
66 m_agentConnection = NULL;
67 m_snmpProxyConnection = NULL;
1d0d82b3 68 m_smclpConnection = NULL;
5f8890c1
AK
69 m_lastAgentTrapId = 0;
70 m_lastSNMPTrapId = 0;
71 m_lastSyslogMessageId = 0;
42a3be4f 72 m_lastAgentPushRequestId = 0;
5039dede
AK
73 m_szAgentVersion[0] = 0;
74 m_szPlatformName[0] = 0;
5f8890c1
AK
75 m_sysDescription = NULL;
76 m_sysName = NULL;
77 m_sysContact = NULL;
78 m_sysLocation = NULL;
79 m_lldpNodeId = NULL;
80 m_lldpLocalPortInfo = NULL;
cc8ce218 81 m_paramList = NULL;
5f8890c1 82 m_tableList = NULL;
9208c84b
VK
83 m_pollerNode = 0;
84 m_agentProxy = 0;
5f8890c1 85 m_snmpProxy = 0;
9208c84b 86 m_icmpProxy = 0;
5039dede
AK
87 memset(m_qwLastEvents, 0, sizeof(QWORD) * MAX_LAST_EVENTS);
88 m_pRoutingTable = NULL;
8573e935
VK
89 m_failTimeSNMP = 0;
90 m_failTimeAgent = 0;
4e3133ee 91 m_lastAgentCommTime = 0;
a01c2a20 92 m_lastAgentConnectAttempt = 0;
5f8890c1
AK
93 m_linkLayerNeighbors = NULL;
94 m_vrrpInfo = NULL;
95 m_pTopology = NULL;
96 m_topologyRebuildTimestamp = 0;
97 m_iPendingStatus = -1;
98 m_iPollCount = 0;
99 m_iRequiredPollCount = 0; // Use system default
100 m_nUseIfXTable = IFXTABLE_DEFAULT; // Use system default
101 m_jobQueue = new ServerJobQueue();
102 m_fdb = NULL;
103 m_vlans = NULL;
104 m_wirelessStations = NULL;
105 m_adoptedApCount = 0;
106 m_totalApCount = 0;
107 m_driver = NULL;
108 m_driverData = NULL;
109 m_components = NULL;
110 m_softwarePackages = NULL;
111 m_winPerfObjects = NULL;
112 memset(m_baseBridgeAddress, 0, MAC_ADDR_LENGTH);
113 m_fileUpdateConn = NULL;
114 m_rackId = 0;
115 m_rackPosition = 0;
116 m_rackHeight = 1;
117 m_chassisId = 0;
118 m_syslogMessageCount = 0;
119 m_snmpTrapCount = 0;
120 m_sshLogin[0] = 0;
121 m_sshPassword[0] = 0;
122 m_sshProxy = 0;
191137b2
VK
123 m_portNumberingScheme = NDD_PN_UNKNOWN;
124 m_portRowCount = 0;
55d99dce 125 m_agentCompressionMode = NODE_AGENT_COMPRESSION_DEFAULT;
5039dede
AK
126}
127
c50f77f7
VK
128/**
129 * Constructor for new node object
130 */
de4c3060 131Node::Node(const InetAddress& addr, UINT32 dwFlags, UINT32 agentProxy, UINT32 snmpProxy, UINT32 icmpProxy, UINT32 sshProxy, UINT32 zoneId) : DataCollectionTarget()
5039dede 132{
c75e9ee4 133 addr.toString(m_primaryName);
db091a1f 134 m_status = STATUS_UNKNOWN;
e980db40
VK
135 m_type = NODE_TYPE_UNKNOWN;
136 m_subType[0] = 0;
c75e9ee4 137 m_ipAddress = addr;
487cde95 138 m_flags = dwFlags;
5039dede 139 m_dwDynamicFlags = 0;
de4c3060 140 m_zoneId = zoneId;
c42b4551
VK
141 m_agentPort = AGENT_LISTEN_PORT;
142 m_agentAuthMethod = AUTH_NONE;
9708eff4 143 m_agentCacheMode = AGENT_CACHE_DEFAULT;
5039dede
AK
144 m_szSharedSecret[0] = 0;
145 m_iStatusPollType = POLL_ICMP_PING;
5d2c5741 146 m_snmpVersion = SNMP_VERSION_1;
296ae03d 147 m_snmpPort = SNMP_DEFAULT_PORT;
5f8890c1 148 m_snmpSecurity = new SNMP_SecurityContext("public");
c75e9ee4 149 addr.toString(m_name); // Make default name from IP address
5039dede 150 m_szObjectId[0] = 0;
8573e935
VK
151 m_lastDiscoveryPoll = 0;
152 m_lastStatusPoll = 0;
153 m_lastConfigurationPoll = 0;
805171de 154 m_lastInstancePoll = 0;
5f8890c1 155 m_lastTopologyPoll = 0;
8573e935 156 m_lastRTUpdate = 0;
5f8890c1 157 m_downSince = 0;
71e4ed3a 158 m_bootTime = 0;
0ab347c0 159 m_agentUpTime = 0;
5039dede
AK
160 m_hPollerMutex = MutexCreate();
161 m_hAgentAccessMutex = MutexCreate();
1d0d82b3 162 m_hSmclpAccessMutex = MutexCreate();
5039dede 163 m_mutexRTAccess = MutexCreate();
5f8890c1 164 m_mutexTopoAccess = MutexCreate();
83191808
VK
165 m_snmpProxyConnectionLock = MutexCreate();
166 m_agentConnection = NULL;
167 m_snmpProxyConnection = NULL;
1d0d82b3 168 m_smclpConnection = NULL;
5f8890c1
AK
169 m_lastAgentTrapId = 0;
170 m_lastSNMPTrapId = 0;
171 m_lastSyslogMessageId = 0;
42a3be4f 172 m_lastAgentPushRequestId = 0;
5039dede
AK
173 m_szAgentVersion[0] = 0;
174 m_szPlatformName[0] = 0;
5f8890c1
AK
175 m_sysDescription = NULL;
176 m_sysName = NULL;
cf38357f
VK
177 m_sysContact = NULL;
178 m_sysLocation = NULL;
5f8890c1
AK
179 m_lldpNodeId = NULL;
180 m_lldpLocalPortInfo = NULL;
cc8ce218 181 m_paramList = NULL;
5f8890c1 182 m_tableList = NULL;
9208c84b
VK
183 m_pollerNode = 0;
184 m_agentProxy = agentProxy;
5f8890c1 185 m_snmpProxy = snmpProxy;
de4c3060 186 m_icmpProxy = icmpProxy;
5039dede 187 memset(m_qwLastEvents, 0, sizeof(QWORD) * MAX_LAST_EVENTS);
01152a54 188 m_isHidden = true;
5039dede 189 m_pRoutingTable = NULL;
8573e935
VK
190 m_failTimeSNMP = 0;
191 m_failTimeAgent = 0;
4e3133ee 192 m_lastAgentCommTime = 0;
a01c2a20 193 m_lastAgentConnectAttempt = 0;
5f8890c1
AK
194 m_linkLayerNeighbors = NULL;
195 m_vrrpInfo = NULL;
196 m_pTopology = NULL;
197 m_topologyRebuildTimestamp = 0;
198 m_iPendingStatus = -1;
199 m_iPollCount = 0;
200 m_iRequiredPollCount = 0; // Use system default
201 m_nUseIfXTable = IFXTABLE_DEFAULT; // Use system default
202 m_jobQueue = new ServerJobQueue();
203 m_fdb = NULL;
204 m_vlans = NULL;
205 m_wirelessStations = NULL;
206 m_adoptedApCount = 0;
207 m_totalApCount = 0;
208 m_driver = NULL;
209 m_driverData = NULL;
210 m_components = NULL;
211 m_softwarePackages = NULL;
212 m_winPerfObjects = NULL;
213 memset(m_baseBridgeAddress, 0, MAC_ADDR_LENGTH);
214 m_fileUpdateConn = NULL;
de674bb6
VK
215 m_rackId = 0;
216 m_rackPosition = 0;
217 m_rackHeight = 1;
e4926628 218 m_chassisId = 0;
ba756b1a
VK
219 m_syslogMessageCount = 0;
220 m_snmpTrapCount = 0;
241541f4
VK
221 m_sshLogin[0] = 0;
222 m_sshPassword[0] = 0;
de4c3060 223 m_sshProxy = sshProxy;
191137b2
VK
224 m_portNumberingScheme = NDD_PN_UNKNOWN;
225 m_portRowCount = 0;
55d99dce 226 m_agentCompressionMode = NODE_AGENT_COMPRESSION_DEFAULT;
5039dede
AK
227}
228
c50f77f7
VK
229/**
230 * Node destructor
231 */
5039dede
AK
232Node::~Node()
233{
5f8890c1 234 delete m_driverData;
5039dede
AK
235 MutexDestroy(m_hPollerMutex);
236 MutexDestroy(m_hAgentAccessMutex);
1d0d82b3 237 MutexDestroy(m_hSmclpAccessMutex);
5039dede 238 MutexDestroy(m_mutexRTAccess);
5f8890c1
AK
239 MutexDestroy(m_mutexTopoAccess);
240 MutexDestroy(m_snmpProxyConnectionLock);
241 if (m_agentConnection != NULL)
242 m_agentConnection->decRefCount();
243 if (m_snmpProxyConnection != NULL)
244 m_snmpProxyConnection->decRefCount();
1d0d82b3 245 delete m_smclpConnection;
cc8ce218 246 delete m_paramList;
5f8890c1
AK
247 delete m_tableList;
248 safe_free(m_sysDescription);
5039dede 249 DestroyRoutingTable(m_pRoutingTable);
5f8890c1
AK
250 if (m_linkLayerNeighbors != NULL)
251 m_linkLayerNeighbors->decRefCount();
252 delete m_vrrpInfo;
253 delete m_pTopology;
254 delete m_jobQueue;
255 delete m_snmpSecurity;
256 if (m_fdb != NULL)
257 m_fdb->decRefCount();
258 if (m_vlans != NULL)
259 m_vlans->decRefCount();
260 delete m_wirelessStations;
33dfe57e
VK
261 if (m_components != NULL)
262 m_components->decRefCount();
5f8890c1
AK
263 delete m_lldpLocalPortInfo;
264 delete m_softwarePackages;
265 delete m_winPerfObjects;
266 safe_free(m_sysName);
267 safe_free(m_sysContact);
268 safe_free(m_sysLocation);
5039dede
AK
269}
270
c50f77f7
VK
271/**
272 * Create object from database data
273 */
9bd1bace 274bool Node::loadFromDatabase(DB_HANDLE hdb, UINT32 dwId)
5039dede 275{
5039dede 276 int i, iNumRows;
967893bb 277 UINT32 dwSubnetId;
5039dede 278 NetObj *pObject;
9bd1bace 279 bool bResult = false;
5039dede 280
c42b4551 281 m_id = dwId;
5039dede 282
9bd1bace 283 if (!loadCommonProperties(hdb))
5039dede 284 {
35f836fe 285 DbgPrintf(2, _T("Cannot load common properties for node object %d"), dwId);
9bd1bace 286 return false;
5039dede
AK
287 }
288
5f8890c1
AK
289 DB_STATEMENT hStmt = DBPrepare(hdb,
290 _T("SELECT primary_name,primary_ip,node_flags,")
4866d57b
VK
291 _T("snmp_version,auth_method,secret,")
292 _T("agent_port,status_poll_type,snmp_oid,agent_version,")
293 _T("platform_name,poller_node_id,zone_guid,")
294 _T("proxy_node,snmp_proxy,required_polls,uname,")
5f8890c1
AK
295 _T("use_ifxtable,snmp_port,community,usm_auth_password,")
296 _T("usm_priv_password,usm_methods,snmp_sys_name,bridge_base_addr,")
9708eff4 297 _T("runtime_flags,down_since,boot_time,driver_name,icmp_proxy,")
de674bb6 298 _T("agent_cache_mode,snmp_sys_contact,snmp_sys_location,")
4e3133ee 299 _T("rack_id,rack_image,rack_position,rack_height,")
e980db40 300 _T("last_agent_comm_time,syslog_msg_count,snmp_trap_count,")
55d99dce
VK
301 _T("node_type,node_subtype,ssh_login,ssh_password,ssh_proxy,")
302 _T("port_rows,port_numbering_scheme,agent_comp_mode FROM nodes WHERE id=?"));
5f8890c1
AK
303 if (hStmt == NULL)
304 return false;
4866d57b 305
5f8890c1
AK
306 DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, dwId);
307 DB_RESULT hResult = DBSelectPrepared(hStmt);
e2babedf 308 if (hResult == NULL)
5f8890c1
AK
309 {
310 DBFreeStatement(hStmt);
9bd1bace 311 return false; // Query failed
5f8890c1 312 }
5039dede
AK
313
314 if (DBGetNumRows(hResult) == 0)
315 {
316 DBFreeResult(hResult);
5f8890c1 317 DBFreeStatement(hStmt);
5d2c5741 318 DbgPrintf(2, _T("Missing record in \"nodes\" table for node object %d"), dwId);
9bd1bace 319 return false;
5039dede
AK
320 }
321
5ad2167d 322 DBGetField(hResult, 0, 0, m_primaryName, MAX_DNS_NAME);
c75e9ee4 323 m_ipAddress = DBGetFieldInetAddr(hResult, 0, 1);
487cde95 324 m_flags = DBGetFieldULong(hResult, 0, 2);
5ad2167d 325 m_snmpVersion = DBGetFieldLong(hResult, 0, 3);
c42b4551 326 m_agentAuthMethod = (WORD)DBGetFieldLong(hResult, 0, 4);
5ad2167d 327 DBGetField(hResult, 0, 5, m_szSharedSecret, MAX_SECRET_LENGTH);
c42b4551 328 m_agentPort = (WORD)DBGetFieldLong(hResult, 0, 6);
5ad2167d
VK
329 m_iStatusPollType = DBGetFieldLong(hResult, 0, 7);
330 DBGetField(hResult, 0, 8, m_szObjectId, MAX_OID_LEN * 4);
5d2c5741 331 DBGetField(hResult, 0, 9, m_szAgentVersion, MAX_AGENT_VERSION_LEN);
5d2c5741 332 DBGetField(hResult, 0, 10, m_szPlatformName, MAX_PLATFORM_NAME_LEN);
9208c84b 333 m_pollerNode = DBGetFieldULong(hResult, 0, 11);
52c31148 334 m_zoneId = DBGetFieldULong(hResult, 0, 12);
9208c84b
VK
335 m_agentProxy = DBGetFieldULong(hResult, 0, 13);
336 m_snmpProxy = DBGetFieldULong(hResult, 0, 14);
5d2c5741 337 m_iRequiredPollCount = DBGetFieldLong(hResult, 0, 15);
0ecc2200 338 m_sysDescription = DBGetField(hResult, 0, 16, NULL, 0);
5d2c5741 339 m_nUseIfXTable = (BYTE)DBGetFieldLong(hResult, 0, 17);
5f8890c1
AK
340 m_snmpPort = (WORD)DBGetFieldLong(hResult, 0, 18);
341
342 // SNMP authentication parameters
343 char snmpAuthObject[256], snmpAuthPassword[256], snmpPrivPassword[256];
344 DBGetFieldA(hResult, 0, 19, snmpAuthObject, 256);
345 DBGetFieldA(hResult, 0, 20, snmpAuthPassword, 256);
346 DBGetFieldA(hResult, 0, 21, snmpPrivPassword, 256);
347 int snmpMethods = DBGetFieldLong(hResult, 0, 22);
348 delete m_snmpSecurity;
349 m_snmpSecurity = new SNMP_SecurityContext(snmpAuthObject, snmpAuthPassword, snmpPrivPassword, snmpMethods & 0xFF, snmpMethods >> 8);
350 m_snmpSecurity->setSecurityModel((m_snmpVersion == SNMP_VERSION_3) ? SNMP_SECURITY_MODEL_USM : SNMP_SECURITY_MODEL_V2C);
5d2c5741 351
5f8890c1 352 m_sysName = DBGetField(hResult, 0, 23, NULL, 0);
d74c80ea 353
5f8890c1
AK
354 TCHAR baseAddr[16];
355 TCHAR *value = DBGetField(hResult, 0, 24, baseAddr, 16);
356 if (value != NULL)
357 StrToBin(value, m_baseBridgeAddress, MAC_ADDR_LENGTH);
3eab63f2 358
5f8890c1
AK
359 m_dwDynamicFlags = DBGetFieldULong(hResult, 0, 25);
360 m_dwDynamicFlags &= NDF_PERSISTENT; // Clear out all non-persistent runtime flags
4866d57b 361
5f8890c1 362 m_downSince = DBGetFieldLong(hResult, 0, 26);
71e4ed3a 363 m_bootTime = DBGetFieldLong(hResult, 0, 27);
dd42ad0a 364
5f8890c1
AK
365 // Setup driver
366 TCHAR driverName[34];
367 DBGetField(hResult, 0, 28, driverName, 34);
368 StrStrip(driverName);
369 if (driverName[0] != 0)
370 m_driver = FindDriverByName(driverName);
28e1575f 371
9208c84b 372 m_icmpProxy = DBGetFieldULong(hResult, 0, 29);
9708eff4
VK
373 m_agentCacheMode = (INT16)DBGetFieldLong(hResult, 0, 30);
374 if ((m_agentCacheMode != AGENT_CACHE_ON) && (m_agentCacheMode != AGENT_CACHE_OFF))
375 m_agentCacheMode = AGENT_CACHE_DEFAULT;
9208c84b 376
cf38357f
VK
377 m_sysContact = DBGetField(hResult, 0, 31, NULL, 0);
378 m_sysLocation = DBGetField(hResult, 0, 32, NULL, 0);
379
de674bb6
VK
380 m_rackId = DBGetFieldULong(hResult, 0, 33);
381 m_rackImage = DBGetFieldGUID(hResult, 0, 34);
382 m_rackPosition = (INT16)DBGetFieldLong(hResult, 0, 35);
383 m_rackHeight = (INT16)DBGetFieldLong(hResult, 0, 36);
4e3133ee 384 m_lastAgentCommTime = DBGetFieldLong(hResult, 0, 37);
ba756b1a
VK
385 m_syslogMessageCount = DBGetFieldInt64(hResult, 0, 38);
386 m_snmpTrapCount = DBGetFieldInt64(hResult, 0, 39);
e980db40
VK
387 m_type = (NodeType)DBGetFieldLong(hResult, 0, 40);
388 DBGetField(hResult, 0, 41, m_subType, MAX_NODE_SUBTYPE_LENGTH);
2223a4d7
VK
389 DBGetField(hResult, 0, 42, m_sshLogin, MAX_SSH_LOGIN_LEN);
390 DBGetField(hResult, 0, 43, m_sshPassword, MAX_SSH_PASSWORD_LEN);
241541f4 391 m_sshProxy = DBGetFieldULong(hResult, 0, 44);
191137b2
VK
392 m_portRowCount = DBGetFieldULong(hResult, 0, 45);
393 m_portNumberingScheme = DBGetFieldULong(hResult, 0, 46);
55d99dce 394 m_agentCompressionMode = (INT16)DBGetFieldLong(hResult, 0, 47);
de674bb6 395
5039dede 396 DBFreeResult(hResult);
5f8890c1 397 DBFreeStatement(hStmt);
5039dede 398
01152a54 399 if (!m_isDeleted)
5039dede
AK
400 {
401 // Link node to subnets
5f8890c1
AK
402 hStmt = DBPrepare(hdb, _T("SELECT subnet_id FROM nsmap WHERE node_id=?"));
403 if (hStmt == NULL)
404 return false;
92c51b1d 405
5f8890c1 406 DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, m_id);
92c51b1d 407 hResult = DBSelectPrepared(hStmt);
5039dede 408 if (hResult == NULL)
5f8890c1
AK
409 {
410 DBFreeStatement(hStmt);
9bd1bace 411 return false; // Query failed
5f8890c1 412 }
5039dede
AK
413
414 iNumRows = DBGetNumRows(hResult);
5039dede
AK
415 for(i = 0; i < iNumRows; i++)
416 {
417 dwSubnetId = DBGetFieldULong(hResult, i, 0);
418 pObject = FindObjectById(dwSubnetId);
419 if (pObject == NULL)
420 {
421 nxlog_write(MSG_INVALID_SUBNET_ID, EVENTLOG_ERROR_TYPE, "dd", dwId, dwSubnetId);
422 break;
423 }
c42b4551 424 else if (pObject->getObjectClass() != OBJECT_SUBNET)
5039dede
AK
425 {
426 nxlog_write(MSG_SUBNET_NOT_SUBNET, EVENTLOG_ERROR_TYPE, "dd", dwId, dwSubnetId);
427 break;
428 }
429 else
430 {
1f8be1f4
VK
431 pObject->addChild(this);
432 addParent(pObject);
5039dede
AK
433 }
434 }
435
436 DBFreeResult(hResult);
5f8890c1 437 DBFreeStatement(hStmt);
92c51b1d 438
5f8890c1 439 loadItemsFromDB(hdb);
9bd1bace 440 loadACLFromDB(hdb);
5039dede
AK
441
442 // Walk through all items in the node and load appropriate thresholds
5f8890c1 443 bResult = true;
16d6f798 444 for(i = 0; i < m_dcObjects->size(); i++)
de674bb6 445 {
9bd1bace 446 if (!m_dcObjects->get(i)->loadThresholdsFromDB(hdb))
5039dede 447 {
5d2c5741 448 DbgPrintf(3, _T("Cannot load thresholds for DCI %d of node %d (%s)"),
c42b4551 449 m_dcObjects->get(i)->getId(), dwId, m_name);
9bd1bace 450 bResult = false;
5039dede 451 }
de674bb6
VK
452 }
453
e4926628
VK
454 updatePhysicalContainerBinding(OBJECT_RACK, m_rackId);
455 updatePhysicalContainerBinding(OBJECT_CHASSIS, m_chassisId);
5039dede
AK
456 }
457 else
458 {
9bd1bace 459 bResult = true;
5039dede
AK
460 }
461
462 return bResult;
463}
464
c50f77f7
VK
465/**
466 * Save object to database
467 */
c42b4551 468BOOL Node::saveToDatabase(DB_HANDLE hdb)
5039dede 469{
5039dede 470 // Lock object's access
c42b4551 471 lockProperties();
5039dede 472
28e1575f 473 if (!saveCommonProperties(hdb))
5f8890c1
AK
474 {
475 unlockProperties();
476 return FALSE;
477 }
5039dede 478
5039dede 479 // Form and execute INSERT or UPDATE query
5f8890c1
AK
480 int snmpMethods = m_snmpSecurity->getAuthMethod() | (m_snmpSecurity->getPrivMethod() << 8);
481 DB_STATEMENT hStmt;
c42b4551 482 if (IsDatabaseRecordExist(hdb, _T("nodes"), _T("id"), m_id))
5f8890c1
AK
483 {
484 hStmt = DBPrepare(hdb,
485 _T("UPDATE nodes SET primary_ip=?,primary_name=?,snmp_port=?,node_flags=?,snmp_version=?,community=?,")
28e1575f 486 _T("status_poll_type=?,agent_port=?,auth_method=?,secret=?,snmp_oid=?,uname=?,agent_version=?,")
5f8890c1
AK
487 _T("platform_name=?,poller_node_id=?,zone_guid=?,proxy_node=?,snmp_proxy=?,icmp_proxy=?,required_polls=?,")
488 _T("use_ifxtable=?,usm_auth_password=?,usm_priv_password=?,usm_methods=?,snmp_sys_name=?,bridge_base_addr=?,")
489 _T("runtime_flags=?,down_since=?,driver_name=?,rack_image=?,rack_position=?,rack_height=?,rack_id=?,boot_time=?,")
ba756b1a 490 _T("agent_cache_mode=?,snmp_sys_contact=?,snmp_sys_location=?,last_agent_comm_time=?,")
86339b28 491 _T("syslog_msg_count=?,snmp_trap_count=?,node_type=?,node_subtype=?,ssh_login=?,ssh_password=?,")
55d99dce 492 _T("ssh_proxy=?,chassis_id=?,port_rows=?,port_numbering_scheme=?,agent_comp_mode=? WHERE id=?"));
5f8890c1 493 }
ba89fed2 494 else
5f8890c1
AK
495 {
496 hStmt = DBPrepare(hdb,
497 _T("INSERT INTO nodes (primary_ip,primary_name,snmp_port,node_flags,snmp_version,community,status_poll_type,")
498 _T("agent_port,auth_method,secret,snmp_oid,uname,agent_version,platform_name,poller_node_id,zone_guid,")
499 _T("proxy_node,snmp_proxy,icmp_proxy,required_polls,use_ifxtable,usm_auth_password,usm_priv_password,usm_methods,")
500 _T("snmp_sys_name,bridge_base_addr,runtime_flags,down_since,driver_name,rack_image,rack_position,rack_height,rack_id,boot_time,")
e980db40 501 _T("agent_cache_mode,snmp_sys_contact,snmp_sys_location,last_agent_comm_time,syslog_msg_count,snmp_trap_count,")
55d99dce
VK
502 _T("node_type,node_subtype,ssh_login,ssh_password,ssh_proxy,chassis_id,port_rows,port_numbering_scheme,agent_comp_mode,id) ")
503 _T("VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"));
5f8890c1
AK
504 }
505 if (hStmt == NULL)
506 {
507 unlockProperties();
508 return FALSE;
509 }
28e1575f 510
55d99dce 511 TCHAR ipAddr[64], baseAddress[16], cacheMode[16], compressionMode[16];
28e1575f 512
5f8890c1
AK
513 DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, m_ipAddress.toString(ipAddr), DB_BIND_STATIC);
514 DBBind(hStmt, 2, DB_SQLTYPE_VARCHAR, m_primaryName, DB_BIND_STATIC);
515 DBBind(hStmt, 3, DB_SQLTYPE_INTEGER, (LONG)m_snmpPort);
516 DBBind(hStmt, 4, DB_SQLTYPE_INTEGER, m_flags);
517 DBBind(hStmt, 5, DB_SQLTYPE_INTEGER, (LONG)m_snmpVersion);
28e1575f 518#ifdef UNICODE
5f8890c1 519 DBBind(hStmt, 6, DB_SQLTYPE_VARCHAR, WideStringFromMBString(m_snmpSecurity->getCommunity()), DB_BIND_DYNAMIC);
28e1575f 520#else
5f8890c1 521 DBBind(hStmt, 6, DB_SQLTYPE_VARCHAR, m_snmpSecurity->getCommunity(), DB_BIND_STATIC);
28e1575f 522#endif
5f8890c1
AK
523 DBBind(hStmt, 7, DB_SQLTYPE_INTEGER, (LONG)m_iStatusPollType);
524 DBBind(hStmt, 8, DB_SQLTYPE_INTEGER, (LONG)m_agentPort);
525 DBBind(hStmt, 9, DB_SQLTYPE_INTEGER, (LONG)m_agentAuthMethod);
526 DBBind(hStmt, 10, DB_SQLTYPE_VARCHAR, m_szSharedSecret, DB_BIND_STATIC);
527 DBBind(hStmt, 11, DB_SQLTYPE_VARCHAR, m_szObjectId, DB_BIND_STATIC);
528 DBBind(hStmt, 12, DB_SQLTYPE_VARCHAR, m_sysDescription, DB_BIND_STATIC);
529 DBBind(hStmt, 13, DB_SQLTYPE_VARCHAR, m_szAgentVersion, DB_BIND_STATIC);
530 DBBind(hStmt, 14, DB_SQLTYPE_VARCHAR, m_szPlatformName, DB_BIND_STATIC);
531 DBBind(hStmt, 15, DB_SQLTYPE_INTEGER, m_pollerNode);
532 DBBind(hStmt, 16, DB_SQLTYPE_INTEGER, m_zoneId);
533 DBBind(hStmt, 17, DB_SQLTYPE_INTEGER, m_agentProxy);
534 DBBind(hStmt, 18, DB_SQLTYPE_INTEGER, m_snmpProxy);
535 DBBind(hStmt, 19, DB_SQLTYPE_INTEGER, m_icmpProxy);
536 DBBind(hStmt, 20, DB_SQLTYPE_INTEGER, (LONG)m_iRequiredPollCount);
537 DBBind(hStmt, 21, DB_SQLTYPE_INTEGER, (LONG)m_nUseIfXTable);
28e1575f 538#ifdef UNICODE
5f8890c1
AK
539 DBBind(hStmt, 22, DB_SQLTYPE_VARCHAR, WideStringFromMBString(m_snmpSecurity->getAuthPassword()), DB_BIND_DYNAMIC);
540 DBBind(hStmt, 23, DB_SQLTYPE_VARCHAR, WideStringFromMBString(m_snmpSecurity->getPrivPassword()), DB_BIND_DYNAMIC);
28e1575f 541#else
5f8890c1
AK
542 DBBind(hStmt, 22, DB_SQLTYPE_VARCHAR, m_snmpSecurity->getAuthPassword(), DB_BIND_STATIC);
543 DBBind(hStmt, 23, DB_SQLTYPE_VARCHAR, m_snmpSecurity->getPrivPassword(), DB_BIND_STATIC);
28e1575f 544#endif
5f8890c1
AK
545 DBBind(hStmt, 24, DB_SQLTYPE_INTEGER, (LONG)snmpMethods);
546 DBBind(hStmt, 25, DB_SQLTYPE_VARCHAR, m_sysName, DB_BIND_STATIC);
547 DBBind(hStmt, 26, DB_SQLTYPE_VARCHAR, BinToStr(m_baseBridgeAddress, MAC_ADDR_LENGTH, baseAddress), DB_BIND_STATIC);
548 DBBind(hStmt, 27, DB_SQLTYPE_INTEGER, m_dwDynamicFlags);
549 DBBind(hStmt, 28, DB_SQLTYPE_INTEGER, (LONG)m_downSince);
550 DBBind(hStmt, 29, DB_SQLTYPE_VARCHAR, (m_driver != NULL) ? m_driver->getName() : _T(""), DB_BIND_STATIC);
551 DBBind(hStmt, 30, DB_SQLTYPE_VARCHAR, m_rackImage); // rack image
552 DBBind(hStmt, 31, DB_SQLTYPE_INTEGER, m_rackPosition); // rack position
de674bb6 553 DBBind(hStmt, 32, DB_SQLTYPE_INTEGER, m_rackHeight); // device height in rack units
5f8890c1
AK
554 DBBind(hStmt, 33, DB_SQLTYPE_INTEGER, m_rackId); // rack ID
555 DBBind(hStmt, 34, DB_SQLTYPE_INTEGER, (LONG)m_bootTime);
55d99dce 556 DBBind(hStmt, 35, DB_SQLTYPE_VARCHAR, _itot(m_agentCacheMode, cacheMode, 10), DB_BIND_STATIC, 1);
de674bb6
VK
557 DBBind(hStmt, 36, DB_SQLTYPE_VARCHAR, m_sysContact, DB_BIND_STATIC);
558 DBBind(hStmt, 37, DB_SQLTYPE_VARCHAR, m_sysLocation, DB_BIND_STATIC);
5f8890c1 559 DBBind(hStmt, 38, DB_SQLTYPE_INTEGER, (LONG)m_lastAgentCommTime);
ba756b1a
VK
560 DBBind(hStmt, 39, DB_SQLTYPE_BIGINT, m_syslogMessageCount);
561 DBBind(hStmt, 40, DB_SQLTYPE_BIGINT, m_snmpTrapCount);
e980db40
VK
562 DBBind(hStmt, 41, DB_SQLTYPE_INTEGER, (INT32)m_type);
563 DBBind(hStmt, 42, DB_SQLTYPE_VARCHAR, m_subType, DB_BIND_STATIC);
241541f4
VK
564 DBBind(hStmt, 43, DB_SQLTYPE_VARCHAR, m_sshLogin, DB_BIND_STATIC);
565 DBBind(hStmt, 44, DB_SQLTYPE_VARCHAR, m_sshPassword, DB_BIND_STATIC);
566 DBBind(hStmt, 45, DB_SQLTYPE_INTEGER, m_sshProxy);
86339b28 567 DBBind(hStmt, 46, DB_SQLTYPE_INTEGER, m_chassisId);
06759600
VK
568 DBBind(hStmt, 47, DB_SQLTYPE_INTEGER, m_portRowCount);
569 DBBind(hStmt, 48, DB_SQLTYPE_INTEGER, m_portNumberingScheme);
55d99dce
VK
570 DBBind(hStmt, 49, DB_SQLTYPE_VARCHAR, _itot(m_agentCompressionMode, compressionMode, 10), DB_BIND_STATIC, 1);
571 DBBind(hStmt, 50, DB_SQLTYPE_INTEGER, m_id);
28e1575f 572
5f8890c1
AK
573 BOOL bResult = DBExecute(hStmt);
574 DBFreeStatement(hStmt);
5039dede 575
7c521895 576 // Save access list
89135050 577 saveACLToDB(hdb);
7c521895 578
c42b4551 579 unlockProperties();
7c521895 580
5039dede
AK
581 // Save data collection items
582 if (bResult)
583 {
5f8890c1 584 lockDciAccess(false);
16d6f798 585 for(int i = 0; i < m_dcObjects->size(); i++)
e7450f3b 586 m_dcObjects->get(i)->saveToDatabase(hdb);
5f8890c1 587 unlockDciAccess();
5039dede
AK
588 }
589
5f8890c1
AK
590 // Clear modifications flag
591 lockProperties();
01152a54 592 m_isModified = false;
5f8890c1 593 unlockProperties();
5039dede 594
5f8890c1 595 return bResult;
5039dede
AK
596}
597
171c2fd6
VK
598/**
599 * Delete object from database
600 */
c42b4551 601bool Node::deleteFromDatabase(DB_HANDLE hdb)
5039dede 602{
c42b4551 603 bool success = DataCollectionTarget::deleteFromDatabase(hdb);
22ee6d97
VK
604 if (success)
605 success = executeQueryOnObject(hdb, _T("DELETE FROM nodes WHERE id=?"));
606 if (success)
607 success = executeQueryOnObject(hdb, _T("DELETE FROM nsmap WHERE node_id=?"));
608 return success;
5039dede
AK
609}
610
80e0db05
VK
611/**
612 * Get ARP cache from node
613 */
7c521895 614ARP_CACHE *Node::getArpCache()
5039dede
AK
615{
616 ARP_CACHE *pArpCache = NULL;
617
487cde95 618 if (m_flags & NF_IS_LOCAL_MGMT)
5039dede
AK
619 {
620 pArpCache = GetLocalArpCache();
621 }
487cde95 622 else if (m_flags & NF_IS_NATIVE_AGENT)
5039dede 623 {
7c521895
VK
624 agentLock();
625 if (connectToAgent())
83191808 626 pArpCache = m_agentConnection->getArpCache();
7c521895 627 agentUnlock();
5039dede 628 }
487cde95 629 else if (m_flags & NF_IS_SNMP)
5039dede 630 {
5f8890c1 631 SNMP_Transport *pTransport;
5039dede 632
5f8890c1
AK
633 pTransport = createSnmpTransport();
634 if (pTransport != NULL)
635 {
636 pArpCache = SnmpGetArpCache(m_snmpVersion, pTransport);
637 delete pTransport;
638 }
5039dede
AK
639 }
640
641 return pArpCache;
642}
643
80e0db05
VK
644/**
645 * Get list of interfaces from node
646 */
98762401 647InterfaceList *Node::getInterfaceList()
5039dede 648{
98762401 649 InterfaceList *pIfList = NULL;
5039dede 650
487cde95 651 if ((m_flags & NF_IS_NATIVE_AGENT) && (!(m_flags & NF_DISABLE_NXCP)))
5039dede 652 {
7c521895
VK
653 agentLock();
654 if (connectToAgent())
5039dede 655 {
83191808 656 pIfList = m_agentConnection->getInterfaceList();
5039dede 657 }
7c521895 658 agentUnlock();
5039dede 659 }
487cde95 660 if ((pIfList == NULL) && (m_flags & NF_IS_LOCAL_MGMT))
b741f151
VK
661 {
662 pIfList = GetLocalInterfaceList();
663 }
487cde95
VK
664 if ((pIfList == NULL) && (m_flags & NF_IS_SNMP) &&
665 (!(m_flags & NF_DISABLE_SNMP)) && (m_driver != NULL))
5039dede 666 {
5f8890c1
AK
667 SNMP_Transport *pTransport = createSnmpTransport();
668 if (pTransport != NULL)
669 {
670 bool useIfXTable;
671 if (m_nUseIfXTable == IFXTABLE_DEFAULT)
672 {
673 useIfXTable = (ConfigReadInt(_T("UseIfXTable"), 1) != 0) ? true : false;
674 }
675 else
676 {
677 useIfXTable = (m_nUseIfXTable == IFXTABLE_ENABLED) ? true : false;
678 }
679
680 int useAliases = ConfigReadInt(_T("UseInterfaceAliases"), 0);
681 pIfList = m_driver->getInterfaces(pTransport, &m_customAttributes, m_driverData, useAliases, useIfXTable);
682
683 if ((pIfList != NULL) && (m_flags & NF_IS_BRIDGE))
684 {
685 BridgeMapPorts(pTransport, pIfList);
686 }
687 delete pTransport;
688 }
5039dede
AK
689 }
690
691 if (pIfList != NULL)
5f8890c1 692 {
024c3faf 693 checkInterfaceNames(pIfList);
5f8890c1
AK
694 addVrrpInterfaces(pIfList);
695 }
5039dede
AK
696
697 return pIfList;
698}
699
6fd6de0a
VK
700/**
701 * Add VRRP interfaces to interface list
702 */
98762401 703void Node::addVrrpInterfaces(InterfaceList *ifList)
0d75ea88 704{
5f8890c1
AK
705 int i, j, k;
706 TCHAR buffer[32];
0d75ea88 707
5f8890c1
AK
708 lockProperties();
709 if (m_vrrpInfo != NULL)
710 {
711 DbgPrintf(6, _T("Node::addVrrpInterfaces(node=%s [%d]): m_vrrpInfo->size()=%d"), m_name, (int)m_id, m_vrrpInfo->size());
0d75ea88 712
5f8890c1
AK
713 for(i = 0; i < m_vrrpInfo->size(); i++)
714 {
715 VrrpRouter *router = m_vrrpInfo->getRouter(i);
716 DbgPrintf(6, _T("Node::addVrrpInterfaces(node=%s [%d]): vrouter %d state=%d"), m_name, (int)m_id, i, router->getState());
717 if (router->getState() != VRRP_STATE_MASTER)
718 continue; // Do not add interfaces if router is not in master state
0d75ea88 719
5f8890c1
AK
720 // Get netmask for this VR
721 int maskBits = 0;
722 for(j = 0; j < ifList->size(); j++)
c30c0c0f
VK
723 {
724 InterfaceInfo *iface = ifList->get(j);
5f8890c1
AK
725 if (iface->index == router->getIfIndex())
726 {
c30c0c0f
VK
727 for(int k = 0; k < iface->ipAddrList.size(); k++)
728 {
729 const InetAddress& addr = iface->ipAddrList.get(k);
730 if (addr.getSubnetAddress().contain(router->getVip(0)))
731 {
732 maskBits = addr.getMaskBits();
733 }
734 }
5f8890c1
AK
735 break;
736 }
737 }
738
739 // Walk through all VR virtual IPs
740 for(j = 0; j < router->getVipCount(); j++)
741 {
742 UINT32 vip = router->getVip(j);
743 DbgPrintf(6, _T("Node::addVrrpInterfaces(node=%s [%d]): checking VIP %s@%d"), m_name, (int)m_id, IpToStr(vip, buffer), i);
744 if (vip != 0)
745 {
746 for(k = 0; k < ifList->size(); k++)
c30c0c0f 747 if (ifList->get(k)->hasAddress(vip))
5f8890c1
AK
748 break;
749 if (k == ifList->size())
750 {
751 InterfaceInfo *iface = new InterfaceInfo(0);
752 _sntprintf(iface->name, MAX_DB_STRING, _T("vrrp.%u.%u.%d"), router->getId(), router->getIfIndex(), j);
753 memcpy(iface->macAddr, router->getVirtualMacAddr(), MAC_ADDR_LENGTH);
c30c0c0f
VK
754 InetAddress addr(vip);
755 addr.setMaskBits(maskBits);
756 iface->ipAddrList.add(addr);
5f8890c1
AK
757 ifList->add(iface);
758 DbgPrintf(6, _T("Node::addVrrpInterfaces(node=%s [%d]): added interface %s"), m_name, (int)m_id, iface->name);
759 }
760 }
761 }
762 }
763 }
764 unlockProperties();
0d75ea88
VK
765}
766
7946bd7c 767/**
14228410 768 * Find interface by index.
71ea7674 769 *
14228410 770 * @param ifIndex interface index to match
71ea7674 771 * @return pointer to interface object or NULL if appropriate interface couldn't be found
7946bd7c 772 */
c75e9ee4 773Interface *Node::findInterfaceByIndex(UINT32 ifIndex)
5039dede 774{
db091a1f 775 lockChildList(false);
274d9c7a 776 for(int i = 0; i < m_childList->size(); i++)
db091a1f 777 if (m_childList->get(i)->getObjectClass() == OBJECT_INTERFACE)
5039dede 778 {
274d9c7a 779 Interface *pInterface = (Interface *)m_childList->get(i);
5f8890c1 780 if (pInterface->getIfIndex() == ifIndex)
5039dede 781 {
db091a1f 782 unlockChildList();
c75e9ee4 783 return pInterface;
5039dede
AK
784 }
785 }
db091a1f 786 unlockChildList();
5039dede
AK
787 return NULL;
788}
789
7946bd7c
VK
790/**
791 * Find interface by name or description
792 * Returns pointer to interface object or NULL if appropriate interface couldn't be found
793 */
c75e9ee4 794Interface *Node::findInterfaceByName(const TCHAR *name)
630e15d6 795{
cf1d689e
VK
796 if ((name == NULL) || (name[0] == 0))
797 return NULL;
798
630e15d6
VK
799 Interface *pInterface;
800
db091a1f 801 lockChildList(false);
274d9c7a 802 for(int i = 0; i < m_childList->size(); i++)
db091a1f 803 if (m_childList->get(i)->getObjectClass() == OBJECT_INTERFACE)
630e15d6 804 {
db091a1f 805 pInterface = (Interface *)m_childList->get(i);
5f8890c1 806 if (!_tcsicmp(pInterface->getName(), name) || !_tcsicmp(pInterface->getDescription(), name))
630e15d6 807 {
db091a1f 808 unlockChildList();
630e15d6
VK
809 return pInterface;
810 }
811 }
db091a1f 812 unlockChildList();
630e15d6
VK
813 return NULL;
814}
815
7946bd7c
VK
816/**
817 * Find interface by slot/port pair
818 * Returns pointer to interface object or NULL if appropriate interface couldn't be found
819 */
967893bb 820Interface *Node::findInterfaceBySlotAndPort(UINT32 slot, UINT32 port)
3f8c54e7 821{
db091a1f 822 lockChildList(false);
274d9c7a 823 for(int i = 0; i < m_childList->size(); i++)
db091a1f 824 if (m_childList->get(i)->getObjectClass() == OBJECT_INTERFACE)
3f8c54e7 825 {
274d9c7a 826 Interface *pInterface = (Interface *)m_childList->get(i);
5f8890c1 827 if (pInterface->isPhysicalPort() && (pInterface->getSlotNumber() == slot) && (pInterface->getPortNumber() == port))
3f8c54e7 828 {
db091a1f 829 unlockChildList();
3f8c54e7
VK
830 return pInterface;
831 }
832 }
db091a1f 833 unlockChildList();
3f8c54e7
VK
834 return NULL;
835}
836
7946bd7c
VK
837/**
838 * Find interface by MAC address
839 * Returns pointer to interface object or NULL if appropriate interface couldn't be found
840 */
eec253a8
VK
841Interface *Node::findInterfaceByMAC(const BYTE *macAddr)
842{
8f26db67 843 Interface *iface = NULL;
db091a1f
VK
844 lockChildList(false);
845 for(int i = 0; i < m_childList->size(); i++)
846 {
847 NetObj *curr = m_childList->get(i);
848 if (curr->getObjectClass() == OBJECT_INTERFACE)
eec253a8 849 {
5f8890c1 850 if (!memcmp(((Interface *)curr)->getMacAddr(), macAddr, MAC_ADDR_LENGTH))
eec253a8 851 {
db091a1f 852 iface = (Interface *)curr;
8f26db67 853 break;
eec253a8
VK
854 }
855 }
db091a1f
VK
856 }
857 unlockChildList();
8f26db67 858 return iface;
eec253a8
VK
859}
860
7946bd7c
VK
861/**
862 * Find interface by IP address
863 * Returns pointer to interface object or NULL if appropriate interface couldn't be found
864 */
c75e9ee4 865Interface *Node::findInterfaceByIP(const InetAddress& addr)
eec253a8 866{
c75e9ee4 867 if (!addr.isValid())
5f8890c1 868 return NULL;
eec253a8 869
db091a1f
VK
870 lockChildList(false);
871 for(int i = 0; i < m_childList->size(); i++)
872 if (m_childList->get(i)->getObjectClass() == OBJECT_INTERFACE)
eec253a8 873 {
db091a1f 874 Interface *pInterface = (Interface *)m_childList->get(i);
c30c0c0f 875 if (pInterface->getIpAddressList()->hasAddress(addr))
eec253a8 876 {
db091a1f 877 unlockChildList();
eec253a8
VK
878 return pInterface;
879 }
880 }
db091a1f 881 unlockChildList();
eec253a8
VK
882 return NULL;
883}
884
7946bd7c
VK
885/**
886 * Find interface by bridge port number
887 */
967893bb 888Interface *Node::findBridgePort(UINT32 bridgePortNumber)
eec253a8 889{
db091a1f
VK
890 lockChildList(false);
891 for(int i = 0; i < m_childList->size(); i++)
892 if (m_childList->get(i)->getObjectClass() == OBJECT_INTERFACE)
eec253a8 893 {
db091a1f 894 Interface *pInterface = (Interface *)m_childList->get(i);
5f8890c1 895 if (pInterface->getBridgePortNumber() == bridgePortNumber)
eec253a8 896 {
db091a1f 897 unlockChildList();
eec253a8
VK
898 return pInterface;
899 }
900 }
db091a1f 901 unlockChildList();
eec253a8
VK
902 return NULL;
903}
904
7946bd7c
VK
905/**
906 * Find connection point for node
907 */
75ebb063 908NetObj *Node::findConnectionPoint(UINT32 *localIfId, BYTE *localMacAddr, int *type)
f42b8099 909{
5f8890c1 910 NetObj *cp = NULL;
db091a1f
VK
911 lockChildList(false);
912 for(int i = 0; i < m_childList->size(); i++)
d0b5d358 913 {
db091a1f 914 if (m_childList->get(i)->getObjectClass() == OBJECT_INTERFACE)
f42b8099 915 {
db091a1f 916 Interface *iface = (Interface *)m_childList->get(i);
5f8890c1
AK
917 cp = FindInterfaceConnectionPoint(iface->getMacAddr(), type);
918 if (cp != NULL)
919 {
920 *localIfId = iface->getId();
921 memcpy(localMacAddr, iface->getMacAddr(), MAC_ADDR_LENGTH);
922 break;
923 }
924 }
d0b5d358 925 }
db091a1f 926 unlockChildList();
f42b8099
VK
927 return cp;
928}
929
a3050773 930/**
8f26db67
VK
931 * Find attached access point by MAC address
932 */
933AccessPoint *Node::findAccessPointByMAC(const BYTE *macAddr)
934{
935 AccessPoint *ap = NULL;
db091a1f
VK
936 lockChildList(false);
937 for(int i = 0; i < m_childList->size(); i++)
938 {
939 NetObj *curr = m_childList->get(i);
940 if (curr->getObjectClass() == OBJECT_ACCESSPOINT)
8f26db67 941 {
db091a1f 942 if (!memcmp(((AccessPoint *)curr)->getMacAddr(), macAddr, MAC_ADDR_LENGTH))
8f26db67 943 {
db091a1f 944 ap = (AccessPoint *)curr;
8f26db67
VK
945 break;
946 }
947 }
db091a1f
VK
948 }
949 unlockChildList();
8f26db67
VK
950 return ap;
951}
952
953/**
954 * Find access point by radio ID (radio interface index)
955 */
956AccessPoint *Node::findAccessPointByRadioId(int rfIndex)
957{
958 AccessPoint *ap = NULL;
db091a1f
VK
959 lockChildList(false);
960 for(int i = 0; i < m_childList->size(); i++)
961 {
962 NetObj *curr = m_childList->get(i);
963 if (curr->getObjectClass() == OBJECT_ACCESSPOINT)
8f26db67 964 {
db091a1f 965 if (((AccessPoint *)curr)->isMyRadio(rfIndex))
8f26db67 966 {
db091a1f 967 ap = (AccessPoint *)curr;
8f26db67
VK
968 break;
969 }
970 }
db091a1f
VK
971 }
972 unlockChildList();
8f26db67
VK
973 return ap;
974}
975
976/**
386f88e3
VK
977 * Find attached access point by BSSID
978 */
979AccessPoint *Node::findAccessPointByBSSID(const BYTE *bssid)
980{
981 AccessPoint *ap = NULL;
db091a1f
VK
982 lockChildList(false);
983 for(int i = 0; i < m_childList->size(); i++)
984 {
985 NetObj *curr = m_childList->get(i);
986 if (curr->getObjectClass() == OBJECT_ACCESSPOINT)
386f88e3 987 {
db091a1f
VK
988 if (!memcmp(((AccessPoint *)curr)->getMacAddr(), bssid, MAC_ADDR_LENGTH) ||
989 ((AccessPoint *)curr)->isMyRadio(bssid))
386f88e3 990 {
db091a1f 991 ap = (AccessPoint *)curr;
386f88e3
VK
992 break;
993 }
994 }
db091a1f
VK
995 }
996 unlockChildList();
386f88e3
VK
997 return ap;
998}
999
1000/**
a3050773
VK
1001 * Check if given IP address is one of node's interfaces
1002 */
c75e9ee4 1003bool Node::isMyIP(const InetAddress& addr)
5039dede 1004{
db091a1f
VK
1005 lockChildList(false);
1006 for(int i = 0; i < m_childList->size(); i++)
1007 if (m_childList->get(i)->getObjectClass() == OBJECT_INTERFACE)
5039dede 1008 {
db091a1f 1009 if (((Interface *)m_childList->get(i))->getIpAddressList()->hasAddress(addr))
5039dede 1010 {
db091a1f 1011 unlockChildList();
c75e9ee4 1012 return true;
5039dede
AK
1013 }
1014 }
db091a1f 1015 unlockChildList();
c75e9ee4 1016 return false;
5039dede
AK
1017}
1018
a3050773 1019/**
e55ff6f9
VK
1020 * Filter interface - should return true if system should proceed with interface creation
1021 */
1022bool Node::filterInterface(InterfaceInfo *info)
1023{
1024 NXSL_VM *vm = g_pScriptLibrary->createVM(_T("Hook::CreateInterface"), new NXSL_ServerEnv);
1025 if (vm == NULL)
1026 {
1027 DbgPrintf(7, _T("Node::filterInterface(%s [%u]): hook script \"Hook::CreateInterface\" not found"), m_name, m_id);
1028 return true;
1029 }
1030
1031 Interface *iface;
1032 if (info->name[0] != 0)
1033 iface = new Interface(info->name, (info->description[0] != 0) ? info->description : info->name,
1034 info->index, info->ipAddrList, info->type, m_zoneId);
1035 else
1036 iface = new Interface(info->ipAddrList, m_zoneId, false);
1037 iface->setMacAddr(info->macAddr, false);
1038 iface->setBridgePortNumber(info->bridgePort);
1039 iface->setSlotNumber(info->slot);
1040 iface->setPortNumber(info->port);
1041 iface->setPhysicalPortFlag(info->isPhysicalPort);
1042 iface->setManualCreationFlag(false);
1043 iface->setSystemFlag(info->isSystem);
1044 iface->setMTU(info->mtu);
1045 iface->setSpeed(info->speed);
1046 iface->setIfTableSuffix(info->ifTableSuffixLength, info->ifTableSuffix);
1047
1048 bool pass = true;
1049 NXSL_Value *argv = new NXSL_Value(new NXSL_Object(&g_nxslInterfaceClass, iface));
1050 vm->setGlobalVariable(_T("$node"), new NXSL_Value(new NXSL_Object(&g_nxslNodeClass, this)));
1051 if (vm->run(1, &argv))
1052 {
1053 NXSL_Value *result = vm->getResult();
1054 if ((result != NULL) && result->isInteger())
1055 {
1056 pass = (result->getValueAsInt32() != 0);
1057 }
1058 }
1059 else
1060 {
1061 DbgPrintf(4, _T("Node::filterInterface(%s [%u]): hook script execution error: %s"), m_name, m_id, vm->getErrorText());
1062 }
1063 delete vm;
1064 delete iface;
1065
1066 DbgPrintf(6, _T("Node::filterInterface(%s [%u]): interface \"%s\" (ifIndex=%d) %s by filter"),
1067 m_name, m_id, info->name, info->index, pass ? _T("accepted") : _T("rejected"));
1068 return pass;
1069}
1070
1071/**
e95680e5
VK
1072 * Create new interface - convenience wrapper
1073 */
c77bdd19 1074Interface *Node::createNewInterface(const InetAddress& ipAddr, BYTE *macAddr, bool fakeInterface)
e95680e5 1075{
c30c0c0f
VK
1076 InterfaceInfo info(1);
1077 info.ipAddrList.add(ipAddr);
e95680e5
VK
1078 if (macAddr != NULL)
1079 memcpy(info.macAddr, macAddr, MAC_ADDR_LENGTH);
c77bdd19 1080 return createNewInterface(&info, false, fakeInterface);
e95680e5
VK
1081}
1082
1083/**
a3050773
VK
1084 * Create new interface
1085 */
c77bdd19 1086Interface *Node::createNewInterface(InterfaceInfo *info, bool manuallyCreated, bool fakeInterface)
5039dede 1087{
5f8890c1 1088 bool bSyntheticMask = false;
c30c0c0f 1089 TCHAR buffer[64];
5039dede 1090
5f8890c1 1091 DbgPrintf(5, _T("Node::createNewInterface(\"%s\", %d, %d, bp=%d, slot=%d, port=%d) called for node %s [%d]"),
c30c0c0f
VK
1092 info->name, info->index, info->type, info->bridgePort, info->slot, info->port, m_name, m_id);
1093 for(int i = 0; i < info->ipAddrList.size(); i++)
1094 {
1095 const InetAddress& addr = info->ipAddrList.get(i);
1096 DbgPrintf(5, _T("Node::createNewInterface(%s): IP address %s/%d"), info->name, addr.toString(buffer), addr.getMaskBits());
1097 }
5039dede
AK
1098
1099 // Find subnet to place interface object to
5f8890c1 1100 if (info->type != IFTYPE_SOFTWARE_LOOPBACK)
5039dede 1101 {
5f8890c1 1102 Cluster *pCluster = getMyCluster();
c30c0c0f
VK
1103 for(int i = 0; i < info->ipAddrList.size(); i++)
1104 {
1105 InetAddress addr = info->ipAddrList.get(i);
1106 bool addToSubnet = addr.isValidUnicast() && ((pCluster == NULL) || !pCluster->isSyncAddr(addr));
5f8890c1
AK
1107 DbgPrintf(5, _T("Node::createNewInterface: node=%s [%d] ip=%s/%d cluster=%s [%d] add=%s"),
1108 m_name, m_id, addr.toString(buffer), addr.getMaskBits(),
c30c0c0f
VK
1109 (pCluster != NULL) ? pCluster->getName() : _T("(null)"),
1110 (pCluster != NULL) ? pCluster->getId() : 0, addToSubnet ? _T("yes") : _T("no"));
5f8890c1
AK
1111 if (addToSubnet)
1112 {
1113 Subnet *pSubnet = FindSubnetForNode(m_zoneId, addr);
1114 if (pSubnet == NULL)
1115 {
1116 // Check if netmask is 0 (detect), and if yes, create
1117 // new subnet with default mask
c30c0c0f 1118 if (addr.getMaskBits() == 0)
5f8890c1
AK
1119 {
1120 bSyntheticMask = true;
1121 addr.setMaskBits((addr.getFamily() == AF_INET) ? ConfigReadInt(_T("DefaultSubnetMaskIPv4"), 24) : ConfigReadInt(_T("DefaultSubnetMaskIPv6"), 64));
5cf8497c 1122 info->ipAddrList.replace(addr);
5f8890c1 1123 }
5039dede 1124
5f8890c1 1125 // Create new subnet object
c30c0c0f 1126 if (addr.getHostBits() >= 2)
5f8890c1
AK
1127 {
1128 pSubnet = createSubnet(addr, bSyntheticMask);
1129 if (bSyntheticMask)
1130 {
1131 // createSubnet may adjust address mask bits
1132 info->ipAddrList.replace(addr);
1133 }
1134 }
1135 }
1136 else
1137 {
1138 // Set correct netmask if we were asked for it
c30c0c0f 1139 if (addr.getMaskBits() == 0)
5f8890c1
AK
1140 {
1141 bSyntheticMask = pSubnet->isSyntheticMask();
5cf8497c
VK
1142 addr.setMaskBits(pSubnet->getIpAddress().getMaskBits());
1143 info->ipAddrList.replace(addr);
5f8890c1
AK
1144 }
1145 }
c30c0c0f
VK
1146 if (pSubnet != NULL)
1147 {
1148 pSubnet->addNode(this);
1149 }
1150 } // addToSubnet
5f8890c1 1151 } // loop by address list
5039dede
AK
1152 }
1153
1154 // Create interface object
c30c0c0f 1155 Interface *pInterface;
e95680e5 1156 if (info->name[0] != 0)
5f8890c1 1157 pInterface = new Interface(info->name, (info->description[0] != 0) ? info->description : info->name,
c30c0c0f 1158 info->index, info->ipAddrList, info->type, m_zoneId);
5039dede 1159 else
c30c0c0f 1160 pInterface = new Interface(info->ipAddrList, m_zoneId, bSyntheticMask);
e55ff6f9 1161 pInterface->setMacAddr(info->macAddr, false);
5f8890c1
AK
1162 pInterface->setBridgePortNumber(info->bridgePort);
1163 pInterface->setSlotNumber(info->slot);
1164 pInterface->setPortNumber(info->port);
e95680e5 1165 pInterface->setPhysicalPortFlag(info->isPhysicalPort);
5f8890c1 1166 pInterface->setManualCreationFlag(manuallyCreated);
e95680e5 1167 pInterface->setSystemFlag(info->isSystem);
33560996 1168 pInterface->setMTU(info->mtu);
e5f4e3ac
VK
1169 pInterface->setSpeed(info->speed);
1170 pInterface->setIfTableSuffix(info->ifTableSuffixLength, info->ifTableSuffix);
5039dede 1171
c908b63b
VK
1172 int defaultExpectedState = ConfigReadInt(_T("DefaultInterfaceExpectedState"), IF_DEFAULT_EXPECTED_STATE_UP);
1173 switch(defaultExpectedState)
1174 {
1175 case IF_DEFAULT_EXPECTED_STATE_AUTO:
c77bdd19 1176 pInterface->setExpectedState(fakeInterface ? IF_EXPECTED_STATE_UP : IF_EXPECTED_STATE_AUTO);
c908b63b
VK
1177 break;
1178 case IF_DEFAULT_EXPECTED_STATE_IGNORE:
1179 pInterface->setExpectedState(IF_EXPECTED_STATE_IGNORE);
1180 break;
1181 default:
1182 pInterface->setExpectedState(IF_EXPECTED_STATE_UP);
1183 break;
1184 }
1185
5039dede 1186 // Insert to objects' list and generate event
e7450f3b 1187 NetObjInsert(pInterface, true, false);
eec253a8 1188 addInterface(pInterface);
01152a54 1189 if (!m_isHidden)
478d4ff4 1190 pInterface->unhide();
01152a54 1191 if (!pInterface->isSystem())
5039dede 1192 {
c30c0c0f
VK
1193 const InetAddress& addr = pInterface->getFirstIpAddress();
1194 PostEvent(EVENT_INTERFACE_ADDED, m_id, "dsAdd", pInterface->getId(),
1195 pInterface->getName(), &addr, addr.getMaskBits(), pInterface->getIfIndex());
5039dede 1196 }
9214177b 1197
5f8890c1 1198 return pInterface;
5039dede
AK
1199}
1200
a3050773
VK
1201/**
1202 * Delete interface from node
1203 */
c30c0c0f 1204void Node::deleteInterface(Interface *iface)
5039dede 1205{
5f8890c1 1206 DbgPrintf(5, _T("Node::deleteInterface(node=%s [%d], interface=%s [%d])"), m_name, m_id, iface->getName(), iface->getId());
dfb38baf 1207
5039dede 1208 // Check if we should unlink node from interface's subnet
c30c0c0f 1209 if (!iface->isExcludedFromTopology())
5039dede 1210 {
c30c0c0f
VK
1211 const ObjectArray<InetAddress> *list = iface->getIpAddressList()->getList();
1212 for(int i = 0; i < list->size(); i++)
1213 {
1214 bool doUnlink = true;
1215 const InetAddress *addr = list->get(i);
5039dede 1216
db091a1f
VK
1217 lockChildList(false);
1218 for(int j = 0; j < m_childList->size(); j++)
1219 {
6e81bd95 1220 NetObj *curr = m_childList->get(j);
db091a1f
VK
1221 if ((curr->getObjectClass() == OBJECT_INTERFACE) && (curr != iface) &&
1222 ((Interface *)curr)->getIpAddressList()->findSameSubnetAddress(*addr).isValid())
c30c0c0f
VK
1223 {
1224 doUnlink = false;
1225 break;
1226 }
db091a1f
VK
1227 }
1228 unlockChildList();
4d2c3a54 1229
c30c0c0f 1230 if (doUnlink)
5039dede 1231 {
c30c0c0f
VK
1232 // Last interface in subnet, should unlink node
1233 Subnet *pSubnet = FindSubnetByIP(m_zoneId, addr->getSubnetAddress());
1234 if (pSubnet != NULL)
1235 {
1f8be1f4
VK
1236 deleteParent(pSubnet);
1237 pSubnet->deleteChild(this);
c30c0c0f 1238 }
5f8890c1
AK
1239 DbgPrintf(5, _T("Node::deleteInterface(node=%s [%d], interface=%s [%d]): unlinked from subnet %s [%d]"),
1240 m_name, m_id, iface->getName(), iface->getId(),
1241 (pSubnet != NULL) ? pSubnet->getName() : _T("(null)"),
1242 (pSubnet != NULL) ? pSubnet->getId() : 0);
5039dede
AK
1243 }
1244 }
1245 }
5f8890c1 1246 iface->deleteObject();
5039dede
AK
1247}
1248
7946bd7c
VK
1249/**
1250 * Calculate node status based on child objects status
1251 */
27f9598d 1252void Node::calculateCompoundStatus(BOOL bForcedRecalc)
5039dede 1253{
db091a1f 1254 int iOldStatus = m_status;
967893bb 1255 static UINT32 dwEventCodes[] = { EVENT_NODE_NORMAL, EVENT_NODE_WARNING,
67c45b4d 1256 EVENT_NODE_MINOR, EVENT_NODE_MAJOR, EVENT_NODE_CRITICAL,
5039dede
AK
1257 EVENT_NODE_UNKNOWN, EVENT_NODE_UNMANAGED };
1258
f94d5259 1259 DataCollectionTarget::calculateCompoundStatus(bForcedRecalc);
db091a1f
VK
1260 if (m_status != iOldStatus)
1261 PostEvent(dwEventCodes[m_status], m_id, "d", iOldStatus);
5039dede
AK
1262}
1263
a5ee7b3b 1264/**
208d7427
VK
1265 * Status poller entry point
1266 */
1267void Node::statusPoll(PollerInfo *poller)
1268{
1269 poller->startExecution();
1270 statusPoll(NULL, 0, poller);
1271
1272 // Check if the node has to be deleted due to long downtime
5f8890c1
AK
1273 time_t unreachableDeleteDays = (time_t)ConfigReadInt(_T("DeleteUnreachableNodesPeriod"), 0);
1274 if ((unreachableDeleteDays > 0) && (m_downSince > 0) &&
1275 (time(NULL) - m_downSince > unreachableDeleteDays * 24 * 3600))
1276 {
1277 deleteObject();
1278 }
208d7427
VK
1279 delete poller;
1280}
1281
1282/**
a5ee7b3b
VK
1283 * Perform status poll on node
1284 */
208d7427 1285void Node::statusPoll(ClientSession *pSession, UINT32 dwRqId, PollerInfo *poller)
5039dede 1286{
5f8890c1
AK
1287 if (m_dwDynamicFlags & NDF_DELETE_IN_PROGRESS)
1288 {
1289 if (dwRqId == 0)
1290 m_dwDynamicFlags &= ~NDF_QUEUED_FOR_STATUS_POLL;
1291 return;
1292 }
46117060 1293
5f8890c1
AK
1294 if (IsShutdownInProgress())
1295 return;
9fc9ec2c 1296
487cde95 1297 UINT32 dwOldFlags = m_flags;
5039dede 1298 NetObj *pPollerNode = NULL, **ppPollList;
5f8890c1
AK
1299 SNMP_Transport *pTransport;
1300 Cluster *pCluster;
5039dede
AK
1301 time_t tNow, tExpire;
1302
c1482463 1303 Queue *pQueue = new Queue; // Delayed event queue
208d7427 1304 poller->setStatus(_T("wait for lock"));
7c521895 1305 pollerLock();
88dc9091
VK
1306
1307 if (IsShutdownInProgress())
1308 {
1309 delete pQueue;
1310 pollerUnlock();
1311 return;
1312 }
1313
c59466d2 1314 m_pollRequestor = pSession;
c42b4551
VK
1315 sendPollerMsg(dwRqId, _T("Starting status poll for node %s\r\n"), m_name);
1316 DbgPrintf(5, _T("Starting status poll for node %s (ID: %d)"), m_name, m_id);
5039dede
AK
1317
1318 // Read capability expiration time and current time
1319 tExpire = (time_t)ConfigReadULong(_T("CapabilityExpirationTime"), 604800);
1320 tNow = time(NULL);
1321
5039dede 1322restart_agent_check:
69a4eaa6 1323 if (g_flags & AF_RESOLVE_IP_FOR_EACH_STATUS_POLL)
385b1f20 1324 {
1325 updatePrimaryIpAddr();
1326 }
1327
1328 // Check SNMP agent connectivity
487cde95 1329 if ((m_flags & NF_IS_SNMP) && (!(m_flags & NF_DISABLE_SNMP)) && m_ipAddress.isValidUnicast())
5039dede
AK
1330 {
1331 TCHAR szBuffer[256];
967893bb 1332 UINT32 dwResult;
5039dede 1333
c42b4551 1334 DbgPrintf(6, _T("StatusPoll(%s): check SNMP"), m_name);
5f8890c1
AK
1335 pTransport = createSnmpTransport();
1336 if (pTransport != NULL)
5039dede 1337 {
208d7427 1338 poller->setStatus(_T("check SNMP"));
61b359bc 1339 sendPollerMsg(dwRqId, _T("Checking SNMP agent connectivity\r\n"));
9eeed592
VK
1340 const TCHAR *testOid = m_customAttributes.get(_T("snmp.testoid"));
1341 if (testOid == NULL)
1342 {
1343 testOid = _T(".1.3.6.1.2.1.1.2.0");
1344 }
5f8890c1 1345 dwResult = SnmpGet(m_snmpVersion, pTransport, testOid, NULL, 0, szBuffer, sizeof(szBuffer), 0);
61b359bc 1346 if ((dwResult == SNMP_ERR_SUCCESS) || (dwResult == SNMP_ERR_NO_OBJECT))
5039dede 1347 {
61b359bc 1348 if (m_dwDynamicFlags & NDF_SNMP_UNREACHABLE)
5039dede 1349 {
5039dede 1350 m_dwDynamicFlags &= ~NDF_SNMP_UNREACHABLE;
c42b4551 1351 PostEventEx(pQueue, EVENT_SNMP_OK, m_id, NULL);
61b359bc 1352 sendPollerMsg(dwRqId, POLLER_INFO _T("Connectivity with SNMP agent restored\r\n"));
5039dede 1353 }
aa379fa0
VK
1354
1355 // Update authoritative engine data for SNMPv3
1356 if ((pTransport->getSnmpVersion() == SNMP_VERSION_3) && (pTransport->getAuthoritativeEngine() != NULL))
1357 {
5f8890c1 1358 lockProperties();
aa379fa0
VK
1359 m_snmpSecurity->setAuthoritativeEngine(*pTransport->getAuthoritativeEngine());
1360 unlockProperties();
1361 }
5039dede 1362 }
23c1cb5d
VK
1363 else if ((dwResult == SNMP_ERR_ENGINE_ID) && (m_snmpVersion == SNMP_VERSION_3))
1364 {
1365 // Reset authoritative engine data
1366 lockProperties();
1367 m_snmpSecurity->setAuthoritativeEngine(SNMP_Engine());
1368 unlockProperties();
1369 goto restart_agent_check;
1370 }
5039dede
AK
1371 else
1372 {
61b359bc
VK
1373 sendPollerMsg(dwRqId, POLLER_ERROR _T("SNMP agent unreachable\r\n"));
1374 if (m_dwDynamicFlags & NDF_SNMP_UNREACHABLE)
1375 {
1376 if ((tNow > m_failTimeSNMP + tExpire) &&
1377 (!(m_dwDynamicFlags & NDF_UNREACHABLE)))
1378 {
487cde95 1379 m_flags &= ~NF_IS_SNMP;
61b359bc
VK
1380 m_dwDynamicFlags &= ~NDF_SNMP_UNREACHABLE;
1381 m_szObjectId[0] = 0;
1382 sendPollerMsg(dwRqId, POLLER_WARNING _T("Attribute isSNMP set to FALSE\r\n"));
1383 }
1384 }
1385 else
1386 {
1387 m_dwDynamicFlags |= NDF_SNMP_UNREACHABLE;
c42b4551 1388 PostEventEx(pQueue, EVENT_SNMP_FAIL, m_id, NULL);
61b359bc
VK
1389 m_failTimeSNMP = tNow;
1390 }
5039dede 1391 }
5f8890c1 1392 delete pTransport;
61b359bc
VK
1393 }
1394 else
1395 {
5f8890c1 1396 DbgPrintf(6, _T("StatusPoll(%s): cannot create SNMP transport"), m_name);
5039dede 1397 }
c42b4551 1398 DbgPrintf(6, _T("StatusPoll(%s): SNMP check finished"), m_name);
5039dede
AK
1399 }
1400
1401 // Check native agent connectivity
487cde95 1402 if ((m_flags & NF_IS_NATIVE_AGENT) && (!(m_flags & NF_DISABLE_NXCP)) && m_ipAddress.isValidUnicast())
5039dede 1403 {
c42b4551 1404 DbgPrintf(6, _T("StatusPoll(%s): checking agent"), m_name);
208d7427 1405 poller->setStatus(_T("check agent"));
21c9acce 1406 sendPollerMsg(dwRqId, _T("Checking NetXMS agent connectivity\r\n"));
c3acd0f6 1407
5f8890c1 1408 UINT32 error, socketError;
a01c2a20 1409 bool newConnection;
5f8890c1 1410 agentLock();
a01c2a20 1411 if (connectToAgent(&error, &socketError, &newConnection, true))
5039dede 1412 {
c42b4551 1413 DbgPrintf(7, _T("StatusPoll(%s): connected to agent"), m_name);
5039dede
AK
1414 if (m_dwDynamicFlags & NDF_AGENT_UNREACHABLE)
1415 {
1416 m_dwDynamicFlags &= ~NDF_AGENT_UNREACHABLE;
c42b4551 1417 PostEventEx(pQueue, EVENT_AGENT_OK, m_id, NULL);
21c9acce 1418 sendPollerMsg(dwRqId, POLLER_INFO _T("Connectivity with NetXMS agent restored\r\n"));
5039dede 1419 }
5039dede
AK
1420 }
1421 else
1422 {
c42b4551 1423 DbgPrintf(6, _T("StatusPoll(%s): agent unreachable, error=%d, socketError=%d"), m_name, (int)error, (int)socketError);
21c9acce 1424 sendPollerMsg(dwRqId, POLLER_ERROR _T("NetXMS agent unreachable\r\n"));
5039dede
AK
1425 if (m_dwDynamicFlags & NDF_AGENT_UNREACHABLE)
1426 {
71e4ed3a 1427 if ((tNow > m_failTimeAgent + tExpire) && !(m_dwDynamicFlags & NDF_UNREACHABLE))
5039dede 1428 {
487cde95 1429 m_flags &= ~NF_IS_NATIVE_AGENT;
5039dede
AK
1430 m_dwDynamicFlags &= ~NDF_AGENT_UNREACHABLE;
1431 m_szPlatformName[0] = 0;
1432 m_szAgentVersion[0] = 0;
21c9acce 1433 sendPollerMsg(dwRqId, POLLER_WARNING _T("Attribute isNetXMSAgent set to FALSE\r\n"));
5039dede
AK
1434 }
1435 }
1436 else
1437 {
1438 m_dwDynamicFlags |= NDF_AGENT_UNREACHABLE;
c42b4551 1439 PostEventEx(pQueue, EVENT_AGENT_FAIL, m_id, NULL);
8573e935 1440 m_failTimeAgent = tNow;
0ab347c0 1441 //cancel file monitoring locally(on agent it is canceled if agent have fallen)
f9f79a93 1442 g_monitoringList.removeDisconnectedNode(m_id);
5039dede
AK
1443 }
1444 }
5f8890c1 1445 agentUnlock();
c42b4551 1446 DbgPrintf(7, _T("StatusPoll(%s): agent check finished"), m_name);
f9f79a93
VK
1447
1448 // If file update connection is active, send NOP command to prevent disconnection by idle timeout
1449 AgentConnection *fileUpdateConnection;
1450 lockProperties();
1451 fileUpdateConnection = m_fileUpdateConn;
1452 if (fileUpdateConnection != NULL)
1453 fileUpdateConnection->incRefCount();
1454 unlockProperties();
1455 if (fileUpdateConnection != NULL)
1456 {
1457 nxlog_debug(6, _T("StatusPoll(%s): sending keepalive command on file monitoring connection"), m_name);
1458 fileUpdateConnection->nop();
1459 fileUpdateConnection->decRefCount();
1460 }
5039dede
AK
1461 }
1462
208d7427 1463 poller->setStatus(_T("prepare polling list"));
5039dede
AK
1464
1465 // Find service poller node object
c42b4551 1466 lockProperties();
9208c84b 1467 if (m_pollerNode != 0)
5039dede 1468 {
5f8890c1
AK
1469 UINT32 id = m_pollerNode;
1470 unlockProperties();
f3218755 1471 pPollerNode = FindObjectById(id);
5039dede
AK
1472 if (pPollerNode != NULL)
1473 {
c42b4551 1474 if (pPollerNode->getObjectClass() != OBJECT_NODE)
5039dede
AK
1475 pPollerNode = NULL;
1476 }
1477 }
5f8890c1
AK
1478 else
1479 {
1480 unlockProperties();
1481 }
5039dede
AK
1482
1483 // If nothing found, use management server
1484 if (pPollerNode == NULL)
1485 {
1486 pPollerNode = FindObjectById(g_dwMgmtNode);
1487 if (pPollerNode != NULL)
21c9acce 1488 pPollerNode->incRefCount();
5039dede
AK
1489 }
1490 else
1491 {
21c9acce 1492 pPollerNode->incRefCount();
5039dede
AK
1493 }
1494
1495 // Create polling list
db091a1f
VK
1496 ppPollList = (NetObj **)malloc(sizeof(NetObj *) * m_childList->size());
1497 lockChildList(false);
274d9c7a
VK
1498 int pollListSize = 0;
1499 for(int i = 0; i < m_childList->size(); i++)
db091a1f
VK
1500 {
1501 NetObj *curr = m_childList->get(i);
1502 if (curr->getStatus() != STATUS_UNMANAGED)
5039dede 1503 {
db091a1f 1504 curr->incRefCount();
274d9c7a 1505 ppPollList[pollListSize++] = curr;
5039dede 1506 }
db091a1f
VK
1507 }
1508 unlockChildList();
5039dede
AK
1509
1510 // Poll interfaces and services
208d7427 1511 poller->setStatus(_T("child poll"));
c42b4551 1512 DbgPrintf(7, _T("StatusPoll(%s): starting child object poll"), m_name);
5f8890c1
AK
1513 pCluster = getMyCluster();
1514 pTransport = createSnmpTransport();
274d9c7a 1515 for(int i = 0; i < pollListSize; i++)
5039dede 1516 {
c42b4551 1517 switch(ppPollList[i]->getObjectClass())
5039dede
AK
1518 {
1519 case OBJECT_INTERFACE:
5f8890c1 1520 DbgPrintf(7, _T("StatusPoll(%s): polling interface %d [%s]"), m_name, ppPollList[i]->getId(), ppPollList[i]->getName());
c30c0c0f 1521 ((Interface *)ppPollList[i])->statusPoll(pSession, dwRqId, pQueue, pCluster, pTransport, m_icmpProxy);
5039dede
AK
1522 break;
1523 case OBJECT_NETWORKSERVICE:
5f8890c1 1524 DbgPrintf(7, _T("StatusPoll(%s): polling network service %d [%s]"), m_name, ppPollList[i]->getId(), ppPollList[i]->getName());
0910fe05 1525 ((NetworkService *)ppPollList[i])->statusPoll(pSession, dwRqId, (Node *)pPollerNode, pQueue);
5039dede 1526 break;
56d5289b 1527 case OBJECT_ACCESSPOINT:
5f8890c1 1528 DbgPrintf(7, _T("StatusPoll(%s): polling access point %d [%s]"), m_name, ppPollList[i]->getId(), ppPollList[i]->getName());
ac58ffe9 1529 ((AccessPoint *)ppPollList[i])->statusPoll(pSession, dwRqId, pQueue, this, pTransport);
56d5289b 1530 break;
5039dede 1531 default:
c42b4551 1532 DbgPrintf(7, _T("StatusPoll(%s): skipping object %d [%s] class %d"), m_name, ppPollList[i]->getId(), ppPollList[i]->getName(), ppPollList[i]->getObjectClass());
5039dede
AK
1533 break;
1534 }
21c9acce 1535 ppPollList[i]->decRefCount();
5039dede 1536 }
5f8890c1 1537 delete pTransport;
5039dede 1538 safe_free(ppPollList);
c42b4551 1539 DbgPrintf(7, _T("StatusPoll(%s): finished child object poll"), m_name);
5039dede
AK
1540
1541 // Check if entire node is down
5f8890c1
AK
1542 // This check is disabled for nodes without IP address
1543 if (m_ipAddress.isValidUnicast())
1544 {
1545 bool allDown = true;
1546 lockChildList(false);
274d9c7a 1547 for(int i = 0; i < m_childList->size(); i++)
db091a1f
VK
1548 {
1549 NetObj *curr = m_childList->get(i);
1550 if ((curr->getObjectClass() == OBJECT_INTERFACE) &&
1551 (((Interface *)curr)->getAdminState() != IF_ADMIN_STATE_DOWN) &&
1552 (((Interface *)curr)->getConfirmedOperState() == IF_OPER_STATE_UP) &&
1553 (curr->getStatus() != STATUS_UNMANAGED))
1554 {
1555 allDown = false;
1556 break;
1557 }
1558 }
5f8890c1
AK
1559 unlockChildList();
1560 if (allDown && (m_flags & NF_IS_NATIVE_AGENT) &&
1561 (!(m_flags & NF_DISABLE_NXCP)))
1562 if (!(m_dwDynamicFlags & NDF_AGENT_UNREACHABLE))
1563 allDown = false;
1564 if (allDown && (m_flags & NF_IS_SNMP) &&
1565 (!(m_flags & NF_DISABLE_SNMP)))
1566 if (!(m_dwDynamicFlags & NDF_SNMP_UNREACHABLE))
59176978 1567 allDown = false;
c1482463 1568
5f8890c1
AK
1569 DbgPrintf(6, _T("StatusPoll(%s): allDown=%s, dynFlags=0x%08X"), m_name, allDown ? _T("true") : _T("false"), m_dwDynamicFlags);
1570 if (allDown)
1571 {
1572 if (!(m_dwDynamicFlags & NDF_UNREACHABLE))
1573 {
1574 m_dwDynamicFlags |= NDF_UNREACHABLE;
1575 m_downSince = time(NULL);
1576 poller->setStatus(_T("check network path"));
1577 if (checkNetworkPath(dwRqId))
1578 {
1579 m_dwDynamicFlags |= NDF_NETWORK_PATH_PROBLEM;
1580
1581 // Set interfaces and network services to UNKNOWN state
1582 lockChildList(false);
1583 for(int i = 0; i < m_childList->size(); i++)
1584 {
1585 NetObj *curr = m_childList->get(i);
1586 if (((curr->getObjectClass() == OBJECT_INTERFACE) || (curr->getObjectClass() == OBJECT_NETWORKSERVICE)) &&
1587 (curr->getStatus() == STATUS_CRITICAL))
1588 {
1589 curr->resetStatus();
1590 }
1591 }
1592 unlockChildList();
1593
1594 // Clear delayed event queue
1595 while(1)
1596 {
1597 Event *pEvent = (Event *)pQueue->get();
1598 if (pEvent == NULL)
1599 break;
1600 delete pEvent;
1601 }
1602 delete_and_null(pQueue);
1603
1604 PostEvent(EVENT_NODE_UNREACHABLE, m_id, NULL);
1605 }
1606 else
1607 {
1608 PostEvent(EVENT_NODE_DOWN, m_id, NULL);
1609 }
1610 sendPollerMsg(dwRqId, POLLER_ERROR _T("Node is unreachable\r\n"));
1611 }
1612 else
1613 {
1614 sendPollerMsg(dwRqId, POLLER_WARNING _T("Node is still unreachable\r\n"));
1615 }
1616 }
1617 else
1618 {
1619 m_downSince = 0;
1620 if (m_dwDynamicFlags & NDF_UNREACHABLE)
1621 {
a26861ad 1622 int reason = (m_dwDynamicFlags & NDF_NETWORK_PATH_PROBLEM) ? 1 : 0;
5f8890c1
AK
1623 m_dwDynamicFlags &= ~(NDF_UNREACHABLE | NDF_SNMP_UNREACHABLE | NDF_AGENT_UNREACHABLE | NDF_NETWORK_PATH_PROBLEM);
1624 PostEvent(EVENT_NODE_UP, m_id, "d", reason);
1625 sendPollerMsg(dwRqId, POLLER_INFO _T("Node recovered from unreachable state\r\n"));
1626 goto restart_agent_check;
1627 }
1628 else
1629 {
1630 sendPollerMsg(dwRqId, POLLER_INFO _T("Node is connected\r\n"));
1631 }
1632 }
1633 }
5039dede 1634
71e4ed3a
VK
1635 // Get uptime and update boot time
1636 if (!(m_dwDynamicFlags & NDF_UNREACHABLE))
1637 {
1638 TCHAR buffer[MAX_RESULT_LENGTH];
1639 if (getItemFromAgent(_T("System.Uptime"), MAX_RESULT_LENGTH, buffer) == DCE_SUCCESS)
1640 {
1641 m_bootTime = time(NULL) - _tcstol(buffer, NULL, 0);
5f8890c1 1642 DbgPrintf(5, _T("StatusPoll(%s [%d]): boot time set to %u from agent"), m_name, m_id, (UINT32)m_bootTime);
71e4ed3a 1643 }
296ae03d 1644 else if (getItemFromSNMP(m_snmpPort, _T(".1.3.6.1.2.1.1.3.0"), MAX_RESULT_LENGTH, buffer, SNMP_RAWTYPE_NONE) == DCE_SUCCESS)
71e4ed3a
VK
1645 {
1646 m_bootTime = time(NULL) - _tcstol(buffer, NULL, 0) / 100; // sysUpTime is in hundredths of a second
5f8890c1 1647 DbgPrintf(5, _T("StatusPoll(%s [%d]): boot time set to %u from SNMP"), m_name, m_id, (UINT32)m_bootTime);
71e4ed3a
VK
1648 }
1649 else
1650 {
5f8890c1 1651 DbgPrintf(5, _T("StatusPoll(%s [%d]): unable to get system uptime"), m_name, m_id);
71e4ed3a
VK
1652 }
1653 }
1654 else
1655 {
1656 m_bootTime = 0;
1657 }
1658
0ab347c0 1659 // Get agent uptime to check if it was restared
1660 if (!(m_dwDynamicFlags & NDF_UNREACHABLE))
1661 {
1662 TCHAR buffer[MAX_RESULT_LENGTH];
1663 if (getItemFromAgent(_T("Agent.Uptime"), MAX_RESULT_LENGTH, buffer) == DCE_SUCCESS)
1664 {
1665 time_t oldAgentuptime = m_agentUpTime;
1666 m_agentUpTime = _tcstol(buffer, NULL, 0);
2e22746d 1667 if ((UINT32)oldAgentuptime > (UINT32)m_agentUpTime)
0ab347c0 1668 {
1669 //cancel file monitoring locally(on agent it is canceled if agent have fallen)
f9f79a93 1670 g_monitoringList.removeDisconnectedNode(m_id);
0ab347c0 1671 }
1672 }
1673 else
1674 {
c42b4551 1675 DbgPrintf(5, _T("StatusPoll(%s [%d]): unable to get agent uptime"), m_name, m_id);
f9f79a93 1676 g_monitoringList.removeDisconnectedNode(m_id);
0ab347c0 1677 m_agentUpTime = 0;
1678 }
1679 }
1680 else
1681 {
f9f79a93 1682 g_monitoringList.removeDisconnectedNode(m_id);
0ab347c0 1683 m_agentUpTime = 0;
1684 }
1685
2e22746d
VK
1686 // Get geolocation
1687 if (!(m_dwDynamicFlags & NDF_UNREACHABLE))
1688 {
1689 TCHAR buffer[MAX_RESULT_LENGTH];
1690 if (getItemFromAgent(_T("GPS.LocationData"), MAX_RESULT_LENGTH, buffer) == DCE_SUCCESS)
1691 {
1692 GeoLocation loc = GeoLocation::parseAgentData(buffer);
1693 if (loc.getType() != GL_UNSET)
1694 {
1695 DbgPrintf(5, _T("StatusPoll(%s [%d]): location set to %s, %s from agent"), m_name, m_id, loc.getLatitudeAsString(), loc.getLongitudeAsString());
1696 lockProperties();
1697 m_geoLocation = loc;
1698 setModified();
1699 unlockProperties();
1700 }
1701 }
1702 else
1703 {
1704 DbgPrintf(5, _T("StatusPoll(%s [%d]): unable to get system location"), m_name, m_id);
1705 }
1706 }
1707
849e464d 1708 // Get agent log and agent local database status
b123ecb3 1709 if (!(m_dwDynamicFlags & NDF_UNREACHABLE))
1710 {
1711 TCHAR buffer[MAX_RESULT_LENGTH];
7b30e5ae 1712 if (getItemFromAgent(_T("Agent.LogFile.Status"), MAX_RESULT_LENGTH, buffer) == DCE_SUCCESS)
b123ecb3 1713 {
1714 UINT32 status = _tcstol(buffer, NULL, 0);
7b30e5ae
VK
1715 if (status != 0)
1716 PostEvent(EVENT_AGENT_LOG_PROBLEM, m_id, "ds", status, _T("could not open"));
b123ecb3 1717 }
1718 else
1719 {
7b30e5ae 1720 nxlog_debug(5, _T("StatusPoll(%s [%d]): unable to get agent log status"), m_name, m_id);
b123ecb3 1721 }
1722
7b30e5ae 1723 if (getItemFromAgent(_T("Agent.LocalDatabase.Status"), MAX_RESULT_LENGTH, buffer) == DCE_SUCCESS)
b123ecb3 1724 {
1725 UINT32 status = _tcstol(buffer, NULL, 0);
1726 const TCHAR *statusDescription[3]= {
1727 _T("normal"),
1728 _T("could not open database"),
1729 _T("could not update database"),
1730 };
7b30e5ae
VK
1731 if (status != 0)
1732 PostEvent(EVENT_AGENT_LOCAL_DATABASE_PROBLEM, m_id, "ds", status, statusDescription[status]);
b123ecb3 1733 }
1734 else
1735 {
7b30e5ae 1736 nxlog_debug(5, _T("StatusPoll(%s [%d]): unable to get agent local database status"), m_name, m_id);
b123ecb3 1737 }
1738 }
1739
5039dede 1740 // Send delayed events and destroy delayed event queue
5f8890c1
AK
1741 if (pQueue != NULL)
1742 {
1743 ResendEvents(pQueue);
1744 delete pQueue;
1745 }
a5ee7b3b
VK
1746
1747 // Call hooks in loaded modules
967893bb 1748 for(UINT32 i = 0; i < g_dwNumModules; i++)
5f8890c1
AK
1749 {
1750 if (g_pModuleList[i].pfStatusPollHook != NULL)
1751 {
1752 DbgPrintf(5, _T("StatusPoll(%s [%d]): calling hook in module %s"), m_name, m_id, g_pModuleList[i].szName);
1753 g_pModuleList[i].pfStatusPollHook(this, pSession, dwRqId, poller);
1754 }
1755 }
1756
1757 // Execute hook script
208d7427 1758 poller->setStatus(_T("hook"));
5f8890c1 1759 executeHookScript(_T("StatusPoll"));
a5ee7b3b 1760
208d7427 1761 poller->setStatus(_T("cleanup"));
5039dede 1762 if (pPollerNode != NULL)
21c9acce 1763 pPollerNode->decRefCount();
5039dede 1764
487cde95 1765 if (dwOldFlags != m_flags)
5039dede 1766 {
487cde95 1767 PostEvent(EVENT_NODE_FLAGS_CHANGED, m_id, "xx", dwOldFlags, m_flags);
c42b4551
VK
1768 lockProperties();
1769 setModified();
1770 unlockProperties();
5039dede
AK
1771 }
1772
27f9598d 1773 calculateCompoundStatus();
8573e935 1774 m_lastStatusPoll = time(NULL);
c42b4551 1775 sendPollerMsg(dwRqId, _T("Finished status poll for node %s\r\n"), m_name);
db091a1f 1776 sendPollerMsg(dwRqId, _T("Node status after poll is %s\r\n"), GetStatusAsText(m_status, true));
c59466d2 1777 m_pollRequestor = NULL;
5039dede
AK
1778 if (dwRqId == 0)
1779 m_dwDynamicFlags &= ~NDF_QUEUED_FOR_STATUS_POLL;
7c521895 1780 pollerUnlock();
c42b4551 1781 DbgPrintf(5, _T("Finished status poll for node %s (ID: %d)"), m_name, m_id);
5039dede
AK
1782}
1783
7946bd7c 1784/**
1babf64d 1785 * Check single element of network path
beae365a 1786 */
967893bb 1787bool Node::checkNetworkPathElement(UINT32 nodeId, const TCHAR *nodeType, bool isProxy, UINT32 dwRqId)
beae365a 1788{
5f8890c1
AK
1789 Node *node = (Node *)FindObjectById(nodeId, OBJECT_NODE);
1790 if (node == NULL)
1791 return false;
1792
1793 DbgPrintf(6, _T("Node::checkNetworkPathElement(%s [%d]): found %s: %s [%d]"), m_name, m_id, nodeType, node->getName(), node->getId());
1794 if (node->isDown())
1795 {
1796 DbgPrintf(5, _T("Node::checkNetworkPathElement(%s [%d]): %s %s [%d] is down"),
1797 m_name, m_id, nodeType, node->getName(), node->getId());
1798 sendPollerMsg(dwRqId, POLLER_WARNING _T(" %s %s is down\r\n"), nodeType, node->getName());
1799 return true;
1800 }
1801 if (isProxy && node->isNativeAgent() && (node->getRuntimeFlags() & NDF_AGENT_UNREACHABLE))
1802 {
1803 DbgPrintf(5, _T("Node::checkNetworkPathElement(%s [%d]): agent on %s %s [%d] is down"),
1804 m_name, m_id, nodeType, node->getName(), node->getId());
1805 sendPollerMsg(dwRqId, POLLER_WARNING _T(" Agent on %s %s is down\r\n"), nodeType, node->getName());
1806 return true;
1807 }
1808 if (node->m_lastStatusPoll < time(NULL) - 1)
1809 {
1810 DbgPrintf(6, _T("Node::checkNetworkPathElement(%s [%d]): forced status poll on node %s [%d]"),
1811 m_name, m_id, node->getName(), node->getId());
208d7427
VK
1812 PollerInfo *poller = RegisterPoller(POLLER_TYPE_STATUS, node);
1813 poller->startExecution();
5f8890c1 1814 node->statusPoll(NULL, 0, poller);
208d7427 1815 delete poller;
5f8890c1
AK
1816 if (node->isDown())
1817 {
1818 DbgPrintf(5, _T("Node::checkNetworkPathElement(%s [%d]): %s %s [%d] is down"),
1819 m_name, m_id, nodeType, node->getName(), node->getId());
1820 sendPollerMsg(dwRqId, POLLER_WARNING _T(" %s %s is down\r\n"), nodeType, node->getName());
1821 return true;
1822 }
1823 if (isProxy && node->isNativeAgent() && (node->getRuntimeFlags() & NDF_AGENT_UNREACHABLE))
1824 {
1825 DbgPrintf(5, _T("Node::checkNetworkPathElement(%s [%d]): agent on %s %s [%d] is down"),
1826 m_name, m_id, nodeType, node->getName(), node->getId());
1827 sendPollerMsg(dwRqId, POLLER_WARNING _T(" Agent on %s %s is down\r\n"), nodeType, node->getName());
1828 return true;
1829 }
1830 }
1831 return false;
beae365a
VK
1832}
1833
1834/**
7946bd7c 1835 * Check network path between node and management server to detect possible intermediate node failure
c1482463
VK
1836 *
1837 * @return true if network path problems found
7946bd7c 1838 */
967893bb 1839bool Node::checkNetworkPath(UINT32 dwRqId)
7946bd7c 1840{
5f8890c1 1841 time_t now = time(NULL);
67c45b4d 1842
5f8890c1
AK
1843 // Check proxy node(s)
1844 if (IsZoningEnabled() && (m_zoneId != 0))
1845 {
1846 Zone *zone = (Zone *)g_idxZoneByGUID.get(m_zoneId);
1847 if ((zone != NULL) && (zone->getProxyNodeId() != 0) &&
1848 checkNetworkPathElement(zone->getProxyNodeId(), _T("zone proxy"), true, dwRqId))
1849 return true;
1850 }
beae365a 1851
5f8890c1 1852 // Check directly connected switch
67c45b4d 1853 sendPollerMsg(dwRqId, _T("Checking ethernet connectivity...\r\n"));
5f8890c1
AK
1854 Interface *iface = findInterfaceByIP(m_ipAddress);
1855 if ((iface != NULL) && (iface->getPeerNodeId() != 0))
1856 {
1857 DbgPrintf(6, _T("Node::checkNetworkPath(%s [%d]): found interface object for primary IP: %s [%d]"), m_name, m_id, iface->getName(), iface->getId());
1858 if (checkNetworkPathElement(iface->getPeerNodeId(), _T("upstream switch"), false, dwRqId))
1859 return true;
1860 }
1861 else
1862 {
1863 DbgPrintf(5, _T("Node::checkNetworkPath(%s [%d]): cannot find interface object for primary IP"), m_name, m_id);
1864 }
67c45b4d 1865
7946bd7c
VK
1866 Node *mgmtNode = (Node *)FindObjectById(g_dwMgmtNode);
1867 if (mgmtNode == NULL)
5f8890c1
AK
1868 {
1869 DbgPrintf(5, _T("Node::checkNetworkPath(%s [%d]): cannot find management node"), m_name, m_id);
1870 return false;
1871 }
5039dede 1872
5f8890c1 1873 NetworkPath *trace = TraceRoute(mgmtNode, this);
7946bd7c 1874 if (trace == NULL)
5f8890c1
AK
1875 {
1876 DbgPrintf(5, _T("Node::checkNetworkPath(%s [%d]): trace not available"), m_name, m_id);
1877 return false;
1878 }
1879 DbgPrintf(5, _T("Node::checkNetworkPath(%s [%d]): trace available, %d hops, %s"),
1880 m_name, m_id, trace->getHopCount(), trace->isComplete() ? _T("complete") : _T("incomplete"));
1881
1882 // We will do path check in two passes
1883 // If unreachable intermediate node will be found on first pass,
1884 // then method will just return true. Otherwise, we will do
1885 // second pass, this time forcing status poll on each node in the path.
21c9acce 1886 sendPollerMsg(dwRqId, _T("Checking network path...\r\n"));
5f8890c1
AK
1887 bool secondPass = false;
1888 bool pathProblemFound = false;
7946bd7c
VK
1889restart:
1890 for(int i = 0; i < trace->getHopCount(); i++)
1891 {
5f8890c1 1892 HOP_INFO *hop = trace->getHopInfo(i);
c42b4551 1893 if ((hop->object == NULL) || (hop->object == this) || (hop->object->getObjectClass() != OBJECT_NODE))
5f8890c1 1894 continue;
7946bd7c 1895
5f8890c1
AK
1896 DbgPrintf(6, _T("Node::checkNetworkPath(%s [%d]): checking upstream node %s [%d]"),
1897 m_name, m_id, hop->object->getName(), hop->object->getId());
8573e935 1898 if (secondPass && !((Node *)hop->object)->isDown() && (((Node *)hop->object)->m_lastStatusPoll < now - 1))
5f8890c1
AK
1899 {
1900 DbgPrintf(6, _T("Node::checkNetworkPath(%s [%d]): forced status poll on node %s [%d]"),
1901 m_name, m_id, hop->object->getName(), hop->object->getId());
208d7427
VK
1902 PollerInfo *poller = RegisterPoller(POLLER_TYPE_STATUS, (Node *)hop->object);
1903 poller->startExecution();
5f8890c1 1904 ((Node *)hop->object)->statusPoll(NULL, 0, poller);
208d7427 1905 delete poller;
5f8890c1 1906 }
1f385e47 1907
7946bd7c
VK
1908 if (((Node *)hop->object)->isDown())
1909 {
5f8890c1
AK
1910 DbgPrintf(5, _T("Node::checkNetworkPath(%s [%d]): upstream node %s [%d] is down"),
1911 m_name, m_id, hop->object->getName(), hop->object->getId());
1912 sendPollerMsg(dwRqId, POLLER_WARNING _T(" Upstream node %s is down\r\n"), hop->object->getName());
1913 pathProblemFound = true;
1914 break;
7946bd7c
VK
1915 }
1916 }
5f8890c1
AK
1917 if (!secondPass && !pathProblemFound)
1918 {
1919 DbgPrintf(5, _T("Node::checkNetworkPath(%s [%d]): will do second pass"), m_name, m_id);
1920 secondPass = true;
1921 goto restart;
1922 }
7946bd7c 1923 delete trace;
5f8890c1 1924 return pathProblemFound;
7946bd7c
VK
1925}
1926
1927/**
1928 * Check agent policy binding
1929 * Intended to be called only from configuration poller
1930 */
1f385e47
VK
1931void Node::checkAgentPolicyBinding(AgentConnection *conn)
1932{
5f8890c1
AK
1933 AgentPolicyInfo *ap;
1934 UINT32 rcc = conn->getPolicyInventory(&ap);
1935 if (rcc == ERR_SUCCESS)
1936 {
1937 // Check for unbound but installed policies
1938 for(int i = 0; i < ap->size(); i++)
1939 {
1940 uuid guid = ap->getGuid(i);
1941 NetObj *object = FindObjectByGUID(guid, -1);
1942 if ((object != NULL) && (!object->isChild(m_id)))
1943 {
1944 object->addChild(this);
1945 addParent(object);
1946 DbgPrintf(5, _T("ConfPoll(%s): bound to policy object %s [%d]"), m_name, object->getName(), object->getId());
1947 }
1948 }
1949
1950 // Check for bound but not installed policies and schedule it's installation again
1951 //Job will be unbound if it was not possible to add job
1952 lockParentList(false);
1953 NetObj **unbindList = (NetObj **)malloc(sizeof(NetObj *) * m_parentList->size());
1954 int unbindListSize = 0;
1955 for(int i = 0; i < m_parentList->size(); i++)
1956 {
1957 if (IsAgentPolicyObject(m_parentList->get(i)))
1958 {
1959 const uuid& guid = m_parentList->get(i)->getGuid();
de4af576 1960 int j;
5f8890c1
AK
1961 for(j = 0; j < ap->size(); j++)
1962 {
1963 if (ap->getGuid(j).equals(guid))
1964 break;
1965 }
1966 if (j == ap->size())
28e59088 1967 {
97cddb39 1968 ServerJob *job = new PolicyInstallJob(this, (AgentPolicy *)m_parentList->get(i), 0);
5f8890c1
AK
1969 if (AddJob(job))
1970 {
db091a1f 1971 DbgPrintf(5, _T("ConfPoll(%s): \"%s\" policy deploy scheduled for \"%s\" node"), m_name, m_parentList->get(i)->getName(), m_name );
5f8890c1
AK
1972 }
1973 else
1974 {
db091a1f 1975 DbgPrintf(5, _T("ConfPoll(%s): \"%s\" policy deploy is not possible to scheduled for \"%s\" node"), m_name, m_parentList->get(i)->getName(), m_name);
5f8890c1 1976 delete job;
db091a1f 1977 unbindList[unbindListSize++] = m_parentList->get(i);
5f8890c1 1978 }
28e59088 1979 }
5f8890c1
AK
1980 }
1981 }
1982 unlockParentList();
1f385e47 1983
5f8890c1
AK
1984 for(int i = 0; i < unbindListSize; i++)
1985 {
1986 unbindList[i]->deleteChild(this);
1987 deleteParent(unbindList[i]);
1988 DbgPrintf(5, _T("ConfPoll(%s): unbound from policy object %s [%d]"), m_name, unbindList[i]->getName(), unbindList[i]->getId());
1989 }
1990 safe_free(unbindList);
1f385e47 1991
5f8890c1
AK
1992 delete ap;
1993 }
1994 else
1995 {
1996 DbgPrintf(5, _T("ConfPoll(%s): AgentConnection::getPolicyInventory() failed: rcc=%d"), m_name, rcc);
1997 }
1f385e47
VK
1998}
1999
a3050773
VK
2000/**
2001 * Update primary IP address from primary name
2002 */
5a7d6a10
VK
2003void Node::updatePrimaryIpAddr()
2004{
5f8890c1
AK
2005 if (m_primaryName[0] == 0)
2006 return;
5a7d6a10 2007
b4cf3199 2008 InetAddress ipAddr = ResolveHostName(m_zoneId, m_primaryName);
c75e9ee4 2009 if (!ipAddr.equals(m_ipAddress) && (ipAddr.isValidUnicast() || !_tcscmp(m_primaryName, _T("0.0.0.0"))))
5f8890c1
AK
2010 {
2011 TCHAR buffer1[64], buffer2[64];
5a7d6a10 2012
5f8890c1 2013 DbgPrintf(4, _T("IP address for node %s [%d] changed from %s to %s"),
c75e9ee4 2014 m_name, (int)m_id, m_ipAddress.toString(buffer1), ipAddr.toString(buffer2));
5f8890c1 2015 PostEvent(EVENT_IP_ADDRESS_CHANGED, m_id, "AA", &ipAddr, &m_ipAddress);
2467ed57 2016
487cde95 2017 if (m_flags & NF_REMOTE_AGENT)
dbe28185 2018 {
c42b4551 2019 lockProperties();
c75e9ee4 2020 m_ipAddress = ipAddr;
c42b4551
VK
2021 setModified();
2022 unlockProperties();
dbe28185
VK
2023 }
2024 else
2025 {
5f8890c1 2026 setPrimaryIPAddress(ipAddr);
dbe28185 2027 }
a3050773 2028
5f8890c1
AK
2029 agentLock();
2030 deleteAgentConnection();
2031 agentUnlock();
2032 }
5a7d6a10
VK
2033}
2034
76720a09 2035/**
208d7427
VK
2036 * Entry point for configuration poller
2037 */
2038void Node::configurationPoll(PollerInfo *poller)
2039{
2040 poller->startExecution();
2041 ObjectTransactionStart();
2042 configurationPoll(NULL, 0, poller, 0);
2043 ObjectTransactionEnd();
2044 delete poller;
2045}
2046
2047/**
76720a09
VK
2048 * Perform configuration poll on node
2049 */
208d7427 2050void Node::configurationPoll(ClientSession *pSession, UINT32 dwRqId, PollerInfo *poller, int maskBits)
5039dede 2051{
5f8890c1
AK
2052 if (m_dwDynamicFlags & NDF_DELETE_IN_PROGRESS)
2053 {
2054 if (dwRqId == 0)
2055 m_dwDynamicFlags &= ~NDF_QUEUED_FOR_CONFIG_POLL;
2056 return;
2057 }
46117060 2058
88dc9091 2059 if (IsShutdownInProgress())
9fc9ec2c
VK
2060 return;
2061
487cde95 2062 UINT32 dwOldFlags = m_flags;
35f836fe 2063 TCHAR szBuffer[4096];
76720a09 2064 bool hasChanges = false;
5039dede 2065
208d7427 2066 poller->setStatus(_T("wait for lock"));
7c521895 2067 pollerLock();
88dc9091
VK
2068
2069 if (IsShutdownInProgress())
2070 {
2071 pollerUnlock();
2072 return;
2073 }
2074
c59466d2 2075 m_pollRequestor = pSession;
c42b4551
VK
2076 sendPollerMsg(dwRqId, _T("Starting configuration poll for node %s\r\n"), m_name);
2077 DbgPrintf(4, _T("Starting configuration poll for node %s (ID: %d)"), m_name, m_id);
5039dede
AK
2078
2079 // Check for forced capabilities recheck
2080 if (m_dwDynamicFlags & NDF_RECHECK_CAPABILITIES)
2081 {
f7e3eb5a 2082 sendPollerMsg(dwRqId, POLLER_WARNING _T("Capability reset\r\n"));
487cde95 2083 m_flags &= ~(NF_IS_NATIVE_AGENT | NF_IS_SNMP | NF_IS_CPSNMP |
0ecc2200 2084 NF_IS_BRIDGE | NF_IS_ROUTER | NF_IS_OSPF | NF_IS_PRINTER |
5f8890c1
AK
2085 NF_IS_CDP | NF_IS_LLDP | NF_IS_SONMP | NF_IS_VRRP | NF_HAS_VLANS |
2086 NF_IS_8021X | NF_IS_STP | NF_HAS_ENTITY_MIB | NF_HAS_IFXTABLE |
2087 NF_HAS_WINPDH);
2088 m_dwDynamicFlags &= ~NDF_CONFIGURATION_POLL_PASSED;
5039dede
AK
2089 m_szObjectId[0] = 0;
2090 m_szPlatformName[0] = 0;
2091 m_szAgentVersion[0] = 0;
5f8890c1
AK
2092 safe_free_and_null(m_sysDescription);
2093 safe_free_and_null(m_sysName);
cf38357f
VK
2094 safe_free_and_null(m_sysContact);
2095 safe_free_and_null(m_sysLocation);
5f8890c1 2096 safe_free_and_null(m_lldpNodeId);
5039dede
AK
2097 }
2098
2099 // Check if node is marked as unreachable
2100 if ((m_dwDynamicFlags & NDF_UNREACHABLE) && !(m_dwDynamicFlags & NDF_RECHECK_CAPABILITIES))
2101 {
21c9acce 2102 sendPollerMsg(dwRqId, POLLER_WARNING _T("Node is marked as unreachable, configuration poll aborted\r\n"));
35f836fe 2103 DbgPrintf(4, _T("Node is marked as unreachable, configuration poll aborted"));
8573e935 2104 m_lastConfigurationPoll = time(NULL);
5039dede
AK
2105 }
2106 else
2107 {
5f8890c1 2108 updatePrimaryIpAddr();
5a7d6a10 2109
208d7427 2110 poller->setStatus(_T("capability check"));
21c9acce 2111 sendPollerMsg(dwRqId, _T("Checking node's capabilities...\r\n"));
5039dede 2112
5f8890c1
AK
2113 if (confPollAgent(dwRqId))
2114 hasChanges = true;
2115 if (confPollSnmp(dwRqId))
2116 hasChanges = true;
5039dede
AK
2117
2118 // Check for CheckPoint SNMP agent on port 260
9a1f7c45 2119 if (ConfigReadInt(_T("EnableCheckPointSNMP"), 0))
5039dede 2120 {
c42b4551 2121 DbgPrintf(5, _T("ConfPoll(%s): checking for CheckPoint SNMP on port 260"), m_name);
487cde95 2122 if (!((m_flags & NF_IS_CPSNMP) && (m_dwDynamicFlags & NDF_CPSNMP_UNREACHABLE)) && m_ipAddress.isValidUnicast())
5039dede 2123 {
5f8890c1
AK
2124 SNMP_Transport *pTransport = new SNMP_UDPTransport;
2125 ((SNMP_UDPTransport *)pTransport)->createUDPTransport(m_ipAddress, CHECKPOINT_SNMP_PORT);
9a1f7c45
VK
2126 if (SnmpGet(SNMP_VERSION_1, pTransport,
2127 _T(".1.3.6.1.4.1.2620.1.1.10.0"), NULL, 0, szBuffer, sizeof(szBuffer), 0) == SNMP_ERR_SUCCESS)
2128 {
c42b4551 2129 lockProperties();
487cde95 2130 m_flags |= NF_IS_CPSNMP | NF_IS_ROUTER;
9a1f7c45 2131 m_dwDynamicFlags &= ~NDF_CPSNMP_UNREACHABLE;
c42b4551 2132 unlockProperties();
9a1f7c45
VK
2133 sendPollerMsg(dwRqId, POLLER_INFO _T(" CheckPoint SNMP agent on port 260 is active\r\n"));
2134 }
5f8890c1 2135 delete pTransport;
5039dede 2136 }
5039dede
AK
2137 }
2138
2139 // Generate event if node flags has been changed
487cde95 2140 if (dwOldFlags != m_flags)
5039dede 2141 {
487cde95 2142 PostEvent(EVENT_NODE_FLAGS_CHANGED, m_id, "xx", dwOldFlags, m_flags);
76720a09 2143 hasChanges = true;
5039dede
AK
2144 }
2145
5039dede 2146 // Retrieve interface list
208d7427 2147 poller->setStatus(_T("interface check"));
21c9acce 2148 sendPollerMsg(dwRqId, _T("Capability check finished\r\n"));
5039dede 2149
5f8890c1
AK
2150 if (updateInterfaceConfiguration(dwRqId, maskBits))
2151 hasChanges = true;
5039dede 2152
8573e935 2153 m_lastConfigurationPoll = time(NULL);
5039dede 2154
5f8890c1
AK
2155 // Check node name
2156 sendPollerMsg(dwRqId, _T("Checking node name\r\n"));
2157 UINT32 dwAddr = ntohl(_t_inet_addr(m_name));
2158 if ((g_flags & AF_RESOLVE_NODE_NAMES) &&
2159 (dwAddr != INADDR_NONE) &&
2160 (dwAddr != INADDR_ANY) &&
2161 isMyIP(dwAddr))
2162 {
2163 sendPollerMsg(dwRqId, _T("Node name is an IP address and need to be resolved\r\n"));
2164 poller->setStatus(_T("resolving name"));
2165 if (resolveName(FALSE))
2166 {
2167 sendPollerMsg(dwRqId, POLLER_INFO _T("Node name resolved to %s\r\n"), m_name);
2168 hasChanges = true;
2169 }
2170 else
2171 {
2172 sendPollerMsg(dwRqId, POLLER_WARNING _T("Node name cannot be resolved\r\n"));
2173 }
2174 }
2175 else
2176 {
2177 if (g_flags & AF_SYNC_NODE_NAMES_WITH_DNS)
2178 {
2179 sendPollerMsg(dwRqId, _T("Syncing node name with DNS\r\n"));
2180 poller->setStatus(_T("resolving name"));
2181 if (resolveName(TRUE))
2182 {
2183 sendPollerMsg(dwRqId, POLLER_INFO _T("Node name resolved to %s\r\n"), m_name);
2184 hasChanges = true;
2185 }
2186 }
2187 else
2188 {
2189 sendPollerMsg(dwRqId, _T("Node name is OK\r\n"));
2190 }
2191 }
2192
2193 applyUserTemplates();
2194 updateContainerMembership();
2195
2196 // Get list of installed products
2197 if (m_flags & NF_IS_NATIVE_AGENT)
2198 {
2199 poller->setStatus(_T("software check"));
2200 sendPollerMsg(dwRqId, _T("Reading list of installed software packages\r\n"));
2201
2202 Table *table;
2203 if (getTableFromAgent(_T("System.InstalledProducts"), &table) == DCE_SUCCESS)
2204 {
2205 lockProperties();
2206 delete m_softwarePackages;
2207 m_softwarePackages = new ObjectArray<SoftwarePackage>(table->getNumRows(), 16, true);
2208 for(int i = 0; i < table->getNumRows(); i++)
2209 m_softwarePackages->add(new SoftwarePackage(table, i));
2210 unlockProperties();
2211 delete table;
2212 sendPollerMsg(dwRqId, POLLER_INFO _T("Got information about %d installed software packages\r\n"), m_softwarePackages->size());
2213 }
2214 else
2215 {
2216 delete_and_null(m_softwarePackages);
2217 sendPollerMsg(dwRqId, POLLER_WARNING _T("Unable to get information about installed software packages\r\n"));
2218 }
2219 }
2220
2221 // Call hooks in loaded modules
2222 for(UINT32 i = 0; i < g_dwNumModules; i++)
2223 {
2224 if (g_pModuleList[i].pfConfPollHook != NULL)
2225 {
2226 DbgPrintf(5, _T("ConfigurationPoll(%s [%d]): calling hook in module %s"), m_name, m_id, g_pModuleList[i].szName);
2227 if (g_pModuleList[i].pfConfPollHook(this, pSession, dwRqId, poller))
3368b8b7 2228 hasChanges = true;
5f8890c1
AK
2229 }
2230 }
a5ee7b3b 2231
270c946c 2232 // Setup permanent connection to agent if not present (needed for proper configuration re-sync)
5f8890c1
AK
2233 if (m_flags & NF_IS_NATIVE_AGENT)
2234 {
270c946c
VK
2235 agentLock();
2236 connectToAgent();
2237 agentUnlock();
2238 }
2239
5f8890c1
AK
2240 // Update node type
2241 NodeType type = detectNodeType();
e980db40 2242 nxlog_debug(5, _T("ConfPoll(%s): detected node type: %d (%s)"), m_name, type, typeName(type));
5f8890c1
AK
2243 lockProperties();
2244 if ((type != NODE_TYPE_UNKNOWN) && (type != m_type))
2245 {
2246 m_type = type;
2247 hasChanges = true;
2248 nxlog_debug(5, _T("ConfPoll(%s): node type set to %d (%s)"), m_name, type, typeName(type));
e980db40 2249 sendPollerMsg(dwRqId, _T(" Node type changed to %s\r\n"), typeName(type));
5f8890c1
AK
2250 }
2251 unlockProperties();
e980db40 2252
5f8890c1
AK
2253 // Execute hook script
2254 poller->setStatus(_T("hook"));
2255 executeHookScript(_T("ConfigurationPoll"));
a3050773 2256
5f8890c1
AK
2257 sendPollerMsg(dwRqId, _T("Finished configuration poll for node %s\r\n"), m_name);
2258 sendPollerMsg(dwRqId, _T("Node configuration was%schanged after poll\r\n"), hasChanges ? _T(" ") : _T(" not "));
270c946c 2259
5f8890c1 2260 m_dwDynamicFlags |= NDF_CONFIGURATION_POLL_PASSED;
a3050773 2261 }
1824629a 2262
4d0c32f3 2263 // Finish configuration poll
208d7427 2264 poller->setStatus(_T("cleanup"));
4d0c32f3
VK
2265 if (dwRqId == 0)
2266 m_dwDynamicFlags &= ~NDF_QUEUED_FOR_CONFIG_POLL;
2267 m_dwDynamicFlags &= ~NDF_RECHECK_CAPABILITIES;
7c521895 2268 pollerUnlock();
c42b4551 2269 DbgPrintf(4, _T("Finished configuration poll for node %s (ID: %d)"), m_name, m_id);
4d0c32f3 2270
76720a09 2271 if (hasChanges)
4d0c32f3 2272 {
c42b4551
VK
2273 lockProperties();
2274 setModified();
2275 unlockProperties();
4d0c32f3
VK
2276 }
2277}
2278
76720a09 2279/**
e980db40
VK
2280 * Detect node type
2281 */
2282NodeType Node::detectNodeType()
2283{
2284 NodeType type = NODE_TYPE_UNKNOWN;
487cde95 2285 if (m_flags & NF_IS_SNMP)
e980db40
VK
2286 {
2287 nxlog_debug(6, _T("Node::detectNodeType(%s [%d]): SNMP node, driver name is %s"), m_name, m_id, m_driver->getName());
2288
2289 // Assume physical device if it supports SNMP and driver is not "GENERIC"
2290 // FIXME: add driver method to determine node type
2291 if (_tcscmp(m_driver->getName(), _T("GENERIC")))
2292 {
2293 type = NODE_TYPE_PHYSICAL;
2294 }
2295 else
2296 {
487cde95 2297 if (m_flags & NF_IS_PRINTER)
e980db40
VK
2298 {
2299 // Assume that printers are physical devices
2300 type = NODE_TYPE_PHYSICAL;
2301 }
2302 }
2303 }
2304 return type;
2305}
2306
2307/**
76720a09
VK
2308 * Configuration poll: check for NetXMS agent
2309 */
967893bb 2310bool Node::confPollAgent(UINT32 dwRqId)
76720a09 2311{
487cde95 2312 DbgPrintf(5, _T("ConfPoll(%s): checking for NetXMS agent Flags={%08X} DynamicFlags={%08X}"), m_name, m_flags, m_dwDynamicFlags);
5f8890c1
AK
2313 if (((m_flags & NF_IS_NATIVE_AGENT) && (m_dwDynamicFlags & NDF_AGENT_UNREACHABLE)) ||
2314 !m_ipAddress.isValidUnicast() || (m_flags & NF_DISABLE_NXCP))
2315 return false;
76720a09 2316
5f8890c1 2317 bool hasChanges = false;
76720a09 2318
5f8890c1 2319 sendPollerMsg(dwRqId, _T(" Checking NetXMS agent...\r\n"));
9674aefa 2320 AgentConnection *pAgentConn = new AgentConnectionEx(m_id, m_ipAddress, m_agentPort, m_agentAuthMethod, m_szSharedSecret, isAgentCompressionAllowed());
76720a09 2321 setAgentProxy(pAgentConn);
f6e04a96 2322 pAgentConn->setCommandTimeout(g_agentCommandTimeout);
c42b4551 2323 DbgPrintf(5, _T("ConfPoll(%s): checking for NetXMS agent - connecting"), m_name);
af21affe
VK
2324
2325 // Try to connect to agent
2326 UINT32 rcc;
2327 if (!pAgentConn->connect(g_pServerKey, FALSE, &rcc))
2328 {
2329 // If there are authentication problem, try default shared secret
2330 if ((rcc == ERR_AUTH_REQUIRED) || (rcc == ERR_AUTH_FAILED))
2331 {
2332 TCHAR secret[MAX_SECRET_LENGTH];
2333 ConfigReadStr(_T("AgentDefaultSharedSecret"), secret, MAX_SECRET_LENGTH, _T("netxms"));
ce9783d2 2334 DecryptPassword(_T("netxms"), secret, secret, MAX_SECRET_LENGTH);
af21affe
VK
2335 pAgentConn->setAuthData(AUTH_SHA1_HASH, secret);
2336 if (pAgentConn->connect(g_pServerKey, FALSE, &rcc))
2337 {
c42b4551 2338 m_agentAuthMethod = AUTH_SHA1_HASH;
af21affe 2339 nx_strncpy(m_szSharedSecret, secret, MAX_SECRET_LENGTH);
c42b4551 2340 DbgPrintf(5, _T("ConfPoll(%s): checking for NetXMS agent - shared secret changed to system default"), m_name);
af21affe
VK
2341 }
2342 }
2343 }
2344
2345 if (rcc == ERR_SUCCESS)
76720a09 2346 {
c42b4551
VK
2347 DbgPrintf(5, _T("ConfPoll(%s): checking for NetXMS agent - connected"), m_name);
2348 lockProperties();
487cde95 2349 m_flags |= NF_IS_NATIVE_AGENT;
76720a09
VK
2350 if (m_dwDynamicFlags & NDF_AGENT_UNREACHABLE)
2351 {
2352 m_dwDynamicFlags &= ~NDF_AGENT_UNREACHABLE;
c42b4551 2353 PostEvent(EVENT_AGENT_OK, m_id, NULL);
21c9acce 2354 sendPollerMsg(dwRqId, POLLER_INFO _T(" Connectivity with NetXMS agent restored\r\n"));
76720a09 2355 }
5f8890c1
AK
2356 else
2357 {
21c9acce 2358 sendPollerMsg(dwRqId, POLLER_INFO _T(" NetXMS native agent is active\r\n"));
5f8890c1 2359 }
c42b4551 2360 unlockProperties();
4d0c32f3 2361
5f8890c1 2362 TCHAR buffer[MAX_RESULT_LENGTH];
76720a09
VK
2363 if (pAgentConn->getParameter(_T("Agent.Version"), MAX_AGENT_VERSION_LEN, buffer) == ERR_SUCCESS)
2364 {
c42b4551 2365 lockProperties();
76720a09
VK
2366 if (_tcscmp(m_szAgentVersion, buffer))
2367 {
2368 _tcscpy(m_szAgentVersion, buffer);
2369 hasChanges = true;
21c9acce 2370 sendPollerMsg(dwRqId, _T(" NetXMS agent version changed to %s\r\n"), m_szAgentVersion);
76720a09 2371 }
c42b4551 2372 unlockProperties();
76720a09
VK
2373 }
2374
2375 if (pAgentConn->getParameter(_T("System.PlatformName"), MAX_PLATFORM_NAME_LEN, buffer) == ERR_SUCCESS)
2376 {
c42b4551 2377 lockProperties();
76720a09
VK
2378 if (_tcscmp(m_szPlatformName, buffer))
2379 {
2380 _tcscpy(m_szPlatformName, buffer);
2381 hasChanges = true;
21c9acce 2382 sendPollerMsg(dwRqId, _T(" Platform name changed to %s\r\n"), m_szPlatformName);
76720a09 2383 }
c42b4551 2384 unlockProperties();
76720a09
VK
2385 }
2386
2387 // Check IP forwarding status
2388 if (pAgentConn->getParameter(_T("Net.IP.Forwarding"), 16, buffer) == ERR_SUCCESS)
2389 {
2390 if (_tcstoul(buffer, NULL, 10) != 0)
487cde95 2391 m_flags |= NF_IS_ROUTER;
76720a09 2392 else
487cde95 2393 m_flags &= ~NF_IS_ROUTER;
76720a09
VK
2394 }
2395
5f8890c1
AK
2396 // Get uname
2397 if (pAgentConn->getParameter(_T("System.Uname"), MAX_DB_STRING, buffer) == ERR_SUCCESS)
2398 {
2399 TranslateStr(buffer, _T("\r\n"), _T(" "));
2400 TranslateStr(buffer, _T("\n"), _T(" "));
2401 TranslateStr(buffer, _T("\r"), _T(" "));
c42b4551 2402 lockProperties();
76720a09
VK
2403 if ((m_sysDescription == NULL) || _tcscmp(m_sysDescription, buffer))
2404 {
5f8890c1 2405 safe_free(m_sysDescription);
76720a09
VK
2406 m_sysDescription = _tcsdup(buffer);
2407 hasChanges = true;
21c9acce 2408 sendPollerMsg(dwRqId, _T(" System description changed to %s\r\n"), m_sysDescription);
76720a09 2409 }
c42b4551 2410 unlockProperties();
5f8890c1 2411 }
76720a09 2412
11b75b2e 2413 // Check for 64 bit counter support.
acf01215 2414 // if Net.Interface.64BitCounters not supported by agent then use
11b75b2e
VK
2415 // only presence of 64 bit parameters as indicator
2416 bool netIf64bitCounters = true;
5f8890c1 2417 if (pAgentConn->getParameter(_T("Net.Interface.64BitCounters"), MAX_DB_STRING, buffer) == ERR_SUCCESS)
11b75b2e
VK
2418 {
2419 netIf64bitCounters = _tcstol(buffer, NULL, 10) ? true : false;
2420 }
2421
5f8890c1 2422 ObjectArray<AgentParameterDefinition> *plist;
86c126f5 2423 ObjectArray<AgentTableDefinition> *tlist;
967893bb 2424 UINT32 rcc = pAgentConn->getSupportedParameters(&plist, &tlist);
5f8890c1
AK
2425 if (rcc == ERR_SUCCESS)
2426 {
2427 lockProperties();
2428 delete m_paramList;
2429 delete m_tableList;
2430 m_paramList = plist;
2431 m_tableList = tlist;
2432
2433 // Check for 64-bit interface counters
2434 m_flags &= ~NF_HAS_AGENT_IFXCOUNTERS;
11b75b2e
VK
2435 if (netIf64bitCounters)
2436 {
5f8890c1
AK
2437 for(int i = 0; i < plist->size(); i++)
2438 {
2439 if (!_tcsicmp(plist->get(i)->getName(), _T("Net.Interface.BytesIn64(*)")))
2440 {
2441 m_flags |= NF_HAS_AGENT_IFXCOUNTERS;
11b75b2e 2442 break;
5f8890c1
AK
2443 }
2444 }
11b75b2e 2445 }
084fb4c1 2446
5f8890c1
AK
2447 unlockProperties();
2448 }
2449 else
2450 {
2451 DbgPrintf(5, _T("ConfPoll(%s): AgentConnection::getSupportedParameters() failed: rcc=%d"), m_name, rcc);
2452 }
76720a09 2453
5f8890c1
AK
2454 // Get supported Windows Performance Counters
2455 if (!_tcsncmp(m_szPlatformName, _T("windows-"), 8))
2456 {
46ee6286 2457 sendPollerMsg(dwRqId, _T(" Reading list of available Windows Performance Counters...\r\n"));
5f8890c1
AK
2458 ObjectArray<WinPerfObject> *perfObjects = WinPerfObject::getWinPerfObjectsFromNode(this, pAgentConn);
2459 lockProperties();
2460 delete m_winPerfObjects;
2461 m_winPerfObjects = perfObjects;
2462 if (m_winPerfObjects != NULL)
2463 {
2464 sendPollerMsg(dwRqId, POLLER_INFO _T(" %d counters read\r\n"), m_winPerfObjects->size());
2465 if (!(m_flags & NF_HAS_WINPDH))
2466 {
2467 m_flags |= NF_HAS_WINPDH;
2468 hasChanges = true;
2469 }
2470 }
2471 else
2472 {
2473 sendPollerMsg(dwRqId, POLLER_ERROR _T(" unable to get Windows Performance Counters list\r\n"));
2474 if (m_flags & NF_HAS_WINPDH)
2475 {
2476 m_flags &= ~NF_HAS_WINPDH;
2477 hasChanges = true;
2478 }
2479 }
2480 unlockProperties();
2481 }
2482
2483 checkAgentPolicyBinding(pAgentConn);
76720a09
VK
2484
2485 pAgentConn->disconnect();
2486 }
5f8890c1
AK
2487 else
2488 {
c42b4551 2489 DbgPrintf(5, _T("ConfPoll(%s): checking for NetXMS agent - failed to connect (error %d)"), m_name, rcc);
5f8890c1 2490 }
da4a8dfe 2491 pAgentConn->decRefCount();
c42b4551 2492 DbgPrintf(5, _T("ConfPoll(%s): checking for NetXMS agent - finished"), m_name);
5f8890c1 2493 return hasChanges;
76720a09
VK
2494}
2495
2496/**
a93aa634 2497 * SNMP walker callback which sets indicator to true after first varbind and aborts walk
76720a09 2498 */
9c5ebc32 2499static UINT32 IndicatorSnmpWalkerCallback(SNMP_Variable *var, SNMP_Transport *transport, void *arg)
76720a09 2500{
a93aa634
VK
2501 (*((bool *)arg)) = true;
2502 return SNMP_ERR_COMM;
76720a09
VK
2503}
2504
2505/**
2506 * Configuration poll: check for SNMP
2507 */
967893bb 2508bool Node::confPollSnmp(UINT32 dwRqId)
76720a09 2509{
5f8890c1
AK
2510 if (((m_flags & NF_IS_SNMP) && (m_dwDynamicFlags & NDF_SNMP_UNREACHABLE)) ||
2511 !m_ipAddress.isValidUnicast() || (m_flags & NF_DISABLE_SNMP))
2512 return false;
76720a09 2513
5f8890c1 2514 bool hasChanges = false;
76720a09 2515
21c9acce 2516 sendPollerMsg(dwRqId, _T(" Checking SNMP...\r\n"));
c42b4551 2517 DbgPrintf(5, _T("ConfPoll(%s): calling SnmpCheckCommSettings()"), m_name);
1f4c37ee
VK
2518 StringList oids;
2519 const TCHAR *customOid = m_customAttributes.get(_T("snmp.testoid"));
2520 if (customOid != NULL)
2521 oids.add(customOid);
2522 oids.add(_T(".1.3.6.1.2.1.1.2.0"));
2523 oids.add(_T(".1.3.6.1.2.1.1.1.0"));
2524 AddDriverSpecificOids(&oids);
d0a2ada6 2525 SNMP_Transport *pTransport = SnmpCheckCommSettings(getEffectiveSnmpProxy(), (getEffectiveSnmpProxy() == m_id) ? InetAddress::LOOPBACK : m_ipAddress, &m_snmpVersion, m_snmpPort, m_snmpSecurity, &oids);
af7ca382 2526 if (pTransport == NULL)
76720a09 2527 {
d0a2ada6 2528 DbgPrintf(5, _T("ConfPoll(%s): unable to create SNMP transport"), m_name);
2529 return false;
2530 }
76720a09 2531
d0a2ada6 2532 lockProperties();
2533 m_snmpPort = pTransport->getPort();
2534 delete m_snmpSecurity;
2535 m_snmpSecurity = new SNMP_SecurityContext(pTransport->getSecurityContext());
487cde95 2536 m_flags |= NF_IS_SNMP;
d0a2ada6 2537 if (m_dwDynamicFlags & NDF_SNMP_UNREACHABLE)
2538 {
2539 m_dwDynamicFlags &= ~NDF_SNMP_UNREACHABLE;
2540 PostEvent(EVENT_SNMP_OK, m_id, NULL);
2541 sendPollerMsg(dwRqId, POLLER_INFO _T(" Connectivity with SNMP agent restored\r\n"));
2542 }
2543 unlockProperties();
2544 sendPollerMsg(dwRqId, _T(" SNMP agent is active (version %s)\r\n"),
2545 (m_snmpVersion == SNMP_VERSION_3) ? _T("3") : ((m_snmpVersion == SNMP_VERSION_2C) ? _T("2c") : _T("1")));
76720a09 2546
d0a2ada6 2547 TCHAR szBuffer[4096];
2548 if (SnmpGet(m_snmpVersion, pTransport, _T(".1.3.6.1.2.1.1.2.0"), NULL, 0, szBuffer, sizeof(szBuffer), SG_STRING_RESULT) != SNMP_ERR_SUCCESS)
2549 {
2550 // Set snmp object ID to .0.0 if it cannot be read
2551 _tcscpy(szBuffer, _T(".0.0"));
2552 }
2553 lockProperties();
2554 if (_tcscmp(m_szObjectId, szBuffer))
2555 {
2556 nx_strncpy(m_szObjectId, szBuffer, MAX_OID_LEN * 4);
2557 hasChanges = true;
2558 }
2559 unlockProperties();
76720a09 2560
d0a2ada6 2561 // Get system description
2562 if (SnmpGet(m_snmpVersion, pTransport, _T(".1.3.6.1.2.1.1.1.0"), NULL, 0, szBuffer, sizeof(szBuffer), SG_STRING_RESULT) == SNMP_ERR_SUCCESS)
2563 {
2564 TranslateStr(szBuffer, _T("\r\n"), _T(" "));
2565 TranslateStr(szBuffer, _T("\n"), _T(" "));
2566 TranslateStr(szBuffer, _T("\r"), _T(" "));
2567 lockProperties();
2568 if ((m_sysDescription == NULL) || _tcscmp(m_sysDescription, szBuffer))
76720a09 2569 {
d0a2ada6 2570 safe_free(m_sysDescription);
2571 m_sysDescription = _tcsdup(szBuffer);
2572 hasChanges = true;
2573 sendPollerMsg(dwRqId, _T(" System description changed to %s\r\n"), m_sysDescription);
76720a09 2574 }
d0a2ada6 2575 unlockProperties();
2576 }
76720a09 2577
d0a2ada6 2578 // Select device driver
2579 NetworkDeviceDriver *driver = FindDriverForNode(this, pTransport);
2580 DbgPrintf(5, _T("ConfPoll(%s): selected device driver %s"), m_name, driver->getName());
2581 lockProperties();
2582 if (driver != m_driver)
2583 {
2584 m_driver = driver;
2585 sendPollerMsg(dwRqId, _T(" New network device driver selected: %s\r\n"), m_driver->getName());
2586 }
2587 unlockProperties();
eec253a8 2588
d0a2ada6 2589 // Allow driver to gather additional info
2590 m_driver->analyzeDevice(pTransport, m_szObjectId, &m_customAttributes, &m_driverData);
291644e3
EJ
2591 NDD_MODULE_LAYOUT layout;
2592 m_driver->getModuleLayout(pTransport, &m_customAttributes, m_driverData, 1, &layout); // TODO module set to 1
191137b2
VK
2593 m_portRowCount = layout.rows;
2594 m_portNumberingScheme = layout.numberingScheme;
76720a09 2595
cf38357f
VK
2596 // Get sysName, sysContact, sysLocation
2597 if (querySnmpSysProperty(pTransport, _T(".1.3.6.1.2.1.1.5.0"), _T("name"), dwRqId, &m_sysName))
2598 hasChanges = true;
2599 if (querySnmpSysProperty(pTransport, _T(".1.3.6.1.2.1.1.4.0"), _T("contact"), dwRqId, &m_sysContact))
2600 hasChanges = true;
2601 if (querySnmpSysProperty(pTransport, _T(".1.3.6.1.2.1.1.6.0"), _T("location"), dwRqId, &m_sysLocation))
2602 hasChanges = true;
76720a09 2603
d0a2ada6 2604 // Check IP forwarding
2605 if (checkSNMPIntegerValue(pTransport, _T(".1.3.6.1.2.1.4.1.0"), 1))
2606 {
2607 lockProperties();
487cde95 2608 m_flags |= NF_IS_ROUTER;
d0a2ada6 2609 unlockProperties();
2610 }
2611 else
2612 {
2613 lockProperties();
487cde95 2614 m_flags &= ~NF_IS_ROUTER;
d0a2ada6 2615 unlockProperties();
2616 }
76720a09 2617
d0a2ada6 2618 checkIfXTable(pTransport);
2619 checkBridgeMib(pTransport);
76720a09 2620
d0a2ada6 2621 // Check for ENTITY-MIB support
2622 if (SnmpGet(m_snmpVersion, pTransport, _T(".1.3.6.1.2.1.47.1.4.1.0"), NULL, 0, szBuffer, sizeof(szBuffer), SG_RAW_RESULT) == SNMP_ERR_SUCCESS)
2623 {
2624 lockProperties();
487cde95 2625 m_flags |= NF_HAS_ENTITY_MIB;
d0a2ada6 2626 unlockProperties();
2627
2628 ComponentTree *components = BuildComponentTree(this, pTransport);
2629 lockProperties();
2630 if (m_components != NULL)
2631 m_components->decRefCount();
2632 m_components = components;
2633 unlockProperties();
2634 }
2635 else
2636 {
2637 lockProperties();
487cde95 2638 m_flags &= ~NF_HAS_ENTITY_MIB;
d0a2ada6 2639 if (m_components != NULL)
76720a09 2640 {
d0a2ada6 2641 m_components->decRefCount();
2642 m_components = NULL;
76720a09 2643 }
d0a2ada6 2644 unlockProperties();
2645 }
76720a09 2646
d0a2ada6 2647 // Check for printer MIB support
a93aa634 2648 bool present = false;
9c5ebc32 2649 SnmpWalk(pTransport, _T(".1.3.6.1.2.1.43"), IndicatorSnmpWalkerCallback, &present);
a93aa634 2650 if (present)
d0a2ada6 2651 {
2652 lockProperties();
487cde95 2653 m_flags |= NF_IS_PRINTER;
d0a2ada6 2654 unlockProperties();
2655 }
2656 else
2657 {
2658 lockProperties();
487cde95 2659 m_flags &= ~NF_IS_PRINTER;
d0a2ada6 2660 unlockProperties();
2661 }
76720a09 2662
d0a2ada6 2663 // Check for CDP (Cisco Discovery Protocol) support
2664 if (checkSNMPIntegerValue(pTransport, _T(".1.3.6.1.4.1.9.9.23.1.3.1.0"), 1))
2665 {
2666 lockProperties();
487cde95 2667 m_flags |= NF_IS_CDP;
d0a2ada6 2668 unlockProperties();
2669 }
2670 else
2671 {
2672 lockProperties();
487cde95 2673 m_flags &= ~NF_IS_CDP;
d0a2ada6 2674 unlockProperties();
2675 }
3a82d5ae 2676
d0a2ada6 2677 // Check for NDP (Nortel Discovery Protocol) support
2678 if (checkSNMPIntegerValue(pTransport, _T(".1.3.6.1.4.1.45.1.6.13.1.2.0"), 1))
2679 {
2680 lockProperties();
487cde95 2681 m_flags |= NF_IS_NDP;
d0a2ada6 2682 unlockProperties();
2683 }
2684 else
2685 {
2686 lockProperties();
487cde95 2687 m_flags &= ~NF_IS_NDP;
d0a2ada6 2688 unlockProperties();
2689 }
76720a09 2690
d0a2ada6 2691 // Check for LLDP (Link Layer Discovery Protocol) support
2692 if (SnmpGet(m_snmpVersion, pTransport, _T(".1.0.8802.1.1.2.1.3.2.0"), NULL, 0, szBuffer, sizeof(szBuffer), 0) == SNMP_ERR_SUCCESS)
2693 {
2694 lockProperties();
487cde95 2695 m_flags |= NF_IS_LLDP;
d0a2ada6 2696 unlockProperties();
2697
2698 INT32 type;
2699 BYTE data[256];
2700 UINT32 dataLen;
2701 if ((SnmpGetEx(pTransport, _T(".1.0.8802.1.1.2.1.3.1.0"), NULL, 0, &type, sizeof(INT32), 0, NULL) == SNMP_ERR_SUCCESS) &&
2702 (SnmpGetEx(pTransport, _T(".1.0.8802.1.1.2.1.3.2.0"), NULL, 0, data, 256, SG_RAW_RESULT, &dataLen) == SNMP_ERR_SUCCESS))
76720a09 2703 {
d0a2ada6 2704 BuildLldpId(type, data, dataLen, szBuffer, 1024);
2705 lockProperties();
2706 if ((m_lldpNodeId == NULL) || _tcscmp(m_lldpNodeId, szBuffer))
2707 {
2708 safe_free(m_lldpNodeId);
2709 m_lldpNodeId = _tcsdup(szBuffer);
2710 hasChanges = true;
2711 sendPollerMsg(dwRqId, _T(" LLDP node ID changed to %s\r\n"), m_lldpNodeId);
2712 }
2713 unlockProperties();
76720a09
VK
2714 }
2715
d0a2ada6 2716 ObjectArray<LLDP_LOCAL_PORT_INFO> *lldpPorts = GetLLDPLocalPortInfo(pTransport);
2717 lockProperties();
2718 delete m_lldpLocalPortInfo;
2719 m_lldpLocalPortInfo = lldpPorts;
2720 unlockProperties();
2721 }
2722 else
2723 {
2724 lockProperties();
487cde95 2725 m_flags &= ~NF_IS_LLDP;
d0a2ada6 2726 unlockProperties();
2727 }
76720a09 2728
d0a2ada6 2729 // Check for 802.1x support
2730 if (checkSNMPIntegerValue(pTransport, _T(".1.0.8802.1.1.1.1.1.1.0"), 1))
2731 {
2732 lockProperties();
487cde95 2733 m_flags |= NF_IS_8021X;
d0a2ada6 2734 unlockProperties();
2735 }
2736 else
2737 {
2738 lockProperties();
487cde95 2739 m_flags &= ~NF_IS_8021X;
d0a2ada6 2740 unlockProperties();
2741 }
c6afd26a 2742
d0a2ada6 2743 checkOSPFSupport(pTransport);
c6afd26a 2744
d0a2ada6 2745 // Get VRRP information
2746 VrrpInfo *vrrpInfo = GetVRRPInfo(this);
2747 if (vrrpInfo != NULL)
2748 {
2749 lockProperties();
487cde95 2750 m_flags |= NF_IS_VRRP;
d0a2ada6 2751 delete m_vrrpInfo;
2752 m_vrrpInfo = vrrpInfo;
2753 unlockProperties();
2754 }
2755 else
2756 {
2757 lockProperties();
487cde95 2758 m_flags &= ~NF_IS_VRRP;
d0a2ada6 2759 unlockProperties();
2760 }
8f26db67 2761
d0a2ada6 2762 // Get wireless controller data
2763 if ((m_driver != NULL) && m_driver->isWirelessController(pTransport, &m_customAttributes, m_driverData))
2764 {
2765 DbgPrintf(5, _T("ConfPoll(%s): node is wireless controller, reading access point information"), m_name);
2766 sendPollerMsg(dwRqId, _T(" Reading wireless access point information\r\n"));
2767 lockProperties();
487cde95 2768 m_flags |= NF_IS_WIFI_CONTROLLER;
d0a2ada6 2769 unlockProperties();
f1989a3a 2770
d0a2ada6 2771 int clusterMode = m_driver->getClusterMode(pTransport, &m_customAttributes, m_driverData);
4d2c3a54 2772
d0a2ada6 2773 ObjectArray<AccessPointInfo> *aps = m_driver->getAccessPoints(pTransport, &m_customAttributes, m_driverData);
2774 if (aps != NULL)
2775 {
2776 sendPollerMsg(dwRqId, POLLER_INFO _T(" %d wireless access points found\r\n"), aps->size());
2777 DbgPrintf(5, _T("ConfPoll(%s): got information about %d access points"), m_name, aps->size());
2778 int adopted = 0;
2779 for(int i = 0; i < aps->size(); i++)
2780 {
2781 AccessPointInfo *info = aps->get(i);
2782 if (info->getState() == AP_ADOPTED)
2783 adopted++;
2784
2785 bool newAp = false;
2786 AccessPoint *ap = (clusterMode == CLUSTER_MODE_STANDALONE) ? findAccessPointByMAC(info->getMacAddr()) : FindAccessPointByMAC(info->getMacAddr());
2787 if (ap == NULL)
2788 {
2789 String name;
2790
2791 if (info->getName() != NULL)
2792 {
2793 name = info->getName();
2794 }
2795 else
2796 {
2797 for(int j = 0; j < info->getRadioInterfaces()->size(); j++)
ffb44442 2798 {
d0a2ada6 2799 if (j > 0)
2800 name += _T("/");
2801 name += info->getRadioInterfaces()->get(j)->name;
ffb44442 2802 }
23ed00c4 2803 }
d0a2ada6 2804 ap = new AccessPoint((const TCHAR *)name, info->getIndex(), info->getMacAddr());
e7450f3b 2805 NetObjInsert(ap, true, false);
d0a2ada6 2806 DbgPrintf(5, _T("ConfPoll(%s): created new access point object %s [%d]"), m_name, ap->getName(), ap->getId());
2807 newAp = true;
2808 }
2809 ap->attachToNode(m_id);
2810 ap->setIpAddress(info->getIpAddr());
2811 if ((info->getState() == AP_ADOPTED) || newAp)
2812 {
2813 ap->updateRadioInterfaces(info->getRadioInterfaces());
2814 ap->updateInfo(info->getVendor(), info->getModel(), info->getSerial());
2815 }
2816 ap->unhide();
2817 ap->updateState(info->getState());
2818 }
f1989a3a 2819
d0a2ada6 2820 lockProperties();
2821 m_adoptedApCount = adopted;
2822 m_totalApCount = aps->size();
2823 unlockProperties();
f1989a3a 2824
d0a2ada6 2825 delete aps;
2826 }
2827 else
2828 {
2829 DbgPrintf(5, _T("ConfPoll(%s): failed to read access point information"), m_name);
2830 sendPollerMsg(dwRqId, POLLER_ERROR _T(" Failed to read access point information\r\n"));
2831 }
2832 }
2833 else
2834 {
2835 lockProperties();
487cde95 2836 m_flags &= ~NF_IS_WIFI_CONTROLLER;
d0a2ada6 2837 unlockProperties();
76720a09 2838 }
d0a2ada6 2839
2840 if (ConfigReadInt(_T("EnableCheckPointSNMP"), 0))
76720a09
VK
2841 {
2842 // Check for CheckPoint SNMP agent on port 161
c42b4551 2843 DbgPrintf(5, _T("ConfPoll(%s): checking for CheckPoint SNMP"), m_name);
5f8890c1
AK
2844 TCHAR szBuffer[4096];
2845 if (SnmpGet(SNMP_VERSION_1, pTransport, _T(".1.3.6.1.4.1.2620.1.1.10.0"), NULL, 0, szBuffer, sizeof(szBuffer), 0) == SNMP_ERR_SUCCESS)
76720a09 2846 {
c42b4551 2847 lockProperties();
76720a09
VK
2848 if (_tcscmp(m_szObjectId, _T(".1.3.6.1.4.1.2620.1.1")))
2849 {
2850 nx_strncpy(m_szObjectId, _T(".1.3.6.1.4.1.2620.1.1"), MAX_OID_LEN * 4);
2851 hasChanges = true;
2852 }
2853
487cde95 2854 m_flags |= NF_IS_SNMP | NF_IS_ROUTER;
76720a09 2855 m_dwDynamicFlags &= ~NDF_SNMP_UNREACHABLE;
c42b4551 2856 unlockProperties();
21c9acce 2857 sendPollerMsg(dwRqId, POLLER_INFO _T(" CheckPoint SNMP agent on port 161 is active\r\n"));
76720a09
VK
2858 }
2859 }
5f8890c1
AK
2860 delete pTransport;
2861 return hasChanges;
76720a09
VK
2862}
2863
2864/**
cf38357f
VK
2865 * Query SNMP sys property (sysName, sysLocation, etc.)
2866 */
2867bool Node::querySnmpSysProperty(SNMP_Transport *snmp, const TCHAR *oid, const TCHAR *propName, UINT32 pollRqId, TCHAR **value)
2868{
2869 TCHAR buffer[256];
2870 bool hasChanges = false;
2871
2872 if (SnmpGet(m_snmpVersion, snmp, oid, NULL, 0, buffer, sizeof(buffer), SG_STRING_RESULT) == SNMP_ERR_SUCCESS)
2873 {
2874 lockProperties();
2875 if ((*value == NULL) || _tcscmp(*value, buffer))
2876 {
2877 safe_free(*value);
2878 *value = _tcsdup(buffer);
2879 hasChanges = true;
2880 sendPollerMsg(pollRqId, _T(" System %s changed to %s\r\n"), propName, *value);
2881 }
2882 unlockProperties();
2883 }
2884 return hasChanges;
2885}
2886
2887/**
76720a09
VK
2888 * Configuration poll: check for BRIDGE MIB
2889 */
2890void Node::checkBridgeMib(SNMP_Transport *pTransport)
2891{
5f8890c1 2892 TCHAR szBuffer[4096];
d525c9ed 2893 if (SnmpGet(m_snmpVersion, pTransport, _T(".1.3.6.1.2.1.17.1.1.0"), NULL, 0, szBuffer, sizeof(szBuffer), SG_RAW_RESULT) == SNMP_ERR_SUCCESS)
76720a09 2894 {
5f8890c1 2895 lockProperties();
487cde95 2896 m_flags |= NF_IS_BRIDGE;
5f8890c1
AK
2897 memcpy(m_baseBridgeAddress, szBuffer, 6);
2898 unlockProperties();
2899
2900 // Check for Spanning Tree (IEEE 802.1d) MIB support
2901 if (checkSNMPIntegerValue(pTransport, _T(".1.3.6.1.2.1.17.2.1.0"), 3))
2902 {
2903 lockProperties();
2904 m_flags |= NF_IS_STP;
2905 unlockProperties();
2906 }
2907 else
2908 {
2909 lockProperties();
2910 m_flags &= ~NF_IS_STP;
2911 unlockProperties();
2912 }
76720a09
VK
2913 }
2914 else
2915 {
5f8890c1 2916 lockProperties();
487cde95 2917 m_flags &= ~(NF_IS_BRIDGE | NF_IS_STP);
5f8890c1 2918 unlockProperties();
76720a09
VK
2919 }
2920}
2921
2922/**
2923 * Configuration poll: check for ifXTable
2924 */
2925void Node::checkIfXTable(SNMP_Transport *pTransport)
2926{
5f8890c1
AK
2927 bool present = false;
2928 SnmpWalk(pTransport, _T(".1.3.6.1.2.1.31.1.1.1.1"), IndicatorSnmpWalkerCallback, &present);
a93aa634 2929 if (present)
76720a09 2930 {
5f8890c1 2931 lockProperties();
487cde95 2932 m_flags |= NF_HAS_IFXTABLE;
5f8890c1 2933 unlockProperties();
76720a09
VK
2934 }
2935 else
2936 {
5f8890c1 2937 lockProperties();
487cde95 2938 m_flags &= ~NF_HAS_IFXTABLE;
5f8890c1 2939 unlockProperties();
76720a09
VK
2940 }
2941}
2942
2943/**
dfed892b
VK
2944 * Delete duplicate interfaces
2945 * (find and delete multiple interfaces with same ifIndex value created by version prior to 2.0-M3)
2946 */
2947bool Node::deleteDuplicateInterfaces(UINT32 rqid)
2948{
2949 ObjectArray<Interface> deleteList(16, 16, false);
2950
db091a1f
VK
2951 lockChildList(false);
2952 for(int i = 0; i < m_childList->size(); i++)
dfed892b 2953 {
db091a1f
VK
2954 NetObj *curr = m_childList->get(i);
2955
2956 if ((curr->getObjectClass() != OBJECT_INTERFACE) ||
2957 ((Interface *)curr)->isManuallyCreated())
dfed892b 2958 continue;
db091a1f
VK
2959 Interface *iface = (Interface *)curr;
2960 for(int j = i + 1; j < m_childList->size(); j++)
dfed892b 2961 {
db091a1f
VK
2962 NetObj *next = m_childList->get(j);
2963
2964 if ((next->getObjectClass() != OBJECT_INTERFACE) ||
2965 ((Interface *)next)->isManuallyCreated() ||
2966 (deleteList.contains((Interface *)next)))
dfed892b 2967 continue;
db091a1f 2968 if (iface->getIfIndex() == ((Interface *)next)->getIfIndex())
dfed892b 2969 {
db091a1f 2970 deleteList.add((Interface *)next);
dfed892b 2971 DbgPrintf(6, _T("Node::deleteDuplicateInterfaces(%s [%d]): found duplicate interface %s [%d], original %s [%d], ifIndex=%d"),
db091a1f 2972 m_name, m_id, next->getName(), next->getId(), iface->getName(), iface->getId(), iface->getIfIndex());
dfed892b
VK
2973 }
2974 }
2975 }
db091a1f 2976 unlockChildList();
dfed892b
VK
2977
2978 for(int i = 0; i < deleteList.size(); i++)
2979 {
2980 Interface *iface = deleteList.get(i);
2981 sendPollerMsg(rqid, POLLER_WARNING _T(" Duplicate interface \"%s\" deleted\r\n"), iface->getName());
2982 deleteInterface(iface);
2983 }
2984
2985 return deleteList.size() > 0;
2986}
2987
2988/**
76720a09
VK
2989 * Update interface configuration
2990 */
dfed892b 2991bool Node::updateInterfaceConfiguration(UINT32 rqid, int maskBits)
eec253a8 2992{
dfed892b
VK
2993 sendPollerMsg(rqid, _T("Checking interface configuration...\r\n"));
2994
2995 bool hasChanges = deleteDuplicateInterfaces(rqid);
2996
2997 InterfaceList *pIfList = getInterfaceList();
eec253a8
VK
2998 if (pIfList != NULL)
2999 {
5f8890c1 3000 DbgPrintf(6, _T("Node::updateInterfaceConfiguration(%s [%u]): got %d interfaces"), m_name, m_id, pIfList->size());
eec253a8
VK
3001
3002 // Find non-existing interfaces
db091a1f
VK
3003 lockChildList(false);
3004 ObjectArray<Interface> deleteList(m_childList->size(), 8, false);
3005 for(int i = 0; i < m_childList->size(); i++)
eec253a8 3006 {
db091a1f 3007 if (m_childList->get(i)->getObjectClass() == OBJECT_INTERFACE)
eec253a8 3008 {
db091a1f 3009 Interface *pInterface = (Interface *)m_childList->get(i);
5f8890c1
AK
3010 if (!pInterface->isManuallyCreated())
3011 {
dfed892b 3012 int j;
5f8890c1
AK
3013 for(j = 0; j < pIfList->size(); j++)
3014 {
3015 if (pIfList->get(j)->index == pInterface->getIfIndex())
3016 break;
3017 }
3018
3019 if (j == pIfList->size())
3020 {
3021 // No such interface in current configuration, add it to delete list
5f6e8d09 3022 deleteList.add(pInterface);
5f8890c1
AK
3023 }
3024 }
eec253a8
VK
3025 }
3026 }
db091a1f 3027 unlockChildList();
eec253a8
VK
3028
3029 // Delete non-existent interfaces
5f6e8d09 3030 if (deleteList.size() > 0)
eec253a8 3031 {
5f6e8d09 3032 for(int j = 0; j < deleteList.size(); j++)
eec253a8 3033 {
5f6e8d09
VK
3034 Interface *iface = deleteList.get(j);
3035 sendPollerMsg(rqid, POLLER_WARNING _T(" Interface \"%s\" is no longer exist\r\n"), iface->getName());
3036 const InetAddress& addr = iface->getFirstIpAddress();
3037 PostEvent(EVENT_INTERFACE_DELETED, m_id, "dsAd", iface->getIfIndex(), iface->getName(), &addr, addr.getMaskBits());
3038 deleteInterface(iface);
eec253a8 3039 }
dfed892b 3040 hasChanges = true;
eec253a8 3041 }
eec253a8
VK
3042
3043 // Add new interfaces and check configuration of existing
dfed892b 3044 for(int j = 0; j < pIfList->size(); j++)
eec253a8 3045 {
5f8890c1 3046 InterfaceInfo *ifInfo = pIfList->get(j);
eec253a8
VK
3047 BOOL bNewInterface = TRUE;
3048
db091a1f
VK
3049 lockChildList(false);
3050 for(int i = 0; i < m_childList->size(); i++)
eec253a8 3051 {
db091a1f 3052 if (m_childList->get(i)->getObjectClass() == OBJECT_INTERFACE)
eec253a8 3053 {
db091a1f 3054 Interface *pInterface = (Interface *)m_childList->get(i);
eec253a8 3055
c30c0c0f 3056 if (ifInfo->index == pInterface->getIfIndex())
eec253a8
VK
3057 {
3058 // Existing interface, check configuration
e83d726c 3059 if (memcmp(ifInfo->macAddr, "\x00\x00\x00\x00\x00\x00", MAC_ADDR_LENGTH) &&
c30c0c0f 3060 memcmp(ifInfo->macAddr, pInterface->getMacAddr(), MAC_ADDR_LENGTH))
eec253a8
VK
3061 {
3062 TCHAR szOldMac[16], szNewMac[16];
3063
3064 BinToStr((BYTE *)pInterface->getMacAddr(), MAC_ADDR_LENGTH, szOldMac);
e95680e5 3065 BinToStr(ifInfo->macAddr, MAC_ADDR_LENGTH, szNewMac);
c42b4551
VK
3066 PostEvent(EVENT_MAC_ADDR_CHANGED, m_id, "idsss",
3067 pInterface->getId(), pInterface->getIfIndex(),
3068 pInterface->getName(), szOldMac, szNewMac);
e55ff6f9 3069 pInterface->setMacAddr(ifInfo->macAddr, true);
e95680e5
VK
3070 }
3071 if (_tcscmp(ifInfo->name, pInterface->getName()))
3072 {
3073 pInterface->setName(ifInfo->name);
eec253a8 3074 }
e95680e5 3075 if (_tcscmp(ifInfo->description, pInterface->getDescription()))
eec253a8 3076 {
e95680e5 3077 pInterface->setDescription(ifInfo->description);
eec253a8 3078 }
e95680e5 3079 if (_tcscmp(ifInfo->alias, pInterface->getAlias()))
478d4ff4 3080 {
e95680e5 3081 pInterface->setAlias(ifInfo->alias);
478d4ff4 3082 }
5f8890c1
AK
3083 if (ifInfo->bridgePort != pInterface->getBridgePortNumber())
3084 {
3085 pInterface->setBridgePortNumber(ifInfo->bridgePort);
3086 }
3087 if (ifInfo->slot != pInterface->getSlotNumber())
3088 {
3089 pInterface->setSlotNumber(ifInfo->slot);
3090 }
3091 if (ifInfo->port != pInterface->getPortNumber())
3092 {
3093 pInterface->setPortNumber(ifInfo->port);
3094 }
3095 if (ifInfo->isPhysicalPort != pInterface->isPhysicalPort())
3096 {
3097 pInterface->setPhysicalPortFlag(ifInfo->isPhysicalPort);
3098 }
33560996
VK
3099 if (ifInfo->mtu != pInterface->getMTU())
3100 {
3101 pInterface->setMTU(ifInfo->mtu);
3102 }
3d37f7bf
VK
3103 if (ifInfo->speed != pInterface->getSpeed())
3104 {
3105 pInterface->setSpeed(ifInfo->speed);
3106 }
3107 if ((ifInfo->ifTableSuffixLength != pInterface->getIfTableSuffixLen()) ||
d0a2ada6 3108 memcmp(ifInfo->ifTableSuffix, pInterface->getIfTableSuffix(),