unfinished work on network maps
[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 ")
e642792a 324 _T("(%d,'%s',%d,%d,%d,%s,%d,%d,%d,%s,%s,%d,%d,%s,%s,%s,%d,%d,%d,%d,%d,%s,%s,%d)"),
65e2005b
VK
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
2fd7144f 1912 if ((((m_dwDynamicFlags & NDF_SNMP_UNREACHABLE) || !(m_dwFlags & NF_IS_SNMP)) && (port == 0)) ||
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) ||
2fd7144f
VK
1980 (m_dwDynamicFlags & NDF_UNREACHABLE) ||
1981 (m_dwFlags & NF_DISABLE_NXCP) ||
1982 !(m_dwFlags & NF_IS_NATIVE_AGENT))
5039dede
AK
1983 return DCE_COMM_ERROR;
1984
7c521895 1985 agentLock();
5039dede
AK
1986
1987 // Establish connection if needed
1988 if (m_pAgentConnection == NULL)
7c521895 1989 if (!connectToAgent())
5039dede
AK
1990 goto end_loop;
1991
1992 // Get parameter from agent
1993 while(dwTries-- > 0)
1994 {
1995 dwError = m_pAgentConnection->GetParameter((char *)szParam, dwBufSize, szBuffer);
1996 switch(dwError)
1997 {
1998 case ERR_SUCCESS:
1999 dwResult = DCE_SUCCESS;
2000 goto end_loop;
2001 case ERR_UNKNOWN_PARAMETER:
2002 dwResult = DCE_NOT_SUPPORTED;
2003 goto end_loop;
2004 case ERR_NOT_CONNECTED:
2005 case ERR_CONNECTION_BROKEN:
7c521895 2006 if (!connectToAgent())
5039dede
AK
2007 goto end_loop;
2008 break;
2009 case ERR_REQUEST_TIMEOUT:
2010 // Reset connection to agent after timeout
2011 DbgPrintf(7, _T("Node(%s)->GetItemFromAgent(%s): timeout; resetting connection to agent..."), m_szName, szParam);
2012 delete_and_null(m_pAgentConnection);
7c521895 2013 if (!connectToAgent())
5039dede
AK
2014 goto end_loop;
2015 DbgPrintf(7, _T("Node(%s)->GetItemFromAgent(%s): connection to agent restored successfully"), m_szName, szParam);
2016 break;
2017 }
2018 }
2019
2020end_loop:
7c521895 2021 agentUnlock();
5039dede
AK
2022 DbgPrintf(7, "Node(%s)->GetItemFromAgent(%s): dwError=%d dwResult=%d",
2023 m_szName, szParam, dwError, dwResult);
2024 return dwResult;
2025}
2026
2027
2028//
2029// Get value for server's internal parameter
2030//
2031
2032DWORD Node::GetInternalItem(const char *szParam, DWORD dwBufSize, char *szBuffer)
2033{
2034 DWORD dwError = DCE_SUCCESS;
2035
2036 if (!stricmp(szParam, "Status"))
2037 {
2038 sprintf(szBuffer, "%d", m_iStatus);
2039 }
2040 else if (!stricmp(szParam, "Dummy"))
2041 {
2042 _tcscpy(szBuffer, _T("0"));
2043 }
2044 else if (!stricmp(szParam, "AgentStatus"))
2045 {
2046 if (m_dwFlags & NF_IS_NATIVE_AGENT)
2047 {
2048 szBuffer[0] = (m_dwDynamicFlags & NDF_AGENT_UNREACHABLE) ? '1' : '0';
2049 szBuffer[1] = 0;
2050 }
2051 else
2052 {
2053 dwError = DCE_NOT_SUPPORTED;
2054 }
2055 }
2056 else if (MatchString("ChildStatus(*)", szParam, FALSE))
2057 {
2058 char *pEnd, szArg[256];
2059 DWORD i, dwId;
2060 NetObj *pObject = NULL;
2061
6173bea8 2062 AgentGetParameterArg((char *)szParam, 1, szArg, 256);
5039dede
AK
2063 dwId = strtoul(szArg, &pEnd, 0);
2064 if (*pEnd != 0)
2065 {
2066 // Argument is object's name
2067 dwId = 0;
2068 }
2069
2070 // Find child object with requested ID or name
2071 LockChildList(FALSE);
2072 for(i = 0; i < m_dwChildCount; i++)
2073 {
2074 if (((dwId == 0) && (!stricmp(m_pChildList[i]->Name(), szArg))) ||
2075 (dwId == m_pChildList[i]->Id()))
2076 {
2077 pObject = m_pChildList[i];
2078 break;
2079 }
2080 }
2081 UnlockChildList();
2082
2083 if (pObject != NULL)
2084 {
2085 sprintf(szBuffer, "%d", pObject->Status());
2086 }
2087 else
2088 {
2089 dwError = DCE_NOT_SUPPORTED;
2090 }
2091 }
2092 else if (MatchString("ConditionStatus(*)", szParam, FALSE))
2093 {
2094 char *pEnd, szArg[256];
2095 DWORD dwId;
2096 NetObj *pObject = NULL;
2097
6173bea8 2098 AgentGetParameterArg((char *)szParam, 1, szArg, 256);
5039dede
AK
2099 dwId = strtoul(szArg, &pEnd, 0);
2100 if (*pEnd == 0)
2101 {
2102 pObject = FindObjectById(dwId);
2103 if (pObject != NULL)
2104 if (pObject->Type() != OBJECT_CONDITION)
2105 pObject = NULL;
2106 }
2107 else
2108 {
2109 // Argument is object's name
2110 pObject = FindObjectByName(szArg, OBJECT_CONDITION);
2111 }
2112
2113 if (pObject != NULL)
2114 {
2115 if (pObject->IsTrustedNode(m_dwId))
2116 {
2117 sprintf(szBuffer, "%d", pObject->Status());
2118 }
2119 else
2120 {
2121 dwError = DCE_NOT_SUPPORTED;
2122 }
2123 }
2124 else
2125 {
2126 dwError = DCE_NOT_SUPPORTED;
2127 }
2128 }
2129 else if (m_dwFlags & NF_IS_LOCAL_MGMT)
2130 {
2131 if (!stricmp(szParam, "Server.AverageDCPollerQueueSize"))
2132 {
2133 sprintf(szBuffer, "%f", g_dAvgPollerQueueSize);
2134 }
2135 else if (!stricmp(szParam, "Server.AverageDBWriterQueueSize"))
2136 {
2137 sprintf(szBuffer, "%f", g_dAvgDBWriterQueueSize);
2138 }
2139 else if (!stricmp(szParam, "Server.AverageStatusPollerQueueSize"))
2140 {
2141 sprintf(szBuffer, "%f", g_dAvgStatusPollerQueueSize);
2142 }
2143 else if (!stricmp(szParam, "Server.AverageConfigurationPollerQueueSize"))
2144 {
2145 sprintf(szBuffer, "%f", g_dAvgConfigPollerQueueSize);
2146 }
2147 else if (!stricmp(szParam, "Server.AverageDCIQueuingTime"))
2148 {
2149 sprintf(szBuffer, "%u", g_dwAvgDCIQueuingTime);
2150 }
2151 else if (!stricmp(szParam, "Server.TotalEventsProcessed"))
2152 {
2153 sprintf(szBuffer, INT64_FMT, g_totalEventsProcessed);
2154 }
2155 else
2156 {
2157 dwError = DCE_NOT_SUPPORTED;
2158 }
2159 }
2160 else
2161 {
2162 dwError = DCE_NOT_SUPPORTED;
2163 }
2164
2165 return dwError;
2166}
2167
2168
2169//
2170// Get item's value for client
2171//
2172
2173DWORD Node::GetItemForClient(int iOrigin, const char *pszParam, char *pszBuffer, DWORD dwBufSize)
2174{
2175 DWORD dwResult = 0, dwRetCode;
2176
2177 // Get data from node
2178 switch(iOrigin)
2179 {
2180 case DS_INTERNAL:
2181 dwRetCode = GetInternalItem(pszParam, dwBufSize, pszBuffer);
2182 break;
2183 case DS_NATIVE_AGENT:
2184 dwRetCode = GetItemFromAgent(pszParam, dwBufSize, pszBuffer);
2185 break;
2186 case DS_SNMP_AGENT:
65e2005b 2187 dwRetCode = GetItemFromSNMP(0, pszParam, dwBufSize, pszBuffer);
5039dede
AK
2188 break;
2189 case DS_CHECKPOINT_AGENT:
2190 dwRetCode = GetItemFromCheckPointSNMP(pszParam, dwBufSize, pszBuffer);
2191 break;
2192 default:
2193 dwResult = RCC_INVALID_ARGUMENT;
2194 break;
2195 }
2196
2197 // Translate return code to RCC
2198 if (dwResult != RCC_INVALID_ARGUMENT)
2199 {
2200 switch(dwRetCode)
2201 {
2202 case DCE_SUCCESS:
2203 dwResult = RCC_SUCCESS;
2204 break;
2205 case DCE_COMM_ERROR:
2206 dwResult = RCC_COMM_FAILURE;
2207 break;
2208 case DCE_NOT_SUPPORTED:
2209 dwResult = RCC_DCI_NOT_SUPPORTED;
2210 break;
2211 default:
2212 dwResult = RCC_SYSTEM_FAILURE;
2213 break;
2214 }
2215 }
2216
2217 return dwResult;
2218}
2219
2220
2221//
2222// Put items which requires polling into the queue
2223//
2224
7c521895 2225void Node::queueItemsForPolling(Queue *pPollerQueue)
5039dede
AK
2226{
2227 DWORD i;
2228 time_t currTime;
2229
2230 if ((m_iStatus == STATUS_UNMANAGED) ||
2231 (m_dwFlags & NF_DISABLE_DATA_COLLECT) ||
2232 (m_bIsDeleted))
2233 return; // Do not collect data for unmanaged nodes or if data collection is disabled
2234
2235 currTime = time(NULL);
2236
7c521895 2237 lockDciAccess();
5039dede
AK
2238 for(i = 0; i < m_dwNumItems; i++)
2239 {
fb05c05b 2240 if (m_ppItems[i]->isReadyForPolling(currTime))
5039dede 2241 {
fb05c05b 2242 m_ppItems[i]->setBusyFlag(TRUE);
5039dede
AK
2243 IncRefCount(); // Increment reference count for each queued DCI
2244 pPollerQueue->Put(m_ppItems[i]);
61b48d2f 2245 DbgPrintf(8, _T("Node(%s)->QueueItemsForPolling(): item %d \"%s\" added to queue"), m_szName, m_ppItems[i]->getId(), m_ppItems[i]->getName());
5039dede
AK
2246 }
2247 }
7c521895 2248 unlockDciAccess();
5039dede
AK
2249}
2250
2251
2252//
2253// Create CSCP message with object's data
2254//
2255
2256void Node::CreateMessage(CSCPMessage *pMsg)
2257{
2258 Template::CreateMessage(pMsg);
2259 pMsg->SetVariable(VID_FLAGS, m_dwFlags);
fa6173b9 2260 pMsg->SetVariable(VID_RUNTIME_FLAGS, m_dwDynamicFlags);
5039dede
AK
2261 pMsg->SetVariable(VID_AGENT_PORT, m_wAgentPort);
2262 pMsg->SetVariable(VID_AUTH_METHOD, m_wAuthMethod);
2263 pMsg->SetVariable(VID_SHARED_SECRET, m_szSharedSecret);
4b7d8903
VK
2264 pMsg->SetVariable(VID_SNMP_AUTH_OBJECT, m_snmpSecurity->getCommunity());
2265 pMsg->SetVariable(VID_SNMP_AUTH_PASSWORD, m_snmpSecurity->getAuthPassword());
2266 pMsg->SetVariable(VID_SNMP_PRIV_PASSWORD, m_snmpSecurity->getPrivPassword());
2267 pMsg->SetVariable(VID_SNMP_USM_METHODS, (WORD)((WORD)m_snmpSecurity->getAuthMethod() | ((WORD)m_snmpSecurity->getPrivMethod() << 8)));
5039dede 2268 pMsg->SetVariable(VID_SNMP_OID, m_szObjectId);
65e2005b 2269 pMsg->SetVariable(VID_SNMP_PORT, m_wSNMPPort);
5039dede 2270 pMsg->SetVariable(VID_NODE_TYPE, m_dwNodeType);
5d2c5741 2271 pMsg->SetVariable(VID_SNMP_VERSION, (WORD)m_snmpVersion);
5039dede
AK
2272 pMsg->SetVariable(VID_AGENT_VERSION, m_szAgentVersion);
2273 pMsg->SetVariable(VID_PLATFORM_NAME, m_szPlatformName);
2274 pMsg->SetVariable(VID_POLLER_NODE_ID, m_dwPollerNode);
2275 pMsg->SetVariable(VID_ZONE_GUID, m_dwZoneGUID);
2276 pMsg->SetVariable(VID_PROXY_NODE, m_dwProxyNode);
2277 pMsg->SetVariable(VID_SNMP_PROXY, m_dwSNMPProxy);
2278 pMsg->SetVariable(VID_REQUIRED_POLLS, (WORD)m_iRequiredPollCount);
2279 pMsg->SetVariable(VID_SYS_DESCRIPTION, m_szSysDescription);
2280 pMsg->SetVariable(VID_USE_IFXTABLE, (WORD)m_nUseIfXTable);
2281}
2282
2283
2284//
2285// Modify object from message
2286//
2287
2288DWORD Node::ModifyFromMessage(CSCPMessage *pRequest, BOOL bAlreadyLocked)
2289{
5d2c5741
VK
2290 TCHAR buffer[256];
2291
5039dede
AK
2292 if (!bAlreadyLocked)
2293 LockData();
2294
2295 // Change primary IP address
2296 if (pRequest->IsVariableExist(VID_IP_ADDRESS))
2297 {
2298 DWORD i, dwIpAddr;
2299
2300 dwIpAddr = pRequest->GetVariableLong(VID_IP_ADDRESS);
2301
2302 // Check if received IP address is one of node's interface addresses
2303 LockChildList(FALSE);
2304 for(i = 0; i < m_dwChildCount; i++)
2305 if ((m_pChildList[i]->Type() == OBJECT_INTERFACE) &&
2306 (m_pChildList[i]->IpAddr() == dwIpAddr))
2307 break;
2308 UnlockChildList();
2309 if (i == m_dwChildCount)
2310 {
2311 UnlockData();
2312 return RCC_INVALID_IP_ADDR;
2313 }
2314
2315 UpdateNodeIndex(m_dwIpAddr, dwIpAddr, this);
2316 m_dwIpAddr = dwIpAddr;
2317 }
2318
2319 // Poller node ID
2320 if (pRequest->IsVariableExist(VID_POLLER_NODE_ID))
2321 {
2322 DWORD dwNodeId;
2323 NetObj *pObject;
2324
2325 dwNodeId = pRequest->GetVariableLong(VID_POLLER_NODE_ID);
2326 pObject = FindObjectById(dwNodeId);
2327
2328 // Check if received id is a valid node id
2329 if (pObject == NULL)
2330 {
2331 UnlockData();
2332 return RCC_INVALID_OBJECT_ID;
2333 }
2334 if (pObject->Type() != OBJECT_NODE)
2335 {
2336 UnlockData();
2337 return RCC_INVALID_OBJECT_ID;
2338 }
2339
2340 m_dwPollerNode = dwNodeId;
2341 }
2342
2343 // Change listen port of native agent
2344 if (pRequest->IsVariableExist(VID_AGENT_PORT))
2345 m_wAgentPort = pRequest->GetVariableShort(VID_AGENT_PORT);
2346
2347 // Change authentication method of native agent
2348 if (pRequest->IsVariableExist(VID_AUTH_METHOD))
2349 m_wAuthMethod = pRequest->GetVariableShort(VID_AUTH_METHOD);
2350
2351 // Change shared secret of native agent
2352 if (pRequest->IsVariableExist(VID_SHARED_SECRET))
2353 pRequest->GetVariableStr(VID_SHARED_SECRET, m_szSharedSecret, MAX_SECRET_LENGTH);
2354
2355 // Change SNMP protocol version
2356 if (pRequest->IsVariableExist(VID_SNMP_VERSION))
14b98b3a 2357 {
5d2c5741 2358 m_snmpVersion = pRequest->GetVariableShort(VID_SNMP_VERSION);
14b98b3a
VK
2359 m_snmpSecurity->setSecurityModel((m_snmpVersion == SNMP_VERSION_3) ? SNMP_SECURITY_MODEL_USM : SNMP_SECURITY_MODEL_V2C);
2360 }
5039dede 2361
65e2005b
VK
2362 // Change SNMP port
2363 if (pRequest->IsVariableExist(VID_SNMP_PORT))
2364 m_wSNMPPort = pRequest->GetVariableShort(VID_SNMP_PORT);
2365
4b7d8903
VK
2366 // Change SNMP authentication data
2367 if (pRequest->IsVariableExist(VID_SNMP_AUTH_OBJECT))
5d2c5741 2368 {
4b7d8903
VK
2369 pRequest->GetVariableStr(VID_SNMP_AUTH_OBJECT, buffer, 256);
2370 m_snmpSecurity->setAuthName(buffer);
2371
2372 pRequest->GetVariableStr(VID_SNMP_AUTH_PASSWORD, buffer, 256);
2373 m_snmpSecurity->setAuthPassword(buffer);
2374
2375 pRequest->GetVariableStr(VID_SNMP_PRIV_PASSWORD, buffer, 256);
2376 m_snmpSecurity->setPrivPassword(buffer);
2377
2378 WORD methods = pRequest->GetVariableShort(VID_SNMP_USM_METHODS);
2379 m_snmpSecurity->setAuthMethod((int)(methods & 0xFF));
2380 m_snmpSecurity->setPrivMethod((int)(methods >> 8));
5d2c5741 2381 }
5039dede
AK
2382
2383 // Change proxy node
2384 if (pRequest->IsVariableExist(VID_PROXY_NODE))
2385 m_dwProxyNode = pRequest->GetVariableLong(VID_PROXY_NODE);
2386
2387 // Change SNMP proxy node
2388 if (pRequest->IsVariableExist(VID_SNMP_PROXY))
2389 m_dwSNMPProxy = pRequest->GetVariableLong(VID_SNMP_PROXY);
2390
2391 // Number of required polls
2392 if (pRequest->IsVariableExist(VID_REQUIRED_POLLS))
2393 m_iRequiredPollCount = (int)pRequest->GetVariableShort(VID_REQUIRED_POLLS);
2394
2395 // Enable/disable usage of ifXTable
2396 if (pRequest->IsVariableExist(VID_USE_IFXTABLE))
2397 m_nUseIfXTable = (BYTE)pRequest->GetVariableShort(VID_USE_IFXTABLE);
2398
2399 // Change flags
2400 if (pRequest->IsVariableExist(VID_FLAGS))
2401 {
2402 m_dwFlags &= NF_SYSTEM_FLAGS;
2403 m_dwFlags |= pRequest->GetVariableLong(VID_FLAGS) & NF_USER_FLAGS;
2404 }
2405
2406 return Template::ModifyFromMessage(pRequest, TRUE);
2407}
2408
2409
2410//
2411// Wakeup node using magic packet
2412//
2413
7c521895 2414DWORD Node::wakeUp()
5039dede
AK
2415{
2416 DWORD i, dwResult = RCC_NO_WOL_INTERFACES;
2417
2418 LockChildList(FALSE);
2419
2420 for(i = 0; i < m_dwChildCount; i++)
2421 if ((m_pChildList[i]->Type() == OBJECT_INTERFACE) &&
2422 (m_pChildList[i]->Status() != STATUS_UNMANAGED) &&
2423 (m_pChildList[i]->IpAddr() != 0))
2424 {
7c521895 2425 dwResult = ((Interface *)m_pChildList[i])->wakeUp();
5039dede
AK
2426 break;
2427 }
2428
2429 UnlockChildList();
2430 return dwResult;
2431}
2432
2433
2434//
2435// Get status of interface with given index from SNMP agent
2436//
2437
58b3e451 2438int Node::getInterfaceStatusFromSNMP(SNMP_Transport *pTransport, DWORD dwIndex)
5039dede 2439{
5d2c5741 2440 return SnmpGetInterfaceStatus(m_snmpVersion, pTransport, dwIndex);
5039dede
AK
2441}
2442
2443
2444//
2445// Get status of interface with given index from native agent
2446//
2447
58b3e451 2448int Node::getInterfaceStatusFromAgent(DWORD dwIndex)
5039dede
AK
2449{
2450 char szParam[128], szBuffer[32];
2451 DWORD dwAdminStatus, dwLinkState;
2452 int iStatus;
2453
2454 // Get administrative status
2455 sprintf(szParam, "Net.Interface.AdminStatus(%u)", dwIndex);
2456 if (GetItemFromAgent(szParam, 32, szBuffer) == DCE_SUCCESS)
2457 {
2458 dwAdminStatus = strtoul(szBuffer, NULL, 0);
2459
2460 switch(dwAdminStatus)
2461 {
2462 case 3:
2463 iStatus = STATUS_TESTING;
2464 break;
2465 case 2:
2466 case 0: // Agents before 0.2.1 may return 0 instead of 2
2467 iStatus = STATUS_DISABLED;
2468 break;
2469 case 1: // Interface administratively up, check link state
2470 sprintf(szParam, "Net.Interface.Link(%u)", dwIndex);
2471 if (GetItemFromAgent(szParam, 32, szBuffer) == DCE_SUCCESS)
2472 {
2473 dwLinkState = strtoul(szBuffer, NULL, 0);
2474 iStatus = (dwLinkState == 0) ? STATUS_CRITICAL : STATUS_NORMAL;
2475 }
2476 else
2477 {
2478 iStatus = STATUS_UNKNOWN;
2479 }
2480 break;
2481 default:
2482 iStatus = STATUS_UNKNOWN;
2483 break;
2484 }
2485 }
2486 else
2487 {
2488 iStatus = STATUS_UNKNOWN;
2489 }
2490
2491 return iStatus;
2492}
2493
2494
2495//
2496// Put list of supported parameters into CSCP message
2497//
2498
2499void Node::WriteParamListToMessage(CSCPMessage *pMsg)
2500{
2501 DWORD i, dwId;
2502
2503 LockData();
2504 if (m_pParamList != NULL)
2505 {
2506 pMsg->SetVariable(VID_NUM_PARAMETERS, m_dwNumParams);
2507 for(i = 0, dwId = VID_PARAM_LIST_BASE; i < m_dwNumParams; i++)
2508 {
2509 pMsg->SetVariable(dwId++, m_pParamList[i].szName);
2510 pMsg->SetVariable(dwId++, m_pParamList[i].szDescription);
2511 pMsg->SetVariable(dwId++, (WORD)m_pParamList[i].iDataType);
2512 }
2513 DbgPrintf(6, _T("Node[%s]::WriteParamListToMessage(): sending %d parameters"), m_szName, m_dwNumParams);
2514 }
2515 else
2516 {
2517 DbgPrintf(6, _T("Node[%s]::WriteParamListToMessage(): m_pParamList == NULL"), m_szName);
2518 pMsg->SetVariable(VID_NUM_PARAMETERS, (DWORD)0);
2519 }
2520 UnlockData();
2521}
2522
2523
2524//
2525// Open list of supported parameters for reading
2526//
2527
2528void Node::OpenParamList(DWORD *pdwNumParams, NXC_AGENT_PARAM **ppParamList)
2529{
2530 LockData();
2531 *pdwNumParams = m_dwNumParams;
2532 *ppParamList = m_pParamList;
2533}
2534
2535
2536//
2537// Check status of network service
2538//
2539
2540DWORD Node::CheckNetworkService(DWORD *pdwStatus, DWORD dwIpAddr, int iServiceType,
2541 WORD wPort, WORD wProto, TCHAR *pszRequest,
2542 TCHAR *pszResponse)
2543{
2544 DWORD dwError = ERR_NOT_CONNECTED;
2545
2546 if ((m_dwFlags & NF_IS_NATIVE_AGENT) &&
2547 (!(m_dwDynamicFlags & NDF_AGENT_UNREACHABLE)) &&
2548 (!(m_dwDynamicFlags & NDF_UNREACHABLE)))
2549 {
2550 AgentConnection *pConn;
2551
cd9f247e 2552 pConn = createAgentConnection();
5039dede
AK
2553 if (pConn != NULL)
2554 {
2555 dwError = pConn->CheckNetworkService(pdwStatus, dwIpAddr, iServiceType,
2556 wPort, wProto, pszRequest, pszResponse);
7c521895 2557 pConn->disconnect();
5039dede
AK
2558 delete pConn;
2559 }
2560 }
2561 return dwError;
2562}
2563
2564
2565//
2566// Handler for object deletion
2567//
2568
2569void Node::OnObjectDelete(DWORD dwObjectId)
2570{
f5d16551 2571 LockData();
5039dede
AK
2572 if (dwObjectId == m_dwPollerNode)
2573 {
2574 // If deleted object is our poller node, change it to default
5039dede
AK
2575 m_dwPollerNode = 0;
2576 Modify();
2577 DbgPrintf(3, _T("Node \"%s\": poller node %d deleted"), m_szName, dwObjectId);
2578 }
f5d16551 2579 UnlockData();
5039dede
AK
2580}
2581
2582
2583//
2584// Check node for OSPF support
2585//
2586
2587void Node::CheckOSPFSupport(SNMP_Transport *pTransport)
2588{
2589 LONG nAdminStatus;
2590
5d2c5741 2591 if (SnmpGet(m_snmpVersion, pTransport,
5039dede
AK
2592 ".1.3.6.1.2.1.14.1.2.0", NULL, 0, &nAdminStatus, sizeof(LONG),
2593 FALSE, FALSE) == SNMP_ERR_SUCCESS)
2594 {
2595 LockData();
2596 if (nAdminStatus)
2597 {
2598 m_dwFlags |= NF_IS_OSPF;
2599 }
2600 else
2601 {
2602 m_dwFlags &= ~NF_IS_OSPF;
2603 }
2604 UnlockData();
2605 }
2606}
2607
2608
2609//
2610// Create ready to use agent connection
2611//
2612
cd9f247e 2613AgentConnectionEx *Node::createAgentConnection()
5039dede 2614{
45d84f8a 2615 AgentConnectionEx *conn;
5039dede
AK
2616
2617 if ((!(m_dwFlags & NF_IS_NATIVE_AGENT)) ||
6b2bb22c 2618 (m_dwFlags & NF_DISABLE_NXCP) ||
5039dede
AK
2619 (m_dwDynamicFlags & NDF_AGENT_UNREACHABLE) ||
2620 (m_dwDynamicFlags & NDF_UNREACHABLE))
2621 return NULL;
2622
45d84f8a
VK
2623 conn = new AgentConnectionEx(htonl(m_dwIpAddr), m_wAgentPort,
2624 m_wAuthMethod, m_szSharedSecret);
7c521895
VK
2625 setAgentProxy(conn);
2626 if (!conn->connect(g_pServerKey))
5039dede 2627 {
45d84f8a
VK
2628 delete conn;
2629 conn = NULL;
5039dede 2630 }
45d84f8a 2631 return conn;
5039dede
AK
2632}
2633
2634
2635//
2636// Get last collected values of all DCIs
2637//
2638
7c521895 2639DWORD Node::getLastValues(CSCPMessage *pMsg)
5039dede
AK
2640{
2641 DWORD i, dwId, dwCount;
2642
7c521895 2643 lockDciAccess();
5039dede
AK
2644
2645 for(i = 0, dwId = VID_DCI_VALUES_BASE, dwCount = 0; i < m_dwNumItems; i++)
2646 {
fb05c05b 2647 if (_tcsnicmp(m_ppItems[i]->getDescription(), _T("@system."), 8))
5039dede 2648 {
fb05c05b 2649 m_ppItems[i]->getLastValue(pMsg, dwId);
5039dede
AK
2650 dwId += 10;
2651 dwCount++;
2652 }
2653 }
2654 pMsg->SetVariable(VID_NUM_ITEMS, dwCount);
2655
7c521895 2656 unlockDciAccess();
5039dede
AK
2657 return RCC_SUCCESS;
2658}
2659
2660
2661//
2662// Clean expired DCI data
2663//
2664
7c521895 2665void Node::cleanDCIData()
5039dede
AK
2666{
2667 DWORD i;
2668
7c521895 2669 lockDciAccess();
5039dede 2670 for(i = 0; i < m_dwNumItems; i++)
fb05c05b 2671 m_ppItems[i]->deleteExpiredData();
7c521895 2672 unlockDciAccess();
5039dede
AK
2673}
2674
2675
2676//
2677// Apply DCI from template
2678// pItem passed to this method should be a template's DCI
2679//
2680
a2069340 2681BOOL Node::applyTemplateItem(DWORD dwTemplateId, DCItem *pItem)
5039dede
AK
2682{
2683 BOOL bResult = TRUE;
2684 DWORD i;
2685 DCItem *pNewItem;
2686
a2069340 2687 lockDciAccess(); // write lock
5039dede 2688
fb05c05b 2689 DbgPrintf(5, "Applying item \"%s\" to node \"%s\"", pItem->getName(), m_szName);
5039dede
AK
2690
2691 // Check if that template item exists
2692 for(i = 0; i < m_dwNumItems; i++)
fb05c05b
VK
2693 if ((m_ppItems[i]->getTemplateId() == dwTemplateId) &&
2694 (m_ppItems[i]->getTemplateItemId() == pItem->getId()))
5039dede
AK
2695 break; // Item with specified id already exist
2696
2697 if (i == m_dwNumItems)
2698 {
2699 // New item from template, just add it
2700 pNewItem = new DCItem(pItem);
fb05c05b
VK
2701 pNewItem->setTemplateId(dwTemplateId, pItem->getId());
2702 pNewItem->changeBinding(CreateUniqueId(IDG_ITEM), this, TRUE);
7c521895 2703 bResult = addItem(pNewItem, true);
5039dede
AK
2704 }
2705 else
2706 {
2707 // Update existing item
fb05c05b 2708 m_ppItems[i]->updateFromTemplate(pItem);
5039dede
AK
2709 }
2710
7c521895
VK
2711 unlockDciAccess();
2712
2713 if (bResult)
2714 {
2715 LockData();
2716 m_bIsModified = TRUE;
2717 UnlockData();
2718 }
5039dede
AK
2719 return bResult;
2720}
2721
2722
2723//
2724// Clean deleted template items from node's DCI list
2725// Arguments is template id and list of valid template item ids.
2726// all items related to given template and not presented in list should be deleted.
2727//
2728
a2069340 2729void Node::cleanDeletedTemplateItems(DWORD dwTemplateId, DWORD dwNumItems, DWORD *pdwItemList)
5039dede
AK
2730{
2731 DWORD i, j, dwNumDeleted, *pdwDeleteList;
2732
a2069340 2733 lockDciAccess(); // write lock
5039dede
AK
2734
2735 pdwDeleteList = (DWORD *)malloc(sizeof(DWORD) * m_dwNumItems);
2736 dwNumDeleted = 0;
2737
2738 for(i = 0; i < m_dwNumItems; i++)
fb05c05b 2739 if (m_ppItems[i]->getTemplateId() == dwTemplateId)
5039dede
AK
2740 {
2741 for(j = 0; j < dwNumItems; j++)
fb05c05b 2742 if (m_ppItems[i]->getTemplateItemId() == pdwItemList[j])
5039dede
AK
2743 break;
2744
2745 // Delete DCI if it's not in list
2746 if (j == dwNumItems)
fb05c05b 2747 pdwDeleteList[dwNumDeleted++] = m_ppItems[i]->getId();
5039dede
AK
2748 }
2749
2750 for(i = 0; i < dwNumDeleted; i++)
7c521895 2751 deleteItem(pdwDeleteList[i], false);
5039dede 2752
7c521895 2753 unlockDciAccess();
5039dede
AK
2754 free(pdwDeleteList);
2755}
2756
2757
2758//
2759// Unbind node from template, i.e either remove DCI association with template
2760// or remove these DCIs at all
2761//
2762
a2069340 2763void Node::unbindFromTemplate(DWORD dwTemplateId, BOOL bRemoveDCI)
5039dede 2764{
17b055bb 2765 DWORD i;
5039dede
AK
2766
2767 if (bRemoveDCI)
2768 {
17b055bb
VK
2769 DWORD *pdwDeleteList = (DWORD *)malloc(sizeof(DWORD) * m_dwNumItems);
2770 DWORD dwNumDeleted = 0;
5039dede 2771
a2069340 2772 lockDciAccess(); // write lock
5039dede
AK
2773
2774 for(i = 0; i < m_dwNumItems; i++)
fb05c05b 2775 if (m_ppItems[i]->getTemplateId() == dwTemplateId)
5039dede 2776 {
fb05c05b 2777 pdwDeleteList[dwNumDeleted++] = m_ppItems[i]->getId();
5039dede
AK
2778 }
2779
2780 for(i = 0; i < dwNumDeleted; i++)
7c521895 2781 deleteItem(pdwDeleteList[i], false);
5039dede 2782
7c521895 2783 unlockDciAccess();
17b055bb
VK
2784
2785 safe_free(pdwDeleteList);
5039dede
AK
2786 }
2787 else
2788 {
7c521895 2789 lockDciAccess();
5039dede
AK
2790
2791 for(i = 0; i < m_dwNumItems; i++)
fb05c05b 2792 if (m_ppItems[i]->getTemplateId() == dwTemplateId)
5039dede 2793 {
fb05c05b 2794 m_ppItems[i]->setTemplateId(0, 0);
5039dede
AK
2795 }
2796
7c521895 2797 unlockDciAccess();
5039dede
AK
2798 }
2799}
2800
2801
2802//
2803// Change node's IP address
2804//
2805
58b3e451 2806void Node::changeIPAddress(DWORD dwIpAddr)
5039dede
AK
2807{
2808 DWORD i;
2809
7c521895 2810 pollerLock();
5039dede
AK
2811
2812 LockData();
2813
2814 UpdateNodeIndex(m_dwIpAddr, dwIpAddr, this);
2815 m_dwIpAddr = dwIpAddr;
2816 m_dwDynamicFlags |= NDF_FORCE_CONFIGURATION_POLL | NDF_RECHECK_CAPABILITIES;
2817
2818 // Change status of node and all it's childs to UNKNOWN
2819 m_iStatus = STATUS_UNKNOWN;
2820 LockChildList(FALSE);
2821 for(i = 0; i < m_dwChildCount; i++)
2822 {
2823 m_pChildList[i]->ResetStatus();
2824 if (m_pChildList[i]->Type() == OBJECT_INTERFACE)
2825 {
2826 if (((Interface *)m_pChildList[i])->IsFake())
2827 {
2828 ((Interface *)m_pChildList[i])->SetIpAddr(dwIpAddr);
2829 }
2830 }
2831 }
2832 UnlockChildList();
2833
2834 Modify();
2835 UnlockData();
2836
7c521895 2837 agentLock();
5039dede 2838 delete_and_null(m_pAgentConnection);
7c521895 2839 agentUnlock();
5039dede 2840
7c521895 2841 pollerUnlock();
5039dede
AK
2842}
2843
2844
2845//
2846// Get number of interface objects and pointer to the last one
2847//
2848
7c521895 2849DWORD Node::getInterfaceCount(Interface **ppInterface)
5039dede
AK
2850{
2851 DWORD i, dwCount;
2852
2853 LockChildList(FALSE);
2854 for(i = 0, dwCount = 0; i < m_dwChildCount; i++)
2855 if (m_pChildList[i]->Type() == OBJECT_INTERFACE)
2856 {
2857 dwCount++;
2858 *ppInterface = (Interface *)m_pChildList[i];
2859 }
2860 UnlockChildList();
2861 return dwCount;
2862}
2863
2864
2865//
2866// Update cache for all DCI's
2867//
2868
a2069340 2869void Node::updateDciCache()
5039dede
AK
2870{
2871 DWORD i;
2872
a2069340 2873 lockDciAccess();
5039dede 2874 for(i = 0; i < m_dwNumItems; i++)
fb05c05b 2875 m_ppItems[i]->updateCacheSize();
a2069340 2876 unlockDciAccess();
5039dede
AK
2877}
2878
2879
2880//
2881// Get routing table from node
2882//
2883
58b3e451 2884ROUTING_TABLE *Node::getRoutingTable()
5039dede
AK
2885{
2886 ROUTING_TABLE *pRT = NULL;
2887
2888 if ((m_dwFlags & NF_IS_NATIVE_AGENT) && (!(m_dwFlags & NF_DISABLE_NXCP)))
2889 {
7c521895
VK
2890 agentLock();
2891 if (connectToAgent())
5039dede
AK
2892 {
2893 pRT = m_pAgentConnection->GetRoutingTable();
2894 }
7c521895 2895 agentUnlock();
5039dede
AK
2896 }
2897 if ((pRT == NULL) && (m_dwFlags & NF_IS_SNMP) && (!(m_dwFlags & NF_DISABLE_SNMP)))
2898 {
2899 SNMP_Transport *pTransport;
2900
cd9f247e 2901 pTransport = createSnmpTransport();
803d47be
VK
2902 if (pTransport != NULL)
2903 {
2904 pRT = SnmpGetRoutingTable(m_snmpVersion, pTransport);
2905 delete pTransport;
2906 }
5039dede
AK
2907 }
2908
2909 if (pRT != NULL)
2910 {
2911 SortRoutingTable(pRT);
2912 }
2913 return pRT;
2914}
2915
2916
2917//
2918// Get next hop for given destination address
2919//
2920
58b3e451 2921BOOL Node::getNextHop(DWORD dwSrcAddr, DWORD dwDestAddr, DWORD *pdwNextHop,
5039dede
AK
2922 DWORD *pdwIfIndex, BOOL *pbIsVPN)
2923{
2924 DWORD i;
2925 BOOL bResult = FALSE;
2926
2927 // Check VPN connectors
2928 LockChildList(FALSE);
2929 for(i = 0; i < m_dwChildCount; i++)
2930 if (m_pChildList[i]->Type() == OBJECT_VPNCONNECTOR)
2931 {
2932 if (((VPNConnector *)m_pChildList[i])->IsRemoteAddr(dwDestAddr) &&
2933 ((VPNConnector *)m_pChildList[i])->IsLocalAddr(dwSrcAddr))
2934 {
2935 *pdwNextHop = ((VPNConnector *)m_pChildList[i])->GetPeerGatewayAddr();
2936 *pdwIfIndex = m_pChildList[i]->Id();
2937 *pbIsVPN = TRUE;
2938 bResult = TRUE;
2939 break;
2940 }
2941 }
2942 UnlockChildList();
2943
2944 // Check routing table
2945 if (!bResult)
2946 {
7c521895 2947 routingTableLock();
5039dede
AK
2948 if (m_pRoutingTable != NULL)
2949 {
2950 for(i = 0; i < (DWORD)m_pRoutingTable->iNumEntries; i++)
2951 if ((dwDestAddr & m_pRoutingTable->pRoutes[i].dwDestMask) == m_pRoutingTable->pRoutes[i].dwDestAddr)
2952 {
2953 *pdwNextHop = m_pRoutingTable->pRoutes[i].dwNextHop;
2954 *pdwIfIndex = m_pRoutingTable->pRoutes[i].dwIfIndex;
2955 *pbIsVPN = FALSE;
2956 bResult = TRUE;
2957 break;
2958 }
2959 }
7c521895 2960 routingTableUnlock();
5039dede
AK
2961 }
2962
2963 return bResult;
2964}
2965
2966
2967//
2968// Update cached routing table
2969//
2970
58b3e451 2971void Node::updateRoutingTable()
5039dede
AK
2972{
2973 ROUTING_TABLE *pRT;
2974
58b3e451 2975 pRT = getRoutingTable();
5039dede
AK
2976 if (pRT != NULL)
2977 {
7c521895 2978 routingTableLock();
5039dede
AK
2979 DestroyRoutingTable(m_pRoutingTable);
2980 m_pRoutingTable = pRT;
7c521895 2981 routingTableUnlock();
5039dede
AK
2982 }
2983 m_tLastRTUpdate = time(NULL);
2984 m_dwDynamicFlags &= ~NDF_QUEUED_FOR_ROUTE_POLL;
2985}
2986
2987
2988//
2989// Call SNMP Enumerate with node's SNMP parameters
2990//
2991
2992DWORD Node::CallSnmpEnumerate(const char *pszRootOid,
5d2c5741 2993 DWORD (* pHandler)(DWORD, SNMP_Variable *, SNMP_Transport *, void *),
5039dede
AK
2994 void *pArg)
2995{
2996 if ((m_dwFlags & NF_IS_SNMP) &&
2997 (!(m_dwDynamicFlags & NDF_SNMP_UNREACHABLE)) &&
2998 (!(m_dwDynamicFlags & NDF_UNREACHABLE)))
2999 {
3000 SNMP_Transport *pTransport;
3001 DWORD dwResult;
3002
cd9f247e 3003 pTransport = createSnmpTransport();
803d47be
VK
3004 if (pTransport != NULL)
3005 {
3006 dwResult = SnmpEnumerate(m_snmpVersion, pTransport,
3007 pszRootOid, pHandler, pArg, FALSE);
3008 delete pTransport;
3009 }
3010 else
3011 {
3012 dwResult = SNMP_ERR_COMM;
3013 }
5039dede
AK
3014 return dwResult;
3015 }
3016 else
3017 {
3018 return SNMP_ERR_COMM;
3019 }
3020}
3021
3022
3023//
3024// Set proxy information for agent's connection
3025//
3026
7c521895 3027void Node::setAgentProxy(AgentConnection *pConn)
5039dede
AK
3028{
3029 if (m_dwProxyNode != 0)
3030 {
3031 Node *pNode;
3032
3033 pNode = (Node *)FindObjectById(m_dwProxyNode);
3034 if (pNode != NULL)
3035 {
7c521895 3036 pConn->setProxy(htonl(pNode->m_dwIpAddr), pNode->m_wAgentPort,
5039dede
AK
3037 pNode->m_wAuthMethod, pNode->m_szSharedSecret);
3038 }
3039 }
3040}
3041
3042
3043//
3044// Prepare node object for deletion
3045//
3046
3047void Node::PrepareForDeletion(void)
3048{
3049 // Prevent node from being queued for polling
3050 LockData();
3051 m_dwDynamicFlags |= NDF_POLLING_DISABLED;
3052 UnlockData();
3053
3054 // Wait for all pending polls
3055 while(1)
3056 {
3057 LockData();
3058 if ((m_dwDynamicFlags &
3059 (NDF_QUEUED_FOR_STATUS_POLL | NDF_QUEUED_FOR_CONFIG_POLL |
3060 NDF_QUEUED_FOR_DISCOVERY_POLL | NDF_QUEUED_FOR_ROUTE_POLL)) == 0)
3061 {
3062 UnlockData();
3063 break;
3064 }
3065 UnlockData();
3066 ThreadSleepMs(100);
3067 }
3068 Template::PrepareForDeletion();
3069}
3070
3071
3072//
3073// Check if specified SNMP variable set to specified value.
3074// If variable doesn't exist at all, will return FALSE
3075//
3076
3077BOOL Node::CheckSNMPIntegerValue(SNMP_Transport *pTransport, const char *pszOID, int nValue)
3078{
3079 DWORD dwTemp;
3080
5d2c5741
VK
3081 if (SnmpGet(m_snmpVersion, pTransport, pszOID, NULL, 0, &dwTemp,
3082 sizeof(DWORD), FALSE, FALSE) == SNMP_ERR_SUCCESS)
5039dede
AK
3083 return (int)dwTemp == nValue;
3084 return FALSE;
3085}
3086
3087
3088//
3089// Check and update if needed interface names
3090//
3091
3092void Node::CheckInterfaceNames(INTERFACE_LIST *pIfList)
3093{
3094 int i;
3095 TCHAR *ptr;
3096
3097 if ((m_dwNodeType == NODE_TYPE_NORTEL_BAYSTACK) ||
3098 (m_dwNodeType == NODE_TYPE_NORTEL_OPTERA))
3099 {
3100 // Translate interface names
3101 for(i = 0; i < pIfList->iNumEntries; i++)
3102 {
3103 if ((ptr = _tcsstr(pIfList->pInterfaces[i].szName, _T("- Port"))) != NULL)
3104 {
3105 ptr += 2;
3106 memmove(pIfList->pInterfaces[i].szName, ptr, _tcslen(ptr) + 1);
3107 }
3108 else if ((ptr = _tcsstr(pIfList->pInterfaces[i].szName, _T("- Unit"))) != NULL)
3109 {
3110 ptr += 2;
3111 memmove(pIfList->pInterfaces[i].szName, ptr, _tcslen(ptr) + 1);
3112 }
3113 else if ((_tcsstr(pIfList->pInterfaces[i].szName, _T("BayStack")) != NULL) ||
3114 (_tcsstr(pIfList->pInterfaces[i].szName, _T("Nortel Ethernet Switch")) != NULL))
3115 {
3116 ptr = _tcsrchr(pIfList->pInterfaces[i].szName, _T('-'));
3117 if (ptr != NULL)
3118 {
3119 ptr++;
3120 while(*ptr == _T(' '))
3121 ptr++;
3122 memmove(pIfList->pInterfaces[i].szName, ptr, _tcslen(ptr) + 1);
3123 }
3124 }
3125 StrStrip(pIfList->pInterfaces[i].szName);
3126 }
3127 }
3128
3129 // Cut interface names to MAX_OBJECT_NAME and check for unnamed interfaces
3130 for(i = 0; i < pIfList->iNumEntries; i++)
3131 {
3132 pIfList->pInterfaces[i].szName[MAX_OBJECT_NAME - 1] = 0;
3133 if (pIfList->pInterfaces[i].szName[0] == 0)
3134 _stprintf(pIfList->pInterfaces[i].szName, _T("%d"), pIfList->pInterfaces[i].dwIndex);
3135 }
3136}
3137
3138
3139//
3140// Get cluster object this node belongs to, if any
3141//
3142
7c521895 3143Cluster *Node::getMyCluster()
5039dede
AK
3144{
3145 DWORD i;
3146 Cluster *pCluster = NULL;
3147
3148 LockParentList(FALSE);
3149 for(i = 0; i < m_dwParentCount; i++)
3150 if (m_pParentList[i]->Type() == OBJECT_CLUSTER)
3151 {
3152 pCluster = (Cluster *)m_pParentList[i];
3153 break;
3154 }
3155 UnlockParentList();
3156 return pCluster;
3157}
3158
3159
3160//
3161// Create SNMP transport
3162//
3163
65e2005b 3164SNMP_Transport *Node::createSnmpTransport(WORD port)
5039dede
AK
3165{
3166 SNMP_Transport *pTransport = NULL;
3167
3168 if (m_dwSNMPProxy == 0)
3169 {
3170 pTransport = new SNMP_UDPTransport;
65e2005b 3171 ((SNMP_UDPTransport *)pTransport)->createUDPTransport(NULL, htonl(m_dwIpAddr), (port != 0) ? port : m_wSNMPPort);
5039dede
AK
3172 }
3173 else
3174 {
3175 NetObj *pObject;
3176
3177 pObject = FindObjectById(m_dwSNMPProxy);
3178 if (pObject != NULL)
3179 {
3180 if (pObject->Type() == OBJECT_NODE)
3181 {
3182 AgentConnection *pConn;
3183
cd9f247e 3184 pConn = ((Node *)pObject)->createAgentConnection();
5039dede
AK
3185 if (pConn != NULL)
3186 {
65e2005b 3187 pTransport = new SNMP_ProxyTransport(pConn, m_dwIpAddr, (port != 0) ? port : m_wSNMPPort);
5039dede
AK
3188 }
3189 }
3190 }
3191 }
5d2c5741
VK
3192
3193 // Set security
3194 if (pTransport != NULL)
3195 {
df8a4ca2 3196 LockData();
5d2c5741 3197 pTransport->setSecurityContext(new SNMP_SecurityContext(m_snmpSecurity));
df8a4ca2 3198 UnlockData();
5d2c5741 3199 }
5039dede
AK
3200 return pTransport;
3201}
cd9f247e
VK
3202
3203
3204//
3205// Get SNMP security context
3206// ATTENTION: This method returns new copy of security context
3207// which must be destroyed by the caller
3208//
3209
3210SNMP_SecurityContext *Node::getSnmpSecurityContext()
3211{
3212 LockData();
3213 SNMP_SecurityContext *ctx = new SNMP_SecurityContext(m_snmpSecurity);
3214 UnlockData();
3215 return ctx;
3216}
5039dede
AK
3217
3218
3219//
3220// Resolve node's name
3221//
3222
3223BOOL Node::ResolveName(BOOL useOnlyDNS)
3224{
3225 BOOL bSuccess = FALSE;
3226 HOSTENT *hs;
3227 DWORD i, dwAddr;
3228 TCHAR szBuffer[256];
3229
3230 DbgPrintf(4, _T("Resolving name for node %d [%s]..."), m_dwId, m_szName);
3231
3232 // Try to resolve primary IP
3233 dwAddr = htonl(m_dwIpAddr);
3234 hs = gethostbyaddr((const char *)&dwAddr, 4, AF_INET);
3235 if (hs != NULL)
3236 {
3237 nx_strncpy(m_szName, hs->h_name, MAX_OBJECT_NAME);
3238 bSuccess = TRUE;
3239 }
3240 else
3241 {
3242 // Try to resolve each interface's IP address
3243 LockChildList(FALSE);
3244 for(i = 0; i < m_dwChildCount; i++)
3245 {
3246 if (m_pChildList[i]->Type() == OBJECT_INTERFACE)
3247 {
3248 dwAddr = htonl(m_pChildList[i]->IpAddr());
3249 if (dwAddr != 0)
3250 {
3251 hs = gethostbyaddr((const char *)&dwAddr, 4, AF_INET);
3252 if (hs != NULL)
3253 {
3254 nx_strncpy(m_szName, hs->h_name, MAX_OBJECT_NAME);
3255 bSuccess = TRUE;
3256 break;
3257 }
3258 }
3259 }
3260 }
3261 UnlockChildList();
3262
3263 // Try to get hostname from agent if address resolution fails
3264 if (!(bSuccess || useOnlyDNS))
3265 {
3266 DbgPrintf(4, _T("Resolving name for node %d [%s] via agent..."), m_dwId, m_szName);
3267 if (GetItemFromAgent("System.Hostname", 256, szBuffer) == DCE_SUCCESS)
3268 {
3269 StrStrip(szBuffer);
3270 if (szBuffer[0] != 0)
3271 {
3272 nx_strncpy(m_szName, szBuffer, MAX_OBJECT_NAME);
3273 bSuccess = TRUE;
3274 }
3275 }
3276 }
3277
3278 // Try to get hostname from SNMP if other methods fails
3279 if (!(bSuccess || useOnlyDNS))
3280 {
3281 DbgPrintf(4, _T("Resolving name for node %d [%s] via SNMP..."), m_dwId, m_szName);
65e2005b 3282 if (GetItemFromSNMP(0, ".1.3.6.1.2.1.1.5.0", 256, szBuffer) == DCE_SUCCESS)
5039dede
AK
3283 {
3284 StrStrip(szBuffer);
3285 if (szBuffer[0] != 0)
3286 {
3287 nx_strncpy(m_szName, szBuffer, MAX_OBJECT_NAME);
3288 bSuccess = TRUE;
3289 }
3290 }
3291 }
3292 }
3293
3294 if (bSuccess)
3295 DbgPrintf(4, _T("Name for node %d was resolved to %s"), m_dwId, m_szName);
3296 else
3297 DbgPrintf(4, _T("Name for node %d was not resolved"), m_dwId, m_szName);
3298 return bSuccess;
3299}
3300
3301
3302//
3303// Send list of system DCIs
3304//
3305
74526d25 3306DWORD Node::getPerfTabDCIList(CSCPMessage *pMsg)
5039dede
AK
3307{
3308 DWORD i, dwId, dwCount;
3309
3310 LockData();
3311
3312 for(i = 0, dwId = VID_SYSDCI_LIST_BASE, dwCount = 0; i < m_dwNumItems; i++)
3313 {
74526d25
VK
3314 if (!_tcsnicmp(m_ppItems[i]->getDescription(), _T("@System."), 8) ||
3315 (m_ppItems[i]->getPerfTabSettings() != NULL))
5039dede 3316 {
fb05c05b
VK
3317 pMsg->SetVariable(dwId++, m_ppItems[i]->getId());
3318 pMsg->SetVariable(dwId++, (TCHAR *)m_ppItems[i]->getDescription());
3319 pMsg->SetVariable(dwId++, (WORD)m_ppItems[i]->getStatus());
e76d8b6f
VK
3320 if (m_ppItems[i]->getPerfTabSettings() != NULL)
3321 {
3322 pMsg->SetVariable(dwId++, m_ppItems[i]->getPerfTabSettings());
3323 dwId += 6;
3324 }
3325 else
3326 {
3327 dwId += 7;
3328 }
5039dede
AK
3329 dwCount++;
3330 }
3331 }
3332 pMsg->SetVariable(VID_NUM_ITEMS, dwCount);
3333
3334 UnlockData();
3335 return RCC_SUCCESS;
3336}
3337
3338
3339//
3340// Get current layer 2 topology (as dynamically created list which should be destroyed by caller)
3341// Will return NULL if there are no topology information or it is expired
3342//
3343
3344nxmap_ObjList *Node::GetL2Topology(void)
3345{
3346 nxmap_ObjList *pResult;
3347 DWORD dwExpTime;
3348
3349 dwExpTime = ConfigReadULong(_T("TopologyExpirationTime"), 900);
3350 MutexLock(m_mutexTopoAccess, INFINITE);
3351 if ((m_pTopology == NULL) || (m_tLastTopologyPoll + (time_t)dwExpTime < time(NULL)))
3352 {
3353 pResult = NULL;
3354 }
3355 else
3356 {
3357 pResult = new nxmap_ObjList(m_pTopology);
3358 }
3359 MutexUnlock(m_mutexTopoAccess);
3360 return pResult;
3361}
3362
3363
3364//
3365// Rebuild layer 2 topology and return it as dynamically reated list which should be destroyed by caller
3366//
3367
3368nxmap_ObjList *Node::BuildL2Topology(DWORD *pdwStatus)
3369{
3370 nxmap_ObjList *pResult;
3371 int nDepth;
3372
3373 nDepth = ConfigReadInt(_T("TopologyDiscoveryRadius"), 5);
3374 MutexLock(m_mutexTopoAccess, INFINITE);
3375 delete m_pTopology;
3376 if ((m_dwFlags & NF_IS_CDP) || (m_dwFlags & NF_IS_SONMP) || (m_dwFlags & NF_IS_LLDP))
3377 {
3378 m_pTopology = new nxmap_ObjList;
3379 if ((*pdwStatus = ::BuildL2Topology(*m_pTopology, this, NULL, nDepth, NULL)) == RCC_SUCCESS)
3380 {
3381 m_tLastTopologyPoll = time(NULL);
3382 pResult = new nxmap_ObjList(m_pTopology);
3383 }
3384 else
3385 {
3386 delete_and_null(m_pTopology);
3387 pResult = NULL;
3388 }
3389 }
3390 else
3391 {
3392 pResult = NULL;
3393 m_pTopology = NULL;
3394 *pdwStatus = RCC_NO_L2_TOPOLOGY_SUPPORT;
3395 }
3396 MutexUnlock(m_mutexTopoAccess);
3397 return pResult;
3398}
3399
3400
3401//
3402// Check subnet bindings
3403//
3404
3405void Node::CheckSubnetBinding(INTERFACE_LIST *pIfList)
3406{
3407 Subnet *pSubnet;
3408 Interface *pInterface;
3409 Cluster *pCluster;
3410 NetObj **ppUnlinkList;
3411 int i, j, count;
3412 BOOL isSync;
3413
7c521895 3414 pCluster = getMyCluster();
5039dede
AK
3415
3416 // Check if we have subnet bindings for all interfaces
3417 for(i = 0; i < pIfList->iNumEntries; i++)
3418 {
3419 if (pIfList->pInterfaces[i].dwIpAddr != 0)
3420 {
58b3e451 3421 pInterface = findInterface(pIfList->pInterfaces[i].dwIndex, pIfList->pInterfaces[i].dwIpAddr);
5039dede
AK
3422 if (pInterface == NULL)
3423 {
3424 nxlog_write(MSG_INTERNAL_ERROR, EVENTLOG_WARNING_TYPE, "s", _T("Cannot find interface object in Node::CheckSubnetBinding()"));
3425 break; // Something goes really wrong
3426 }
3427
3428 // Is cluster interconnect interface?
58b3e451 3429 isSync = (pCluster != NULL) ? pCluster->isSyncAddr(pInterface->IpAddr()) : FALSE;
5039dede
AK
3430
3431 pSubnet = FindSubnetForNode(pIfList->pInterfaces[i].dwIpAddr);
3432 if (pSubnet != NULL)
3433 {
3434 if (isSync)
3435 {
3436 pSubnet = NULL; // No further checks on this subnet
3437 }
3438 else
3439 {
3440 if (pSubnet->IsSyntheticMask())
3441 {
3442 DbgPrintf(4, _T("Setting correct netmask for subnet %s [%d] from node %s [%d]"),
3443 pSubnet->Name(), pSubnet->Id(), m_szName, m_dwId);
3444 pSubnet->SetCorrectMask(pInterface->IpAddr() & pInterface->IpNetMask(), pInterface->IpNetMask());
3445 }
3446 }
3447 }
3448 else if (!isSync)
3449 {
3450 // Create subnet
3451 pSubnet = new Subnet(pIfList->pInterfaces[i].dwIpAddr & pIfList->pInterfaces[i].dwIpNetMask,
3452 pIfList->pInterfaces[i].dwIpNetMask, m_dwZoneGUID, FALSE);
3453 NetObjInsert(pSubnet, TRUE);
3454 g_pEntireNet->AddSubnet(pSubnet);
3455 pSubnet->AddNode(this);
3456 DbgPrintf(4, _T("Node::CheckSubnetBinding(): Creating new subnet %s [%d] for node %s [%d]"),
3457 pSubnet->Name(), pSubnet->Id(), m_szName, m_dwId);
3458 }
3459
3460 // Check if subnet mask is correct on interface
3461 if ((pSubnet != NULL) && (pSubnet->IpNetMask() != pIfList->pInterfaces[i].dwIpNetMask))
3462 {
3463 PostEvent(EVENT_INCORRECT_NETMASK, m_dwId, "idsaa", pInterface->Id(),
3464 pInterface->IfIndex(), pInterface->Name(),
3465 pInterface->IpNetMask(), pSubnet->IpNetMask());
3466 }
3467 }
3468 }
3469
3470 // Check if we have incorrect subnets as parents
3471 LockParentList(FALSE);
3472 LockChildList(FALSE);
3473 ppUnlinkList = (NetObj **)malloc(sizeof(NetObj *) * m_dwParentCount);
3474 for(i = 0, count = 0; i < (int)m_dwParentCount; i++)
3475 {
3476 if (m_pParentList[i]->Type() == OBJECT_SUBNET)
3477 {
3478 pSubnet = (Subnet *)m_pParentList[i];
3479 for(j = 0; j < (int)m_dwChildCount; j++)
3480 {
3481 if (m_pChildList[j]->Type() == OBJECT_INTERFACE)
3482 {
3483 if (pSubnet->IpAddr() == (m_pChildList[j]->IpAddr() & pSubnet->IpNetMask()))
3484 {
3485 if (pCluster != NULL)
3486 {
58b3e451 3487 if (pCluster->isSyncAddr(m_pChildList[j]->IpAddr()))
5039dede
AK
3488 {
3489 j = (int)m_dwChildCount; // Cause to unbind from this subnet
3490 }
3491 }
3492 break;
3493 }
3494 }
3495 }
3496 if (j == (int)m_dwChildCount)
3497 {
3498 DbgPrintf(4, _T("Node::CheckSubnetBinding(): Subnet %s [%d] is incorrect for node %s [%d]"),
3499 pSubnet->Name(), pSubnet->Id(), m_szName, m_dwId);
3500 ppUnlinkList[count++] = pSubnet;
3501 }
3502 }
3503 }
3504 UnlockChildList();
3505 UnlockParentList();
3506
3507 // Unlink for incorrect subnet objects
3508 for(i = 0; i < count; i++)
3509 {
3510 ppUnlinkList[i]->DeleteChild(this);
3511 DeleteParent(ppUnlinkList[i]);
3512 }
3513 safe_free(ppUnlinkList);
3514}
3515
3516
3517//
3518// Update interface names
3519//
3520
58b3e451 3521void Node::updateInterfaceNames(ClientSession *pSession, DWORD dwRqId)
5039dede
AK
3522{
3523 INTERFACE_LIST *pIfList;
3524 DWORD i;
3525 int j;
3526
7c521895 3527 pollerLock();
5039dede
AK
3528 m_pPollRequestor = pSession;
3529 SendPollerMsg(dwRqId, _T("Starting interface names poll for node %s\r\n"), m_szName);
3530 DbgPrintf(4, "Starting interface names poll for node %s (ID: %d)", m_szName, m_dwId);
3531
3532 // Retrieve interface list
58b3e451 3533 pIfList = getInterfaceList();
5039dede
AK
3534 if (pIfList != NULL)
3535 {
3536 // Check names of existing interfaces
3537 for(j = 0; j < pIfList->iNumEntries; j++)
3538 {
3539 LockChildList(FALSE);
3540 for(i = 0; i < m_dwChildCount; i++)
3541 {
3542 if (m_pChildList[i]->Type() == OBJECT_INTERFACE)
3543 {
3544 Interface *pInterface = (Interface *)m_pChildList[i];
3545
3546 if (pIfList->pInterfaces[j].dwIndex == pInterface->IfIndex())
3547 {
3548 SendPollerMsg(dwRqId, _T(" Checking interface %d (%s)\r\n"), pInterface->IfIndex(), pInterface->Name());
3549 if (strcmp(pIfList->pInterfaces[j].szName, pInterface->Name()))
3550 {
3551 pInterface->SetName(pIfList->pInterfaces[j].szName);
3552 SendPollerMsg(dwRqId, POLLER_WARNING _T(" Name of interface %d changed to %s\r\n"), pInterface->IfIndex(), pIfList->pInterfaces[j].szName);
3553 }
3554 break;
3555 }
3556 }
3557 }
3558 UnlockChildList();
3559 }
3560
3561 DestroyInterfaceList(pIfList);
3562 }
3563 else /* pIfList == NULL */
3564 {
3565 SendPollerMsg(dwRqId, POLLER_ERROR _T(" Unable to get interface list from node\r\n"));
3566 }
3567
3568 // Finish poll
3569 SendPollerMsg(dwRqId, _T("Finished interface names poll for node %s\r\n"), m_szName);
7c521895 3570 pollerUnlock();
5039dede
AK
3571 DbgPrintf(4, "Finished interface names poll for node %s (ID: %d)", m_szName, m_dwId);
3572}
a2069340
VK
3573
3574
3575//
3576// Process new DCI value
3577//
3578
3579void Node::processNewDciValue(DCItem *item, time_t currTime, const TCHAR *value)
3580{
3581 lockDciAccess();
3582 item->processNewValue(currTime, value);
3583 unlockDciAccess();
3584}
501b7b03
VK
3585
3586
3587//
3588// Get list of parent objects for NXSL script
3589//
3590
3591NXSL_Array *Node::getParentsForNXSL()
3592{
3593 NXSL_Array *parents = new NXSL_Array;
3594 int index = 0;
3595
3596 LockParentList(FALSE);
3597 for(DWORD i = 0; i < m_dwParentCount; i++)
3598 {
3599 if (((m_pParentList[i]->Type() == OBJECT_CONTAINER) ||
3600 (m_pParentList[i]->Type() == OBJECT_CLUSTER) ||
3601 (m_pParentList[i]->Type() == OBJECT_SUBNET) ||
3602 (m_pParentList[i]->Type() == OBJECT_SERVICEROOT)) &&
3603 m_pParentList[i]->IsTrustedNode(m_dwId))
3604 {
541a3ebc 3605 parents->set(index++, new NXSL_Value(new NXSL_Object(&g_nxslNetObjClass, m_pParentList[i])));
501b7b03
VK
3606 }
3607 }
3608 UnlockParentList();
3609
3610 return parents;
3611}