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