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