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