latest changes backported from 1.0.x
[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//
1f385e47
VK
995// Check agent policy binding
996// Intended to be called only from configuration poller
997//
998
999void Node::checkAgentPolicyBinding(AgentConnection *conn)
1000{
1001 AgentPolicyInfo *ap;
1002 DWORD rcc = conn->getPolicyInventory(&ap);
1003 if (rcc == ERR_SUCCESS)
1004 {
1005 // Check for unbound but installed policies
1006 for(int i = 0; i < ap->getSize(); i++)
1007 {
1008 uuid_t guid;
1009 ap->getGuid(i, guid);
1010 NetObj *object = FindObjectByGUID(guid, -1);
1011 if ((object != NULL) && (!object->IsChild(m_dwId)))
1012 {
1013 object->AddChild(this);
1014 AddParent(object);
1015 DbgPrintf(5, _T("ConfPoll(%s): bound to policy object %s [%d]"), m_szName, object->Name(), object->Id());
1016 }
1017 }
1018
1019 // Check for bound but not installed policies
1020 LockParentList(FALSE);
1021 NetObj **unbindList = (NetObj **)malloc(sizeof(NetObj *) * m_dwParentCount);
1022 int unbindListSize = 0;
1023 for(DWORD i = 0; i < m_dwParentCount; i++)
1024 {
1025 if (IsAgentPolicyObject(m_pParentList[i]))
1026 {
1027 uuid_t guid1, guid2;
1028 int j;
1029
1030 m_pParentList[i]->getGuid(guid1);
1031 for(j = 0; j < ap->getSize(); j++)
1032 {
1033 ap->getGuid(j, guid2);
1034 if (!uuid_compare(guid1, guid2))
1035 break;
1036 }
1037 if (j == ap->getSize())
1038 unbindList[unbindListSize++] = m_pParentList[i];
1039 }
1040 }
1041 UnlockParentList();
1042
1043 for(int i = 0; i < unbindListSize; i++)
1044 {
1045 unbindList[i]->DeleteChild(this);
1046 DeleteParent(unbindList[i]);
1047 DbgPrintf(5, _T("ConfPoll(%s): unbound from policy object %s [%d]"), m_szName, unbindList[i]->Name(), unbindList[i]->Id());
1048 }
1049 safe_free(unbindList);
1050
1051 delete ap;
1052 }
1053 else
1054 {
1055 DbgPrintf(5, _T("ConfPoll(%s): AgentConnection::getPolicyInventory() failed: rcc=%d"), m_szName, rcc);
1056 }
1057}
1058
1059
1060//
5039dede
AK
1061// Perform configuration poll on node
1062//
1063
58b3e451 1064void Node::configurationPoll(ClientSession *pSession, DWORD dwRqId,
5039dede
AK
1065 int nPoller, DWORD dwNetMask)
1066{
1067 DWORD i, dwOldFlags = m_dwFlags, dwAddr, rcc, dwNumParams;
1068 NXC_AGENT_PARAM *pParamList;
1069 Interface **ppDeleteList;
1070 int j, iDelCount;
1071 AgentConnection *pAgentConn;
1072 INTERFACE_LIST *pIfList;
1073 char szBuffer[4096];
1074 Cluster *pCluster;
1075 SNMP_Transport *pTransport;
5039dede
AK
1076 BOOL bHasChanges = FALSE;
1077
1078 SetPollerInfo(nPoller, "wait for lock");
7c521895 1079 pollerLock();
5039dede
AK
1080 m_pPollRequestor = pSession;
1081 SendPollerMsg(dwRqId, _T("Starting configuration poll for node %s\r\n"), m_szName);
1082 DbgPrintf(4, "Starting configuration poll for node %s (ID: %d)", m_szName, m_dwId);
1083
1084 // Check for forced capabilities recheck
1085 if (m_dwDynamicFlags & NDF_RECHECK_CAPABILITIES)
1086 {
1087 m_dwFlags &= ~(NF_IS_NATIVE_AGENT | NF_IS_SNMP | NF_IS_CPSNMP |
1088 NF_IS_BRIDGE | NF_IS_ROUTER | NF_IS_OSPF);
e4a64da2 1089 m_dwDynamicFlags &= ~NDF_CONFIGURATION_POLL_PASSED;
5039dede
AK
1090 m_szObjectId[0] = 0;
1091 m_szPlatformName[0] = 0;
1092 m_szAgentVersion[0] = 0;
1093 m_szSysDescription[0] = 0;
1094 }
1095
1096 // Check if node is marked as unreachable
1097 if ((m_dwDynamicFlags & NDF_UNREACHABLE) && !(m_dwDynamicFlags & NDF_RECHECK_CAPABILITIES))
1098 {
1099 SendPollerMsg(dwRqId, POLLER_WARNING _T("Node is marked as unreachable, configuration poll aborted\r\n"));
1100 DbgPrintf(4, "Node is marked as unreachable, configuration poll aborted");
1101 m_tLastConfigurationPoll = time(NULL);
1102 }
1103 else
1104 {
1105 // Check node's capabilities
1106 SetPollerInfo(nPoller, "capability check");
1107 SendPollerMsg(dwRqId, _T("Checking node's capabilities...\r\n"));
1108
1109 // ***** NetXMS agent check *****
1110 DbgPrintf(5, "ConfPoll(%s): checking for NetXMS agent Flags={%08X} DynamicFlags={%08X}", m_szName, m_dwFlags, m_dwDynamicFlags);
1111 if ((!((m_dwFlags & NF_IS_NATIVE_AGENT) && (m_dwDynamicFlags & NDF_AGENT_UNREACHABLE))) &&
15d6f8c9 1112 (!(m_dwFlags & NF_DISABLE_NXCP)) && (m_dwIpAddr != 0))
5039dede
AK
1113 {
1114 SendPollerMsg(dwRqId, _T(" Checking NetXMS agent...\r\n"));
1115 pAgentConn = new AgentConnection(htonl(m_dwIpAddr), m_wAgentPort,
1116 m_wAuthMethod, m_szSharedSecret);
7c521895 1117 setAgentProxy(pAgentConn);
5039dede 1118 DbgPrintf(5, "ConfPoll(%s): checking for NetXMS agent - connecting", m_szName);
7c521895 1119 if (pAgentConn->connect(g_pServerKey))
5039dede
AK
1120 {
1121 DbgPrintf(5, "ConfPoll(%s): checking for NetXMS agent - connected", m_szName);
1122 LockData();
1123 m_dwFlags |= NF_IS_NATIVE_AGENT;
1124 if (m_dwDynamicFlags & NDF_AGENT_UNREACHABLE)
1125 {
1126 m_dwDynamicFlags &= ~NDF_AGENT_UNREACHABLE;
1127 PostEvent(EVENT_AGENT_OK, m_dwId, NULL);
1128 SendPollerMsg(dwRqId, POLLER_INFO _T(" Connectivity with NetXMS agent restored\r\n"));
1129 }
1f385e47
VK
1130 else
1131 {
1132 SendPollerMsg(dwRqId, POLLER_INFO _T(" NetXMS native agent is active\r\n"));
1133 }
5039dede
AK
1134 UnlockData();
1135
1136 if (pAgentConn->GetParameter("Agent.Version", MAX_AGENT_VERSION_LEN, szBuffer) == ERR_SUCCESS)
1137 {
1138 LockData();
1139 if (strcmp(m_szAgentVersion, szBuffer))
1140 {
1141 strcpy(m_szAgentVersion, szBuffer);
1142 bHasChanges = TRUE;
1143 SendPollerMsg(dwRqId, _T(" NetXMS agent version changed to %s\r\n"), m_szAgentVersion);
1144 }
1145 UnlockData();
1146 }
1147
1148 if (pAgentConn->GetParameter("System.PlatformName", MAX_PLATFORM_NAME_LEN, szBuffer) == ERR_SUCCESS)
1149 {
1150 LockData();
1151 if (strcmp(m_szPlatformName, szBuffer))
1152 {
1153 strcpy(m_szPlatformName, szBuffer);
1154 bHasChanges = TRUE;
1155 SendPollerMsg(dwRqId, _T(" Platform name changed to %s\r\n"), m_szPlatformName);
1156 }
1157 UnlockData();
1158 }
1159
1160 // Check IP forwarding status
1161 if (pAgentConn->GetParameter("Net.IP.Forwarding", 16, szBuffer) == ERR_SUCCESS)
1162 {
1163 if (_tcstoul(szBuffer, NULL, 10) != 0)
1164 m_dwFlags |= NF_IS_ROUTER;
1165 else
1166 m_dwFlags &= ~NF_IS_ROUTER;
1167 }
1168
1169 // Get uname
1170 if (pAgentConn->GetParameter("System.Uname", MAX_DB_STRING, szBuffer) == ERR_SUCCESS)
1171 {
1172 TranslateStr(szBuffer, "\r\n", " ");
1173 TranslateStr(szBuffer, "\n", " ");
1174 TranslateStr(szBuffer, "\r", " ");
1175 LockData();
1176 if (strcmp(m_szSysDescription, szBuffer))
1177 {
1178 strcpy(m_szSysDescription, szBuffer);
1179 bHasChanges = TRUE;
1180 SendPollerMsg(dwRqId, _T(" System description changed to %s\r\n"), m_szSysDescription);
1181 }
1182 UnlockData();
1183 }
1184
1185 rcc = pAgentConn->GetSupportedParameters(&dwNumParams, &pParamList);
1186 if (rcc == ERR_SUCCESS)
1187 {
1188 LockData();
1189 safe_free(m_pParamList);
1190 m_dwNumParams = dwNumParams;
1191 m_pParamList = pParamList;
1192 UnlockData();
1193 }
1194 else
1195 {
1196 DbgPrintf(5, _T("ConfPoll(%s): AgentConnection::GetSupportedParameters() failed: rcc=%d"), m_szName, rcc);
1197 }
1198
1f385e47
VK
1199 checkAgentPolicyBinding(pAgentConn);
1200
7c521895 1201 pAgentConn->disconnect();
5039dede
AK
1202 }
1203 delete pAgentConn;
1204 DbgPrintf(5, "ConfPoll(%s): checking for NetXMS agent - finished", m_szName);
1205 }
1206
1207 // ***** SNMP check *****
1208 if ((!((m_dwFlags & NF_IS_SNMP) && (m_dwDynamicFlags & NDF_SNMP_UNREACHABLE))) &&
15d6f8c9 1209 (!(m_dwFlags & NF_DISABLE_SNMP)) && (m_dwIpAddr != 0))
5039dede
AK
1210 {
1211 SendPollerMsg(dwRqId, _T(" Checking SNMP...\r\n"));
df8a4ca2 1212 DbgPrintf(5, "ConfPoll(%s): calling SnmpCheckCommSettings()", m_szName);
cd9f247e 1213 pTransport = createSnmpTransport();
f2ec1aae
VK
1214 if (pTransport == NULL)
1215 {
1216 DbgPrintf(5, "ConfPoll(%s): unable to create SNMP transport", m_szName);
1217 goto skip_snmp_checks;
1218 }
5039dede 1219
df8a4ca2
VK
1220 SNMP_SecurityContext *newCtx = SnmpCheckCommSettings(pTransport, &m_snmpVersion, m_snmpSecurity);
1221 if (newCtx != NULL)
5039dede
AK
1222 {
1223 DWORD dwNodeFlags, dwNodeType;
1224
1225 LockData();
df8a4ca2
VK
1226 delete m_snmpSecurity;
1227 m_snmpSecurity = newCtx;
5039dede
AK
1228 m_dwFlags |= NF_IS_SNMP;
1229 if (m_dwDynamicFlags & NDF_SNMP_UNREACHABLE)
1230 {
1231 m_dwDynamicFlags &= ~NDF_SNMP_UNREACHABLE;
1232 PostEvent(EVENT_SNMP_OK, m_dwId, NULL);
df8a4ca2 1233 SendPollerMsg(dwRqId, POLLER_INFO _T(" Connectivity with SNMP agent restored\r\n"));
5039dede
AK
1234 }
1235 UnlockData();
df8a4ca2
VK
1236 SendPollerMsg(dwRqId, _T(" SNMP agent is active (version %s)\r\n"),
1237 (m_snmpVersion == SNMP_VERSION_3) ? _T("3") : ((m_snmpVersion == SNMP_VERSION_2C) ? _T("2c") : _T("1")));
5039dede 1238
5d2c5741 1239 if (SnmpGet(m_snmpVersion, pTransport,
5039dede
AK
1240 ".1.3.6.1.2.1.1.2.0", NULL, 0, szBuffer, 4096,
1241 FALSE, FALSE) == SNMP_ERR_SUCCESS)
1242 {
1243 LockData();
1244 if (strcmp(m_szObjectId, szBuffer))
1245 {
1246 nx_strncpy(m_szObjectId, szBuffer, MAX_OID_LEN * 4);
1247 bHasChanges = TRUE;
1248 }
1249 UnlockData();
1250 }
1251
1252 // Check node type
1253 LockData();
1254 dwNodeType = OidToType(m_szObjectId, &dwNodeFlags);
1255 if (m_dwNodeType != dwNodeType)
1256 {
1257 m_dwFlags |= dwNodeFlags;
1258 m_dwNodeType = dwNodeType;
1259 SendPollerMsg(dwRqId, POLLER_WARNING _T(" Node type has been changed to %d\r\n"), m_dwNodeType);
1260 bHasChanges = TRUE;
1261 }
1262 UnlockData();
1263
1264 // Check IP forwarding
1265 if (CheckSNMPIntegerValue(pTransport, ".1.3.6.1.2.1.4.1.0", 1))
1266 {
1267 LockData();
1268 m_dwFlags |= NF_IS_ROUTER;
1269 UnlockData();
1270 }
1271 else
1272 {
1273 LockData();
1274 m_dwFlags &= ~NF_IS_ROUTER;
1275 UnlockData();
1276 }
1277
1278 // Check for bridge MIB support
5d2c5741 1279 if (SnmpGet(m_snmpVersion, pTransport,
5039dede
AK
1280 ".1.3.6.1.2.1.17.1.1.0", NULL, 0, szBuffer, 4096,
1281 FALSE, FALSE) == SNMP_ERR_SUCCESS)
1282 {
1283 LockData();
1284 m_dwFlags |= NF_IS_BRIDGE;
1285 UnlockData();
1286 }
1287 else
1288 {
1289 LockData();
1290 m_dwFlags &= ~NF_IS_BRIDGE;
1291 UnlockData();
1292 }
1293
1294 // Check for CDP (Cisco Discovery Protocol) support
1295 if (CheckSNMPIntegerValue(pTransport, ".1.3.6.1.4.1.9.9.23.1.3.1.0", 1))
1296 {
1297 LockData();
1298 m_dwFlags |= NF_IS_CDP;
1299 UnlockData();
1300 }
1301 else
1302 {
1303 LockData();
1304 m_dwFlags &= ~NF_IS_CDP;
1305 UnlockData();
1306 }
1307
1308 // Check for SONMP (Nortel topology discovery discovery protocol) support
1309 if (CheckSNMPIntegerValue(pTransport, ".1.3.6.1.4.1.45.1.6.13.1.2.0", 1))
1310 {
1311 LockData();
1312 m_dwFlags |= NF_IS_SONMP;
1313 UnlockData();
1314 }
1315 else
1316 {
1317 LockData();
1318 m_dwFlags &= ~NF_IS_SONMP;
1319 UnlockData();
1320 }
1321
1322 // Check for LLDP (Link Layer Discovery Protocol) support
5d2c5741 1323 if (SnmpGet(m_snmpVersion, pTransport,
5039dede
AK
1324 ".1.0.8802.1.1.2.1.3.2.0", NULL, 0, szBuffer, 4096,
1325 FALSE, FALSE) == SNMP_ERR_SUCCESS)
1326 {
1327 LockData();
1328 m_dwFlags |= NF_IS_LLDP;
1329 UnlockData();
1330 }
1331 else
1332 {
1333 LockData();
1334 m_dwFlags &= ~NF_IS_LLDP;
1335 UnlockData();
1336 }
1337
1338 // Get system description
5d2c5741 1339 if (SnmpGet(m_snmpVersion, pTransport,
5039dede
AK
1340 ".1.3.6.1.2.1.1.1.0", NULL, 0, szBuffer,
1341 MAX_DB_STRING, FALSE, FALSE) == SNMP_ERR_SUCCESS)
1342 {
1343 TranslateStr(szBuffer, "\r\n", " ");
1344 TranslateStr(szBuffer, "\n", " ");
1345 TranslateStr(szBuffer, "\r", " ");
1346 LockData();
1347 if (strcmp(m_szSysDescription, szBuffer))
1348 {
1349 strcpy(m_szSysDescription, szBuffer);
1350 bHasChanges = TRUE;
1351 SendPollerMsg(dwRqId, _T(" System description changed to %s\r\n"), m_szSysDescription);
1352 }
1353 UnlockData();
1354 }
1355
1356 CheckOSPFSupport(pTransport);
1357 }
1358 else
1359 {
1360 // Check for CheckPoint SNMP agent on port 161
1361 DbgPrintf(5, "ConfPoll(%s): checking for CheckPoint SNMP", m_szName);
5d2c5741 1362 if (SnmpGet(m_snmpVersion, pTransport,
5039dede
AK
1363 ".1.3.6.1.4.1.2620.1.1.10.0", NULL, 0,
1364 szBuffer, 4096, FALSE, FALSE) == SNMP_ERR_SUCCESS)
1365 {
1366 LockData();
1367 if (strcmp(m_szObjectId, ".1.3.6.1.4.1.2620.1.1"))
1368 {
1369 nx_strncpy(m_szObjectId, ".1.3.6.1.4.1.2620.1.1", MAX_OID_LEN * 4);
1370 bHasChanges = TRUE;
1371 }
1372
1373 m_dwFlags |= NF_IS_SNMP | NF_IS_ROUTER;
1374 m_dwDynamicFlags &= ~NDF_SNMP_UNREACHABLE;
1375 UnlockData();
1376 SendPollerMsg(dwRqId, POLLER_INFO _T(" CheckPoint SNMP agent on port 161 is active\r\n"));
1377 }
1378 }
1379 delete pTransport;
1380 }
1381
f2ec1aae 1382skip_snmp_checks:
5039dede
AK
1383 // Check for CheckPoint SNMP agent on port 260
1384 DbgPrintf(5, "ConfPoll(%s): checking for CheckPoint SNMP on port 260", m_szName);
15d6f8c9 1385 if (!((m_dwFlags & NF_IS_CPSNMP) && (m_dwDynamicFlags & NDF_CPSNMP_UNREACHABLE)) && (m_dwIpAddr != 0))
5039dede
AK
1386 {
1387 pTransport = new SNMP_UDPTransport;
c4366266 1388 ((SNMP_UDPTransport *)pTransport)->createUDPTransport(NULL, htonl(m_dwIpAddr), CHECKPOINT_SNMP_PORT);
5d2c5741 1389 if (SnmpGet(SNMP_VERSION_1, pTransport,
5039dede
AK
1390 ".1.3.6.1.4.1.2620.1.1.10.0", NULL, 0,
1391 szBuffer, 4096, FALSE, FALSE) == SNMP_ERR_SUCCESS)
1392 {
1393 LockData();
1394 m_dwFlags |= NF_IS_CPSNMP | NF_IS_ROUTER;
1395 m_dwDynamicFlags &= ~NDF_CPSNMP_UNREACHABLE;
1396 UnlockData();
1397 SendPollerMsg(dwRqId, POLLER_INFO _T(" CheckPoint SNMP agent on port 260 is active\r\n"));
1398 }
1399 delete pTransport;
1400 }
1401
1402 // Generate event if node flags has been changed
1403 if (dwOldFlags != m_dwFlags)
1404 {
1405 PostEvent(EVENT_NODE_FLAGS_CHANGED, m_dwId, "xx", dwOldFlags, m_dwFlags);
1406 bHasChanges = TRUE;
1407 }
1408
1409 // Get parent cluster object, if any
7c521895 1410 pCluster = getMyCluster();
5039dede
AK
1411
1412 // Retrieve interface list
1413 SetPollerInfo(nPoller, "interface check");
df8a4ca2
VK
1414 SendPollerMsg(dwRqId, _T("Capability check finished\r\n"));
1415 SendPollerMsg(dwRqId, _T("Checking interface configuration...\r\n"));
58b3e451 1416 pIfList = getInterfaceList();
5039dede
AK
1417 if (pIfList != NULL)
1418 {
1419 // Remove cluster virtual interfaces from list
1420 if (pCluster != NULL)
1421 {
1422 for(i = 0; i < (DWORD)pIfList->iNumEntries; i++)
1423 {
58b3e451 1424 if (pCluster->isVirtualAddr(pIfList->pInterfaces[i].dwIpAddr))
5039dede
AK
1425 {
1426 pIfList->iNumEntries--;
1427 memmove(&pIfList->pInterfaces[i], &pIfList->pInterfaces[i + 1],
1428 sizeof(INTERFACE_INFO) * (pIfList->iNumEntries - i));
1429 i--;
1430 }
1431 }
1432 }
1433
1434 // Find non-existing interfaces
1435 LockChildList(FALSE);
1436 ppDeleteList = (Interface **)malloc(sizeof(Interface *) * m_dwChildCount);
1437 for(i = 0, iDelCount = 0; i < m_dwChildCount; i++)
1438 {
1439 if (m_pChildList[i]->Type() == OBJECT_INTERFACE)
1440 {
1441 Interface *pInterface = (Interface *)m_pChildList[i];
1442
1443 if (pInterface->IfType() != IFTYPE_NETXMS_NAT_ADAPTER)
1444 {
1445 for(j = 0; j < pIfList->iNumEntries; j++)
1446 {
1447 if ((pIfList->pInterfaces[j].dwIndex == pInterface->IfIndex()) &&
1448 (pIfList->pInterfaces[j].dwIpAddr == pInterface->IpAddr()) &&
1449 (pIfList->pInterfaces[j].dwIpNetMask == pInterface->IpNetMask()))
1450 break;
1451 }
1452
1453 if (j == pIfList->iNumEntries)
1454 {
1455 // No such interface in current configuration, add it to delete list
1456 ppDeleteList[iDelCount++] = pInterface;
1457 }
1458 }
1459 }
1460 }
1461 UnlockChildList();
1462
1463 // Delete non-existent interfaces
1464 if (iDelCount > 0)
1465 {
1466 for(j = 0; j < iDelCount; j++)
1467 {
1468 SendPollerMsg(dwRqId, POLLER_WARNING _T(" Interface \"%s\" is no longer exist\r\n"),
1469 ppDeleteList[j]->Name());
1470 PostEvent(EVENT_INTERFACE_DELETED, m_dwId, "dsaa", ppDeleteList[j]->IfIndex(),
1471 ppDeleteList[j]->Name(), ppDeleteList[j]->IpAddr(), ppDeleteList[j]->IpNetMask());
1472 DeleteInterface(ppDeleteList[j]);
1473 }
1474 bHasChanges = TRUE;
1475 }
1476 safe_free(ppDeleteList);
1477
1478 // Add new interfaces and check configuration of existing
1479 for(j = 0; j < pIfList->iNumEntries; j++)
1480 {
1481 BOOL bNewInterface = TRUE;
1482
1483 LockChildList(FALSE);
1484 for(i = 0; i < m_dwChildCount; i++)
1485 {
1486 if (m_pChildList[i]->Type() == OBJECT_INTERFACE)
1487 {
1488 Interface *pInterface = (Interface *)m_pChildList[i];
1489
1490 if ((pIfList->pInterfaces[j].dwIndex == pInterface->IfIndex()) &&
1491 (pIfList->pInterfaces[j].dwIpAddr == pInterface->IpAddr()) &&
1492 (pIfList->pInterfaces[j].dwIpNetMask == pInterface->IpNetMask()))
1493 {
1494 // Existing interface, check configuration
1495 if (memcmp(pIfList->pInterfaces[j].bMacAddr, pInterface->MacAddr(), MAC_ADDR_LENGTH))
1496 {
1497 char szOldMac[16], szNewMac[16];
1498
1499 BinToStr((BYTE *)pInterface->MacAddr(), MAC_ADDR_LENGTH, szOldMac);
1500 BinToStr(pIfList->pInterfaces[j].bMacAddr, MAC_ADDR_LENGTH, szNewMac);
1501 PostEvent(EVENT_MAC_ADDR_CHANGED, m_dwId, "idsss",
1502 pInterface->Id(), pInterface->IfIndex(),
1503 pInterface->Name(), szOldMac, szNewMac);
1504 pInterface->SetMacAddr(pIfList->pInterfaces[j].bMacAddr);
1505 }
1506 if (strcmp(pIfList->pInterfaces[j].szName, pInterface->Name()))
1507 {
1508 pInterface->SetName(pIfList->pInterfaces[j].szName);
1509 }
1510 bNewInterface = FALSE;
1511 break;
1512 }
1513 }
1514 }
1515 UnlockChildList();
1516
1517 if (bNewInterface)
1518 {
1519 // New interface
1520 SendPollerMsg(dwRqId, POLLER_INFO _T(" Found new interface \"%s\"\r\n"),
1521 pIfList->pInterfaces[j].szName);
1522 CreateNewInterface(pIfList->pInterfaces[j].dwIpAddr,
1523 pIfList->pInterfaces[j].dwIpNetMask,
1524 pIfList->pInterfaces[j].szName,
1525 pIfList->pInterfaces[j].dwIndex,
1526 pIfList->pInterfaces[j].dwType,
1527 pIfList->pInterfaces[j].bMacAddr);
1528 bHasChanges = TRUE;
1529 }
1530 }
1531
1532 // Check if address we are using to communicate with node
1533 // is configured on one of node's interfaces
1534 for(i = 0; i < (DWORD)pIfList->iNumEntries; i++)
1535 if (pIfList->pInterfaces[i].dwIpAddr == m_dwIpAddr)
1536 break;
1537
1538 if (i == (DWORD)pIfList->iNumEntries)
1539 {
1540 BOOL bCreate = TRUE;
1541
1542 // Node is behind NAT
1543 m_dwFlags |= NF_BEHIND_NAT;
1544
1545 // Check if we already have NAT interface
1546 LockChildList(FALSE);
1547 for(i = 0; i < m_dwChildCount; i++)
1548 if (m_pChildList[i]->Type() == OBJECT_INTERFACE)
1549 {
1550 if (((Interface *)m_pChildList[i])->IfType() == IFTYPE_NETXMS_NAT_ADAPTER)
1551 {
1552 bCreate = FALSE;
1553 break;
1554 }
1555 }
1556 UnlockChildList();
1557
1558 if (bCreate)
1559 {
1560 char szBuffer[MAX_OBJECT_NAME];
1561
1562 // Create pseudo interface for NAT
1563 ConfigReadStr("NATAdapterName", szBuffer, MAX_OBJECT_NAME, "NetXMS NAT Adapter");
1564 CreateNewInterface(m_dwIpAddr, 0, szBuffer,
1565 0x7FFFFFFF, IFTYPE_NETXMS_NAT_ADAPTER);
1566 bHasChanges = TRUE;
1567 }
1568 }
1569 else
1570 {
1571 // Check if NF_BEHIND_NAT flag set incorrectly
1572 if (m_dwFlags & NF_BEHIND_NAT)
1573 {
1574 Interface *pIfNat;
1575
1576 // Remove NAT interface
1577 LockChildList(FALSE);
1578 for(i = 0, pIfNat = NULL; i < m_dwChildCount; i++)
1579 if (m_pChildList[i]->Type() == OBJECT_INTERFACE)
1580 {
1581 if (((Interface *)m_pChildList[i])->IfType() == IFTYPE_NETXMS_NAT_ADAPTER)
1582 {
1583 pIfNat = (Interface *)m_pChildList[i];
1584 break;
1585 }
1586 }
1587 UnlockChildList();
1588
1589 if (pIfNat != NULL)
1590 DeleteInterface(pIfNat);
1591
1592 m_dwFlags &= ~NF_BEHIND_NAT;
1593 bHasChanges = TRUE;
1594 }
1595 }
1596
1597 CheckSubnetBinding(pIfList);
1598
1599 DestroyInterfaceList(pIfList);
1600 }
1601 else /* pIfList == NULL */
1602 {
1603 Interface *pInterface;
1604 DWORD dwCount;
1605
1606 SendPollerMsg(dwRqId, POLLER_ERROR _T("Unable to get interface list from node\r\n"));
1607
1608 // Delete all existing interfaces in case of forced capability recheck
1609 if (m_dwDynamicFlags & NDF_RECHECK_CAPABILITIES)
1610 {
1611 LockChildList(FALSE);
1612 ppDeleteList = (Interface **)malloc(sizeof(Interface *) * m_dwChildCount);
1613 for(i = 0, iDelCount = 0; i < m_dwChildCount; i++)
1614 {
1615 if (m_pChildList[i]->Type() == OBJECT_INTERFACE)
1616 ppDeleteList[iDelCount++] = (Interface *)m_pChildList[i];
1617 }
1618 UnlockChildList();
1619 for(j = 0; j < iDelCount; j++)
1620 {
1621 SendPollerMsg(dwRqId, POLLER_WARNING _T(" Interface \"%s\" is no longer exist\r\n"),
1622 ppDeleteList[j]->Name());
1623 PostEvent(EVENT_INTERFACE_DELETED, m_dwId, "dsaa", ppDeleteList[j]->IfIndex(),
1624 ppDeleteList[j]->Name(), ppDeleteList[j]->IpAddr(), ppDeleteList[j]->IpNetMask());
1625 DeleteInterface(ppDeleteList[j]);
1626 }
1627 safe_free(ppDeleteList);
1628 }
1629
1630 // Check if we have pseudo-interface object
7c521895 1631 dwCount = getInterfaceCount(&pInterface);
5039dede
AK
1632 if (dwCount == 1)
1633 {
1634 if (pInterface->IsFake())
1635 {
1636 // Check if primary IP is different from interface's IP
1637 if (pInterface->IpAddr() != m_dwIpAddr)
1638 {
1639 DeleteInterface(pInterface);
15d6f8c9
VK
1640 if (m_dwIpAddr != 0)
1641 CreateNewInterface(m_dwIpAddr, dwNetMask);
5039dede
AK
1642 }
1643 }
1644 }
1645 else if (dwCount == 0)
1646 {
1647 // No interfaces at all, create pseudo-interface
15d6f8c9
VK
1648 if (m_dwIpAddr != 0)
1649 CreateNewInterface(m_dwIpAddr, dwNetMask);
5039dede
AK
1650 }
1651 }
1652
1653 m_tLastConfigurationPoll = time(NULL);
1654 SendPollerMsg(dwRqId, _T("Interface configuration check finished\r\n"));
1655
1656 // Check node name
1657 SendPollerMsg(dwRqId, _T("Checking node name\r\n"));
1658 dwAddr = ntohl(_t_inet_addr(m_szName));
1659 if ((g_dwFlags & AF_RESOLVE_NODE_NAMES) &&
1660 (dwAddr != INADDR_NONE) &&
1661 (dwAddr != INADDR_ANY) &&
58b3e451 1662 isMyIP(dwAddr))
5039dede
AK
1663 {
1664 SendPollerMsg(dwRqId, _T("Node name is an IP address and need to be resolved\r\n"));
1665 SetPollerInfo(nPoller, "resolving name");
1666 if (ResolveName(FALSE))
1667 {
1668 SendPollerMsg(dwRqId, POLLER_INFO _T("Node name resolved to %s\r\n"), m_szName);
1669 bHasChanges = TRUE;
1670 }
1671 else
1672 {
1673 SendPollerMsg(dwRqId, POLLER_WARNING _T("Node name cannot be resolved\r\n"));
1674 }
1675 }
1676 else
1677 {
1678 if (g_dwFlags & AF_SYNC_NODE_NAMES_WITH_DNS)
1679 {
1680 SendPollerMsg(dwRqId, _T("Syncing node name with DNS\r\n"));
1681 SetPollerInfo(nPoller, "resolving name");
1682 if (ResolveName(TRUE))
1683 {
1684 SendPollerMsg(dwRqId, POLLER_INFO _T("Node name resolved to %s\r\n"), m_szName);
1685 bHasChanges = TRUE;
1686 }
1687 }
1688 else
1689 {
1690 SendPollerMsg(dwRqId, _T("Node name is OK\r\n"));
1691 }
1692 }
1693
4d0c32f3
VK
1694 // Apply templates
1695 ApplySystemTemplates();
1696 ApplyUserTemplates();
1697
7c521895 1698 updateContainerMembership();
4d0c32f3 1699
df8a4ca2
VK
1700 SendPollerMsg(dwRqId, _T("Finished configuration poll for node %s\r\n"), m_szName);
1701 SendPollerMsg(dwRqId, _T("Node configuration was%schanged after poll\r\n"), bHasChanges ? _T(" ") : _T(" not "));
e4a64da2
VK
1702
1703 m_dwDynamicFlags |= NDF_CONFIGURATION_POLL_PASSED;
4d0c32f3
VK
1704 }
1705
1706 // Finish configuration poll
1707 SetPollerInfo(nPoller, "cleanup");
1708 if (dwRqId == 0)
1709 m_dwDynamicFlags &= ~NDF_QUEUED_FOR_CONFIG_POLL;
1710 m_dwDynamicFlags &= ~NDF_RECHECK_CAPABILITIES;
7c521895 1711 pollerUnlock();
4d0c32f3
VK
1712 DbgPrintf(4, "Finished configuration poll for node %s (ID: %d)", m_szName, m_dwId);
1713
1714 if (bHasChanges)
1715 {
1716 LockData();
1717 Modify();
1718 UnlockData();
1719 }
1720}
1721
1722
1723//
1724// Apply system templates
1725//
1726
1727void Node::ApplySystemTemplates()
1728{
1729 Template *pTemplate;
1730
1731 pTemplate = FindTemplateByName(_T("@System.Agent"));
1732 if (pTemplate != NULL)
1733 {
7c521895 1734 if (isNativeAgent())
5039dede 1735 {
4d0c32f3 1736 if (!pTemplate->IsChild(m_dwId))
5039dede 1737 {
4d0c32f3
VK
1738 DbgPrintf(4, _T("Node::ApplySystemTemplates(): applying template %d \"%s\" to node %d \"%s\""),
1739 pTemplate->Id(), pTemplate->Name(), m_dwId, m_szName);
1740 pTemplate->ApplyToNode(this);
5039dede 1741 }
4d0c32f3
VK
1742 }
1743 else
1744 {
1745 if (pTemplate->IsChild(m_dwId))
5039dede 1746 {
4d0c32f3
VK
1747 DbgPrintf(4, _T("Node::ApplySystemTemplates(): removing template %d \"%s\" from node %d \"%s\""),
1748 pTemplate->Id(), pTemplate->Name(), m_dwId, m_szName);
1749 pTemplate->DeleteChild(this);
1750 DeleteParent(pTemplate);
fb05c05b 1751 pTemplate->queueRemoveFromNode(m_dwId, TRUE);
5039dede
AK
1752 }
1753 }
4d0c32f3 1754 }
5039dede 1755
4d0c32f3
VK
1756 pTemplate = FindTemplateByName(_T("@System.SNMP"));
1757 if (pTemplate != NULL)
1758 {
7c521895 1759 if (isSNMPSupported())
4d0c32f3
VK
1760 {
1761 if (!pTemplate->IsChild(m_dwId))
1762 {
1763 DbgPrintf(4, _T("Node::ApplySystemTemplates(): applying template %d \"%s\" to node %d \"%s\""),
1764 pTemplate->Id(), pTemplate->Name(), m_dwId, m_szName);
1765 pTemplate->ApplyToNode(this);
1766 }
1767 }
1768 else
5039dede 1769 {
4d0c32f3
VK
1770 if (pTemplate->IsChild(m_dwId))
1771 {
1772 DbgPrintf(4, _T("Node::ApplySystemTemplates(): removing template %d \"%s\" from node %d \"%s\""),
1773 pTemplate->Id(), pTemplate->Name(), m_dwId, m_szName);
1774 pTemplate->DeleteChild(this);
1775 DeleteParent(pTemplate);
fb05c05b 1776 pTemplate->queueRemoveFromNode(m_dwId, TRUE);
4d0c32f3
VK
1777 }
1778 }
1779 }
1780}
1781
1782
1783//
1784// Apply user templates
1785//
1786
1787void Node::ApplyUserTemplates()
1788{
1789 DWORD i;
1790 Template *pTemplate;
1791
1792 if (g_pIndexById == NULL)
1793 return;
1794
1795 RWLockReadLock(g_rwlockIdIndex, INFINITE);
1796 for(i = 0; i < g_dwIdIndexSize; i++)
1797 {
1798 if ((((NetObj *)g_pIndexById[i].pObject)->Type() == OBJECT_TEMPLATE) &&
1799 (!((NetObj *)g_pIndexById[i].pObject)->IsDeleted()))
1800 {
1801 pTemplate = (Template *)g_pIndexById[i].pObject;
fb05c05b 1802 if (pTemplate->isApplicable(this))
5039dede
AK
1803 {
1804 if (!pTemplate->IsChild(m_dwId))
1805 {
4d0c32f3
VK
1806 DbgPrintf(4, _T("Node::ApplyUserTemplates(): applying template %d \"%s\" to node %d \"%s\""),
1807 pTemplate->Id(), pTemplate->Name(), m_dwId, m_szName);
5039dede
AK
1808 pTemplate->ApplyToNode(this);
1809 }
1810 }
1811 else
1812 {
fb05c05b 1813 if (pTemplate->isAutoApplyEnabled() && pTemplate->IsChild(m_dwId))
5039dede 1814 {
4d0c32f3
VK
1815 DbgPrintf(4, _T("Node::ApplyUserTemplates(): removing template %d \"%s\" from node %d \"%s\""),
1816 pTemplate->Id(), pTemplate->Name(), m_dwId, m_szName);
5039dede
AK
1817 pTemplate->DeleteChild(this);
1818 DeleteParent(pTemplate);
fb05c05b 1819 pTemplate->queueRemoveFromNode(m_dwId, TRUE);
5039dede
AK
1820 }
1821 }
4d0c32f3 1822 }
5039dede 1823 }
4d0c32f3
VK
1824 RWLockUnlock(g_rwlockIdIndex);
1825}
5039dede 1826
5039dede 1827
4d0c32f3
VK
1828//
1829// Update container membership
1830//
1831
7c521895 1832void Node::updateContainerMembership()
4d0c32f3
VK
1833{
1834 DWORD i;
1835 Container *pContainer;
1836
1837 if (g_pIndexById == NULL)
1838 return;
1839
1840 RWLockReadLock(g_rwlockIdIndex, INFINITE);
1841 for(i = 0; i < g_dwIdIndexSize; i++)
5039dede 1842 {
4d0c32f3
VK
1843 if ((((NetObj *)g_pIndexById[i].pObject)->Type() == OBJECT_CONTAINER) &&
1844 (!((NetObj *)g_pIndexById[i].pObject)->IsDeleted()))
1845 {
1846 pContainer = (Container *)g_pIndexById[i].pObject;
1847 if (pContainer->IsSuitableForNode(this))
1848 {
1849 if (!pContainer->IsChild(m_dwId))
1850 {
1851 DbgPrintf(4, _T("Node::UpdateContainerMembership(): binding node %d \"%s\" to container %d \"%s\""),
1852 m_dwId, m_szName, pContainer->Id(), pContainer->Name());
1853 pContainer->AddChild(this);
1854 AddParent(pContainer);
1855 }
1856 }
1857 else
1858 {
1859 if (pContainer->IsAutoBindEnabled() && pContainer->IsChild(m_dwId))
1860 {
1861 DbgPrintf(4, _T("Node::UpdateContainerMembership(): removing node %d \"%s\" from container %d \"%s\""),
1862 m_dwId, m_szName, pContainer->Id(), pContainer->Name());
1863 pContainer->DeleteChild(this);
1864 DeleteParent(pContainer);
1865 }
1866 }
1867 }
5039dede 1868 }
4d0c32f3 1869 RWLockUnlock(g_rwlockIdIndex);
5039dede
AK
1870}
1871
1872
1873//
1874// Connect to native agent
1875//
1876
7c521895 1877BOOL Node::connectToAgent()
5039dede
AK
1878{
1879 BOOL bRet;
1880
1881 // Create new agent connection object if needed
1882 if (m_pAgentConnection == NULL)
1883 m_pAgentConnection = new AgentConnectionEx(htonl(m_dwIpAddr), m_wAgentPort, m_wAuthMethod, m_szSharedSecret);
1884
1885 // Check if we already connected
45d84f8a 1886 if (m_pAgentConnection->nop() == ERR_SUCCESS)
5039dede
AK
1887 return TRUE;
1888
1889 // Close current connection or clean up after broken connection
7c521895
VK
1890 m_pAgentConnection->disconnect();
1891 m_pAgentConnection->setPort(m_wAgentPort);
1892 m_pAgentConnection->setAuthData(m_wAuthMethod, m_szSharedSecret);
1893 setAgentProxy(m_pAgentConnection);
1894 bRet = m_pAgentConnection->connect(g_pServerKey);
5039dede
AK
1895 if (bRet)
1896 {
45d84f8a
VK
1897 m_pAgentConnection->setCommandTimeout(g_dwAgentCommandTimeout);
1898 m_pAgentConnection->enableTraps();
5039dede
AK
1899 }
1900 return bRet;
1901}
1902
1903
1904//
1905// Get item's value via SNMP
1906//
1907
65e2005b 1908DWORD Node::GetItemFromSNMP(WORD port, const char *szParam, DWORD dwBufSize, char *szBuffer)
5039dede
AK
1909{
1910 DWORD dwResult;
1911
1912 if ((m_dwDynamicFlags & NDF_SNMP_UNREACHABLE) ||
6b2bb22c
VK
1913 (m_dwDynamicFlags & NDF_UNREACHABLE) ||
1914 (m_dwFlags & NF_DISABLE_SNMP))
5039dede
AK
1915 {
1916 dwResult = SNMP_ERR_COMM;
1917 }
1918 else
1919 {
1920 SNMP_Transport *pTransport;
1921
65e2005b 1922 pTransport = createSnmpTransport(port);
803d47be
VK
1923 if (pTransport != NULL)
1924 {
1925 dwResult = SnmpGet(m_snmpVersion, pTransport,
1926 szParam, NULL, 0, szBuffer, dwBufSize, FALSE, TRUE);
1927 delete pTransport;
1928 }
1929 else
1930 {
1931 dwResult = SNMP_ERR_COMM;
1932 }
5039dede 1933 }
61b48d2f 1934 DbgPrintf(7, "Node(%s)->GetItemFromSNMP(%s): dwResult=%d", m_szName, szParam, dwResult);
5039dede
AK
1935 return (dwResult == SNMP_ERR_SUCCESS) ? DCE_SUCCESS :
1936 ((dwResult == SNMP_ERR_NO_OBJECT) ? DCE_NOT_SUPPORTED : DCE_COMM_ERROR);
1937}
1938
1939
1940//
1941// Get item's value via SNMP from CheckPoint's agent
1942//
1943
1944DWORD Node::GetItemFromCheckPointSNMP(const char *szParam, DWORD dwBufSize, char *szBuffer)
1945{
1946 DWORD dwResult;
1947
1948 if ((m_dwDynamicFlags & NDF_CPSNMP_UNREACHABLE) ||
1949 (m_dwDynamicFlags & NDF_UNREACHABLE))
1950 {
1951 dwResult = SNMP_ERR_COMM;
1952 }
1953 else
1954 {
1955 SNMP_Transport *pTransport;
1956
1957 pTransport = new SNMP_UDPTransport;
c4366266 1958 ((SNMP_UDPTransport *)pTransport)->createUDPTransport(NULL, htonl(m_dwIpAddr), CHECKPOINT_SNMP_PORT);
5039dede 1959 dwResult = SnmpGet(SNMP_VERSION_1, pTransport,
5d2c5741 1960 szParam, NULL, 0, szBuffer,
5039dede
AK
1961 dwBufSize, FALSE, TRUE);
1962 delete pTransport;
1963 }
61b48d2f 1964 DbgPrintf(7, "Node(%s)->GetItemFromCheckPointSNMP(%s): dwResult=%d", m_szName, szParam, dwResult);
5039dede
AK
1965 return (dwResult == SNMP_ERR_SUCCESS) ? DCE_SUCCESS :
1966 ((dwResult == SNMP_ERR_NO_OBJECT) ? DCE_NOT_SUPPORTED : DCE_COMM_ERROR);
1967}
1968
1969
1970//
1971// Get item's value via native agent
1972//
1973
1974DWORD Node::GetItemFromAgent(const char *szParam, DWORD dwBufSize, char *szBuffer)
1975{
912b994d 1976 DWORD dwError = ERR_NOT_CONNECTED, dwResult = DCE_COMM_ERROR;
5039dede
AK
1977 DWORD dwTries = 3;
1978
1979 if ((m_dwDynamicFlags & NDF_AGENT_UNREACHABLE) ||
1980 (m_dwDynamicFlags & NDF_UNREACHABLE))
1981 return DCE_COMM_ERROR;
1982
7c521895 1983 agentLock();
5039dede
AK
1984
1985 // Establish connection if needed
1986 if (m_pAgentConnection == NULL)
7c521895 1987 if (!connectToAgent())
5039dede
AK
1988 goto end_loop;
1989
1990 // Get parameter from agent
1991 while(dwTries-- > 0)
1992 {
1993 dwError = m_pAgentConnection->GetParameter((char *)szParam, dwBufSize, szBuffer);
1994 switch(dwError)
1995 {
1996 case ERR_SUCCESS:
1997 dwResult = DCE_SUCCESS;
1998 goto end_loop;
1999 case ERR_UNKNOWN_PARAMETER:
2000 dwResult = DCE_NOT_SUPPORTED;
2001 goto end_loop;
2002 case ERR_NOT_CONNECTED:
2003 case ERR_CONNECTION_BROKEN:
7c521895 2004 if (!connectToAgent())
5039dede
AK
2005 goto end_loop;
2006 break;
2007 case ERR_REQUEST_TIMEOUT:
2008 // Reset connection to agent after timeout
2009 DbgPrintf(7, _T("Node(%s)->GetItemFromAgent(%s): timeout; resetting connection to agent..."), m_szName, szParam);
2010 delete_and_null(m_pAgentConnection);
7c521895 2011 if (!connectToAgent())
5039dede
AK
2012 goto end_loop;
2013 DbgPrintf(7, _T("Node(%s)->GetItemFromAgent(%s): connection to agent restored successfully"), m_szName, szParam);
2014 break;
2015 }
2016 }
2017
2018end_loop:
7c521895 2019 agentUnlock();
5039dede
AK
2020 DbgPrintf(7, "Node(%s)->GetItemFromAgent(%s): dwError=%d dwResult=%d",
2021 m_szName, szParam, dwError, dwResult);
2022 return dwResult;
2023}
2024
2025
2026//
2027// Get value for server's internal parameter
2028//
2029
2030DWORD Node::GetInternalItem(const char *szParam, DWORD dwBufSize, char *szBuffer)
2031{
2032 DWORD dwError = DCE_SUCCESS;
2033
2034 if (!stricmp(szParam, "Status"))
2035 {
2036 sprintf(szBuffer, "%d", m_iStatus);
2037 }
2038 else if (!stricmp(szParam, "Dummy"))
2039 {
2040 _tcscpy(szBuffer, _T("0"));
2041 }
2042 else if (!stricmp(szParam, "AgentStatus"))
2043 {
2044 if (m_dwFlags & NF_IS_NATIVE_AGENT)
2045 {
2046 szBuffer[0] = (m_dwDynamicFlags & NDF_AGENT_UNREACHABLE) ? '1' : '0';
2047 szBuffer[1] = 0;
2048 }
2049 else
2050 {
2051 dwError = DCE_NOT_SUPPORTED;
2052 }
2053 }
2054 else if (MatchString("ChildStatus(*)", szParam, FALSE))
2055 {
2056 char *pEnd, szArg[256];
2057 DWORD i, dwId;
2058 NetObj *pObject = NULL;
2059
6173bea8 2060 AgentGetParameterArg((char *)szParam, 1, szArg, 256);
5039dede
AK
2061 dwId = strtoul(szArg, &pEnd, 0);
2062 if (*pEnd != 0)
2063 {
2064 // Argument is object's name
2065 dwId = 0;
2066 }
2067
2068 // Find child object with requested ID or name
2069 LockChildList(FALSE);
2070 for(i = 0; i < m_dwChildCount; i++)
2071 {
2072 if (((dwId == 0) && (!stricmp(m_pChildList[i]->Name(), szArg))) ||
2073 (dwId == m_pChildList[i]->Id()))
2074 {
2075 pObject = m_pChildList[i];
2076 break;
2077 }
2078 }
2079 UnlockChildList();
2080
2081 if (pObject != NULL)
2082 {
2083 sprintf(szBuffer, "%d", pObject->Status());
2084 }
2085 else
2086 {
2087 dwError = DCE_NOT_SUPPORTED;
2088 }
2089 }
2090 else if (MatchString("ConditionStatus(*)", szParam, FALSE))
2091 {
2092 char *pEnd, szArg[256];
2093 DWORD dwId;
2094 NetObj *pObject = NULL;
2095
6173bea8 2096 AgentGetParameterArg((char *)szParam, 1, szArg, 256);
5039dede
AK
2097 dwId = strtoul(szArg, &pEnd, 0);
2098 if (*pEnd == 0)
2099 {
2100 pObject = FindObjectById(dwId);
2101 if (pObject != NULL)
2102 if (pObject->Type() != OBJECT_CONDITION)
2103 pObject = NULL;
2104 }
2105 else
2106 {
2107 // Argument is object's name
2108 pObject = FindObjectByName(szArg, OBJECT_CONDITION);
2109 }
2110
2111 if (pObject != NULL)
2112 {
2113 if (pObject->IsTrustedNode(m_dwId))
2114 {
2115 sprintf(szBuffer, "%d", pObject->Status());
2116 }
2117 else
2118 {
2119 dwError = DCE_NOT_SUPPORTED;
2120 }
2121 }
2122 else
2123 {
2124 dwError = DCE_NOT_SUPPORTED;
2125 }
2126 }
2127 else if (m_dwFlags & NF_IS_LOCAL_MGMT)
2128 {
2129 if (!stricmp(szParam, "Server.AverageDCPollerQueueSize"))
2130 {
2131 sprintf(szBuffer, "%f", g_dAvgPollerQueueSize);
2132 }
2133 else if (!stricmp(szParam, "Server.AverageDBWriterQueueSize"))
2134 {
2135 sprintf(szBuffer, "%f", g_dAvgDBWriterQueueSize);
2136 }
2137 else if (!stricmp(szParam, "Server.AverageStatusPollerQueueSize"))
2138 {
2139 sprintf(szBuffer, "%f", g_dAvgStatusPollerQueueSize);
2140 }
2141 else if (!stricmp(szParam, "Server.AverageConfigurationPollerQueueSize"))
2142 {
2143 sprintf(szBuffer, "%f", g_dAvgConfigPollerQueueSize);
2144 }
2145 else if (!stricmp(szParam, "Server.AverageDCIQueuingTime"))
2146 {
2147 sprintf(szBuffer, "%u", g_dwAvgDCIQueuingTime);
2148 }
2149 else if (!stricmp(szParam, "Server.TotalEventsProcessed"))
2150 {
2151 sprintf(szBuffer, INT64_FMT, g_totalEventsProcessed);
2152 }
2153 else
2154 {
2155 dwError = DCE_NOT_SUPPORTED;
2156 }
2157 }
2158 else
2159 {
2160 dwError = DCE_NOT_SUPPORTED;
2161 }
2162
2163 return dwError;
2164}
2165
2166
2167//
2168// Get item's value for client
2169//
2170
2171DWORD Node::GetItemForClient(int iOrigin, const char *pszParam, char *pszBuffer, DWORD dwBufSize)
2172{
2173 DWORD dwResult = 0, dwRetCode;
2174
2175 // Get data from node
2176 switch(iOrigin)
2177 {
2178 case DS_INTERNAL:
2179 dwRetCode = GetInternalItem(pszParam, dwBufSize, pszBuffer);
2180 break;
2181 case DS_NATIVE_AGENT:
2182 dwRetCode = GetItemFromAgent(pszParam, dwBufSize, pszBuffer);
2183 break;
2184 case DS_SNMP_AGENT:
65e2005b 2185 dwRetCode = GetItemFromSNMP(0, pszParam, dwBufSize, pszBuffer);
5039dede
AK
2186 break;
2187 case DS_CHECKPOINT_AGENT:
2188 dwRetCode = GetItemFromCheckPointSNMP(pszParam, dwBufSize, pszBuffer);
2189 break;
2190 default:
2191 dwResult = RCC_INVALID_ARGUMENT;
2192 break;
2193 }
2194
2195 // Translate return code to RCC
2196 if (dwResult != RCC_INVALID_ARGUMENT)
2197 {
2198 switch(dwRetCode)
2199 {
2200 case DCE_SUCCESS:
2201 dwResult = RCC_SUCCESS;
2202 break;
2203 case DCE_COMM_ERROR:
2204 dwResult = RCC_COMM_FAILURE;
2205 break;
2206 case DCE_NOT_SUPPORTED:
2207 dwResult = RCC_DCI_NOT_SUPPORTED;
2208 break;
2209 default:
2210 dwResult = RCC_SYSTEM_FAILURE;
2211 break;
2212 }
2213 }
2214
2215 return dwResult;
2216}
2217
2218
2219//
2220// Put items which requires polling into the queue
2221//
2222
7c521895 2223void Node::queueItemsForPolling(Queue *pPollerQueue)
5039dede
AK
2224{
2225 DWORD i;
2226 time_t currTime;
2227
2228 if ((m_iStatus == STATUS_UNMANAGED) ||
2229 (m_dwFlags & NF_DISABLE_DATA_COLLECT) ||
2230 (m_bIsDeleted))
2231 return; // Do not collect data for unmanaged nodes or if data collection is disabled
2232
2233 currTime = time(NULL);
2234
7c521895 2235 lockDciAccess();
5039dede
AK
2236 for(i = 0; i < m_dwNumItems; i++)
2237 {
fb05c05b 2238 if (m_ppItems[i]->isReadyForPolling(currTime))
5039dede 2239 {
fb05c05b 2240 m_ppItems[i]->setBusyFlag(TRUE);
5039dede
AK
2241 IncRefCount(); // Increment reference count for each queued DCI
2242 pPollerQueue->Put(m_ppItems[i]);
61b48d2f 2243 DbgPrintf(8, _T("Node(%s)->QueueItemsForPolling(): item %d \"%s\" added to queue"), m_szName, m_ppItems[i]->getId(), m_ppItems[i]->getName());
5039dede
AK
2244 }
2245 }
7c521895 2246 unlockDciAccess();
5039dede
AK
2247}
2248
2249
2250//
2251// Create CSCP message with object's data
2252//
2253
2254void Node::CreateMessage(CSCPMessage *pMsg)
2255{
2256 Template::CreateMessage(pMsg);
2257 pMsg->SetVariable(VID_FLAGS, m_dwFlags);
fa6173b9 2258 pMsg->SetVariable(VID_RUNTIME_FLAGS, m_dwDynamicFlags);
5039dede
AK
2259 pMsg->SetVariable(VID_AGENT_PORT, m_wAgentPort);
2260 pMsg->SetVariable(VID_AUTH_METHOD, m_wAuthMethod);
2261 pMsg->SetVariable(VID_SHARED_SECRET, m_szSharedSecret);
4b7d8903
VK
2262 pMsg->SetVariable(VID_SNMP_AUTH_OBJECT, m_snmpSecurity->getCommunity());
2263 pMsg->SetVariable(VID_SNMP_AUTH_PASSWORD, m_snmpSecurity->getAuthPassword());
2264 pMsg->SetVariable(VID_SNMP_PRIV_PASSWORD, m_snmpSecurity->getPrivPassword());
2265 pMsg->SetVariable(VID_SNMP_USM_METHODS, (WORD)((WORD)m_snmpSecurity->getAuthMethod() | ((WORD)m_snmpSecurity->getPrivMethod() << 8)));
5039dede 2266 pMsg->SetVariable(VID_SNMP_OID, m_szObjectId);
65e2005b 2267 pMsg->SetVariable(VID_SNMP_PORT, m_wSNMPPort);
5039dede 2268 pMsg->SetVariable(VID_NODE_TYPE, m_dwNodeType);
5d2c5741 2269 pMsg->SetVariable(VID_SNMP_VERSION, (WORD)m_snmpVersion);
5039dede
AK
2270 pMsg->SetVariable(VID_AGENT_VERSION, m_szAgentVersion);
2271 pMsg->SetVariable(VID_PLATFORM_NAME, m_szPlatformName);
2272 pMsg->SetVariable(VID_POLLER_NODE_ID, m_dwPollerNode);
2273 pMsg->SetVariable(VID_ZONE_GUID, m_dwZoneGUID);
2274 pMsg->SetVariable(VID_PROXY_NODE, m_dwProxyNode);
2275 pMsg->SetVariable(VID_SNMP_PROXY, m_dwSNMPProxy);
2276 pMsg->SetVariable(VID_REQUIRED_POLLS, (WORD)m_iRequiredPollCount);
2277 pMsg->SetVariable(VID_SYS_DESCRIPTION, m_szSysDescription);
2278 pMsg->SetVariable(VID_USE_IFXTABLE, (WORD)m_nUseIfXTable);
2279}
2280
2281
2282//
2283// Modify object from message
2284//
2285
2286DWORD Node::ModifyFromMessage(CSCPMessage *pRequest, BOOL bAlreadyLocked)
2287{
5d2c5741
VK
2288 TCHAR buffer[256];
2289
5039dede
AK
2290 if (!bAlreadyLocked)
2291 LockData();
2292
2293 // Change primary IP address
2294 if (pRequest->IsVariableExist(VID_IP_ADDRESS))
2295 {
2296 DWORD i, dwIpAddr;
2297
2298 dwIpAddr = pRequest->GetVariableLong(VID_IP_ADDRESS);
2299
2300 // Check if received IP address is one of node's interface addresses
2301 LockChildList(FALSE);
2302 for(i = 0; i < m_dwChildCount; i++)
2303 if ((m_pChildList[i]->Type() == OBJECT_INTERFACE) &&
2304 (m_pChildList[i]->IpAddr() == dwIpAddr))
2305 break;
2306 UnlockChildList();
2307 if (i == m_dwChildCount)
2308 {
2309 UnlockData();
2310 return RCC_INVALID_IP_ADDR;
2311 }
2312
2313 UpdateNodeIndex(m_dwIpAddr, dwIpAddr, this);
2314 m_dwIpAddr = dwIpAddr;
2315 }
2316
2317 // Poller node ID
2318 if (pRequest->IsVariableExist(VID_POLLER_NODE_ID))
2319 {
2320 DWORD dwNodeId;
2321 NetObj *pObject;
2322
2323 dwNodeId = pRequest->GetVariableLong(VID_POLLER_NODE_ID);
2324 pObject = FindObjectById(dwNodeId);
2325
2326 // Check if received id is a valid node id
2327 if (pObject == NULL)
2328 {
2329 UnlockData();
2330 return RCC_INVALID_OBJECT_ID;
2331 }
2332 if (pObject->Type() != OBJECT_NODE)
2333 {
2334 UnlockData();
2335 return RCC_INVALID_OBJECT_ID;
2336 }
2337
2338 m_dwPollerNode = dwNodeId;
2339 }
2340
2341 // Change listen port of native agent
2342 if (pRequest->IsVariableExist(VID_AGENT_PORT))
2343 m_wAgentPort = pRequest->GetVariableShort(VID_AGENT_PORT);
2344
2345 // Change authentication method of native agent
2346 if (pRequest->IsVariableExist(VID_AUTH_METHOD))
2347 m_wAuthMethod = pRequest->GetVariableShort(VID_AUTH_METHOD);
2348
2349 // Change shared secret of native agent
2350 if (pRequest->IsVariableExist(VID_SHARED_SECRET))
2351 pRequest->GetVariableStr(VID_SHARED_SECRET, m_szSharedSecret, MAX_SECRET_LENGTH);
2352
2353 // Change SNMP protocol version
2354 if (pRequest->IsVariableExist(VID_SNMP_VERSION))
14b98b3a 2355 {
5d2c5741 2356 m_snmpVersion = pRequest->GetVariableShort(VID_SNMP_VERSION);
14b98b3a
VK
2357 m_snmpSecurity->setSecurityModel((m_snmpVersion == SNMP_VERSION_3) ? SNMP_SECURITY_MODEL_USM : SNMP_SECURITY_MODEL_V2C);
2358 }
5039dede 2359
65e2005b
VK
2360 // Change SNMP port
2361 if (pRequest->IsVariableExist(VID_SNMP_PORT))
2362 m_wSNMPPort = pRequest->GetVariableShort(VID_SNMP_PORT);
2363
4b7d8903
VK
2364 // Change SNMP authentication data
2365 if (pRequest->IsVariableExist(VID_SNMP_AUTH_OBJECT))
5d2c5741 2366 {
4b7d8903
VK
2367 pRequest->GetVariableStr(VID_SNMP_AUTH_OBJECT, buffer, 256);
2368 m_snmpSecurity->setAuthName(buffer);
2369
2370 pRequest->GetVariableStr(VID_SNMP_AUTH_PASSWORD, buffer, 256);
2371 m_snmpSecurity->setAuthPassword(buffer);
2372
2373 pRequest->GetVariableStr(VID_SNMP_PRIV_PASSWORD, buffer, 256);
2374 m_snmpSecurity->setPrivPassword(buffer);
2375
2376 WORD methods = pRequest->GetVariableShort(VID_SNMP_USM_METHODS);
2377 m_snmpSecurity->setAuthMethod((int)(methods & 0xFF));
2378 m_snmpSecurity->setPrivMethod((int)(methods >> 8));
5d2c5741 2379 }
5039dede
AK
2380
2381 // Change proxy node
2382 if (pRequest->IsVariableExist(VID_PROXY_NODE))
2383 m_dwProxyNode = pRequest->GetVariableLong(VID_PROXY_NODE);
2384
2385 // Change SNMP proxy node
2386 if (pRequest->IsVariableExist(VID_SNMP_PROXY))
2387 m_dwSNMPProxy = pRequest->GetVariableLong(VID_SNMP_PROXY);
2388
2389 // Number of required polls
2390 if (pRequest->IsVariableExist(VID_REQUIRED_POLLS))
2391 m_iRequiredPollCount = (int)pRequest->GetVariableShort(VID_REQUIRED_POLLS);
2392
2393 // Enable/disable usage of ifXTable
2394 if (pRequest->IsVariableExist(VID_USE_IFXTABLE))
2395 m_nUseIfXTable = (BYTE)pRequest->GetVariableShort(VID_USE_IFXTABLE);
2396
2397 // Change flags
2398 if (pRequest->IsVariableExist(VID_FLAGS))
2399 {
2400 m_dwFlags &= NF_SYSTEM_FLAGS;
2401 m_dwFlags |= pRequest->GetVariableLong(VID_FLAGS) & NF_USER_FLAGS;
2402 }
2403
2404 return Template::ModifyFromMessage(pRequest, TRUE);
2405}
2406
2407
2408//
2409// Wakeup node using magic packet
2410//
2411
7c521895 2412DWORD Node::wakeUp()
5039dede
AK
2413{
2414 DWORD i, dwResult = RCC_NO_WOL_INTERFACES;
2415
2416 LockChildList(FALSE);
2417
2418 for(i = 0; i < m_dwChildCount; i++)
2419 if ((m_pChildList[i]->Type() == OBJECT_INTERFACE) &&
2420 (m_pChildList[i]->Status() != STATUS_UNMANAGED) &&
2421 (m_pChildList[i]->IpAddr() != 0))
2422 {
7c521895 2423 dwResult = ((Interface *)m_pChildList[i])->wakeUp();
5039dede
AK
2424 break;
2425 }
2426
2427 UnlockChildList();
2428 return dwResult;
2429}
2430
2431
2432//
2433// Get status of interface with given index from SNMP agent
2434//
2435
58b3e451 2436int Node::getInterfaceStatusFromSNMP(SNMP_Transport *pTransport, DWORD dwIndex)
5039dede 2437{
5d2c5741 2438 return SnmpGetInterfaceStatus(m_snmpVersion, pTransport, dwIndex);
5039dede
AK
2439}
2440
2441
2442//
2443// Get status of interface with given index from native agent
2444//
2445
58b3e451 2446int Node::getInterfaceStatusFromAgent(DWORD dwIndex)
5039dede
AK
2447{
2448 char szParam[128], szBuffer[32];
2449 DWORD dwAdminStatus, dwLinkState;
2450 int iStatus;
2451
2452 // Get administrative status
2453 sprintf(szParam, "Net.Interface.AdminStatus(%u)", dwIndex);
2454 if (GetItemFromAgent(szParam, 32, szBuffer) == DCE_SUCCESS)
2455 {
2456 dwAdminStatus = strtoul(szBuffer, NULL, 0);
2457
2458 switch(dwAdminStatus)
2459 {
2460 case 3:
2461 iStatus = STATUS_TESTING;
2462 break;
2463 case 2:
2464 case 0: // Agents before 0.2.1 may return 0 instead of 2
2465 iStatus = STATUS_DISABLED;
2466 break;
2467 case 1: // Interface administratively up, check link state
2468 sprintf(szParam, "Net.Interface.Link(%u)", dwIndex);
2469 if (GetItemFromAgent(szParam, 32, szBuffer) == DCE_SUCCESS)
2470 {
2471 dwLinkState = strtoul(szBuffer, NULL, 0);
2472 iStatus = (dwLinkState == 0) ? STATUS_CRITICAL : STATUS_NORMAL;
2473 }
2474 else
2475 {
2476 iStatus = STATUS_UNKNOWN;
2477 }
2478 break;
2479 default:
2480 iStatus = STATUS_UNKNOWN;
2481 break;
2482 }
2483 }
2484 else
2485 {
2486 iStatus = STATUS_UNKNOWN;
2487 }
2488
2489 return iStatus;
2490}
2491
2492
2493//
2494// Put list of supported parameters into CSCP message
2495//
2496
2497void Node::WriteParamListToMessage(CSCPMessage *pMsg)
2498{
2499 DWORD i, dwId;
2500
2501 LockData();
2502 if (m_pParamList != NULL)
2503 {
2504 pMsg->SetVariable(VID_NUM_PARAMETERS, m_dwNumParams);
2505 for(i = 0, dwId = VID_PARAM_LIST_BASE; i < m_dwNumParams; i++)
2506 {
2507 pMsg->SetVariable(dwId++, m_pParamList[i].szName);
2508 pMsg->SetVariable(dwId++, m_pParamList[i].szDescription);
2509 pMsg->SetVariable(dwId++, (WORD)m_pParamList[i].iDataType);
2510 }
2511 DbgPrintf(6, _T("Node[%s]::WriteParamListToMessage(): sending %d parameters"), m_szName, m_dwNumParams);
2512 }
2513 else
2514 {
2515 DbgPrintf(6, _T("Node[%s]::WriteParamListToMessage(): m_pParamList == NULL"), m_szName);
2516 pMsg->SetVariable(VID_NUM_PARAMETERS, (DWORD)0);
2517 }
2518 UnlockData();
2519}
2520
2521
2522//
2523// Open list of supported parameters for reading
2524//
2525
2526void Node::OpenParamList(DWORD *pdwNumParams, NXC_AGENT_PARAM **ppParamList)
2527{
2528 LockData();
2529 *pdwNumParams = m_dwNumParams;
2530 *ppParamList = m_pParamList;
2531}
2532
2533
2534//
2535// Check status of network service
2536//
2537
2538DWORD Node::CheckNetworkService(DWORD *pdwStatus, DWORD dwIpAddr, int iServiceType,
2539 WORD wPort, WORD wProto, TCHAR *pszRequest,
2540 TCHAR *pszResponse)
2541{
2542 DWORD dwError = ERR_NOT_CONNECTED;
2543
2544 if ((m_dwFlags & NF_IS_NATIVE_AGENT) &&
2545 (!(m_dwDynamicFlags & NDF_AGENT_UNREACHABLE)) &&
2546 (!(m_dwDynamicFlags & NDF_UNREACHABLE)))
2547 {
2548 AgentConnection *pConn;
2549
cd9f247e 2550 pConn = createAgentConnection();
5039dede
AK
2551 if (pConn != NULL)
2552 {
2553 dwError = pConn->CheckNetworkService(pdwStatus, dwIpAddr, iServiceType,
2554 wPort, wProto, pszRequest, pszResponse);
7c521895 2555 pConn->disconnect();
5039dede
AK
2556 delete pConn;
2557 }
2558 }
2559 return dwError;
2560}
2561
2562
2563//
2564// Handler for object deletion
2565//
2566
2567void Node::OnObjectDelete(DWORD dwObjectId)
2568{
f5d16551 2569 LockData();
5039dede
AK
2570 if (dwObjectId == m_dwPollerNode)
2571 {
2572 // If deleted object is our poller node, change it to default
5039dede
AK
2573 m_dwPollerNode = 0;
2574 Modify();
2575 DbgPrintf(3, _T("Node \"%s\": poller node %d deleted"), m_szName, dwObjectId);
2576 }
f5d16551 2577 UnlockData();
5039dede
AK
2578}
2579
2580
2581//
2582// Check node for OSPF support
2583//
2584
2585void Node::CheckOSPFSupport(SNMP_Transport *pTransport)
2586{
2587 LONG nAdminStatus;
2588
5d2c5741 2589 if (SnmpGet(m_snmpVersion, pTransport,
5039dede
AK
2590 ".1.3.6.1.2.1.14.1.2.0", NULL, 0, &nAdminStatus, sizeof(LONG),
2591 FALSE, FALSE) == SNMP_ERR_SUCCESS)
2592 {
2593 LockData();
2594 if (nAdminStatus)
2595 {
2596 m_dwFlags |= NF_IS_OSPF;
2597 }
2598 else
2599 {
2600 m_dwFlags &= ~NF_IS_OSPF;
2601 }
2602 UnlockData();
2603 }
2604}
2605
2606
2607//
2608// Create ready to use agent connection
2609//
2610
cd9f247e 2611AgentConnectionEx *Node::createAgentConnection()
5039dede 2612{
45d84f8a 2613 AgentConnectionEx *conn;
5039dede
AK
2614
2615 if ((!(m_dwFlags & NF_IS_NATIVE_AGENT)) ||
6b2bb22c 2616 (m_dwFlags & NF_DISABLE_NXCP) ||
5039dede
AK
2617 (m_dwDynamicFlags & NDF_AGENT_UNREACHABLE) ||
2618 (m_dwDynamicFlags & NDF_UNREACHABLE))
2619 return NULL;
2620
45d84f8a
VK
2621 conn = new AgentConnectionEx(htonl(m_dwIpAddr), m_wAgentPort,
2622 m_wAuthMethod, m_szSharedSecret);
7c521895
VK
2623 setAgentProxy(conn);
2624 if (!conn->connect(g_pServerKey))
5039dede 2625 {
45d84f8a
VK
2626 delete conn;
2627 conn = NULL;
5039dede 2628 }
45d84f8a 2629 return conn;
5039dede
AK
2630}
2631
2632
2633//
2634// Get last collected values of all DCIs
2635//
2636
7c521895 2637DWORD Node::getLastValues(CSCPMessage *pMsg)
5039dede
AK
2638{
2639 DWORD i, dwId, dwCount;
2640
7c521895 2641 lockDciAccess();
5039dede
AK
2642
2643 for(i = 0, dwId = VID_DCI_VALUES_BASE, dwCount = 0; i < m_dwNumItems; i++)
2644 {
fb05c05b 2645 if (_tcsnicmp(m_ppItems[i]->getDescription(), _T("@system."), 8))
5039dede 2646 {
fb05c05b 2647 m_ppItems[i]->getLastValue(pMsg, dwId);
5039dede
AK
2648 dwId += 10;
2649 dwCount++;
2650 }
2651 }
2652 pMsg->SetVariable(VID_NUM_ITEMS, dwCount);
2653
7c521895 2654 unlockDciAccess();
5039dede
AK
2655 return RCC_SUCCESS;
2656}
2657
2658
2659//
2660// Clean expired DCI data
2661//
2662
7c521895 2663void Node::cleanDCIData()
5039dede
AK
2664{
2665 DWORD i;
2666
7c521895 2667 lockDciAccess();
5039dede 2668 for(i = 0; i < m_dwNumItems; i++)
fb05c05b 2669 m_ppItems[i]->deleteExpiredData();
7c521895 2670 unlockDciAccess();
5039dede
AK
2671}
2672
2673
2674//
2675// Apply DCI from template
2676// pItem passed to this method should be a template's DCI
2677//
2678
a2069340 2679BOOL Node::applyTemplateItem(DWORD dwTemplateId, DCItem *pItem)
5039dede
AK
2680{
2681 BOOL bResult = TRUE;
2682 DWORD i;
2683 DCItem *pNewItem;
2684
a2069340 2685 lockDciAccess(); // write lock
5039dede 2686
fb05c05b 2687 DbgPrintf(5, "Applying item \"%s\" to node \"%s\"", pItem->getName(), m_szName);
5039dede
AK
2688
2689 // Check if that template item exists
2690 for(i = 0; i < m_dwNumItems; i++)
fb05c05b
VK
2691 if ((m_ppItems[i]->getTemplateId() == dwTemplateId) &&
2692 (m_ppItems[i]->getTemplateItemId() == pItem->getId()))
5039dede
AK
2693 break; // Item with specified id already exist
2694
2695 if (i == m_dwNumItems)
2696 {
2697 // New item from template, just add it
2698 pNewItem = new DCItem(pItem);
fb05c05b
VK
2699 pNewItem->setTemplateId(dwTemplateId, pItem->getId());
2700 pNewItem->changeBinding(CreateUniqueId(IDG_ITEM), this, TRUE);
7c521895 2701 bResult = addItem(pNewItem, true);
5039dede
AK
2702 }
2703 else
2704 {
2705 // Update existing item
fb05c05b 2706 m_ppItems[i]->updateFromTemplate(pItem);
5039dede
AK
2707 }
2708
7c521895
VK
2709 unlockDciAccess();
2710
2711 if (bResult)
2712 {
2713 LockData();
2714 m_bIsModified = TRUE;
2715 UnlockData();
2716 }
5039dede
AK
2717 return bResult;
2718}
2719
2720
2721//
2722// Clean deleted template items from node's DCI list
2723// Arguments is template id and list of valid template item ids.
2724// all items related to given template and not presented in list should be deleted.
2725//
2726
a2069340 2727void Node::cleanDeletedTemplateItems(DWORD dwTemplateId, DWORD dwNumItems, DWORD *pdwItemList)
5039dede
AK
2728{
2729 DWORD i, j, dwNumDeleted, *pdwDeleteList;
2730
a2069340 2731 lockDciAccess(); // write lock
5039dede
AK
2732
2733 pdwDeleteList = (DWORD *)malloc(sizeof(DWORD) * m_dwNumItems);
2734 dwNumDeleted = 0;
2735
2736 for(i = 0; i < m_dwNumItems; i++)
fb05c05b 2737 if (m_ppItems[i]->getTemplateId() == dwTemplateId)
5039dede
AK
2738 {
2739 for(j = 0; j < dwNumItems; j++)
fb05c05b 2740 if (m_ppItems[i]->getTemplateItemId() == pdwItemList[j])
5039dede
AK
2741 break;
2742
2743 // Delete DCI if it's not in list
2744 if (j == dwNumItems)
fb05c05b 2745 pdwDeleteList[dwNumDeleted++] = m_ppItems[i]->getId();
5039dede
AK
2746 }
2747
2748 for(i = 0; i < dwNumDeleted; i++)
7c521895 2749 deleteItem(pdwDeleteList[i], false);
5039dede 2750
7c521895 2751 unlockDciAccess();
5039dede
AK
2752 free(pdwDeleteList);
2753}
2754
2755
2756//
2757// Unbind node from template, i.e either remove DCI association with template
2758// or remove these DCIs at all
2759//
2760
a2069340 2761void Node::unbindFromTemplate(DWORD dwTemplateId, BOOL bRemoveDCI)
5039dede 2762{
17b055bb 2763 DWORD i;
5039dede
AK
2764
2765 if (bRemoveDCI)
2766 {
17b055bb
VK
2767 DWORD *pdwDeleteList = (DWORD *)malloc(sizeof(DWORD) * m_dwNumItems);
2768 DWORD dwNumDeleted = 0;
5039dede 2769
a2069340 2770 lockDciAccess(); // write lock
5039dede
AK
2771
2772 for(i = 0; i < m_dwNumItems; i++)
fb05c05b 2773 if (m_ppItems[i]->getTemplateId() == dwTemplateId)
5039dede 2774 {
fb05c05b 2775 pdwDeleteList[dwNumDeleted++] = m_ppItems[i]->getId();
5039dede
AK
2776 }
2777
2778 for(i = 0; i < dwNumDeleted; i++)
7c521895 2779 deleteItem(pdwDeleteList[i], false);
5039dede 2780
7c521895 2781 unlockDciAccess();
17b055bb
VK
2782
2783 safe_free(pdwDeleteList);
5039dede
AK
2784 }
2785 else
2786 {
7c521895 2787 lockDciAccess();
5039dede
AK
2788
2789 for(i = 0; i < m_dwNumItems; i++)
fb05c05b 2790 if (m_ppItems[i]->getTemplateId() == dwTemplateId)
5039dede 2791 {
fb05c05b 2792 m_ppItems[i]->setTemplateId(0, 0);
5039dede
AK
2793 }
2794
7c521895 2795 unlockDciAccess();
5039dede
AK
2796 }
2797}
2798
2799
2800//
2801// Change node's IP address
2802//
2803
58b3e451 2804void Node::changeIPAddress(DWORD dwIpAddr)
5039dede
AK
2805{
2806 DWORD i;
2807
7c521895 2808 pollerLock();
5039dede
AK
2809
2810 LockData();
2811
2812 UpdateNodeIndex(m_dwIpAddr, dwIpAddr, this);
2813 m_dwIpAddr = dwIpAddr;
2814 m_dwDynamicFlags |= NDF_FORCE_CONFIGURATION_POLL | NDF_RECHECK_CAPABILITIES;
2815
2816 // Change status of node and all it's childs to UNKNOWN
2817 m_iStatus = STATUS_UNKNOWN;
2818 LockChildList(FALSE);
2819 for(i = 0; i < m_dwChildCount; i++)
2820 {
2821 m_pChildList[i]->ResetStatus();
2822 if (m_pChildList[i]->Type() == OBJECT_INTERFACE)
2823 {
2824 if (((Interface *)m_pChildList[i])->IsFake())
2825 {
2826 ((Interface *)m_pChildList[i])->SetIpAddr(dwIpAddr);
2827 }
2828 }
2829 }
2830 UnlockChildList();
2831
2832 Modify();
2833 UnlockData();
2834
7c521895 2835 agentLock();
5039dede 2836 delete_and_null(m_pAgentConnection);
7c521895 2837 agentUnlock();
5039dede 2838
7c521895 2839 pollerUnlock();
5039dede
AK
2840}
2841
2842
2843//
2844// Get number of interface objects and pointer to the last one
2845//
2846
7c521895 2847DWORD Node::getInterfaceCount(Interface **ppInterface)
5039dede
AK
2848{
2849 DWORD i, dwCount;
2850
2851 LockChildList(FALSE);
2852 for(i = 0, dwCount = 0; i < m_dwChildCount; i++)
2853 if (m_pChildList[i]->Type() == OBJECT_INTERFACE)
2854 {
2855 dwCount++;
2856 *ppInterface = (Interface *)m_pChildList[i];
2857 }
2858 UnlockChildList();
2859 return dwCount;
2860}
2861
2862
2863//
2864// Update cache for all DCI's
2865//
2866
a2069340 2867void Node::updateDciCache()
5039dede
AK
2868{
2869 DWORD i;
2870
a2069340 2871 lockDciAccess();
5039dede 2872 for(i = 0; i < m_dwNumItems; i++)
fb05c05b 2873 m_ppItems[i]->updateCacheSize();
a2069340 2874 unlockDciAccess();
5039dede
AK
2875}
2876
2877
2878//
2879// Get routing table from node
2880//
2881
58b3e451 2882ROUTING_TABLE *Node::getRoutingTable()
5039dede
AK
2883{
2884 ROUTING_TABLE *pRT = NULL;
2885
2886 if ((m_dwFlags & NF_IS_NATIVE_AGENT) && (!(m_dwFlags & NF_DISABLE_NXCP)))
2887 {
7c521895
VK
2888 agentLock();
2889 if (connectToAgent())
5039dede
AK
2890 {
2891 pRT = m_pAgentConnection->GetRoutingTable();
2892 }
7c521895 2893 agentUnlock();
5039dede
AK
2894 }
2895 if ((pRT == NULL) && (m_dwFlags & NF_IS_SNMP) && (!(m_dwFlags & NF_DISABLE_SNMP)))
2896 {
2897 SNMP_Transport *pTransport;
2898
cd9f247e 2899 pTransport = createSnmpTransport();
803d47be
VK
2900 if (pTransport != NULL)
2901 {
2902 pRT = SnmpGetRoutingTable(m_snmpVersion, pTransport);
2903 delete pTransport;
2904 }
5039dede
AK
2905 }
2906
2907 if (pRT != NULL)
2908 {
2909 SortRoutingTable(pRT);
2910 }
2911 return pRT;
2912}
2913
2914
2915//
2916// Get next hop for given destination address
2917//
2918
58b3e451 2919BOOL Node::getNextHop(DWORD dwSrcAddr, DWORD dwDestAddr, DWORD *pdwNextHop,
5039dede
AK
2920 DWORD *pdwIfIndex, BOOL *pbIsVPN)
2921{
2922 DWORD i;
2923 BOOL bResult = FALSE;
2924
2925 // Check VPN connectors
2926 LockChildList(FALSE);
2927 for(i = 0; i < m_dwChildCount; i++)
2928 if (m_pChildList[i]->Type() == OBJECT_VPNCONNECTOR)
2929 {
2930 if (((VPNConnector *)m_pChildList[i])->IsRemoteAddr(dwDestAddr) &&
2931 ((VPNConnector *)m_pChildList[i])->IsLocalAddr(dwSrcAddr))
2932 {
2933 *pdwNextHop = ((VPNConnector *)m_pChildList[i])->GetPeerGatewayAddr();
2934 *pdwIfIndex = m_pChildList[i]->Id();
2935 *pbIsVPN = TRUE;
2936 bResult = TRUE;
2937 break;
2938 }
2939 }
2940 UnlockChildList();
2941
2942 // Check routing table
2943 if (!bResult)
2944 {
7c521895 2945 routingTableLock();
5039dede
AK
2946 if (m_pRoutingTable != NULL)
2947 {
2948 for(i = 0; i < (DWORD)m_pRoutingTable->iNumEntries; i++)
2949 if ((dwDestAddr & m_pRoutingTable->pRoutes[i].dwDestMask) == m_pRoutingTable->pRoutes[i].dwDestAddr)
2950 {
2951 *pdwNextHop = m_pRoutingTable->pRoutes[i].dwNextHop;
2952 *pdwIfIndex = m_pRoutingTable->pRoutes[i].dwIfIndex;
2953 *pbIsVPN = FALSE;
2954 bResult = TRUE;
2955 break;
2956 }
2957 }
7c521895 2958 routingTableUnlock();
5039dede
AK
2959 }
2960
2961 return bResult;
2962}
2963
2964
2965//
2966// Update cached routing table
2967//
2968
58b3e451 2969void Node::updateRoutingTable()
5039dede
AK
2970{
2971 ROUTING_TABLE *pRT;
2972
58b3e451 2973 pRT = getRoutingTable();
5039dede
AK
2974 if (pRT != NULL)
2975 {
7c521895 2976 routingTableLock();
5039dede
AK
2977 DestroyRoutingTable(m_pRoutingTable);
2978 m_pRoutingTable = pRT;
7c521895 2979 routingTableUnlock();
5039dede
AK
2980 }
2981 m_tLastRTUpdate = time(NULL);
2982 m_dwDynamicFlags &= ~NDF_QUEUED_FOR_ROUTE_POLL;
2983}
2984
2985
2986//
2987// Call SNMP Enumerate with node's SNMP parameters
2988//
2989
2990DWORD Node::CallSnmpEnumerate(const char *pszRootOid,
5d2c5741 2991 DWORD (* pHandler)(DWORD, SNMP_Variable *, SNMP_Transport *, void *),
5039dede
AK
2992 void *pArg)
2993{
2994 if ((m_dwFlags & NF_IS_SNMP) &&
2995 (!(m_dwDynamicFlags & NDF_SNMP_UNREACHABLE)) &&
2996 (!(m_dwDynamicFlags & NDF_UNREACHABLE)))
2997 {
2998 SNMP_Transport *pTransport;
2999 DWORD dwResult;
3000
cd9f247e 3001 pTransport = createSnmpTransport();
803d47be
VK
3002 if (pTransport != NULL)
3003 {
3004 dwResult = SnmpEnumerate(m_snmpVersion, pTransport,
3005 pszRootOid, pHandler, pArg, FALSE);
3006 delete pTransport;
3007 }
3008 else
3009 {
3010 dwResult = SNMP_ERR_COMM;
3011 }
5039dede
AK
3012 return dwResult;
3013 }
3014 else
3015 {
3016 return SNMP_ERR_COMM;
3017 }
3018}
3019
3020
3021//
3022// Set proxy information for agent's connection
3023//
3024
7c521895 3025void Node::setAgentProxy(AgentConnection *pConn)
5039dede
AK
3026{
3027 if (m_dwProxyNode != 0)
3028 {
3029 Node *pNode;
3030
3031 pNode = (Node *)FindObjectById(m_dwProxyNode);
3032 if (pNode != NULL)
3033 {
7c521895 3034 pConn->setProxy(htonl(pNode->m_dwIpAddr), pNode->m_wAgentPort,
5039dede
AK
3035 pNode->m_wAuthMethod, pNode->m_szSharedSecret);
3036 }
3037 }
3038}
3039
3040
3041//
3042// Prepare node object for deletion
3043//
3044
3045void Node::PrepareForDeletion(void)
3046{
3047 // Prevent node from being queued for polling
3048 LockData();
3049 m_dwDynamicFlags |= NDF_POLLING_DISABLED;
3050 UnlockData();
3051
3052 // Wait for all pending polls
3053 while(1)
3054 {
3055 LockData();
3056 if ((m_dwDynamicFlags &
3057 (NDF_QUEUED_FOR_STATUS_POLL | NDF_QUEUED_FOR_CONFIG_POLL |
3058 NDF_QUEUED_FOR_DISCOVERY_POLL | NDF_QUEUED_FOR_ROUTE_POLL)) == 0)
3059 {
3060 UnlockData();
3061 break;
3062 }
3063 UnlockData();
3064 ThreadSleepMs(100);
3065 }
3066 Template::PrepareForDeletion();
3067}
3068
3069
3070//
3071// Check if specified SNMP variable set to specified value.
3072// If variable doesn't exist at all, will return FALSE
3073//
3074
3075BOOL Node::CheckSNMPIntegerValue(SNMP_Transport *pTransport, const char *pszOID, int nValue)
3076{
3077 DWORD dwTemp;
3078
5d2c5741
VK
3079 if (SnmpGet(m_snmpVersion, pTransport, pszOID, NULL, 0, &dwTemp,
3080 sizeof(DWORD), FALSE, FALSE) == SNMP_ERR_SUCCESS)
5039dede
AK
3081 return (int)dwTemp == nValue;
3082 return FALSE;
3083}
3084
3085
3086//
3087// Check and update if needed interface names
3088//
3089
3090void Node::CheckInterfaceNames(INTERFACE_LIST *pIfList)
3091{
3092 int i;
3093 TCHAR *ptr;
3094
3095 if ((m_dwNodeType == NODE_TYPE_NORTEL_BAYSTACK) ||
3096 (m_dwNodeType == NODE_TYPE_NORTEL_OPTERA))
3097 {
3098 // Translate interface names
3099 for(i = 0; i < pIfList->iNumEntries; i++)
3100 {
3101 if ((ptr = _tcsstr(pIfList->pInterfaces[i].szName, _T("- Port"))) != NULL)
3102 {
3103 ptr += 2;
3104 memmove(pIfList->pInterfaces[i].szName, ptr, _tcslen(ptr) + 1);
3105 }
3106 else if ((ptr = _tcsstr(pIfList->pInterfaces[i].szName, _T("- Unit"))) != NULL)
3107 {
3108 ptr += 2;
3109 memmove(pIfList->pInterfaces[i].szName, ptr, _tcslen(ptr) + 1);
3110 }
3111 else if ((_tcsstr(pIfList->pInterfaces[i].szName, _T("BayStack")) != NULL) ||
3112 (_tcsstr(pIfList->pInterfaces[i].szName, _T("Nortel Ethernet Switch")) != NULL))
3113 {
3114 ptr = _tcsrchr(pIfList->pInterfaces[i].szName, _T('-'));
3115 if (ptr != NULL)
3116 {
3117 ptr++;
3118 while(*ptr == _T(' '))
3119 ptr++;
3120 memmove(pIfList->pInterfaces[i].szName, ptr, _tcslen(ptr) + 1);
3121 }
3122 }
3123 StrStrip(pIfList->pInterfaces[i].szName);
3124 }
3125 }
3126
3127 // Cut interface names to MAX_OBJECT_NAME and check for unnamed interfaces
3128 for(i = 0; i < pIfList->iNumEntries; i++)
3129 {
3130 pIfList->pInterfaces[i].szName[MAX_OBJECT_NAME - 1] = 0;
3131 if (pIfList->pInterfaces[i].szName[0] == 0)
3132 _stprintf(pIfList->pInterfaces[i].szName, _T("%d"), pIfList->pInterfaces[i].dwIndex);
3133 }
3134}
3135
3136
3137//
3138// Get cluster object this node belongs to, if any
3139//
3140
7c521895 3141Cluster *Node::getMyCluster()
5039dede
AK
3142{
3143 DWORD i;
3144 Cluster *pCluster = NULL;
3145
3146 LockParentList(FALSE);
3147 for(i = 0; i < m_dwParentCount; i++)
3148 if (m_pParentList[i]->Type() == OBJECT_CLUSTER)
3149 {
3150 pCluster = (Cluster *)m_pParentList[i];
3151 break;
3152 }
3153 UnlockParentList();
3154 return pCluster;
3155}
3156
3157
3158//
3159// Create SNMP transport
3160//
3161
65e2005b 3162SNMP_Transport *Node::createSnmpTransport(WORD port)
5039dede
AK
3163{
3164 SNMP_Transport *pTransport = NULL;
3165
3166 if (m_dwSNMPProxy == 0)
3167 {
3168 pTransport = new SNMP_UDPTransport;
65e2005b 3169 ((SNMP_UDPTransport *)pTransport)->createUDPTransport(NULL, htonl(m_dwIpAddr), (port != 0) ? port : m_wSNMPPort);
5039dede
AK
3170 }
3171 else
3172 {
3173 NetObj *pObject;
3174
3175 pObject = FindObjectById(m_dwSNMPProxy);
3176 if (pObject != NULL)
3177 {
3178 if (pObject->Type() == OBJECT_NODE)
3179 {
3180 AgentConnection *pConn;
3181
cd9f247e 3182 pConn = ((Node *)pObject)->createAgentConnection();
5039dede
AK
3183 if (pConn != NULL)
3184 {
65e2005b 3185 pTransport = new SNMP_ProxyTransport(pConn, m_dwIpAddr, (port != 0) ? port : m_wSNMPPort);
5039dede
AK
3186 }
3187 }
3188 }
3189 }
5d2c5741
VK
3190
3191 // Set security
3192 if (pTransport != NULL)
3193 {
df8a4ca2 3194 LockData();
5d2c5741 3195 pTransport->setSecurityContext(new SNMP_SecurityContext(m_snmpSecurity));
df8a4ca2 3196 UnlockData();
5d2c5741 3197 }
5039dede
AK
3198 return pTransport;
3199}
cd9f247e
VK
3200
3201
3202//
3203// Get SNMP security context
3204// ATTENTION: This method returns new copy of security context
3205// which must be destroyed by the caller
3206//
3207
3208SNMP_SecurityContext *Node::getSnmpSecurityContext()
3209{
3210 LockData();
3211 SNMP_SecurityContext *ctx = new SNMP_SecurityContext(m_snmpSecurity);
3212 UnlockData();
3213 return ctx;
3214}
5039dede
AK
3215
3216
3217//
3218// Resolve node's name
3219//
3220
3221BOOL Node::ResolveName(BOOL useOnlyDNS)
3222{
3223 BOOL bSuccess = FALSE;
3224 HOSTENT *hs;
3225 DWORD i, dwAddr;
3226 TCHAR szBuffer[256];
3227
3228 DbgPrintf(4, _T("Resolving name for node %d [%s]..."), m_dwId, m_szName);
3229
3230 // Try to resolve primary IP
3231 dwAddr = htonl(m_dwIpAddr);
3232 hs = gethostbyaddr((const char *)&dwAddr, 4, AF_INET);
3233 if (hs != NULL)
3234 {
3235 nx_strncpy(m_szName, hs->h_name, MAX_OBJECT_NAME);
3236 bSuccess = TRUE;
3237 }
3238 else
3239 {
3240 // Try to resolve each interface's IP address
3241 LockChildList(FALSE);
3242 for(i = 0; i < m_dwChildCount; i++)
3243 {
3244 if (m_pChildList[i]->Type() == OBJECT_INTERFACE)
3245 {
3246 dwAddr = htonl(m_pChildList[i]->IpAddr());
3247 if (dwAddr != 0)
3248 {
3249 hs = gethostbyaddr((const char *)&dwAddr, 4, AF_INET);
3250 if (hs != NULL)
3251 {
3252 nx_strncpy(m_szName, hs->h_name, MAX_OBJECT_NAME);
3253 bSuccess = TRUE;
3254 break;
3255 }
3256 }
3257 }
3258 }
3259 UnlockChildList();
3260
3261 // Try to get hostname from agent if address resolution fails
3262 if (!(bSuccess || useOnlyDNS))
3263 {
3264 DbgPrintf(4, _T("Resolving name for node %d [%s] via agent..."), m_dwId, m_szName);
3265 if (GetItemFromAgent("System.Hostname", 256, szBuffer) == DCE_SUCCESS)
3266 {
3267 StrStrip(szBuffer);
3268 if (szBuffer[0] != 0)
3269 {
3270 nx_strncpy(m_szName, szBuffer, MAX_OBJECT_NAME);
3271 bSuccess = TRUE;
3272 }
3273 }
3274 }
3275
3276 // Try to get hostname from SNMP if other methods fails
3277 if (!(bSuccess || useOnlyDNS))
3278 {
3279 DbgPrintf(4, _T("Resolving name for node %d [%s] via SNMP..."), m_dwId, m_szName);
65e2005b 3280 if (GetItemFromSNMP(0, ".1.3.6.1.2.1.1.5.0", 256, szBuffer) == DCE_SUCCESS)
5039dede
AK
3281 {
3282 StrStrip(szBuffer);
3283 if (szBuffer[0] != 0)
3284 {
3285 nx_strncpy(m_szName, szBuffer, MAX_OBJECT_NAME);
3286 bSuccess = TRUE;
3287 }
3288 }
3289 }
3290 }
3291
3292 if (bSuccess)
3293 DbgPrintf(4, _T("Name for node %d was resolved to %s"), m_dwId, m_szName);
3294 else
3295 DbgPrintf(4, _T("Name for node %d was not resolved"), m_dwId, m_szName);
3296 return bSuccess;
3297}
3298
3299
3300//
3301// Send list of system DCIs
3302//
3303
74526d25 3304DWORD Node::getPerfTabDCIList(CSCPMessage *pMsg)
5039dede
AK
3305{
3306 DWORD i, dwId, dwCount;
3307
3308 LockData();
3309
3310 for(i = 0, dwId = VID_SYSDCI_LIST_BASE, dwCount = 0; i < m_dwNumItems; i++)
3311 {
74526d25
VK
3312 if (!_tcsnicmp(m_ppItems[i]->getDescription(), _T("@System."), 8) ||
3313 (m_ppItems[i]->getPerfTabSettings() != NULL))
5039dede 3314 {
fb05c05b
VK
3315 pMsg->SetVariable(dwId++, m_ppItems[i]->getId());
3316 pMsg->SetVariable(dwId++, (TCHAR *)m_ppItems[i]->getDescription());
3317 pMsg->SetVariable(dwId++, (WORD)m_ppItems[i]->getStatus());
e76d8b6f
VK
3318 if (m_ppItems[i]->getPerfTabSettings() != NULL)
3319 {
3320 pMsg->SetVariable(dwId++, m_ppItems[i]->getPerfTabSettings());
3321 dwId += 6;
3322 }
3323 else
3324 {
3325 dwId += 7;
3326 }
5039dede
AK
3327 dwCount++;
3328 }
3329 }
3330 pMsg->SetVariable(VID_NUM_ITEMS, dwCount);
3331
3332 UnlockData();
3333 return RCC_SUCCESS;
3334}
3335
3336
3337//
3338// Get current layer 2 topology (as dynamically created list which should be destroyed by caller)
3339// Will return NULL if there are no topology information or it is expired
3340//
3341
3342nxmap_ObjList *Node::GetL2Topology(void)
3343{
3344 nxmap_ObjList *pResult;
3345 DWORD dwExpTime;
3346
3347 dwExpTime = ConfigReadULong(_T("TopologyExpirationTime"), 900);
3348 MutexLock(m_mutexTopoAccess, INFINITE);
3349 if ((m_pTopology == NULL) || (m_tLastTopologyPoll + (time_t)dwExpTime < time(NULL)))
3350 {
3351 pResult = NULL;
3352 }
3353 else
3354 {
3355 pResult = new nxmap_ObjList(m_pTopology);
3356 }
3357 MutexUnlock(m_mutexTopoAccess);
3358 return pResult;
3359}
3360
3361
3362//
3363// Rebuild layer 2 topology and return it as dynamically reated list which should be destroyed by caller
3364//
3365
3366nxmap_ObjList *Node::BuildL2Topology(DWORD *pdwStatus)
3367{
3368 nxmap_ObjList *pResult;
3369 int nDepth;
3370
3371 nDepth = ConfigReadInt(_T("TopologyDiscoveryRadius"), 5);
3372 MutexLock(m_mutexTopoAccess, INFINITE);
3373 delete m_pTopology;
3374 if ((m_dwFlags & NF_IS_CDP) || (m_dwFlags & NF_IS_SONMP) || (m_dwFlags & NF_IS_LLDP))
3375 {
3376 m_pTopology = new nxmap_ObjList;
3377 if ((*pdwStatus = ::BuildL2Topology(*m_pTopology, this, NULL, nDepth, NULL)) == RCC_SUCCESS)
3378 {
3379 m_tLastTopologyPoll = time(NULL);
3380 pResult = new nxmap_ObjList(m_pTopology);
3381 }
3382 else
3383 {
3384 delete_and_null(m_pTopology);
3385 pResult = NULL;
3386 }
3387 }
3388 else
3389 {
3390 pResult = NULL;
3391 m_pTopology = NULL;
3392 *pdwStatus = RCC_NO_L2_TOPOLOGY_SUPPORT;
3393 }
3394 MutexUnlock(m_mutexTopoAccess);
3395 return pResult;
3396}
3397
3398
3399//
3400// Check subnet bindings
3401//
3402
3403void Node::CheckSubnetBinding(INTERFACE_LIST *pIfList)
3404{
3405 Subnet *pSubnet;
3406 Interface *pInterface;
3407 Cluster *pCluster;
3408 NetObj **ppUnlinkList;
3409 int i, j, count;
3410 BOOL isSync;
3411
7c521895 3412 pCluster = getMyCluster();
5039dede
AK
3413
3414 // Check if we have subnet bindings for all interfaces
3415 for(i = 0; i < pIfList->iNumEntries; i++)
3416 {
3417 if (pIfList->pInterfaces[i].dwIpAddr != 0)
3418 {
58b3e451 3419 pInterface = findInterface(pIfList->pInterfaces[i].dwIndex, pIfList->pInterfaces[i].dwIpAddr);
5039dede
AK
3420 if (pInterface == NULL)
3421 {
3422 nxlog_write(MSG_INTERNAL_ERROR, EVENTLOG_WARNING_TYPE, "s", _T("Cannot find interface object in Node::CheckSubnetBinding()"));
3423 break; // Something goes really wrong
3424 }
3425
3426 // Is cluster interconnect interface?
58b3e451 3427 isSync = (pCluster != NULL) ? pCluster->isSyncAddr(pInterface->IpAddr()) : FALSE;
5039dede
AK
3428
3429 pSubnet = FindSubnetForNode(pIfList->pInterfaces[i].dwIpAddr);
3430 if (pSubnet != NULL)
3431 {
3432 if (isSync)
3433 {
3434 pSubnet = NULL; // No further checks on this subnet
3435 }
3436 else
3437 {
3438 if (pSubnet->IsSyntheticMask())
3439 {
3440 DbgPrintf(4, _T("Setting correct netmask for subnet %s [%d] from node %s [%d]"),
3441 pSubnet->Name(), pSubnet->Id(), m_szName, m_dwId);
3442 pSubnet->SetCorrectMask(pInterface->IpAddr() & pInterface->IpNetMask(), pInterface->IpNetMask());
3443 }
3444 }
3445 }
3446 else if (!isSync)
3447 {
3448 // Create subnet
3449 pSubnet = new Subnet(pIfList->pInterfaces[i].dwIpAddr & pIfList->pInterfaces[i].dwIpNetMask,
3450 pIfList->pInterfaces[i].dwIpNetMask, m_dwZoneGUID, FALSE);
3451 NetObjInsert(pSubnet, TRUE);
3452 g_pEntireNet->AddSubnet(pSubnet);
3453 pSubnet->AddNode(this);
3454 DbgPrintf(4, _T("Node::CheckSubnetBinding(): Creating new subnet %s [%d] for node %s [%d]"),
3455 pSubnet->Name(), pSubnet->Id(), m_szName, m_dwId);
3456 }
3457
3458 // Check if subnet mask is correct on interface
3459 if ((pSubnet != NULL) && (pSubnet->IpNetMask() != pIfList->pInterfaces[i].dwIpNetMask))
3460 {
3461 PostEvent(EVENT_INCORRECT_NETMASK, m_dwId, "idsaa", pInterface->Id(),
3462 pInterface->IfIndex(), pInterface->Name(),
3463 pInterface->IpNetMask(), pSubnet->IpNetMask());
3464 }
3465 }
3466 }
3467
3468 // Check if we have incorrect subnets as parents
3469 LockParentList(FALSE);
3470 LockChildList(FALSE);
3471 ppUnlinkList = (NetObj **)malloc(sizeof(NetObj *) * m_dwParentCount);
3472 for(i = 0, count = 0; i < (int)m_dwParentCount; i++)
3473 {
3474 if (m_pParentList[i]->Type() == OBJECT_SUBNET)
3475 {
3476 pSubnet = (Subnet *)m_pParentList[i];
3477 for(j = 0; j < (int)m_dwChildCount; j++)
3478 {
3479 if (m_pChildList[j]->Type() == OBJECT_INTERFACE)
3480 {
3481 if (pSubnet->IpAddr() == (m_pChildList[j]->IpAddr() & pSubnet->IpNetMask()))
3482 {
3483 if (pCluster != NULL)
3484 {
58b3e451 3485 if (pCluster->isSyncAddr(m_pChildList[j]->IpAddr()))
5039dede
AK
3486 {
3487 j = (int)m_dwChildCount; // Cause to unbind from this subnet
3488 }
3489 }
3490 break;
3491 }
3492 }
3493 }
3494 if (j == (int)m_dwChildCount)
3495 {
3496 DbgPrintf(4, _T("Node::CheckSubnetBinding(): Subnet %s [%d] is incorrect for node %s [%d]"),
3497 pSubnet->Name(), pSubnet->Id(), m_szName, m_dwId);
3498 ppUnlinkList[count++] = pSubnet;
3499 }
3500 }
3501 }
3502 UnlockChildList();
3503 UnlockParentList();
3504
3505 // Unlink for incorrect subnet objects
3506 for(i = 0; i < count; i++)
3507 {
3508 ppUnlinkList[i]->DeleteChild(this);
3509 DeleteParent(ppUnlinkList[i]);
3510 }
3511 safe_free(ppUnlinkList);
3512}
3513
3514
3515//
3516// Update interface names
3517//
3518
58b3e451 3519void Node::updateInterfaceNames(ClientSession *pSession, DWORD dwRqId)
5039dede
AK
3520{
3521 INTERFACE_LIST *pIfList;
3522 DWORD i;
3523 int j;
3524
7c521895 3525 pollerLock();
5039dede
AK
3526 m_pPollRequestor = pSession;
3527 SendPollerMsg(dwRqId, _T("Starting interface names poll for node %s\r\n"), m_szName);
3528 DbgPrintf(4, "Starting interface names poll for node %s (ID: %d)", m_szName, m_dwId);
3529
3530 // Retrieve interface list
58b3e451 3531 pIfList = getInterfaceList();
5039dede
AK
3532 if (pIfList != NULL)
3533 {
3534 // Check names of existing interfaces
3535 for(j = 0; j < pIfList->iNumEntries; j++)
3536 {
3537 LockChildList(FALSE);
3538 for(i = 0; i < m_dwChildCount; i++)
3539 {
3540 if (m_pChildList[i]->Type() == OBJECT_INTERFACE)
3541 {
3542 Interface *pInterface = (Interface *)m_pChildList[i];
3543
3544 if (pIfList->pInterfaces[j].dwIndex == pInterface->IfIndex())
3545 {
3546 SendPollerMsg(dwRqId, _T(" Checking interface %d (%s)\r\n"), pInterface->IfIndex(), pInterface->Name());
3547 if (strcmp(pIfList->pInterfaces[j].szName, pInterface->Name()))
3548 {
3549 pInterface->SetName(pIfList->pInterfaces[j].szName);
3550 SendPollerMsg(dwRqId, POLLER_WARNING _T(" Name of interface %d changed to %s\r\n"), pInterface->IfIndex(), pIfList->pInterfaces[j].szName);
3551 }
3552 break;
3553 }
3554 }
3555 }
3556 UnlockChildList();
3557 }
3558
3559 DestroyInterfaceList(pIfList);
3560 }
3561 else /* pIfList == NULL */
3562 {
3563 SendPollerMsg(dwRqId, POLLER_ERROR _T(" Unable to get interface list from node\r\n"));
3564 }
3565
3566 // Finish poll
3567 SendPollerMsg(dwRqId, _T("Finished interface names poll for node %s\r\n"), m_szName);
7c521895 3568 pollerUnlock();
5039dede
AK
3569 DbgPrintf(4, "Finished interface names poll for node %s (ID: %d)", m_szName, m_dwId);
3570}
a2069340
VK
3571
3572
3573//
3574// Process new DCI value
3575//
3576
3577void Node::processNewDciValue(DCItem *item, time_t currTime, const TCHAR *value)
3578{
3579 lockDciAccess();
3580 item->processNewValue(currTime, value);
3581 unlockDciAccess();
3582}