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