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