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