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