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