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