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