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