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