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