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