Rollback from r3608 to r3606
[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 {
234 DBFreeResult(hResult);
235 DbgPrintf(3, "Unbound node object %d (%s)", dwId, m_szName);
236 return FALSE; // No parents - it shouldn't happen if database isn't corrupted
237 }
238
239 for(i = 0; i < iNumRows; i++)
240 {
241 dwSubnetId = DBGetFieldULong(hResult, i, 0);
242 pObject = FindObjectById(dwSubnetId);
243 if (pObject == NULL)
244 {
245 nxlog_write(MSG_INVALID_SUBNET_ID, EVENTLOG_ERROR_TYPE, "dd", dwId, dwSubnetId);
246 break;
247 }
248 else if (pObject->Type() != OBJECT_SUBNET)
249 {
250 nxlog_write(MSG_SUBNET_NOT_SUBNET, EVENTLOG_ERROR_TYPE, "dd", dwId, dwSubnetId);
251 break;
252 }
253 else
254 {
255 pObject->AddChild(this);
256 AddParent(pObject);
257 bResult = TRUE;
258 }
259 }
260
261 DBFreeResult(hResult);
262 LoadItemsFromDB();
263 LoadACLFromDB();
264
265 // Walk through all items in the node and load appropriate thresholds
266 for(i = 0; i < (int)m_dwNumItems; i++)
267 if (!m_ppItems[i]->LoadThresholdsFromDB())
268 {
269 DbgPrintf(3, "Cannot load thresholds for DCI %d of node %d (%s)",
270 m_ppItems[i]->Id(), dwId, m_szName);
271 bResult = FALSE;
272 }
273 }
274 else
275 {
276 bResult = TRUE;
277 }
278
279 return bResult;
280}
281
282
283//
284// Save object to database
285//
286
287BOOL Node::SaveToDB(DB_HANDLE hdb)
288{
289 TCHAR *pszEscVersion, *pszEscPlatform, *pszEscSecret;
290 TCHAR *pszEscCommunity, szQuery[4096], szIpAddr[16];
291 TCHAR *pszEscDescr;
292 DB_RESULT hResult;
293 BOOL bNewObject = TRUE;
294 BOOL bResult;
295
296 // Lock object's access
297 LockData();
298
299 SaveCommonProperties(hdb);
300
301 // Check for object's existence in database
302 sprintf(szQuery, "SELECT id FROM nodes WHERE id=%d", m_dwId);
303 hResult = DBSelect(hdb, szQuery);
304 if (hResult != 0)
305 {
306 if (DBGetNumRows(hResult) > 0)
307 bNewObject = FALSE;
308 DBFreeResult(hResult);
309 }
310
311 // Form and execute INSERT or UPDATE query
312 pszEscVersion = EncodeSQLString(m_szAgentVersion);
313 pszEscPlatform = EncodeSQLString(m_szPlatformName);
314 pszEscSecret = EncodeSQLString(m_szSharedSecret);
315 pszEscCommunity = EncodeSQLString(m_szCommunityString);
316 pszEscDescr = EncodeSQLString(m_szSysDescription);
317 if (bNewObject)
318 snprintf(szQuery, 4096,
319 "INSERT INTO nodes (id,primary_ip,"
320 "node_flags,snmp_version,community,status_poll_type,"
321 "agent_port,auth_method,secret,snmp_oid,proxy_node,"
322 "node_type,agent_version,platform_name,uname,"
323 "poller_node_id,zone_guid,snmp_proxy,required_polls,"
324 "use_ifxtable) VALUES "
325 "(%d,'%s',%d,%d,'%s',%d,%d,%d,'%s','%s',%d,%d,'%s','%s','%s',%d,%d,%d,%d,%d)",
326 m_dwId, IpToStr(m_dwIpAddr, szIpAddr), m_dwFlags,
327 m_iSNMPVersion, pszEscCommunity, m_iStatusPollType,
328 m_wAgentPort, m_wAuthMethod, pszEscSecret, m_szObjectId,
329 m_dwProxyNode, m_dwNodeType, pszEscVersion,
330 pszEscPlatform, pszEscDescr, m_dwPollerNode, m_dwZoneGUID,
331 m_dwSNMPProxy, m_iRequiredPollCount,m_nUseIfXTable);
332 else
333 snprintf(szQuery, 4096,
334 "UPDATE nodes SET primary_ip='%s',"
335 "node_flags=%d,snmp_version=%d,community='%s',"
336 "status_poll_type=%d,agent_port=%d,auth_method=%d,secret='%s',"
337 "snmp_oid='%s',node_type=%d,uname='%s',"
338 "agent_version='%s',platform_name='%s',poller_node_id=%d,"
339 "zone_guid=%d,proxy_node=%d,snmp_proxy=%d,"
340 "required_polls=%d,use_ifxtable=%d WHERE id=%d",
341 IpToStr(m_dwIpAddr, szIpAddr),
342 m_dwFlags, m_iSNMPVersion, pszEscCommunity,
343 m_iStatusPollType, m_wAgentPort, m_wAuthMethod, pszEscSecret,
344 m_szObjectId, m_dwNodeType, pszEscDescr,
345 pszEscVersion, pszEscPlatform, m_dwPollerNode, m_dwZoneGUID,
346 m_dwProxyNode, m_dwSNMPProxy, m_iRequiredPollCount,
347 m_nUseIfXTable, m_dwId);
348 bResult = DBQuery(hdb, szQuery);
349 free(pszEscVersion);
350 free(pszEscPlatform);
351 free(pszEscSecret);
352 free(pszEscCommunity);
353 free(pszEscDescr);
354
355 // Save data collection items
356 if (bResult)
357 {
358 DWORD i;
359
360 for(i = 0; i < m_dwNumItems; i++)
361 m_ppItems[i]->SaveToDB(hdb);
362 }
363
364 // Save access list
365 SaveACLToDB(hdb);
366
367 // Clear modifications flag and unlock object
368 m_bIsModified = FALSE;
369 UnlockData();
370
371 return bResult;
372}
373
374
375//
376// Delete object from database
377//
378
379BOOL Node::DeleteFromDB(void)
380{
381 char szQuery[256];
382 BOOL bSuccess;
383
384 bSuccess = Template::DeleteFromDB();
385 if (bSuccess)
386 {
387 sprintf(szQuery, "DELETE FROM nodes WHERE id=%d", m_dwId);
388 QueueSQLRequest(szQuery);
389 sprintf(szQuery, "DELETE FROM nsmap WHERE node_id=%d", m_dwId);
390 QueueSQLRequest(szQuery);
391 sprintf(szQuery, "DROP TABLE idata_%d", m_dwId);
392 QueueSQLRequest(szQuery);
393 }
394 return bSuccess;
395}
396
397
398//
399// Get ARP cache from node
400//
401
402ARP_CACHE *Node::GetArpCache(void)
403{
404 ARP_CACHE *pArpCache = NULL;
405
406 if (m_dwFlags & NF_IS_LOCAL_MGMT)
407 {
408 pArpCache = GetLocalArpCache();
409 }
410 else if (m_dwFlags & NF_IS_NATIVE_AGENT)
411 {
412 AgentLock();
413 if (ConnectToAgent())
414 pArpCache = m_pAgentConnection->GetArpCache();
415 AgentUnlock();
416 }
417 else if (m_dwFlags & NF_IS_SNMP)
418 {
419 SNMP_Transport *pTransport;
420
421 pTransport = CreateSNMPTransport();
422 pArpCache = SnmpGetArpCache(m_iSNMPVersion, pTransport,
423 m_szCommunityString);
424 delete pTransport;
425 }
426
427 return pArpCache;
428}
429
430
431//
432// Get list of interfaces from node
433//
434
435INTERFACE_LIST *Node::GetInterfaceList(void)
436{
437 INTERFACE_LIST *pIfList = NULL;
438
439 if (m_dwFlags & NF_IS_LOCAL_MGMT)
440 {
441 pIfList = GetLocalInterfaceList();
442 }
443 if ((pIfList == NULL) && (m_dwFlags & NF_IS_NATIVE_AGENT) &&
444 (!(m_dwFlags & NF_DISABLE_NXCP)))
445 {
446 AgentLock();
447 if (ConnectToAgent())
448 {
449 pIfList = m_pAgentConnection->GetInterfaceList();
450 CleanInterfaceList(pIfList);
451 }
452 AgentUnlock();
453 }
454 if ((pIfList == NULL) && (m_dwFlags & NF_IS_SNMP) &&
455 (!(m_dwFlags & NF_DISABLE_SNMP)))
456 {
457 SNMP_Transport *pTransport;
458 BOOL useIfXTable;
459
460 pTransport = CreateSNMPTransport();
461 if (m_nUseIfXTable == IFXTABLE_DEFAULT)
462 {
463 useIfXTable = (ConfigReadInt(_T("UseIfXTable"), 1) != 0);
464 }
465 else
466 {
467 useIfXTable = (m_nUseIfXTable == IFXTABLE_ENABLED);
468 }
469 pIfList = SnmpGetInterfaceList(m_iSNMPVersion, pTransport,
470 m_szCommunityString, m_dwNodeType,
471 useIfXTable);
472 delete pTransport;
473 }
474
475 if (pIfList != NULL)
476 CheckInterfaceNames(pIfList);
477
478 return pIfList;
479}
480
481
482//
483// Find interface by index and node IP
484// Returns pointer to interface object or NULL if appropriate interface couldn't be found
485//
486
487Interface *Node::FindInterface(DWORD dwIndex, DWORD dwHostAddr)
488{
489 DWORD i;
490 Interface *pInterface;
491
492 LockChildList(FALSE);
493 for(i = 0; i < m_dwChildCount; i++)
494 if (m_pChildList[i]->Type() == OBJECT_INTERFACE)
495 {
496 pInterface = (Interface *)m_pChildList[i];
497 if (pInterface->IfIndex() == dwIndex)
498 {
499 if (((pInterface->IpAddr() & pInterface->IpNetMask()) ==
500 (dwHostAddr & pInterface->IpNetMask())) ||
501 (dwHostAddr == INADDR_ANY))
502 {
503 UnlockChildList();
504 return pInterface;
505 }
506 }
507 }
508 UnlockChildList();
509 return NULL;
510}
511
512
513//
514// Check if given IP address is one of node's interfaces
515//
516
517BOOL Node::IsMyIP(DWORD dwIpAddr)
518{
519 DWORD i;
520
521 LockChildList(FALSE);
522 for(i = 0; i < m_dwChildCount; i++)
523 if (m_pChildList[i]->Type() == OBJECT_INTERFACE)
524 {
525 if (((Interface *)m_pChildList[i])->IpAddr() == dwIpAddr)
526 {
527 UnlockChildList();
528 return TRUE;
529 }
530 }
531 UnlockChildList();
532 return FALSE;
533}
534
535
536//
537// Create new interface
538//
539
540void Node::CreateNewInterface(DWORD dwIpAddr, DWORD dwNetMask, char *szName,
541 DWORD dwIndex, DWORD dwType, BYTE *pbMacAddr)
542{
543 Interface *pInterface;
544 Subnet *pSubnet = NULL;
545 Cluster *pCluster;
546 BOOL bAddToSubnet, bSyntheticMask = FALSE;
547
548 DbgPrintf(5, _T("Node::CreateNewInterface(%08X, %08X, %s, %d, %d) called for node %s [%d]"),
549 dwIpAddr, dwNetMask, szName, dwIndex, dwType, m_szName, m_dwId);
550
551 // Find subnet to place interface object to
552 if (dwIpAddr != 0)
553 {
554 pCluster = GetMyCluster();
555 bAddToSubnet = (pCluster != NULL) ? !pCluster->IsSyncAddr(dwIpAddr) : TRUE;
556 DbgPrintf(5, _T("Node::CreateNewInterface: node=%s [%d] cluster=%s [%d] add=%d"),
557 m_szName, m_dwId, (pCluster != NULL) ? pCluster->Name() : _T("(null)"),
558 (pCluster != NULL) ? pCluster->Id() : 0, bAddToSubnet);
559 if (bAddToSubnet)
560 {
561 pSubnet = FindSubnetForNode(dwIpAddr);
562 if (pSubnet == NULL)
563 {
564 // Check if netmask is 0 (detect), and if yes, create
565 // new subnet with class mask
566 if (dwNetMask == 0)
567 {
568 bSyntheticMask = TRUE;
569 if (dwIpAddr < 0xE0000000)
570 {
571 dwNetMask = 0xFFFFFF00; // Class A, B or C
572 }
573 else
574 {
575 TCHAR szBuffer[16];
576
577 // Multicast address??
578 DbgPrintf(2, _T("Attempt to create interface object with multicast address %s"),
579 IpToStr(dwIpAddr, szBuffer));
580 }
581 }
582
583 // Create new subnet object
584 if (dwIpAddr < 0xE0000000)
585 {
586 pSubnet = new Subnet(dwIpAddr & dwNetMask, dwNetMask, m_dwZoneGUID, bSyntheticMask);
587 NetObjInsert(pSubnet, TRUE);
588 g_pEntireNet->AddSubnet(pSubnet);
589 }
590 }
591 else
592 {
593 // Set correct netmask if we was asked for it
594 if (dwNetMask == 0)
595 {
596 dwNetMask = pSubnet->IpNetMask();
597 bSyntheticMask = pSubnet->IsSyntheticMask();
598 }
599 }
600 }
601 }
602
603 // Create interface object
604 if (szName != NULL)
605 pInterface = new Interface(szName, dwIndex, dwIpAddr, dwNetMask, dwType);
606 else
607 pInterface = new Interface(dwIpAddr, dwNetMask, bSyntheticMask);
608 if (pbMacAddr != NULL)
609 pInterface->SetMacAddr(pbMacAddr);
610
611 // Insert to objects' list and generate event
612 NetObjInsert(pInterface, TRUE);
613 AddInterface(pInterface);
614 if (!m_bIsHidden)
615 pInterface->Unhide();
616 PostEvent(EVENT_INTERFACE_ADDED, m_dwId, "dsaad", pInterface->Id(),
617 pInterface->Name(), pInterface->IpAddr(),
618 pInterface->IpNetMask(), pInterface->IfIndex());
619
620 // Bind node to appropriate subnet
621 if (pSubnet != NULL)
622 {
623 pSubnet->AddNode(this);
624
625 // Check if subnet mask is correct on interface
626 if ((pSubnet->IpNetMask() != pInterface->IpNetMask()) &&
627 (!pSubnet->IsSyntheticMask()))
628 {
629 PostEvent(EVENT_INCORRECT_NETMASK, m_dwId, "idsaa", pInterface->Id(),
630 pInterface->IfIndex(), pInterface->Name(),
631 pInterface->IpNetMask(), pSubnet->IpNetMask());
632 }
633 }
634}
635
636
637//
638// Delete interface from node
639//
640
641void Node::DeleteInterface(Interface *pInterface)
642{
643 DWORD i;
644
645 // Check if we should unlink node from interface's subnet
646 if (pInterface->IpAddr() != 0)
647 {
648 BOOL bUnlink = TRUE;
649
650 LockChildList(FALSE);
651 for(i = 0; i < m_dwChildCount; i++)
652 if (m_pChildList[i]->Type() == OBJECT_INTERFACE)
653 if (m_pChildList[i] != pInterface)
654 if ((((Interface *)m_pChildList[i])->IpAddr() & ((Interface *)m_pChildList[i])->IpNetMask()) ==
655 (pInterface->IpAddr() & pInterface->IpNetMask()))
656 {
657 bUnlink = FALSE;
658 break;
659 }
660 UnlockChildList();
661
662 if (bUnlink)
663 {
664 // Last interface in subnet, should unlink node
665 Subnet *pSubnet = FindSubnetByIP(pInterface->IpAddr() & pInterface->IpNetMask());
666 if (pSubnet != NULL)
667 {
668 DeleteParent(pSubnet);
669 pSubnet->DeleteChild(this);
670 }
671 }
672 }
673 pInterface->Delete(FALSE);
674}
675
676
677//
678// Calculate node status based on child objects status
679//
680
681void Node::CalculateCompoundStatus(BOOL bForcedRecalc)
682{
683 int iOldStatus = m_iStatus;
684 static DWORD dwEventCodes[] = { EVENT_NODE_NORMAL, EVENT_NODE_MINOR,
685 EVENT_NODE_WARNING, EVENT_NODE_MAJOR, EVENT_NODE_CRITICAL,
686 EVENT_NODE_UNKNOWN, EVENT_NODE_UNMANAGED };
687
688 NetObj::CalculateCompoundStatus(bForcedRecalc);
689 if (m_iStatus != iOldStatus)
690 PostEvent(dwEventCodes[m_iStatus], m_dwId, "d", iOldStatus);
691}
692
693
694//
695// Perform status poll on node
696//
697
698void Node::StatusPoll(ClientSession *pSession, DWORD dwRqId, int nPoller)
699{
700 DWORD i, dwPollListSize, dwOldFlags = m_dwFlags;
701 NetObj *pPollerNode = NULL, **ppPollList;
702 BOOL bAllDown;
703 Queue *pQueue; // Delayed event queue
704 SNMP_Transport *pTransport;
705 Cluster *pCluster;
706 time_t tNow, tExpire;
707
708 pQueue = new Queue;
709 SetPollerInfo(nPoller, "wait for lock");
710 PollerLock();
711 m_pPollRequestor = pSession;
712 SendPollerMsg(dwRqId, "Starting status poll for node %s\r\n", m_szName);
713 DbgPrintf(5, "Starting status poll for node %s (ID: %d)", m_szName, m_dwId);
714
715 // Read capability expiration time and current time
716 tExpire = (time_t)ConfigReadULong(_T("CapabilityExpirationTime"), 604800);
717 tNow = time(NULL);
718
719 // Check SNMP agent connectivity
720restart_agent_check:
721 if ((m_dwFlags & NF_IS_SNMP) && (!(m_dwFlags & NF_DISABLE_SNMP)))
722 {
723 TCHAR szBuffer[256];
724 DWORD dwResult;
725
726 DbgPrintf(6, "StatusPoll(%s): check SNMP", m_szName);
727 pTransport = CreateSNMPTransport();
728 SetPollerInfo(nPoller, "check SNMP");
729 SendPollerMsg(dwRqId, "Checking SNMP agent connectivity\r\n");
730 dwResult = SnmpGet(m_iSNMPVersion, pTransport, m_szCommunityString,
731 ".1.3.6.1.2.1.1.2.0", NULL, 0, szBuffer, 256,
732 FALSE, FALSE);
733 if ((dwResult == SNMP_ERR_SUCCESS) || (dwResult == SNMP_ERR_NO_OBJECT))
734 {
735 if (m_dwDynamicFlags & NDF_SNMP_UNREACHABLE)
736 {
737 m_dwDynamicFlags &= ~NDF_SNMP_UNREACHABLE;
738 PostEventEx(pQueue, EVENT_SNMP_OK, m_dwId, NULL);
739 SendPollerMsg(dwRqId, POLLER_INFO "Connectivity with SNMP agent restored\r\n");
740 }
741 }
742 else
743 {
744 SendPollerMsg(dwRqId, POLLER_ERROR "SNMP agent unreachable\r\n");
745 if (m_dwDynamicFlags & NDF_SNMP_UNREACHABLE)
746 {
747 if ((tNow > m_tFailTimeSNMP + tExpire) &&
748 (!(m_dwDynamicFlags & NDF_UNREACHABLE)))
749 {
750 m_dwFlags &= ~NF_IS_SNMP;
751 m_dwDynamicFlags &= ~NDF_SNMP_UNREACHABLE;
752 m_szObjectId[0] = 0;
753 SendPollerMsg(dwRqId, POLLER_WARNING "Attribute isSNMP set to FALSE\r\n");
754 }
755 }
756 else
757 {
758 m_dwDynamicFlags |= NDF_SNMP_UNREACHABLE;
759 PostEventEx(pQueue, EVENT_SNMP_FAIL, m_dwId, NULL);
760 m_tFailTimeSNMP = tNow;
761 }
762 }
763 delete pTransport;
764 DbgPrintf(6, "StatusPoll(%s): SNMP check finished", m_szName);
765 }
766
767 // Check native agent connectivity
768 if ((m_dwFlags & NF_IS_NATIVE_AGENT) && (!(m_dwFlags & NF_DISABLE_NXCP)))
769 {
770 AgentConnection *pAgentConn;
771
772 DbgPrintf(6, "StatusPoll(%s): checking agent", m_szName);
773 SetPollerInfo(nPoller, "check agent");
774 SendPollerMsg(dwRqId, "Checking NetXMS agent connectivity\r\n");
775 pAgentConn = new AgentConnection(htonl(m_dwIpAddr), m_wAgentPort,
776 m_wAuthMethod, m_szSharedSecret);
777 SetAgentProxy(pAgentConn);
778 if (pAgentConn->Connect(g_pServerKey))
779 {
780 DbgPrintf(7, "StatusPoll(%s): connected to agent", m_szName);
781 if (m_dwDynamicFlags & NDF_AGENT_UNREACHABLE)
782 {
783 m_dwDynamicFlags &= ~NDF_AGENT_UNREACHABLE;
784 PostEventEx(pQueue, EVENT_AGENT_OK, m_dwId, NULL);
785 SendPollerMsg(dwRqId, POLLER_INFO "Connectivity with NetXMS agent restored\r\n");
786 }
787 pAgentConn->Disconnect();
788 DbgPrintf(7, "StatusPoll(%s): disconnected from agent", m_szName);
789 }
790 else
791 {
792 DbgPrintf(7, "StatusPoll(%s): agent unreachable", m_szName);
793 SendPollerMsg(dwRqId, POLLER_ERROR "NetXMS agent unreachable\r\n");
794 if (m_dwDynamicFlags & NDF_AGENT_UNREACHABLE)
795 {
796 if ((tNow > m_tFailTimeAgent + tExpire) &&
797 (!(m_dwDynamicFlags & NDF_UNREACHABLE)))
798 {
799 m_dwFlags &= ~NF_IS_NATIVE_AGENT;
800 m_dwDynamicFlags &= ~NDF_AGENT_UNREACHABLE;
801 m_szPlatformName[0] = 0;
802 m_szAgentVersion[0] = 0;
803 SendPollerMsg(dwRqId, POLLER_WARNING "Attribute isNetXMSAgent set to FALSE\r\n");
804 }
805 }
806 else
807 {
808 m_dwDynamicFlags |= NDF_AGENT_UNREACHABLE;
809 PostEventEx(pQueue, EVENT_AGENT_FAIL, m_dwId, NULL);
810 m_tFailTimeAgent = tNow;
811 }
812 }
813 DbgPrintf(7, "StatusPoll(%s): deleting agent connection", m_szName);
814 delete pAgentConn;
815 DbgPrintf(7, "StatusPoll(%s): agent connection deleted", m_szName);
816 }
817
818 SetPollerInfo(nPoller, "prepare polling list");
819
820 // Find service poller node object
821 LockData();
822 if (m_dwPollerNode != 0)
823 {
824 pPollerNode = FindObjectById(m_dwPollerNode);
825 if (pPollerNode != NULL)
826 {
827 if (pPollerNode->Type() != OBJECT_NODE)
828 pPollerNode = NULL;
829 }
830 }
831 UnlockData();
832
833 // If nothing found, use management server
834 if (pPollerNode == NULL)
835 {
836 pPollerNode = FindObjectById(g_dwMgmtNode);
837 if (pPollerNode != NULL)
838 pPollerNode->IncRefCount();
839 }
840 else
841 {
842 pPollerNode->IncRefCount();
843 }
844
845 // Create polling list
846 ppPollList = (NetObj **)malloc(sizeof(NetObj *) * m_dwChildCount);
847 LockChildList(FALSE);
848 for(i = 0, dwPollListSize = 0; i < m_dwChildCount; i++)
849 if (m_pChildList[i]->Status() != STATUS_UNMANAGED)
850 {
851 m_pChildList[i]->IncRefCount();
852 ppPollList[dwPollListSize++] = m_pChildList[i];
853 }
854 UnlockChildList();
855
856 // Poll interfaces and services
857 SetPollerInfo(nPoller, "child poll");
858 DbgPrintf(7, "StatusPoll(%s): starting child object poll", m_szName);
859 pCluster = GetMyCluster();
860 pTransport = CreateSNMPTransport();
861 for(i = 0; i < dwPollListSize; i++)
862 {
863 switch(ppPollList[i]->Type())
864 {
865 case OBJECT_INTERFACE:
866 DbgPrintf(7, "StatusPoll(%s): polling interface %d [%s]", m_szName, ppPollList[i]->Id(), ppPollList[i]->Name());
867 ((Interface *)ppPollList[i])->StatusPoll(pSession, dwRqId, pQueue,
868 (pCluster != NULL) ? pCluster->IsSyncAddr(((Interface *)ppPollList[i])->IpAddr()) : FALSE,
869 pTransport);
870 break;
871 case OBJECT_NETWORKSERVICE:
872 DbgPrintf(7, "StatusPoll(%s): polling network service %d [%s]", m_szName, ppPollList[i]->Id(), ppPollList[i]->Name());
873 ((NetworkService *)ppPollList[i])->StatusPoll(pSession, dwRqId,
874 (Node *)pPollerNode, pQueue);
875 break;
876 default:
877 break;
878 }
879 ppPollList[i]->DecRefCount();
880 }
881 delete pTransport;
882 safe_free(ppPollList);
883 DbgPrintf(7, "StatusPoll(%s): finished child object poll", m_szName);
884
885 // Check if entire node is down
886 LockChildList(FALSE);
887 if (m_dwChildCount > 0)
888 {
889 for(i = 0, bAllDown = TRUE; i < m_dwChildCount; i++)
890 if ((m_pChildList[i]->Type() == OBJECT_INTERFACE) &&
891 (m_pChildList[i]->Status() != STATUS_CRITICAL) &&
892 (m_pChildList[i]->Status() != STATUS_UNKNOWN) &&
893 (m_pChildList[i]->Status() != STATUS_UNMANAGED) &&
894 (m_pChildList[i]->Status() != STATUS_DISABLED))
895 {
896 bAllDown = FALSE;
897 break;
898 }
899 }
900 else
901 {
902 bAllDown = FALSE;
903 }
904 UnlockChildList();
905 if (bAllDown && (m_dwFlags & NF_IS_NATIVE_AGENT) &&
906 (!(m_dwFlags & NF_DISABLE_NXCP)))
907 if (!(m_dwDynamicFlags & NDF_AGENT_UNREACHABLE))
908 bAllDown = FALSE;
909 if (bAllDown && (m_dwFlags & NF_IS_SNMP) &&
910 (!(m_dwFlags & NF_DISABLE_SNMP)))
911 if (!(m_dwDynamicFlags & NDF_SNMP_UNREACHABLE))
912 bAllDown = FALSE;
913 if (bAllDown)
914 {
915 if (!(m_dwDynamicFlags & NDF_UNREACHABLE))
916 {
917 m_dwDynamicFlags |= NDF_UNREACHABLE;
918 PostEvent(EVENT_NODE_DOWN, m_dwId, NULL);
919 SendPollerMsg(dwRqId, POLLER_ERROR "Node is unreachable\r\n");
920 }
921 else
922 {
923 SendPollerMsg(dwRqId, POLLER_WARNING "Node is still unreachable\r\n");
924 }
925 }
926 else
927 {
928 if (m_dwDynamicFlags & NDF_UNREACHABLE)
929 {
930 m_dwDynamicFlags &= ~(NDF_UNREACHABLE | NDF_SNMP_UNREACHABLE | NDF_AGENT_UNREACHABLE);
931 PostEvent(EVENT_NODE_UP, m_dwId, NULL);
932 SendPollerMsg(dwRqId, POLLER_INFO "Node recovered from unreachable state\r\n");
933 goto restart_agent_check;
934 }
935 else
936 {
937 SendPollerMsg(dwRqId, POLLER_INFO "Node is connected\r\n");
938 }
939 }
940
941 // Send delayed events and destroy delayed event queue
942 ResendEvents(pQueue);
943 delete pQueue;
944
945 SetPollerInfo(nPoller, "cleanup");
946 if (pPollerNode != NULL)
947 pPollerNode->DecRefCount();
948
949 if (dwOldFlags != m_dwFlags)
950 {
951 PostEvent(EVENT_NODE_FLAGS_CHANGED, m_dwId, "xx", dwOldFlags, m_dwFlags);
952 LockData();
953 Modify();
954 UnlockData();
955 }
956
957 CalculateCompoundStatus();
958 m_tLastStatusPoll = time(NULL);
959 SendPollerMsg(dwRqId, "Finished status poll for node %s\r\n"
960 "Node status after poll is %s\r\n", m_szName, g_szStatusTextSmall[m_iStatus]);
961 m_pPollRequestor = NULL;
962 if (dwRqId == 0)
963 m_dwDynamicFlags &= ~NDF_QUEUED_FOR_STATUS_POLL;
964 PollerUnlock();
965 DbgPrintf(5, "Finished status poll for node %s (ID: %d)", m_szName, m_dwId);
966}
967
968
969//
970// Perform configuration poll on node
971//
972
973void Node::ConfigurationPoll(ClientSession *pSession, DWORD dwRqId,
974 int nPoller, DWORD dwNetMask)
975{
976 DWORD i, dwOldFlags = m_dwFlags, dwAddr, rcc, dwNumParams;
977 NXC_AGENT_PARAM *pParamList;
978 Interface **ppDeleteList;
979 int j, iDelCount;
980 AgentConnection *pAgentConn;
981 INTERFACE_LIST *pIfList;
982 char szBuffer[4096];
983 Cluster *pCluster;
984 SNMP_Transport *pTransport;
985 Template *pTemplate;
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
1587 // Apply system templates
1588 pTemplate = FindTemplateByName(_T("@System.Agent"));
1589 if (pTemplate != NULL)
1590 {
1591 if (IsNativeAgent())
1592 {
1593 if (!pTemplate->IsChild(m_dwId))
1594 {
1595 pTemplate->ApplyToNode(this);
1596 }
1597 }
1598 else
1599 {
1600 if (pTemplate->IsChild(m_dwId))
1601 {
1602 pTemplate->DeleteChild(this);
1603 DeleteParent(pTemplate);
1604 pTemplate->QueueRemoveFromNode(m_dwId, TRUE);
1605 }
1606 }
1607 }
1608
1609 pTemplate = FindTemplateByName(_T("@System.SNMP"));
1610 if (pTemplate != NULL)
1611 {
1612 if (IsSNMPSupported())
1613 {
1614 if (!pTemplate->IsChild(m_dwId))
1615 {
1616 pTemplate->ApplyToNode(this);
1617 }
1618 }
1619 else
1620 {
1621 if (pTemplate->IsChild(m_dwId))
1622 {
1623 pTemplate->DeleteChild(this);
1624 DeleteParent(pTemplate);
1625 pTemplate->QueueRemoveFromNode(m_dwId, TRUE);
1626 }
1627 }
1628 }
1629
1630 SendPollerMsg(dwRqId, _T("Finished configuration poll for node %s\r\n")
1631 _T("Node configuration was%schanged after poll\r\n"),
1632 m_szName, bHasChanges ? _T(" ") : _T(" not "));
1633 }
1634
1635 // Finish configuration poll
1636 SetPollerInfo(nPoller, "cleanup");
1637 if (dwRqId == 0)
1638 m_dwDynamicFlags &= ~NDF_QUEUED_FOR_CONFIG_POLL;
1639 m_dwDynamicFlags &= ~NDF_RECHECK_CAPABILITIES;
1640 PollerUnlock();
1641 DbgPrintf(4, "Finished configuration poll for node %s (ID: %d)", m_szName, m_dwId);
1642
1643 if (bHasChanges)
1644 {
1645 LockData();
1646 Modify();
1647 UnlockData();
1648 }
1649}
1650
1651
1652//
1653// Connect to native agent
1654//
1655
1656BOOL Node::ConnectToAgent(void)
1657{
1658 BOOL bRet;
1659
1660 // Create new agent connection object if needed
1661 if (m_pAgentConnection == NULL)
1662 m_pAgentConnection = new AgentConnectionEx(htonl(m_dwIpAddr), m_wAgentPort, m_wAuthMethod, m_szSharedSecret);
1663
1664 // Check if we already connected
1665 if (m_pAgentConnection->Nop() == ERR_SUCCESS)
1666 return TRUE;
1667
1668 // Close current connection or clean up after broken connection
1669 m_pAgentConnection->Disconnect();
1670 m_pAgentConnection->SetPort(m_wAgentPort);
1671 m_pAgentConnection->SetAuthData(m_wAuthMethod, m_szSharedSecret);
1672 SetAgentProxy(m_pAgentConnection);
1673 bRet = m_pAgentConnection->Connect(g_pServerKey);
1674 if (bRet)
1675 {
1676 m_pAgentConnection->SetCommandTimeout(g_dwAgentCommandTimeout);
1677 m_pAgentConnection->EnableTraps();
1678 }
1679 return bRet;
1680}
1681
1682
1683//
1684// Get item's value via SNMP
1685//
1686
1687DWORD Node::GetItemFromSNMP(const char *szParam, DWORD dwBufSize, char *szBuffer)
1688{
1689 DWORD dwResult;
1690
1691 if ((m_dwDynamicFlags & NDF_SNMP_UNREACHABLE) ||
1692 (m_dwDynamicFlags & NDF_UNREACHABLE))
1693 {
1694 dwResult = SNMP_ERR_COMM;
1695 }
1696 else
1697 {
1698 SNMP_Transport *pTransport;
1699
1700 pTransport = CreateSNMPTransport();
1701 dwResult = SnmpGet(m_iSNMPVersion, pTransport, m_szCommunityString,
1702 szParam, NULL, 0, szBuffer, dwBufSize, FALSE, TRUE);
1703 delete pTransport;
1704 }
1705 return (dwResult == SNMP_ERR_SUCCESS) ? DCE_SUCCESS :
1706 ((dwResult == SNMP_ERR_NO_OBJECT) ? DCE_NOT_SUPPORTED : DCE_COMM_ERROR);
1707}
1708
1709
1710//
1711// Get item's value via SNMP from CheckPoint's agent
1712//
1713
1714DWORD Node::GetItemFromCheckPointSNMP(const char *szParam, DWORD dwBufSize, char *szBuffer)
1715{
1716 DWORD dwResult;
1717
1718 if ((m_dwDynamicFlags & NDF_CPSNMP_UNREACHABLE) ||
1719 (m_dwDynamicFlags & NDF_UNREACHABLE))
1720 {
1721 dwResult = SNMP_ERR_COMM;
1722 }
1723 else
1724 {
1725 SNMP_Transport *pTransport;
1726
1727 pTransport = new SNMP_UDPTransport;
1728 ((SNMP_UDPTransport *)pTransport)->CreateUDPTransport(NULL, htonl(m_dwIpAddr), CHECKPOINT_SNMP_PORT);
1729 dwResult = SnmpGet(SNMP_VERSION_1, pTransport,
1730 m_szCommunityString, szParam, NULL, 0, szBuffer,
1731 dwBufSize, FALSE, TRUE);
1732 delete pTransport;
1733 }
1734 return (dwResult == SNMP_ERR_SUCCESS) ? DCE_SUCCESS :
1735 ((dwResult == SNMP_ERR_NO_OBJECT) ? DCE_NOT_SUPPORTED : DCE_COMM_ERROR);
1736}
1737
1738
1739//
1740// Get item's value via native agent
1741//
1742
1743DWORD Node::GetItemFromAgent(const char *szParam, DWORD dwBufSize, char *szBuffer)
1744{
1745 DWORD dwError, dwResult = DCE_COMM_ERROR;
1746 DWORD dwTries = 3;
1747
1748 if ((m_dwDynamicFlags & NDF_AGENT_UNREACHABLE) ||
1749 (m_dwDynamicFlags & NDF_UNREACHABLE))
1750 return DCE_COMM_ERROR;
1751
1752 AgentLock();
1753
1754 // Establish connection if needed
1755 if (m_pAgentConnection == NULL)
1756 if (!ConnectToAgent())
1757 goto end_loop;
1758
1759 // Get parameter from agent
1760 while(dwTries-- > 0)
1761 {
1762 dwError = m_pAgentConnection->GetParameter((char *)szParam, dwBufSize, szBuffer);
1763 switch(dwError)
1764 {
1765 case ERR_SUCCESS:
1766 dwResult = DCE_SUCCESS;
1767 goto end_loop;
1768 case ERR_UNKNOWN_PARAMETER:
1769 dwResult = DCE_NOT_SUPPORTED;
1770 goto end_loop;
1771 case ERR_NOT_CONNECTED:
1772 case ERR_CONNECTION_BROKEN:
1773 if (!ConnectToAgent())
1774 goto end_loop;
1775 break;
1776 case ERR_REQUEST_TIMEOUT:
1777 // Reset connection to agent after timeout
1778 DbgPrintf(7, _T("Node(%s)->GetItemFromAgent(%s): timeout; resetting connection to agent..."), m_szName, szParam);
1779 delete_and_null(m_pAgentConnection);
1780 if (!ConnectToAgent())
1781 goto end_loop;
1782 DbgPrintf(7, _T("Node(%s)->GetItemFromAgent(%s): connection to agent restored successfully"), m_szName, szParam);
1783 break;
1784 }
1785 }
1786
1787end_loop:
1788 AgentUnlock();
1789 DbgPrintf(7, "Node(%s)->GetItemFromAgent(%s): dwError=%d dwResult=%d",
1790 m_szName, szParam, dwError, dwResult);
1791 return dwResult;
1792}
1793
1794
1795//
1796// Get value for server's internal parameter
1797//
1798
1799DWORD Node::GetInternalItem(const char *szParam, DWORD dwBufSize, char *szBuffer)
1800{
1801 DWORD dwError = DCE_SUCCESS;
1802
1803 if (!stricmp(szParam, "Status"))
1804 {
1805 sprintf(szBuffer, "%d", m_iStatus);
1806 }
1807 else if (!stricmp(szParam, "Dummy"))
1808 {
1809 _tcscpy(szBuffer, _T("0"));
1810 }
1811 else if (!stricmp(szParam, "AgentStatus"))
1812 {
1813 if (m_dwFlags & NF_IS_NATIVE_AGENT)
1814 {
1815 szBuffer[0] = (m_dwDynamicFlags & NDF_AGENT_UNREACHABLE) ? '1' : '0';
1816 szBuffer[1] = 0;
1817 }
1818 else
1819 {
1820 dwError = DCE_NOT_SUPPORTED;
1821 }
1822 }
1823 else if (MatchString("ChildStatus(*)", szParam, FALSE))
1824 {
1825 char *pEnd, szArg[256];
1826 DWORD i, dwId;
1827 NetObj *pObject = NULL;
1828
1829 NxGetParameterArg((char *)szParam, 1, szArg, 256);
1830 dwId = strtoul(szArg, &pEnd, 0);
1831 if (*pEnd != 0)
1832 {
1833 // Argument is object's name
1834 dwId = 0;
1835 }
1836
1837 // Find child object with requested ID or name
1838 LockChildList(FALSE);
1839 for(i = 0; i < m_dwChildCount; i++)
1840 {
1841 if (((dwId == 0) && (!stricmp(m_pChildList[i]->Name(), szArg))) ||
1842 (dwId == m_pChildList[i]->Id()))
1843 {
1844 pObject = m_pChildList[i];
1845 break;
1846 }
1847 }
1848 UnlockChildList();
1849
1850 if (pObject != NULL)
1851 {
1852 sprintf(szBuffer, "%d", pObject->Status());
1853 }
1854 else
1855 {
1856 dwError = DCE_NOT_SUPPORTED;
1857 }
1858 }
1859 else if (MatchString("ConditionStatus(*)", szParam, FALSE))
1860 {
1861 char *pEnd, szArg[256];
1862 DWORD dwId;
1863 NetObj *pObject = NULL;
1864
1865 NxGetParameterArg((char *)szParam, 1, szArg, 256);
1866 dwId = strtoul(szArg, &pEnd, 0);
1867 if (*pEnd == 0)
1868 {
1869 pObject = FindObjectById(dwId);
1870 if (pObject != NULL)
1871 if (pObject->Type() != OBJECT_CONDITION)
1872 pObject = NULL;
1873 }
1874 else
1875 {
1876 // Argument is object's name
1877 pObject = FindObjectByName(szArg, OBJECT_CONDITION);
1878 }
1879
1880 if (pObject != NULL)
1881 {
1882 if (pObject->IsTrustedNode(m_dwId))
1883 {
1884 sprintf(szBuffer, "%d", pObject->Status());
1885 }
1886 else
1887 {
1888 dwError = DCE_NOT_SUPPORTED;
1889 }
1890 }
1891 else
1892 {
1893 dwError = DCE_NOT_SUPPORTED;
1894 }
1895 }
1896 else if (m_dwFlags & NF_IS_LOCAL_MGMT)
1897 {
1898 if (!stricmp(szParam, "Server.AverageDCPollerQueueSize"))
1899 {
1900 sprintf(szBuffer, "%f", g_dAvgPollerQueueSize);
1901 }
1902 else if (!stricmp(szParam, "Server.AverageDBWriterQueueSize"))
1903 {
1904 sprintf(szBuffer, "%f", g_dAvgDBWriterQueueSize);
1905 }
1906 else if (!stricmp(szParam, "Server.AverageStatusPollerQueueSize"))
1907 {
1908 sprintf(szBuffer, "%f", g_dAvgStatusPollerQueueSize);
1909 }
1910 else if (!stricmp(szParam, "Server.AverageConfigurationPollerQueueSize"))
1911 {
1912 sprintf(szBuffer, "%f", g_dAvgConfigPollerQueueSize);
1913 }
1914 else if (!stricmp(szParam, "Server.AverageDCIQueuingTime"))
1915 {
1916 sprintf(szBuffer, "%u", g_dwAvgDCIQueuingTime);
1917 }
1918 else if (!stricmp(szParam, "Server.TotalEventsProcessed"))
1919 {
1920 sprintf(szBuffer, INT64_FMT, g_totalEventsProcessed);
1921 }
1922 else
1923 {
1924 dwError = DCE_NOT_SUPPORTED;
1925 }
1926 }
1927 else
1928 {
1929 dwError = DCE_NOT_SUPPORTED;
1930 }
1931
1932 return dwError;
1933}
1934
1935
1936//
1937// Get item's value for client
1938//
1939
1940DWORD Node::GetItemForClient(int iOrigin, const char *pszParam, char *pszBuffer, DWORD dwBufSize)
1941{
1942 DWORD dwResult = 0, dwRetCode;
1943
1944 // Get data from node
1945 switch(iOrigin)
1946 {
1947 case DS_INTERNAL:
1948 dwRetCode = GetInternalItem(pszParam, dwBufSize, pszBuffer);
1949 break;
1950 case DS_NATIVE_AGENT:
1951 dwRetCode = GetItemFromAgent(pszParam, dwBufSize, pszBuffer);
1952 break;
1953 case DS_SNMP_AGENT:
1954 dwRetCode = GetItemFromSNMP(pszParam, dwBufSize, pszBuffer);
1955 break;
1956 case DS_CHECKPOINT_AGENT:
1957 dwRetCode = GetItemFromCheckPointSNMP(pszParam, dwBufSize, pszBuffer);
1958 break;
1959 default:
1960 dwResult = RCC_INVALID_ARGUMENT;
1961 break;
1962 }
1963
1964 // Translate return code to RCC
1965 if (dwResult != RCC_INVALID_ARGUMENT)
1966 {
1967 switch(dwRetCode)
1968 {
1969 case DCE_SUCCESS:
1970 dwResult = RCC_SUCCESS;
1971 break;
1972 case DCE_COMM_ERROR:
1973 dwResult = RCC_COMM_FAILURE;
1974 break;
1975 case DCE_NOT_SUPPORTED:
1976 dwResult = RCC_DCI_NOT_SUPPORTED;
1977 break;
1978 default:
1979 dwResult = RCC_SYSTEM_FAILURE;
1980 break;
1981 }
1982 }
1983
1984 return dwResult;
1985}
1986
1987
1988//
1989// Put items which requires polling into the queue
1990//
1991
1992void Node::QueueItemsForPolling(Queue *pPollerQueue)
1993{
1994 DWORD i;
1995 time_t currTime;
1996
1997 if ((m_iStatus == STATUS_UNMANAGED) ||
1998 (m_dwFlags & NF_DISABLE_DATA_COLLECT) ||
1999 (m_bIsDeleted))
2000 return; // Do not collect data for unmanaged nodes or if data collection is disabled
2001
2002 currTime = time(NULL);
2003
2004 LockData();
2005 for(i = 0; i < m_dwNumItems; i++)
2006 {
2007 if (m_ppItems[i]->ReadyForPolling(currTime))
2008 {
2009 m_ppItems[i]->SetBusyFlag(TRUE);
2010 IncRefCount(); // Increment reference count for each queued DCI
2011 pPollerQueue->Put(m_ppItems[i]);
2012 }
2013 }
2014 UnlockData();
2015}
2016
2017
2018//
2019// Create CSCP message with object's data
2020//
2021
2022void Node::CreateMessage(CSCPMessage *pMsg)
2023{
2024 Template::CreateMessage(pMsg);
2025 pMsg->SetVariable(VID_FLAGS, m_dwFlags);
2026 pMsg->SetVariable(VID_AGENT_PORT, m_wAgentPort);
2027 pMsg->SetVariable(VID_AUTH_METHOD, m_wAuthMethod);
2028 pMsg->SetVariable(VID_SHARED_SECRET, m_szSharedSecret);
2029 pMsg->SetVariable(VID_COMMUNITY_STRING, m_szCommunityString);
2030 pMsg->SetVariable(VID_SNMP_OID, m_szObjectId);
2031 pMsg->SetVariable(VID_NODE_TYPE, m_dwNodeType);
2032 pMsg->SetVariable(VID_SNMP_VERSION, (WORD)m_iSNMPVersion);
2033 pMsg->SetVariable(VID_AGENT_VERSION, m_szAgentVersion);
2034 pMsg->SetVariable(VID_PLATFORM_NAME, m_szPlatformName);
2035 pMsg->SetVariable(VID_POLLER_NODE_ID, m_dwPollerNode);
2036 pMsg->SetVariable(VID_ZONE_GUID, m_dwZoneGUID);
2037 pMsg->SetVariable(VID_PROXY_NODE, m_dwProxyNode);
2038 pMsg->SetVariable(VID_SNMP_PROXY, m_dwSNMPProxy);
2039 pMsg->SetVariable(VID_REQUIRED_POLLS, (WORD)m_iRequiredPollCount);
2040 pMsg->SetVariable(VID_SYS_DESCRIPTION, m_szSysDescription);
2041 pMsg->SetVariable(VID_USE_IFXTABLE, (WORD)m_nUseIfXTable);
2042}
2043
2044
2045//
2046// Modify object from message
2047//
2048
2049DWORD Node::ModifyFromMessage(CSCPMessage *pRequest, BOOL bAlreadyLocked)
2050{
2051 if (!bAlreadyLocked)
2052 LockData();
2053
2054 // Change primary IP address
2055 if (pRequest->IsVariableExist(VID_IP_ADDRESS))
2056 {
2057 DWORD i, dwIpAddr;
2058
2059 dwIpAddr = pRequest->GetVariableLong(VID_IP_ADDRESS);
2060
2061 // Check if received IP address is one of node's interface addresses
2062 LockChildList(FALSE);
2063 for(i = 0; i < m_dwChildCount; i++)
2064 if ((m_pChildList[i]->Type() == OBJECT_INTERFACE) &&
2065 (m_pChildList[i]->IpAddr() == dwIpAddr))
2066 break;
2067 UnlockChildList();
2068 if (i == m_dwChildCount)
2069 {
2070 UnlockData();
2071 return RCC_INVALID_IP_ADDR;
2072 }
2073
2074 UpdateNodeIndex(m_dwIpAddr, dwIpAddr, this);
2075 m_dwIpAddr = dwIpAddr;
2076 }
2077
2078 // Poller node ID
2079 if (pRequest->IsVariableExist(VID_POLLER_NODE_ID))
2080 {
2081 DWORD dwNodeId;
2082 NetObj *pObject;
2083
2084 dwNodeId = pRequest->GetVariableLong(VID_POLLER_NODE_ID);
2085 pObject = FindObjectById(dwNodeId);
2086
2087 // Check if received id is a valid node id
2088 if (pObject == NULL)
2089 {
2090 UnlockData();
2091 return RCC_INVALID_OBJECT_ID;
2092 }
2093 if (pObject->Type() != OBJECT_NODE)
2094 {
2095 UnlockData();
2096 return RCC_INVALID_OBJECT_ID;
2097 }
2098
2099 m_dwPollerNode = dwNodeId;
2100 }
2101
2102 // Change listen port of native agent
2103 if (pRequest->IsVariableExist(VID_AGENT_PORT))
2104 m_wAgentPort = pRequest->GetVariableShort(VID_AGENT_PORT);
2105
2106 // Change authentication method of native agent
2107 if (pRequest->IsVariableExist(VID_AUTH_METHOD))
2108 m_wAuthMethod = pRequest->GetVariableShort(VID_AUTH_METHOD);
2109
2110 // Change shared secret of native agent
2111 if (pRequest->IsVariableExist(VID_SHARED_SECRET))
2112 pRequest->GetVariableStr(VID_SHARED_SECRET, m_szSharedSecret, MAX_SECRET_LENGTH);
2113
2114 // Change SNMP protocol version
2115 if (pRequest->IsVariableExist(VID_SNMP_VERSION))
2116 m_iSNMPVersion = pRequest->GetVariableShort(VID_SNMP_VERSION);
2117
2118 // Change SNMP community string
2119 if (pRequest->IsVariableExist(VID_COMMUNITY_STRING))
2120 pRequest->GetVariableStr(VID_COMMUNITY_STRING, m_szCommunityString, MAX_COMMUNITY_LENGTH);
2121
2122 // Change proxy node
2123 if (pRequest->IsVariableExist(VID_PROXY_NODE))
2124 m_dwProxyNode = pRequest->GetVariableLong(VID_PROXY_NODE);
2125
2126 // Change SNMP proxy node
2127 if (pRequest->IsVariableExist(VID_SNMP_PROXY))
2128 m_dwSNMPProxy = pRequest->GetVariableLong(VID_SNMP_PROXY);
2129
2130 // Number of required polls
2131 if (pRequest->IsVariableExist(VID_REQUIRED_POLLS))
2132 m_iRequiredPollCount = (int)pRequest->GetVariableShort(VID_REQUIRED_POLLS);
2133
2134 // Enable/disable usage of ifXTable
2135 if (pRequest->IsVariableExist(VID_USE_IFXTABLE))
2136 m_nUseIfXTable = (BYTE)pRequest->GetVariableShort(VID_USE_IFXTABLE);
2137
2138 // Change flags
2139 if (pRequest->IsVariableExist(VID_FLAGS))
2140 {
2141 m_dwFlags &= NF_SYSTEM_FLAGS;
2142 m_dwFlags |= pRequest->GetVariableLong(VID_FLAGS) & NF_USER_FLAGS;
2143 }
2144
2145 return Template::ModifyFromMessage(pRequest, TRUE);
2146}
2147
2148
2149//
2150// Wakeup node using magic packet
2151//
2152
2153DWORD Node::WakeUp(void)
2154{
2155 DWORD i, dwResult = RCC_NO_WOL_INTERFACES;
2156
2157 LockChildList(FALSE);
2158
2159 for(i = 0; i < m_dwChildCount; i++)
2160 if ((m_pChildList[i]->Type() == OBJECT_INTERFACE) &&
2161 (m_pChildList[i]->Status() != STATUS_UNMANAGED) &&
2162 (m_pChildList[i]->IpAddr() != 0))
2163 {
2164 dwResult = ((Interface *)m_pChildList[i])->WakeUp();
2165 break;
2166 }
2167
2168 UnlockChildList();
2169 return dwResult;
2170}
2171
2172
2173//
2174// Get status of interface with given index from SNMP agent
2175//
2176
2177int Node::GetInterfaceStatusFromSNMP(SNMP_Transport *pTransport, DWORD dwIndex)
2178{
2179 return SnmpGetInterfaceStatus(m_iSNMPVersion, pTransport, m_szCommunityString, dwIndex);
2180}
2181
2182
2183//
2184// Get status of interface with given index from native agent
2185//
2186
2187int Node::GetInterfaceStatusFromAgent(DWORD dwIndex)
2188{
2189 char szParam[128], szBuffer[32];
2190 DWORD dwAdminStatus, dwLinkState;
2191 int iStatus;
2192
2193 // Get administrative status
2194 sprintf(szParam, "Net.Interface.AdminStatus(%u)", dwIndex);
2195 if (GetItemFromAgent(szParam, 32, szBuffer) == DCE_SUCCESS)
2196 {
2197 dwAdminStatus = strtoul(szBuffer, NULL, 0);
2198
2199 switch(dwAdminStatus)
2200 {
2201 case 3:
2202 iStatus = STATUS_TESTING;
2203 break;
2204 case 2:
2205 case 0: // Agents before 0.2.1 may return 0 instead of 2
2206 iStatus = STATUS_DISABLED;
2207 break;
2208 case 1: // Interface administratively up, check link state
2209 sprintf(szParam, "Net.Interface.Link(%u)", dwIndex);
2210 if (GetItemFromAgent(szParam, 32, szBuffer) == DCE_SUCCESS)
2211 {
2212 dwLinkState = strtoul(szBuffer, NULL, 0);
2213 iStatus = (dwLinkState == 0) ? STATUS_CRITICAL : STATUS_NORMAL;
2214 }
2215 else
2216 {
2217 iStatus = STATUS_UNKNOWN;
2218 }
2219 break;
2220 default:
2221 iStatus = STATUS_UNKNOWN;
2222 break;
2223 }
2224 }
2225 else
2226 {
2227 iStatus = STATUS_UNKNOWN;
2228 }
2229
2230 return iStatus;
2231}
2232
2233
2234//
2235// Put list of supported parameters into CSCP message
2236//
2237
2238void Node::WriteParamListToMessage(CSCPMessage *pMsg)
2239{
2240 DWORD i, dwId;
2241
2242 LockData();
2243 if (m_pParamList != NULL)
2244 {
2245 pMsg->SetVariable(VID_NUM_PARAMETERS, m_dwNumParams);
2246 for(i = 0, dwId = VID_PARAM_LIST_BASE; i < m_dwNumParams; i++)
2247 {
2248 pMsg->SetVariable(dwId++, m_pParamList[i].szName);
2249 pMsg->SetVariable(dwId++, m_pParamList[i].szDescription);
2250 pMsg->SetVariable(dwId++, (WORD)m_pParamList[i].iDataType);
2251 }
2252 DbgPrintf(6, _T("Node[%s]::WriteParamListToMessage(): sending %d parameters"), m_szName, m_dwNumParams);
2253 }
2254 else
2255 {
2256 DbgPrintf(6, _T("Node[%s]::WriteParamListToMessage(): m_pParamList == NULL"), m_szName);
2257 pMsg->SetVariable(VID_NUM_PARAMETERS, (DWORD)0);
2258 }
2259 UnlockData();
2260}
2261
2262
2263//
2264// Open list of supported parameters for reading
2265//
2266
2267void Node::OpenParamList(DWORD *pdwNumParams, NXC_AGENT_PARAM **ppParamList)
2268{
2269 LockData();
2270 *pdwNumParams = m_dwNumParams;
2271 *ppParamList = m_pParamList;
2272}
2273
2274
2275//
2276// Check status of network service
2277//
2278
2279DWORD Node::CheckNetworkService(DWORD *pdwStatus, DWORD dwIpAddr, int iServiceType,
2280 WORD wPort, WORD wProto, TCHAR *pszRequest,
2281 TCHAR *pszResponse)
2282{
2283 DWORD dwError = ERR_NOT_CONNECTED;
2284
2285 if ((m_dwFlags & NF_IS_NATIVE_AGENT) &&
2286 (!(m_dwDynamicFlags & NDF_AGENT_UNREACHABLE)) &&
2287 (!(m_dwDynamicFlags & NDF_UNREACHABLE)))
2288 {
2289 AgentConnection *pConn;
2290
2291 pConn = CreateAgentConnection();
2292 if (pConn != NULL)
2293 {
2294 dwError = pConn->CheckNetworkService(pdwStatus, dwIpAddr, iServiceType,
2295 wPort, wProto, pszRequest, pszResponse);
2296 pConn->Disconnect();
2297 delete pConn;
2298 }
2299 }
2300 return dwError;
2301}
2302
2303
2304//
2305// Handler for object deletion
2306//
2307
2308void Node::OnObjectDelete(DWORD dwObjectId)
2309{
2310 if (dwObjectId == m_dwPollerNode)
2311 {
2312 // If deleted object is our poller node, change it to default
2313 /* LOCK? */
2314 m_dwPollerNode = 0;
2315 Modify();
2316 DbgPrintf(3, _T("Node \"%s\": poller node %d deleted"), m_szName, dwObjectId);
2317 }
2318}
2319
2320
2321//
2322// Check node for OSPF support
2323//
2324
2325void Node::CheckOSPFSupport(SNMP_Transport *pTransport)
2326{
2327 LONG nAdminStatus;
2328
2329 if (SnmpGet(m_iSNMPVersion, pTransport, m_szCommunityString,
2330 ".1.3.6.1.2.1.14.1.2.0", NULL, 0, &nAdminStatus, sizeof(LONG),
2331 FALSE, FALSE) == SNMP_ERR_SUCCESS)
2332 {
2333 LockData();
2334 if (nAdminStatus)
2335 {
2336 m_dwFlags |= NF_IS_OSPF;
2337 }
2338 else
2339 {
2340 m_dwFlags &= ~NF_IS_OSPF;
2341 }
2342 UnlockData();
2343 }
2344}
2345
2346
2347//
2348// Create ready to use agent connection
2349//
2350
2351AgentConnection *Node::CreateAgentConnection(void)
2352{
2353 AgentConnection *pConn;
2354
2355 if ((!(m_dwFlags & NF_IS_NATIVE_AGENT)) ||
2356 (m_dwDynamicFlags & NDF_AGENT_UNREACHABLE) ||
2357 (m_dwDynamicFlags & NDF_UNREACHABLE))
2358 return NULL;
2359
2360 pConn = new AgentConnection(htonl(m_dwIpAddr), m_wAgentPort,
2361 m_wAuthMethod, m_szSharedSecret);
2362 SetAgentProxy(pConn);
2363 if (!pConn->Connect(g_pServerKey))
2364 {
2365 delete pConn;
2366 pConn = NULL;
2367 }
2368 return pConn;
2369}
2370
2371
2372//
2373// Get last collected values of all DCIs
2374//
2375
2376DWORD Node::GetLastValues(CSCPMessage *pMsg)
2377{
2378 DWORD i, dwId, dwCount;
2379
2380 LockData();
2381
2382 for(i = 0, dwId = VID_DCI_VALUES_BASE, dwCount = 0; i < m_dwNumItems; i++)
2383 {
2384 if (_tcsnicmp(m_ppItems[i]->Description(), _T("@system."), 8))
2385 {
2386 m_ppItems[i]->GetLastValue(pMsg, dwId);
2387 dwId += 10;
2388 dwCount++;
2389 }
2390 }
2391 pMsg->SetVariable(VID_NUM_ITEMS, dwCount);
2392
2393 UnlockData();
2394 return RCC_SUCCESS;
2395}
2396
2397
2398//
2399// Clean expired DCI data
2400//
2401
2402void Node::CleanDCIData(void)
2403{
2404 DWORD i;
2405
2406 LockData();
2407 for(i = 0; i < m_dwNumItems; i++)
2408 m_ppItems[i]->DeleteExpiredData();
2409 UnlockData();
2410}
2411
2412
2413//
2414// Apply DCI from template
2415// pItem passed to this method should be a template's DCI
2416//
2417
2418BOOL Node::ApplyTemplateItem(DWORD dwTemplateId, DCItem *pItem)
2419{
2420 BOOL bResult = TRUE;
2421 DWORD i;
2422 DCItem *pNewItem;
2423
2424 LockData();
2425
2426 DbgPrintf(5, "Applying item \"%s\" to node \"%s\"", pItem->Name(), m_szName);
2427
2428 // Check if that template item exists
2429 for(i = 0; i < m_dwNumItems; i++)
2430 if ((m_ppItems[i]->TemplateId() == dwTemplateId) &&
2431 (m_ppItems[i]->TemplateItemId() == pItem->Id()))
2432 break; // Item with specified id already exist
2433
2434 if (i == m_dwNumItems)
2435 {
2436 // New item from template, just add it
2437 pNewItem = new DCItem(pItem);
2438 pNewItem->SetTemplateId(dwTemplateId, pItem->Id());
2439 pNewItem->ChangeBinding(CreateUniqueId(IDG_ITEM), this, TRUE);
2440 bResult = AddItem(pNewItem, TRUE);
2441 }
2442 else
2443 {
2444 // Update existing item
2445 m_ppItems[i]->UpdateFromTemplate(pItem);
2446 Modify();
2447 }
2448
2449 UnlockData();
2450 return bResult;
2451}
2452
2453
2454//
2455// Clean deleted template items from node's DCI list
2456// Arguments is template id and list of valid template item ids.
2457// all items related to given template and not presented in list should be deleted.
2458//
2459
2460void Node::CleanDeletedTemplateItems(DWORD dwTemplateId, DWORD dwNumItems, DWORD *pdwItemList)
2461{
2462 DWORD i, j, dwNumDeleted, *pdwDeleteList;
2463
2464 LockData();
2465
2466 pdwDeleteList = (DWORD *)malloc(sizeof(DWORD) * m_dwNumItems);
2467 dwNumDeleted = 0;
2468
2469 for(i = 0; i < m_dwNumItems; i++)
2470 if (m_ppItems[i]->TemplateId() == dwTemplateId)
2471 {
2472 for(j = 0; j < dwNumItems; j++)
2473 if (m_ppItems[i]->TemplateItemId() == pdwItemList[j])
2474 break;
2475
2476 // Delete DCI if it's not in list
2477 if (j == dwNumItems)
2478 pdwDeleteList[dwNumDeleted++] = m_ppItems[i]->Id();
2479 }
2480
2481 for(i = 0; i < dwNumDeleted; i++)
2482 DeleteItem(pdwDeleteList[i], FALSE);
2483
2484 UnlockData();
2485 free(pdwDeleteList);
2486}
2487
2488
2489//
2490// Unbind node from template, i.e either remove DCI association with template
2491// or remove these DCIs at all
2492//
2493
2494void Node::UnbindFromTemplate(DWORD dwTemplateId, BOOL bRemoveDCI)
2495{
2496 DWORD i, dwNumDeleted, *pdwDeleteList;
2497
2498 if (bRemoveDCI)
2499 {
2500 LockData();
2501
2502 pdwDeleteList = (DWORD *)malloc(sizeof(DWORD) * m_dwNumItems);
2503 dwNumDeleted = 0;
2504
2505 for(i = 0; i < m_dwNumItems; i++)
2506 if (m_ppItems[i]->TemplateId() == dwTemplateId)
2507 {
2508 pdwDeleteList[dwNumDeleted++] = m_ppItems[i]->Id();
2509 }
2510
2511 for(i = 0; i < dwNumDeleted; i++)
2512 DeleteItem(pdwDeleteList[i], FALSE);
2513
2514 UnlockData();
2515 }
2516 else
2517 {
2518 LockData();
2519
2520 for(i = 0; i < m_dwNumItems; i++)
2521 if (m_ppItems[i]->TemplateId() == dwTemplateId)
2522 {
2523 m_ppItems[i]->SetTemplateId(0, 0);
2524 }
2525
2526 UnlockData();
2527 }
2528}
2529
2530
2531//
2532// Change node's IP address
2533//
2534
2535void Node::ChangeIPAddress(DWORD dwIpAddr)
2536{
2537 DWORD i;
2538
2539 PollerLock();
2540
2541 LockData();
2542
2543 UpdateNodeIndex(m_dwIpAddr, dwIpAddr, this);
2544 m_dwIpAddr = dwIpAddr;
2545 m_dwDynamicFlags |= NDF_FORCE_CONFIGURATION_POLL | NDF_RECHECK_CAPABILITIES;
2546
2547 // Change status of node and all it's childs to UNKNOWN
2548 m_iStatus = STATUS_UNKNOWN;
2549 LockChildList(FALSE);
2550 for(i = 0; i < m_dwChildCount; i++)
2551 {
2552 m_pChildList[i]->ResetStatus();
2553 if (m_pChildList[i]->Type() == OBJECT_INTERFACE)
2554 {
2555 if (((Interface *)m_pChildList[i])->IsFake())
2556 {
2557 ((Interface *)m_pChildList[i])->SetIpAddr(dwIpAddr);
2558 }
2559 }
2560 }
2561 UnlockChildList();
2562
2563 Modify();
2564 UnlockData();
2565
2566 AgentLock();
2567 delete_and_null(m_pAgentConnection);
2568 AgentUnlock();
2569
2570 PollerUnlock();
2571}
2572
2573
2574//
2575// Get number of interface objects and pointer to the last one
2576//
2577
2578DWORD Node::GetInterfaceCount(Interface **ppInterface)
2579{
2580 DWORD i, dwCount;
2581
2582 LockChildList(FALSE);
2583 for(i = 0, dwCount = 0; i < m_dwChildCount; i++)
2584 if (m_pChildList[i]->Type() == OBJECT_INTERFACE)
2585 {
2586 dwCount++;
2587 *ppInterface = (Interface *)m_pChildList[i];
2588 }
2589 UnlockChildList();
2590 return dwCount;
2591}
2592
2593
2594//
2595// Update cache for all DCI's
2596//
2597
2598void Node::UpdateDCICache(void)
2599{
2600 DWORD i;
2601
2602 /* LOCK? */
2603 for(i = 0; i < m_dwNumItems; i++)
2604 m_ppItems[i]->UpdateCacheSize();
2605}
2606
2607
2608//
2609// Get routing table from node
2610//
2611
2612ROUTING_TABLE *Node::GetRoutingTable(void)
2613{
2614 ROUTING_TABLE *pRT = NULL;
2615
2616 if ((m_dwFlags & NF_IS_NATIVE_AGENT) && (!(m_dwFlags & NF_DISABLE_NXCP)))
2617 {
2618 AgentLock();
2619 if (ConnectToAgent())
2620 {
2621 pRT = m_pAgentConnection->GetRoutingTable();
2622 }
2623 AgentUnlock();
2624 }
2625 if ((pRT == NULL) && (m_dwFlags & NF_IS_SNMP) && (!(m_dwFlags & NF_DISABLE_SNMP)))
2626 {
2627 SNMP_Transport *pTransport;
2628
2629 pTransport = CreateSNMPTransport();
2630 pRT = SnmpGetRoutingTable(m_iSNMPVersion, pTransport, m_szCommunityString);
2631 delete pTransport;
2632 }
2633
2634 if (pRT != NULL)
2635 {
2636 SortRoutingTable(pRT);
2637 }
2638 return pRT;
2639}
2640
2641
2642//
2643// Get next hop for given destination address
2644//
2645
2646BOOL Node::GetNextHop(DWORD dwSrcAddr, DWORD dwDestAddr, DWORD *pdwNextHop,
2647 DWORD *pdwIfIndex, BOOL *pbIsVPN)
2648{
2649 DWORD i;
2650 BOOL bResult = FALSE;
2651
2652 // Check VPN connectors
2653 LockChildList(FALSE);
2654 for(i = 0; i < m_dwChildCount; i++)
2655 if (m_pChildList[i]->Type() == OBJECT_VPNCONNECTOR)
2656 {
2657 if (((VPNConnector *)m_pChildList[i])->IsRemoteAddr(dwDestAddr) &&
2658 ((VPNConnector *)m_pChildList[i])->IsLocalAddr(dwSrcAddr))
2659 {
2660 *pdwNextHop = ((VPNConnector *)m_pChildList[i])->GetPeerGatewayAddr();
2661 *pdwIfIndex = m_pChildList[i]->Id();
2662 *pbIsVPN = TRUE;
2663 bResult = TRUE;
2664 break;
2665 }
2666 }
2667 UnlockChildList();
2668
2669 // Check routing table
2670 if (!bResult)
2671 {
2672 RTLock();
2673 if (m_pRoutingTable != NULL)
2674 {
2675 for(i = 0; i < (DWORD)m_pRoutingTable->iNumEntries; i++)
2676 if ((dwDestAddr & m_pRoutingTable->pRoutes[i].dwDestMask) == m_pRoutingTable->pRoutes[i].dwDestAddr)
2677 {
2678 *pdwNextHop = m_pRoutingTable->pRoutes[i].dwNextHop;
2679 *pdwIfIndex = m_pRoutingTable->pRoutes[i].dwIfIndex;
2680 *pbIsVPN = FALSE;
2681 bResult = TRUE;
2682 break;
2683 }
2684 }
2685 RTUnlock();
2686 }
2687
2688 return bResult;
2689}
2690
2691
2692//
2693// Update cached routing table
2694//
2695
2696void Node::UpdateRoutingTable(void)
2697{
2698 ROUTING_TABLE *pRT;
2699
2700 pRT = GetRoutingTable();
2701 if (pRT != NULL)
2702 {
2703 RTLock();
2704 DestroyRoutingTable(m_pRoutingTable);
2705 m_pRoutingTable = pRT;
2706 RTUnlock();
2707 }
2708 m_tLastRTUpdate = time(NULL);
2709 m_dwDynamicFlags &= ~NDF_QUEUED_FOR_ROUTE_POLL;
2710}
2711
2712
2713//
2714// Call SNMP Enumerate with node's SNMP parameters
2715//
2716
2717DWORD Node::CallSnmpEnumerate(const char *pszRootOid,
2718 DWORD (* pHandler)(DWORD, const char *, SNMP_Variable *, SNMP_Transport *, void *),
2719 void *pArg)
2720{
2721 if ((m_dwFlags & NF_IS_SNMP) &&
2722 (!(m_dwDynamicFlags & NDF_SNMP_UNREACHABLE)) &&
2723 (!(m_dwDynamicFlags & NDF_UNREACHABLE)))
2724 {
2725 SNMP_Transport *pTransport;
2726 DWORD dwResult;
2727
2728 pTransport = CreateSNMPTransport();
2729 dwResult = SnmpEnumerate(m_iSNMPVersion, pTransport,
2730 m_szCommunityString, pszRootOid, pHandler, pArg, FALSE);
2731 delete pTransport;
2732 return dwResult;
2733 }
2734 else
2735 {
2736 return SNMP_ERR_COMM;
2737 }
2738}
2739
2740
2741//
2742// Set proxy information for agent's connection
2743//
2744
2745void Node::SetAgentProxy(AgentConnection *pConn)
2746{
2747 if (m_dwProxyNode != 0)
2748 {
2749 Node *pNode;
2750
2751 pNode = (Node *)FindObjectById(m_dwProxyNode);
2752 if (pNode != NULL)
2753 {
2754 pConn->SetProxy(htonl(pNode->m_dwIpAddr), pNode->m_wAgentPort,
2755 pNode->m_wAuthMethod, pNode->m_szSharedSecret);
2756 }
2757 }
2758}
2759
2760
2761//
2762// Prepare node object for deletion
2763//
2764
2765void Node::PrepareForDeletion(void)
2766{
2767 // Prevent node from being queued for polling
2768 LockData();
2769 m_dwDynamicFlags |= NDF_POLLING_DISABLED;
2770 UnlockData();
2771
2772 // Wait for all pending polls
2773 while(1)
2774 {
2775 LockData();
2776 if ((m_dwDynamicFlags &
2777 (NDF_QUEUED_FOR_STATUS_POLL | NDF_QUEUED_FOR_CONFIG_POLL |
2778 NDF_QUEUED_FOR_DISCOVERY_POLL | NDF_QUEUED_FOR_ROUTE_POLL)) == 0)
2779 {
2780 UnlockData();
2781 break;
2782 }
2783 UnlockData();
2784 ThreadSleepMs(100);
2785 }
2786 Template::PrepareForDeletion();
2787}
2788
2789
2790//
2791// Check if specified SNMP variable set to specified value.
2792// If variable doesn't exist at all, will return FALSE
2793//
2794
2795BOOL Node::CheckSNMPIntegerValue(SNMP_Transport *pTransport, const char *pszOID, int nValue)
2796{
2797 DWORD dwTemp;
2798
2799 if (SnmpGet(m_iSNMPVersion, pTransport, m_szCommunityString,
2800 pszOID, NULL, 0, &dwTemp, sizeof(DWORD), FALSE, FALSE) == SNMP_ERR_SUCCESS)
2801 return (int)dwTemp == nValue;
2802 return FALSE;
2803}
2804
2805
2806//
2807// Check and update if needed interface names
2808//
2809
2810void Node::CheckInterfaceNames(INTERFACE_LIST *pIfList)
2811{
2812 int i;
2813 TCHAR *ptr;
2814
2815 if ((m_dwNodeType == NODE_TYPE_NORTEL_BAYSTACK) ||
2816 (m_dwNodeType == NODE_TYPE_NORTEL_OPTERA))
2817 {
2818 // Translate interface names
2819 for(i = 0; i < pIfList->iNumEntries; i++)
2820 {
2821 if ((ptr = _tcsstr(pIfList->pInterfaces[i].szName, _T("- Port"))) != NULL)
2822 {
2823 ptr += 2;
2824 memmove(pIfList->pInterfaces[i].szName, ptr, _tcslen(ptr) + 1);
2825 }
2826 else if ((ptr = _tcsstr(pIfList->pInterfaces[i].szName, _T("- Unit"))) != NULL)
2827 {
2828 ptr += 2;
2829 memmove(pIfList->pInterfaces[i].szName, ptr, _tcslen(ptr) + 1);
2830 }
2831 else if ((_tcsstr(pIfList->pInterfaces[i].szName, _T("BayStack")) != NULL) ||
2832 (_tcsstr(pIfList->pInterfaces[i].szName, _T("Nortel Ethernet Switch")) != NULL))
2833 {
2834 ptr = _tcsrchr(pIfList->pInterfaces[i].szName, _T('-'));
2835 if (ptr != NULL)
2836 {
2837 ptr++;
2838 while(*ptr == _T(' '))
2839 ptr++;
2840 memmove(pIfList->pInterfaces[i].szName, ptr, _tcslen(ptr) + 1);
2841 }
2842 }
2843 StrStrip(pIfList->pInterfaces[i].szName);
2844 }
2845 }
2846
2847 // Cut interface names to MAX_OBJECT_NAME and check for unnamed interfaces
2848 for(i = 0; i < pIfList->iNumEntries; i++)
2849 {
2850 pIfList->pInterfaces[i].szName[MAX_OBJECT_NAME - 1] = 0;
2851 if (pIfList->pInterfaces[i].szName[0] == 0)
2852 _stprintf(pIfList->pInterfaces[i].szName, _T("%d"), pIfList->pInterfaces[i].dwIndex);
2853 }
2854}
2855
2856
2857//
2858// Get cluster object this node belongs to, if any
2859//
2860
2861Cluster *Node::GetMyCluster(void)
2862{
2863 DWORD i;
2864 Cluster *pCluster = NULL;
2865
2866 LockParentList(FALSE);
2867 for(i = 0; i < m_dwParentCount; i++)
2868 if (m_pParentList[i]->Type() == OBJECT_CLUSTER)
2869 {
2870 pCluster = (Cluster *)m_pParentList[i];
2871 break;
2872 }
2873 UnlockParentList();
2874 return pCluster;
2875}
2876
2877
2878//
2879// Create SNMP transport
2880//
2881
2882SNMP_Transport *Node::CreateSNMPTransport(void)
2883{
2884 SNMP_Transport *pTransport = NULL;
2885
2886 if (m_dwSNMPProxy == 0)
2887 {
2888 pTransport = new SNMP_UDPTransport;
2889 ((SNMP_UDPTransport *)pTransport)->CreateUDPTransport(NULL, htonl(m_dwIpAddr), m_wSNMPPort);
2890 }
2891 else
2892 {
2893 NetObj *pObject;
2894
2895 pObject = FindObjectById(m_dwSNMPProxy);
2896 if (pObject != NULL)
2897 {
2898 if (pObject->Type() == OBJECT_NODE)
2899 {
2900 AgentConnection *pConn;
2901
2902 pConn = ((Node *)pObject)->CreateAgentConnection();
2903 if (pConn != NULL)
2904 {
2905 pTransport = new SNMP_ProxyTransport(pConn, m_dwIpAddr, m_wSNMPPort);
2906 }
2907 }
2908 }
2909 }
2910 return pTransport;
2911}
2912
2913
2914//
2915// Resolve node's name
2916//
2917
2918BOOL Node::ResolveName(BOOL useOnlyDNS)
2919{
2920 BOOL bSuccess = FALSE;
2921 HOSTENT *hs;
2922 DWORD i, dwAddr;
2923 TCHAR szBuffer[256];
2924
2925 DbgPrintf(4, _T("Resolving name for node %d [%s]..."), m_dwId, m_szName);
2926
2927 // Try to resolve primary IP
2928 dwAddr = htonl(m_dwIpAddr);
2929 hs = gethostbyaddr((const char *)&dwAddr, 4, AF_INET);
2930 if (hs != NULL)
2931 {
2932 nx_strncpy(m_szName, hs->h_name, MAX_OBJECT_NAME);
2933 bSuccess = TRUE;
2934 }
2935 else
2936 {
2937 // Try to resolve each interface's IP address
2938 LockChildList(FALSE);
2939 for(i = 0; i < m_dwChildCount; i++)
2940 {
2941 if (m_pChildList[i]->Type() == OBJECT_INTERFACE)
2942 {
2943 dwAddr = htonl(m_pChildList[i]->IpAddr());
2944 if (dwAddr != 0)
2945 {
2946 hs = gethostbyaddr((const char *)&dwAddr, 4, AF_INET);
2947 if (hs != NULL)
2948 {
2949 nx_strncpy(m_szName, hs->h_name, MAX_OBJECT_NAME);
2950 bSuccess = TRUE;
2951 break;
2952 }
2953 }
2954 }
2955 }
2956 UnlockChildList();
2957
2958 // Try to get hostname from agent if address resolution fails
2959 if (!(bSuccess || useOnlyDNS))
2960 {
2961 DbgPrintf(4, _T("Resolving name for node %d [%s] via agent..."), m_dwId, m_szName);
2962 if (GetItemFromAgent("System.Hostname", 256, szBuffer) == DCE_SUCCESS)
2963 {
2964 StrStrip(szBuffer);
2965 if (szBuffer[0] != 0)
2966 {
2967 nx_strncpy(m_szName, szBuffer, MAX_OBJECT_NAME);
2968 bSuccess = TRUE;
2969 }
2970 }
2971 }
2972
2973 // Try to get hostname from SNMP if other methods fails
2974 if (!(bSuccess || useOnlyDNS))
2975 {
2976 DbgPrintf(4, _T("Resolving name for node %d [%s] via SNMP..."), m_dwId, m_szName);
2977 if (GetItemFromSNMP(".1.3.6.1.2.1.1.5.0", 256, szBuffer) == DCE_SUCCESS)
2978 {
2979 StrStrip(szBuffer);
2980 if (szBuffer[0] != 0)
2981 {
2982 nx_strncpy(m_szName, szBuffer, MAX_OBJECT_NAME);
2983 bSuccess = TRUE;
2984 }
2985 }
2986 }
2987 }
2988
2989 if (bSuccess)
2990 DbgPrintf(4, _T("Name for node %d was resolved to %s"), m_dwId, m_szName);
2991 else
2992 DbgPrintf(4, _T("Name for node %d was not resolved"), m_dwId, m_szName);
2993 return bSuccess;
2994}
2995
2996
2997//
2998// Send list of system DCIs
2999//
3000
3001DWORD Node::GetSystemDCIList(CSCPMessage *pMsg)
3002{
3003 DWORD i, dwId, dwCount;
3004
3005 LockData();
3006
3007 for(i = 0, dwId = VID_SYSDCI_LIST_BASE, dwCount = 0; i < m_dwNumItems; i++)
3008 {
3009 if (!_tcsnicmp(m_ppItems[i]->Description(), _T("@System."), 8))
3010 {
3011 pMsg->SetVariable(dwId++, m_ppItems[i]->Id());
3012 pMsg->SetVariable(dwId++, (TCHAR *)m_ppItems[i]->Description());
3013 pMsg->SetVariable(dwId++, (WORD)m_ppItems[i]->Status());
3014 dwId += 7;
3015 dwCount++;
3016 }
3017 }
3018 pMsg->SetVariable(VID_NUM_ITEMS, dwCount);
3019
3020 UnlockData();
3021 return RCC_SUCCESS;
3022}
3023
3024
3025//
3026// Get current layer 2 topology (as dynamically created list which should be destroyed by caller)
3027// Will return NULL if there are no topology information or it is expired
3028//
3029
3030nxmap_ObjList *Node::GetL2Topology(void)
3031{
3032 nxmap_ObjList *pResult;
3033 DWORD dwExpTime;
3034
3035 dwExpTime = ConfigReadULong(_T("TopologyExpirationTime"), 900);
3036 MutexLock(m_mutexTopoAccess, INFINITE);
3037 if ((m_pTopology == NULL) || (m_tLastTopologyPoll + (time_t)dwExpTime < time(NULL)))
3038 {
3039 pResult = NULL;
3040 }
3041 else
3042 {
3043 pResult = new nxmap_ObjList(m_pTopology);
3044 }
3045 MutexUnlock(m_mutexTopoAccess);
3046 return pResult;
3047}
3048
3049
3050//
3051// Rebuild layer 2 topology and return it as dynamically reated list which should be destroyed by caller
3052//
3053
3054nxmap_ObjList *Node::BuildL2Topology(DWORD *pdwStatus)
3055{
3056 nxmap_ObjList *pResult;
3057 int nDepth;
3058
3059 nDepth = ConfigReadInt(_T("TopologyDiscoveryRadius"), 5);
3060 MutexLock(m_mutexTopoAccess, INFINITE);
3061 delete m_pTopology;
3062 if ((m_dwFlags & NF_IS_CDP) || (m_dwFlags & NF_IS_SONMP) || (m_dwFlags & NF_IS_LLDP))
3063 {
3064 m_pTopology = new nxmap_ObjList;
3065 if ((*pdwStatus = ::BuildL2Topology(*m_pTopology, this, NULL, nDepth, NULL)) == RCC_SUCCESS)
3066 {
3067 m_tLastTopologyPoll = time(NULL);
3068 pResult = new nxmap_ObjList(m_pTopology);
3069 }
3070 else
3071 {
3072 delete_and_null(m_pTopology);
3073 pResult = NULL;
3074 }
3075 }
3076 else
3077 {
3078 pResult = NULL;
3079 m_pTopology = NULL;
3080 *pdwStatus = RCC_NO_L2_TOPOLOGY_SUPPORT;
3081 }
3082 MutexUnlock(m_mutexTopoAccess);
3083 return pResult;
3084}
3085
3086
3087//
3088// Check subnet bindings
3089//
3090
3091void Node::CheckSubnetBinding(INTERFACE_LIST *pIfList)
3092{
3093 Subnet *pSubnet;
3094 Interface *pInterface;
3095 Cluster *pCluster;
3096 NetObj **ppUnlinkList;
3097 int i, j, count;
3098 BOOL isSync;
3099
3100 pCluster = GetMyCluster();
3101
3102 // Check if we have subnet bindings for all interfaces
3103 for(i = 0; i < pIfList->iNumEntries; i++)
3104 {
3105 if (pIfList->pInterfaces[i].dwIpAddr != 0)
3106 {
3107 pInterface = FindInterface(pIfList->pInterfaces[i].dwIndex, pIfList->pInterfaces[i].dwIpAddr);
3108 if (pInterface == NULL)
3109 {
3110 nxlog_write(MSG_INTERNAL_ERROR, EVENTLOG_WARNING_TYPE, "s", _T("Cannot find interface object in Node::CheckSubnetBinding()"));
3111 break; // Something goes really wrong
3112 }
3113
3114 // Is cluster interconnect interface?
3115 isSync = (pCluster != NULL) ? pCluster->IsSyncAddr(pInterface->IpAddr()) : FALSE;
3116
3117 pSubnet = FindSubnetForNode(pIfList->pInterfaces[i].dwIpAddr);
3118 if (pSubnet != NULL)
3119 {
3120 if (isSync)
3121 {
3122 pSubnet = NULL; // No further checks on this subnet
3123 }
3124 else
3125 {
3126 if (pSubnet->IsSyntheticMask())
3127 {
3128 DbgPrintf(4, _T("Setting correct netmask for subnet %s [%d] from node %s [%d]"),
3129 pSubnet->Name(), pSubnet->Id(), m_szName, m_dwId);
3130 pSubnet->SetCorrectMask(pInterface->IpAddr() & pInterface->IpNetMask(), pInterface->IpNetMask());
3131 }
3132 }
3133 }
3134 else if (!isSync)
3135 {
3136 // Create subnet
3137 pSubnet = new Subnet(pIfList->pInterfaces[i].dwIpAddr & pIfList->pInterfaces[i].dwIpNetMask,
3138 pIfList->pInterfaces[i].dwIpNetMask, m_dwZoneGUID, FALSE);
3139 NetObjInsert(pSubnet, TRUE);
3140 g_pEntireNet->AddSubnet(pSubnet);
3141 pSubnet->AddNode(this);
3142 DbgPrintf(4, _T("Node::CheckSubnetBinding(): Creating new subnet %s [%d] for node %s [%d]"),
3143 pSubnet->Name(), pSubnet->Id(), m_szName, m_dwId);
3144 }
3145
3146 // Check if subnet mask is correct on interface
3147 if ((pSubnet != NULL) && (pSubnet->IpNetMask() != pIfList->pInterfaces[i].dwIpNetMask))
3148 {
3149 PostEvent(EVENT_INCORRECT_NETMASK, m_dwId, "idsaa", pInterface->Id(),
3150 pInterface->IfIndex(), pInterface->Name(),
3151 pInterface->IpNetMask(), pSubnet->IpNetMask());
3152 }
3153 }
3154 }
3155
3156 // Check if we have incorrect subnets as parents
3157 LockParentList(FALSE);
3158 LockChildList(FALSE);
3159 ppUnlinkList = (NetObj **)malloc(sizeof(NetObj *) * m_dwParentCount);
3160 for(i = 0, count = 0; i < (int)m_dwParentCount; i++)
3161 {
3162 if (m_pParentList[i]->Type() == OBJECT_SUBNET)
3163 {
3164 pSubnet = (Subnet *)m_pParentList[i];
3165 for(j = 0; j < (int)m_dwChildCount; j++)
3166 {
3167 if (m_pChildList[j]->Type() == OBJECT_INTERFACE)
3168 {
3169 if (pSubnet->IpAddr() == (m_pChildList[j]->IpAddr() & pSubnet->IpNetMask()))
3170 {
3171 if (pCluster != NULL)
3172 {
3173 if (pCluster->IsSyncAddr(m_pChildList[j]->IpAddr()))
3174 {
3175 j = (int)m_dwChildCount; // Cause to unbind from this subnet
3176 }
3177 }
3178 break;
3179 }
3180 }
3181 }
3182 if (j == (int)m_dwChildCount)
3183 {
3184 DbgPrintf(4, _T("Node::CheckSubnetBinding(): Subnet %s [%d] is incorrect for node %s [%d]"),
3185 pSubnet->Name(), pSubnet->Id(), m_szName, m_dwId);
3186 ppUnlinkList[count++] = pSubnet;
3187 }
3188 }
3189 }
3190 UnlockChildList();
3191 UnlockParentList();
3192
3193 // Unlink for incorrect subnet objects
3194 for(i = 0; i < count; i++)
3195 {
3196 ppUnlinkList[i]->DeleteChild(this);
3197 DeleteParent(ppUnlinkList[i]);
3198 }
3199 safe_free(ppUnlinkList);
3200}
3201
3202
3203//
3204// Update interface names
3205//
3206
3207void Node::UpdateInterfaceNames(ClientSession *pSession, DWORD dwRqId)
3208{
3209 INTERFACE_LIST *pIfList;
3210 DWORD i;
3211 int j;
3212
3213 PollerLock();
3214 m_pPollRequestor = pSession;
3215 SendPollerMsg(dwRqId, _T("Starting interface names poll for node %s\r\n"), m_szName);
3216 DbgPrintf(4, "Starting interface names poll for node %s (ID: %d)", m_szName, m_dwId);
3217
3218 // Retrieve interface list
3219 pIfList = GetInterfaceList();
3220 if (pIfList != NULL)
3221 {
3222 // Check names of existing interfaces
3223 for(j = 0; j < pIfList->iNumEntries; j++)
3224 {
3225 LockChildList(FALSE);
3226 for(i = 0; i < m_dwChildCount; i++)
3227 {
3228 if (m_pChildList[i]->Type() == OBJECT_INTERFACE)
3229 {
3230 Interface *pInterface = (Interface *)m_pChildList[i];
3231
3232 if (pIfList->pInterfaces[j].dwIndex == pInterface->IfIndex())
3233 {
3234 SendPollerMsg(dwRqId, _T(" Checking interface %d (%s)\r\n"), pInterface->IfIndex(), pInterface->Name());
3235 if (strcmp(pIfList->pInterfaces[j].szName, pInterface->Name()))
3236 {
3237 pInterface->SetName(pIfList->pInterfaces[j].szName);
3238 SendPollerMsg(dwRqId, POLLER_WARNING _T(" Name of interface %d changed to %s\r\n"), pInterface->IfIndex(), pIfList->pInterfaces[j].szName);
3239 }
3240 break;
3241 }
3242 }
3243 }
3244 UnlockChildList();
3245 }
3246
3247 DestroyInterfaceList(pIfList);
3248 }
3249 else /* pIfList == NULL */
3250 {
3251 SendPollerMsg(dwRqId, POLLER_ERROR _T(" Unable to get interface list from node\r\n"));
3252 }
3253
3254 // Finish poll
3255 SendPollerMsg(dwRqId, _T("Finished interface names poll for node %s\r\n"), m_szName);
3256 PollerUnlock();
3257 DbgPrintf(4, "Finished interface names poll for node %s (ID: %d)", m_szName, m_dwId);
3258}