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