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