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