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