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