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