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