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