fixed bug in mib parser
[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);
2195 pMsg->SetVariable(VID_AGENT_PORT, m_wAgentPort);
2196 pMsg->SetVariable(VID_AUTH_METHOD, m_wAuthMethod);
2197 pMsg->SetVariable(VID_SHARED_SECRET, m_szSharedSecret);
4b7d8903
VK
2198 pMsg->SetVariable(VID_SNMP_AUTH_OBJECT, m_snmpSecurity->getCommunity());
2199 pMsg->SetVariable(VID_SNMP_AUTH_PASSWORD, m_snmpSecurity->getAuthPassword());
2200 pMsg->SetVariable(VID_SNMP_PRIV_PASSWORD, m_snmpSecurity->getPrivPassword());
2201 pMsg->SetVariable(VID_SNMP_USM_METHODS, (WORD)((WORD)m_snmpSecurity->getAuthMethod() | ((WORD)m_snmpSecurity->getPrivMethod() << 8)));
5039dede
AK
2202 pMsg->SetVariable(VID_SNMP_OID, m_szObjectId);
2203 pMsg->SetVariable(VID_NODE_TYPE, m_dwNodeType);
5d2c5741 2204 pMsg->SetVariable(VID_SNMP_VERSION, (WORD)m_snmpVersion);
5039dede
AK
2205 pMsg->SetVariable(VID_AGENT_VERSION, m_szAgentVersion);
2206 pMsg->SetVariable(VID_PLATFORM_NAME, m_szPlatformName);
2207 pMsg->SetVariable(VID_POLLER_NODE_ID, m_dwPollerNode);
2208 pMsg->SetVariable(VID_ZONE_GUID, m_dwZoneGUID);
2209 pMsg->SetVariable(VID_PROXY_NODE, m_dwProxyNode);
2210 pMsg->SetVariable(VID_SNMP_PROXY, m_dwSNMPProxy);
2211 pMsg->SetVariable(VID_REQUIRED_POLLS, (WORD)m_iRequiredPollCount);
2212 pMsg->SetVariable(VID_SYS_DESCRIPTION, m_szSysDescription);
2213 pMsg->SetVariable(VID_USE_IFXTABLE, (WORD)m_nUseIfXTable);
2214}
2215
2216
2217//
2218// Modify object from message
2219//
2220
2221DWORD Node::ModifyFromMessage(CSCPMessage *pRequest, BOOL bAlreadyLocked)
2222{
5d2c5741
VK
2223 TCHAR buffer[256];
2224
5039dede
AK
2225 if (!bAlreadyLocked)
2226 LockData();
2227
2228 // Change primary IP address
2229 if (pRequest->IsVariableExist(VID_IP_ADDRESS))
2230 {
2231 DWORD i, dwIpAddr;
2232
2233 dwIpAddr = pRequest->GetVariableLong(VID_IP_ADDRESS);
2234
2235 // Check if received IP address is one of node's interface addresses
2236 LockChildList(FALSE);
2237 for(i = 0; i < m_dwChildCount; i++)
2238 if ((m_pChildList[i]->Type() == OBJECT_INTERFACE) &&
2239 (m_pChildList[i]->IpAddr() == dwIpAddr))
2240 break;
2241 UnlockChildList();
2242 if (i == m_dwChildCount)
2243 {
2244 UnlockData();
2245 return RCC_INVALID_IP_ADDR;
2246 }
2247
2248 UpdateNodeIndex(m_dwIpAddr, dwIpAddr, this);
2249 m_dwIpAddr = dwIpAddr;
2250 }
2251
2252 // Poller node ID
2253 if (pRequest->IsVariableExist(VID_POLLER_NODE_ID))
2254 {
2255 DWORD dwNodeId;
2256 NetObj *pObject;
2257
2258 dwNodeId = pRequest->GetVariableLong(VID_POLLER_NODE_ID);
2259 pObject = FindObjectById(dwNodeId);
2260
2261 // Check if received id is a valid node id
2262 if (pObject == NULL)
2263 {
2264 UnlockData();
2265 return RCC_INVALID_OBJECT_ID;
2266 }
2267 if (pObject->Type() != OBJECT_NODE)
2268 {
2269 UnlockData();
2270 return RCC_INVALID_OBJECT_ID;
2271 }
2272
2273 m_dwPollerNode = dwNodeId;
2274 }
2275
2276 // Change listen port of native agent
2277 if (pRequest->IsVariableExist(VID_AGENT_PORT))
2278 m_wAgentPort = pRequest->GetVariableShort(VID_AGENT_PORT);
2279
2280 // Change authentication method of native agent
2281 if (pRequest->IsVariableExist(VID_AUTH_METHOD))
2282 m_wAuthMethod = pRequest->GetVariableShort(VID_AUTH_METHOD);
2283
2284 // Change shared secret of native agent
2285 if (pRequest->IsVariableExist(VID_SHARED_SECRET))
2286 pRequest->GetVariableStr(VID_SHARED_SECRET, m_szSharedSecret, MAX_SECRET_LENGTH);
2287
2288 // Change SNMP protocol version
2289 if (pRequest->IsVariableExist(VID_SNMP_VERSION))
14b98b3a 2290 {
5d2c5741 2291 m_snmpVersion = pRequest->GetVariableShort(VID_SNMP_VERSION);
14b98b3a
VK
2292 m_snmpSecurity->setSecurityModel((m_snmpVersion == SNMP_VERSION_3) ? SNMP_SECURITY_MODEL_USM : SNMP_SECURITY_MODEL_V2C);
2293 }
5039dede 2294
4b7d8903
VK
2295 // Change SNMP authentication data
2296 if (pRequest->IsVariableExist(VID_SNMP_AUTH_OBJECT))
5d2c5741 2297 {
4b7d8903
VK
2298 pRequest->GetVariableStr(VID_SNMP_AUTH_OBJECT, buffer, 256);
2299 m_snmpSecurity->setAuthName(buffer);
2300
2301 pRequest->GetVariableStr(VID_SNMP_AUTH_PASSWORD, buffer, 256);
2302 m_snmpSecurity->setAuthPassword(buffer);
2303
2304 pRequest->GetVariableStr(VID_SNMP_PRIV_PASSWORD, buffer, 256);
2305 m_snmpSecurity->setPrivPassword(buffer);
2306
2307 WORD methods = pRequest->GetVariableShort(VID_SNMP_USM_METHODS);
2308 m_snmpSecurity->setAuthMethod((int)(methods & 0xFF));
2309 m_snmpSecurity->setPrivMethod((int)(methods >> 8));
5d2c5741 2310 }
5039dede
AK
2311
2312 // Change proxy node
2313 if (pRequest->IsVariableExist(VID_PROXY_NODE))
2314 m_dwProxyNode = pRequest->GetVariableLong(VID_PROXY_NODE);
2315
2316 // Change SNMP proxy node
2317 if (pRequest->IsVariableExist(VID_SNMP_PROXY))
2318 m_dwSNMPProxy = pRequest->GetVariableLong(VID_SNMP_PROXY);
2319
2320 // Number of required polls
2321 if (pRequest->IsVariableExist(VID_REQUIRED_POLLS))
2322 m_iRequiredPollCount = (int)pRequest->GetVariableShort(VID_REQUIRED_POLLS);
2323
2324 // Enable/disable usage of ifXTable
2325 if (pRequest->IsVariableExist(VID_USE_IFXTABLE))
2326 m_nUseIfXTable = (BYTE)pRequest->GetVariableShort(VID_USE_IFXTABLE);
2327
2328 // Change flags
2329 if (pRequest->IsVariableExist(VID_FLAGS))
2330 {
2331 m_dwFlags &= NF_SYSTEM_FLAGS;
2332 m_dwFlags |= pRequest->GetVariableLong(VID_FLAGS) & NF_USER_FLAGS;
2333 }
2334
2335 return Template::ModifyFromMessage(pRequest, TRUE);
2336}
2337
2338
2339//
2340// Wakeup node using magic packet
2341//
2342
2343DWORD Node::WakeUp(void)
2344{
2345 DWORD i, dwResult = RCC_NO_WOL_INTERFACES;
2346
2347 LockChildList(FALSE);
2348
2349 for(i = 0; i < m_dwChildCount; i++)
2350 if ((m_pChildList[i]->Type() == OBJECT_INTERFACE) &&
2351 (m_pChildList[i]->Status() != STATUS_UNMANAGED) &&
2352 (m_pChildList[i]->IpAddr() != 0))
2353 {
2354 dwResult = ((Interface *)m_pChildList[i])->WakeUp();
2355 break;
2356 }
2357
2358 UnlockChildList();
2359 return dwResult;
2360}
2361
2362
2363//
2364// Get status of interface with given index from SNMP agent
2365//
2366
2367int Node::GetInterfaceStatusFromSNMP(SNMP_Transport *pTransport, DWORD dwIndex)
2368{
5d2c5741 2369 return SnmpGetInterfaceStatus(m_snmpVersion, pTransport, dwIndex);
5039dede
AK
2370}
2371
2372
2373//
2374// Get status of interface with given index from native agent
2375//
2376
2377int Node::GetInterfaceStatusFromAgent(DWORD dwIndex)
2378{
2379 char szParam[128], szBuffer[32];
2380 DWORD dwAdminStatus, dwLinkState;
2381 int iStatus;
2382
2383 // Get administrative status
2384 sprintf(szParam, "Net.Interface.AdminStatus(%u)", dwIndex);
2385 if (GetItemFromAgent(szParam, 32, szBuffer) == DCE_SUCCESS)
2386 {
2387 dwAdminStatus = strtoul(szBuffer, NULL, 0);
2388
2389 switch(dwAdminStatus)
2390 {
2391 case 3:
2392 iStatus = STATUS_TESTING;
2393 break;
2394 case 2:
2395 case 0: // Agents before 0.2.1 may return 0 instead of 2
2396 iStatus = STATUS_DISABLED;
2397 break;
2398 case 1: // Interface administratively up, check link state
2399 sprintf(szParam, "Net.Interface.Link(%u)", dwIndex);
2400 if (GetItemFromAgent(szParam, 32, szBuffer) == DCE_SUCCESS)
2401 {
2402 dwLinkState = strtoul(szBuffer, NULL, 0);
2403 iStatus = (dwLinkState == 0) ? STATUS_CRITICAL : STATUS_NORMAL;
2404 }
2405 else
2406 {
2407 iStatus = STATUS_UNKNOWN;
2408 }
2409 break;
2410 default:
2411 iStatus = STATUS_UNKNOWN;
2412 break;
2413 }
2414 }
2415 else
2416 {
2417 iStatus = STATUS_UNKNOWN;
2418 }
2419
2420 return iStatus;
2421}
2422
2423
2424//
2425// Put list of supported parameters into CSCP message
2426//
2427
2428void Node::WriteParamListToMessage(CSCPMessage *pMsg)
2429{
2430 DWORD i, dwId;
2431
2432 LockData();
2433 if (m_pParamList != NULL)
2434 {
2435 pMsg->SetVariable(VID_NUM_PARAMETERS, m_dwNumParams);
2436 for(i = 0, dwId = VID_PARAM_LIST_BASE; i < m_dwNumParams; i++)
2437 {
2438 pMsg->SetVariable(dwId++, m_pParamList[i].szName);
2439 pMsg->SetVariable(dwId++, m_pParamList[i].szDescription);
2440 pMsg->SetVariable(dwId++, (WORD)m_pParamList[i].iDataType);
2441 }
2442 DbgPrintf(6, _T("Node[%s]::WriteParamListToMessage(): sending %d parameters"), m_szName, m_dwNumParams);
2443 }
2444 else
2445 {
2446 DbgPrintf(6, _T("Node[%s]::WriteParamListToMessage(): m_pParamList == NULL"), m_szName);
2447 pMsg->SetVariable(VID_NUM_PARAMETERS, (DWORD)0);
2448 }
2449 UnlockData();
2450}
2451
2452
2453//
2454// Open list of supported parameters for reading
2455//
2456
2457void Node::OpenParamList(DWORD *pdwNumParams, NXC_AGENT_PARAM **ppParamList)
2458{
2459 LockData();
2460 *pdwNumParams = m_dwNumParams;
2461 *ppParamList = m_pParamList;
2462}
2463
2464
2465//
2466// Check status of network service
2467//
2468
2469DWORD Node::CheckNetworkService(DWORD *pdwStatus, DWORD dwIpAddr, int iServiceType,
2470 WORD wPort, WORD wProto, TCHAR *pszRequest,
2471 TCHAR *pszResponse)
2472{
2473 DWORD dwError = ERR_NOT_CONNECTED;
2474
2475 if ((m_dwFlags & NF_IS_NATIVE_AGENT) &&
2476 (!(m_dwDynamicFlags & NDF_AGENT_UNREACHABLE)) &&
2477 (!(m_dwDynamicFlags & NDF_UNREACHABLE)))
2478 {
2479 AgentConnection *pConn;
2480
cd9f247e 2481 pConn = createAgentConnection();
5039dede
AK
2482 if (pConn != NULL)
2483 {
2484 dwError = pConn->CheckNetworkService(pdwStatus, dwIpAddr, iServiceType,
2485 wPort, wProto, pszRequest, pszResponse);
2486 pConn->Disconnect();
2487 delete pConn;
2488 }
2489 }
2490 return dwError;
2491}
2492
2493
2494//
2495// Handler for object deletion
2496//
2497
2498void Node::OnObjectDelete(DWORD dwObjectId)
2499{
f5d16551 2500 LockData();
5039dede
AK
2501 if (dwObjectId == m_dwPollerNode)
2502 {
2503 // If deleted object is our poller node, change it to default
5039dede
AK
2504 m_dwPollerNode = 0;
2505 Modify();
2506 DbgPrintf(3, _T("Node \"%s\": poller node %d deleted"), m_szName, dwObjectId);
2507 }
f5d16551 2508 UnlockData();
5039dede
AK
2509}
2510
2511
2512//
2513// Check node for OSPF support
2514//
2515
2516void Node::CheckOSPFSupport(SNMP_Transport *pTransport)
2517{
2518 LONG nAdminStatus;
2519
5d2c5741 2520 if (SnmpGet(m_snmpVersion, pTransport,
5039dede
AK
2521 ".1.3.6.1.2.1.14.1.2.0", NULL, 0, &nAdminStatus, sizeof(LONG),
2522 FALSE, FALSE) == SNMP_ERR_SUCCESS)
2523 {
2524 LockData();
2525 if (nAdminStatus)
2526 {
2527 m_dwFlags |= NF_IS_OSPF;
2528 }
2529 else
2530 {
2531 m_dwFlags &= ~NF_IS_OSPF;
2532 }
2533 UnlockData();
2534 }
2535}
2536
2537
2538//
2539// Create ready to use agent connection
2540//
2541
cd9f247e 2542AgentConnectionEx *Node::createAgentConnection()
5039dede 2543{
45d84f8a 2544 AgentConnectionEx *conn;
5039dede
AK
2545
2546 if ((!(m_dwFlags & NF_IS_NATIVE_AGENT)) ||
6b2bb22c 2547 (m_dwFlags & NF_DISABLE_NXCP) ||
5039dede
AK
2548 (m_dwDynamicFlags & NDF_AGENT_UNREACHABLE) ||
2549 (m_dwDynamicFlags & NDF_UNREACHABLE))
2550 return NULL;
2551
45d84f8a
VK
2552 conn = new AgentConnectionEx(htonl(m_dwIpAddr), m_wAgentPort,
2553 m_wAuthMethod, m_szSharedSecret);
2554 SetAgentProxy(conn);
2555 if (!conn->Connect(g_pServerKey))
5039dede 2556 {
45d84f8a
VK
2557 delete conn;
2558 conn = NULL;
5039dede 2559 }
45d84f8a 2560 return conn;
5039dede
AK
2561}
2562
2563
2564//
2565// Get last collected values of all DCIs
2566//
2567
2568DWORD Node::GetLastValues(CSCPMessage *pMsg)
2569{
2570 DWORD i, dwId, dwCount;
2571
2572 LockData();
2573
2574 for(i = 0, dwId = VID_DCI_VALUES_BASE, dwCount = 0; i < m_dwNumItems; i++)
2575 {
fb05c05b 2576 if (_tcsnicmp(m_ppItems[i]->getDescription(), _T("@system."), 8))
5039dede 2577 {
fb05c05b 2578 m_ppItems[i]->getLastValue(pMsg, dwId);
5039dede
AK
2579 dwId += 10;
2580 dwCount++;
2581 }
2582 }
2583 pMsg->SetVariable(VID_NUM_ITEMS, dwCount);
2584
2585 UnlockData();
2586 return RCC_SUCCESS;
2587}
2588
2589
2590//
2591// Clean expired DCI data
2592//
2593
2594void Node::CleanDCIData(void)
2595{
2596 DWORD i;
2597
2598 LockData();
2599 for(i = 0; i < m_dwNumItems; i++)
fb05c05b 2600 m_ppItems[i]->deleteExpiredData();
5039dede
AK
2601 UnlockData();
2602}
2603
2604
2605//
2606// Apply DCI from template
2607// pItem passed to this method should be a template's DCI
2608//
2609
2610BOOL Node::ApplyTemplateItem(DWORD dwTemplateId, DCItem *pItem)
2611{
2612 BOOL bResult = TRUE;
2613 DWORD i;
2614 DCItem *pNewItem;
2615
2616 LockData();
2617
fb05c05b 2618 DbgPrintf(5, "Applying item \"%s\" to node \"%s\"", pItem->getName(), m_szName);
5039dede
AK
2619
2620 // Check if that template item exists
2621 for(i = 0; i < m_dwNumItems; i++)
fb05c05b
VK
2622 if ((m_ppItems[i]->getTemplateId() == dwTemplateId) &&
2623 (m_ppItems[i]->getTemplateItemId() == pItem->getId()))
5039dede
AK
2624 break; // Item with specified id already exist
2625
2626 if (i == m_dwNumItems)
2627 {
2628 // New item from template, just add it
2629 pNewItem = new DCItem(pItem);
fb05c05b
VK
2630 pNewItem->setTemplateId(dwTemplateId, pItem->getId());
2631 pNewItem->changeBinding(CreateUniqueId(IDG_ITEM), this, TRUE);
5039dede
AK
2632 bResult = AddItem(pNewItem, TRUE);
2633 }
2634 else
2635 {
2636 // Update existing item
fb05c05b 2637 m_ppItems[i]->updateFromTemplate(pItem);
5039dede
AK
2638 Modify();
2639 }
2640
2641 UnlockData();
2642 return bResult;
2643}
2644
2645
2646//
2647// Clean deleted template items from node's DCI list
2648// Arguments is template id and list of valid template item ids.
2649// all items related to given template and not presented in list should be deleted.
2650//
2651
2652void Node::CleanDeletedTemplateItems(DWORD dwTemplateId, DWORD dwNumItems, DWORD *pdwItemList)
2653{
2654 DWORD i, j, dwNumDeleted, *pdwDeleteList;
2655
2656 LockData();
2657
2658 pdwDeleteList = (DWORD *)malloc(sizeof(DWORD) * m_dwNumItems);
2659 dwNumDeleted = 0;
2660
2661 for(i = 0; i < m_dwNumItems; i++)
fb05c05b 2662 if (m_ppItems[i]->getTemplateId() == dwTemplateId)
5039dede
AK
2663 {
2664 for(j = 0; j < dwNumItems; j++)
fb05c05b 2665 if (m_ppItems[i]->getTemplateItemId() == pdwItemList[j])
5039dede
AK
2666 break;
2667
2668 // Delete DCI if it's not in list
2669 if (j == dwNumItems)
fb05c05b 2670 pdwDeleteList[dwNumDeleted++] = m_ppItems[i]->getId();
5039dede
AK
2671 }
2672
2673 for(i = 0; i < dwNumDeleted; i++)
2674 DeleteItem(pdwDeleteList[i], FALSE);
2675
2676 UnlockData();
2677 free(pdwDeleteList);
2678}
2679
2680
2681//
2682// Unbind node from template, i.e either remove DCI association with template
2683// or remove these DCIs at all
2684//
2685
2686void Node::UnbindFromTemplate(DWORD dwTemplateId, BOOL bRemoveDCI)
2687{
17b055bb 2688 DWORD i;
5039dede
AK
2689
2690 if (bRemoveDCI)
2691 {
17b055bb
VK
2692 DWORD *pdwDeleteList = (DWORD *)malloc(sizeof(DWORD) * m_dwNumItems);
2693 DWORD dwNumDeleted = 0;
5039dede 2694
17b055bb 2695 LockData();
5039dede
AK
2696
2697 for(i = 0; i < m_dwNumItems; i++)
fb05c05b 2698 if (m_ppItems[i]->getTemplateId() == dwTemplateId)
5039dede 2699 {
fb05c05b 2700 pdwDeleteList[dwNumDeleted++] = m_ppItems[i]->getId();
5039dede
AK
2701 }
2702
2703 for(i = 0; i < dwNumDeleted; i++)
2704 DeleteItem(pdwDeleteList[i], FALSE);
2705
2706 UnlockData();
17b055bb
VK
2707
2708 safe_free(pdwDeleteList);
5039dede
AK
2709 }
2710 else
2711 {
2712 LockData();
2713
2714 for(i = 0; i < m_dwNumItems; i++)
fb05c05b 2715 if (m_ppItems[i]->getTemplateId() == dwTemplateId)
5039dede 2716 {
fb05c05b 2717 m_ppItems[i]->setTemplateId(0, 0);
5039dede
AK
2718 }
2719
2720 UnlockData();
2721 }
2722}
2723
2724
2725//
2726// Change node's IP address
2727//
2728
2729void Node::ChangeIPAddress(DWORD dwIpAddr)
2730{
2731 DWORD i;
2732
2733 PollerLock();
2734
2735 LockData();
2736
2737 UpdateNodeIndex(m_dwIpAddr, dwIpAddr, this);
2738 m_dwIpAddr = dwIpAddr;
2739 m_dwDynamicFlags |= NDF_FORCE_CONFIGURATION_POLL | NDF_RECHECK_CAPABILITIES;
2740
2741 // Change status of node and all it's childs to UNKNOWN
2742 m_iStatus = STATUS_UNKNOWN;
2743 LockChildList(FALSE);
2744 for(i = 0; i < m_dwChildCount; i++)
2745 {
2746 m_pChildList[i]->ResetStatus();
2747 if (m_pChildList[i]->Type() == OBJECT_INTERFACE)
2748 {
2749 if (((Interface *)m_pChildList[i])->IsFake())
2750 {
2751 ((Interface *)m_pChildList[i])->SetIpAddr(dwIpAddr);
2752 }
2753 }
2754 }
2755 UnlockChildList();
2756
2757 Modify();
2758 UnlockData();
2759
2760 AgentLock();
2761 delete_and_null(m_pAgentConnection);
2762 AgentUnlock();
2763
2764 PollerUnlock();
2765}
2766
2767
2768//
2769// Get number of interface objects and pointer to the last one
2770//
2771
2772DWORD Node::GetInterfaceCount(Interface **ppInterface)
2773{
2774 DWORD i, dwCount;
2775
2776 LockChildList(FALSE);
2777 for(i = 0, dwCount = 0; i < m_dwChildCount; i++)
2778 if (m_pChildList[i]->Type() == OBJECT_INTERFACE)
2779 {
2780 dwCount++;
2781 *ppInterface = (Interface *)m_pChildList[i];
2782 }
2783 UnlockChildList();
2784 return dwCount;
2785}
2786
2787
2788//
2789// Update cache for all DCI's
2790//
2791
2792void Node::UpdateDCICache(void)
2793{
2794 DWORD i;
2795
2796 /* LOCK? */
2797 for(i = 0; i < m_dwNumItems; i++)
fb05c05b 2798 m_ppItems[i]->updateCacheSize();
5039dede
AK
2799}
2800
2801
2802//
2803// Get routing table from node
2804//
2805
2806ROUTING_TABLE *Node::GetRoutingTable(void)
2807{
2808 ROUTING_TABLE *pRT = NULL;
2809
2810 if ((m_dwFlags & NF_IS_NATIVE_AGENT) && (!(m_dwFlags & NF_DISABLE_NXCP)))
2811 {
2812 AgentLock();
2813 if (ConnectToAgent())
2814 {
2815 pRT = m_pAgentConnection->GetRoutingTable();
2816 }
2817 AgentUnlock();
2818 }
2819 if ((pRT == NULL) && (m_dwFlags & NF_IS_SNMP) && (!(m_dwFlags & NF_DISABLE_SNMP)))
2820 {
2821 SNMP_Transport *pTransport;
2822
cd9f247e 2823 pTransport = createSnmpTransport();
803d47be
VK
2824 if (pTransport != NULL)
2825 {
2826 pRT = SnmpGetRoutingTable(m_snmpVersion, pTransport);
2827 delete pTransport;
2828 }
5039dede
AK
2829 }
2830
2831 if (pRT != NULL)
2832 {
2833 SortRoutingTable(pRT);
2834 }
2835 return pRT;
2836}
2837
2838
2839//
2840// Get next hop for given destination address
2841//
2842
2843BOOL Node::GetNextHop(DWORD dwSrcAddr, DWORD dwDestAddr, DWORD *pdwNextHop,
2844 DWORD *pdwIfIndex, BOOL *pbIsVPN)
2845{
2846 DWORD i;
2847 BOOL bResult = FALSE;
2848
2849 // Check VPN connectors
2850 LockChildList(FALSE);
2851 for(i = 0; i < m_dwChildCount; i++)
2852 if (m_pChildList[i]->Type() == OBJECT_VPNCONNECTOR)
2853 {
2854 if (((VPNConnector *)m_pChildList[i])->IsRemoteAddr(dwDestAddr) &&
2855 ((VPNConnector *)m_pChildList[i])->IsLocalAddr(dwSrcAddr))
2856 {
2857 *pdwNextHop = ((VPNConnector *)m_pChildList[i])->GetPeerGatewayAddr();
2858 *pdwIfIndex = m_pChildList[i]->Id();
2859 *pbIsVPN = TRUE;
2860 bResult = TRUE;
2861 break;
2862 }
2863 }
2864 UnlockChildList();
2865
2866 // Check routing table
2867 if (!bResult)
2868 {
2869 RTLock();
2870 if (m_pRoutingTable != NULL)
2871 {
2872 for(i = 0; i < (DWORD)m_pRoutingTable->iNumEntries; i++)
2873 if ((dwDestAddr & m_pRoutingTable->pRoutes[i].dwDestMask) == m_pRoutingTable->pRoutes[i].dwDestAddr)
2874 {
2875 *pdwNextHop = m_pRoutingTable->pRoutes[i].dwNextHop;
2876 *pdwIfIndex = m_pRoutingTable->pRoutes[i].dwIfIndex;
2877 *pbIsVPN = FALSE;
2878 bResult = TRUE;
2879 break;
2880 }
2881 }
2882 RTUnlock();
2883 }
2884
2885 return bResult;
2886}
2887
2888
2889//
2890// Update cached routing table
2891//
2892
2893void Node::UpdateRoutingTable(void)
2894{
2895 ROUTING_TABLE *pRT;
2896
2897 pRT = GetRoutingTable();
2898 if (pRT != NULL)
2899 {
2900 RTLock();
2901 DestroyRoutingTable(m_pRoutingTable);
2902 m_pRoutingTable = pRT;
2903 RTUnlock();
2904 }
2905 m_tLastRTUpdate = time(NULL);
2906 m_dwDynamicFlags &= ~NDF_QUEUED_FOR_ROUTE_POLL;
2907}
2908
2909
2910//
2911// Call SNMP Enumerate with node's SNMP parameters
2912//
2913
2914DWORD Node::CallSnmpEnumerate(const char *pszRootOid,
5d2c5741 2915 DWORD (* pHandler)(DWORD, SNMP_Variable *, SNMP_Transport *, void *),
5039dede
AK
2916 void *pArg)
2917{
2918 if ((m_dwFlags & NF_IS_SNMP) &&
2919 (!(m_dwDynamicFlags & NDF_SNMP_UNREACHABLE)) &&
2920 (!(m_dwDynamicFlags & NDF_UNREACHABLE)))
2921 {
2922 SNMP_Transport *pTransport;
2923 DWORD dwResult;
2924
cd9f247e 2925 pTransport = createSnmpTransport();
803d47be
VK
2926 if (pTransport != NULL)
2927 {
2928 dwResult = SnmpEnumerate(m_snmpVersion, pTransport,
2929 pszRootOid, pHandler, pArg, FALSE);
2930 delete pTransport;
2931 }
2932 else
2933 {
2934 dwResult = SNMP_ERR_COMM;
2935 }
5039dede
AK
2936 return dwResult;
2937 }
2938 else
2939 {
2940 return SNMP_ERR_COMM;
2941 }
2942}
2943
2944
2945//
2946// Set proxy information for agent's connection
2947//
2948
2949void Node::SetAgentProxy(AgentConnection *pConn)
2950{
2951 if (m_dwProxyNode != 0)
2952 {
2953 Node *pNode;
2954
2955 pNode = (Node *)FindObjectById(m_dwProxyNode);
2956 if (pNode != NULL)
2957 {
2958 pConn->SetProxy(htonl(pNode->m_dwIpAddr), pNode->m_wAgentPort,
2959 pNode->m_wAuthMethod, pNode->m_szSharedSecret);
2960 }
2961 }
2962}
2963
2964
2965//
2966// Prepare node object for deletion
2967//
2968
2969void Node::PrepareForDeletion(void)
2970{
2971 // Prevent node from being queued for polling
2972 LockData();
2973 m_dwDynamicFlags |= NDF_POLLING_DISABLED;
2974 UnlockData();
2975
2976 // Wait for all pending polls
2977 while(1)
2978 {
2979 LockData();
2980 if ((m_dwDynamicFlags &
2981 (NDF_QUEUED_FOR_STATUS_POLL | NDF_QUEUED_FOR_CONFIG_POLL |
2982 NDF_QUEUED_FOR_DISCOVERY_POLL | NDF_QUEUED_FOR_ROUTE_POLL)) == 0)
2983 {
2984 UnlockData();
2985 break;
2986 }
2987 UnlockData();
2988 ThreadSleepMs(100);
2989 }
2990 Template::PrepareForDeletion();
2991}
2992
2993
2994//
2995// Check if specified SNMP variable set to specified value.
2996// If variable doesn't exist at all, will return FALSE
2997//
2998
2999BOOL Node::CheckSNMPIntegerValue(SNMP_Transport *pTransport, const char *pszOID, int nValue)
3000{
3001 DWORD dwTemp;
3002
5d2c5741
VK
3003 if (SnmpGet(m_snmpVersion, pTransport, pszOID, NULL, 0, &dwTemp,
3004 sizeof(DWORD), FALSE, FALSE) == SNMP_ERR_SUCCESS)
5039dede
AK
3005 return (int)dwTemp == nValue;
3006 return FALSE;
3007}
3008
3009
3010//
3011// Check and update if needed interface names
3012//
3013
3014void Node::CheckInterfaceNames(INTERFACE_LIST *pIfList)
3015{
3016 int i;
3017 TCHAR *ptr;
3018
3019 if ((m_dwNodeType == NODE_TYPE_NORTEL_BAYSTACK) ||
3020 (m_dwNodeType == NODE_TYPE_NORTEL_OPTERA))
3021 {
3022 // Translate interface names
3023 for(i = 0; i < pIfList->iNumEntries; i++)
3024 {
3025 if ((ptr = _tcsstr(pIfList->pInterfaces[i].szName, _T("- Port"))) != NULL)
3026 {
3027 ptr += 2;
3028 memmove(pIfList->pInterfaces[i].szName, ptr, _tcslen(ptr) + 1);
3029 }
3030 else if ((ptr = _tcsstr(pIfList->pInterfaces[i].szName, _T("- Unit"))) != NULL)
3031 {
3032 ptr += 2;
3033 memmove(pIfList->pInterfaces[i].szName, ptr, _tcslen(ptr) + 1);
3034 }
3035 else if ((_tcsstr(pIfList->pInterfaces[i].szName, _T("BayStack")) != NULL) ||
3036 (_tcsstr(pIfList->pInterfaces[i].szName, _T("Nortel Ethernet Switch")) != NULL))
3037 {
3038 ptr = _tcsrchr(pIfList->pInterfaces[i].szName, _T('-'));
3039 if (ptr != NULL)
3040 {
3041 ptr++;
3042 while(*ptr == _T(' '))
3043 ptr++;
3044 memmove(pIfList->pInterfaces[i].szName, ptr, _tcslen(ptr) + 1);
3045 }
3046 }
3047 StrStrip(pIfList->pInterfaces[i].szName);
3048 }
3049 }
3050
3051 // Cut interface names to MAX_OBJECT_NAME and check for unnamed interfaces
3052 for(i = 0; i < pIfList->iNumEntries; i++)
3053 {
3054 pIfList->pInterfaces[i].szName[MAX_OBJECT_NAME - 1] = 0;
3055 if (pIfList->pInterfaces[i].szName[0] == 0)
3056 _stprintf(pIfList->pInterfaces[i].szName, _T("%d"), pIfList->pInterfaces[i].dwIndex);
3057 }
3058}
3059
3060
3061//
3062// Get cluster object this node belongs to, if any
3063//
3064
3065Cluster *Node::GetMyCluster(void)
3066{
3067 DWORD i;
3068 Cluster *pCluster = NULL;
3069
3070 LockParentList(FALSE);
3071 for(i = 0; i < m_dwParentCount; i++)
3072 if (m_pParentList[i]->Type() == OBJECT_CLUSTER)
3073 {
3074 pCluster = (Cluster *)m_pParentList[i];
3075 break;
3076 }
3077 UnlockParentList();
3078 return pCluster;
3079}
3080
3081
3082//
3083// Create SNMP transport
3084//
3085
cd9f247e 3086SNMP_Transport *Node::createSnmpTransport()
5039dede
AK
3087{
3088 SNMP_Transport *pTransport = NULL;
3089
3090 if (m_dwSNMPProxy == 0)
3091 {
3092 pTransport = new SNMP_UDPTransport;
c4366266 3093 ((SNMP_UDPTransport *)pTransport)->createUDPTransport(NULL, htonl(m_dwIpAddr), m_wSNMPPort);
5039dede
AK
3094 }
3095 else
3096 {
3097 NetObj *pObject;
3098
3099 pObject = FindObjectById(m_dwSNMPProxy);
3100 if (pObject != NULL)
3101 {
3102 if (pObject->Type() == OBJECT_NODE)
3103 {
3104 AgentConnection *pConn;
3105
cd9f247e 3106 pConn = ((Node *)pObject)->createAgentConnection();
5039dede
AK
3107 if (pConn != NULL)
3108 {
3109 pTransport = new SNMP_ProxyTransport(pConn, m_dwIpAddr, m_wSNMPPort);
3110 }
3111 }
3112 }
3113 }
5d2c5741
VK
3114
3115 // Set security
3116 if (pTransport != NULL)
3117 {
df8a4ca2 3118 LockData();
5d2c5741 3119 pTransport->setSecurityContext(new SNMP_SecurityContext(m_snmpSecurity));
df8a4ca2 3120 UnlockData();
5d2c5741 3121 }
5039dede
AK
3122 return pTransport;
3123}
cd9f247e
VK
3124
3125
3126//
3127// Get SNMP security context
3128// ATTENTION: This method returns new copy of security context
3129// which must be destroyed by the caller
3130//
3131
3132SNMP_SecurityContext *Node::getSnmpSecurityContext()
3133{
3134 LockData();
3135 SNMP_SecurityContext *ctx = new SNMP_SecurityContext(m_snmpSecurity);
3136 UnlockData();
3137 return ctx;
3138}
5039dede
AK
3139
3140
3141//
3142// Resolve node's name
3143//
3144
3145BOOL Node::ResolveName(BOOL useOnlyDNS)
3146{
3147 BOOL bSuccess = FALSE;
3148 HOSTENT *hs;
3149 DWORD i, dwAddr;
3150 TCHAR szBuffer[256];
3151
3152 DbgPrintf(4, _T("Resolving name for node %d [%s]..."), m_dwId, m_szName);
3153
3154 // Try to resolve primary IP
3155 dwAddr = htonl(m_dwIpAddr);
3156 hs = gethostbyaddr((const char *)&dwAddr, 4, AF_INET);
3157 if (hs != NULL)
3158 {
3159 nx_strncpy(m_szName, hs->h_name, MAX_OBJECT_NAME);
3160 bSuccess = TRUE;
3161 }
3162 else
3163 {
3164 // Try to resolve each interface's IP address
3165 LockChildList(FALSE);
3166 for(i = 0; i < m_dwChildCount; i++)
3167 {
3168 if (m_pChildList[i]->Type() == OBJECT_INTERFACE)
3169 {
3170 dwAddr = htonl(m_pChildList[i]->IpAddr());
3171 if (dwAddr != 0)
3172 {
3173 hs = gethostbyaddr((const char *)&dwAddr, 4, AF_INET);
3174 if (hs != NULL)
3175 {
3176 nx_strncpy(m_szName, hs->h_name, MAX_OBJECT_NAME);
3177 bSuccess = TRUE;
3178 break;
3179 }
3180 }
3181 }
3182 }
3183 UnlockChildList();
3184
3185 // Try to get hostname from agent if address resolution fails
3186 if (!(bSuccess || useOnlyDNS))
3187 {
3188 DbgPrintf(4, _T("Resolving name for node %d [%s] via agent..."), m_dwId, m_szName);
3189 if (GetItemFromAgent("System.Hostname", 256, szBuffer) == DCE_SUCCESS)
3190 {
3191 StrStrip(szBuffer);
3192 if (szBuffer[0] != 0)
3193 {
3194 nx_strncpy(m_szName, szBuffer, MAX_OBJECT_NAME);
3195 bSuccess = TRUE;
3196 }
3197 }
3198 }
3199
3200 // Try to get hostname from SNMP if other methods fails
3201 if (!(bSuccess || useOnlyDNS))
3202 {
3203 DbgPrintf(4, _T("Resolving name for node %d [%s] via SNMP..."), m_dwId, m_szName);
3204 if (GetItemFromSNMP(".1.3.6.1.2.1.1.5.0", 256, szBuffer) == DCE_SUCCESS)
3205 {
3206 StrStrip(szBuffer);
3207 if (szBuffer[0] != 0)
3208 {
3209 nx_strncpy(m_szName, szBuffer, MAX_OBJECT_NAME);
3210 bSuccess = TRUE;
3211 }
3212 }
3213 }
3214 }
3215
3216 if (bSuccess)
3217 DbgPrintf(4, _T("Name for node %d was resolved to %s"), m_dwId, m_szName);
3218 else
3219 DbgPrintf(4, _T("Name for node %d was not resolved"), m_dwId, m_szName);
3220 return bSuccess;
3221}
3222
3223
3224//
3225// Send list of system DCIs
3226//
3227
3228DWORD Node::GetSystemDCIList(CSCPMessage *pMsg)
3229{
3230 DWORD i, dwId, dwCount;
3231
3232 LockData();
3233
3234 for(i = 0, dwId = VID_SYSDCI_LIST_BASE, dwCount = 0; i < m_dwNumItems; i++)
3235 {
fb05c05b 3236 if (!_tcsnicmp(m_ppItems[i]->getDescription(), _T("@System."), 8))
5039dede 3237 {
fb05c05b
VK
3238 pMsg->SetVariable(dwId++, m_ppItems[i]->getId());
3239 pMsg->SetVariable(dwId++, (TCHAR *)m_ppItems[i]->getDescription());
3240 pMsg->SetVariable(dwId++, (WORD)m_ppItems[i]->getStatus());
5039dede
AK
3241 dwId += 7;
3242 dwCount++;
3243 }
3244 }
3245 pMsg->SetVariable(VID_NUM_ITEMS, dwCount);
3246
3247 UnlockData();
3248 return RCC_SUCCESS;
3249}
3250
3251
3252//
3253// Get current layer 2 topology (as dynamically created list which should be destroyed by caller)
3254// Will return NULL if there are no topology information or it is expired
3255//
3256
3257nxmap_ObjList *Node::GetL2Topology(void)
3258{
3259 nxmap_ObjList *pResult;
3260 DWORD dwExpTime;
3261
3262 dwExpTime = ConfigReadULong(_T("TopologyExpirationTime"), 900);
3263 MutexLock(m_mutexTopoAccess, INFINITE);
3264 if ((m_pTopology == NULL) || (m_tLastTopologyPoll + (time_t)dwExpTime < time(NULL)))
3265 {
3266 pResult = NULL;
3267 }
3268 else
3269 {
3270 pResult = new nxmap_ObjList(m_pTopology);
3271 }
3272 MutexUnlock(m_mutexTopoAccess);
3273 return pResult;
3274}
3275
3276
3277//
3278// Rebuild layer 2 topology and return it as dynamically reated list which should be destroyed by caller
3279//
3280
3281nxmap_ObjList *Node::BuildL2Topology(DWORD *pdwStatus)
3282{
3283 nxmap_ObjList *pResult;
3284 int nDepth;
3285
3286 nDepth = ConfigReadInt(_T("TopologyDiscoveryRadius"), 5);
3287 MutexLock(m_mutexTopoAccess, INFINITE);
3288 delete m_pTopology;
3289 if ((m_dwFlags & NF_IS_CDP) || (m_dwFlags & NF_IS_SONMP) || (m_dwFlags & NF_IS_LLDP))
3290 {
3291 m_pTopology = new nxmap_ObjList;
3292 if ((*pdwStatus = ::BuildL2Topology(*m_pTopology, this, NULL, nDepth, NULL)) == RCC_SUCCESS)
3293 {
3294 m_tLastTopologyPoll = time(NULL);
3295 pResult = new nxmap_ObjList(m_pTopology);
3296 }
3297 else
3298 {
3299 delete_and_null(m_pTopology);
3300 pResult = NULL;
3301 }
3302 }
3303 else
3304 {
3305 pResult = NULL;
3306 m_pTopology = NULL;
3307 *pdwStatus = RCC_NO_L2_TOPOLOGY_SUPPORT;
3308 }
3309 MutexUnlock(m_mutexTopoAccess);
3310 return pResult;
3311}
3312
3313
3314//
3315// Check subnet bindings
3316//
3317
3318void Node::CheckSubnetBinding(INTERFACE_LIST *pIfList)
3319{
3320 Subnet *pSubnet;
3321 Interface *pInterface;
3322 Cluster *pCluster;
3323 NetObj **ppUnlinkList;
3324 int i, j, count;
3325 BOOL isSync;
3326
3327 pCluster = GetMyCluster();
3328
3329 // Check if we have subnet bindings for all interfaces
3330 for(i = 0; i < pIfList->iNumEntries; i++)
3331 {
3332 if (pIfList->pInterfaces[i].dwIpAddr != 0)
3333 {
3334 pInterface = FindInterface(pIfList->pInterfaces[i].dwIndex, pIfList->pInterfaces[i].dwIpAddr);
3335 if (pInterface == NULL)
3336 {
3337 nxlog_write(MSG_INTERNAL_ERROR, EVENTLOG_WARNING_TYPE, "s", _T("Cannot find interface object in Node::CheckSubnetBinding()"));
3338 break; // Something goes really wrong
3339 }
3340
3341 // Is cluster interconnect interface?
3342 isSync = (pCluster != NULL) ? pCluster->IsSyncAddr(pInterface->IpAddr()) : FALSE;
3343
3344 pSubnet = FindSubnetForNode(pIfList->pInterfaces[i].dwIpAddr);
3345 if (pSubnet != NULL)
3346 {
3347 if (isSync)
3348 {
3349 pSubnet = NULL; // No further checks on this subnet
3350 }
3351 else
3352 {
3353 if (pSubnet->IsSyntheticMask())
3354 {
3355 DbgPrintf(4, _T("Setting correct netmask for subnet %s [%d] from node %s [%d]"),
3356 pSubnet->Name(), pSubnet->Id(), m_szName, m_dwId);
3357 pSubnet->SetCorrectMask(pInterface->IpAddr() & pInterface->IpNetMask(), pInterface->IpNetMask());
3358 }
3359 }
3360 }
3361 else if (!isSync)
3362 {
3363 // Create subnet
3364 pSubnet = new Subnet(pIfList->pInterfaces[i].dwIpAddr & pIfList->pInterfaces[i].dwIpNetMask,
3365 pIfList->pInterfaces[i].dwIpNetMask, m_dwZoneGUID, FALSE);
3366 NetObjInsert(pSubnet, TRUE);
3367 g_pEntireNet->AddSubnet(pSubnet);
3368 pSubnet->AddNode(this);
3369 DbgPrintf(4, _T("Node::CheckSubnetBinding(): Creating new subnet %s [%d] for node %s [%d]"),
3370 pSubnet->Name(), pSubnet->Id(), m_szName, m_dwId);
3371 }
3372
3373 // Check if subnet mask is correct on interface
3374 if ((pSubnet != NULL) && (pSubnet->IpNetMask() != pIfList->pInterfaces[i].dwIpNetMask))
3375 {
3376 PostEvent(EVENT_INCORRECT_NETMASK, m_dwId, "idsaa", pInterface->Id(),
3377 pInterface->IfIndex(), pInterface->Name(),
3378 pInterface->IpNetMask(), pSubnet->IpNetMask());
3379 }
3380 }
3381 }
3382
3383 // Check if we have incorrect subnets as parents
3384 LockParentList(FALSE);
3385 LockChildList(FALSE);
3386 ppUnlinkList = (NetObj **)malloc(sizeof(NetObj *) * m_dwParentCount);
3387 for(i = 0, count = 0; i < (int)m_dwParentCount; i++)
3388 {
3389 if (m_pParentList[i]->Type() == OBJECT_SUBNET)
3390 {
3391 pSubnet = (Subnet *)m_pParentList[i];
3392 for(j = 0; j < (int)m_dwChildCount; j++)
3393 {
3394 if (m_pChildList[j]->Type() == OBJECT_INTERFACE)
3395 {
3396 if (pSubnet->IpAddr() == (m_pChildList[j]->IpAddr() & pSubnet->IpNetMask()))
3397 {
3398 if (pCluster != NULL)
3399 {
3400 if (pCluster->IsSyncAddr(m_pChildList[j]->IpAddr()))
3401 {
3402 j = (int)m_dwChildCount; // Cause to unbind from this subnet
3403 }
3404 }
3405 break;
3406 }
3407 }
3408 }
3409 if (j == (int)m_dwChildCount)
3410 {
3411 DbgPrintf(4, _T("Node::CheckSubnetBinding(): Subnet %s [%d] is incorrect for node %s [%d]"),
3412 pSubnet->Name(), pSubnet->Id(), m_szName, m_dwId);
3413 ppUnlinkList[count++] = pSubnet;
3414 }
3415 }
3416 }
3417 UnlockChildList();
3418 UnlockParentList();
3419
3420 // Unlink for incorrect subnet objects
3421 for(i = 0; i < count; i++)
3422 {
3423 ppUnlinkList[i]->DeleteChild(this);
3424 DeleteParent(ppUnlinkList[i]);
3425 }
3426 safe_free(ppUnlinkList);
3427}
3428
3429
3430//
3431// Update interface names
3432//
3433
3434void Node::UpdateInterfaceNames(ClientSession *pSession, DWORD dwRqId)
3435{
3436 INTERFACE_LIST *pIfList;
3437 DWORD i;
3438 int j;
3439
3440 PollerLock();
3441 m_pPollRequestor = pSession;
3442 SendPollerMsg(dwRqId, _T("Starting interface names poll for node %s\r\n"), m_szName);
3443 DbgPrintf(4, "Starting interface names poll for node %s (ID: %d)", m_szName, m_dwId);
3444
3445 // Retrieve interface list
3446 pIfList = GetInterfaceList();
3447 if (pIfList != NULL)
3448 {
3449 // Check names of existing interfaces
3450 for(j = 0; j < pIfList->iNumEntries; j++)
3451 {
3452 LockChildList(FALSE);
3453 for(i = 0; i < m_dwChildCount; i++)
3454 {
3455 if (m_pChildList[i]->Type() == OBJECT_INTERFACE)
3456 {
3457 Interface *pInterface = (Interface *)m_pChildList[i];
3458
3459 if (pIfList->pInterfaces[j].dwIndex == pInterface->IfIndex())
3460 {
3461 SendPollerMsg(dwRqId, _T(" Checking interface %d (%s)\r\n"), pInterface->IfIndex(), pInterface->Name());
3462 if (strcmp(pIfList->pInterfaces[j].szName, pInterface->Name()))
3463 {
3464 pInterface->SetName(pIfList->pInterfaces[j].szName);
3465 SendPollerMsg(dwRqId, POLLER_WARNING _T(" Name of interface %d changed to %s\r\n"), pInterface->IfIndex(), pIfList->pInterfaces[j].szName);
3466 }
3467 break;
3468 }
3469 }
3470 }
3471 UnlockChildList();
3472 }
3473
3474 DestroyInterfaceList(pIfList);
3475 }
3476 else /* pIfList == NULL */
3477 {
3478 SendPollerMsg(dwRqId, POLLER_ERROR _T(" Unable to get interface list from node\r\n"));
3479 }
3480
3481 // Finish poll
3482 SendPollerMsg(dwRqId, _T("Finished interface names poll for node %s\r\n"), m_szName);
3483 PollerUnlock();
3484 DbgPrintf(4, "Finished interface names poll for node %s (ID: %d)", m_szName, m_dwId);
3485}