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