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