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