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