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