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