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