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