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