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