improvements in web UI look
[public/netxms.git] / src / server / core / node.cpp
CommitLineData
5039dede
AK
1/*
2** NetXMS - Network Management System
33ae8896 3** Copyright (C) 2003-2012 Victor Kirhenshtein
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"
24
25
26//
46117060
VK
27// Externals
28//
29
30extern Queue g_statusPollQueue;
31extern Queue g_configPollQueue;
32extern Queue g_topologyPollQueue;
33extern Queue g_routePollQueue;
34extern Queue g_discoveryPollQueue;
35
36
37//
5039dede
AK
38// Node class default constructor
39//
40
5a7d6a10 41Node::Node() : Template()
5039dede 42{
5ad2167d 43 m_primaryName[0] = 0;
a65c1819 44 m_iStatus = STATUS_UNKNOWN;
5039dede
AK
45 m_dwFlags = 0;
46 m_dwDynamicFlags = 0;
52c31148 47 m_zoneId = 0;
5039dede
AK
48 m_wAgentPort = AGENT_LISTEN_PORT;
49 m_wAuthMethod = AUTH_NONE;
50 m_szSharedSecret[0] = 0;
51 m_iStatusPollType = POLL_ICMP_PING;
5d2c5741 52 m_snmpVersion = SNMP_VERSION_1;
5039dede 53 m_wSNMPPort = SNMP_DEFAULT_PORT;
35f836fe
VK
54 char community[MAX_COMMUNITY_LENGTH];
55 ConfigReadStrA(_T("DefaultCommunityString"), community, MAX_COMMUNITY_LENGTH, "public");
5d2c5741 56 m_snmpSecurity = new SNMP_SecurityContext(community);
5039dede
AK
57 m_szObjectId[0] = 0;
58 m_tLastDiscoveryPoll = 0;
59 m_tLastStatusPoll = 0;
60 m_tLastConfigurationPoll = 0;
b6ead716 61 m_tLastTopologyPoll = 0;
5039dede
AK
62 m_tLastRTUpdate = 0;
63 m_hPollerMutex = MutexCreate();
64 m_hAgentAccessMutex = MutexCreate();
65 m_mutexRTAccess = MutexCreate();
66 m_mutexTopoAccess = MutexCreate();
67 m_pAgentConnection = NULL;
fed33789 68 m_lastAgentTrapId = 0;
5039dede
AK
69 m_szAgentVersion[0] = 0;
70 m_szPlatformName[0] = 0;
0ecc2200
VK
71 m_sysDescription = NULL;
72 m_sysName = NULL;
73 m_lldpNodeId = NULL;
cc8ce218
VK
74 m_paramList = NULL;
75 m_tableList = NULL;
5039dede
AK
76 m_dwPollerNode = 0;
77 m_dwProxyNode = 0;
78 m_dwSNMPProxy = 0;
79 memset(m_qwLastEvents, 0, sizeof(QWORD) * MAX_LAST_EVENTS);
80 m_pRoutingTable = NULL;
81 m_tFailTimeSNMP = 0;
82 m_tFailTimeAgent = 0;
040c45fa 83 m_linkLayerNeighbors = NULL;
0d75ea88 84 m_vrrpInfo = NULL;
5039dede 85 m_tLastTopologyPoll = 0;
040c45fa
VK
86 m_pTopology = NULL;
87 m_topologyRebuildTimestamp = 0;
5039dede
AK
88 m_iPendingStatus = -1;
89 m_iPollCount = 0;
90 m_iRequiredPollCount = 0; // Use system default
91 m_nUseIfXTable = IFXTABLE_DEFAULT; // Use system default
ab621f39 92 m_jobQueue = new ServerJobQueue();
f42b8099 93 m_fdb = NULL;
7f632dfe 94 m_vlans = NULL;
9796ce45 95 m_driver = NULL;
50d0de67 96 m_components = NULL;
3eab63f2 97 memset(m_baseBridgeAddress, 0, MAC_ADDR_LENGTH);
5039dede
AK
98}
99
100
101//
102// Constructor for new node object
103//
104
5a7d6a10 105Node::Node(DWORD dwAddr, DWORD dwFlags, DWORD dwProxyNode, DWORD dwSNMPProxy, DWORD dwZone) : Template()
5039dede 106{
5ad2167d 107 IpToStr(dwAddr, m_primaryName);
a65c1819 108 m_iStatus = STATUS_UNKNOWN;
5039dede
AK
109 m_dwIpAddr = dwAddr;
110 m_dwFlags = dwFlags;
111 m_dwDynamicFlags = 0;
52c31148 112 m_zoneId = dwZone;
5039dede
AK
113 m_wAgentPort = AGENT_LISTEN_PORT;
114 m_wAuthMethod = AUTH_NONE;
115 m_szSharedSecret[0] = 0;
116 m_iStatusPollType = POLL_ICMP_PING;
5d2c5741 117 m_snmpVersion = SNMP_VERSION_1;
5039dede 118 m_wSNMPPort = SNMP_DEFAULT_PORT;
35f836fe
VK
119 char community[MAX_COMMUNITY_LENGTH];
120 ConfigReadStrA(_T("DefaultCommunityString"), community, MAX_COMMUNITY_LENGTH, "public");
5d2c5741 121 m_snmpSecurity = new SNMP_SecurityContext(community);
5039dede
AK
122 IpToStr(dwAddr, m_szName); // Make default name from IP address
123 m_szObjectId[0] = 0;
124 m_tLastDiscoveryPoll = 0;
125 m_tLastStatusPoll = 0;
126 m_tLastConfigurationPoll = 0;
b6ead716 127 m_tLastTopologyPoll = 0;
5039dede
AK
128 m_tLastRTUpdate = 0;
129 m_hPollerMutex = MutexCreate();
130 m_hAgentAccessMutex = MutexCreate();
131 m_mutexRTAccess = MutexCreate();
132 m_mutexTopoAccess = MutexCreate();
133 m_pAgentConnection = NULL;
fed33789 134 m_lastAgentTrapId = 0;
5039dede
AK
135 m_szAgentVersion[0] = 0;
136 m_szPlatformName[0] = 0;
0ecc2200
VK
137 m_sysDescription = NULL;
138 m_sysName = NULL;
139 m_lldpNodeId = NULL;
cc8ce218
VK
140 m_paramList = NULL;
141 m_tableList = NULL;
5039dede
AK
142 m_dwPollerNode = 0;
143 m_dwProxyNode = dwProxyNode;
144 m_dwSNMPProxy = dwSNMPProxy;
145 memset(m_qwLastEvents, 0, sizeof(QWORD) * MAX_LAST_EVENTS);
146 m_bIsHidden = TRUE;
147 m_pRoutingTable = NULL;
148 m_tFailTimeSNMP = 0;
149 m_tFailTimeAgent = 0;
040c45fa 150 m_linkLayerNeighbors = NULL;
0d75ea88 151 m_vrrpInfo = NULL;
5039dede 152 m_tLastTopologyPoll = 0;
040c45fa
VK
153 m_pTopology = NULL;
154 m_topologyRebuildTimestamp = 0;
5039dede
AK
155 m_iPendingStatus = -1;
156 m_iPollCount = 0;
157 m_iRequiredPollCount = 0; // Use system default
158 m_nUseIfXTable = IFXTABLE_DEFAULT; // Use system default
ab621f39 159 m_jobQueue = new ServerJobQueue();
f42b8099 160 m_fdb = NULL;
7f632dfe 161 m_vlans = NULL;
9796ce45 162 m_driver = NULL;
50d0de67 163 m_components = NULL;
3eab63f2 164 memset(m_baseBridgeAddress, 0, MAC_ADDR_LENGTH);
5039dede
AK
165}
166
167
168//
169// Node destructor
170//
171
172Node::~Node()
173{
174 MutexDestroy(m_hPollerMutex);
175 MutexDestroy(m_hAgentAccessMutex);
176 MutexDestroy(m_mutexRTAccess);
177 MutexDestroy(m_mutexTopoAccess);
178 delete m_pAgentConnection;
cc8ce218
VK
179 delete m_paramList;
180 delete m_tableList;
bb151059 181 safe_free(m_sysDescription);
5039dede 182 DestroyRoutingTable(m_pRoutingTable);
a9ad9f61
VK
183 if (m_linkLayerNeighbors != NULL)
184 m_linkLayerNeighbors->decRefCount();
0d75ea88 185 delete m_vrrpInfo;
5039dede 186 delete m_pTopology;
ab621f39 187 delete m_jobQueue;
5d2c5741 188 delete m_snmpSecurity;
f42b8099
VK
189 if (m_fdb != NULL)
190 m_fdb->decRefCount();
7f632dfe
VK
191 if (m_vlans != NULL)
192 m_vlans->decRefCount();
50d0de67 193 delete m_components;
5039dede
AK
194}
195
196
197//
198// Create object from database data
199//
200
201BOOL Node::CreateFromDB(DWORD dwId)
202{
5039dede
AK
203 int i, iNumRows;
204 DWORD dwSubnetId;
205 NetObj *pObject;
206 BOOL bResult = FALSE;
207
208 m_dwId = dwId;
209
89135050 210 if (!loadCommonProperties())
5039dede 211 {
35f836fe 212 DbgPrintf(2, _T("Cannot load common properties for node object %d"), dwId);
5039dede
AK
213 return FALSE;
214 }
215
4866d57b
VK
216 DB_STATEMENT hStmt = DBPrepare(g_hCoreDB,
217 _T("SELECT primary_name,primary_ip,node_flags,")
218 _T("snmp_version,auth_method,secret,")
219 _T("agent_port,status_poll_type,snmp_oid,agent_version,")
220 _T("platform_name,poller_node_id,zone_guid,")
221 _T("proxy_node,snmp_proxy,required_polls,uname,")
222 _T("use_ifxtable,snmp_port,community,usm_auth_password,")
223 _T("usm_priv_password,usm_methods,snmp_sys_name,bridge_base_addr,")
224 _T("runtime_flags FROM nodes WHERE id=?"));
225 if (hStmt == NULL)
226 return FALSE;
227
228 DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, dwId);
92c51b1d 229 DB_RESULT hResult = DBSelectPrepared(hStmt);
e2babedf 230 if (hResult == NULL)
b1789b80
VK
231 {
232 DBFreeStatement(hStmt);
5039dede 233 return FALSE; // Query failed
b1789b80 234 }
5039dede
AK
235
236 if (DBGetNumRows(hResult) == 0)
237 {
238 DBFreeResult(hResult);
b1789b80 239 DBFreeStatement(hStmt);
5d2c5741 240 DbgPrintf(2, _T("Missing record in \"nodes\" table for node object %d"), dwId);
5039dede
AK
241 return FALSE;
242 }
243
5ad2167d
VK
244 DBGetField(hResult, 0, 0, m_primaryName, MAX_DNS_NAME);
245 m_dwIpAddr = DBGetFieldIPAddr(hResult, 0, 1);
246 m_dwFlags = DBGetFieldULong(hResult, 0, 2);
247 m_snmpVersion = DBGetFieldLong(hResult, 0, 3);
248 m_wAuthMethod = (WORD)DBGetFieldLong(hResult, 0, 4);
249 DBGetField(hResult, 0, 5, m_szSharedSecret, MAX_SECRET_LENGTH);
250 m_wAgentPort = (WORD)DBGetFieldLong(hResult, 0, 6);
251 m_iStatusPollType = DBGetFieldLong(hResult, 0, 7);
252 DBGetField(hResult, 0, 8, m_szObjectId, MAX_OID_LEN * 4);
5d2c5741 253 DBGetField(hResult, 0, 9, m_szAgentVersion, MAX_AGENT_VERSION_LEN);
5d2c5741 254 DBGetField(hResult, 0, 10, m_szPlatformName, MAX_PLATFORM_NAME_LEN);
5d2c5741 255 m_dwPollerNode = DBGetFieldULong(hResult, 0, 11);
52c31148 256 m_zoneId = DBGetFieldULong(hResult, 0, 12);
5d2c5741
VK
257 m_dwProxyNode = DBGetFieldULong(hResult, 0, 13);
258 m_dwSNMPProxy = DBGetFieldULong(hResult, 0, 14);
259 m_iRequiredPollCount = DBGetFieldLong(hResult, 0, 15);
0ecc2200 260 m_sysDescription = DBGetField(hResult, 0, 16, NULL, 0);
5d2c5741 261 m_nUseIfXTable = (BYTE)DBGetFieldLong(hResult, 0, 17);
65e2005b 262 m_wSNMPPort = (WORD)DBGetFieldLong(hResult, 0, 18);
5039dede 263
5d2c5741 264 // SNMP authentication parameters
35f836fe
VK
265 char snmpAuthObject[256], snmpAuthPassword[256], snmpPrivPassword[256];
266 DBGetFieldA(hResult, 0, 19, snmpAuthObject, 256);
267 DBGetFieldA(hResult, 0, 20, snmpAuthPassword, 256);
268 DBGetFieldA(hResult, 0, 21, snmpPrivPassword, 256);
3408b115 269 int snmpMethods = DBGetFieldLong(hResult, 0, 22);
5d2c5741
VK
270 delete m_snmpSecurity;
271 m_snmpSecurity = new SNMP_SecurityContext(snmpAuthObject, snmpAuthPassword, snmpPrivPassword, snmpMethods & 0xFF, snmpMethods >> 8);
14b98b3a 272 m_snmpSecurity->setSecurityModel((m_snmpVersion == SNMP_VERSION_3) ? SNMP_SECURITY_MODEL_USM : SNMP_SECURITY_MODEL_V2C);
5d2c5741 273
88ac8e88 274 m_sysName = DBGetField(hResult, 0, 23, NULL, 0);
d74c80ea 275
3eab63f2
VK
276 TCHAR baseAddr[16];
277 TCHAR *value = DBGetField(hResult, 0, 24, baseAddr, 16);
278 if (value != NULL)
279 StrToBin(value, m_baseBridgeAddress, MAC_ADDR_LENGTH);
280
4866d57b 281 m_dwDynamicFlags = DBGetFieldULong(hResult, 0, 25);
b6ead716 282 m_dwDynamicFlags &= NDF_PERSISTENT; // Clear out all non-persistent runtime flags
4866d57b 283
5039dede 284 DBFreeResult(hResult);
b1789b80 285 DBFreeStatement(hStmt);
5039dede
AK
286
287 if (!m_bIsDeleted)
288 {
289 // Link node to subnets
92c51b1d
VK
290 hStmt = DBPrepare(g_hCoreDB, _T("SELECT subnet_id FROM nsmap WHERE node_id=?"));
291 if (hStmt == NULL)
292 return FALSE;
293
294 DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, m_dwId);
295 hResult = DBSelectPrepared(hStmt);
5039dede 296 if (hResult == NULL)
92c51b1d
VK
297 {
298 DBFreeStatement(hStmt);
5039dede 299 return FALSE; // Query failed
92c51b1d 300 }
5039dede
AK
301
302 iNumRows = DBGetNumRows(hResult);
5039dede
AK
303 for(i = 0; i < iNumRows; i++)
304 {
305 dwSubnetId = DBGetFieldULong(hResult, i, 0);
306 pObject = FindObjectById(dwSubnetId);
307 if (pObject == NULL)
308 {
309 nxlog_write(MSG_INVALID_SUBNET_ID, EVENTLOG_ERROR_TYPE, "dd", dwId, dwSubnetId);
310 break;
311 }
312 else if (pObject->Type() != OBJECT_SUBNET)
313 {
314 nxlog_write(MSG_SUBNET_NOT_SUBNET, EVENTLOG_ERROR_TYPE, "dd", dwId, dwSubnetId);
315 break;
316 }
317 else
318 {
319 pObject->AddChild(this);
320 AddParent(pObject);
5039dede
AK
321 }
322 }
323
324 DBFreeResult(hResult);
92c51b1d
VK
325 DBFreeStatement(hStmt);
326
327 loadItemsFromDB();
89135050 328 loadACLFromDB();
5039dede
AK
329
330 // Walk through all items in the node and load appropriate thresholds
a6c1f07f 331 bResult = TRUE;
16d6f798
VK
332 for(i = 0; i < m_dcObjects->size(); i++)
333 if (!m_dcObjects->get(i)->loadThresholdsFromDB())
5039dede 334 {
5d2c5741 335 DbgPrintf(3, _T("Cannot load thresholds for DCI %d of node %d (%s)"),
16d6f798 336 m_dcObjects->get(i)->getId(), dwId, m_szName);
5039dede
AK
337 bResult = FALSE;
338 }
339 }
340 else
341 {
342 bResult = TRUE;
343 }
344
345 return bResult;
346}
347
348
349//
350// Save object to database
351//
352
353BOOL Node::SaveToDB(DB_HANDLE hdb)
354{
3eab63f2 355 TCHAR szQuery[4096], szIpAddr[16], baseAddress[16];
5039dede
AK
356 BOOL bNewObject = TRUE;
357 BOOL bResult;
358
359 // Lock object's access
360 LockData();
361
89135050 362 saveCommonProperties(hdb);
5039dede 363
5039dede 364 // Form and execute INSERT or UPDATE query
4b7d8903 365 int snmpMethods = m_snmpSecurity->getAuthMethod() | (m_snmpSecurity->getPrivMethod() << 8);
ba89fed2
VK
366 if (IsDatabaseRecordExist(hdb, _T("nodes"), _T("id"), m_dwId))
367 {
368 _sntprintf(szQuery, 4096,
369 _T("UPDATE nodes SET primary_ip='%s',primary_name=%s,snmp_port=%d,")
370 _T("node_flags=%d,snmp_version=%d,community=%s,")
371 _T("status_poll_type=%d,agent_port=%d,auth_method=%d,secret=%s,")
372 _T("snmp_oid=%s,uname=%s,agent_version=%s,platform_name=%s,poller_node_id=%d,")
373 _T("zone_guid=%d,proxy_node=%d,snmp_proxy=%d,")
374 _T("required_polls=%d,use_ifxtable=%d,usm_auth_password=%s,")
375 _T("usm_priv_password=%s,usm_methods=%d,snmp_sys_name=%s,bridge_base_addr='%s',")
376 _T("runtime_flags=%d WHERE id=%d"),
377 IpToStr(m_dwIpAddr, szIpAddr), (const TCHAR *)DBPrepareString(hdb, m_primaryName), m_wSNMPPort,
378 m_dwFlags, m_snmpVersion, (const TCHAR *)DBPrepareStringA(hdb, m_snmpSecurity->getCommunity()),
379 m_iStatusPollType, m_wAgentPort, m_wAuthMethod,
380 (const TCHAR *)DBPrepareString(hdb, m_szSharedSecret),
381 (const TCHAR *)DBPrepareString(hdb, m_szObjectId),
382 (const TCHAR *)DBPrepareString(hdb, m_sysDescription),
383 (const TCHAR *)DBPrepareString(hdb, m_szAgentVersion),
384 (const TCHAR *)DBPrepareString(hdb, m_szPlatformName), m_dwPollerNode, m_zoneId,
385 m_dwProxyNode, m_dwSNMPProxy, m_iRequiredPollCount,
386 m_nUseIfXTable, (const TCHAR *)DBPrepareStringA(hdb, m_snmpSecurity->getAuthPassword()),
387 (const TCHAR *)DBPrepareStringA(hdb, m_snmpSecurity->getPrivPassword()), snmpMethods,
388 (const TCHAR *)DBPrepareString(hdb, m_sysName),
389 BinToStr(m_baseBridgeAddress, MAC_ADDR_LENGTH, baseAddress), (int)m_dwDynamicFlags, (int)m_dwId);
390 }
391 else
65e2005b
VK
392 {
393 _sntprintf(szQuery, 4096,
5ad2167d 394 _T("INSERT INTO nodes (id,primary_ip,primary_name,snmp_port,")
65e2005b
VK
395 _T("node_flags,snmp_version,community,status_poll_type,")
396 _T("agent_port,auth_method,secret,snmp_oid,proxy_node,")
5ad2167d 397 _T("agent_version,platform_name,uname,")
65e2005b 398 _T("poller_node_id,zone_guid,snmp_proxy,required_polls,")
3eab63f2 399 _T("use_ifxtable,usm_auth_password,usm_priv_password,usm_methods,")
4866d57b
VK
400 _T("snmp_sys_name,bridge_base_addr,runtime_flags) VALUES ")
401 _T("(%d,'%s',%s,%d,%d,%d,%s,%d,%d,%d,%s,%s,%d,%s,%s,%s,%d,%d,%d,%d,%d,%s,%s,%d,%s,'%s',%d)"),
402 (int)m_dwId, IpToStr(m_dwIpAddr, szIpAddr), (const TCHAR *)DBPrepareString(hdb, m_primaryName),
5ad2167d
VK
403 (int)m_wSNMPPort, m_dwFlags, m_snmpVersion, (
404 const TCHAR *)DBPrepareStringA(hdb, m_snmpSecurity->getCommunity()),
65e2005b
VK
405 m_iStatusPollType, (int)m_wAgentPort, m_wAuthMethod,
406 (const TCHAR *)DBPrepareString(hdb, m_szSharedSecret),
407 (const TCHAR *)DBPrepareString(hdb, m_szObjectId),
5ad2167d 408 m_dwProxyNode, (const TCHAR *)DBPrepareString(hdb, m_szAgentVersion),
65e2005b 409 (const TCHAR *)DBPrepareString(hdb, m_szPlatformName),
0ecc2200 410 (const TCHAR *)DBPrepareString(hdb, m_sysDescription),
52c31148 411 m_dwPollerNode, m_zoneId, m_dwSNMPProxy, m_iRequiredPollCount, m_nUseIfXTable,
35f836fe 412 (const TCHAR *)DBPrepareStringA(hdb, m_snmpSecurity->getAuthPassword()),
d74c80ea 413 (const TCHAR *)DBPrepareStringA(hdb, m_snmpSecurity->getPrivPassword()), snmpMethods,
3eab63f2 414 (const TCHAR *)DBPrepareString(hdb, m_sysName),
4866d57b 415 BinToStr(m_baseBridgeAddress, MAC_ADDR_LENGTH, baseAddress), (int)m_dwDynamicFlags);
65e2005b 416 }
5039dede 417 bResult = DBQuery(hdb, szQuery);
5039dede 418
7c521895 419 // Save access list
89135050 420 saveACLToDB(hdb);
7c521895
VK
421
422 UnlockData();
423
5039dede
AK
424 // Save data collection items
425 if (bResult)
426 {
7c521895 427 lockDciAccess();
16d6f798
VK
428 for(int i = 0; i < m_dcObjects->size(); i++)
429 m_dcObjects->get(i)->saveToDB(hdb);
7c521895 430 unlockDciAccess();
5039dede
AK
431 }
432
7c521895
VK
433 // Clear modifications flag
434 LockData();
5039dede 435 m_bIsModified = FALSE;
7c521895 436 UnlockData();
5039dede 437
7c521895 438 return bResult;
5039dede
AK
439}
440
441
442//
443// Delete object from database
444//
445
65e2005b 446BOOL Node::DeleteFromDB()
5039dede 447{
35f836fe 448 TCHAR szQuery[256];
5039dede
AK
449 BOOL bSuccess;
450
451 bSuccess = Template::DeleteFromDB();
452 if (bSuccess)
453 {
d6124fa0 454 _sntprintf(szQuery, 256, _T("DELETE FROM nodes WHERE id=%d"), (int)m_dwId);
5039dede 455 QueueSQLRequest(szQuery);
d6124fa0 456 _sntprintf(szQuery, 256, _T("DELETE FROM nsmap WHERE node_id=%d"), (int)m_dwId);
5039dede 457 QueueSQLRequest(szQuery);
d6124fa0
VK
458 _sntprintf(szQuery, 256, _T("DROP TABLE idata_%d"), (int)m_dwId);
459 QueueSQLRequest(szQuery);
ba89fed2 460 _sntprintf(szQuery, 256, _T("DROP TABLE tdata_%d"), (int)m_dwId);
5039dede
AK
461 QueueSQLRequest(szQuery);
462 }
463 return bSuccess;
464}
465
466
467//
468// Get ARP cache from node
469//
470
7c521895 471ARP_CACHE *Node::getArpCache()
5039dede
AK
472{
473 ARP_CACHE *pArpCache = NULL;
474
475 if (m_dwFlags & NF_IS_LOCAL_MGMT)
476 {
477 pArpCache = GetLocalArpCache();
478 }
479 else if (m_dwFlags & NF_IS_NATIVE_AGENT)
480 {
7c521895
VK
481 agentLock();
482 if (connectToAgent())
4687826e 483 pArpCache = m_pAgentConnection->getArpCache();
7c521895 484 agentUnlock();
5039dede
AK
485 }
486 else if (m_dwFlags & NF_IS_SNMP)
487 {
488 SNMP_Transport *pTransport;
489
cd9f247e 490 pTransport = createSnmpTransport();
803d47be
VK
491 if (pTransport != NULL)
492 {
493 pArpCache = SnmpGetArpCache(m_snmpVersion, pTransport);
494 delete pTransport;
495 }
5039dede
AK
496 }
497
498 return pArpCache;
499}
500
501
502//
503// Get list of interfaces from node
504//
505
98762401 506InterfaceList *Node::getInterfaceList()
5039dede 507{
98762401 508 InterfaceList *pIfList = NULL;
5039dede 509
b741f151 510 if ((m_dwFlags & NF_IS_NATIVE_AGENT) && (!(m_dwFlags & NF_DISABLE_NXCP)))
5039dede 511 {
7c521895
VK
512 agentLock();
513 if (connectToAgent())
5039dede 514 {
4687826e 515 pIfList = m_pAgentConnection->getInterfaceList();
5039dede 516 }
7c521895 517 agentUnlock();
5039dede 518 }
b741f151
VK
519 if ((pIfList == NULL) && (m_dwFlags & NF_IS_LOCAL_MGMT))
520 {
521 pIfList = GetLocalInterfaceList();
522 }
5039dede 523 if ((pIfList == NULL) && (m_dwFlags & NF_IS_SNMP) &&
9796ce45 524 (!(m_dwFlags & NF_DISABLE_SNMP)) && (m_driver != NULL))
5039dede
AK
525 {
526 SNMP_Transport *pTransport;
9796ce45 527 bool useIfXTable;
5039dede 528
cd9f247e 529 pTransport = createSnmpTransport();
803d47be 530 if (pTransport != NULL)
5039dede 531 {
803d47be
VK
532 if (m_nUseIfXTable == IFXTABLE_DEFAULT)
533 {
9796ce45 534 useIfXTable = (ConfigReadInt(_T("UseIfXTable"), 1) != 0) ? true : false;
803d47be
VK
535 }
536 else
537 {
9796ce45 538 useIfXTable = (m_nUseIfXTable == IFXTABLE_ENABLED) ? true : false;
803d47be 539 }
9796ce45
VK
540
541 int useAliases = ConfigReadInt(_T("UseInterfaceAliases"), 0);
542 pIfList = m_driver->getInterfaces(pTransport, &m_customAttributes, useAliases, useIfXTable);
eec253a8 543
8792fe27 544 if ((pIfList != NULL) && (m_dwFlags & NF_IS_BRIDGE))
eec253a8
VK
545 {
546 BridgeMapPorts(m_snmpVersion, pTransport, pIfList);
547 }
803d47be 548 delete pTransport;
5039dede 549 }
5039dede
AK
550 }
551
552 if (pIfList != NULL)
0d75ea88 553 {
024c3faf 554 checkInterfaceNames(pIfList);
0d75ea88
VK
555 addVrrpInterfaces(pIfList);
556 }
5039dede
AK
557
558 return pIfList;
559}
560
561
562//
0d75ea88
VK
563// Add VRRP interfaces to interface list
564//
565
98762401 566void Node::addVrrpInterfaces(InterfaceList *ifList)
0d75ea88
VK
567{
568 int i, j, k;
569 TCHAR buffer[32];
570
571 LockData();
572 if (m_vrrpInfo != NULL)
573 {
574 DbgPrintf(6, _T("Node::addVrrpInterfaces(node=%s [%d]): m_vrrpInfo->getSize()=%d"), m_szName, (int)m_dwId, m_vrrpInfo->getSize());
575
576 for(i = 0; i < m_vrrpInfo->getSize(); i++)
577 {
578 VrrpRouter *router = m_vrrpInfo->getRouter(i);
579 DbgPrintf(6, _T("Node::addVrrpInterfaces(node=%s [%d]): vrouter %d state=%d"), m_szName, (int)m_dwId, i, router->getState());
580 if (router->getState() != VRRP_STATE_MASTER)
581 continue; // Do not add interfaces if router is not in master state
582
583 // Get netmask for this VR
584 DWORD netmask = 0;
98762401
VK
585 for(j = 0; j < ifList->getSize(); j++)
586 if (ifList->get(j)->dwIndex == router->getIfIndex())
0d75ea88 587 {
98762401 588 netmask = ifList->get(j)->dwIpNetMask;
0d75ea88
VK
589 break;
590 }
591
592 // Walk through all VR virtual IPs
593 for(j = 0; j < router->getVipCount(); j++)
594 {
595 DWORD vip = router->getVip(j);
596 DbgPrintf(6, _T("Node::addVrrpInterfaces(node=%s [%d]): checking VIP %s@%d"), m_szName, (int)m_dwId, IpToStr(vip, buffer), i);
597 if (vip != 0)
598 {
98762401
VK
599 for(k = 0; k < ifList->getSize(); k++)
600 if (ifList->get(k)->dwIpAddr == vip)
0d75ea88 601 break;
98762401 602 if (k == ifList->getSize())
0d75ea88 603 {
60557d06
VK
604 NX_INTERFACE_INFO iface;
605 memset(&iface, 0, sizeof(NX_INTERFACE_INFO));
98762401
VK
606 _sntprintf(iface.szName, MAX_DB_STRING, _T("vrrp.%u.%u.%d"), router->getId(), router->getIfIndex(), j);
607 memcpy(iface.bMacAddr, router->getVirtualMacAddr(), MAC_ADDR_LENGTH);
608 iface.dwIpAddr = vip;
609 iface.dwIpNetMask = netmask;
610 ifList->add(&iface);
611 DbgPrintf(6, _T("Node::addVrrpInterfaces(node=%s [%d]): added interface %s"), m_szName, (int)m_dwId, iface.szName);
0d75ea88
VK
612 }
613 }
614 }
615 }
616 }
617 UnlockData();
618}
619
620
621//
5039dede
AK
622// Find interface by index and node IP
623// Returns pointer to interface object or NULL if appropriate interface couldn't be found
624//
625
58b3e451 626Interface *Node::findInterface(DWORD dwIndex, DWORD dwHostAddr)
5039dede
AK
627{
628 DWORD i;
629 Interface *pInterface;
630
631 LockChildList(FALSE);
632 for(i = 0; i < m_dwChildCount; i++)
633 if (m_pChildList[i]->Type() == OBJECT_INTERFACE)
634 {
635 pInterface = (Interface *)m_pChildList[i];
eec253a8 636 if (pInterface->getIfIndex() == dwIndex)
5039dede 637 {
eec253a8
VK
638 if (((pInterface->IpAddr() & pInterface->getIpNetMask()) ==
639 (dwHostAddr & pInterface->getIpNetMask())) ||
5039dede
AK
640 (dwHostAddr == INADDR_ANY))
641 {
642 UnlockChildList();
643 return pInterface;
644 }
645 }
646 }
647 UnlockChildList();
648 return NULL;
649}
650
651
652//
478d4ff4 653// Find interface by name or description
630e15d6
VK
654// Returns pointer to interface object or NULL if appropriate interface couldn't be found
655//
656
657Interface *Node::findInterface(const TCHAR *name)
658{
659 DWORD i;
660 Interface *pInterface;
661
662 LockChildList(FALSE);
663 for(i = 0; i < m_dwChildCount; i++)
664 if (m_pChildList[i]->Type() == OBJECT_INTERFACE)
665 {
666 pInterface = (Interface *)m_pChildList[i];
478d4ff4 667 if (!_tcsicmp(pInterface->Name(), name) || !_tcsicmp(pInterface->getDescription(), name))
630e15d6
VK
668 {
669 UnlockChildList();
670 return pInterface;
671 }
672 }
673 UnlockChildList();
674 return NULL;
675}
676
677
678//
3f8c54e7
VK
679// Find interface by slot/port pair
680// Returns pointer to interface object or NULL if appropriate interface couldn't be found
681//
682
683Interface *Node::findInterfaceBySlotAndPort(DWORD slot, DWORD port)
684{
685 DWORD i;
686 Interface *pInterface;
687
3f8c54e7
VK
688 LockChildList(FALSE);
689 for(i = 0; i < m_dwChildCount; i++)
690 if (m_pChildList[i]->Type() == OBJECT_INTERFACE)
691 {
692 pInterface = (Interface *)m_pChildList[i];
4c16cdc7 693 if (pInterface->isPhysicalPort() && (pInterface->getSlotNumber() == slot) && (pInterface->getPortNumber() == port))
3f8c54e7
VK
694 {
695 UnlockChildList();
696 return pInterface;
697 }
698 }
699 UnlockChildList();
700 return NULL;
701}
702
703
704//
eec253a8
VK
705// Find interface by MAC address
706// Returns pointer to interface object or NULL if appropriate interface couldn't be found
707//
708
709Interface *Node::findInterfaceByMAC(const BYTE *macAddr)
710{
711 DWORD i;
712 Interface *pInterface;
713
714 LockChildList(FALSE);
715 for(i = 0; i < m_dwChildCount; i++)
716 if (m_pChildList[i]->Type() == OBJECT_INTERFACE)
717 {
718 pInterface = (Interface *)m_pChildList[i];
719 if (!memcmp(pInterface->getMacAddr(), macAddr, MAC_ADDR_LENGTH))
720 {
721 UnlockChildList();
722 return pInterface;
723 }
724 }
725 UnlockChildList();
726 return NULL;
727}
728
729
730//
731// Find interface by IP address
732// Returns pointer to interface object or NULL if appropriate interface couldn't be found
733//
734
735Interface *Node::findInterfaceByIP(DWORD ipAddr)
736{
737 DWORD i;
738 Interface *pInterface;
739
740 if (ipAddr == 0)
741 return NULL;
742
743 LockChildList(FALSE);
744 for(i = 0; i < m_dwChildCount; i++)
745 if (m_pChildList[i]->Type() == OBJECT_INTERFACE)
746 {
747 pInterface = (Interface *)m_pChildList[i];
748 if (pInterface->IpAddr() == ipAddr)
749 {
750 UnlockChildList();
751 return pInterface;
752 }
753 }
754 UnlockChildList();
755 return NULL;
756}
757
758
759//
760// Find interface by bridge port number
761//
762
763Interface *Node::findBridgePort(DWORD bridgePortNumber)
764{
765 DWORD i;
766 Interface *pInterface;
767
768 LockChildList(FALSE);
769 for(i = 0; i < m_dwChildCount; i++)
770 if (m_pChildList[i]->Type() == OBJECT_INTERFACE)
771 {
772 pInterface = (Interface *)m_pChildList[i];
773 if (pInterface->getBridgePortNumber() == bridgePortNumber)
774 {
775 UnlockChildList();
776 return pInterface;
777 }
778 }
779 UnlockChildList();
780 return NULL;
781}
782
783
784//
f42b8099
VK
785// Find connection point for node
786//
787
46117060 788Interface *Node::findConnectionPoint(DWORD *localIfId, BYTE *localMacAddr, bool *exactMatch)
f42b8099
VK
789{
790 Interface *cp = NULL;
791 LockChildList(FALSE);
792 for(DWORD i = 0; i < m_dwChildCount; i++)
793 if (m_pChildList[i]->Type() == OBJECT_INTERFACE)
794 {
795 Interface *iface = (Interface *)m_pChildList[i];
46117060 796 cp = FindInterfaceConnectionPoint(iface->getMacAddr(), exactMatch);
f42b8099 797 if (cp != NULL)
06a93345
VK
798 {
799 *localIfId = iface->Id();
eec253a8 800 memcpy(localMacAddr, iface->getMacAddr(), MAC_ADDR_LENGTH);
f42b8099 801 break;
06a93345 802 }
f42b8099
VK
803 }
804 UnlockChildList();
805 return cp;
806}
807
808
809//
5039dede
AK
810// Check if given IP address is one of node's interfaces
811//
812
58b3e451 813BOOL Node::isMyIP(DWORD dwIpAddr)
5039dede
AK
814{
815 DWORD i;
816
817 LockChildList(FALSE);
818 for(i = 0; i < m_dwChildCount; i++)
819 if (m_pChildList[i]->Type() == OBJECT_INTERFACE)
820 {
821 if (((Interface *)m_pChildList[i])->IpAddr() == dwIpAddr)
822 {
823 UnlockChildList();
824 return TRUE;
825 }
826 }
827 UnlockChildList();
828 return FALSE;
829}
830
831
832//
833// Create new interface
834//
835
9214177b
VK
836Interface *Node::createNewInterface(DWORD dwIpAddr, DWORD dwNetMask, const TCHAR *name, const TCHAR *descr,
837 DWORD dwIndex, DWORD dwType, BYTE *pbMacAddr, DWORD bridgePort,
838 DWORD slot, DWORD port, bool physPort, bool manuallyCreated)
5039dede
AK
839{
840 Interface *pInterface;
841 Subnet *pSubnet = NULL;
842 Cluster *pCluster;
eec253a8 843 bool bAddToSubnet, bSyntheticMask = false;
5039dede 844
f7694811
VK
845 DbgPrintf(5, _T("Node::createNewInterface(%08X, %08X, %s, %d, %d, bp=%d, slot=%d, port=%d) called for node %s [%d]"),
846 dwIpAddr, dwNetMask, CHECK_NULL(name), dwIndex, dwType, bridgePort, slot, port, m_szName, m_dwId);
5039dede
AK
847
848 // Find subnet to place interface object to
314c4f38 849 if ((dwIpAddr != 0) && (dwType != IFTYPE_SOFTWARE_LOOPBACK) && ((dwIpAddr & 0xFF000000) != 0x7F000000))
5039dede 850 {
7c521895 851 pCluster = getMyCluster();
58b3e451 852 bAddToSubnet = (pCluster != NULL) ? !pCluster->isSyncAddr(dwIpAddr) : TRUE;
f7694811 853 DbgPrintf(5, _T("Node::createNewInterface: node=%s [%d] cluster=%s [%d] add=%d"),
5039dede
AK
854 m_szName, m_dwId, (pCluster != NULL) ? pCluster->Name() : _T("(null)"),
855 (pCluster != NULL) ? pCluster->Id() : 0, bAddToSubnet);
856 if (bAddToSubnet)
857 {
89135050 858 pSubnet = FindSubnetForNode(m_zoneId, dwIpAddr);
5039dede
AK
859 if (pSubnet == NULL)
860 {
861 // Check if netmask is 0 (detect), and if yes, create
862 // new subnet with class mask
863 if (dwNetMask == 0)
864 {
865 bSyntheticMask = TRUE;
866 if (dwIpAddr < 0xE0000000)
867 {
868 dwNetMask = 0xFFFFFF00; // Class A, B or C
869 }
870 else
871 {
872 TCHAR szBuffer[16];
873
874 // Multicast address??
875 DbgPrintf(2, _T("Attempt to create interface object with multicast address %s"),
876 IpToStr(dwIpAddr, szBuffer));
877 }
878 }
879
880 // Create new subnet object
881 if (dwIpAddr < 0xE0000000)
882 {
52c31148 883 pSubnet = new Subnet(dwIpAddr & dwNetMask, dwNetMask, m_zoneId, bSyntheticMask);
5039dede 884 NetObjInsert(pSubnet, TRUE);
89135050
VK
885 if (IsZoningEnabled())
886 {
024c3faf 887 Zone *zone = FindZoneByGUID(m_zoneId);
89135050
VK
888 if (zone != NULL)
889 {
890 zone->addSubnet(pSubnet);
891 }
892 }
893 else
894 {
895 g_pEntireNet->AddSubnet(pSubnet);
896 }
5039dede
AK
897 }
898 }
899 else
900 {
901 // Set correct netmask if we was asked for it
902 if (dwNetMask == 0)
903 {
eec253a8
VK
904 dwNetMask = pSubnet->getIpNetMask();
905 bSyntheticMask = pSubnet->isSyntheticMask();
5039dede
AK
906 }
907 }
908 }
909 }
910
911 // Create interface object
35f836fe 912 if (name != NULL)
4ecd55b3 913 pInterface = new Interface(name, (descr != NULL) ? descr : name, dwIndex, dwIpAddr, dwNetMask, dwType, m_zoneId);
5039dede 914 else
4ecd55b3 915 pInterface = new Interface(dwIpAddr, dwNetMask, m_zoneId, bSyntheticMask);
5039dede 916 if (pbMacAddr != NULL)
eec253a8
VK
917 pInterface->setMacAddr(pbMacAddr);
918 pInterface->setBridgePortNumber(bridgePort);
76f9abfd
VK
919 pInterface->setSlotNumber(slot);
920 pInterface->setPortNumber(port);
4c16cdc7 921 pInterface->setPhysicalPortFlag(physPort);
9214177b 922 pInterface->setManualCreationFlag(manuallyCreated);
5039dede
AK
923
924 // Insert to objects' list and generate event
925 NetObjInsert(pInterface, TRUE);
eec253a8 926 addInterface(pInterface);
5039dede 927 if (!m_bIsHidden)
478d4ff4 928 pInterface->unhide();
5039dede
AK
929 PostEvent(EVENT_INTERFACE_ADDED, m_dwId, "dsaad", pInterface->Id(),
930 pInterface->Name(), pInterface->IpAddr(),
eec253a8 931 pInterface->getIpNetMask(), pInterface->getIfIndex());
5039dede
AK
932
933 // Bind node to appropriate subnet
934 if (pSubnet != NULL)
935 {
936 pSubnet->AddNode(this);
937
938 // Check if subnet mask is correct on interface
eec253a8 939 if ((pSubnet->getIpNetMask() != pInterface->getIpNetMask()) && !pSubnet->isSyntheticMask())
5039dede
AK
940 {
941 PostEvent(EVENT_INCORRECT_NETMASK, m_dwId, "idsaa", pInterface->Id(),
eec253a8
VK
942 pInterface->getIfIndex(), pInterface->Name(),
943 pInterface->getIpNetMask(), pSubnet->getIpNetMask());
5039dede
AK
944 }
945 }
9214177b
VK
946
947 return pInterface;
5039dede
AK
948}
949
950
951//
952// Delete interface from node
953//
954
eec253a8 955void Node::deleteInterface(Interface *pInterface)
5039dede
AK
956{
957 DWORD i;
958
dfb38baf
VK
959 DbgPrintf(5, _T("Node::deleteInterface(node=%s [%d], interface=%s [%d])"), m_szName, m_dwId, pInterface->Name(), pInterface->Id());
960
5039dede 961 // Check if we should unlink node from interface's subnet
314c4f38 962 if ((pInterface->IpAddr() != 0) && !pInterface->isExcludedFromTopology())
5039dede
AK
963 {
964 BOOL bUnlink = TRUE;
965
966 LockChildList(FALSE);
967 for(i = 0; i < m_dwChildCount; i++)
968 if (m_pChildList[i]->Type() == OBJECT_INTERFACE)
969 if (m_pChildList[i] != pInterface)
eec253a8
VK
970 if ((((Interface *)m_pChildList[i])->IpAddr() & ((Interface *)m_pChildList[i])->getIpNetMask()) ==
971 (pInterface->IpAddr() & pInterface->getIpNetMask()))
5039dede
AK
972 {
973 bUnlink = FALSE;
974 break;
975 }
976 UnlockChildList();
977
978 if (bUnlink)
979 {
980 // Last interface in subnet, should unlink node
89135050 981 Subnet *pSubnet = FindSubnetByIP(m_zoneId, pInterface->IpAddr() & pInterface->getIpNetMask());
5039dede
AK
982 if (pSubnet != NULL)
983 {
984 DeleteParent(pSubnet);
985 pSubnet->DeleteChild(this);
986 }
dfb38baf 987 DbgPrintf(5, _T("Node::deleteInterface(node=%s [%d], interface=%s [%d]): unlinked from subnet %s [%d]"),
2a1431bc
VK
988 m_szName, m_dwId, pInterface->Name(), pInterface->Id(),
989 (pSubnet != NULL) ? pSubnet->Name() : _T("(null)"),
990 (pSubnet != NULL) ? pSubnet->Id() : 0);
5039dede
AK
991 }
992 }
27de5dab 993 pInterface->deleteObject();
5039dede
AK
994}
995
996
997//
998// Calculate node status based on child objects status
999//
1000
27f9598d 1001void Node::calculateCompoundStatus(BOOL bForcedRecalc)
5039dede
AK
1002{
1003 int iOldStatus = m_iStatus;
1004 static DWORD dwEventCodes[] = { EVENT_NODE_NORMAL, EVENT_NODE_MINOR,
1005 EVENT_NODE_WARNING, EVENT_NODE_MAJOR, EVENT_NODE_CRITICAL,
1006 EVENT_NODE_UNKNOWN, EVENT_NODE_UNMANAGED };
1007
27f9598d 1008 NetObj::calculateCompoundStatus(bForcedRecalc);
5039dede
AK
1009 if (m_iStatus != iOldStatus)
1010 PostEvent(dwEventCodes[m_iStatus], m_dwId, "d", iOldStatus);
1011}
1012
1013
1014//
1015// Perform status poll on node
1016//
1017
58b3e451 1018void Node::statusPoll(ClientSession *pSession, DWORD dwRqId, int nPoller)
5039dede 1019{
46117060
VK
1020 if (m_dwDynamicFlags & NDF_DELETE_IN_PROGRESS)
1021 {
1022 if (dwRqId == 0)
1023 m_dwDynamicFlags &= ~NDF_QUEUED_FOR_STATUS_POLL;
1024 return;
1025 }
1026
5039dede
AK
1027 DWORD i, dwPollListSize, dwOldFlags = m_dwFlags;
1028 NetObj *pPollerNode = NULL, **ppPollList;
1029 BOOL bAllDown;
1030 Queue *pQueue; // Delayed event queue
1031 SNMP_Transport *pTransport;
1032 Cluster *pCluster;
1033 time_t tNow, tExpire;
1034
1035 pQueue = new Queue;
35f836fe 1036 SetPollerInfo(nPoller, _T("wait for lock"));
7c521895 1037 pollerLock();
5039dede 1038 m_pPollRequestor = pSession;
35f836fe
VK
1039 SendPollerMsg(dwRqId, _T("Starting status poll for node %s\r\n"), m_szName);
1040 DbgPrintf(5, _T("Starting status poll for node %s (ID: %d)"), m_szName, m_dwId);
5039dede
AK
1041
1042 // Read capability expiration time and current time
1043 tExpire = (time_t)ConfigReadULong(_T("CapabilityExpirationTime"), 604800);
1044 tNow = time(NULL);
1045
1046 // Check SNMP agent connectivity
1047restart_agent_check:
15d6f8c9 1048 if ((m_dwFlags & NF_IS_SNMP) && (!(m_dwFlags & NF_DISABLE_SNMP)) && (m_dwIpAddr != 0))
5039dede
AK
1049 {
1050 TCHAR szBuffer[256];
1051 DWORD dwResult;
1052
35f836fe 1053 DbgPrintf(6, _T("StatusPoll(%s): check SNMP"), m_szName);
cd9f247e 1054 pTransport = createSnmpTransport();
803d47be
VK
1055 if (pTransport == NULL)
1056 {
35f836fe 1057 DbgPrintf(6, _T("StatusPoll(%s): cannot create SNMP transport"), m_szName);
803d47be
VK
1058 goto skip_snmp_check;
1059 }
1060
35f836fe
VK
1061 SetPollerInfo(nPoller, _T("check SNMP"));
1062 SendPollerMsg(dwRqId, _T("Checking SNMP agent connectivity\r\n"));
f42b8099 1063 dwResult = SnmpGet(m_snmpVersion, pTransport, _T(".1.3.6.1.2.1.1.2.0"), NULL, 0, szBuffer, 256, 0);
5039dede
AK
1064 if ((dwResult == SNMP_ERR_SUCCESS) || (dwResult == SNMP_ERR_NO_OBJECT))
1065 {
1066 if (m_dwDynamicFlags & NDF_SNMP_UNREACHABLE)
1067 {
1068 m_dwDynamicFlags &= ~NDF_SNMP_UNREACHABLE;
1069 PostEventEx(pQueue, EVENT_SNMP_OK, m_dwId, NULL);
35f836fe 1070 SendPollerMsg(dwRqId, POLLER_INFO _T("Connectivity with SNMP agent restored\r\n"));
5039dede
AK
1071 }
1072 }
1073 else
1074 {
35f836fe 1075 SendPollerMsg(dwRqId, POLLER_ERROR _T("SNMP agent unreachable\r\n"));
5039dede
AK
1076 if (m_dwDynamicFlags & NDF_SNMP_UNREACHABLE)
1077 {
1078 if ((tNow > m_tFailTimeSNMP + tExpire) &&
1079 (!(m_dwDynamicFlags & NDF_UNREACHABLE)))
1080 {
1081 m_dwFlags &= ~NF_IS_SNMP;
1082 m_dwDynamicFlags &= ~NDF_SNMP_UNREACHABLE;
1083 m_szObjectId[0] = 0;
35f836fe 1084 SendPollerMsg(dwRqId, POLLER_WARNING _T("Attribute isSNMP set to FALSE\r\n"));
5039dede
AK
1085 }
1086 }
1087 else
1088 {
1089 m_dwDynamicFlags |= NDF_SNMP_UNREACHABLE;
1090 PostEventEx(pQueue, EVENT_SNMP_FAIL, m_dwId, NULL);
1091 m_tFailTimeSNMP = tNow;
1092 }
1093 }
1094 delete pTransport;
35f836fe 1095 DbgPrintf(6, _T("StatusPoll(%s): SNMP check finished"), m_szName);
5039dede
AK
1096 }
1097
803d47be 1098skip_snmp_check:
5039dede 1099 // Check native agent connectivity
15d6f8c9 1100 if ((m_dwFlags & NF_IS_NATIVE_AGENT) && (!(m_dwFlags & NF_DISABLE_NXCP)) && (m_dwIpAddr != 0))
5039dede 1101 {
35f836fe
VK
1102 DbgPrintf(6, _T("StatusPoll(%s): checking agent"), m_szName);
1103 SetPollerInfo(nPoller, _T("check agent"));
1104 SendPollerMsg(dwRqId, _T("Checking NetXMS agent connectivity\r\n"));
c3acd0f6
VK
1105
1106 DWORD error, socketError;
a4569c4d
VK
1107 agentLock();
1108 if (connectToAgent(&error, &socketError))
5039dede 1109 {
35f836fe 1110 DbgPrintf(7, _T("StatusPoll(%s): connected to agent"), m_szName);
5039dede
AK
1111 if (m_dwDynamicFlags & NDF_AGENT_UNREACHABLE)
1112 {
1113 m_dwDynamicFlags &= ~NDF_AGENT_UNREACHABLE;
1114 PostEventEx(pQueue, EVENT_AGENT_OK, m_dwId, NULL);
35f836fe 1115 SendPollerMsg(dwRqId, POLLER_INFO _T("Connectivity with NetXMS agent restored\r\n"));
5039dede 1116 }
5039dede
AK
1117 }
1118 else
1119 {
35f836fe
VK
1120 DbgPrintf(6, _T("StatusPoll(%s): agent unreachable, error=%d, socketError=%d"), m_szName, (int)error, (int)socketError);
1121 SendPollerMsg(dwRqId, POLLER_ERROR _T("NetXMS agent unreachable\r\n"));
5039dede
AK
1122 if (m_dwDynamicFlags & NDF_AGENT_UNREACHABLE)
1123 {
1124 if ((tNow > m_tFailTimeAgent + tExpire) &&
1125 (!(m_dwDynamicFlags & NDF_UNREACHABLE)))
1126 {
1127 m_dwFlags &= ~NF_IS_NATIVE_AGENT;
1128 m_dwDynamicFlags &= ~NDF_AGENT_UNREACHABLE;
1129 m_szPlatformName[0] = 0;
1130 m_szAgentVersion[0] = 0;
35f836fe 1131 SendPollerMsg(dwRqId, POLLER_WARNING _T("Attribute isNetXMSAgent set to FALSE\r\n"));
5039dede
AK
1132 }
1133 }
1134 else
1135 {
1136 m_dwDynamicFlags |= NDF_AGENT_UNREACHABLE;
1137 PostEventEx(pQueue, EVENT_AGENT_FAIL, m_dwId, NULL);
1138 m_tFailTimeAgent = tNow;
1139 }
1140 }
a4569c4d 1141 agentUnlock();
35f836fe 1142 DbgPrintf(7, _T("StatusPoll(%s): agent check finished"), m_szName);
5039dede
AK
1143 }
1144
35f836fe 1145 SetPollerInfo(nPoller, _T("prepare polling list"));
5039dede
AK
1146
1147 // Find service poller node object
1148 LockData();
1149 if (m_dwPollerNode != 0)
1150 {
f3218755
VK
1151 DWORD id = m_dwPollerNode;
1152 UnlockData();
1153 pPollerNode = FindObjectById(id);
5039dede
AK
1154 if (pPollerNode != NULL)
1155 {
1156 if (pPollerNode->Type() != OBJECT_NODE)
1157 pPollerNode = NULL;
1158 }
1159 }
f3218755
VK
1160 else
1161 {
1162 UnlockData();
1163 }
5039dede
AK
1164
1165 // If nothing found, use management server
1166 if (pPollerNode == NULL)
1167 {
1168 pPollerNode = FindObjectById(g_dwMgmtNode);
1169 if (pPollerNode != NULL)
1170 pPollerNode->IncRefCount();
1171 }
1172 else
1173 {
1174 pPollerNode->IncRefCount();
1175 }
1176
1177 // Create polling list
1178 ppPollList = (NetObj **)malloc(sizeof(NetObj *) * m_dwChildCount);
1179 LockChildList(FALSE);
1180 for(i = 0, dwPollListSize = 0; i < m_dwChildCount; i++)
1181 if (m_pChildList[i]->Status() != STATUS_UNMANAGED)
1182 {
1183 m_pChildList[i]->IncRefCount();
1184 ppPollList[dwPollListSize++] = m_pChildList[i];
1185 }
1186 UnlockChildList();
1187
1188 // Poll interfaces and services
35f836fe
VK
1189 SetPollerInfo(nPoller, _T("child poll"));
1190 DbgPrintf(7, _T("StatusPoll(%s): starting child object poll"), m_szName);
7c521895 1191 pCluster = getMyCluster();
cd9f247e 1192 pTransport = createSnmpTransport();
5039dede
AK
1193 for(i = 0; i < dwPollListSize; i++)
1194 {
1195 switch(ppPollList[i]->Type())
1196 {
1197 case OBJECT_INTERFACE:
35f836fe 1198 DbgPrintf(7, _T("StatusPoll(%s): polling interface %d [%s]"), m_szName, ppPollList[i]->Id(), ppPollList[i]->Name());
5039dede 1199 ((Interface *)ppPollList[i])->StatusPoll(pSession, dwRqId, pQueue,
58b3e451 1200 (pCluster != NULL) ? pCluster->isSyncAddr(((Interface *)ppPollList[i])->IpAddr()) : FALSE,
5039dede
AK
1201 pTransport);
1202 break;
1203 case OBJECT_NETWORKSERVICE:
35f836fe 1204 DbgPrintf(7, _T("StatusPoll(%s): polling network service %d [%s]"), m_szName, ppPollList[i]->Id(), ppPollList[i]->Name());
5039dede
AK
1205 ((NetworkService *)ppPollList[i])->StatusPoll(pSession, dwRqId,
1206 (Node *)pPollerNode, pQueue);
1207 break;
1208 default:
1209 break;
1210 }
1211 ppPollList[i]->DecRefCount();
1212 }
1213 delete pTransport;
1214 safe_free(ppPollList);
35f836fe 1215 DbgPrintf(7, _T("StatusPoll(%s): finished child object poll"), m_szName);
5039dede
AK
1216
1217 // Check if entire node is down
15d6f8c9
VK
1218 // This check is disabled for nodes without IP address
1219 if (m_dwIpAddr != 0)
5039dede 1220 {
15d6f8c9
VK
1221 LockChildList(FALSE);
1222 if (m_dwChildCount > 0)
1223 {
1224 for(i = 0, bAllDown = TRUE; i < m_dwChildCount; i++)
1225 if ((m_pChildList[i]->Type() == OBJECT_INTERFACE) &&
1226 (m_pChildList[i]->Status() != STATUS_CRITICAL) &&
1227 (m_pChildList[i]->Status() != STATUS_UNKNOWN) &&
1228 (m_pChildList[i]->Status() != STATUS_UNMANAGED) &&
1229 (m_pChildList[i]->Status() != STATUS_DISABLED))
1230 {
1231 bAllDown = FALSE;
1232 break;
1233 }
1234 }
1235 else
1236 {
1237 bAllDown = FALSE;
1238 }
1239 UnlockChildList();
1240 if (bAllDown && (m_dwFlags & NF_IS_NATIVE_AGENT) &&
1241 (!(m_dwFlags & NF_DISABLE_NXCP)))
1242 if (!(m_dwDynamicFlags & NDF_AGENT_UNREACHABLE))
1243 bAllDown = FALSE;
1244 if (bAllDown && (m_dwFlags & NF_IS_SNMP) &&
1245 (!(m_dwFlags & NF_DISABLE_SNMP)))
1246 if (!(m_dwDynamicFlags & NDF_SNMP_UNREACHABLE))
1247 bAllDown = FALSE;
1248 if (bAllDown)
1249 {
1250 if (!(m_dwDynamicFlags & NDF_UNREACHABLE))
1251 {
1252 m_dwDynamicFlags |= NDF_UNREACHABLE;
1253 PostEvent(EVENT_NODE_DOWN, m_dwId, NULL);
35f836fe 1254 SendPollerMsg(dwRqId, POLLER_ERROR _T("Node is unreachable\r\n"));
15d6f8c9
VK
1255 }
1256 else
1257 {
35f836fe 1258 SendPollerMsg(dwRqId, POLLER_WARNING _T("Node is still unreachable\r\n"));
15d6f8c9
VK
1259 }
1260 }
1261 else
1262 {
1263 if (m_dwDynamicFlags & NDF_UNREACHABLE)
1264 {
1265 m_dwDynamicFlags &= ~(NDF_UNREACHABLE | NDF_SNMP_UNREACHABLE | NDF_AGENT_UNREACHABLE);
1266 PostEvent(EVENT_NODE_UP, m_dwId, NULL);
35f836fe 1267 SendPollerMsg(dwRqId, POLLER_INFO _T("Node recovered from unreachable state\r\n"));
15d6f8c9
VK
1268 goto restart_agent_check;
1269 }
1270 else
1271 {
35f836fe 1272 SendPollerMsg(dwRqId, POLLER_INFO _T("Node is connected\r\n"));
15d6f8c9
VK
1273 }
1274 }
5039dede 1275 }
5039dede
AK
1276
1277 // Send delayed events and destroy delayed event queue
1278 ResendEvents(pQueue);
1279 delete pQueue;
1280
35f836fe 1281 SetPollerInfo(nPoller, _T("cleanup"));
5039dede
AK
1282 if (pPollerNode != NULL)
1283 pPollerNode->DecRefCount();
1284
1285 if (dwOldFlags != m_dwFlags)
1286 {
1287 PostEvent(EVENT_NODE_FLAGS_CHANGED, m_dwId, "xx", dwOldFlags, m_dwFlags);
1288 LockData();
1289 Modify();
1290 UnlockData();
1291 }
1292
27f9598d 1293 calculateCompoundStatus();
5039dede 1294 m_tLastStatusPoll = time(NULL);
35f836fe
VK
1295 SendPollerMsg(dwRqId, _T("Finished status poll for node %s\r\n"), m_szName);
1296 SendPollerMsg(dwRqId, _T("Node status after poll is %s\r\n"), g_szStatusText[m_iStatus]);
5039dede
AK
1297 m_pPollRequestor = NULL;
1298 if (dwRqId == 0)
1299 m_dwDynamicFlags &= ~NDF_QUEUED_FOR_STATUS_POLL;
7c521895 1300 pollerUnlock();
35f836fe 1301 DbgPrintf(5, _T("Finished status poll for node %s (ID: %d)"), m_szName, m_dwId);
5039dede
AK
1302}
1303
1304
1305//
1f385e47
VK
1306// Check agent policy binding
1307// Intended to be called only from configuration poller
1308//
1309
1310void Node::checkAgentPolicyBinding(AgentConnection *conn)
1311{
1312 AgentPolicyInfo *ap;
1313 DWORD rcc = conn->getPolicyInventory(&ap);
1314 if (rcc == ERR_SUCCESS)
1315 {
1316 // Check for unbound but installed policies
1317 for(int i = 0; i < ap->getSize(); i++)
1318 {
1319 uuid_t guid;
1320 ap->getGuid(i, guid);
1321 NetObj *object = FindObjectByGUID(guid, -1);
1322 if ((object != NULL) && (!object->IsChild(m_dwId)))
1323 {
1324 object->AddChild(this);
1325 AddParent(object);
1326 DbgPrintf(5, _T("ConfPoll(%s): bound to policy object %s [%d]"), m_szName, object->Name(), object->Id());
1327 }
1328 }
1329
1330 // Check for bound but not installed policies
1331 LockParentList(FALSE);
1332 NetObj **unbindList = (NetObj **)malloc(sizeof(NetObj *) * m_dwParentCount);
1333 int unbindListSize = 0;
1334 for(DWORD i = 0; i < m_dwParentCount; i++)
1335 {
1336 if (IsAgentPolicyObject(m_pParentList[i]))
1337 {
1338 uuid_t guid1, guid2;
1339 int j;
1340
1341 m_pParentList[i]->getGuid(guid1);
1342 for(j = 0; j < ap->getSize(); j++)
1343 {
1344 ap->getGuid(j, guid2);
1345 if (!uuid_compare(guid1, guid2))
1346 break;
1347 }
1348 if (j == ap->getSize())
1349 unbindList[unbindListSize++] = m_pParentList[i];
1350 }
1351 }
1352 UnlockParentList();
1353
1354 for(int i = 0; i < unbindListSize; i++)
1355 {
1356 unbindList[i]->DeleteChild(this);
1357 DeleteParent(unbindList[i]);
1358 DbgPrintf(5, _T("ConfPoll(%s): unbound from policy object %s [%d]"), m_szName, unbindList[i]->Name(), unbindList[i]->Id());
1359 }
1360 safe_free(unbindList);
1361
1362 delete ap;
1363 }
1364 else
1365 {
1366 DbgPrintf(5, _T("ConfPoll(%s): AgentConnection::getPolicyInventory() failed: rcc=%d"), m_szName, rcc);
1367 }
1368}
1369
1370
1371//
5a7d6a10
VK
1372// Update primary IP address from primary name
1373//
1374
1375void Node::updatePrimaryIpAddr()
1376{
1377 if (m_primaryName[0] == 0)
1378 return;
1379
1380 DWORD ipAddr = ntohl(ResolveHostName(m_primaryName));
1381 if ((ipAddr != m_dwIpAddr) && (ipAddr != INADDR_ANY) && (ipAddr != INADDR_NONE))
1382 {
1383 TCHAR buffer1[32], buffer2[32];
1384
1385 DbgPrintf(4, _T("IP address for node %s [%d] changed from %s to %s"),
1386 m_szName, (int)m_dwId, IpToStr(m_dwIpAddr, buffer1), IpToStr(ipAddr, buffer2));
1387 PostEvent(EVENT_IP_ADDRESS_CHANGED, m_dwId, "aa", ipAddr, m_dwIpAddr);
1388 m_dwIpAddr = ipAddr;
1389 }
1390}
1391
1392
1393//
0ecc2200
VK
1394// Walker callback for print MIB
1395//
1396
1397static DWORD PrintMIBWalkerCallback(DWORD version, SNMP_Variable *var, SNMP_Transport *transport, void *arg)
1398{
1399 (*((int *)arg))++;
1400 return SNMP_ERR_SUCCESS;
1401}
1402
1403
1404//
5039dede
AK
1405// Perform configuration poll on node
1406//
1407
58b3e451 1408void Node::configurationPoll(ClientSession *pSession, DWORD dwRqId,
5039dede
AK
1409 int nPoller, DWORD dwNetMask)
1410{
46117060
VK
1411 if (m_dwDynamicFlags & NDF_DELETE_IN_PROGRESS)
1412 {
1413 if (dwRqId == 0)
1414 m_dwDynamicFlags &= ~NDF_QUEUED_FOR_CONFIG_POLL;
1415 return;
1416 }
1417
cc8ce218 1418 DWORD dwOldFlags = m_dwFlags, dwAddr, rcc;
5039dede 1419 AgentConnection *pAgentConn;
35f836fe 1420 TCHAR szBuffer[4096];
5039dede 1421 SNMP_Transport *pTransport;
5039dede
AK
1422 BOOL bHasChanges = FALSE;
1423
35f836fe 1424 SetPollerInfo(nPoller, _T("wait for lock"));
7c521895 1425 pollerLock();
5039dede
AK
1426 m_pPollRequestor = pSession;
1427 SendPollerMsg(dwRqId, _T("Starting configuration poll for node %s\r\n"), m_szName);
35f836fe 1428 DbgPrintf(4, _T("Starting configuration poll for node %s (ID: %d)"), m_szName, m_dwId);
5039dede
AK
1429
1430 // Check for forced capabilities recheck
1431 if (m_dwDynamicFlags & NDF_RECHECK_CAPABILITIES)
1432 {
1433 m_dwFlags &= ~(NF_IS_NATIVE_AGENT | NF_IS_SNMP | NF_IS_CPSNMP |
0ecc2200
VK
1434 NF_IS_BRIDGE | NF_IS_ROUTER | NF_IS_OSPF | NF_IS_PRINTER |
1435 NF_IS_CDP | NF_IS_LLDP | NF_IS_SONMP);
e4a64da2 1436 m_dwDynamicFlags &= ~NDF_CONFIGURATION_POLL_PASSED;
5039dede
AK
1437 m_szObjectId[0] = 0;
1438 m_szPlatformName[0] = 0;
1439 m_szAgentVersion[0] = 0;
0ecc2200
VK
1440 safe_free_and_null(m_sysDescription);
1441 safe_free_and_null(m_sysName);
1442 safe_free_and_null(m_lldpNodeId);
5039dede
AK
1443 }
1444
1445 // Check if node is marked as unreachable
1446 if ((m_dwDynamicFlags & NDF_UNREACHABLE) && !(m_dwDynamicFlags & NDF_RECHECK_CAPABILITIES))
1447 {
1448 SendPollerMsg(dwRqId, POLLER_WARNING _T("Node is marked as unreachable, configuration poll aborted\r\n"));
35f836fe 1449 DbgPrintf(4, _T("Node is marked as unreachable, configuration poll aborted"));
5039dede
AK
1450 m_tLastConfigurationPoll = time(NULL);
1451 }
1452 else
1453 {
5a7d6a10
VK
1454 updatePrimaryIpAddr();
1455
5039dede 1456 // Check node's capabilities
35f836fe 1457 SetPollerInfo(nPoller, _T("capability check"));
5039dede
AK
1458 SendPollerMsg(dwRqId, _T("Checking node's capabilities...\r\n"));
1459
1460 // ***** NetXMS agent check *****
35f836fe 1461 DbgPrintf(5, _T("ConfPoll(%s): checking for NetXMS agent Flags={%08X} DynamicFlags={%08X}"), m_szName, m_dwFlags, m_dwDynamicFlags);
5039dede 1462 if ((!((m_dwFlags & NF_IS_NATIVE_AGENT) && (m_dwDynamicFlags & NDF_AGENT_UNREACHABLE))) &&
15d6f8c9 1463 (!(m_dwFlags & NF_DISABLE_NXCP)) && (m_dwIpAddr != 0))
5039dede
AK
1464 {
1465 SendPollerMsg(dwRqId, _T(" Checking NetXMS agent...\r\n"));
4a64261c 1466 pAgentConn = new AgentConnection(htonl(m_dwIpAddr), m_wAgentPort, m_wAuthMethod, m_szSharedSecret);
7c521895 1467 setAgentProxy(pAgentConn);
35f836fe 1468 DbgPrintf(5, _T("ConfPoll(%s): checking for NetXMS agent - connecting"), m_szName);
7c521895 1469 if (pAgentConn->connect(g_pServerKey))
5039dede 1470 {
35f836fe 1471 DbgPrintf(5, _T("ConfPoll(%s): checking for NetXMS agent - connected"), m_szName);
5039dede
AK
1472 LockData();
1473 m_dwFlags |= NF_IS_NATIVE_AGENT;
1474 if (m_dwDynamicFlags & NDF_AGENT_UNREACHABLE)
1475 {
1476 m_dwDynamicFlags &= ~NDF_AGENT_UNREACHABLE;
1477 PostEvent(EVENT_AGENT_OK, m_dwId, NULL);
1478 SendPollerMsg(dwRqId, POLLER_INFO _T(" Connectivity with NetXMS agent restored\r\n"));
1479 }
1f385e47
VK
1480 else
1481 {
1482 SendPollerMsg(dwRqId, POLLER_INFO _T(" NetXMS native agent is active\r\n"));
1483 }
5039dede
AK
1484 UnlockData();
1485
4687826e 1486 if (pAgentConn->getParameter(_T("Agent.Version"), MAX_AGENT_VERSION_LEN, szBuffer) == ERR_SUCCESS)
5039dede
AK
1487 {
1488 LockData();
35f836fe 1489 if (_tcscmp(m_szAgentVersion, szBuffer))
5039dede 1490 {
35f836fe 1491 _tcscpy(m_szAgentVersion, szBuffer);
5039dede
AK
1492 bHasChanges = TRUE;
1493 SendPollerMsg(dwRqId, _T(" NetXMS agent version changed to %s\r\n"), m_szAgentVersion);
1494 }
1495 UnlockData();
1496 }
1497
4687826e 1498 if (pAgentConn->getParameter(_T("System.PlatformName"), MAX_PLATFORM_NAME_LEN, szBuffer) == ERR_SUCCESS)
5039dede
AK
1499 {
1500 LockData();
35f836fe 1501 if (_tcscmp(m_szPlatformName, szBuffer))
5039dede 1502 {
35f836fe 1503 _tcscpy(m_szPlatformName, szBuffer);
5039dede
AK
1504 bHasChanges = TRUE;
1505 SendPollerMsg(dwRqId, _T(" Platform name changed to %s\r\n"), m_szPlatformName);
1506 }
1507 UnlockData();
1508 }
1509
1510 // Check IP forwarding status
4687826e 1511 if (pAgentConn->getParameter(_T("Net.IP.Forwarding"), 16, szBuffer) == ERR_SUCCESS)
5039dede
AK
1512 {
1513 if (_tcstoul(szBuffer, NULL, 10) != 0)
1514 m_dwFlags |= NF_IS_ROUTER;
1515 else
1516 m_dwFlags &= ~NF_IS_ROUTER;
1517 }
1518
1519 // Get uname
4687826e 1520 if (pAgentConn->getParameter(_T("System.Uname"), MAX_DB_STRING, szBuffer) == ERR_SUCCESS)
5039dede 1521 {
35f836fe
VK
1522 TranslateStr(szBuffer, _T("\r\n"), _T(" "));
1523 TranslateStr(szBuffer, _T("\n"), _T(" "));
1524 TranslateStr(szBuffer, _T("\r"), _T(" "));
5039dede 1525 LockData();
0ecc2200 1526 if ((m_sysDescription == NULL) || _tcscmp(m_sysDescription, szBuffer))
5039dede 1527 {
bb151059 1528 safe_free(m_sysDescription);
0ecc2200 1529 m_sysDescription = _tcsdup(szBuffer);
5039dede 1530 bHasChanges = TRUE;
0ecc2200 1531 SendPollerMsg(dwRqId, _T(" System description changed to %s\r\n"), m_sysDescription);
5039dede
AK
1532 }
1533 UnlockData();
1534 }
1535
cc8ce218
VK
1536 StructArray<NXC_AGENT_PARAM> *plist;
1537 StructArray<NXC_AGENT_TABLE> *tlist;
1538 rcc = pAgentConn->getSupportedParameters(&plist, &tlist);
5039dede
AK
1539 if (rcc == ERR_SUCCESS)
1540 {
1541 LockData();
cc8ce218
VK
1542 delete m_paramList;
1543 delete m_tableList;
1544 m_paramList = plist;
1545 m_tableList = tlist;
5039dede
AK
1546 UnlockData();
1547 }
1548 else
1549 {
cc8ce218 1550 DbgPrintf(5, _T("ConfPoll(%s): AgentConnection::getSupportedParameters() failed: rcc=%d"), m_szName, rcc);
5039dede
AK
1551 }
1552
1f385e47
VK
1553 checkAgentPolicyBinding(pAgentConn);
1554
7c521895 1555 pAgentConn->disconnect();
5039dede 1556 }
1fa5706e
VK
1557 else
1558 {
1559 DbgPrintf(5, _T("ConfPoll(%s): checking for NetXMS agent - failed to connect"), m_szName);
1560 }
5039dede 1561 delete pAgentConn;
35f836fe 1562 DbgPrintf(5, _T("ConfPoll(%s): checking for NetXMS agent - finished"), m_szName);
5039dede
AK
1563 }
1564
1565 // ***** SNMP check *****
1566 if ((!((m_dwFlags & NF_IS_SNMP) && (m_dwDynamicFlags & NDF_SNMP_UNREACHABLE))) &&
15d6f8c9 1567 (!(m_dwFlags & NF_DISABLE_SNMP)) && (m_dwIpAddr != 0))
5039dede
AK
1568 {
1569 SendPollerMsg(dwRqId, _T(" Checking SNMP...\r\n"));
35f836fe 1570 DbgPrintf(5, _T("ConfPoll(%s): calling SnmpCheckCommSettings()"), m_szName);
cd9f247e 1571 pTransport = createSnmpTransport();
f2ec1aae
VK
1572 if (pTransport == NULL)
1573 {
35f836fe 1574 DbgPrintf(5, _T("ConfPoll(%s): unable to create SNMP transport"), m_szName);
f2ec1aae
VK
1575 goto skip_snmp_checks;
1576 }
5039dede 1577
df8a4ca2
VK
1578 SNMP_SecurityContext *newCtx = SnmpCheckCommSettings(pTransport, &m_snmpVersion, m_snmpSecurity);
1579 if (newCtx != NULL)
5039dede 1580 {
5039dede 1581 LockData();
df8a4ca2
VK
1582 delete m_snmpSecurity;
1583 m_snmpSecurity = newCtx;
5039dede
AK
1584 m_dwFlags |= NF_IS_SNMP;
1585 if (m_dwDynamicFlags & NDF_SNMP_UNREACHABLE)
1586 {
1587 m_dwDynamicFlags &= ~NDF_SNMP_UNREACHABLE;
1588 PostEvent(EVENT_SNMP_OK, m_dwId, NULL);
df8a4ca2 1589 SendPollerMsg(dwRqId, POLLER_INFO _T(" Connectivity with SNMP agent restored\r\n"));
5039dede
AK
1590 }
1591 UnlockData();
df8a4ca2
VK
1592 SendPollerMsg(dwRqId, _T(" SNMP agent is active (version %s)\r\n"),
1593 (m_snmpVersion == SNMP_VERSION_3) ? _T("3") : ((m_snmpVersion == SNMP_VERSION_2C) ? _T("2c") : _T("1")));
5039dede 1594
5d2c5741 1595 if (SnmpGet(m_snmpVersion, pTransport,
f42b8099 1596 _T(".1.3.6.1.2.1.1.2.0"), NULL, 0, szBuffer, 4096, SG_STRING_RESULT) == SNMP_ERR_SUCCESS)
5039dede
AK
1597 {
1598 LockData();
35f836fe 1599 if (_tcscmp(m_szObjectId, szBuffer))
5039dede
AK
1600 {
1601 nx_strncpy(m_szObjectId, szBuffer, MAX_OID_LEN * 4);
1602 bHasChanges = TRUE;
1603 }
1604 UnlockData();
1605 }
1606
9796ce45
VK
1607 // Get system description
1608 if (SnmpGet(m_snmpVersion, pTransport,
1609 _T(".1.3.6.1.2.1.1.1.0"), NULL, 0, szBuffer, MAX_DB_STRING, SG_STRING_RESULT) == SNMP_ERR_SUCCESS)
1610 {
1611 TranslateStr(szBuffer, _T("\r\n"), _T(" "));
1612 TranslateStr(szBuffer, _T("\n"), _T(" "));
1613 TranslateStr(szBuffer, _T("\r"), _T(" "));
1614 LockData();
1615 if ((m_sysDescription == NULL) || _tcscmp(m_sysDescription, szBuffer))
1616 {
1617 safe_free(m_sysDescription);
1618 m_sysDescription = _tcsdup(szBuffer);
1619 bHasChanges = TRUE;
1620 SendPollerMsg(dwRqId, _T(" System description changed to %s\r\n"), m_sysDescription);
1621 }
1622 UnlockData();
1623 }
1624
1625 // Select device driver
21254a93 1626 NetworkDeviceDriver *driver = FindDriverForNode(this, pTransport);
9796ce45
VK
1627 DbgPrintf(5, _T("ConfPoll(%s): selected device driver %s"), m_szName, driver->getName());
1628 LockData();
1629 if (driver != m_driver)
1630 {
1631 m_driver = driver;
1632 SendPollerMsg(dwRqId, _T(" New network device driver selected: %s\r\n"), m_driver->getName());
1633 }
1634 UnlockData();
1635
8373ffeb
VK
1636 // Allow driver to gather additional info
1637 m_driver->analyzeDevice(pTransport, m_szObjectId, &m_customAttributes);
1638
1639 // Get sysName
1640 if (SnmpGet(m_snmpVersion, pTransport,
1641 _T(".1.3.6.1.2.1.1.5.0"), NULL, 0, szBuffer, MAX_DB_STRING, SG_STRING_RESULT) == SNMP_ERR_SUCCESS)
1642 {
1643 LockData();
1644 if ((m_sysName == NULL) || _tcscmp(m_sysName, szBuffer))
1645 {
1646 safe_free(m_sysName);
1647 m_sysName = _tcsdup(szBuffer);
1648 bHasChanges = TRUE;
1649 SendPollerMsg(dwRqId, _T(" System name changed to %s\r\n"), m_sysName);
1650 }
1651 UnlockData();
1652 }
1653
5039dede 1654 // Check IP forwarding
35f836fe 1655 if (CheckSNMPIntegerValue(pTransport, _T(".1.3.6.1.2.1.4.1.0"), 1))
5039dede
AK
1656 {
1657 LockData();
1658 m_dwFlags |= NF_IS_ROUTER;
1659 UnlockData();
1660 }
1661 else
1662 {
1663 LockData();
1664 m_dwFlags &= ~NF_IS_ROUTER;
1665 UnlockData();
1666 }
1667
1668 // Check for bridge MIB support
3eab63f2 1669 if (SnmpGet(m_snmpVersion, pTransport, _T(".1.3.6.1.2.1.17.1.1.0"), NULL, 0, szBuffer, 4096, SG_RAW_RESULT) == SNMP_ERR_SUCCESS)
5039dede
AK
1670 {
1671 LockData();
1672 m_dwFlags |= NF_IS_BRIDGE;
3eab63f2 1673 memcpy(m_baseBridgeAddress, szBuffer, 6);
5039dede 1674 UnlockData();
3eab63f2
VK
1675
1676 // Check for Spanning Tree (IEEE 802.1d) MIB support
1677 if (CheckSNMPIntegerValue(pTransport, _T(".1.3.6.1.2.1.17.2.1.0"), 3))
1678 {
1679 LockData();
1680 m_dwFlags |= NF_IS_STP;
1681 UnlockData();
1682 }
1683 else
1684 {
1685 LockData();
1686 m_dwFlags &= ~NF_IS_STP;
1687 UnlockData();
1688 }
5039dede
AK
1689 }
1690 else
1691 {
1692 LockData();
3eab63f2 1693 m_dwFlags &= ~(NF_IS_BRIDGE | NF_IS_STP);
5039dede
AK
1694 UnlockData();
1695 }
1696
4312f994
VK
1697 // Check for ENTITY-MIB support
1698 if (SnmpGet(m_snmpVersion, pTransport, _T(".1.3.6.1.2.1.47.1.4.1.0"), NULL, 0, szBuffer, 4096, SG_RAW_RESULT) == SNMP_ERR_SUCCESS)
1699 {
1700 LockData();
1701 m_dwFlags |= NF_HAS_ENTITY_MIB;
1702 UnlockData();
50d0de67 1703
8836184f 1704 ComponentTree *components = BuildComponentTree(this, pTransport);
50d0de67 1705 LockData();
8836184f
VK
1706 if (m_components != NULL)
1707 m_components->decRefCount();
1708 m_components = components;
50d0de67 1709 UnlockData();
4312f994
VK
1710 }
1711 else
1712 {
1713 LockData();
1714 m_dwFlags &= ~NF_HAS_ENTITY_MIB;
8836184f
VK
1715 if (m_components != NULL)
1716 {
1717 m_components->decRefCount();
1718 m_components = NULL;
1719 }
4312f994
VK
1720 UnlockData();
1721 }
1722
0ecc2200
VK
1723 // Check for printer MIB support
1724 int count = 0;
1725 SnmpEnumerate(m_snmpVersion, pTransport, _T(".1.3.6.1.2.1.43.5.1.1.17"), PrintMIBWalkerCallback, &count, FALSE);
1726 if (count > 0)
1727 {
1728 LockData();
1729 m_dwFlags |= NF_IS_PRINTER;
1730 UnlockData();
1731 }
1732 else
1733 {
1734 LockData();
1735 m_dwFlags &= ~NF_IS_PRINTER;
1736 UnlockData();
1737 }
1738
5039dede 1739 // Check for CDP (Cisco Discovery Protocol) support
35f836fe 1740 if (CheckSNMPIntegerValue(pTransport, _T(".1.3.6.1.4.1.9.9.23.1.3.1.0"), 1))
5039dede
AK
1741 {
1742 LockData();
1743 m_dwFlags |= NF_IS_CDP;
1744 UnlockData();
1745 }
1746 else
1747 {
1748 LockData();
1749 m_dwFlags &= ~NF_IS_CDP;
1750 UnlockData();
1751 }
1752
ae2ef6f9 1753 // Check for NDP (Nortel Discovery Protocol) support
35f836fe 1754 if (CheckSNMPIntegerValue(pTransport, _T(".1.3.6.1.4.1.45.1.6.13.1.2.0"), 1))
5039dede
AK
1755 {
1756 LockData();
ae2ef6f9 1757 m_dwFlags |= NF_IS_NDP;
5039dede
AK
1758 UnlockData();
1759 }
1760 else
1761 {
1762 LockData();
ae2ef6f9 1763 m_dwFlags &= ~NF_IS_NDP;
5039dede
AK
1764 UnlockData();
1765 }
1766
1767 // Check for LLDP (Link Layer Discovery Protocol) support
0ecc2200 1768 if (SnmpGet(m_snmpVersion, pTransport, _T(".1.0.8802.1.1.2.1.3.2.0"), NULL, 0, szBuffer, 4096, 0) == SNMP_ERR_SUCCESS)
5039dede
AK
1769 {
1770 LockData();
1771 m_dwFlags |= NF_IS_LLDP;
1772 UnlockData();
0ecc2200
VK
1773
1774 if (SnmpGet(m_snmpVersion, pTransport, _T(".1.0.8802.1.1.2.1.3.1.0"), NULL, 0, szBuffer, 4096, SG_STRING_RESULT) == SNMP_ERR_SUCCESS)
1775 {
1776 _tcscat(szBuffer, _T("@"));
1777 int len = (int)_tcslen(szBuffer);
1778 if (SnmpGet(m_snmpVersion, pTransport, _T(".1.0.8802.1.1.2.1.3.2.0"), NULL, 0, &szBuffer[len], 4096 - len, SG_HSTRING_RESULT) == SNMP_ERR_SUCCESS)
1779 {
1780 LockData();
1781 if ((m_lldpNodeId == NULL) || _tcscmp(m_lldpNodeId, szBuffer))
1782 {
1783 safe_free(m_lldpNodeId);
1784 m_lldpNodeId = _tcsdup(szBuffer);
1785 bHasChanges = TRUE;
1786 SendPollerMsg(dwRqId, _T(" LLDP node ID changed to %s\r\n"), m_lldpNodeId);
1787 }
1788 UnlockData();
1789 }
1790 }
5039dede
AK
1791 }
1792 else
1793 {
1794 LockData();
1795 m_dwFlags &= ~NF_IS_LLDP;
1796 UnlockData();
1797 }
1798
d8ca56d5
VK
1799 // Check for 802.1x support
1800 if (CheckSNMPIntegerValue(pTransport, _T(".1.0.8802.1.1.1.1.1.1.0"), 1))
1801 {
1802 LockData();
1803 m_dwFlags |= NF_IS_8021X;
1804 UnlockData();
1805 }
1806 else
1807 {
1808 LockData();
1809 m_dwFlags &= ~NF_IS_8021X;
1810 UnlockData();
1811 }
1812
5039dede 1813 CheckOSPFSupport(pTransport);
0d75ea88
VK
1814
1815 // Get VRRP information
1816 VrrpInfo *vrrpInfo = GetVRRPInfo(this);
1817 if (vrrpInfo != NULL)
1818 {
1819 LockData();
1820 m_dwFlags |= NF_IS_VRRP;
1821 delete m_vrrpInfo;
1822 m_vrrpInfo = vrrpInfo;
1823 UnlockData();
1824 }
1825 else
1826 {
1827 LockData();
1828 m_dwFlags &= ~NF_IS_VRRP;
1829 UnlockData();
1830 }
5039dede
AK
1831 }
1832 else
1833 {
1834 // Check for CheckPoint SNMP agent on port 161
35f836fe 1835 DbgPrintf(5, _T("ConfPoll(%s): checking for CheckPoint SNMP"), m_szName);
0df58041 1836 if (SnmpGet(SNMP_VERSION_1, pTransport, _T(".1.3.6.1.4.1.2620.1.1.10.0"), NULL, 0, szBuffer, 4096, 0) == SNMP_ERR_SUCCESS)
5039dede
AK
1837 {
1838 LockData();
35f836fe 1839 if (_tcscmp(m_szObjectId, _T(".1.3.6.1.4.1.2620.1.1")))
5039dede 1840 {
35f836fe 1841 nx_strncpy(m_szObjectId, _T(".1.3.6.1.4.1.2620.1.1"), MAX_OID_LEN * 4);
5039dede
AK
1842 bHasChanges = TRUE;
1843 }
1844
1845 m_dwFlags |= NF_IS_SNMP | NF_IS_ROUTER;
1846 m_dwDynamicFlags &= ~NDF_SNMP_UNREACHABLE;
1847 UnlockData();
1848 SendPollerMsg(dwRqId, POLLER_INFO _T(" CheckPoint SNMP agent on port 161 is active\r\n"));
1849 }
1850 }
1851 delete pTransport;
1852 }
1853
f2ec1aae 1854skip_snmp_checks:
5039dede 1855 // Check for CheckPoint SNMP agent on port 260
35f836fe 1856 DbgPrintf(5, _T("ConfPoll(%s): checking for CheckPoint SNMP on port 260"), m_szName);
15d6f8c9 1857 if (!((m_dwFlags & NF_IS_CPSNMP) && (m_dwDynamicFlags & NDF_CPSNMP_UNREACHABLE)) && (m_dwIpAddr != 0))
5039dede
AK
1858 {
1859 pTransport = new SNMP_UDPTransport;
c4366266 1860 ((SNMP_UDPTransport *)pTransport)->createUDPTransport(NULL, htonl(m_dwIpAddr), CHECKPOINT_SNMP_PORT);
5d2c5741 1861 if (SnmpGet(SNMP_VERSION_1, pTransport,
f42b8099 1862 _T(".1.3.6.1.4.1.2620.1.1.10.0"), NULL, 0, szBuffer, 4096, 0) == SNMP_ERR_SUCCESS)
5039dede
AK
1863 {
1864 LockData();
1865 m_dwFlags |= NF_IS_CPSNMP | NF_IS_ROUTER;
1866 m_dwDynamicFlags &= ~NDF_CPSNMP_UNREACHABLE;
1867 UnlockData();
1868 SendPollerMsg(dwRqId, POLLER_INFO _T(" CheckPoint SNMP agent on port 260 is active\r\n"));
1869 }
1870 delete pTransport;
1871 }
1872
1873 // Generate event if node flags has been changed
1874 if (dwOldFlags != m_dwFlags)
1875 {
1876 PostEvent(EVENT_NODE_FLAGS_CHANGED, m_dwId, "xx", dwOldFlags, m_dwFlags);
1877 bHasChanges = TRUE;
1878 }
1879
5039dede 1880 // Retrieve interface list
35f836fe 1881 SetPollerInfo(nPoller, _T("interface check"));
df8a4ca2 1882 SendPollerMsg(dwRqId, _T("Capability check finished\r\n"));
5039dede 1883
eec253a8
VK
1884 if (updateInterfaceConfiguration(dwRqId, dwNetMask))
1885 bHasChanges = TRUE;
5039dede
AK
1886
1887 m_tLastConfigurationPoll = time(NULL);
5039dede
AK
1888
1889 // Check node name
1890 SendPollerMsg(dwRqId, _T("Checking node name\r\n"));
1891 dwAddr = ntohl(_t_inet_addr(m_szName));
1892 if ((g_dwFlags & AF_RESOLVE_NODE_NAMES) &&
1893 (dwAddr != INADDR_NONE) &&
1894 (dwAddr != INADDR_ANY) &&
58b3e451 1895 isMyIP(dwAddr))
5039dede
AK
1896 {
1897 SendPollerMsg(dwRqId, _T("Node name is an IP address and need to be resolved\r\n"));
35f836fe 1898 SetPollerInfo(nPoller, _T("resolving name"));
024c3faf 1899 if (resolveName(FALSE))
5039dede
AK
1900 {
1901 SendPollerMsg(dwRqId, POLLER_INFO _T("Node name resolved to %s\r\n"), m_szName);
1902 bHasChanges = TRUE;
1903 }
1904 else
1905 {
1906 SendPollerMsg(dwRqId, POLLER_WARNING _T("Node name cannot be resolved\r\n"));
1907 }
1908 }
1909 else
1910 {
1911 if (g_dwFlags & AF_SYNC_NODE_NAMES_WITH_DNS)
1912 {
1913 SendPollerMsg(dwRqId, _T("Syncing node name with DNS\r\n"));
35f836fe 1914 SetPollerInfo(nPoller, _T("resolving name"));
024c3faf 1915 if (resolveName(TRUE))
5039dede
AK
1916 {
1917 SendPollerMsg(dwRqId, POLLER_INFO _T("Node name resolved to %s\r\n"), m_szName);
1918 bHasChanges = TRUE;
1919 }
1920 }
1921 else
1922 {
1923 SendPollerMsg(dwRqId, _T("Node name is OK\r\n"));
1924 }
1925 }
1926
4d0c32f3
VK
1927 // Apply templates
1928 ApplySystemTemplates();
1929 ApplyUserTemplates();
1930
7c521895 1931 updateContainerMembership();
4d0c32f3 1932
df8a4ca2
VK
1933 SendPollerMsg(dwRqId, _T("Finished configuration poll for node %s\r\n"), m_szName);
1934 SendPollerMsg(dwRqId, _T("Node configuration was%schanged after poll\r\n"), bHasChanges ? _T(" ") : _T(" not "));
e4a64da2
VK
1935
1936 m_dwDynamicFlags |= NDF_CONFIGURATION_POLL_PASSED;
4d0c32f3
VK
1937 }
1938
1939 // Finish configuration poll
35f836fe 1940 SetPollerInfo(nPoller, _T("cleanup"));
4d0c32f3
VK
1941 if (dwRqId == 0)
1942 m_dwDynamicFlags &= ~NDF_QUEUED_FOR_CONFIG_POLL;
1943 m_dwDynamicFlags &= ~NDF_RECHECK_CAPABILITIES;
7c521895 1944 pollerUnlock();
35f836fe 1945 DbgPrintf(4, _T("Finished configuration poll for node %s (ID: %d)"), m_szName, m_dwId);
4d0c32f3
VK
1946
1947 if (bHasChanges)
1948 {
1949 LockData();
1950 Modify();
1951 UnlockData();
1952 }
1953}
1954
1955
1956//
eec253a8
VK
1957// Update interface configuration
1958//
1959
1960BOOL Node::updateInterfaceConfiguration(DWORD dwRqId, DWORD dwNetMask)
1961{
98762401 1962 InterfaceList *pIfList;
eec253a8
VK
1963 Interface **ppDeleteList;
1964 int i, j, iDelCount;
1965 BOOL hasChanges = FALSE;
1966 Cluster *pCluster = getMyCluster();
1967
1968 SendPollerMsg(dwRqId, _T("Checking interface configuration...\r\n"));
1969 pIfList = getInterfaceList();
1970 if (pIfList != NULL)
1971 {
1972 // Remove cluster virtual interfaces from list
1973 if (pCluster != NULL)
1974 {
98762401 1975 for(i = 0; i < pIfList->getSize(); i++)
eec253a8 1976 {
98762401 1977 if (pCluster->isVirtualAddr(pIfList->get(i)->dwIpAddr))
eec253a8 1978 {
98762401 1979 pIfList->remove(i);
eec253a8
VK
1980 i--;
1981 }
1982 }
1983 }
1984
1985 // Find non-existing interfaces
1986 LockChildList(FALSE);
1987 ppDeleteList = (Interface **)malloc(sizeof(Interface *) * m_dwChildCount);
1988 for(i = 0, iDelCount = 0; i < (int)m_dwChildCount; i++)
1989 {
1990 if (m_pChildList[i]->Type() == OBJECT_INTERFACE)
1991 {
1992 Interface *pInterface = (Interface *)m_pChildList[i];
9214177b
VK
1993 if (!pInterface->isManuallyCreated())
1994 {
1995 for(j = 0; j < pIfList->getSize(); j++)
1996 {
1997 if ((pIfList->get(j)->dwIndex == pInterface->getIfIndex()) &&
1998 (pIfList->get(j)->dwIpAddr == pInterface->IpAddr()))
1999 break;
2000 }
eec253a8 2001
9214177b
VK
2002 if (j == pIfList->getSize())
2003 {
2004 // No such interface in current configuration, add it to delete list
2005 ppDeleteList[iDelCount++] = pInterface;
2006 }
2007 }
eec253a8
VK
2008 }
2009 }
2010 UnlockChildList();
2011
2012 // Delete non-existent interfaces
2013 if (iDelCount > 0)
2014 {
2015 for(j = 0; j < iDelCount; j++)
2016 {
2017 SendPollerMsg(dwRqId, POLLER_WARNING _T(" Interface \"%s\" is no longer exist\r\n"),
2018 ppDeleteList[j]->Name());
2019 PostEvent(EVENT_INTERFACE_DELETED, m_dwId, "dsaa", ppDeleteList[j]->getIfIndex(),
2020 ppDeleteList[j]->Name(), ppDeleteList[j]->IpAddr(), ppDeleteList[j]->getIpNetMask());
2021 deleteInterface(ppDeleteList[j]);
2022 }
2023 hasChanges = TRUE;
2024 }
2025 safe_free(ppDeleteList);
2026
2027 // Add new interfaces and check configuration of existing
98762401 2028 for(j = 0; j < pIfList->getSize(); j++)
eec253a8 2029 {
60557d06 2030 NX_INTERFACE_INFO *ifInfo = pIfList->get(j);
eec253a8
VK
2031 BOOL bNewInterface = TRUE;
2032
2033 LockChildList(FALSE);
2034 for(i = 0; i < (int)m_dwChildCount; i++)
2035 {
2036 if (m_pChildList[i]->Type() == OBJECT_INTERFACE)
2037 {
2038 Interface *pInterface = (Interface *)m_pChildList[i];
2039
98762401
VK
2040 if ((ifInfo->dwIndex == pInterface->getIfIndex()) &&
2041 (ifInfo->dwIpAddr == pInterface->IpAddr()))
eec253a8
VK
2042 {
2043 // Existing interface, check configuration
98762401 2044 if (memcmp(ifInfo->bMacAddr, pInterface->getMacAddr(), MAC_ADDR_LENGTH))
eec253a8
VK
2045 {
2046 TCHAR szOldMac[16], szNewMac[16];
2047
2048 BinToStr((BYTE *)pInterface->getMacAddr(), MAC_ADDR_LENGTH, szOldMac);
98762401 2049 BinToStr(ifInfo->bMacAddr, MAC_ADDR_LENGTH, szNewMac);
eec253a8
VK
2050 PostEvent(EVENT_MAC_ADDR_CHANGED, m_dwId, "idsss",
2051 pInterface->Id(), pInterface->getIfIndex(),
2052 pInterface->Name(), szOldMac, szNewMac);
98762401 2053 pInterface->setMacAddr(ifInfo->bMacAddr);
eec253a8 2054 }
98762401 2055 if (_tcscmp(ifInfo->szName, pInterface->Name()))
eec253a8 2056 {
98762401 2057 pInterface->setName(ifInfo->szName);
eec253a8 2058 }
478d4ff4
VK
2059 if (_tcscmp(ifInfo->szDescription, pInterface->getDescription()))
2060 {
2061 pInterface->setDescription(ifInfo->szDescription);
2062 }
98762401 2063 if (ifInfo->dwBridgePortNumber != pInterface->getBridgePortNumber())
eec253a8 2064 {
98762401 2065 pInterface->setBridgePortNumber(ifInfo->dwBridgePortNumber);
eec253a8 2066 }
98762401 2067 if (ifInfo->dwSlotNumber != pInterface->getSlotNumber())
76f9abfd 2068 {
98762401 2069 pInterface->setSlotNumber(ifInfo->dwSlotNumber);
76f9abfd 2070 }
98762401 2071 if (ifInfo->dwPortNumber != pInterface->getPortNumber())
76f9abfd 2072 {
98762401 2073 pInterface->setPortNumber(ifInfo->dwPortNumber);
76f9abfd 2074 }
4c16cdc7
VK
2075 if (ifInfo->isPhysicalPort != pInterface->isPhysicalPort())
2076 {
2077 pInterface->setPhysicalPortFlag(ifInfo->isPhysicalPort);
2078 }
98762401 2079 if ((ifInfo->dwIpNetMask != 0) && (ifInfo->dwIpNetMask != pInterface->getIpNetMask()))
dfb38baf 2080 {
98762401 2081 pInterface->setIpNetMask(ifInfo->dwIpNetMask);
dfb38baf 2082 }
eec253a8
VK
2083 bNewInterface = FALSE;
2084 break;
2085 }
2086 }
2087 }
2088 UnlockChildList();
2089
2090 if (bNewInterface)
2091 {
2092 // New interface
98762401
VK
2093 SendPollerMsg(dwRqId, POLLER_INFO _T(" Found new interface \"%s\"\r\n"), ifInfo->szName);
2094 createNewInterface(ifInfo->dwIpAddr,
2095 ifInfo->dwIpNetMask,
2096 ifInfo->szName,
478d4ff4 2097 ifInfo->szDescription,
98762401
VK
2098 ifInfo->dwIndex,
2099 ifInfo->dwType,
2100 ifInfo->bMacAddr,
2101 ifInfo->dwBridgePortNumber,
2102 ifInfo->dwSlotNumber,
4c16cdc7
VK
2103 ifInfo->dwPortNumber,
2104 ifInfo->isPhysicalPort);
eec253a8
VK
2105 hasChanges = TRUE;
2106 }
2107 }
2108
2109 // Check if address we are using to communicate with node
2110 // is configured on one of node's interfaces
98762401
VK
2111 for(i = 0; i < pIfList->getSize(); i++)
2112 if (pIfList->get(i)->dwIpAddr == m_dwIpAddr)
eec253a8
VK
2113 break;
2114
98762401 2115 if (i == (DWORD)pIfList->getSize())
eec253a8 2116 {
eec253a8 2117 // Node is behind NAT
563179bc 2118 if (!(m_dwFlags & NF_BEHIND_NAT))
eec253a8 2119 {
563179bc
VK
2120 m_dwFlags |= NF_BEHIND_NAT;
2121 hasChanges = TRUE;
2122 }
eec253a8
VK
2123 }
2124 else
2125 {
2126 // Check if NF_BEHIND_NAT flag set incorrectly
2127 if (m_dwFlags & NF_BEHIND_NAT)
2128 {
eec253a8
VK
2129 m_dwFlags &= ~NF_BEHIND_NAT;
2130 hasChanges = TRUE;
2131 }
2132 }
2133
024c3faf 2134 checkSubnetBinding(pIfList);
eec253a8 2135
98762401 2136 delete pIfList;
eec253a8
VK
2137 }
2138 else /* pIfList == NULL */
2139 {
2140 Interface *pInterface;
2141 DWORD dwCount;
2142
2143 SendPollerMsg(dwRqId, POLLER_ERROR _T("Unable to get interface list from node\r\n"));
2144
2145 // Delete all existing interfaces in case of forced capability recheck
2146 if (m_dwDynamicFlags & NDF_RECHECK_CAPABILITIES)
2147 {
2148 LockChildList(FALSE);
2149 ppDeleteList = (Interface **)malloc(sizeof(Interface *) * m_dwChildCount);
2150 for(i = 0, iDelCount = 0; i < (int)m_dwChildCount; i++)
2151 {
9214177b 2152 if ((m_pChildList[i]->Type() == OBJECT_INTERFACE) && !((Interface *)m_pChildList[i])->isManuallyCreated())
eec253a8
VK
2153 ppDeleteList[iDelCount++] = (Interface *)m_pChildList[i];
2154 }
2155 UnlockChildList();
2156 for(j = 0; j < iDelCount; j++)
2157 {
2158 SendPollerMsg(dwRqId, POLLER_WARNING _T(" Interface \"%s\" is no longer exist\r\n"),
2159 ppDeleteList[j]->Name());
2160 PostEvent(EVENT_INTERFACE_DELETED, m_dwId, "dsaa", ppDeleteList[j]->getIfIndex(),
2161 ppDeleteList[j]->Name(), ppDeleteList[j]->IpAddr(), ppDeleteList[j]->getIpNetMask());
2162 deleteInterface(ppDeleteList[j]);
2163 }
2164 safe_free(ppDeleteList);
2165 }
2166
2167 // Check if we have pseudo-interface object
2168 dwCount = getInterfaceCount(&pInterface);
2169 if (dwCount == 1)
2170 {
2171 if (pInterface->isFake())
2172 {
2173 // Check if primary IP is different from interface's IP
2174 if (pInterface->IpAddr() != m_dwIpAddr)
2175 {
2176 deleteInterface(pInterface);
2177 if (m_dwIpAddr != 0)
2178 createNewInterface(m_dwIpAddr, dwNetMask);
2179 }
2180 }
2181 }
2182 else if (dwCount == 0)
2183 {
2184 // No interfaces at all, create pseudo-interface
2185 if (m_dwIpAddr != 0)
2186 createNewInterface(m_dwIpAddr, dwNetMask);
2187 }
2188 }
2189
2190 SendPollerMsg(dwRqId, _T("Interface configuration check finished\r\n"));
2191 return hasChanges;
2192}
2193
2194
2195//
4d0c32f3
VK
2196// Apply system templates
2197//
2198
2199void Node::ApplySystemTemplates()
2200{
2201 Template *pTemplate;
2202
2203 pTemplate = FindTemplateByName(_T("@System.Agent"));
2204 if (pTemplate != NULL)
2205 {
7c521895 2206 if (isNativeAgent())
5039dede 2207 {
4d0c32f3 2208 if (!pTemplate->IsChild(m_dwId))
5039dede 2209 {
4d0c32f3
VK
2210 DbgPrintf(4, _T("Node::ApplySystemTemplates(): applying template %d \"%s\" to node %d \"%s\""),
2211 pTemplate->Id(), pTemplate->Name(), m_dwId, m_szName);
2212 pTemplate->ApplyToNode(this);
5039dede 2213 }
4d0c32f3
VK
2214 }
2215 else
2216 {
2217 if (pTemplate->IsChild(m_dwId))
5039dede 2218 {
4d0c32f3
VK
2219 DbgPrintf(4, _T("Node::ApplySystemTemplates(): removing template %d \"%s\" from node %d \"%s\""),
2220 pTemplate->Id(), pTemplate->Name(), m_dwId, m_szName);
2221 pTemplate->DeleteChild(this);
2222 DeleteParent(pTemplate);
fb05c05b 2223 pTemplate->queueRemoveFromNode(m_dwId, TRUE);
5039dede
AK
2224 }
2225 }
4d0c32f3 2226 }
4d0c32f3
VK
2227}
2228
2229
2230//
2231// Apply user templates
2232//
2233
27de5dab 2234static void ApplyTemplate(NetObj *object, void *node)
4d0c32f3 2235{
6ff21d27 2236 if ((object->Type() == OBJECT_TEMPLATE) && !object->isDeleted())
4d0c32f3 2237 {
27de5dab
VK
2238 Template *pTemplate = (Template *)object;
2239 if (pTemplate->isApplicable((Node *)node))
2240 {
2241 if (!pTemplate->IsChild(((Node *)node)->Id()))
5039dede 2242 {
27de5dab
VK
2243 DbgPrintf(4, _T("Node::ApplyUserTemplates(): applying template %d \"%s\" to node %d \"%s\""),
2244 pTemplate->Id(), pTemplate->Name(), ((Node *)node)->Id(), ((Node *)node)->Name());
2245 pTemplate->ApplyToNode((Node *)node);
9b64b406 2246 PostEvent(EVENT_TEMPLATE_AUTOAPPLY, g_dwMgmtNode, "isis", ((Node *)node)->Id(), ((Node *)node)->Name(), pTemplate->Id(), pTemplate->Name());
5039dede 2247 }
27de5dab
VK
2248 }
2249 else
2250 {
9b64b406 2251 if (pTemplate->isAutoRemoveEnabled() && pTemplate->IsChild(((Node *)node)->Id()))
5039dede 2252 {
27de5dab
VK
2253 DbgPrintf(4, _T("Node::ApplyUserTemplates(): removing template %d \"%s\" from node %d \"%s\""),
2254 pTemplate->Id(), pTemplate->Name(), ((Node *)node)->Id(), ((Node *)node)->Name());
2255 pTemplate->DeleteChild((Node *)node);
2256 ((Node *)node)->DeleteParent(pTemplate);
2257 pTemplate->queueRemoveFromNode(((Node *)node)->Id(), TRUE);
9b64b406 2258 PostEvent(EVENT_TEMPLATE_AUTOREMOVE, g_dwMgmtNode, "isis", ((Node *)node)->Id(), ((Node *)node)->Name(), pTemplate->Id(), pTemplate->Name());
5039dede 2259 }
27de5dab 2260 }
5039dede 2261 }
27de5dab
VK
2262}
2263
2264void Node::ApplyUserTemplates()
2265{
2266 g_idxObjectById.forEach(ApplyTemplate, this);
4d0c32f3 2267}
5039dede 2268
5039dede 2269
4d0c32f3
VK
2270//
2271// Update container membership
2272//
2273
27de5dab 2274static void UpdateContainerBinding(NetObj *object, void *node)
4d0c32f3 2275{
6ff21d27 2276 if ((object->Type() == OBJECT_CONTAINER) && !object->isDeleted())
5039dede 2277 {
27de5dab 2278 Container *pContainer = (Container *)object;
926e8ce7 2279 if (pContainer->isSuitableForNode((Node *)node))
27de5dab
VK
2280 {
2281 if (!pContainer->IsChild(((Node *)node)->Id()))
4d0c32f3 2282 {
27de5dab
VK
2283 DbgPrintf(4, _T("Node::UpdateContainerMembership(): binding node %d \"%s\" to container %d \"%s\""),
2284 ((Node *)node)->Id(), ((Node *)node)->Name(), pContainer->Id(), pContainer->Name());
2285 pContainer->AddChild((Node *)node);
2286 ((Node *)node)->AddParent(pContainer);
9b64b406 2287 PostEvent(EVENT_CONTAINER_AUTOBIND, g_dwMgmtNode, "isis", ((Node *)node)->Id(), ((Node *)node)->Name(), pContainer->Id(), pContainer->Name());
4d0c32f3 2288 }
27de5dab
VK
2289 }
2290 else
2291 {
9b64b406 2292 if (pContainer->isAutoUnbindEnabled() && pContainer->IsChild(((Node *)node)->Id()))
4d0c32f3 2293 {
27de5dab
VK
2294 DbgPrintf(4, _T("Node::UpdateContainerMembership(): removing node %d \"%s\" from container %d \"%s\""),
2295 ((Node *)node)->Id(), ((Node *)node)->Name(), pContainer->Id(), pContainer->Name());
2296 pContainer->DeleteChild((Node *)node);
2297 ((Node *)node)->DeleteParent(pContainer);
9b64b406 2298 PostEvent(EVENT_CONTAINER_AUTOUNBIND, g_dwMgmtNode, "isis", ((Node *)node)->Id(), ((Node *)node)->Name(), pContainer->Id(), pContainer->Name());
4d0c32f3 2299 }
27de5dab 2300 }
5039dede 2301 }
27de5dab
VK
2302}
2303
2304void Node::updateContainerMembership()
2305{
2306 g_idxObjectById.forEach(UpdateContainerBinding, this);
5039dede
AK
2307}
2308
2309
2310//
2311// Connect to native agent
2312//
2313
a4569c4d 2314BOOL Node::connectToAgent(DWORD *error, DWORD *socketError)
5039dede
AK
2315{
2316 BOOL bRet;
2317
2318 // Create new agent connection object if needed
2319 if (m_pAgentConnection == NULL)
2320 m_pAgentConnection = new AgentConnectionEx(htonl(m_dwIpAddr), m_wAgentPort, m_wAuthMethod, m_szSharedSecret);
2321
2322 // Check if we already connected
45d84f8a 2323 if (m_pAgentConnection->nop() == ERR_SUCCESS)
5039dede
AK
2324 return TRUE;
2325
2326 // Close current connection or clean up after broken connection
7c521895
VK
2327 m_pAgentConnection->disconnect();
2328 m_pAgentConnection->setPort(m_wAgentPort);
35f836fe
VK
2329#ifdef UNICODE
2330 char mbSecret[MAX_SECRET_LENGTH];
2331 WideCharToMultiByte(CP_ACP, WC_DEFAULTCHAR | WC_COMPOSITECHECK, m_szSharedSecret, -1, mbSecret, MAX_SECRET_LENGTH, NULL, NULL);
2332 mbSecret[MAX_SECRET_LENGTH - 1] = 0;
2333 m_pAgentConnection->setAuthData(m_wAuthMethod, mbSecret);
2334#else
7c521895 2335 m_pAgentConnection->setAuthData(m_wAuthMethod, m_szSharedSecret);
35f836fe 2336#endif
7c521895 2337 setAgentProxy(m_pAgentConnection);
a4569c4d 2338 bRet = m_pAgentConnection->connect(g_pServerKey, FALSE, error, socketError);
5039dede
AK
2339 if (bRet)
2340 {
45d84f8a
VK
2341 m_pAgentConnection->setCommandTimeout(g_dwAgentCommandTimeout);
2342 m_pAgentConnection->enableTraps();
5039dede
AK
2343 }
2344 return bRet;
2345}
2346
2347
2348//
2349// Get item's value via SNMP
2350//
2351
e320f8ce 2352DWORD Node::getItemFromSNMP(WORD port, const TCHAR *szParam, DWORD dwBufSize, TCHAR *szBuffer, int interpretRawValue)
5039dede
AK
2353{
2354 DWORD dwResult;
2355
2fd7144f 2356 if ((((m_dwDynamicFlags & NDF_SNMP_UNREACHABLE) || !(m_dwFlags & NF_IS_SNMP)) && (port == 0)) ||
6b2bb22c
VK
2357 (m_dwDynamicFlags & NDF_UNREACHABLE) ||
2358 (m_dwFlags & NF_DISABLE_SNMP))
5039dede
AK
2359 {
2360 dwResult = SNMP_ERR_COMM;
2361 }
2362 else
2363 {
2364 SNMP_Transport *pTransport;
2365
65e2005b 2366 pTransport = createSnmpTransport(port);
803d47be
VK
2367 if (pTransport != NULL)
2368 {
e320f8ce
VK
2369 if (interpretRawValue == SNMP_RAWTYPE_NONE)
2370 {
2371 dwResult = SnmpGet(m_snmpVersion, pTransport, szParam, NULL, 0, szBuffer, dwBufSize, SG_PSTRING_RESULT);
2372 }
2373 else
2374 {
2375 BYTE rawValue[1024];
2376 memset(rawValue, 0, 1024);
2377 dwResult = SnmpGet(m_snmpVersion, pTransport, szParam, NULL, 0, rawValue, 1024, SG_RAW_RESULT);
2378 if (dwResult == SNMP_ERR_SUCCESS)
2379 {
2380 switch(interpretRawValue)
2381 {
2382 case SNMP_RAWTYPE_INT32:
2383 _sntprintf(szBuffer, dwBufSize, _T("%d"), ntohl(*((LONG *)rawValue)));
2384 break;
2385 case SNMP_RAWTYPE_UINT32:
2386 _sntprintf(szBuffer, dwBufSize, _T("%u"), ntohl(*((DWORD *)rawValue)));
2387 break;
2388 case SNMP_RAWTYPE_INT64:
2389 _sntprintf(szBuffer, dwBufSize, INT64_FMT, ntohq(*((INT64 *)rawValue)));
2390 break;
2391 case SNMP_RAWTYPE_UINT64:
2392 _sntprintf(szBuffer, dwBufSize, UINT64_FMT, ntohq(*((QWORD *)rawValue)));
2393 break;
2394 case SNMP_RAWTYPE_DOUBLE:
2395 _sntprintf(szBuffer, dwBufSize, _T("%f"), ntohd(*((double *)rawValue)));
2396 break;
2397 case SNMP_RAWTYPE_IP_ADDR:
2398 IpToStr(ntohl(*((DWORD *)rawValue)), szBuffer);
2399 break;
2400 case SNMP_RAWTYPE_MAC_ADDR:
2401 MACToStr(rawValue, szBuffer);
2402 break;
2403 default:
2404 szBuffer[0] = 0;
2405 break;
2406 }
2407 }
2408 }
803d47be
VK
2409 delete pTransport;
2410 }
2411 else
2412 {
2413 dwResult = SNMP_ERR_COMM;
2414 }
5039dede 2415 }
35f836fe 2416 DbgPrintf(7, _T("Node(%s)->GetItemFromSNMP(%s): dwResult=%d"), m_szName, szParam, dwResult);
5039dede
AK
2417 return (dwResult == SNMP_ERR_SUCCESS) ? DCE_SUCCESS :
2418 ((dwResult == SNMP_ERR_NO_OBJECT) ? DCE_NOT_SUPPORTED : DCE_COMM_ERROR);
2419}
2420
2421
2422//
2423// Get item's value via SNMP from CheckPoint's agent
2424//
2425
35f836fe 2426DWORD Node::GetItemFromCheckPointSNMP(const TCHAR *szParam, DWORD dwBufSize, TCHAR *szBuffer)
5039dede
AK
2427{
2428 DWORD dwResult;
2429
2430 if ((m_dwDynamicFlags & NDF_CPSNMP_UNREACHABLE) ||
2431 (m_dwDynamicFlags & NDF_UNREACHABLE))
2432 {
2433 dwResult = SNMP_ERR_COMM;
2434 }
2435 else
2436 {
2437 SNMP_Transport *pTransport;
2438
2439 pTransport = new SNMP_UDPTransport;
c4366266 2440 ((SNMP_UDPTransport *)pTransport)->createUDPTransport(NULL, htonl(m_dwIpAddr), CHECKPOINT_SNMP_PORT);
f42b8099 2441 dwResult = SnmpGet(SNMP_VERSION_1, pTransport, szParam, NULL, 0, szBuffer, dwBufSize, SG_STRING_RESULT);
5039dede
AK
2442 delete pTransport;
2443 }
35f836fe 2444 DbgPrintf(7, _T("Node(%s)->GetItemFromCheckPointSNMP(%s): dwResult=%d"), m_szName, szParam, dwResult);
5039dede
AK
2445 return (dwResult == SNMP_ERR_SUCCESS) ? DCE_SUCCESS :
2446 ((dwResult == SNMP_ERR_NO_OBJECT) ? DCE_NOT_SUPPORTED : DCE_COMM_ERROR);
2447}
2448
2449
2450//
2451// Get item's value via native agent
2452//
2453
35f836fe 2454DWORD Node::GetItemFromAgent(const TCHAR *szParam, DWORD dwBufSize, TCHAR *szBuffer)
5039dede 2455{
912b994d 2456 DWORD dwError = ERR_NOT_CONNECTED, dwResult = DCE_COMM_ERROR;
5039dede
AK
2457 DWORD dwTries = 3;
2458
2459 if ((m_dwDynamicFlags & NDF_AGENT_UNREACHABLE) ||
2fd7144f
VK
2460 (m_dwDynamicFlags & NDF_UNREACHABLE) ||
2461 (m_dwFlags & NF_DISABLE_NXCP) ||
2462 !(m_dwFlags & NF_IS_NATIVE_AGENT))
5039dede
AK
2463 return DCE_COMM_ERROR;
2464
7c521895 2465 agentLock();
5039dede
AK
2466
2467 // Establish connection if needed
2468 if (m_pAgentConnection == NULL)
7c521895 2469 if (!connectToAgent())
5039dede
AK
2470 goto end_loop;
2471
2472 // Get parameter from agent
2473 while(dwTries-- > 0)
2474 {
4687826e 2475 dwError = m_pAgentConnection->getParameter(szParam, dwBufSize, szBuffer);
5039dede
AK
2476 switch(dwError)
2477 {
2478 case ERR_SUCCESS:
2479 dwResult = DCE_SUCCESS;
2480 goto end_loop;
2481 case ERR_UNKNOWN_PARAMETER:
2482 dwResult = DCE_NOT_SUPPORTED;
2483 goto end_loop;
2484 case ERR_NOT_CONNECTED:
2485 case ERR_CONNECTION_BROKEN:
7c521895 2486 if (!connectToAgent())
5039dede
AK
2487 goto end_loop;
2488 break;
2489 case ERR_REQUEST_TIMEOUT:
2490 // Reset connection to agent after timeout
2491 DbgPrintf(7, _T("Node(%s)->GetItemFromAgent(%s): timeout; resetting connection to agent..."), m_szName, szParam);
2492 delete_and_null(m_pAgentConnection);
7c521895 2493 if (!connectToAgent())
5039dede
AK
2494 goto end_loop;
2495 DbgPrintf(7, _T("Node(%s)->GetItemFromAgent(%s): connection to agent restored successfully"), m_szName, szParam);
2496 break;
2497 }
2498 }
2499
2500end_loop:
7c521895 2501 agentUnlock();
adac28be
VK
2502 DbgPrintf(7, _T("Node(%s)->GetItemFromAgent(%s): dwError=%d dwResult=%d"), m_szName, szParam, dwError, dwResult);
2503 return dwResult;
2504}
2505
2506
2507//
2508// Get table from agent
2509//
2510
2511DWORD Node::getTableFromAgent(const TCHAR *name, Table **table)
2512{
2513 DWORD dwError = ERR_NOT_CONNECTED, dwResult = DCE_COMM_ERROR;
2514 DWORD dwTries = 3;
2515
2516 *table = NULL;
2517
2518 if ((m_dwDynamicFlags & NDF_AGENT_UNREACHABLE) ||
2519 (m_dwDynamicFlags & NDF_UNREACHABLE) ||
2520 (m_dwFlags & NF_DISABLE_NXCP) ||
2521 !(m_dwFlags & NF_IS_NATIVE_AGENT))
2522 return DCE_COMM_ERROR;
2523
2524 agentLock();
2525
2526 // Establish connection if needed
2527 if (m_pAgentConnection == NULL)
2528 if (!connectToAgent())
2529 goto end_loop;
2530
2531 // Get parameter from agent
2532 while(dwTries-- > 0)
2533 {
2534 dwError = m_pAgentConnection->getTable(name, table);
2535 switch(dwError)
2536 {
2537 case ERR_SUCCESS:
2538 dwResult = DCE_SUCCESS;
2539 goto end_loop;
2540 case ERR_UNKNOWN_PARAMETER:
2541 dwResult = DCE_NOT_SUPPORTED;
2542 goto end_loop;
2543 case ERR_NOT_CONNECTED:
2544 case ERR_CONNECTION_BROKEN:
2545 if (!connectToAgent())
2546 goto end_loop;
2547 break;
2548 case ERR_REQUEST_TIMEOUT:
2549 // Reset connection to agent after timeout
2550 DbgPrintf(7, _T("Node(%s)->getTableFromAgent(%s): timeout; resetting connection to agent..."), m_szName, name);
2551 delete_and_null(m_pAgentConnection);
2552 if (!connectToAgent())
2553 goto end_loop;
2554 DbgPrintf(7, _T("Node(%s)->getTableFromAgent(%s): connection to agent restored successfully"), m_szName, name);
2555 break;
2556 }
2557 }
2558
2559end_loop:
2560 agentUnlock();
2561 DbgPrintf(7, _T("Node(%s)->getTableFromAgent(%s): dwError=%d dwResult=%d"), m_szName, name, dwError, dwResult);
5039dede
AK
2562 return dwResult;
2563}
2564
2565
2566//
2567// Get value for server's internal parameter
2568//
2569
35f836fe 2570DWORD Node::GetInternalItem(const TCHAR *szParam, DWORD dwBufSize, TCHAR *szBuffer)
5039dede
AK
2571{
2572 DWORD dwError = DCE_SUCCESS;
2573
35f836fe 2574 if (!_tcsicmp(szParam, _T("Status")))
5039dede 2575 {
35f836fe 2576 _sntprintf(szBuffer, dwBufSize, _T("%d"), m_iStatus);
5039dede 2577 }
35f836fe 2578 else if (!_tcsicmp(szParam, _T("Dummy")))
5039dede
AK
2579 {
2580 _tcscpy(szBuffer, _T("0"));
2581 }
20c842ee
VK
2582 else if (MatchString(_T("Net.IP.NextHop(*)"), szParam, FALSE))
2583 {
2584 if ((m_dwFlags & NF_IS_NATIVE_AGENT) || (m_dwFlags & NF_IS_SNMP))
2585 {
2586 TCHAR arg[256] = _T("");
2587 DWORD destAddr, nextHop, ifIndex;
2588 BOOL isVpn;
2589
2590 AgentGetParameterArg(szParam, 1, arg, 256);
2591 destAddr = ntohl(_t_inet_addr(arg));
2592 if ((destAddr > 0) && (destAddr < 0xE0000000))
2593 {
2594 if (getNextHop(m_dwIpAddr, destAddr, &nextHop, &ifIndex, &isVpn))
2595 {
2596 IpToStr(nextHop, szBuffer);
2597 }
2598 else
2599 {
2600 _tcscpy(szBuffer, _T("UNREACHABLE"));
2601 }
2602 }
2603 else
2604 {
2605 dwError = DCE_NOT_SUPPORTED;
2606 }
2607 }
2608 else
2609 {
2610 dwError = DCE_NOT_SUPPORTED;
2611 }
2612 }
35f836fe 2613 else if (!_tcsicmp(szParam, _T("AgentStatus")))
5039dede
AK
2614 {
2615 if (m_dwFlags & NF_IS_NATIVE_AGENT)
2616 {
35f836fe 2617 szBuffer[0] = (m_dwDynamicFlags & NDF_AGENT_UNREACHABLE) ? _T('1') : _T('0');
5039dede
AK
2618 szBuffer[1] = 0;
2619 }
2620 else
2621 {
2622 dwError = DCE_NOT_SUPPORTED;
2623 }
2624 }
35f836fe 2625 else if (MatchString(_T("ChildStatus(*)"), szParam, FALSE))
5039dede 2626 {
35f836fe 2627 TCHAR *pEnd, szArg[256];
5039dede
AK
2628 DWORD i, dwId;
2629 NetObj *pObject = NULL;
2630
35f836fe
VK
2631 AgentGetParameterArg(szParam, 1, szArg, 256);
2632 dwId = _tcstoul(szArg, &pEnd, 0);
5039dede
AK
2633 if (*pEnd != 0)
2634 {
2635 // Argument is object's name
2636 dwId = 0;
2637 }
2638
2639 // Find child object with requested ID or name
2640 LockChildList(FALSE);
2641 for(i = 0; i < m_dwChildCount; i++)
2642 {
35f836fe 2643 if (((dwId == 0) && (!_tcsicmp(m_pChildList[i]->Name(), szArg))) ||
5039dede
AK
2644 (dwId == m_pChildList[i]->Id()))
2645 {
2646 pObject = m_pChildList[i];
2647 break;
2648 }
2649 }
2650 UnlockChildList();
2651
2652 if (pObject != NULL)
2653 {
35f836fe 2654 _sntprintf(szBuffer, dwBufSize, _T("%d"), pObject->Status());
5039dede
AK
2655 }
2656 else
2657 {
2658 dwError = DCE_NOT_SUPPORTED;
2659 }
2660 }
35f836fe 2661 else if (MatchString(_T("ConditionStatus(*)"), szParam, FALSE))
5039dede 2662 {
35f836fe 2663 TCHAR *pEnd, szArg[256];
5039dede
AK
2664 DWORD dwId;
2665 NetObj *pObject = NULL;
2666
35f836fe
VK
2667 AgentGetParameterArg(szParam, 1, szArg, 256);
2668 dwId = _tcstoul(szArg, &pEnd, 0);
5039dede
AK
2669 if (*pEnd == 0)
2670 {
2671 pObject = FindObjectById(dwId);
2672 if (pObject != NULL)
2673 if (pObject->Type() != OBJECT_CONDITION)
2674 pObject = NULL;
2675 }
2676 else
2677 {
2678 // Argument is object's name
2679 pObject = FindObjectByName(szArg, OBJECT_CONDITION);
2680 }
2681
2682 if (pObject != NULL)
2683 {
2684 if (pObject->IsTrustedNode(m_dwId))
2685 {
35f836fe 2686 _sntprintf(szBuffer, dwBufSize, _T("%d"), pObject->Status());
5039dede
AK
2687 }
2688 else
2689 {
2690 dwError = DCE_NOT_SUPPORTED;
2691 }
2692 }
2693 else
2694 {
2695 dwError = DCE_NOT_SUPPORTED;
2696 }
2697 }
2698 else if (m_dwFlags & NF_IS_LOCAL_MGMT)
2699 {
35f836fe 2700 if (!_tcsicmp(szParam, _T("Server.AverageDCPollerQueueSize")))
5039dede 2701 {
35f836fe 2702 _sntprintf(szBuffer, dwBufSize, _T("%f"), g_dAvgPollerQueueSize);
5039dede 2703 }
35f836fe 2704 else if (!_tcsicmp(szParam, _T("Server.AverageDBWriterQueueSize")))
5039dede 2705 {
cf084617
VK
2706 _sntprintf(szBuffer, dwBufSize, _T("%f"), g_dAvgDBAndIDataWriterQueueSize);
2707 }
2708 else if (!_tcsicmp(szParam, _T("Server.AverageDBWriterQueueSize.Other")))
2709 {
35f836fe 2710 _sntprintf(szBuffer, dwBufSize, _T("%f"), g_dAvgDBWriterQueueSize);
5039dede 2711 }
cf084617
VK
2712 else if (!_tcsicmp(szParam, _T("Server.AverageDBWriterQueueSize.IData")))
2713 {
2714 _sntprintf(szBuffer, dwBufSize, _T("%f"), g_dAvgIDataWriterQueueSize);
2715 }
35f836fe 2716 else if (!_tcsicmp(szParam, _T("Server.AverageStatusPollerQueueSize")))
5039dede 2717 {
35f836fe 2718 _sntprintf(szBuffer, dwBufSize, _T("%f"), g_dAvgStatusPollerQueueSize);
5039dede 2719 }
35f836fe 2720 else if (!_tcsicmp(szParam, _T("Server.AverageConfigurationPollerQueueSize")))
5039dede 2721 {
35f836fe 2722 _sntprintf(szBuffer, dwBufSize, _T("%f"), g_dAvgConfigPollerQueueSize);
5039dede 2723 }
35f836fe 2724 else if (!_tcsicmp(szParam, _T("Server.AverageDCIQueuingTime")))
5039dede 2725 {
35f836fe 2726 _sntprintf(szBuffer, dwBufSize, _T("%u"), g_dwAvgDCIQueuingTime);
5039dede 2727 }
35f836fe 2728 else if (!_tcsicmp(szParam, _T("Server.TotalEventsProcessed")))
5039dede 2729 {
35f836fe 2730 _sntprintf(szBuffer, dwBufSize, INT64_FMT, g_totalEventsProcessed);
5039dede
AK
2731 }
2732 else
2733 {
2734 dwError = DCE_NOT_SUPPORTED;
2735 }
2736 }
2737 else
2738 {
2739 dwError = DCE_NOT_SUPPORTED;
2740 }
2741
2742 return dwError;
2743}
2744
2745
2746//
adac28be
VK
2747// Translate DCI error code into RCC
2748//
2749
2750static DWORD RCCFromDCIError(DWORD error)
2751{
3188558a 2752 switch(error)
adac28be
VK
2753 {
2754 case DCE_SUCCESS:
2755 return RCC_SUCCESS;
2756 case DCE_COMM_ERROR:
2757 return RCC_COMM_FAILURE;
2758 case DCE_NOT_SUPPORTED:
2759 return RCC_DCI_NOT_SUPPORTED;
2760 default:
2761 return RCC_SYSTEM_FAILURE;
2762 }
2763}
2764
2765
2766//
5039dede
AK
2767// Get item's value for client
2768//
2769
adac28be 2770DWORD Node::getItemForClient(int iOrigin, const TCHAR *pszParam, TCHAR *pszBuffer, DWORD dwBufSize)
5039dede
AK
2771{
2772 DWORD dwResult = 0, dwRetCode;
2773
2774 // Get data from node
2775 switch(iOrigin)
2776 {
2777 case DS_INTERNAL:
2778 dwRetCode = GetInternalItem(pszParam, dwBufSize, pszBuffer);
2779 break;
2780 case DS_NATIVE_AGENT:
2781 dwRetCode = GetItemFromAgent(pszParam, dwBufSize, pszBuffer);
2782 break;
2783 case DS_SNMP_AGENT:
e320f8ce 2784 dwRetCode = getItemFromSNMP(0, pszParam, dwBufSize, pszBuffer, SNMP_RAWTYPE_NONE);
5039dede
AK
2785 break;
2786 case DS_CHECKPOINT_AGENT:
2787 dwRetCode = GetItemFromCheckPointSNMP(pszParam, dwBufSize, pszBuffer);
2788 break;
2789 default:
2790 dwResult = RCC_INVALID_ARGUMENT;
2791 break;
2792 }
2793
2794 // Translate return code to RCC
2795 if (dwResult != RCC_INVALID_ARGUMENT)
adac28be 2796 dwResult = RCCFromDCIError(dwRetCode);
5039dede
AK
2797
2798 return dwResult;
2799}
2800
2801
2802//
adac28be
VK
2803// Get table for client
2804//
2805
3188558a 2806DWORD Node::getTableForClient(const TCHAR *name, Table **table)
adac28be 2807{
3188558a 2808 DWORD dwRetCode = getTableFromAgent(name, table);
adac28be
VK
2809 return RCCFromDCIError(dwRetCode);
2810}
2811
2812
2813//
5039dede
AK
2814// Put items which requires polling into the queue
2815//
2816
7c521895 2817void Node::queueItemsForPolling(Queue *pPollerQueue)
5039dede 2818{
5039dede
AK
2819 if ((m_iStatus == STATUS_UNMANAGED) ||
2820 (m_dwFlags & NF_DISABLE_DATA_COLLECT) ||
2821 (m_bIsDeleted))
2822 return; // Do not collect data for unmanaged nodes or if data collection is disabled
2823
16d6f798 2824 time_t currTime = time(NULL);
5039dede 2825
7c521895 2826 lockDciAccess();
16d6f798 2827 for(int i = 0; i < m_dcObjects->size(); i++)
5039dede 2828 {
16d6f798
VK
2829 DCObject *object = m_dcObjects->get(i);
2830 if (object->isReadyForPolling(currTime))
5039dede 2831 {
16d6f798 2832 object->setBusyFlag(TRUE);
5039dede 2833 IncRefCount(); // Increment reference count for each queued DCI
16d6f798
VK
2834 pPollerQueue->Put(object);
2835 DbgPrintf(8, _T("Node(%s)->QueueItemsForPolling(): item %d \"%s\" added to queue"), m_szName, object->getId(), object->getName());
5039dede
AK
2836 }
2837 }
7c521895 2838 unlockDciAccess();
5039dede
AK
2839}
2840
2841
2842//
2843// Create CSCP message with object's data
2844//
2845
2846void Node::CreateMessage(CSCPMessage *pMsg)
2847{
2848 Template::CreateMessage(pMsg);
5a7d6a10 2849 pMsg->SetVariable(VID_PRIMARY_NAME, m_primaryName);
5039dede 2850 pMsg->SetVariable(VID_FLAGS, m_dwFlags);
fa6173b9 2851 pMsg->SetVariable(VID_RUNTIME_FLAGS, m_dwDynamicFlags);
5039dede
AK
2852 pMsg->SetVariable(VID_AGENT_PORT, m_wAgentPort);
2853 pMsg->SetVariable(VID_AUTH_METHOD, m_wAuthMethod);
2854 pMsg->SetVariable(VID_SHARED_SECRET, m_szSharedSecret);
35f836fe
VK
2855 pMsg->SetVariableFromMBString(VID_SNMP_AUTH_OBJECT, m_snmpSecurity->getCommunity());
2856 pMsg->SetVariableFromMBString(VID_SNMP_AUTH_PASSWORD, m_snmpSecurity->getAuthPassword());
2857 pMsg->SetVariableFromMBString(VID_SNMP_PRIV_PASSWORD, m_snmpSecurity->getPrivPassword());
4b7d8903 2858 pMsg->SetVariable(VID_SNMP_USM_METHODS, (WORD)((WORD)m_snmpSecurity->getAuthMethod() | ((WORD)m_snmpSecurity->getPrivMethod() << 8)));
5039dede 2859 pMsg->SetVariable(VID_SNMP_OID, m_szObjectId);
65e2005b 2860 pMsg->SetVariable(VID_SNMP_PORT, m_wSNMPPort);
5d2c5741 2861 pMsg->SetVariable(VID_SNMP_VERSION, (WORD)m_snmpVersion);
5039dede
AK
2862 pMsg->SetVariable(VID_AGENT_VERSION, m_szAgentVersion);
2863 pMsg->SetVariable(VID_PLATFORM_NAME, m_szPlatformName);
2864 pMsg->SetVariable(VID_POLLER_NODE_ID, m_dwPollerNode);
52c31148 2865 pMsg->SetVariable(VID_ZONE_ID, m_zoneId);
e41fced3 2866 pMsg->SetVariable(VID_AGENT_PROXY, m_dwProxyNode);
5039dede
AK
2867 pMsg->SetVariable(VID_SNMP_PROXY, m_dwSNMPProxy);
2868 pMsg->SetVariable(VID_REQUIRED_POLLS, (WORD)m_iRequiredPollCount);
0ecc2200
VK
2869 pMsg->SetVariable(VID_SYS_NAME, CHECK_NULL_EX(m_sysName));
2870 pMsg->SetVariable(VID_SYS_DESCRIPTION, CHECK_NULL_EX(m_sysDescription));
3eab63f2 2871 pMsg->SetVariable(VID_BRIDGE_BASE_ADDRESS, m_baseBridgeAddress, 6);
0ecc2200
VK
2872 if (m_lldpNodeId != NULL)
2873 pMsg->SetVariable(VID_LLDP_NODE_ID, m_lldpNodeId);
5039dede 2874 pMsg->SetVariable(VID_USE_IFXTABLE, (WORD)m_nUseIfXTable);
0d75ea88
VK
2875 if (m_vrrpInfo != NULL)
2876 {
2877 pMsg->SetVariable(VID_VRRP_VERSION, (WORD)m_vrrpInfo->getVersion());
2878 pMsg->SetVariable(VID_VRRP_VR_COUNT, (WORD)m_vrrpInfo->getSize());
2879 }
9796ce45
VK
2880 if (m_driver != NULL)
2881 {
2882 pMsg->SetVariable(VID_DRIVER_NAME, m_driver->getName());
2883 pMsg->SetVariable(VID_DRIVER_VERSION, m_driver->getVersion());
2884 }
5039dede
AK
2885}
2886
2887
2888//
2889// Modify object from message
2890//
2891
2892DWORD Node::ModifyFromMessage(CSCPMessage *pRequest, BOOL bAlreadyLocked)
2893{
2894 if (!bAlreadyLocked)
2895 LockData();
2896
2897 // Change primary IP address
2898 if (pRequest->IsVariableExist(VID_IP_ADDRESS))
2899 {
2900 DWORD i, dwIpAddr;
2901
2902 dwIpAddr = pRequest->GetVariableLong(VID_IP_ADDRESS);
2903
2904 // Check if received IP address is one of node's interface addresses
2905 LockChildList(FALSE);
2906 for(i = 0; i < m_dwChildCount; i++)
2907 if ((m_pChildList[i]->Type() == OBJECT_INTERFACE) &&
2908 (m_pChildList[i]->IpAddr() == dwIpAddr))
2909 break;
2910 UnlockChildList();
2911 if (i == m_dwChildCount)
2912 {
2913 UnlockData();
2914 return RCC_INVALID_IP_ADDR;
2915 }
2916
5039dede 2917 m_dwIpAddr = dwIpAddr;
5a7d6a10
VK
2918
2919 // Update primary name if it is not set with the same message
2920 if (!pRequest->IsVariableExist(VID_PRIMARY_NAME))
2921 {
2922 IpToStr(m_dwIpAddr, m_primaryName);
2923 }
5039dede
AK
2924 }
2925
fed33789 2926 // Change primary host name
5a7d6a10
VK
2927 if (pRequest->IsVariableExist(VID_PRIMARY_NAME))
2928 {
2929 pRequest->GetVariableStr(VID_PRIMARY_NAME, m_primaryName, MAX_DNS_NAME);
2930 m_dwDynamicFlags |= NDF_FORCE_CONFIGURATION_POLL | NDF_RECHECK_CAPABILITIES;
2931 }
2932
5039dede
AK
2933 // Poller node ID
2934 if (pRequest->IsVariableExist(VID_POLLER_NODE_ID))
2935 {
2936 DWORD dwNodeId;
2937 NetObj *pObject;
2938
2939 dwNodeId = pRequest->GetVariableLong(VID_POLLER_NODE_ID);
41f9a6dc
VK
2940 if (dwNodeId != 0)
2941 {
2942 pObject = FindObjectById(dwNodeId);
5039dede 2943
41f9a6dc
VK
2944 // Check if received id is a valid node id
2945 if (pObject == NULL)
2946 {
2947 UnlockData();
2948 return RCC_INVALID_OBJECT_ID;
2949 }
2950 if (pObject->Type() != OBJECT_NODE)
2951 {
2952 UnlockData();
2953 return RCC_INVALID_OBJECT_ID;
2954 }
2955 }
2956 m_dwPollerNode = dwNodeId;
5039dede
AK
2957 }
2958
2959 // Change listen port of native agent
2960 if (pRequest->IsVariableExist(VID_AGENT_PORT))
2961 m_wAgentPort = pRequest->GetVariableShort(VID_AGENT_PORT);
2962
2963 // Change authentication method of native agent
2964 if (pRequest->IsVariableExist(VID_AUTH_METHOD))
2965 m_wAuthMethod = pRequest->GetVariableShort(VID_AUTH_METHOD);
2966
2967 // Change shared secret of native agent
2968 if (pRequest->IsVariableExist(VID_SHARED_SECRET))
2969 pRequest->GetVariableStr(VID_SHARED_SECRET, m_szSharedSecret, MAX_SECRET_LENGTH);
2970
2971 // Change SNMP protocol version
2972 if (pRequest->IsVariableExist(VID_SNMP_VERSION))
14b98b3a 2973 {
5d2c5741 2974 m_snmpVersion = pRequest->GetVariableShort(VID_SNMP_VERSION);
14b98b3a
VK
2975 m_snmpSecurity->setSecurityModel((m_snmpVersion == SNMP_VERSION_3) ? SNMP_SECURITY_MODEL_USM : SNMP_SECURITY_MODEL_V2C);
2976 }
5039dede 2977
65e2005b
VK
2978 // Change SNMP port
2979 if (pRequest->IsVariableExist(VID_SNMP_PORT))
2980 m_wSNMPPort = pRequest->GetVariableShort(VID_SNMP_PORT);
2981
4b7d8903
VK
2982 // Change SNMP authentication data
2983 if (pRequest->IsVariableExist(VID_SNMP_AUTH_OBJECT))
5d2c5741 2984 {
35f836fe
VK
2985 char mbBuffer[256];
2986
2987 pRequest->GetVariableStrA(VID_SNMP_AUTH_OBJECT, mbBuffer, 256);
2988 m_snmpSecurity->setAuthName(mbBuffer);
4b7d8903 2989
35f836fe
VK
2990 pRequest->GetVariableStrA(VID_SNMP_AUTH_PASSWORD, mbBuffer, 256);
2991 m_snmpSecurity->setAuthPassword(mbBuffer);
4b7d8903 2992
35f836fe
VK
2993 pRequest->GetVariableStrA(VID_SNMP_PRIV_PASSWORD, mbBuffer, 256);
2994 m_snmpSecurity->setPrivPassword(mbBuffer);
4b7d8903
VK
2995
2996 WORD methods = pRequest->GetVariableShort(VID_SNMP_USM_METHODS);
2997 m_snmpSecurity->setAuthMethod((int)(methods & 0xFF));
2998 m_snmpSecurity->setPrivMethod((int)(methods >> 8));
5d2c5741 2999 }
5039dede
AK
3000
3001 // Change proxy node
e41fced3
VK
3002 if (pRequest->IsVariableExist(VID_AGENT_PROXY))
3003 m_dwProxyNode = pRequest->GetVariableLong(VID_AGENT_PROXY);
5039dede
AK
3004
3005 // Change SNMP proxy node
3006 if (pRequest->IsVariableExist(VID_SNMP_PROXY))
3007 m_dwSNMPProxy = pRequest->GetVariableLong(VID_SNMP_PROXY);
3008
3009 // Number of required polls
3010 if (pRequest->IsVariableExist(VID_REQUIRED_POLLS))
3011 m_iRequiredPollCount = (int)pRequest->GetVariableShort(VID_REQUIRED_POLLS);
3012
3013 // Enable/disable usage of ifXTable
3014 if (pRequest->IsVariableExist(VID_USE_IFXTABLE))
3015 m_nUseIfXTable = (BYTE)pRequest->GetVariableShort(VID_USE_IFXTABLE);
3016
3017 // Change flags
3018 if (pRequest->IsVariableExist(VID_FLAGS))
3019 {
3020 m_dwFlags &= NF_SYSTEM_FLAGS;
3021 m_dwFlags |= pRequest->GetVariableLong(VID_FLAGS) & NF_USER_FLAGS;
3022 }
3023
3024 return Template::ModifyFromMessage(pRequest, TRUE);
3025}
3026
3027
3028//
3029// Wakeup node using magic packet
3030//
3031
7c521895 3032DWORD Node::wakeUp()
5039dede
AK
3033{
3034 DWORD i, dwResult = RCC_NO_WOL_INTERFACES;
3035
3036 LockChildList(FALSE);
3037
3038 for(i = 0; i < m_dwChildCount; i++)
3039 if ((m_pChildList[i]->Type() == OBJECT_INTERFACE) &&
3040 (m_pChildList[i]->Status() != STATUS_UNMANAGED) &&
3041 (m_pChildList[i]->IpAddr() != 0))
3042 {
7c521895 3043 dwResult = ((Interface *)m_pChildList[i])->wakeUp();
5039dede
AK
3044 break;
3045 }
3046
3047 UnlockChildList();
3048 return dwResult;
3049}
3050
3051
3052//
3053// Get status of interface with given index from SNMP agent
3054//
3055
1e6b68a6 3056void Node::getInterfaceStatusFromSNMP(SNMP_Transport *pTransport, DWORD dwIndex, int *adminState, int *operState)
5039dede 3057{
1e6b68a6 3058 SnmpGetInterfaceStatus(m_snmpVersion, pTransport, dwIndex, adminState, operState);
5039dede
AK
3059}
3060
3061
3062//
3063// Get status of interface with given index from native agent
3064//
3065
1e6b68a6 3066void Node::getInterfaceStatusFromAgent(DWORD dwIndex, int *adminState, int *operState)
5039dede 3067{
35f836fe 3068 TCHAR szParam[128], szBuffer[32];
5039dede
AK
3069
3070 // Get administrative status
35f836fe 3071 _sntprintf(szParam, 128, _T("Net.Interface.AdminStatus(%u)"), dwIndex);
5039dede
AK
3072 if (GetItemFromAgent(szParam, 32, szBuffer) == DCE_SUCCESS)
3073 {
1e6b68a6 3074 *adminState = _tcstol(szBuffer, NULL, 0);
5039dede 3075
1e6b68a6 3076 switch(*adminState)
5039dede 3077 {
1e6b68a6
VK
3078 case IF_ADMIN_STATE_TESTING:
3079 *operState = IF_OPER_STATE_UNKNOWN;
5039dede 3080 break;
1e6b68a6 3081 case IF_ADMIN_STATE_DOWN:
5039dede 3082 case 0: // Agents before 0.2.1 may return 0 instead of 2
1e6b68a6 3083 *operState = IF_OPER_STATE_DOWN;
5039dede 3084 break;
1e6b68a6 3085 case IF_ADMIN_STATE_UP: // Interface administratively up, check link state
35f836fe 3086 _sntprintf(szParam, 128, _T("Net.Interface.Link(%u)"), dwIndex);
5039dede
AK
3087 if (GetItemFromAgent(szParam, 32, szBuffer) == DCE_SUCCESS)
3088 {
1e6b68a6
VK
3089 DWORD dwLinkState = _tcstoul(szBuffer, NULL, 0);
3090 *operState = (dwLinkState == 0) ? IF_OPER_STATE_DOWN : IF_OPER_STATE_UP;
5039dede
AK
3091 }
3092 else
3093 {
1e6b68a6 3094 *operState = IF_OPER_STATE_UNKNOWN;
5039dede
AK
3095 }
3096 break;
3097 default:
1e6b68a6
VK
3098 *adminState = IF_ADMIN_STATE_UNKNOWN;
3099 *operState = IF_OPER_STATE_UNKNOWN;
5039dede
AK
3100 break;
3101 }
3102 }
3103 else
3104 {
1e6b68a6
VK
3105 *adminState = IF_ADMIN_STATE_UNKNOWN;
3106 *operState = IF_OPER_STATE_UNKNOWN;
5039dede 3107 }
5039dede
AK
3108}
3109
3110
3111//
3112// Put list of supported parameters into CSCP message
3113//
3114
cc8ce218 3115void Node::writeParamListToMessage(CSCPMessage *pMsg)
5039dede 3116{
5039dede 3117 LockData();
cc8ce218
VK
3118
3119 if (m_paramList != NULL)
5039dede 3120 {
cc8ce218
VK
3121 pMsg->SetVariable(VID_NUM_PARAMETERS, (DWORD)m_paramList->size());
3122
3123 int i;
3124 DWORD dwId;
3125 for(i = 0, dwId = VID_PARAM_LIST_BASE; i < m_paramList->size(); i++)
5039dede 3126 {
cc8ce218
VK
3127 NXC_AGENT_PARAM *p = m_paramList->get(i);
3128 pMsg->SetVariable(dwId++, p->szName);
3129 pMsg->SetVariable(dwId++, p->szDescription);
3130 pMsg->SetVariable(dwId++, (WORD)p->iDataType);
5039dede 3131 }
cc8ce218 3132 DbgPrintf(6, _T("Node[%s]::writeParamListToMessage(): sending %d parameters"), m_szName, m_paramList->size());
5039dede
AK
3133 }
3134 else
3135 {
cc8ce218 3136 DbgPrintf(6, _T("Node[%s]::writeParamListToMessage(): m_paramList == NULL"), m_szName);
5039dede
AK
3137 pMsg->SetVariable(VID_NUM_PARAMETERS, (DWORD)0);
3138 }
cc8ce218
VK
3139
3140 if (m_tableList != NULL)
3141 {
3142 pMsg->SetVariable(VID_NUM_TABLES, (DWORD)m_tableList->size());
3143
3144 int i;
3145 DWORD dwId;
3146 for(i = 0, dwId = VID_TABLE_LIST_BASE; i < m_tableList->size(); i++)
3147 {
3148 NXC_AGENT_TABLE *t = m_tableList->get(i);
3149 pMsg->SetVariable(dwId++, t->name);
3150 pMsg->SetVariable(dwId++, t->instanceColumn);
3151 pMsg->SetVariable(dwId++, t->description);
3152 }
3153 DbgPrintf(6, _T("Node[%s]::writeParamListToMessage(): sending %d tables"), m_szName, m_tableList->size());
3154 }
3155 else
3156 {
3157 DbgPrintf(6, _T("Node[%s]::writeParamListToMessage(): m_tableList == NULL"), m_szName);
3158 pMsg->SetVariable(VID_NUM_TABLES, (DWORD)0);
3159 }
3160
3161 UnlockData();
5039dede
AK
3162}
3163
3164
3165//
3166// Open list of supported parameters for reading
3167//
3168
cc8ce218 3169void Node::openParamList(StructArray<NXC_AGENT_PARAM> **paramList)
5039dede
AK
3170{
3171 LockData();
cc8ce218 3172 *paramList = m_paramList;
5039dede
AK
3173}
3174
3175
3176//
3177// Check status of network service
3178//
3179
3180DWORD Node::CheckNetworkService(DWORD *pdwStatus, DWORD dwIpAddr, int iServiceType,
3181 WORD wPort, WORD wProto, TCHAR *pszRequest,
3182 TCHAR *pszResponse)
3183{
3184 DWORD dwError = ERR_NOT_CONNECTED;
3185
3186 if ((m_dwFlags & NF_IS_NATIVE_AGENT) &&
3187 (!(m_dwDynamicFlags & NDF_AGENT_UNREACHABLE)) &&
3188 (!(m_dwDynamicFlags & NDF_UNREACHABLE)))
3189 {
3190 AgentConnection *pConn;
3191
cd9f247e 3192 pConn = createAgentConnection();
5039dede
AK
3193 if (pConn != NULL)
3194 {
4687826e 3195 dwError = pConn->checkNetworkService(pdwStatus, dwIpAddr, iServiceType,
5039dede 3196 wPort, wProto, pszRequest, pszResponse);
7c521895 3197 pConn->disconnect();
5039dede
AK
3198 delete pConn;
3199 }
3200 }
3201 return dwError;
3202}
3203
3204
3205//
3206// Handler for object deletion
3207//
3208
3209void Node::OnObjectDelete(DWORD dwObjectId)
3210{
f5d16551 3211 LockData();
5039dede
AK
3212 if (dwObjectId == m_dwPollerNode)
3213 {
3214 // If deleted object is our poller node, change it to default
5039dede
AK
3215 m_dwPollerNode = 0;
3216 Modify();
3217 DbgPrintf(3, _T("Node \"%s\": poller node %d deleted"), m_szName, dwObjectId);
3218 }
f5d16551 3219 UnlockData();
5039dede
AK
3220}
3221
3222
3223//
3224// Check node for OSPF support
3225//
3226
3227void Node::CheckOSPFSupport(SNMP_Transport *pTransport)
3228{
3229 LONG nAdminStatus;
3230
5d2c5741 3231 if (SnmpGet(m_snmpVersion, pTransport,
f42b8099 3232 _T(".1.3.6.1.2.1.14.1.2.0"), NULL, 0, &nAdminStatus, sizeof(LONG), 0) == SNMP_ERR_SUCCESS)
5039dede
AK
3233 {
3234 LockData();
3235 if (nAdminStatus)
3236 {
3237 m_dwFlags |= NF_IS_OSPF;
3238 }
3239 else
3240 {
3241 m_dwFlags &= ~NF_IS_OSPF;
3242 }
3243 UnlockData();
3244 }
3245}
3246
3247
3248//
3249// Create ready to use agent connection
3250//
3251
cd9f247e 3252AgentConnectionEx *Node::createAgentConnection()
5039dede 3253{
45d84f8a 3254 AgentConnectionEx *conn;
5039dede
AK
3255
3256 if ((!(m_dwFlags & NF_IS_NATIVE_AGENT)) ||
6b2bb22c 3257 (m_dwFlags & NF_DISABLE_NXCP) ||
5039dede
AK
3258 (m_dwDynamicFlags & NDF_AGENT_UNREACHABLE) ||
3259 (m_dwDynamicFlags & NDF_UNREACHABLE))
3260 return NULL;
3261
1fa5706e
VK
3262 DbgPrintf(6, _T("Node::createAgentConnection(%s [%d])"), m_szName, (int)m_dwId);
3263 conn = new AgentConnectionEx(htonl(m_dwIpAddr), m_wAgentPort, m_wAuthMethod, m_szSharedSecret);
7c521895
VK
3264 setAgentProxy(conn);
3265 if (!conn->connect(g_pServerKey))
5039dede 3266 {
45d84f8a
VK
3267 delete conn;
3268 conn = NULL;
5039dede 3269 }
1fa5706e 3270 DbgPrintf(6, _T("Node::createAgentConnection(%s [%d]): conn=%p"), m_szName, (int)m_dwId, conn);
45d84f8a 3271 return conn;
5039dede
AK
3272}
3273
3274
3275//
3276// Get last collected values of all DCIs
3277//
3278
b9a8e081 3279DWORD Node::getLastValues(CSCPMessage *msg)
5039dede 3280{
7c521895 3281 lockDciAccess();
5039dede 3282
16d6f798
VK
3283 DWORD dwId = VID_DCI_VALUES_BASE, dwCount = 0;
3284 for(int i = 0; i < m_dcObjects->size(); i++)
5039dede 3285 {
16d6f798 3286 DCObject *object = m_dcObjects->get(i);
92c51b1d 3287 if (_tcsnicmp(object->getDescription(), _T("@system."), 8))
5039dede 3288 {
92c51b1d
VK
3289 if (object->getType() == DCO_TYPE_ITEM)
3290 {
3291 ((DCItem *)object)->getLastValue(msg, dwId);
3292 dwId += 50;
3293 dwCount++;
3294 }
3295 else if (object->getType() == DCO_TYPE_TABLE)
3296 {
3297 ((DCTable *)object)->getLastValueSummary(msg, dwId);
3298 dwId += 50;
3299 dwCount++;
3300 }
5039dede
AK
3301 }
3302 }
b9a8e081 3303 msg->SetVariable(VID_NUM_ITEMS, dwCount);
5039dede 3304
7c521895 3305 unlockDciAccess();
5039dede
AK
3306 return RCC_SUCCESS;
3307}
3308
3309
3310//
b9a8e081
VK
3311// Get last collected values of givel table
3312//
3313
3314DWORD Node::getTableLastValues(DWORD dciId, CSCPMessage *msg)
3315{
3316 DWORD rcc = RCC_INVALID_DCI_ID;
3317
3318 lockDciAccess();
3319
3320 for(int i = 0; i < m_dcObjects->size(); i++)
3321 {
3322 DCObject *object = m_dcObjects->get(i);
3323 if ((object->getId() == dciId) && (object->getType() == DCO_TYPE_TABLE))
3324 {
3325 ((DCTable *)object)->getLastValue(msg);
3326 rcc = RCC_SUCCESS;
3327 break;
3328 }
3329 }
3330
3331 unlockDciAccess();
3332 return rcc;
3333}
3334
3335
3336//
5039dede
AK
3337// Clean expired DCI data
3338//
3339
7c521895 3340void Node::cleanDCIData()
5039dede 3341{
7c521895 3342 lockDciAccess();
16d6f798
VK
3343 for(int i = 0; i < m_dcObjects->size(); i++)
3344 m_dcObjects->get(i)->deleteExpiredData();
7c521895 3345 unlockDciAccess();
5039dede
AK
3346}
3347
3348
3349//
3350// Apply DCI from template
3351// pItem passed to this method should be a template's DCI
3352//
3353
16d6f798 3354bool Node::applyTemplateItem(DWORD dwTemplateId, DCObject *dcObject)
5039dede 3355{
16d6f798 3356 bool bResult = true;
5039dede 3357
a2069340 3358 lockDciAccess(); // write lock
5039dede 3359
16d6f798 3360 DbgPrintf(5, _T("Applying DCO \"%s\" to node \"%s\""), dcObject->getName(), m_szName);
5039dede
AK
3361
3362 // Check if that template item exists
16d6f798
VK
3363 int i;
3364 for(i = 0; i < m_dcObjects->size(); i++)
3365 if ((m_dcObjects->get(i)->getTemplateId() == dwTemplateId) &&
3366 (m_dcObjects->get(i)->getTemplateItemId() == dcObject->getId()))
5039dede
AK
3367 break; // Item with specified id already exist
3368
16d6f798 3369 if (i == m_dcObjects->size())
5039dede
AK
3370 {