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