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