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