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