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