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