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