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