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