libnxsl; nxscript; nxlptest - synched
[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;
986 Template *pTemplate;
987 BOOL bHasChanges = FALSE;
988
989 SetPollerInfo(nPoller, "wait for lock");
990 PollerLock();
991 m_pPollRequestor = pSession;
992 SendPollerMsg(dwRqId, _T("Starting configuration poll for node %s\r\n"), m_szName);
993 DbgPrintf(4, "Starting configuration poll for node %s (ID: %d)", m_szName, m_dwId);
994
995 // Check for forced capabilities recheck
996 if (m_dwDynamicFlags & NDF_RECHECK_CAPABILITIES)
997 {
998 m_dwFlags &= ~(NF_IS_NATIVE_AGENT | NF_IS_SNMP | NF_IS_CPSNMP |
999 NF_IS_BRIDGE | NF_IS_ROUTER | NF_IS_OSPF);
1000 m_szObjectId[0] = 0;
1001 m_szPlatformName[0] = 0;
1002 m_szAgentVersion[0] = 0;
1003 m_szSysDescription[0] = 0;
1004 }
1005
1006 // Check if node is marked as unreachable
1007 if ((m_dwDynamicFlags & NDF_UNREACHABLE) && !(m_dwDynamicFlags & NDF_RECHECK_CAPABILITIES))
1008 {
1009 SendPollerMsg(dwRqId, POLLER_WARNING _T("Node is marked as unreachable, configuration poll aborted\r\n"));
1010 DbgPrintf(4, "Node is marked as unreachable, configuration poll aborted");
1011 m_tLastConfigurationPoll = time(NULL);
1012 }
1013 else
1014 {
1015 // Check node's capabilities
1016 SetPollerInfo(nPoller, "capability check");
1017 SendPollerMsg(dwRqId, _T("Checking node's capabilities...\r\n"));
1018
1019 // ***** NetXMS agent check *****
1020 DbgPrintf(5, "ConfPoll(%s): checking for NetXMS agent Flags={%08X} DynamicFlags={%08X}", m_szName, m_dwFlags, m_dwDynamicFlags);
1021 if ((!((m_dwFlags & NF_IS_NATIVE_AGENT) && (m_dwDynamicFlags & NDF_AGENT_UNREACHABLE))) &&
1022 (!(m_dwFlags & NF_DISABLE_NXCP)))
1023 {
1024 SendPollerMsg(dwRqId, _T(" Checking NetXMS agent...\r\n"));
1025 pAgentConn = new AgentConnection(htonl(m_dwIpAddr), m_wAgentPort,
1026 m_wAuthMethod, m_szSharedSecret);
1027 SetAgentProxy(pAgentConn);
1028 DbgPrintf(5, "ConfPoll(%s): checking for NetXMS agent - connecting", m_szName);
1029 if (pAgentConn->Connect(g_pServerKey))
1030 {
1031 DbgPrintf(5, "ConfPoll(%s): checking for NetXMS agent - connected", m_szName);
1032 LockData();
1033 m_dwFlags |= NF_IS_NATIVE_AGENT;
1034 if (m_dwDynamicFlags & NDF_AGENT_UNREACHABLE)
1035 {
1036 m_dwDynamicFlags &= ~NDF_AGENT_UNREACHABLE;
1037 PostEvent(EVENT_AGENT_OK, m_dwId, NULL);
1038 SendPollerMsg(dwRqId, POLLER_INFO _T(" Connectivity with NetXMS agent restored\r\n"));
1039 }
1040 UnlockData();
1041
1042 if (pAgentConn->GetParameter("Agent.Version", MAX_AGENT_VERSION_LEN, szBuffer) == ERR_SUCCESS)
1043 {
1044 LockData();
1045 if (strcmp(m_szAgentVersion, szBuffer))
1046 {
1047 strcpy(m_szAgentVersion, szBuffer);
1048 bHasChanges = TRUE;
1049 SendPollerMsg(dwRqId, _T(" NetXMS agent version changed to %s\r\n"), m_szAgentVersion);
1050 }
1051 UnlockData();
1052 }
1053
1054 if (pAgentConn->GetParameter("System.PlatformName", MAX_PLATFORM_NAME_LEN, szBuffer) == ERR_SUCCESS)
1055 {
1056 LockData();
1057 if (strcmp(m_szPlatformName, szBuffer))
1058 {
1059 strcpy(m_szPlatformName, szBuffer);
1060 bHasChanges = TRUE;
1061 SendPollerMsg(dwRqId, _T(" Platform name changed to %s\r\n"), m_szPlatformName);
1062 }
1063 UnlockData();
1064 }
1065
1066 // Check IP forwarding status
1067 if (pAgentConn->GetParameter("Net.IP.Forwarding", 16, szBuffer) == ERR_SUCCESS)
1068 {
1069 if (_tcstoul(szBuffer, NULL, 10) != 0)
1070 m_dwFlags |= NF_IS_ROUTER;
1071 else
1072 m_dwFlags &= ~NF_IS_ROUTER;
1073 }
1074
1075 // Get uname
1076 if (pAgentConn->GetParameter("System.Uname", MAX_DB_STRING, szBuffer) == ERR_SUCCESS)
1077 {
1078 TranslateStr(szBuffer, "\r\n", " ");
1079 TranslateStr(szBuffer, "\n", " ");
1080 TranslateStr(szBuffer, "\r", " ");
1081 LockData();
1082 if (strcmp(m_szSysDescription, szBuffer))
1083 {
1084 strcpy(m_szSysDescription, szBuffer);
1085 bHasChanges = TRUE;
1086 SendPollerMsg(dwRqId, _T(" System description changed to %s\r\n"), m_szSysDescription);
1087 }
1088 UnlockData();
1089 }
1090
1091 rcc = pAgentConn->GetSupportedParameters(&dwNumParams, &pParamList);
1092 if (rcc == ERR_SUCCESS)
1093 {
1094 LockData();
1095 safe_free(m_pParamList);
1096 m_dwNumParams = dwNumParams;
1097 m_pParamList = pParamList;
1098 UnlockData();
1099 }
1100 else
1101 {
1102 DbgPrintf(5, _T("ConfPoll(%s): AgentConnection::GetSupportedParameters() failed: rcc=%d"), m_szName, rcc);
1103 }
1104
1105 pAgentConn->Disconnect();
1106 SendPollerMsg(dwRqId, POLLER_INFO _T(" NetXMS native agent is active\r\n"));
1107 }
1108 delete pAgentConn;
1109 DbgPrintf(5, "ConfPoll(%s): checking for NetXMS agent - finished", m_szName);
1110 }
1111
1112 // ***** SNMP check *****
1113 if ((!((m_dwFlags & NF_IS_SNMP) && (m_dwDynamicFlags & NDF_SNMP_UNREACHABLE))) &&
1114 (!(m_dwFlags & NF_DISABLE_SNMP)))
1115 {
1116 SendPollerMsg(dwRqId, _T(" Checking SNMP...\r\n"));
1117 DbgPrintf(5, "ConfPoll(%s): trying SNMP GET", m_szName);
1118 pTransport = CreateSNMPTransport();
1119
1120 strcpy(szBuffer, m_szCommunityString);
1121 if (SnmpCheckCommSettings(pTransport, szBuffer, &m_iSNMPVersion, m_szCommunityString))
1122 {
1123 DWORD dwNodeFlags, dwNodeType;
1124
1125 LockData();
1126 m_dwFlags |= NF_IS_SNMP;
1127 if (m_dwDynamicFlags & NDF_SNMP_UNREACHABLE)
1128 {
1129 m_dwDynamicFlags &= ~NDF_SNMP_UNREACHABLE;
1130 PostEvent(EVENT_SNMP_OK, m_dwId, NULL);
1131 SendPollerMsg(dwRqId, POLLER_WARNING " Connectivity with SNMP agent restored\r\n");
1132 }
1133 UnlockData();
1134 SendPollerMsg(dwRqId, _T(" SNMP agent is active (version %s)\r\n"), (m_iSNMPVersion == SNMP_VERSION_2C) ? _T("2c") : _T("1"));
1135
1136 if (SnmpGet(m_iSNMPVersion, pTransport, m_szCommunityString,
1137 ".1.3.6.1.2.1.1.2.0", NULL, 0, szBuffer, 4096,
1138 FALSE, FALSE) == SNMP_ERR_SUCCESS)
1139 {
1140 LockData();
1141 if (strcmp(m_szObjectId, szBuffer))
1142 {
1143 nx_strncpy(m_szObjectId, szBuffer, MAX_OID_LEN * 4);
1144 bHasChanges = TRUE;
1145 }
1146 UnlockData();
1147 }
1148
1149 // Check node type
1150 LockData();
1151 dwNodeType = OidToType(m_szObjectId, &dwNodeFlags);
1152 if (m_dwNodeType != dwNodeType)
1153 {
1154 m_dwFlags |= dwNodeFlags;
1155 m_dwNodeType = dwNodeType;
1156 SendPollerMsg(dwRqId, POLLER_WARNING _T(" Node type has been changed to %d\r\n"), m_dwNodeType);
1157 bHasChanges = TRUE;
1158 }
1159 UnlockData();
1160
1161 // Check IP forwarding
1162 if (CheckSNMPIntegerValue(pTransport, ".1.3.6.1.2.1.4.1.0", 1))
1163 {
1164 LockData();
1165 m_dwFlags |= NF_IS_ROUTER;
1166 UnlockData();
1167 }
1168 else
1169 {
1170 LockData();
1171 m_dwFlags &= ~NF_IS_ROUTER;
1172 UnlockData();
1173 }
1174
1175 // Check for bridge MIB support
1176 if (SnmpGet(m_iSNMPVersion, pTransport, m_szCommunityString,
1177 ".1.3.6.1.2.1.17.1.1.0", NULL, 0, szBuffer, 4096,
1178 FALSE, FALSE) == SNMP_ERR_SUCCESS)
1179 {
1180 LockData();
1181 m_dwFlags |= NF_IS_BRIDGE;
1182 UnlockData();
1183 }
1184 else
1185 {
1186 LockData();
1187 m_dwFlags &= ~NF_IS_BRIDGE;
1188 UnlockData();
1189 }
1190
1191 // Check for CDP (Cisco Discovery Protocol) support
1192 if (CheckSNMPIntegerValue(pTransport, ".1.3.6.1.4.1.9.9.23.1.3.1.0", 1))
1193 {
1194 LockData();
1195 m_dwFlags |= NF_IS_CDP;
1196 UnlockData();
1197 }
1198 else
1199 {
1200 LockData();
1201 m_dwFlags &= ~NF_IS_CDP;
1202 UnlockData();
1203 }
1204
1205 // Check for SONMP (Nortel topology discovery discovery protocol) support
1206 if (CheckSNMPIntegerValue(pTransport, ".1.3.6.1.4.1.45.1.6.13.1.2.0", 1))
1207 {
1208 LockData();
1209 m_dwFlags |= NF_IS_SONMP;
1210 UnlockData();
1211 }
1212 else
1213 {
1214 LockData();
1215 m_dwFlags &= ~NF_IS_SONMP;
1216 UnlockData();
1217 }
1218
1219 // Check for LLDP (Link Layer Discovery Protocol) support
1220 if (SnmpGet(m_iSNMPVersion, pTransport, m_szCommunityString,
1221 ".1.0.8802.1.1.2.1.3.2.0", NULL, 0, szBuffer, 4096,
1222 FALSE, FALSE) == SNMP_ERR_SUCCESS)
1223 {
1224 LockData();
1225 m_dwFlags |= NF_IS_LLDP;
1226 UnlockData();
1227 }
1228 else
1229 {
1230 LockData();
1231 m_dwFlags &= ~NF_IS_LLDP;
1232 UnlockData();
1233 }
1234
1235 // Get system description
1236 if (SnmpGet(m_iSNMPVersion, pTransport, m_szCommunityString,
1237 ".1.3.6.1.2.1.1.1.0", NULL, 0, szBuffer,
1238 MAX_DB_STRING, FALSE, FALSE) == SNMP_ERR_SUCCESS)
1239 {
1240 TranslateStr(szBuffer, "\r\n", " ");
1241 TranslateStr(szBuffer, "\n", " ");
1242 TranslateStr(szBuffer, "\r", " ");
1243 LockData();
1244 if (strcmp(m_szSysDescription, szBuffer))
1245 {
1246 strcpy(m_szSysDescription, szBuffer);
1247 bHasChanges = TRUE;
1248 SendPollerMsg(dwRqId, _T(" System description changed to %s\r\n"), m_szSysDescription);
1249 }
1250 UnlockData();
1251 }
1252
1253 CheckOSPFSupport(pTransport);
1254 }
1255 else
1256 {
1257 // Check for CheckPoint SNMP agent on port 161
1258 DbgPrintf(5, "ConfPoll(%s): checking for CheckPoint SNMP", m_szName);
1259 if (SnmpGet(m_iSNMPVersion, pTransport, m_szCommunityString,
1260 ".1.3.6.1.4.1.2620.1.1.10.0", NULL, 0,
1261 szBuffer, 4096, FALSE, FALSE) == SNMP_ERR_SUCCESS)
1262 {
1263 LockData();
1264 if (strcmp(m_szObjectId, ".1.3.6.1.4.1.2620.1.1"))
1265 {
1266 nx_strncpy(m_szObjectId, ".1.3.6.1.4.1.2620.1.1", MAX_OID_LEN * 4);
1267 bHasChanges = TRUE;
1268 }
1269
1270 m_dwFlags |= NF_IS_SNMP | NF_IS_ROUTER;
1271 m_dwDynamicFlags &= ~NDF_SNMP_UNREACHABLE;
1272 UnlockData();
1273 SendPollerMsg(dwRqId, POLLER_INFO _T(" CheckPoint SNMP agent on port 161 is active\r\n"));
1274 }
1275 }
1276 delete pTransport;
1277 }
1278
1279 // Check for CheckPoint SNMP agent on port 260
1280 DbgPrintf(5, "ConfPoll(%s): checking for CheckPoint SNMP on port 260", m_szName);
1281 if (!((m_dwFlags & NF_IS_CPSNMP) && (m_dwDynamicFlags & NDF_CPSNMP_UNREACHABLE)))
1282 {
1283 pTransport = new SNMP_UDPTransport;
1284 ((SNMP_UDPTransport *)pTransport)->CreateUDPTransport(NULL, htonl(m_dwIpAddr), CHECKPOINT_SNMP_PORT);
1285 if (SnmpGet(SNMP_VERSION_1, pTransport, m_szCommunityString,
1286 ".1.3.6.1.4.1.2620.1.1.10.0", NULL, 0,
1287 szBuffer, 4096, FALSE, FALSE) == SNMP_ERR_SUCCESS)
1288 {
1289 LockData();
1290 m_dwFlags |= NF_IS_CPSNMP | NF_IS_ROUTER;
1291 m_dwDynamicFlags &= ~NDF_CPSNMP_UNREACHABLE;
1292 UnlockData();
1293 SendPollerMsg(dwRqId, POLLER_INFO _T(" CheckPoint SNMP agent on port 260 is active\r\n"));
1294 }
1295 delete pTransport;
1296 }
1297
1298 // Generate event if node flags has been changed
1299 if (dwOldFlags != m_dwFlags)
1300 {
1301 PostEvent(EVENT_NODE_FLAGS_CHANGED, m_dwId, "xx", dwOldFlags, m_dwFlags);
1302 bHasChanges = TRUE;
1303 }
1304
1305 // Get parent cluster object, if any
1306 pCluster = GetMyCluster();
1307
1308 // Retrieve interface list
1309 SetPollerInfo(nPoller, "interface check");
1310 SendPollerMsg(dwRqId, _T("Capability check finished\r\n"
1311 "Checking interface configuration...\r\n"));
1312 pIfList = GetInterfaceList();
1313 if (pIfList != NULL)
1314 {
1315 // Remove cluster virtual interfaces from list
1316 if (pCluster != NULL)
1317 {
1318 for(i = 0; i < (DWORD)pIfList->iNumEntries; i++)
1319 {
1320 if (pCluster->IsVirtualAddr(pIfList->pInterfaces[i].dwIpAddr))
1321 {
1322 pIfList->iNumEntries--;
1323 memmove(&pIfList->pInterfaces[i], &pIfList->pInterfaces[i + 1],
1324 sizeof(INTERFACE_INFO) * (pIfList->iNumEntries - i));
1325 i--;
1326 }
1327 }
1328 }
1329
1330 // Find non-existing interfaces
1331 LockChildList(FALSE);
1332 ppDeleteList = (Interface **)malloc(sizeof(Interface *) * m_dwChildCount);
1333 for(i = 0, iDelCount = 0; i < m_dwChildCount; i++)
1334 {
1335 if (m_pChildList[i]->Type() == OBJECT_INTERFACE)
1336 {
1337 Interface *pInterface = (Interface *)m_pChildList[i];
1338
1339 if (pInterface->IfType() != IFTYPE_NETXMS_NAT_ADAPTER)
1340 {
1341 for(j = 0; j < pIfList->iNumEntries; j++)
1342 {
1343 if ((pIfList->pInterfaces[j].dwIndex == pInterface->IfIndex()) &&
1344 (pIfList->pInterfaces[j].dwIpAddr == pInterface->IpAddr()) &&
1345 (pIfList->pInterfaces[j].dwIpNetMask == pInterface->IpNetMask()))
1346 break;
1347 }
1348
1349 if (j == pIfList->iNumEntries)
1350 {
1351 // No such interface in current configuration, add it to delete list
1352 ppDeleteList[iDelCount++] = pInterface;
1353 }
1354 }
1355 }
1356 }
1357 UnlockChildList();
1358
1359 // Delete non-existent interfaces
1360 if (iDelCount > 0)
1361 {
1362 for(j = 0; j < iDelCount; j++)
1363 {
1364 SendPollerMsg(dwRqId, POLLER_WARNING _T(" Interface \"%s\" is no longer exist\r\n"),
1365 ppDeleteList[j]->Name());
1366 PostEvent(EVENT_INTERFACE_DELETED, m_dwId, "dsaa", ppDeleteList[j]->IfIndex(),
1367 ppDeleteList[j]->Name(), ppDeleteList[j]->IpAddr(), ppDeleteList[j]->IpNetMask());
1368 DeleteInterface(ppDeleteList[j]);
1369 }
1370 bHasChanges = TRUE;
1371 }
1372 safe_free(ppDeleteList);
1373
1374 // Add new interfaces and check configuration of existing
1375 for(j = 0; j < pIfList->iNumEntries; j++)
1376 {
1377 BOOL bNewInterface = TRUE;
1378
1379 LockChildList(FALSE);
1380 for(i = 0; i < m_dwChildCount; i++)
1381 {
1382 if (m_pChildList[i]->Type() == OBJECT_INTERFACE)
1383 {
1384 Interface *pInterface = (Interface *)m_pChildList[i];
1385
1386 if ((pIfList->pInterfaces[j].dwIndex == pInterface->IfIndex()) &&
1387 (pIfList->pInterfaces[j].dwIpAddr == pInterface->IpAddr()) &&
1388 (pIfList->pInterfaces[j].dwIpNetMask == pInterface->IpNetMask()))
1389 {
1390 // Existing interface, check configuration
1391 if (memcmp(pIfList->pInterfaces[j].bMacAddr, pInterface->MacAddr(), MAC_ADDR_LENGTH))
1392 {
1393 char szOldMac[16], szNewMac[16];
1394
1395 BinToStr((BYTE *)pInterface->MacAddr(), MAC_ADDR_LENGTH, szOldMac);
1396 BinToStr(pIfList->pInterfaces[j].bMacAddr, MAC_ADDR_LENGTH, szNewMac);
1397 PostEvent(EVENT_MAC_ADDR_CHANGED, m_dwId, "idsss",
1398 pInterface->Id(), pInterface->IfIndex(),
1399 pInterface->Name(), szOldMac, szNewMac);
1400 pInterface->SetMacAddr(pIfList->pInterfaces[j].bMacAddr);
1401 }
1402 if (strcmp(pIfList->pInterfaces[j].szName, pInterface->Name()))
1403 {
1404 pInterface->SetName(pIfList->pInterfaces[j].szName);
1405 }
1406 bNewInterface = FALSE;
1407 break;
1408 }
1409 }
1410 }
1411 UnlockChildList();
1412
1413 if (bNewInterface)
1414 {
1415 // New interface
1416 SendPollerMsg(dwRqId, POLLER_INFO _T(" Found new interface \"%s\"\r\n"),
1417 pIfList->pInterfaces[j].szName);
1418 CreateNewInterface(pIfList->pInterfaces[j].dwIpAddr,
1419 pIfList->pInterfaces[j].dwIpNetMask,
1420 pIfList->pInterfaces[j].szName,
1421 pIfList->pInterfaces[j].dwIndex,
1422 pIfList->pInterfaces[j].dwType,
1423 pIfList->pInterfaces[j].bMacAddr);
1424 bHasChanges = TRUE;
1425 }
1426 }
1427
1428 // Check if address we are using to communicate with node
1429 // is configured on one of node's interfaces
1430 for(i = 0; i < (DWORD)pIfList->iNumEntries; i++)
1431 if (pIfList->pInterfaces[i].dwIpAddr == m_dwIpAddr)
1432 break;
1433
1434 if (i == (DWORD)pIfList->iNumEntries)
1435 {
1436 BOOL bCreate = TRUE;
1437
1438 // Node is behind NAT
1439 m_dwFlags |= NF_BEHIND_NAT;
1440
1441 // Check if we already have NAT interface
1442 LockChildList(FALSE);
1443 for(i = 0; i < m_dwChildCount; i++)
1444 if (m_pChildList[i]->Type() == OBJECT_INTERFACE)
1445 {
1446 if (((Interface *)m_pChildList[i])->IfType() == IFTYPE_NETXMS_NAT_ADAPTER)
1447 {
1448 bCreate = FALSE;
1449 break;
1450 }
1451 }
1452 UnlockChildList();
1453
1454 if (bCreate)
1455 {
1456 char szBuffer[MAX_OBJECT_NAME];
1457
1458 // Create pseudo interface for NAT
1459 ConfigReadStr("NATAdapterName", szBuffer, MAX_OBJECT_NAME, "NetXMS NAT Adapter");
1460 CreateNewInterface(m_dwIpAddr, 0, szBuffer,
1461 0x7FFFFFFF, IFTYPE_NETXMS_NAT_ADAPTER);
1462 bHasChanges = TRUE;
1463 }
1464 }
1465 else
1466 {
1467 // Check if NF_BEHIND_NAT flag set incorrectly
1468 if (m_dwFlags & NF_BEHIND_NAT)
1469 {
1470 Interface *pIfNat;
1471
1472 // Remove NAT interface
1473 LockChildList(FALSE);
1474 for(i = 0, pIfNat = NULL; i < m_dwChildCount; i++)
1475 if (m_pChildList[i]->Type() == OBJECT_INTERFACE)
1476 {
1477 if (((Interface *)m_pChildList[i])->IfType() == IFTYPE_NETXMS_NAT_ADAPTER)
1478 {
1479 pIfNat = (Interface *)m_pChildList[i];
1480 break;
1481 }
1482 }
1483 UnlockChildList();
1484
1485 if (pIfNat != NULL)
1486 DeleteInterface(pIfNat);
1487
1488 m_dwFlags &= ~NF_BEHIND_NAT;
1489 bHasChanges = TRUE;
1490 }
1491 }
1492
1493 CheckSubnetBinding(pIfList);
1494
1495 DestroyInterfaceList(pIfList);
1496 }
1497 else /* pIfList == NULL */
1498 {
1499 Interface *pInterface;
1500 DWORD dwCount;
1501
1502 SendPollerMsg(dwRqId, POLLER_ERROR _T("Unable to get interface list from node\r\n"));
1503
1504 // Delete all existing interfaces in case of forced capability recheck
1505 if (m_dwDynamicFlags & NDF_RECHECK_CAPABILITIES)
1506 {
1507 LockChildList(FALSE);
1508 ppDeleteList = (Interface **)malloc(sizeof(Interface *) * m_dwChildCount);
1509 for(i = 0, iDelCount = 0; i < m_dwChildCount; i++)
1510 {
1511 if (m_pChildList[i]->Type() == OBJECT_INTERFACE)
1512 ppDeleteList[iDelCount++] = (Interface *)m_pChildList[i];
1513 }
1514 UnlockChildList();
1515 for(j = 0; j < iDelCount; j++)
1516 {
1517 SendPollerMsg(dwRqId, POLLER_WARNING _T(" Interface \"%s\" is no longer exist\r\n"),
1518 ppDeleteList[j]->Name());
1519 PostEvent(EVENT_INTERFACE_DELETED, m_dwId, "dsaa", ppDeleteList[j]->IfIndex(),
1520 ppDeleteList[j]->Name(), ppDeleteList[j]->IpAddr(), ppDeleteList[j]->IpNetMask());
1521 DeleteInterface(ppDeleteList[j]);
1522 }
1523 safe_free(ppDeleteList);
1524 }
1525
1526 // Check if we have pseudo-interface object
1527 dwCount = GetInterfaceCount(&pInterface);
1528 if (dwCount == 1)
1529 {
1530 if (pInterface->IsFake())
1531 {
1532 // Check if primary IP is different from interface's IP
1533 if (pInterface->IpAddr() != m_dwIpAddr)
1534 {
1535 DeleteInterface(pInterface);
1536 CreateNewInterface(m_dwIpAddr, dwNetMask);
1537 }
1538 }
1539 }
1540 else if (dwCount == 0)
1541 {
1542 // No interfaces at all, create pseudo-interface
1543 CreateNewInterface(m_dwIpAddr, dwNetMask);
1544 }
1545 }
1546
1547 m_tLastConfigurationPoll = time(NULL);
1548 SendPollerMsg(dwRqId, _T("Interface configuration check finished\r\n"));
1549
1550 // Check node name
1551 SendPollerMsg(dwRqId, _T("Checking node name\r\n"));
1552 dwAddr = ntohl(_t_inet_addr(m_szName));
1553 if ((g_dwFlags & AF_RESOLVE_NODE_NAMES) &&
1554 (dwAddr != INADDR_NONE) &&
1555 (dwAddr != INADDR_ANY) &&
1556 IsMyIP(dwAddr))
1557 {
1558 SendPollerMsg(dwRqId, _T("Node name is an IP address and need to be resolved\r\n"));
1559 SetPollerInfo(nPoller, "resolving name");
1560 if (ResolveName(FALSE))
1561 {
1562 SendPollerMsg(dwRqId, POLLER_INFO _T("Node name resolved to %s\r\n"), m_szName);
1563 bHasChanges = TRUE;
1564 }
1565 else
1566 {
1567 SendPollerMsg(dwRqId, POLLER_WARNING _T("Node name cannot be resolved\r\n"));
1568 }
1569 }
1570 else
1571 {
1572 if (g_dwFlags & AF_SYNC_NODE_NAMES_WITH_DNS)
1573 {
1574 SendPollerMsg(dwRqId, _T("Syncing node name with DNS\r\n"));
1575 SetPollerInfo(nPoller, "resolving name");
1576 if (ResolveName(TRUE))
1577 {
1578 SendPollerMsg(dwRqId, POLLER_INFO _T("Node name resolved to %s\r\n"), m_szName);
1579 bHasChanges = TRUE;
1580 }
1581 }
1582 else
1583 {
1584 SendPollerMsg(dwRqId, _T("Node name is OK\r\n"));
1585 }
1586 }
1587
1588 // Apply system templates
1589 pTemplate = FindTemplateByName(_T("@System.Agent"));
1590 if (pTemplate != NULL)
1591 {
1592 if (IsNativeAgent())
1593 {
1594 if (!pTemplate->IsChild(m_dwId))
1595 {
1596 pTemplate->ApplyToNode(this);
1597 }
1598 }
1599 else
1600 {
1601 if (pTemplate->IsChild(m_dwId))
1602 {
1603 pTemplate->DeleteChild(this);
1604 DeleteParent(pTemplate);
1605 pTemplate->QueueRemoveFromNode(m_dwId, TRUE);
1606 }
1607 }
1608 }
1609
1610 pTemplate = FindTemplateByName(_T("@System.SNMP"));
1611 if (pTemplate != NULL)
1612 {
1613 if (IsSNMPSupported())
1614 {
1615 if (!pTemplate->IsChild(m_dwId))
1616 {
1617 pTemplate->ApplyToNode(this);
1618 }
1619 }
1620 else
1621 {
1622 if (pTemplate->IsChild(m_dwId))
1623 {
1624 pTemplate->DeleteChild(this);
1625 DeleteParent(pTemplate);
1626 pTemplate->QueueRemoveFromNode(m_dwId, TRUE);
1627 }
1628 }
1629 }
1630
1631 SendPollerMsg(dwRqId, _T("Finished configuration poll for node %s\r\n")
1632 _T("Node configuration was%schanged after poll\r\n"),
1633 m_szName, bHasChanges ? _T(" ") : _T(" not "));
1634 }
1635
1636 // Finish configuration poll
1637 SetPollerInfo(nPoller, "cleanup");
1638 if (dwRqId == 0)
1639 m_dwDynamicFlags &= ~NDF_QUEUED_FOR_CONFIG_POLL;
1640 m_dwDynamicFlags &= ~NDF_RECHECK_CAPABILITIES;
1641 PollerUnlock();
1642 DbgPrintf(4, "Finished configuration poll for node %s (ID: %d)", m_szName, m_dwId);
1643
1644 if (bHasChanges)
1645 {
1646 LockData();
1647 Modify();
1648 UnlockData();
1649 }
1650}
1651
1652
1653//
1654// Connect to native agent
1655//
1656
1657BOOL Node::ConnectToAgent(void)
1658{
1659 BOOL bRet;
1660
1661 // Create new agent connection object if needed
1662 if (m_pAgentConnection == NULL)
1663 m_pAgentConnection = new AgentConnectionEx(htonl(m_dwIpAddr), m_wAgentPort, m_wAuthMethod, m_szSharedSecret);
1664
1665 // Check if we already connected
1666 if (m_pAgentConnection->Nop() == ERR_SUCCESS)
1667 return TRUE;
1668
1669 // Close current connection or clean up after broken connection
1670 m_pAgentConnection->Disconnect();
1671 m_pAgentConnection->SetPort(m_wAgentPort);
1672 m_pAgentConnection->SetAuthData(m_wAuthMethod, m_szSharedSecret);
1673 SetAgentProxy(m_pAgentConnection);
1674 bRet = m_pAgentConnection->Connect(g_pServerKey);
1675 if (bRet)
1676 {
1677 m_pAgentConnection->SetCommandTimeout(g_dwAgentCommandTimeout);
1678 m_pAgentConnection->EnableTraps();
1679 }
1680 return bRet;
1681}
1682
1683
1684//
1685// Get item's value via SNMP
1686//
1687
1688DWORD Node::GetItemFromSNMP(const char *szParam, DWORD dwBufSize, char *szBuffer)
1689{
1690 DWORD dwResult;
1691
1692 if ((m_dwDynamicFlags & NDF_SNMP_UNREACHABLE) ||
1693 (m_dwDynamicFlags & NDF_UNREACHABLE))
1694 {
1695 dwResult = SNMP_ERR_COMM;
1696 }
1697 else
1698 {
1699 SNMP_Transport *pTransport;
1700
1701 pTransport = CreateSNMPTransport();
1702 dwResult = SnmpGet(m_iSNMPVersion, pTransport, m_szCommunityString,
1703 szParam, NULL, 0, szBuffer, dwBufSize, FALSE, TRUE);
1704 delete pTransport;
1705 }
1706 return (dwResult == SNMP_ERR_SUCCESS) ? DCE_SUCCESS :
1707 ((dwResult == SNMP_ERR_NO_OBJECT) ? DCE_NOT_SUPPORTED : DCE_COMM_ERROR);
1708}
1709
1710
1711//
1712// Get item's value via SNMP from CheckPoint's agent
1713//
1714
1715DWORD Node::GetItemFromCheckPointSNMP(const char *szParam, DWORD dwBufSize, char *szBuffer)
1716{
1717 DWORD dwResult;
1718
1719 if ((m_dwDynamicFlags & NDF_CPSNMP_UNREACHABLE) ||
1720 (m_dwDynamicFlags & NDF_UNREACHABLE))
1721 {
1722 dwResult = SNMP_ERR_COMM;
1723 }
1724 else
1725 {
1726 SNMP_Transport *pTransport;
1727
1728 pTransport = new SNMP_UDPTransport;
1729 ((SNMP_UDPTransport *)pTransport)->CreateUDPTransport(NULL, htonl(m_dwIpAddr), CHECKPOINT_SNMP_PORT);
1730 dwResult = SnmpGet(SNMP_VERSION_1, pTransport,
1731 m_szCommunityString, szParam, NULL, 0, szBuffer,
1732 dwBufSize, FALSE, TRUE);
1733 delete pTransport;
1734 }
1735 return (dwResult == SNMP_ERR_SUCCESS) ? DCE_SUCCESS :
1736 ((dwResult == SNMP_ERR_NO_OBJECT) ? DCE_NOT_SUPPORTED : DCE_COMM_ERROR);
1737}
1738
1739
1740//
1741// Get item's value via native agent
1742//
1743
1744DWORD Node::GetItemFromAgent(const char *szParam, DWORD dwBufSize, char *szBuffer)
1745{
912b994d 1746 DWORD dwError = ERR_NOT_CONNECTED, dwResult = DCE_COMM_ERROR;
5039dede
AK
1747 DWORD dwTries = 3;
1748
1749 if ((m_dwDynamicFlags & NDF_AGENT_UNREACHABLE) ||
1750 (m_dwDynamicFlags & NDF_UNREACHABLE))
1751 return DCE_COMM_ERROR;
1752
1753 AgentLock();
1754
1755 // Establish connection if needed
1756 if (m_pAgentConnection == NULL)
1757 if (!ConnectToAgent())
1758 goto end_loop;
1759
1760 // Get parameter from agent
1761 while(dwTries-- > 0)
1762 {
1763 dwError = m_pAgentConnection->GetParameter((char *)szParam, dwBufSize, szBuffer);
1764 switch(dwError)
1765 {
1766 case ERR_SUCCESS:
1767 dwResult = DCE_SUCCESS;
1768 goto end_loop;
1769 case ERR_UNKNOWN_PARAMETER:
1770 dwResult = DCE_NOT_SUPPORTED;
1771 goto end_loop;
1772 case ERR_NOT_CONNECTED:
1773 case ERR_CONNECTION_BROKEN:
1774 if (!ConnectToAgent())
1775 goto end_loop;
1776 break;
1777 case ERR_REQUEST_TIMEOUT:
1778 // Reset connection to agent after timeout
1779 DbgPrintf(7, _T("Node(%s)->GetItemFromAgent(%s): timeout; resetting connection to agent..."), m_szName, szParam);
1780 delete_and_null(m_pAgentConnection);
1781 if (!ConnectToAgent())
1782 goto end_loop;
1783 DbgPrintf(7, _T("Node(%s)->GetItemFromAgent(%s): connection to agent restored successfully"), m_szName, szParam);
1784 break;
1785 }
1786 }
1787
1788end_loop:
1789 AgentUnlock();
1790 DbgPrintf(7, "Node(%s)->GetItemFromAgent(%s): dwError=%d dwResult=%d",
1791 m_szName, szParam, dwError, dwResult);
1792 return dwResult;
1793}
1794
1795
1796//
1797// Get value for server's internal parameter
1798//
1799
1800DWORD Node::GetInternalItem(const char *szParam, DWORD dwBufSize, char *szBuffer)
1801{
1802 DWORD dwError = DCE_SUCCESS;
1803
1804 if (!stricmp(szParam, "Status"))
1805 {
1806 sprintf(szBuffer, "%d", m_iStatus);
1807 }
1808 else if (!stricmp(szParam, "Dummy"))
1809 {
1810 _tcscpy(szBuffer, _T("0"));
1811 }
1812 else if (!stricmp(szParam, "AgentStatus"))
1813 {
1814 if (m_dwFlags & NF_IS_NATIVE_AGENT)
1815 {
1816 szBuffer[0] = (m_dwDynamicFlags & NDF_AGENT_UNREACHABLE) ? '1' : '0';
1817 szBuffer[1] = 0;
1818 }
1819 else
1820 {
1821 dwError = DCE_NOT_SUPPORTED;
1822 }
1823 }
1824 else if (MatchString("ChildStatus(*)", szParam, FALSE))
1825 {
1826 char *pEnd, szArg[256];
1827 DWORD i, dwId;
1828 NetObj *pObject = NULL;
1829
1830 NxGetParameterArg((char *)szParam, 1, szArg, 256);
1831 dwId = strtoul(szArg, &pEnd, 0);
1832 if (*pEnd != 0)
1833 {
1834 // Argument is object's name
1835 dwId = 0;
1836 }
1837
1838 // Find child object with requested ID or name
1839 LockChildList(FALSE);
1840 for(i = 0; i < m_dwChildCount; i++)
1841 {
1842 if (((dwId == 0) && (!stricmp(m_pChildList[i]->Name(), szArg))) ||
1843 (dwId == m_pChildList[i]->Id()))
1844 {
1845 pObject = m_pChildList[i];
1846 break;
1847 }
1848 }
1849 UnlockChildList();
1850
1851 if (pObject != NULL)
1852 {
1853 sprintf(szBuffer, "%d", pObject->Status());
1854 }
1855 else
1856 {
1857 dwError = DCE_NOT_SUPPORTED;
1858 }
1859 }
1860 else if (MatchString("ConditionStatus(*)", szParam, FALSE))
1861 {
1862 char *pEnd, szArg[256];
1863 DWORD dwId;
1864 NetObj *pObject = NULL;
1865
1866 NxGetParameterArg((char *)szParam, 1, szArg, 256);
1867 dwId = strtoul(szArg, &pEnd, 0);
1868 if (*pEnd == 0)
1869 {
1870 pObject = FindObjectById(dwId);
1871 if (pObject != NULL)
1872 if (pObject->Type() != OBJECT_CONDITION)
1873 pObject = NULL;
1874 }
1875 else
1876 {
1877 // Argument is object's name
1878 pObject = FindObjectByName(szArg, OBJECT_CONDITION);
1879 }
1880
1881 if (pObject != NULL)
1882 {
1883 if (pObject->IsTrustedNode(m_dwId))
1884 {
1885 sprintf(szBuffer, "%d", pObject->Status());
1886 }
1887 else
1888 {
1889 dwError = DCE_NOT_SUPPORTED;
1890 }
1891 }
1892 else
1893 {
1894 dwError = DCE_NOT_SUPPORTED;
1895 }
1896 }
1897 else if (m_dwFlags & NF_IS_LOCAL_MGMT)
1898 {
1899 if (!stricmp(szParam, "Server.AverageDCPollerQueueSize"))
1900 {
1901 sprintf(szBuffer, "%f", g_dAvgPollerQueueSize);
1902 }
1903 else if (!stricmp(szParam, "Server.AverageDBWriterQueueSize"))
1904 {
1905 sprintf(szBuffer, "%f", g_dAvgDBWriterQueueSize);
1906 }
1907 else if (!stricmp(szParam, "Server.AverageStatusPollerQueueSize"))
1908 {
1909 sprintf(szBuffer, "%f", g_dAvgStatusPollerQueueSize);
1910 }
1911 else if (!stricmp(szParam, "Server.AverageConfigurationPollerQueueSize"))
1912 {
1913 sprintf(szBuffer, "%f", g_dAvgConfigPollerQueueSize);
1914 }
1915 else if (!stricmp(szParam, "Server.AverageDCIQueuingTime"))
1916 {
1917 sprintf(szBuffer, "%u", g_dwAvgDCIQueuingTime);
1918 }
1919 else if (!stricmp(szParam, "Server.TotalEventsProcessed"))
1920 {
1921 sprintf(szBuffer, INT64_FMT, g_totalEventsProcessed);
1922 }
1923 else
1924 {
1925 dwError = DCE_NOT_SUPPORTED;
1926 }
1927 }
1928 else
1929 {
1930 dwError = DCE_NOT_SUPPORTED;
1931 }
1932
1933 return dwError;
1934}
1935
1936
1937//
1938// Get item's value for client
1939//
1940
1941DWORD Node::GetItemForClient(int iOrigin, const char *pszParam, char *pszBuffer, DWORD dwBufSize)
1942{
1943 DWORD dwResult = 0, dwRetCode;
1944
1945 // Get data from node
1946 switch(iOrigin)
1947 {
1948 case DS_INTERNAL:
1949 dwRetCode = GetInternalItem(pszParam, dwBufSize, pszBuffer);
1950 break;
1951 case DS_NATIVE_AGENT:
1952 dwRetCode = GetItemFromAgent(pszParam, dwBufSize, pszBuffer);
1953 break;
1954 case DS_SNMP_AGENT:
1955 dwRetCode = GetItemFromSNMP(pszParam, dwBufSize, pszBuffer);
1956 break;
1957 case DS_CHECKPOINT_AGENT:
1958 dwRetCode = GetItemFromCheckPointSNMP(pszParam, dwBufSize, pszBuffer);
1959 break;
1960 default:
1961 dwResult = RCC_INVALID_ARGUMENT;
1962 break;
1963 }
1964
1965 // Translate return code to RCC
1966 if (dwResult != RCC_INVALID_ARGUMENT)
1967 {
1968 switch(dwRetCode)
1969 {
1970 case DCE_SUCCESS:
1971 dwResult = RCC_SUCCESS;
1972 break;
1973 case DCE_COMM_ERROR:
1974 dwResult = RCC_COMM_FAILURE;
1975 break;
1976 case DCE_NOT_SUPPORTED:
1977 dwResult = RCC_DCI_NOT_SUPPORTED;
1978 break;
1979 default:
1980 dwResult = RCC_SYSTEM_FAILURE;
1981 break;
1982 }
1983 }
1984
1985 return dwResult;
1986}
1987
1988
1989//
1990// Put items which requires polling into the queue
1991//
1992
1993void Node::QueueItemsForPolling(Queue *pPollerQueue)
1994{
1995 DWORD i;
1996 time_t currTime;
1997
1998 if ((m_iStatus == STATUS_UNMANAGED) ||
1999 (m_dwFlags & NF_DISABLE_DATA_COLLECT) ||
2000 (m_bIsDeleted))
2001 return; // Do not collect data for unmanaged nodes or if data collection is disabled
2002
2003 currTime = time(NULL);
2004
2005 LockData();
2006 for(i = 0; i < m_dwNumItems; i++)
2007 {
2008 if (m_ppItems[i]->ReadyForPolling(currTime))
2009 {
2010 m_ppItems[i]->SetBusyFlag(TRUE);
2011 IncRefCount(); // Increment reference count for each queued DCI
2012 pPollerQueue->Put(m_ppItems[i]);
2013 }
2014 }
2015 UnlockData();
2016}
2017
2018
2019//
2020// Create CSCP message with object's data
2021//
2022
2023void Node::CreateMessage(CSCPMessage *pMsg)
2024{
2025 Template::CreateMessage(pMsg);
2026 pMsg->SetVariable(VID_FLAGS, m_dwFlags);
2027 pMsg->SetVariable(VID_AGENT_PORT, m_wAgentPort);
2028 pMsg->SetVariable(VID_AUTH_METHOD, m_wAuthMethod);
2029 pMsg->SetVariable(VID_SHARED_SECRET, m_szSharedSecret);
2030 pMsg->SetVariable(VID_COMMUNITY_STRING, m_szCommunityString);
2031 pMsg->SetVariable(VID_SNMP_OID, m_szObjectId);
2032 pMsg->SetVariable(VID_NODE_TYPE, m_dwNodeType);
2033 pMsg->SetVariable(VID_SNMP_VERSION, (WORD)m_iSNMPVersion);
2034 pMsg->SetVariable(VID_AGENT_VERSION, m_szAgentVersion);
2035 pMsg->SetVariable(VID_PLATFORM_NAME, m_szPlatformName);
2036 pMsg->SetVariable(VID_POLLER_NODE_ID, m_dwPollerNode);
2037 pMsg->SetVariable(VID_ZONE_GUID, m_dwZoneGUID);
2038 pMsg->SetVariable(VID_PROXY_NODE, m_dwProxyNode);
2039 pMsg->SetVariable(VID_SNMP_PROXY, m_dwSNMPProxy);
2040 pMsg->SetVariable(VID_REQUIRED_POLLS, (WORD)m_iRequiredPollCount);
2041 pMsg->SetVariable(VID_SYS_DESCRIPTION, m_szSysDescription);
2042 pMsg->SetVariable(VID_USE_IFXTABLE, (WORD)m_nUseIfXTable);
2043}
2044
2045
2046//
2047// Modify object from message
2048//
2049
2050DWORD Node::ModifyFromMessage(CSCPMessage *pRequest, BOOL bAlreadyLocked)
2051{
2052 if (!bAlreadyLocked)
2053 LockData();
2054
2055 // Change primary IP address
2056 if (pRequest->IsVariableExist(VID_IP_ADDRESS))
2057 {
2058 DWORD i, dwIpAddr;
2059
2060 dwIpAddr = pRequest->GetVariableLong(VID_IP_ADDRESS);
2061
2062 // Check if received IP address is one of node's interface addresses
2063 LockChildList(FALSE);
2064 for(i = 0; i < m_dwChildCount; i++)
2065 if ((m_pChildList[i]->Type() == OBJECT_INTERFACE) &&
2066 (m_pChildList[i]->IpAddr() == dwIpAddr))
2067 break;
2068 UnlockChildList();
2069 if (i == m_dwChildCount)
2070 {
2071 UnlockData();
2072 return RCC_INVALID_IP_ADDR;
2073 }
2074
2075 UpdateNodeIndex(m_dwIpAddr, dwIpAddr, this);
2076 m_dwIpAddr = dwIpAddr;
2077 }
2078
2079 // Poller node ID
2080 if (pRequest->IsVariableExist(VID_POLLER_NODE_ID))
2081 {
2082 DWORD dwNodeId;
2083 NetObj *pObject;
2084
2085 dwNodeId = pRequest->GetVariableLong(VID_POLLER_NODE_ID);
2086 pObject = FindObjectById(dwNodeId);
2087
2088 // Check if received id is a valid node id
2089 if (pObject == NULL)
2090 {
2091 UnlockData();
2092 return RCC_INVALID_OBJECT_ID;
2093 }
2094 if (pObject->Type() != OBJECT_NODE)
2095 {
2096 UnlockData();
2097 return RCC_INVALID_OBJECT_ID;
2098 }
2099
2100 m_dwPollerNode = dwNodeId;
2101 }
2102
2103 // Change listen port of native agent
2104 if (pRequest->IsVariableExist(VID_AGENT_PORT))
2105 m_wAgentPort = pRequest->GetVariableShort(VID_AGENT_PORT);
2106
2107 // Change authentication method of native agent
2108 if (pRequest->IsVariableExist(VID_AUTH_METHOD))
2109 m_wAuthMethod = pRequest->GetVariableShort(VID_AUTH_METHOD);
2110
2111 // Change shared secret of native agent
2112 if (pRequest->IsVariableExist(VID_SHARED_SECRET))
2113 pRequest->GetVariableStr(VID_SHARED_SECRET, m_szSharedSecret, MAX_SECRET_LENGTH);
2114
2115 // Change SNMP protocol version
2116 if (pRequest->IsVariableExist(VID_SNMP_VERSION))
2117 m_iSNMPVersion = pRequest->GetVariableShort(VID_SNMP_VERSION);
2118
2119 // Change SNMP community string
2120 if (pRequest->IsVariableExist(VID_COMMUNITY_STRING))
2121 pRequest->GetVariableStr(VID_COMMUNITY_STRING, m_szCommunityString, MAX_COMMUNITY_LENGTH);
2122
2123 // Change proxy node
2124 if (pRequest->IsVariableExist(VID_PROXY_NODE))
2125 m_dwProxyNode = pRequest->GetVariableLong(VID_PROXY_NODE);
2126
2127 // Change SNMP proxy node
2128 if (pRequest->IsVariableExist(VID_SNMP_PROXY))
2129 m_dwSNMPProxy = pRequest->GetVariableLong(VID_SNMP_PROXY);
2130
2131 // Number of required polls
2132 if (pRequest->IsVariableExist(VID_REQUIRED_POLLS))
2133 m_iRequiredPollCount = (int)pRequest->GetVariableShort(VID_REQUIRED_POLLS);
2134
2135 // Enable/disable usage of ifXTable
2136 if (pRequest->IsVariableExist(VID_USE_IFXTABLE))
2137 m_nUseIfXTable = (BYTE)pRequest->GetVariableShort(VID_USE_IFXTABLE);
2138
2139 // Change flags
2140 if (pRequest->IsVariableExist(VID_FLAGS))
2141 {
2142 m_dwFlags &= NF_SYSTEM_FLAGS;
2143 m_dwFlags |= pRequest->GetVariableLong(VID_FLAGS) & NF_USER_FLAGS;
2144 }
2145
2146 return Template::ModifyFromMessage(pRequest, TRUE);
2147}
2148
2149
2150//
2151// Wakeup node using magic packet
2152//
2153
2154DWORD Node::WakeUp(void)
2155{
2156 DWORD i, dwResult = RCC_NO_WOL_INTERFACES;
2157
2158 LockChildList(FALSE);
2159
2160 for(i = 0; i < m_dwChildCount; i++)
2161 if ((m_pChildList[i]->Type() == OBJECT_INTERFACE) &&
2162 (m_pChildList[i]->Status() != STATUS_UNMANAGED) &&
2163 (m_pChildList[i]->IpAddr() != 0))
2164 {
2165 dwResult = ((Interface *)m_pChildList[i])->WakeUp();
2166 break;
2167 }
2168
2169 UnlockChildList();
2170 return dwResult;
2171}
2172
2173
2174//
2175// Get status of interface with given index from SNMP agent
2176//
2177
2178int Node::GetInterfaceStatusFromSNMP(SNMP_Transport *pTransport, DWORD dwIndex)
2179{
2180 return SnmpGetInterfaceStatus(m_iSNMPVersion, pTransport, m_szCommunityString, dwIndex);
2181}
2182
2183
2184//
2185// Get status of interface with given index from native agent
2186//
2187
2188int Node::GetInterfaceStatusFromAgent(DWORD dwIndex)
2189{
2190 char szParam[128], szBuffer[32];
2191 DWORD dwAdminStatus, dwLinkState;
2192 int iStatus;
2193
2194 // Get administrative status
2195 sprintf(szParam, "Net.Interface.AdminStatus(%u)", dwIndex);
2196 if (GetItemFromAgent(szParam, 32, szBuffer) == DCE_SUCCESS)
2197 {
2198 dwAdminStatus = strtoul(szBuffer, NULL, 0);
2199
2200 switch(dwAdminStatus)
2201 {
2202 case 3:
2203 iStatus = STATUS_TESTING;
2204 break;
2205 case 2:
2206 case 0: // Agents before 0.2.1 may return 0 instead of 2
2207 iStatus = STATUS_DISABLED;
2208 break;
2209 case 1: // Interface administratively up, check link state
2210 sprintf(szParam, "Net.Interface.Link(%u)", dwIndex);
2211 if (GetItemFromAgent(szParam, 32, szBuffer) == DCE_SUCCESS)
2212 {
2213 dwLinkState = strtoul(szBuffer, NULL, 0);
2214 iStatus = (dwLinkState == 0) ? STATUS_CRITICAL : STATUS_NORMAL;
2215 }
2216 else
2217 {
2218 iStatus = STATUS_UNKNOWN;
2219 }
2220 break;
2221 default:
2222 iStatus = STATUS_UNKNOWN;
2223 break;
2224 }
2225 }
2226 else
2227 {
2228 iStatus = STATUS_UNKNOWN;
2229 }
2230
2231 return iStatus;
2232}
2233
2234
2235//
2236// Put list of supported parameters into CSCP message
2237//
2238
2239void Node::WriteParamListToMessage(CSCPMessage *pMsg)
2240{
2241 DWORD i, dwId;
2242
2243 LockData();
2244 if (m_pParamList != NULL)
2245 {
2246 pMsg->SetVariable(VID_NUM_PARAMETERS, m_dwNumParams);
2247 for(i = 0, dwId = VID_PARAM_LIST_BASE; i < m_dwNumParams; i++)
2248 {
2249 pMsg->SetVariable(dwId++, m_pParamList[i].szName);
2250 pMsg->SetVariable(dwId++, m_pParamList[i].szDescription);
2251 pMsg->SetVariable(dwId++, (WORD)m_pParamList[i].iDataType);
2252 }
2253 DbgPrintf(6, _T("Node[%s]::WriteParamListToMessage(): sending %d parameters"), m_szName, m_dwNumParams);
2254 }
2255 else
2256 {
2257 DbgPrintf(6, _T("Node[%s]::WriteParamListToMessage(): m_pParamList == NULL"), m_szName);
2258 pMsg->SetVariable(VID_NUM_PARAMETERS, (DWORD)0);
2259 }
2260 UnlockData();
2261}
2262
2263
2264//
2265// Open list of supported parameters for reading
2266//
2267
2268void Node::OpenParamList(DWORD *pdwNumParams, NXC_AGENT_PARAM **ppParamList)
2269{
2270 LockData();
2271 *pdwNumParams = m_dwNumParams;
2272 *ppParamList = m_pParamList;
2273}
2274
2275
2276//
2277// Check status of network service
2278//
2279
2280DWORD Node::CheckNetworkService(DWORD *pdwStatus, DWORD dwIpAddr, int iServiceType,
2281 WORD wPort, WORD wProto, TCHAR *pszRequest,
2282 TCHAR *pszResponse)
2283{
2284 DWORD dwError = ERR_NOT_CONNECTED;
2285
2286 if ((m_dwFlags & NF_IS_NATIVE_AGENT) &&
2287 (!(m_dwDynamicFlags & NDF_AGENT_UNREACHABLE)) &&
2288 (!(m_dwDynamicFlags & NDF_UNREACHABLE)))
2289 {
2290 AgentConnection *pConn;
2291
2292 pConn = CreateAgentConnection();
2293 if (pConn != NULL)
2294 {
2295 dwError = pConn->CheckNetworkService(pdwStatus, dwIpAddr, iServiceType,
2296 wPort, wProto, pszRequest, pszResponse);
2297 pConn->Disconnect();
2298 delete pConn;
2299 }
2300 }
2301 return dwError;
2302}
2303
2304
2305//
2306// Handler for object deletion
2307//
2308
2309void Node::OnObjectDelete(DWORD dwObjectId)
2310{
2311 if (dwObjectId == m_dwPollerNode)
2312 {
2313 // If deleted object is our poller node, change it to default
2314 /* LOCK? */
2315 m_dwPollerNode = 0;
2316 Modify();
2317 DbgPrintf(3, _T("Node \"%s\": poller node %d deleted"), m_szName, dwObjectId);
2318 }
2319}
2320
2321
2322//
2323// Check node for OSPF support
2324//
2325
2326void Node::CheckOSPFSupport(SNMP_Transport *pTransport)
2327{
2328 LONG nAdminStatus;
2329
2330 if (SnmpGet(m_iSNMPVersion, pTransport, m_szCommunityString,
2331 ".1.3.6.1.2.1.14.1.2.0", NULL, 0, &nAdminStatus, sizeof(LONG),
2332 FALSE, FALSE) == SNMP_ERR_SUCCESS)
2333 {
2334 LockData();
2335 if (nAdminStatus)
2336 {
2337 m_dwFlags |= NF_IS_OSPF;
2338 }
2339 else
2340 {
2341 m_dwFlags &= ~NF_IS_OSPF;
2342 }
2343 UnlockData();
2344 }
2345}
2346
2347
2348//
2349// Create ready to use agent connection
2350//
2351
2352AgentConnection *Node::CreateAgentConnection(void)
2353{
2354 AgentConnection *pConn;
2355
2356 if ((!(m_dwFlags & NF_IS_NATIVE_AGENT)) ||
2357 (m_dwDynamicFlags & NDF_AGENT_UNREACHABLE) ||
2358 (m_dwDynamicFlags & NDF_UNREACHABLE))
2359 return NULL;
2360
2361 pConn = new AgentConnection(htonl(m_dwIpAddr), m_wAgentPort,
2362 m_wAuthMethod, m_szSharedSecret);
2363 SetAgentProxy(pConn);
2364 if (!pConn->Connect(g_pServerKey))
2365 {
2366 delete pConn;
2367 pConn = NULL;
2368 }
2369 return pConn;
2370}
2371
2372
2373//
2374// Get last collected values of all DCIs
2375//
2376
2377DWORD Node::GetLastValues(CSCPMessage *pMsg)
2378{
2379 DWORD i, dwId, dwCount;
2380
2381 LockData();
2382
2383 for(i = 0, dwId = VID_DCI_VALUES_BASE, dwCount = 0; i < m_dwNumItems; i++)
2384 {
2385 if (_tcsnicmp(m_ppItems[i]->Description(), _T("@system."), 8))
2386 {
2387 m_ppItems[i]->GetLastValue(pMsg, dwId);
2388 dwId += 10;
2389 dwCount++;
2390 }
2391 }
2392 pMsg->SetVariable(VID_NUM_ITEMS, dwCount);
2393
2394 UnlockData();
2395 return RCC_SUCCESS;
2396}
2397
2398
2399//
2400// Clean expired DCI data
2401//
2402
2403void Node::CleanDCIData(void)
2404{
2405 DWORD i;
2406
2407 LockData();
2408 for(i = 0; i < m_dwNumItems; i++)
2409 m_ppItems[i]->DeleteExpiredData();
2410 UnlockData();
2411}
2412
2413
2414//
2415// Apply DCI from template
2416// pItem passed to this method should be a template's DCI
2417//
2418
2419BOOL Node::ApplyTemplateItem(DWORD dwTemplateId, DCItem *pItem)
2420{
2421 BOOL bResult = TRUE;
2422 DWORD i;
2423 DCItem *pNewItem;
2424
2425 LockData();
2426
2427 DbgPrintf(5, "Applying item \"%s\" to node \"%s\"", pItem->Name(), m_szName);
2428
2429 // Check if that template item exists
2430 for(i = 0; i < m_dwNumItems; i++)
2431 if ((m_ppItems[i]->TemplateId() == dwTemplateId) &&
2432 (m_ppItems[i]->TemplateItemId() == pItem->Id()))
2433 break; // Item with specified id already exist
2434
2435 if (i == m_dwNumItems)
2436 {
2437 // New item from template, just add it
2438 pNewItem = new DCItem(pItem);
2439 pNewItem->SetTemplateId(dwTemplateId, pItem->Id());
2440 pNewItem->ChangeBinding(CreateUniqueId(IDG_ITEM), this, TRUE);
2441 bResult = AddItem(pNewItem, TRUE);
2442 }
2443 else
2444 {
2445 // Update existing item
2446 m_ppItems[i]->UpdateFromTemplate(pItem);
2447 Modify();
2448 }
2449
2450 UnlockData();
2451 return bResult;
2452}
2453
2454
2455//
2456// Clean deleted template items from node's DCI list
2457// Arguments is template id and list of valid template item ids.
2458// all items related to given template and not presented in list should be deleted.
2459//
2460
2461void Node::CleanDeletedTemplateItems(DWORD dwTemplateId, DWORD dwNumItems, DWORD *pdwItemList)
2462{
2463 DWORD i, j, dwNumDeleted, *pdwDeleteList;
2464
2465 LockData();
2466
2467 pdwDeleteList = (DWORD *)malloc(sizeof(DWORD) * m_dwNumItems);
2468 dwNumDeleted = 0;
2469
2470 for(i = 0; i < m_dwNumItems; i++)
2471 if (m_ppItems[i]->TemplateId() == dwTemplateId)
2472 {
2473 for(j = 0; j < dwNumItems; j++)
2474 if (m_ppItems[i]->TemplateItemId() == pdwItemList[j])
2475 break;
2476
2477 // Delete DCI if it's not in list
2478 if (j == dwNumItems)
2479 pdwDeleteList[dwNumDeleted++] = m_ppItems[i]->Id();
2480 }
2481
2482 for(i = 0; i < dwNumDeleted; i++)
2483 DeleteItem(pdwDeleteList[i], FALSE);
2484
2485 UnlockData();
2486 free(pdwDeleteList);
2487}
2488
2489
2490//
2491// Unbind node from template, i.e either remove DCI association with template
2492// or remove these DCIs at all
2493//
2494
2495void Node::UnbindFromTemplate(DWORD dwTemplateId, BOOL bRemoveDCI)
2496{
2497 DWORD i, dwNumDeleted, *pdwDeleteList;
2498
2499 if (bRemoveDCI)
2500 {
2501 LockData();
2502
2503 pdwDeleteList = (DWORD *)malloc(sizeof(DWORD) * m_dwNumItems);
2504 dwNumDeleted = 0;
2505
2506 for(i = 0; i < m_dwNumItems; i++)
2507 if (m_ppItems[i]->TemplateId() == dwTemplateId)
2508 {
2509 pdwDeleteList[dwNumDeleted++] = m_ppItems[i]->Id();
2510 }
2511
2512 for(i = 0; i < dwNumDeleted; i++)
2513 DeleteItem(pdwDeleteList[i], FALSE);
2514
2515 UnlockData();
2516 }
2517 else
2518 {
2519 LockData();
2520
2521 for(i = 0; i < m_dwNumItems; i++)
2522 if (m_ppItems[i]->TemplateId() == dwTemplateId)
2523 {
2524 m_ppItems[i]->SetTemplateId(0, 0);
2525 }
2526
2527 UnlockData();
2528 }
2529}
2530
2531
2532//
2533// Change node's IP address
2534//
2535
2536void Node::ChangeIPAddress(DWORD dwIpAddr)
2537{
2538 DWORD i;
2539
2540 PollerLock();
2541
2542 LockData();
2543
2544 UpdateNodeIndex(m_dwIpAddr, dwIpAddr, this);
2545 m_dwIpAddr = dwIpAddr;
2546 m_dwDynamicFlags |= NDF_FORCE_CONFIGURATION_POLL | NDF_RECHECK_CAPABILITIES;
2547
2548 // Change status of node and all it's childs to UNKNOWN
2549 m_iStatus = STATUS_UNKNOWN;
2550 LockChildList(FALSE);
2551 for(i = 0; i < m_dwChildCount; i++)
2552 {
2553 m_pChildList[i]->ResetStatus();
2554 if (m_pChildList[i]->Type() == OBJECT_INTERFACE)
2555 {
2556 if (((Interface *)m_pChildList[i])->IsFake())
2557 {
2558 ((Interface *)m_pChildList[i])->SetIpAddr(dwIpAddr);
2559 }
2560 }
2561 }
2562 UnlockChildList();
2563
2564 Modify();
2565 UnlockData();
2566
2567 AgentLock();
2568 delete_and_null(m_pAgentConnection);
2569 AgentUnlock();
2570
2571 PollerUnlock();
2572}
2573
2574
2575//
2576// Get number of interface objects and pointer to the last one
2577//
2578
2579DWORD Node::GetInterfaceCount(Interface **ppInterface)
2580{
2581 DWORD i, dwCount;
2582
2583 LockChildList(FALSE);
2584 for(i = 0, dwCount = 0; i < m_dwChildCount; i++)
2585 if (m_pChildList[i]->Type() == OBJECT_INTERFACE)
2586 {
2587 dwCount++;
2588 *ppInterface = (Interface *)m_pChildList[i];
2589 }
2590 UnlockChildList();
2591 return dwCount;
2592}
2593
2594
2595//
2596// Update cache for all DCI's
2597//
2598
2599void Node::UpdateDCICache(void)
2600{
2601 DWORD i;
2602
2603 /* LOCK? */
2604 for(i = 0; i < m_dwNumItems; i++)
2605 m_ppItems[i]->UpdateCacheSize();
2606}
2607
2608
2609//
2610// Get routing table from node
2611//
2612
2613ROUTING_TABLE *Node::GetRoutingTable(void)
2614{
2615 ROUTING_TABLE *pRT = NULL;
2616
2617 if ((m_dwFlags & NF_IS_NATIVE_AGENT) && (!(m_dwFlags & NF_DISABLE_NXCP)))
2618 {
2619 AgentLock();
2620 if (ConnectToAgent())
2621 {
2622 pRT = m_pAgentConnection->GetRoutingTable();
2623 }
2624 AgentUnlock();
2625 }
2626 if ((pRT == NULL) && (m_dwFlags & NF_IS_SNMP) && (!(m_dwFlags & NF_DISABLE_SNMP)))
2627 {
2628 SNMP_Transport *pTransport;
2629
2630 pTransport = CreateSNMPTransport();
2631 pRT = SnmpGetRoutingTable(m_iSNMPVersion, pTransport, m_szCommunityString);
2632 delete pTransport;
2633 }
2634
2635 if (pRT != NULL)
2636 {
2637 SortRoutingTable(pRT);
2638 }
2639 return pRT;
2640}
2641
2642
2643//
2644// Get next hop for given destination address
2645//
2646
2647BOOL Node::GetNextHop(DWORD dwSrcAddr, DWORD dwDestAddr, DWORD *pdwNextHop,
2648 DWORD *pdwIfIndex, BOOL *pbIsVPN)
2649{
2650 DWORD i;
2651 BOOL bResult = FALSE;
2652
2653 // Check VPN connectors
2654 LockChildList(FALSE);
2655 for(i = 0; i < m_dwChildCount; i++)
2656 if (m_pChildList[i]->Type() == OBJECT_VPNCONNECTOR)
2657 {
2658 if (((VPNConnector *)m_pChildList[i])->IsRemoteAddr(dwDestAddr) &&
2659 ((VPNConnector *)m_pChildList[i])->IsLocalAddr(dwSrcAddr))
2660 {
2661 *pdwNextHop = ((VPNConnector *)m_pChildList[i])->GetPeerGatewayAddr();
2662 *pdwIfIndex = m_pChildList[i]->Id();
2663 *pbIsVPN = TRUE;
2664 bResult = TRUE;
2665 break;
2666 }
2667 }
2668 UnlockChildList();
2669
2670 // Check routing table
2671 if (!bResult)
2672 {
2673 RTLock();
2674 if (m_pRoutingTable != NULL)
2675 {
2676 for(i = 0; i < (DWORD)m_pRoutingTable->iNumEntries; i++)
2677 if ((dwDestAddr & m_pRoutingTable->pRoutes[i].dwDestMask) == m_pRoutingTable->pRoutes[i].dwDestAddr)
2678 {
2679 *pdwNextHop = m_pRoutingTable->pRoutes[i].dwNextHop;
2680 *pdwIfIndex = m_pRoutingTable->pRoutes[i].dwIfIndex;
2681 *pbIsVPN = FALSE;
2682 bResult = TRUE;
2683 break;
2684 }
2685 }
2686 RTUnlock();
2687 }
2688
2689 return bResult;
2690}
2691
2692
2693//
2694// Update cached routing table
2695//
2696
2697void Node::UpdateRoutingTable(void)
2698{
2699 ROUTING_TABLE *pRT;
2700
2701 pRT = GetRoutingTable();
2702 if (pRT != NULL)
2703 {
2704 RTLock();
2705 DestroyRoutingTable(m_pRoutingTable);
2706 m_pRoutingTable = pRT;
2707 RTUnlock();
2708 }
2709 m_tLastRTUpdate = time(NULL);
2710 m_dwDynamicFlags &= ~NDF_QUEUED_FOR_ROUTE_POLL;
2711}
2712
2713
2714//
2715// Call SNMP Enumerate with node's SNMP parameters
2716//
2717
2718DWORD Node::CallSnmpEnumerate(const char *pszRootOid,
2719 DWORD (* pHandler)(DWORD, const char *, SNMP_Variable *, SNMP_Transport *, void *),
2720 void *pArg)
2721{
2722 if ((m_dwFlags & NF_IS_SNMP) &&
2723 (!(m_dwDynamicFlags & NDF_SNMP_UNREACHABLE)) &&
2724 (!(m_dwDynamicFlags & NDF_UNREACHABLE)))
2725 {
2726 SNMP_Transport *pTransport;
2727 DWORD dwResult;
2728
2729 pTransport = CreateSNMPTransport();
2730 dwResult = SnmpEnumerate(m_iSNMPVersion, pTransport,
2731 m_szCommunityString, pszRootOid, pHandler, pArg, FALSE);
2732 delete pTransport;
2733 return dwResult;
2734 }
2735 else
2736 {
2737 return SNMP_ERR_COMM;
2738 }
2739}
2740
2741
2742//
2743// Set proxy information for agent's connection
2744//
2745
2746void Node::SetAgentProxy(AgentConnection *pConn)
2747{
2748 if (m_dwProxyNode != 0)
2749 {
2750 Node *pNode;
2751
2752 pNode = (Node *)FindObjectById(m_dwProxyNode);
2753 if (pNode != NULL)
2754 {
2755 pConn->SetProxy(htonl(pNode->m_dwIpAddr), pNode->m_wAgentPort,
2756 pNode->m_wAuthMethod, pNode->m_szSharedSecret);
2757 }
2758 }
2759}
2760
2761
2762//
2763// Prepare node object for deletion
2764//
2765
2766void Node::PrepareForDeletion(void)
2767{
2768 // Prevent node from being queued for polling
2769 LockData();
2770 m_dwDynamicFlags |= NDF_POLLING_DISABLED;
2771 UnlockData();
2772
2773 // Wait for all pending polls
2774 while(1)
2775 {
2776 LockData();
2777 if ((m_dwDynamicFlags &
2778 (NDF_QUEUED_FOR_STATUS_POLL | NDF_QUEUED_FOR_CONFIG_POLL |
2779 NDF_QUEUED_FOR_DISCOVERY_POLL | NDF_QUEUED_FOR_ROUTE_POLL)) == 0)
2780 {
2781 UnlockData();
2782 break;
2783 }
2784 UnlockData();
2785 ThreadSleepMs(100);
2786 }
2787 Template::PrepareForDeletion();
2788}
2789
2790
2791//
2792// Check if specified SNMP variable set to specified value.
2793// If variable doesn't exist at all, will return FALSE
2794//
2795
2796BOOL Node::CheckSNMPIntegerValue(SNMP_Transport *pTransport, const char *pszOID, int nValue)
2797{
2798 DWORD dwTemp;
2799
2800 if (SnmpGet(m_iSNMPVersion, pTransport, m_szCommunityString,
2801 pszOID, NULL, 0, &dwTemp, sizeof(DWORD), FALSE, FALSE) == SNMP_ERR_SUCCESS)
2802 return (int)dwTemp == nValue;
2803 return FALSE;
2804}
2805
2806
2807//
2808// Check and update if needed interface names
2809//
2810
2811void Node::CheckInterfaceNames(INTERFACE_LIST *pIfList)
2812{
2813 int i;
2814 TCHAR *ptr;
2815
2816 if ((m_dwNodeType == NODE_TYPE_NORTEL_BAYSTACK) ||
2817 (m_dwNodeType == NODE_TYPE_NORTEL_OPTERA))
2818 {
2819 // Translate interface names
2820 for(i = 0; i < pIfList->iNumEntries; i++)
2821 {
2822 if ((ptr = _tcsstr(pIfList->pInterfaces[i].szName, _T("- Port"))) != NULL)
2823 {
2824 ptr += 2;
2825 memmove(pIfList->pInterfaces[i].szName, ptr, _tcslen(ptr) + 1);
2826 }
2827 else if ((ptr = _tcsstr(pIfList->pInterfaces[i].szName, _T("- Unit"))) != NULL)
2828 {
2829 ptr += 2;
2830 memmove(pIfList->pInterfaces[i].szName, ptr, _tcslen(ptr) + 1);
2831 }
2832 else if ((_tcsstr(pIfList->pInterfaces[i].szName, _T("BayStack")) != NULL) ||
2833 (_tcsstr(pIfList->pInterfaces[i].szName, _T("Nortel Ethernet Switch")) != NULL))
2834 {
2835 ptr = _tcsrchr(pIfList->pInterfaces[i].szName, _T('-'));
2836 if (ptr != NULL)
2837 {
2838 ptr++;
2839 while(*ptr == _T(' '))
2840 ptr++;
2841 memmove(pIfList->pInterfaces[i].szName, ptr, _tcslen(ptr) + 1);
2842 }
2843 }
2844 StrStrip(pIfList->pInterfaces[i].szName);
2845 }
2846 }
2847
2848 // Cut interface names to MAX_OBJECT_NAME and check for unnamed interfaces
2849 for(i = 0; i < pIfList->iNumEntries; i++)
2850 {
2851 pIfList->pInterfaces[i].szName[MAX_OBJECT_NAME - 1] = 0;
2852 if (pIfList->pInterfaces[i].szName[0] == 0)
2853 _stprintf(pIfList->pInterfaces[i].szName, _T("%d"), pIfList->pInterfaces[i].dwIndex);
2854 }
2855}
2856
2857
2858//
2859// Get cluster object this node belongs to, if any
2860//
2861
2862Cluster *Node::GetMyCluster(void)
2863{
2864 DWORD i;
2865 Cluster *pCluster = NULL;
2866
2867 LockParentList(FALSE);
2868 for(i = 0; i < m_dwParentCount; i++)
2869 if (m_pParentList[i]->Type() == OBJECT_CLUSTER)
2870 {
2871 pCluster = (Cluster *)m_pParentList[i];
2872 break;
2873 }
2874 UnlockParentList();
2875 return pCluster;
2876}
2877
2878
2879//
2880// Create SNMP transport
2881//
2882
2883SNMP_Transport *Node::CreateSNMPTransport(void)
2884{
2885 SNMP_Transport *pTransport = NULL;
2886
2887 if (m_dwSNMPProxy == 0)
2888 {
2889 pTransport = new SNMP_UDPTransport;
2890 ((SNMP_UDPTransport *)pTransport)->CreateUDPTransport(NULL, htonl(m_dwIpAddr), m_wSNMPPort);
2891 }
2892 else
2893 {
2894 NetObj *pObject;
2895
2896 pObject = FindObjectById(m_dwSNMPProxy);
2897 if (pObject != NULL)
2898 {
2899 if (pObject->Type() == OBJECT_NODE)
2900 {
2901 AgentConnection *pConn;
2902
2903 pConn = ((Node *)pObject)->CreateAgentConnection();
2904 if (pConn != NULL)
2905 {
2906 pTransport = new SNMP_ProxyTransport(pConn, m_dwIpAddr, m_wSNMPPort);
2907 }
2908 }
2909 }
2910 }
2911 return pTransport;
2912}
2913
2914
2915//
2916// Resolve node's name
2917//
2918
2919BOOL Node::ResolveName(BOOL useOnlyDNS)
2920{
2921 BOOL bSuccess = FALSE;
2922 HOSTENT *hs;
2923 DWORD i, dwAddr;
2924 TCHAR szBuffer[256];
2925
2926 DbgPrintf(4, _T("Resolving name for node %d [%s]..."), m_dwId, m_szName);
2927
2928 // Try to resolve primary IP
2929 dwAddr = htonl(m_dwIpAddr);
2930 hs = gethostbyaddr((const char *)&dwAddr, 4, AF_INET);
2931 if (hs != NULL)
2932 {
2933 nx_strncpy(m_szName, hs->h_name, MAX_OBJECT_NAME);
2934 bSuccess = TRUE;
2935 }
2936 else
2937 {
2938 // Try to resolve each interface's IP address
2939 LockChildList(FALSE);
2940 for(i = 0; i < m_dwChildCount; i++)
2941 {
2942 if (m_pChildList[i]->Type() == OBJECT_INTERFACE)
2943 {
2944 dwAddr = htonl(m_pChildList[i]->IpAddr());
2945 if (dwAddr != 0)
2946 {
2947 hs = gethostbyaddr((const char *)&dwAddr, 4, AF_INET);
2948 if (hs != NULL)
2949 {
2950 nx_strncpy(m_szName, hs->h_name, MAX_OBJECT_NAME);
2951 bSuccess = TRUE;
2952 break;
2953 }
2954 }
2955 }
2956 }
2957 UnlockChildList();
2958
2959 // Try to get hostname from agent if address resolution fails
2960 if (!(bSuccess || useOnlyDNS))
2961 {
2962 DbgPrintf(4, _T("Resolving name for node %d [%s] via agent..."), m_dwId, m_szName);
2963 if (GetItemFromAgent("System.Hostname", 256, szBuffer) == DCE_SUCCESS)
2964 {
2965 StrStrip(szBuffer);
2966 if (szBuffer[0] != 0)
2967 {
2968 nx_strncpy(m_szName, szBuffer, MAX_OBJECT_NAME);
2969 bSuccess = TRUE;
2970 }
2971 }
2972 }
2973
2974 // Try to get hostname from SNMP if other methods fails
2975 if (!(bSuccess || useOnlyDNS))
2976 {
2977 DbgPrintf(4, _T("Resolving name for node %d [%s] via SNMP..."), m_dwId, m_szName);
2978 if (GetItemFromSNMP(".1.3.6.1.2.1.1.5.0", 256, szBuffer) == DCE_SUCCESS)
2979 {
2980 StrStrip(szBuffer);
2981 if (szBuffer[0] != 0)
2982 {
2983 nx_strncpy(m_szName, szBuffer, MAX_OBJECT_NAME);
2984 bSuccess = TRUE;
2985 }
2986 }
2987 }
2988 }
2989
2990 if (bSuccess)
2991 DbgPrintf(4, _T("Name for node %d was resolved to %s"), m_dwId, m_szName);
2992 else
2993 DbgPrintf(4, _T("Name for node %d was not resolved"), m_dwId, m_szName);
2994 return bSuccess;
2995}
2996
2997
2998//
2999// Send list of system DCIs
3000//
3001
3002DWORD Node::GetSystemDCIList(CSCPMessage *pMsg)
3003{
3004 DWORD i, dwId, dwCount;
3005
3006 LockData();
3007
3008 for(i = 0, dwId = VID_SYSDCI_LIST_BASE, dwCount = 0; i < m_dwNumItems; i++)
3009 {
3010 if (!_tcsnicmp(m_ppItems[i]->Description(), _T("@System."), 8))
3011 {
3012 pMsg->SetVariable(dwId++, m_ppItems[i]->Id());
3013 pMsg->SetVariable(dwId++, (TCHAR *)m_ppItems[i]->Description());
3014 pMsg->SetVariable(dwId++, (WORD)m_ppItems[i]->Status());
3015 dwId += 7;
3016 dwCount++;
3017 }
3018 }
3019 pMsg->SetVariable(VID_NUM_ITEMS, dwCount);
3020
3021 UnlockData();
3022 return RCC_SUCCESS;
3023}
3024
3025
3026//
3027// Get current layer 2 topology (as dynamically created list which should be destroyed by caller)
3028// Will return NULL if there are no topology information or it is expired
3029//
3030
3031nxmap_ObjList *Node::GetL2Topology(void)
3032{
3033 nxmap_ObjList *pResult;
3034 DWORD dwExpTime;
3035
3036 dwExpTime = ConfigReadULong(_T("TopologyExpirationTime"), 900);
3037 MutexLock(m_mutexTopoAccess, INFINITE);
3038 if ((m_pTopology == NULL) || (m_tLastTopologyPoll + (time_t)dwExpTime < time(NULL)))
3039 {
3040 pResult = NULL;
3041 }
3042 else
3043 {
3044 pResult = new nxmap_ObjList(m_pTopology);
3045 }
3046 MutexUnlock(m_mutexTopoAccess);
3047 return pResult;
3048}
3049
3050
3051//
3052// Rebuild layer 2 topology and return it as dynamically reated list which should be destroyed by caller
3053//
3054
3055nxmap_ObjList *Node::BuildL2Topology(DWORD *pdwStatus)
3056{
3057 nxmap_ObjList *pResult;
3058 int nDepth;
3059
3060 nDepth = ConfigReadInt(_T("TopologyDiscoveryRadius"), 5);
3061 MutexLock(m_mutexTopoAccess, INFINITE);
3062 delete m_pTopology;
3063 if ((m_dwFlags & NF_IS_CDP) || (m_dwFlags & NF_IS_SONMP) || (m_dwFlags & NF_IS_LLDP))
3064 {
3065 m_pTopology = new nxmap_ObjList;
3066 if ((*pdwStatus = ::BuildL2Topology(*m_pTopology, this, NULL, nDepth, NULL)) == RCC_SUCCESS)
3067 {
3068 m_tLastTopologyPoll = time(NULL);
3069 pResult = new nxmap_ObjList(m_pTopology);
3070 }
3071 else
3072 {
3073 delete_and_null(m_pTopology);
3074 pResult = NULL;
3075 }
3076 }
3077 else
3078 {
3079 pResult = NULL;
3080 m_pTopology = NULL;
3081 *pdwStatus = RCC_NO_L2_TOPOLOGY_SUPPORT;
3082 }
3083 MutexUnlock(m_mutexTopoAccess);
3084 return pResult;
3085}
3086
3087
3088//
3089// Check subnet bindings
3090//
3091
3092void Node::CheckSubnetBinding(INTERFACE_LIST *pIfList)
3093{
3094 Subnet *pSubnet;
3095 Interface *pInterface;
3096 Cluster *pCluster;
3097 NetObj **ppUnlinkList;
3098 int i, j, count;
3099 BOOL isSync;
3100
3101 pCluster = GetMyCluster();
3102
3103 // Check if we have subnet bindings for all interfaces
3104 for(i = 0; i < pIfList->iNumEntries; i++)
3105 {
3106 if (pIfList->pInterfaces[i].dwIpAddr != 0)
3107 {
3108 pInterface = FindInterface(pIfList->pInterfaces[i].dwIndex, pIfList->pInterfaces[i].dwIpAddr);
3109 if (pInterface == NULL)
3110 {
3111 nxlog_write(MSG_INTERNAL_ERROR, EVENTLOG_WARNING_TYPE, "s", _T("Cannot find interface object in Node::CheckSubnetBinding()"));
3112 break; // Something goes really wrong
3113 }
3114
3115 // Is cluster interconnect interface?
3116 isSync = (pCluster != NULL) ? pCluster->IsSyncAddr(pInterface->IpAddr()) : FALSE;
3117
3118 pSubnet = FindSubnetForNode(pIfList->pInterfaces[i].dwIpAddr);
3119 if (pSubnet != NULL)
3120 {
3121 if (isSync)
3122 {
3123 pSubnet = NULL; // No further checks on this subnet
3124 }
3125 else
3126 {
3127 if (pSubnet->IsSyntheticMask())
3128 {
3129 DbgPrintf(4, _T("Setting correct netmask for subnet %s [%d] from node %s [%d]"),
3130 pSubnet->Name(), pSubnet->Id(), m_szName, m_dwId);
3131 pSubnet->SetCorrectMask(pInterface->IpAddr() & pInterface->IpNetMask(), pInterface->IpNetMask());
3132 }
3133 }
3134 }
3135 else if (!isSync)
3136 {
3137 // Create subnet
3138 pSubnet = new Subnet(pIfList->pInterfaces[i].dwIpAddr & pIfList->pInterfaces[i].dwIpNetMask,
3139 pIfList->pInterfaces[i].dwIpNetMask, m_dwZoneGUID, FALSE);
3140 NetObjInsert(pSubnet, TRUE);
3141 g_pEntireNet->AddSubnet(pSubnet);
3142 pSubnet->AddNode(this);
3143 DbgPrintf(4, _T("Node::CheckSubnetBinding(): Creating new subnet %s [%d] for node %s [%d]"),
3144 pSubnet->Name(), pSubnet->Id(), m_szName, m_dwId);
3145 }
3146
3147 // Check if subnet mask is correct on interface
3148 if ((pSubnet != NULL) && (pSubnet->IpNetMask() != pIfList->pInterfaces[i].dwIpNetMask))
3149 {
3150 PostEvent(EVENT_INCORRECT_NETMASK, m_dwId, "idsaa", pInterface->Id(),
3151 pInterface->IfIndex(), pInterface->Name(),
3152 pInterface->IpNetMask(), pSubnet->IpNetMask());
3153 }
3154 }
3155 }
3156
3157 // Check if we have incorrect subnets as parents
3158 LockParentList(FALSE);
3159 LockChildList(FALSE);
3160 ppUnlinkList = (NetObj **)malloc(sizeof(NetObj *) * m_dwParentCount);
3161 for(i = 0, count = 0; i < (int)m_dwParentCount; i++)
3162 {
3163 if (m_pParentList[i]->Type() == OBJECT_SUBNET)
3164 {
3165 pSubnet = (Subnet *)m_pParentList[i];
3166 for(j = 0; j < (int)m_dwChildCount; j++)
3167 {
3168 if (m_pChildList[j]->Type() == OBJECT_INTERFACE)
3169 {
3170 if (pSubnet->IpAddr() == (m_pChildList[j]->IpAddr() & pSubnet->IpNetMask()))
3171 {
3172 if (pCluster != NULL)
3173 {
3174 if (pCluster->IsSyncAddr(m_pChildList[j]->IpAddr()))
3175 {
3176 j = (int)m_dwChildCount; // Cause to unbind from this subnet
3177 }
3178 }
3179 break;
3180 }
3181 }
3182 }
3183 if (j == (int)m_dwChildCount)
3184 {
3185 DbgPrintf(4, _T("Node::CheckSubnetBinding(): Subnet %s [%d] is incorrect for node %s [%d]"),
3186 pSubnet->Name(), pSubnet->Id(), m_szName, m_dwId);
3187 ppUnlinkList[count++] = pSubnet;
3188 }
3189 }
3190 }
3191 UnlockChildList();
3192 UnlockParentList();
3193
3194 // Unlink for incorrect subnet objects
3195 for(i = 0; i < count; i++)
3196 {
3197 ppUnlinkList[i]->DeleteChild(this);
3198 DeleteParent(ppUnlinkList[i]);
3199 }
3200 safe_free(ppUnlinkList);
3201}
3202
3203
3204//
3205// Update interface names
3206//
3207
3208void Node::UpdateInterfaceNames(ClientSession *pSession, DWORD dwRqId)
3209{
3210 INTERFACE_LIST *pIfList;
3211 DWORD i;
3212 int j;
3213
3214 PollerLock();
3215 m_pPollRequestor = pSession;
3216 SendPollerMsg(dwRqId, _T("Starting interface names poll for node %s\r\n"), m_szName);
3217 DbgPrintf(4, "Starting interface names poll for node %s (ID: %d)", m_szName, m_dwId);
3218
3219 // Retrieve interface list
3220 pIfList = GetInterfaceList();
3221 if (pIfList != NULL)
3222 {
3223 // Check names of existing interfaces
3224 for(j = 0; j < pIfList->iNumEntries; j++)
3225 {
3226 LockChildList(FALSE);
3227 for(i = 0; i < m_dwChildCount; i++)
3228 {
3229 if (m_pChildList[i]->Type() == OBJECT_INTERFACE)
3230 {
3231 Interface *pInterface = (Interface *)m_pChildList[i];
3232
3233 if (pIfList->pInterfaces[j].dwIndex == pInterface->IfIndex())
3234 {
3235 SendPollerMsg(dwRqId, _T(" Checking interface %d (%s)\r\n"), pInterface->IfIndex(), pInterface->Name());
3236 if (strcmp(pIfList->pInterfaces[j].szName, pInterface->Name()))
3237 {
3238 pInterface->SetName(pIfList->pInterfaces[j].szName);
3239 SendPollerMsg(dwRqId, POLLER_WARNING _T(" Name of interface %d changed to %s\r\n"), pInterface->IfIndex(), pIfList->pInterfaces[j].szName);
3240 }
3241 break;
3242 }
3243 }
3244 }
3245 UnlockChildList();
3246 }
3247
3248 DestroyInterfaceList(pIfList);
3249 }
3250 else /* pIfList == NULL */
3251 {
3252 SendPollerMsg(dwRqId, POLLER_ERROR _T(" Unable to get interface list from node\r\n"));
3253 }
3254
3255 // Finish poll
3256 SendPollerMsg(dwRqId, _T("Finished interface names poll for node %s\r\n"), m_szName);
3257 PollerUnlock();
3258 DbgPrintf(4, "Finished interface names poll for node %s (ID: %d)", m_szName, m_dwId);
3259}