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