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