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