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