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