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