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