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