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