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