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