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