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