Added is_ospf field to nodes table
[public/netxms.git] / src / server / core / node.cpp
CommitLineData
eefe7d68 1/*
1275c750 2** NetXMS - Network Management System
b50f1100 3** Copyright (C) 2003, 2004 Victor Kirhenshtein
eefe7d68
VK
4**
5** This program is free software; you can redistribute it and/or modify
6** it under the terms of the GNU General Public License as published by
7** the Free Software Foundation; either version 2 of the License, or
8** (at your option) any later version.
9**
10** This program is distributed in the hope that it will be useful,
11** but WITHOUT ANY WARRANTY; without even the implied warranty of
12** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13** GNU General Public License for more details.
14**
15** You should have received a copy of the GNU General Public License
16** along with this program; if not, write to the Free Software
17** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18**
19** $module: node.cpp
20**
21**/
22
a551fe4d 23#include "nxcore.h"
eefe7d68
VK
24
25
26//
27// Node class default constructor
28//
29
30Node::Node()
b50f1100 31 :Template()
eefe7d68
VK
32{
33 m_dwFlags = 0;
34 m_dwDiscoveryFlags = 0;
4e839863 35 m_dwDynamicFlags = 0;
18e26ff8 36 m_dwNodeType = NODE_TYPE_GENERIC;
2da1357c
VK
37 m_wAgentPort = AGENT_LISTEN_PORT;
38 m_wAuthMethod = AUTH_NONE;
39 m_szSharedSecret[0] = 0;
40 m_iStatusPollType = POLL_ICMP_PING;
469b937c 41 m_iSNMPVersion = SNMP_VERSION_1;
2da1357c 42 strcpy(m_szCommunityString, "public");
469b937c 43 m_szObjectId[0] = 0;
48b1c0ac 44 m_tLastDiscoveryPoll = 0;
f00307b7 45 m_tLastStatusPoll = 0;
364aa19a
VK
46 m_tLastConfigurationPoll = 0;
47 m_iSnmpAgentFails = 0;
48 m_iNativeAgentFails = 0;
323f8bec 49 m_hPollerMutex = MutexCreate();
3ea35b38 50 m_hAgentAccessMutex = MutexCreate();
1275c750 51 m_pAgentConnection = NULL;
ae3a55d9 52 m_szAgentVersion[0] = 0;
1c8b8363 53 m_szPlatformName[0] = 0;
89235715
VK
54 m_dwNumParams = 0;
55 m_pParamList = NULL;
1a735d7c 56 m_dwPollerNode = 0;
eefe7d68
VK
57}
58
59
60//
61// Constructor for new node object
62//
63
64Node::Node(DWORD dwAddr, DWORD dwFlags, DWORD dwDiscoveryFlags)
b50f1100 65 :Template()
eefe7d68
VK
66{
67 m_dwIpAddr = dwAddr;
68 m_dwFlags = dwFlags;
4e839863 69 m_dwDynamicFlags = 0;
18e26ff8 70 m_dwNodeType = NODE_TYPE_GENERIC;
eefe7d68 71 m_dwDiscoveryFlags = dwDiscoveryFlags;
2da1357c
VK
72 m_wAgentPort = AGENT_LISTEN_PORT;
73 m_wAuthMethod = AUTH_NONE;
74 m_szSharedSecret[0] = 0;
75 m_iStatusPollType = POLL_ICMP_PING;
469b937c 76 m_iSNMPVersion = SNMP_VERSION_1;
2da1357c 77 strcpy(m_szCommunityString, "public");
cc140cce 78 IpToStr(dwAddr, m_szName); // Make default name from IP address
469b937c 79 m_szObjectId[0] = 0;
48b1c0ac 80 m_tLastDiscoveryPoll = 0;
f00307b7 81 m_tLastStatusPoll = 0;
364aa19a
VK
82 m_tLastConfigurationPoll = 0;
83 m_iSnmpAgentFails = 0;
84 m_iNativeAgentFails = 0;
323f8bec 85 m_hPollerMutex = MutexCreate();
3ea35b38 86 m_hAgentAccessMutex = MutexCreate();
1275c750 87 m_pAgentConnection = NULL;
ae3a55d9 88 m_szAgentVersion[0] = 0;
1c8b8363 89 m_szPlatformName[0] = 0;
89235715
VK
90 m_dwNumParams = 0;
91 m_pParamList = NULL;
1a735d7c 92 m_dwPollerNode = 0;
eefe7d68
VK
93}
94
95
96//
97// Node destructor
98//
99
100Node::~Node()
101{
323f8bec 102 MutexDestroy(m_hPollerMutex);
3ea35b38 103 MutexDestroy(m_hAgentAccessMutex);
1275c750
VK
104 if (m_pAgentConnection != NULL)
105 delete m_pAgentConnection;
89235715 106 safe_free(m_pParamList);
eefe7d68
VK
107}
108
109
2da1357c
VK
110//
111// Create object from database data
112//
113
114BOOL Node::CreateFromDB(DWORD dwId)
115{
ae3a55d9 116 char szQuery[512];
2da1357c
VK
117 DB_RESULT hResult;
118 int i, iNumRows;
119 DWORD dwSubnetId;
120 NetObj *pObject;
333ece94 121 BOOL bResult = FALSE;
2da1357c 122
5eba0220
VK
123 _sntprintf(szQuery, 512, "SELECT name,status,primary_ip,is_snmp,is_agent,is_bridge,"
124 "is_router,is_ospf,snmp_version,discovery_flags,auth_method,secret,"
ae3a55d9 125 "agent_port,status_poll_type,community,snmp_oid,is_local_mgmt,"
d4c266b6 126 "image_id,is_deleted,description,node_type,agent_version,"
1a735d7c 127 "platform_name,poller_node_id FROM nodes WHERE id=%d", dwId);
2da1357c
VK
128 hResult = DBSelect(g_hCoreDB, szQuery);
129 if (hResult == 0)
130 return FALSE; // Query failed
131
132 if (DBGetNumRows(hResult) == 0)
133 {
134 DBFreeResult(hResult);
135 return FALSE;
136 }
137
138 m_dwId = dwId;
5eba0220
VK
139 strncpy(m_szName, DBGetField(hResult, 0, 0), MAX_OBJECT_NAME);
140 m_iStatus = DBGetFieldLong(hResult, 0, 1);
141 m_dwIpAddr = DBGetFieldIPAddr(hResult, 0, 2);
2da1357c
VK
142
143 // Flags
5eba0220 144 if (DBGetFieldLong(hResult, 0, 3))
2da1357c 145 m_dwFlags |= NF_IS_SNMP;
5eba0220 146 if (DBGetFieldLong(hResult, 0, 4))
2da1357c 147 m_dwFlags |= NF_IS_NATIVE_AGENT;
5eba0220 148 if (DBGetFieldLong(hResult, 0, 5))
2da1357c 149 m_dwFlags |= NF_IS_BRIDGE;
5eba0220 150 if (DBGetFieldLong(hResult, 0, 6))
2da1357c 151 m_dwFlags |= NF_IS_ROUTER;
5eba0220
VK
152 if (DBGetFieldLong(hResult, 0, 7))
153 m_dwFlags |= NF_IS_OSPF;
ce19c304
VK
154 if (DBGetFieldLong(hResult, 0, 16))
155 m_dwFlags |= NF_IS_LOCAL_MGMT;
2da1357c
VK
156
157 m_iSNMPVersion = DBGetFieldLong(hResult, 0, 8);
158 m_dwDiscoveryFlags = DBGetFieldULong(hResult, 0, 9);
159 m_wAuthMethod = (WORD)DBGetFieldLong(hResult, 0, 10);
160 strncpy(m_szSharedSecret, DBGetField(hResult, 0, 11), MAX_SECRET_LENGTH);
161 m_wAgentPort = (WORD)DBGetFieldLong(hResult, 0, 12);
162 m_iStatusPollType = DBGetFieldLong(hResult, 0, 13);
163 strncpy(m_szCommunityString, DBGetField(hResult, 0, 14), MAX_COMMUNITY_LENGTH);
a0495b6e 164 strncpy(m_szObjectId, DBGetField(hResult, 0, 15), MAX_OID_LEN * 4);
cb151d1e 165 m_dwImageId = DBGetFieldULong(hResult, 0, 17);
333ece94 166 m_bIsDeleted = DBGetFieldLong(hResult, 0, 18);
18e26ff8
VK
167 m_pszDescription = _tcsdup(CHECK_NULL_EX(DBGetField(hResult, 0, 19)));
168 DecodeSQLString(m_pszDescription);
169 m_dwNodeType = DBGetFieldULong(hResult, 0, 20);
ae3a55d9
VK
170 _tcsncpy(m_szAgentVersion, CHECK_NULL_EX(DBGetField(hResult, 0, 21)), MAX_AGENT_VERSION_LEN);
171 DecodeSQLString(m_szAgentVersion);
d4c266b6
VK
172 _tcsncpy(m_szPlatformName, CHECK_NULL_EX(DBGetField(hResult, 0, 22)), MAX_PLATFORM_NAME_LEN);
173 DecodeSQLString(m_szPlatformName);
1a735d7c 174 m_dwPollerNode = DBGetFieldULong(hResult, 0, 23);
2da1357c
VK
175
176 DBFreeResult(hResult);
177
333ece94 178 if (!m_bIsDeleted)
2da1357c 179 {
333ece94
VK
180 // Link node to subnets
181 sprintf(szQuery, "SELECT subnet_id FROM nsmap WHERE node_id=%d", dwId);
182 hResult = DBSelect(g_hCoreDB, szQuery);
183 if (hResult == NULL)
184 return FALSE; // Query failed
2da1357c 185
333ece94 186 if (DBGetNumRows(hResult) == 0)
2da1357c 187 {
333ece94
VK
188 DBFreeResult(hResult);
189 return FALSE; // No parents - it shouldn't happen if database isn't corrupted
2da1357c 190 }
333ece94
VK
191
192 iNumRows = DBGetNumRows(hResult);
193 for(i = 0; i < iNumRows; i++)
2da1357c 194 {
333ece94
VK
195 dwSubnetId = DBGetFieldULong(hResult, i, 0);
196 pObject = FindObjectById(dwSubnetId);
197 if (pObject == NULL)
198 {
199 WriteLog(MSG_INVALID_SUBNET_ID, EVENTLOG_ERROR_TYPE, "dd", dwId, dwSubnetId);
200 break;
201 }
202 else if (pObject->Type() != OBJECT_SUBNET)
203 {
204 WriteLog(MSG_SUBNET_NOT_SUBNET, EVENTLOG_ERROR_TYPE, "dd", dwId, dwSubnetId);
205 break;
206 }
207 else
208 {
209 pObject->AddChild(this);
210 AddParent(pObject);
211 bResult = TRUE;
212 }
2da1357c 213 }
2da1357c 214
333ece94
VK
215 DBFreeResult(hResult);
216 LoadItemsFromDB();
217 LoadACLFromDB();
3ea35b38 218
333ece94
VK
219 // Walk through all items in the node and load appropriate thresholds
220 for(i = 0; i < (int)m_dwNumItems; i++)
221 if (!m_ppItems[i]->LoadThresholdsFromDB())
222 bResult = FALSE;
223 }
224 else
225 {
226 bResult = TRUE;
227 }
3ea35b38 228
cc140cce 229 return bResult;
2da1357c
VK
230}
231
232
eefe7d68
VK
233//
234// Save object to database
235//
236
237BOOL Node::SaveToDB(void)
238{
d4c266b6
VK
239 TCHAR *pszEscDescr, *pszEscVersion, *pszEscPlatform;
240 TCHAR szQuery[4096], szIpAddr[16];
eefe7d68
VK
241 DB_RESULT hResult;
242 BOOL bNewObject = TRUE;
3ea35b38 243 BOOL bResult;
eefe7d68
VK
244
245 // Lock object's access
246 Lock();
247
248 // Check for object's existence in database
249 sprintf(szQuery, "SELECT id FROM nodes WHERE id=%ld", m_dwId);
250 hResult = DBSelect(g_hCoreDB, szQuery);
251 if (hResult != 0)
252 {
253 if (DBGetNumRows(hResult) > 0)
254 bNewObject = FALSE;
255 DBFreeResult(hResult);
256 }
257
258 // Form and execute INSERT or UPDATE query
18e26ff8 259 pszEscDescr = EncodeSQLString(CHECK_NULL_EX(m_pszDescription));
ae3a55d9 260 pszEscVersion = EncodeSQLString(m_szAgentVersion);
d4c266b6 261 pszEscPlatform = EncodeSQLString(m_szPlatformName);
eefe7d68 262 if (bNewObject)
d4c266b6
VK
263 snprintf(szQuery, 4096,
264 "INSERT INTO nodes (id,name,status,is_deleted,primary_ip,"
265 "is_snmp,is_agent,is_bridge,is_router,snmp_version,community,"
266 "discovery_flags,status_poll_type,agent_port,auth_method,secret,"
267 "snmp_oid,is_local_mgmt,image_id,description,node_type,"
5eba0220 268 "agent_version,platform_name,poller_node_id,is_ospf)"
d4c266b6 269 " VALUES (%d,'%s',%d,%d,'%s',%d,%d,%d,%d,%d,'%s',%d,%d,%d,%d,"
5eba0220 270 "'%s','%s',%d,%ld,'%s',%ld,'%s','%s',%ld,%d)",
d4c266b6
VK
271 m_dwId, m_szName, m_iStatus, m_bIsDeleted,
272 IpToStr(m_dwIpAddr, szIpAddr),
273 m_dwFlags & NF_IS_SNMP ? 1 : 0,
274 m_dwFlags & NF_IS_NATIVE_AGENT ? 1 : 0,
275 m_dwFlags & NF_IS_BRIDGE ? 1 : 0,
276 m_dwFlags & NF_IS_ROUTER ? 1 : 0,
277 m_iSNMPVersion, m_szCommunityString, m_dwDiscoveryFlags, m_iStatusPollType,
278 m_wAgentPort,m_wAuthMethod,m_szSharedSecret, m_szObjectId,
279 m_dwFlags & NF_IS_LOCAL_MGMT ? 1 : 0, m_dwImageId,
5eba0220
VK
280 pszEscDescr, m_dwNodeType, pszEscVersion, pszEscPlatform,
281 m_dwPollerNode, m_dwFlags & NF_IS_OSPF ? 1 : 0);
eefe7d68 282 else
d4c266b6
VK
283 snprintf(szQuery, 4096,
284 "UPDATE nodes SET name='%s',status=%d,is_deleted=%d,primary_ip='%s',"
285 "is_snmp=%d,is_agent=%d,is_bridge=%d,is_router=%d,snmp_version=%d,"
286 "community='%s',discovery_flags=%d,status_poll_type=%d,agent_port=%d,"
287 "auth_method=%d,secret='%s',snmp_oid='%s',is_local_mgmt=%d,"
288 "image_id=%ld,description='%s',node_type=%ld,agent_version='%s',"
5eba0220 289 "platform_name='%s',poller_node_id=%ld,is_ospf=%d WHERE id=%ld",
d4c266b6
VK
290 m_szName, m_iStatus, m_bIsDeleted,
291 IpToStr(m_dwIpAddr, szIpAddr),
292 m_dwFlags & NF_IS_SNMP ? 1 : 0,
293 m_dwFlags & NF_IS_NATIVE_AGENT ? 1 : 0,
294 m_dwFlags & NF_IS_BRIDGE ? 1 : 0,
295 m_dwFlags & NF_IS_ROUTER ? 1 : 0,
296 m_iSNMPVersion, m_szCommunityString, m_dwDiscoveryFlags,
297 m_iStatusPollType, m_wAgentPort, m_wAuthMethod, m_szSharedSecret,
298 m_szObjectId, m_dwFlags & NF_IS_LOCAL_MGMT ? 1 : 0, m_dwImageId,
1a735d7c 299 pszEscDescr, m_dwNodeType, pszEscVersion, pszEscPlatform,
5eba0220 300 m_dwPollerNode, m_dwFlags & NF_IS_OSPF ? 1 : 0, m_dwId);
3ea35b38 301 bResult = DBQuery(g_hCoreDB, szQuery);
18e26ff8 302 free(pszEscDescr);
ae3a55d9 303 free(pszEscVersion);
d4c266b6 304 free(pszEscPlatform);
3ea35b38
VK
305
306 // Save data collection items
307 if (bResult)
308 {
309 DWORD i;
310
311 for(i = 0; i < m_dwNumItems; i++)
312 m_ppItems[i]->SaveToDB();
313 }
eefe7d68 314
de78f964
VK
315 // Save access list
316 SaveACLToDB();
317
eefe7d68
VK
318 // Clear modifications flag and unlock object
319 m_bIsModified = FALSE;
320 Unlock();
321
3ea35b38 322 return bResult;
eefe7d68
VK
323}
324
325
326//
327// Delete object from database
328//
329
330BOOL Node::DeleteFromDB(void)
331{
332 char szQuery[256];
ef44d5ea 333 BOOL bSuccess;
eefe7d68 334
b50f1100 335 bSuccess = Template::DeleteFromDB();
ef44d5ea
VK
336 if (bSuccess)
337 {
338 sprintf(szQuery, "DELETE FROM nodes WHERE id=%ld", m_dwId);
339 QueueSQLRequest(szQuery);
340 sprintf(szQuery, "DELETE FROM nsmap WHERE node_id=%ld", m_dwId);
341 QueueSQLRequest(szQuery);
342 sprintf(szQuery, "DROP TABLE idata_%ld", m_dwId);
343 QueueSQLRequest(szQuery);
344 }
345 return bSuccess;
eefe7d68 346}
469b937c
VK
347
348
349//
350// Poll newly discovered node
351// Usually called once by node poller thread when new node is discovered
352// and object for it is created
353//
354
1a4e3eff 355void Node::NewNodePoll(DWORD dwNetMask)
469b937c 356{
5811233f
VK
357 AgentConnection *pAgentConn;
358
be0a5a53
VK
359 PollerLock();
360
469b937c 361 // Determine node's capabilities
3d1cb7d6 362 if (SnmpGet(SNMP_VERSION_2C, m_dwIpAddr, m_szCommunityString, ".1.3.6.1.2.1.1.2.0", NULL, 0,
80de4676 363 m_szObjectId, MAX_OID_LEN * 4, FALSE, FALSE) == SNMP_ERR_SUCCESS)
18e26ff8
VK
364 {
365 DWORD dwNodeFlags;
366
367 m_dwNodeType = OidToType(m_szObjectId, &dwNodeFlags);
368 m_dwFlags |= NF_IS_SNMP | dwNodeFlags;
3d1cb7d6 369 m_iSNMPVersion = SNMP_VERSION_2C;
37c4d6aa
VK
370 }
371 else
372 {
373 if (SnmpGet(SNMP_VERSION_1, m_dwIpAddr, m_szCommunityString, ".1.3.6.1.2.1.1.2.0", NULL, 0,
80de4676 374 m_szObjectId, MAX_OID_LEN * 4, FALSE, FALSE) == SNMP_ERR_SUCCESS)
37c4d6aa
VK
375 {
376 DWORD dwNodeFlags;
377
378 m_dwNodeType = OidToType(m_szObjectId, &dwNodeFlags);
379 m_dwFlags |= NF_IS_SNMP | dwNodeFlags;
380 m_iSNMPVersion = SNMP_VERSION_1;
381 }
18e26ff8 382 }
469b937c 383
0ff9b273
VK
384 // Check OSPF capabilities
385 if (m_dwFlags & NF_IS_SNMP)
386 {
387 CheckOSPFSupport();
388 }
389
205acaf4 390 pAgentConn = new AgentConnection(htonl(m_dwIpAddr), m_wAgentPort, m_wAuthMethod,
a7b85168 391 m_szSharedSecret);
5811233f 392 if (pAgentConn->Connect())
ae3a55d9 393 {
5811233f 394 m_dwFlags |= NF_IS_NATIVE_AGENT;
ae3a55d9 395 pAgentConn->GetParameter("Agent.Version", MAX_AGENT_VERSION_LEN, m_szAgentVersion);
1c8b8363 396 pAgentConn->GetParameter("System.PlatformName", MAX_PLATFORM_NAME_LEN, m_szPlatformName);
89235715
VK
397
398 pAgentConn->GetSupportedParameters(&m_dwNumParams, &m_pParamList);
ae3a55d9 399 }
5811233f 400
469b937c 401 // Get interface list
a7b85168
VK
402 if ((m_dwFlags & NF_IS_SNMP) || (m_dwFlags & NF_IS_NATIVE_AGENT) ||
403 (m_dwFlags & NF_IS_LOCAL_MGMT))
469b937c 404 {
5811233f 405 INTERFACE_LIST *pIfList = NULL;
a0495b6e
VK
406 int i;
407
ce19c304
VK
408 if (m_dwFlags & NF_IS_LOCAL_MGMT) // For local machine
409 pIfList = GetLocalInterfaceList();
410 else if (m_dwFlags & NF_IS_NATIVE_AGENT) // For others prefer native agent
fd5aa295 411 {
5811233f 412 pIfList = pAgentConn->GetInterfaceList();
fd5aa295
VK
413 CleanInterfaceList(pIfList);
414 }
5811233f 415 if ((pIfList == NULL) && (m_dwFlags & NF_IS_SNMP)) // Use SNMP if we cannot get interfaces via agent
37c4d6aa 416 pIfList = SnmpGetInterfaceList(m_iSNMPVersion, m_dwIpAddr, m_szCommunityString, m_dwNodeType);
5811233f
VK
417
418 if (pIfList != NULL)
a0495b6e 419 {
5811233f 420 for(i = 0; i < pIfList->iNumEntries; i++)
323f8bec
VK
421 CreateNewInterface(pIfList->pInterfaces[i].dwIpAddr,
422 pIfList->pInterfaces[i].dwIpNetMask,
423 pIfList->pInterfaces[i].szName,
424 pIfList->pInterfaces[i].dwIndex,
b50f1100
VK
425 pIfList->pInterfaces[i].dwType,
426 pIfList->pInterfaces[i].bMacAddr);
5811233f 427 DestroyInterfaceList(pIfList);
a0495b6e 428 }
9437ca82
VK
429 else
430 {
431 // We cannot get interface list from node for some reasons, create dummy one
323f8bec 432 CreateNewInterface(m_dwIpAddr, dwNetMask);
9437ca82 433 }
469b937c
VK
434 }
435 else // No SNMP, no native agent - create pseudo interface object
436 {
323f8bec 437 CreateNewInterface(m_dwIpAddr, dwNetMask);
469b937c
VK
438 }
439
5811233f
VK
440 // Clean up agent connection
441 if (m_dwFlags & NF_IS_NATIVE_AGENT)
442 pAgentConn->Disconnect();
443 delete pAgentConn;
444
be0a5a53 445 PollerUnlock();
469b937c 446}
ce19c304
VK
447
448
449//
c8b1f788 450// Get ARP cache from node
ce19c304
VK
451//
452
c8b1f788 453ARP_CACHE *Node::GetArpCache(void)
ce19c304
VK
454{
455 ARP_CACHE *pArpCache = NULL;
456
457 if (m_dwFlags & NF_IS_LOCAL_MGMT)
458 {
459 pArpCache = GetLocalArpCache();
460 }
461 else if (m_dwFlags & NF_IS_NATIVE_AGENT)
462 {
3ea35b38 463 AgentLock();
1275c750
VK
464 if (ConnectToAgent())
465 pArpCache = m_pAgentConnection->GetArpCache();
3ea35b38 466 AgentUnlock();
ce19c304
VK
467 }
468 else if (m_dwFlags & NF_IS_SNMP)
469 {
37c4d6aa 470 pArpCache = SnmpGetArpCache(m_iSNMPVersion, m_dwIpAddr, m_szCommunityString);
ce19c304
VK
471 }
472
473 return pArpCache;
474}
475
476
477//
478// Get list of interfaces from node
479//
480
481INTERFACE_LIST *Node::GetInterfaceList(void)
482{
483 INTERFACE_LIST *pIfList = NULL;
484
485 if (m_dwFlags & NF_IS_LOCAL_MGMT)
486 {
487 pIfList = GetLocalInterfaceList();
488 }
489 else if (m_dwFlags & NF_IS_NATIVE_AGENT)
490 {
1c62be36
VK
491 AgentLock();
492 if (ConnectToAgent())
ce19c304 493 {
1c62be36 494 pIfList = m_pAgentConnection->GetInterfaceList();
fd5aa295 495 CleanInterfaceList(pIfList);
ce19c304 496 }
1c62be36 497 AgentUnlock();
ce19c304
VK
498 }
499 else if (m_dwFlags & NF_IS_SNMP)
500 {
37c4d6aa 501 pIfList = SnmpGetInterfaceList(m_iSNMPVersion, m_dwIpAddr, m_szCommunityString, m_dwNodeType);
ce19c304
VK
502 }
503
504 return pIfList;
505}
48b1c0ac
VK
506
507
508//
509// Find interface by index and node IP
510// Returns pointer to interface object or NULL if appropriate interface couldn't be found
511//
512
513Interface *Node::FindInterface(DWORD dwIndex, DWORD dwHostAddr)
514{
515 DWORD i;
516 Interface *pInterface;
517
c695e7e3 518 Lock();
48b1c0ac
VK
519 for(i = 0; i < m_dwChildCount; i++)
520 if (m_pChildList[i]->Type() == OBJECT_INTERFACE)
521 {
522 pInterface = (Interface *)m_pChildList[i];
523 if (pInterface->IfIndex() == dwIndex)
205acaf4 524 {
48b1c0ac
VK
525 if ((pInterface->IpAddr() & pInterface->IpNetMask()) ==
526 (dwHostAddr & pInterface->IpNetMask()))
c695e7e3
VK
527 {
528 Unlock();
48b1c0ac 529 return pInterface;
c695e7e3 530 }
205acaf4 531 }
48b1c0ac 532 }
c695e7e3 533 Unlock();
48b1c0ac
VK
534 return NULL;
535}
f00307b7
VK
536
537
323f8bec
VK
538//
539// Create new interface
540//
541
b50f1100
VK
542void Node::CreateNewInterface(DWORD dwIpAddr, DWORD dwNetMask, char *szName,
543 DWORD dwIndex, DWORD dwType, BYTE *pbMacAddr)
323f8bec
VK
544{
545 Interface *pInterface;
28fbe2be 546 Subnet *pSubnet = NULL;
323f8bec 547
c695e7e3
VK
548 // Find subnet to place interface object to
549 if (dwIpAddr != 0)
550 {
551 pSubnet = FindSubnetForNode(dwIpAddr);
552 if (pSubnet == NULL)
553 {
554 // Check if netmask is 0 (detect), and if yes, create
555 // new subnet with class mask
556 if (dwNetMask == 0)
557 {
205acaf4
VK
558 if (dwIpAddr < 0x80000000)
559 dwNetMask = 0xFF000000; // Class A
560 else if (dwIpAddr < 0xC0000000)
561 dwNetMask = 0xFFFF0000; // Class B
562 else if (dwIpAddr < 0xE0000000)
563 dwNetMask = 0xFFFFFF00; // Class C
c695e7e3
VK
564 else
565 {
28fbe2be
VK
566 TCHAR szBuffer[16];
567
c695e7e3
VK
568 // Multicast address??
569 DbgPrintf(AF_DEBUG_DISCOVERY,
570 "Attempt to create interface object with multicast address %s",
28fbe2be 571 IpToStr(dwIpAddr, szBuffer));
c695e7e3
VK
572 }
573 }
574
575 // Create new subnet object
205acaf4 576 if (dwIpAddr < 0xE0000000)
28fbe2be
VK
577 {
578 pSubnet = new Subnet(dwIpAddr & dwNetMask, dwNetMask);
579 NetObjInsert(pSubnet, TRUE);
580 g_pEntireNet->AddSubnet(pSubnet);
581 }
c695e7e3
VK
582 }
583 else
584 {
585 // Set correct netmask if we was asked for it
586 if (dwNetMask == 0)
587 {
588 dwNetMask = pSubnet->IpNetMask();
589 }
590 }
591 }
592
323f8bec
VK
593 // Create interface object
594 if (szName != NULL)
595 pInterface = new Interface(szName, dwIndex, dwIpAddr, dwNetMask, dwType);
596 else
597 pInterface = new Interface(dwIpAddr, dwNetMask);
b50f1100
VK
598 if (pbMacAddr != NULL)
599 pInterface->SetMacAddr(pbMacAddr);
323f8bec
VK
600
601 // Insert to objects' list and generate event
602 NetObjInsert(pInterface, TRUE);
603 AddInterface(pInterface);
604 PostEvent(EVENT_INTERFACE_ADDED, m_dwId, "dsaad", pInterface->Id(),
605 pInterface->Name(), pInterface->IpAddr(),
606 pInterface->IpNetMask(), pInterface->IfIndex());
607
608 // Bind node to appropriate subnet
28fbe2be 609 if (pSubnet != NULL)
323f8bec 610 {
323f8bec 611 pSubnet->AddNode(this);
28fbe2be
VK
612
613 // Check if subnet mask is correct on interface
614 if (pSubnet->IpNetMask() != dwNetMask)
615 PostEvent(EVENT_INCORRECT_NETMASK, m_dwId, "idsaa", pInterface->Id(),
616 pInterface->IfIndex(), pInterface->Name(),
617 pInterface->IpNetMask(), pSubnet->IpNetMask());
323f8bec
VK
618 }
619}
620
621
622//
623// Delete interface from node
624//
625
626void Node::DeleteInterface(Interface *pInterface)
627{
628 DWORD i;
629
630 // Check if we should unlink node from interface's subnet
631 if (pInterface->IpAddr() != 0)
632 {
633 for(i = 0; i < m_dwChildCount; i++)
634 if (m_pChildList[i]->Type() == OBJECT_INTERFACE)
635 if (m_pChildList[i] != pInterface)
636 if ((((Interface *)m_pChildList[i])->IpAddr() & ((Interface *)m_pChildList[i])->IpNetMask()) ==
637 (pInterface->IpAddr() & pInterface->IpNetMask()))
638 break;
639 if (i == m_dwChildCount)
640 {
641 // Last interface in subnet, should unlink node
642 Subnet *pSubnet = FindSubnetByIP(pInterface->IpAddr() & pInterface->IpNetMask());
3ea35b38 643 DeleteParent(pSubnet);
323f8bec 644 if (pSubnet != NULL)
3ea35b38 645 {
323f8bec 646 pSubnet->DeleteChild(this);
3ea35b38
VK
647 if ((pSubnet->IsEmpty()) && (g_dwFlags & AF_DELETE_EMPTY_SUBNETS))
648 {
649 PostEvent(EVENT_SUBNET_DELETED, pSubnet->Id(), NULL);
9a029be8 650 pSubnet->Delete(FALSE);
3ea35b38
VK
651 }
652 }
323f8bec
VK
653 }
654 }
9a029be8 655 pInterface->Delete(FALSE);
323f8bec
VK
656}
657
658
f00307b7
VK
659//
660// Calculate node status based on child objects status
661//
662
663void Node::CalculateCompoundStatus(void)
664{
665 int iOldStatus = m_iStatus;
666 static DWORD dwEventCodes[] = { EVENT_NODE_NORMAL, EVENT_NODE_MINOR,
667 EVENT_NODE_WARNING, EVENT_NODE_MAJOR, EVENT_NODE_CRITICAL,
668 EVENT_NODE_UNKNOWN, EVENT_NODE_UNMANAGED };
669
670 NetObj::CalculateCompoundStatus();
671 if (m_iStatus != iOldStatus)
672 PostEvent(dwEventCodes[m_iStatus], m_dwId, "d", iOldStatus);
673}
674
675
676//
677// Perform status poll on node
678//
679
d966d18a 680void Node::StatusPoll(ClientSession *pSession, DWORD dwRqId)
f00307b7
VK
681{
682 DWORD i;
1a735d7c 683 NetObj *pPollerNode = NULL;
f00307b7 684
323f8bec 685 PollerLock();
eb8b1960 686 m_pPollRequestor = pSession;
0ba90743 687 SendPollerMsg(dwRqId, _T("Starting status poll for node %s\r\n"), m_szName);
6c60ff91 688 Lock();
1a735d7c
VK
689
690 // Find service poller node object
691 if (m_dwPollerNode != 0)
692 {
693 pPollerNode = FindObjectById(m_dwPollerNode);
694 if (pPollerNode != NULL)
695 {
696 if (pPollerNode->Type() != OBJECT_NODE)
697 pPollerNode = NULL;
698 }
699 }
700
701 // If nothing found, use management server
702 if (pPollerNode == NULL)
703 {
704 pPollerNode = FindObjectById(g_dwMgmtNode);
705 if (pPollerNode != NULL)
706 pPollerNode->IncRefCount();
707 }
708 else
709 {
710 pPollerNode->IncRefCount();
711 }
712
f00307b7 713 for(i = 0; i < m_dwChildCount; i++)
6c60ff91
VK
714 if (m_pChildList[i]->Status() != STATUS_UNMANAGED)
715 {
716 switch(m_pChildList[i]->Type())
717 {
718 case OBJECT_INTERFACE:
719 ((Interface *)m_pChildList[i])->StatusPoll(pSession, dwRqId);
720 break;
721 case OBJECT_NETWORKSERVICE:
1a735d7c 722 ((NetworkService *)m_pChildList[i])->StatusPoll(pSession, dwRqId, (Node *)pPollerNode);
6c60ff91
VK
723 break;
724 default:
725 break;
726 }
727 }
1a735d7c
VK
728
729 if (pPollerNode != NULL)
730 pPollerNode->DecRefCount();
6c60ff91 731 Unlock();
1a735d7c 732
f00307b7
VK
733 CalculateCompoundStatus();
734 m_tLastStatusPoll = time(NULL);
d966d18a
VK
735 SendPollerMsg(dwRqId, "Finished status poll for node %s\r\n"
736 "Node status after poll is %s\r\n", m_szName, g_pszStatusName[m_iStatus]);
eb8b1960 737 m_pPollRequestor = NULL;
4e839863 738 m_dwDynamicFlags &= ~NDF_QUEUED_FOR_STATUS_POLL;
323f8bec 739 PollerUnlock();
f00307b7 740}
364aa19a
VK
741
742
743//
744// Perform configuration poll on node
745//
746
0ba90743 747void Node::ConfigurationPoll(ClientSession *pSession, DWORD dwRqId)
364aa19a
VK
748{
749 DWORD dwOldFlags = m_dwFlags;
750 AgentConnection *pAgentConn;
751 INTERFACE_LIST *pIfList;
6159a875 752 BOOL bHasChanges = FALSE;
364aa19a 753
323f8bec 754 PollerLock();
0ba90743 755 m_pPollRequestor = pSession;
a098be0b 756 SendPollerMsg(dwRqId, _T("Starting configuration poll for node %s\r\n"), m_szName);
b1dd534d 757 DbgPrintf(AF_DEBUG_DISCOVERY, "Starting configuration poll for node %s (ID: %d)", m_szName, m_dwId);
323f8bec 758
364aa19a 759 // Check node's capabilities
0ba90743 760 SendPollerMsg(dwRqId, _T("Checking node's capabilities...\r\n"));
498ccc60
VK
761 if (SnmpGet(m_iSNMPVersion, m_dwIpAddr, m_szCommunityString, ".1.3.6.1.2.1.1.2.0", NULL, 0,
762 m_szObjectId, MAX_OID_LEN * 4, FALSE, FALSE) == SNMP_ERR_SUCCESS)
364aa19a 763 {
18e26ff8
VK
764 DWORD dwNodeFlags, dwNodeType;
765
364aa19a
VK
766 m_dwFlags |= NF_IS_SNMP;
767 m_iSnmpAgentFails = 0;
0ba90743 768 SendPollerMsg(dwRqId, _T(" SNMP agent is active\r\n"));
18e26ff8
VK
769
770 // Check node type
771 dwNodeType = OidToType(m_szObjectId, &dwNodeFlags);
772 if (m_dwNodeType != dwNodeType)
773 {
774 m_dwFlags |= dwNodeFlags;
775 m_dwNodeType = dwNodeType;
776 SendPollerMsg(dwRqId, _T(" Node type has been changed to %d\r\n"), m_dwNodeType);
777 }
0ff9b273
VK
778
779 CheckOSPFSupport();
364aa19a
VK
780 }
781 else
782 {
4ea67c99
VK
783 if (m_dwFlags & NF_IS_SNMP)
784 {
785 if (m_iSnmpAgentFails == 0)
786 PostEvent(EVENT_SNMP_FAIL, m_dwId, NULL);
787 m_iSnmpAgentFails++;
788 }
0ba90743 789 SendPollerMsg(dwRqId, _T(" SNMP agent is not responding\r\n"));
364aa19a
VK
790 }
791
205acaf4 792 pAgentConn = new AgentConnection(htonl(m_dwIpAddr), m_wAgentPort, m_wAuthMethod, m_szSharedSecret);
364aa19a
VK
793 if (pAgentConn->Connect())
794 {
795 m_dwFlags |= NF_IS_NATIVE_AGENT;
796 m_iNativeAgentFails = 0;
89235715
VK
797
798 Lock();
ae3a55d9 799 pAgentConn->GetParameter("Agent.Version", MAX_AGENT_VERSION_LEN, m_szAgentVersion);
1c8b8363 800 pAgentConn->GetParameter("System.PlatformName", MAX_PLATFORM_NAME_LEN, m_szPlatformName);
89235715
VK
801
802 safe_free(m_pParamList);
803 pAgentConn->GetSupportedParameters(&m_dwNumParams, &m_pParamList);
804
805 Unlock();
f91fa4c2 806 pAgentConn->Disconnect();
0ba90743 807 SendPollerMsg(dwRqId, _T(" NetXMS native agent is active\r\n"));
364aa19a
VK
808 }
809 else
810 {
4ea67c99
VK
811 if (m_dwFlags & NF_IS_NATIVE_AGENT)
812 {
813 if (m_iNativeAgentFails == 0)
814 PostEvent(EVENT_AGENT_FAIL, m_dwId, NULL);
815 m_iNativeAgentFails++;
816 }
0ba90743 817 SendPollerMsg(dwRqId, _T(" NetXMS native agent is not responding\r\n"));
364aa19a 818 }
f91fa4c2 819 delete pAgentConn;
364aa19a
VK
820
821 // Generate event if node flags has been changed
822 if (dwOldFlags != m_dwFlags)
6159a875 823 {
364aa19a 824 PostEvent(EVENT_NODE_FLAGS_CHANGED, m_dwId, "xx", dwOldFlags, m_dwFlags);
6159a875
VK
825 bHasChanges = TRUE;
826 }
364aa19a
VK
827
828 // Retrieve interface list
0ba90743
VK
829 SendPollerMsg(dwRqId, _T("Capability check finished\r\n"
830 "Checking interface configuration...\r\n"));
364aa19a
VK
831 pIfList = GetInterfaceList();
832 if (pIfList != NULL)
833 {
834 DWORD i;
323f8bec 835 int j;
364aa19a
VK
836
837 // Find non-existing interfaces
838 for(i = 0; i < m_dwChildCount; i++)
839 if (m_pChildList[i]->Type() == OBJECT_INTERFACE)
840 {
841 Interface *pInterface = (Interface *)m_pChildList[i];
364aa19a
VK
842
843 for(j = 0; j < pIfList->iNumEntries; j++)
844 if ((pIfList->pInterfaces[j].dwIndex == pInterface->IfIndex()) &&
845 (pIfList->pInterfaces[j].dwIpAddr == pInterface->IpAddr()) &&
846 (pIfList->pInterfaces[j].dwIpNetMask == pInterface->IpNetMask()))
847 break;
848 if (j == pIfList->iNumEntries)
849 {
850 // No such interface in current configuration, delete it
0ba90743
VK
851 SendPollerMsg(dwRqId, _T(" Interface \"%s\" is no longer exist\r\n"),
852 pInterface->Name());
364aa19a
VK
853 PostEvent(EVENT_INTERFACE_DELETED, m_dwId, "dsaa", pInterface->IfIndex(),
854 pInterface->Name(), pInterface->IpAddr(), pInterface->IpNetMask());
323f8bec 855 DeleteInterface(pInterface);
4e839863 856 i = 0xFFFFFFFF; // Restart loop
6159a875 857 bHasChanges = TRUE;
364aa19a
VK
858 }
859 }
860
b50f1100 861 // Add new interfaces and check configuration of existing
323f8bec
VK
862 for(j = 0; j < pIfList->iNumEntries; j++)
863 {
864 for(i = 0; i < m_dwChildCount; i++)
865 if (m_pChildList[i]->Type() == OBJECT_INTERFACE)
866 {
867 Interface *pInterface = (Interface *)m_pChildList[i];
868
869 if ((pIfList->pInterfaces[j].dwIndex == pInterface->IfIndex()) &&
870 (pIfList->pInterfaces[j].dwIpAddr == pInterface->IpAddr()) &&
871 (pIfList->pInterfaces[j].dwIpNetMask == pInterface->IpNetMask()))
b50f1100
VK
872 {
873 // Existing interface, check configuration
874 if (memcmp(pIfList->pInterfaces[j].bMacAddr, pInterface->MacAddr(), MAC_ADDR_LENGTH))
875 {
876 char szOldMac[16], szNewMac[16];
877
878 BinToStr((BYTE *)pInterface->MacAddr(), MAC_ADDR_LENGTH, szOldMac);
879 BinToStr(pIfList->pInterfaces[j].bMacAddr, MAC_ADDR_LENGTH, szNewMac);
28fbe2be 880 PostEvent(EVENT_MAC_ADDR_CHANGED, m_dwId, "idsss",
b50f1100
VK
881 pInterface->Id(), pInterface->IfIndex(),
882 pInterface->Name(), szOldMac, szNewMac);
883 pInterface->SetMacAddr(pIfList->pInterfaces[j].bMacAddr);
884 }
323f8bec 885 break;
b50f1100 886 }
323f8bec
VK
887 }
888 if (i == m_dwChildCount)
889 {
890 // New interface
0ba90743
VK
891 SendPollerMsg(dwRqId, _T(" Found new interface \"%s\"\r\n"),
892 pIfList->pInterfaces[j].szName);
323f8bec
VK
893 CreateNewInterface(pIfList->pInterfaces[j].dwIpAddr,
894 pIfList->pInterfaces[j].dwIpNetMask,
895 pIfList->pInterfaces[j].szName,
896 pIfList->pInterfaces[j].dwIndex,
b50f1100
VK
897 pIfList->pInterfaces[j].dwType,
898 pIfList->pInterfaces[j].bMacAddr);
6159a875 899 bHasChanges = TRUE;
323f8bec
VK
900 }
901 }
e0d3b217
VK
902
903 DestroyInterfaceList(pIfList);
364aa19a 904 }
e7b47627
VK
905 else
906 {
907 SendPollerMsg(dwRqId, _T(" Unable to get interface list from node\r\n"));
908 }
323f8bec 909
8bff53f6 910 m_tLastConfigurationPoll = time(NULL);
0ba90743
VK
911 SendPollerMsg(dwRqId, _T("Interface configuration check finished\r\n"
912 "Finished configuration poll for node %s\r\n"
913 "Node configuration was%schanged after poll\r\n"),
914 m_szName, bHasChanges ? _T(" ") : _T(" not "));
89235715
VK
915
916 // Finish configuration poll
4e839863 917 m_dwDynamicFlags &= ~NDF_QUEUED_FOR_CONFIG_POLL;
323f8bec 918 PollerUnlock();
b1dd534d 919 DbgPrintf(AF_DEBUG_DISCOVERY, "Finished configuration poll for node %s (ID: %d)", m_szName, m_dwId);
6159a875
VK
920
921 if (bHasChanges)
922 {
923 Lock();
924 Modify();
925 Unlock();
926 }
364aa19a 927}
6f595ce2
VK
928
929
1275c750
VK
930//
931// Connect to native agent
932//
933
934BOOL Node::ConnectToAgent(void)
935{
936 // Create new agent connection object if needed
937 if (m_pAgentConnection == NULL)
205acaf4 938 m_pAgentConnection = new AgentConnection(htonl(m_dwIpAddr), m_wAgentPort, m_wAuthMethod, m_szSharedSecret);
1275c750
VK
939
940 // Check if we already connected
941 if (m_pAgentConnection->Nop() == ERR_SUCCESS)
942 return TRUE;
943
944 // Close current connection or clean up after broken connection
945 m_pAgentConnection->Disconnect();
946 return m_pAgentConnection->Connect();
947}
948
949
950//
951// Get item's value via SNMP
952//
953
3ea35b38 954DWORD Node::GetItemFromSNMP(const char *szParam, DWORD dwBufSize, char *szBuffer)
1275c750 955{
80de4676
VK
956 DWORD dwResult;
957
958 dwResult = SnmpGet(m_iSNMPVersion, m_dwIpAddr, m_szCommunityString, szParam, NULL, 0,
959 szBuffer, dwBufSize, FALSE, TRUE);
960 return (dwResult == SNMP_ERR_SUCCESS) ? DCE_SUCCESS :
961 ((dwResult == SNMP_ERR_NO_OBJECT) ? DCE_NOT_SUPPORTED : DCE_COMM_ERROR);
1275c750
VK
962}
963
964
965//
966// Get item's value via native agent
967//
968
3ea35b38 969DWORD Node::GetItemFromAgent(const char *szParam, DWORD dwBufSize, char *szBuffer)
1275c750 970{
3ea35b38 971 DWORD dwError, dwResult = DCE_COMM_ERROR;
1275c750
VK
972 DWORD dwTries = 5;
973
3ea35b38
VK
974 AgentLock();
975
1275c750
VK
976 // Establish connection if needed
977 if (m_pAgentConnection == NULL)
978 if (!ConnectToAgent())
3ea35b38 979 goto end_loop;
1275c750
VK
980
981 // Get parameter from agent
982 while(dwTries-- > 0)
983 {
901c96c7 984 dwError = m_pAgentConnection->GetParameter((char *)szParam, dwBufSize, szBuffer);
1275c750
VK
985 switch(dwError)
986 {
987 case ERR_SUCCESS:
3ea35b38
VK
988 dwResult = DCE_SUCCESS;
989 goto end_loop;
1275c750 990 case ERR_UNKNOWN_PARAMETER:
3ea35b38
VK
991 dwResult = DCE_NOT_SUPPORTED;
992 goto end_loop;
1275c750
VK
993 case ERR_NOT_CONNECTED:
994 case ERR_CONNECTION_BROKEN:
995 if (!ConnectToAgent())
3ea35b38 996 goto end_loop;
1275c750
VK
997 break;
998 case ERR_REQUEST_TIMEOUT:
999 break;
1000 }
1001 }
3ea35b38
VK
1002
1003end_loop:
1004 AgentUnlock();
1005 return dwResult;
1275c750 1006}
8e99117a
VK
1007
1008
1009//
1010// Get value for server's internal parameter
1011//
1012
3ea35b38 1013DWORD Node::GetInternalItem(const char *szParam, DWORD dwBufSize, char *szBuffer)
8e99117a
VK
1014{
1015 DWORD dwError = DCE_SUCCESS;
1016
1017 if (!stricmp(szParam, "status"))
1018 {
1019 sprintf(szBuffer, "%d", m_iStatus);
1020 }
0fd7132e
VK
1021 else if (m_dwFlags & NF_IS_LOCAL_MGMT)
1022 {
1023 if (!stricmp(szParam, "Server.AverageDCPollerQueueSize"))
1024 {
1025 sprintf(szBuffer, "%f", g_dAvgPollerQueueSize);
1026 }
1027 else if (!stricmp(szParam, "Server.AverageDBWriterQueueSize"))
1028 {
1029 sprintf(szBuffer, "%f", g_dAvgDBWriterQueueSize);
1030 }
4e839863
VK
1031 else if (!stricmp(szParam, "Server.AverageStatusPollerQueueSize"))
1032 {
1033 sprintf(szBuffer, "%f", g_dAvgStatusPollerQueueSize);
1034 }
1035 else if (!stricmp(szParam, "Server.AverageConfigurationPollerQueueSize"))
1036 {
1037 sprintf(szBuffer, "%f", g_dAvgConfigPollerQueueSize);
1038 }
1039 else if (!stricmp(szParam, "Server.AverageDCIQueuingTime"))
1040 {
1041 sprintf(szBuffer, "%lu", g_dwAvgDCIQueuingTime);
1042 }
0fd7132e
VK
1043 else
1044 {
1045 dwError = DCE_NOT_SUPPORTED;
1046 }
1047 }
8e99117a
VK
1048 else
1049 {
1050 dwError = DCE_NOT_SUPPORTED;
1051 }
1052
1053 return dwError;
1054}
129f8f7b
VK
1055
1056
80de4676
VK
1057//
1058// Get item's value for client
1059//
1060
1061DWORD Node::GetItemForClient(int iOrigin, const char *pszParam, char *pszBuffer, DWORD dwBufSize)
1062{
1063 DWORD dwResult = 0, dwRetCode;
1064
1065 // Get data from node
1066 switch(iOrigin)
1067 {
1068 case DS_INTERNAL:
1069 dwRetCode = GetInternalItem(pszParam, dwBufSize, pszBuffer);
1070 break;
1071 case DS_NATIVE_AGENT:
1072 dwRetCode = GetItemFromAgent(pszParam, dwBufSize, pszBuffer);
1073 break;
1074 case DS_SNMP_AGENT:
1075 dwRetCode = GetItemFromSNMP(pszParam, dwBufSize, pszBuffer);
1076 break;
1077 default:
1078 dwResult = RCC_INVALID_ARGUMENT;
1079 break;
1080 }
1081
1082 // Translate return code to RCC
1083 if (dwResult != RCC_INVALID_ARGUMENT)
1084 {
1085 switch(dwRetCode)
1086 {
1087 case DCE_SUCCESS:
1088 dwResult = RCC_SUCCESS;
1089 break;
1090 case DCE_COMM_ERROR:
1091 dwResult = RCC_COMM_FAILURE;
1092 break;
1093 case DCE_NOT_SUPPORTED:
1094 dwResult = RCC_DCI_NOT_SUPPORTED;
1095 break;
1096 default:
1097 dwResult = RCC_SYSTEM_FAILURE;
1098 break;
1099 }
1100 }
1101
1102 return dwResult;
1103}
1104
1105
129f8f7b
VK
1106//
1107// Put items which requires polling into the queue
1108//
1109
1110void Node::QueueItemsForPolling(Queue *pPollerQueue)
1111{
1112 DWORD i;
1113 time_t currTime;
1114
1115 currTime = time(NULL);
1116
1117 Lock();
1118 for(i = 0; i < m_dwNumItems; i++)
1119 {
3ea35b38 1120 if (m_ppItems[i]->ReadyForPolling(currTime))
129f8f7b 1121 {
3ea35b38 1122 m_ppItems[i]->SetBusyFlag(TRUE);
4e839863 1123 m_dwRefCount++; // Increment reference count for each queued DCI
5add75d8 1124 pPollerQueue->Put(m_ppItems[i]);
067f2689
VK
1125 }
1126 }
1127 Unlock();
1128}
1129
1130
b81249b7
VK
1131//
1132// Create CSCP message with object's data
1133//
1134
1135void Node::CreateMessage(CSCPMessage *pMsg)
1136{
70573ffe 1137 Template::CreateMessage(pMsg);
a5f8dbb8
VK
1138 pMsg->SetVariable(VID_FLAGS, m_dwFlags);
1139 pMsg->SetVariable(VID_DISCOVERY_FLAGS, m_dwDiscoveryFlags);
1140 pMsg->SetVariable(VID_AGENT_PORT, m_wAgentPort);
1141 pMsg->SetVariable(VID_AUTH_METHOD, m_wAuthMethod);
1142 pMsg->SetVariable(VID_SHARED_SECRET, m_szSharedSecret);
1143 pMsg->SetVariable(VID_COMMUNITY_STRING, m_szCommunityString);
1144 pMsg->SetVariable(VID_SNMP_OID, m_szObjectId);
18e26ff8 1145 pMsg->SetVariable(VID_NODE_TYPE, m_dwNodeType);
37c4d6aa 1146 pMsg->SetVariable(VID_SNMP_VERSION, (WORD)m_iSNMPVersion);
ae3a55d9 1147 pMsg->SetVariable(VID_AGENT_VERSION, m_szAgentVersion);
1c8b8363 1148 pMsg->SetVariable(VID_PLATFORM_NAME, m_szPlatformName);
1a735d7c 1149 pMsg->SetVariable(VID_POLLER_NODE_ID, m_dwPollerNode);
b81249b7 1150}
24156e90
VK
1151
1152
1153//
1154// Modify object from message
1155//
1156
1157DWORD Node::ModifyFromMessage(CSCPMessage *pRequest, BOOL bAlreadyLocked)
1158{
1159 if (!bAlreadyLocked)
1160 Lock();
1161
6c60ff91
VK
1162 // Change primary IP address
1163 if (pRequest->IsVariableExist(VID_IP_ADDRESS))
1164 {
1165 DWORD i, dwIpAddr;
1166
1167 dwIpAddr = pRequest->GetVariableLong(VID_IP_ADDRESS);
1168
1169 // Check if received IP address is one of node's interface addresses
1170 for(i = 0; i < m_dwChildCount; i++)
1171 if ((m_pChildList[i]->Type() == OBJECT_INTERFACE) &&
1172 (m_pChildList[i]->IpAddr() == dwIpAddr))
1173 break;
1174 if (i == m_dwChildCount)
1175 {
1176 Unlock();
1177 return RCC_INVALID_IP_ADDR;
1178 }
1179
1180 m_dwIpAddr = dwIpAddr;
1181 }
1182
1a735d7c
VK
1183 // Poller node ID
1184 if (pRequest->IsVariableExist(VID_POLLER_NODE_ID))
1185 {
1186 DWORD dwNodeId;
1187 NetObj *pObject;
1188
1189 dwNodeId = pRequest->GetVariableLong(VID_POLLER_NODE_ID);
1190 pObject = FindObjectById(dwNodeId);
1191
1192 // Check if received id is a valid node id
1193 if (pObject == NULL)
1194 {
1195 Unlock();
1196 return RCC_INVALID_OBJECT_ID;
1197 }
1198 if (pObject->Type() != OBJECT_NODE)
1199 {
1200 Unlock();
1201 return RCC_INVALID_OBJECT_ID;
1202 }
1203
1204 m_dwPollerNode = dwNodeId;
1205 }
1206
24156e90
VK
1207 // Change listen port of native agent
1208 if (pRequest->IsVariableExist(VID_AGENT_PORT))
1209 m_wAgentPort = pRequest->GetVariableShort(VID_AGENT_PORT);
1210
1211 // Change authentication method of native agent
1212 if (pRequest->IsVariableExist(VID_AUTH_METHOD))
1213 m_wAuthMethod = pRequest->GetVariableShort(VID_AUTH_METHOD);
1214
1215 // Change shared secret of native agent
1216 if (pRequest->IsVariableExist(VID_SHARED_SECRET))
1217 pRequest->GetVariableStr(VID_SHARED_SECRET, m_szSharedSecret, MAX_SECRET_LENGTH);
1218
37c4d6aa
VK
1219 // Change SNMP protocol version
1220 if (pRequest->IsVariableExist(VID_SNMP_VERSION))
1221 m_iSNMPVersion = pRequest->GetVariableShort(VID_SNMP_VERSION);
1222
24156e90
VK
1223 // Change SNMP community string
1224 if (pRequest->IsVariableExist(VID_COMMUNITY_STRING))
1225 pRequest->GetVariableStr(VID_COMMUNITY_STRING, m_szCommunityString, MAX_COMMUNITY_LENGTH);
1226
70573ffe 1227 return Template::ModifyFromMessage(pRequest, TRUE);
24156e90 1228}
ed1140dc
VK
1229
1230
1231//
1232// Wakeup node using magic packet
1233//
1234
1235DWORD Node::WakeUp(void)
1236{
1237 DWORD i, dwResult = RCC_NO_WOL_INTERFACES;
1238
1239 Lock();
1240
1241 for(i = 0; i < m_dwChildCount; i++)
1242 if ((m_pChildList[i]->Type() == OBJECT_INTERFACE) &&
1243 (m_pChildList[i]->Status() != STATUS_UNMANAGED) &&
1244 (m_pChildList[i]->IpAddr() != 0))
1245 {
1246 dwResult = ((Interface *)m_pChildList[i])->WakeUp();
1247 break;
1248 }
1249
1250 Unlock();
1251 return dwResult;
1252}
80de4676
VK
1253
1254
1255//
1256// Get status of interface with given index from SNMP agent
1257//
1258
1259int Node::GetInterfaceStatusFromSNMP(DWORD dwIndex)
1260{
1261 return SnmpGetInterfaceStatus(m_dwIpAddr, m_iSNMPVersion, m_szCommunityString, dwIndex);
1262}
1263
1264
1265//
1266// Get status of interface with given index from native agent
1267//
1268
1269int Node::GetInterfaceStatusFromAgent(DWORD dwIndex)
1270{
1271 char szParam[128], szBuffer[32];
1272 DWORD dwAdminStatus, dwLinkState;
1273 int iStatus;
1274
1275 // Get administrative status
1276 sprintf(szParam, "Net.Interface.AdminStatus(%lu)", dwIndex);
1277 if (GetItemFromAgent(szParam, 32, szBuffer) == DCE_SUCCESS)
1278 {
1279 dwAdminStatus = strtoul(szBuffer, NULL, 0);
1280
1281 switch(dwAdminStatus)
1282 {
1283 case 3:
1284 iStatus = STATUS_TESTING;
1285 break;
1286 case 2:
1287 iStatus = STATUS_DISABLED;
1288 break;
1289 case 1: // Interface administratively up, check link state
1290 sprintf(szParam, "Net.Interface.Link(%lu)", dwIndex);
1291 if (GetItemFromAgent(szParam, 32, szBuffer) == DCE_SUCCESS)
1292 {
1293 dwLinkState = strtoul(szBuffer, NULL, 0);
1294 iStatus = (dwLinkState == 0) ? STATUS_CRITICAL : STATUS_NORMAL;
1295 }
1296 else
1297 {
1298 iStatus = STATUS_UNKNOWN;
1299 }
1300 default:
1301 iStatus = STATUS_UNKNOWN;
1302 break;
1303 }
1304 }
1305 else
1306 {
1307 iStatus = STATUS_UNKNOWN;
1308 }
1309
1310 return iStatus;
1311}
89235715
VK
1312
1313
1314//
1315// Put list of supported parameters into CSCP message
1316//
1317
1318void Node::WriteParamListToMessage(CSCPMessage *pMsg)
1319{
1320 DWORD i, dwId;
1321
1322 Lock();
1323 if (m_pParamList != NULL)
1324 {
1325 pMsg->SetVariable(VID_NUM_PARAMETERS, m_dwNumParams);
1326 for(i = 0, dwId = VID_PARAM_LIST_BASE; i < m_dwNumParams; i++)
1327 {
1328 pMsg->SetVariable(dwId++, m_pParamList[i].szName);
1329 pMsg->SetVariable(dwId++, m_pParamList[i].szDescription);
1330 pMsg->SetVariable(dwId++, (WORD)m_pParamList[i].iDataType);
1331 }
1332 }
1333 else
1334 {
1335 pMsg->SetVariable(VID_NUM_PARAMETERS, (DWORD)0);
1336 }
1337 Unlock();
1338}
1a735d7c
VK
1339
1340
1341//
1342// Check status of network service
1343//
1344
1345DWORD Node::CheckNetworkService(DWORD *pdwStatus, DWORD dwIpAddr, int iServiceType,
1346 WORD wPort, WORD wProto, TCHAR *pszRequest,
1347 TCHAR *pszResponce)
1348{
5eba0220 1349 DWORD dwError = ERR_NOT_CONNECTED;
1a735d7c 1350 DWORD dwTries = 3;
5eba0220 1351 AgentConnection conn(htonl(m_dwIpAddr), m_wAgentPort, m_wAuthMethod, m_szSharedSecret);
1a735d7c 1352
5eba0220
VK
1353 // Establish connection with agent
1354 if (conn.Connect())
1a735d7c 1355 {
5eba0220
VK
1356 dwError = conn.CheckNetworkService(pdwStatus, dwIpAddr, iServiceType,
1357 wPort, wProto, pszRequest, pszResponce);
1358 conn.Disconnect();
1a735d7c 1359 }
1a735d7c
VK
1360 return dwError;
1361}
9a029be8
VK
1362
1363
1364//
1365// Handler for object deletion
1366//
1367
1368void Node::OnObjectDelete(DWORD dwObjectId)
1369{
1370 Lock();
1371 if (dwObjectId == m_dwPollerNode)
1372 {
1373 // If deleted object is our poller node, change it to default
1374 m_dwPollerNode = 0;
1375 Modify();
1376 DbgPrintf(AF_DEBUG_MISC, _T("Node \"%s\": poller node %ld deleted"), m_szName, dwObjectId);
1377 }
1378 Unlock();
1379}
0ff9b273
VK
1380
1381
1382//
1383// Check node for OSPF support
1384//
1385
1386void Node::CheckOSPFSupport(void)
1387{
1388 long nAdminStatus;
1389
1390 if (SnmpGet(m_iSNMPVersion, m_dwIpAddr, m_szCommunityString, ".1.3.6.1.2.1.14.1.2.0",
1391 NULL, 0, &nAdminStatus, sizeof(long), FALSE, FALSE) == SNMP_ERR_SUCCESS)
1392 {
1393 if (nAdminStatus)
1394 {
1395 m_dwFlags |= NF_IS_OSPF;
1396 }
1397 else
1398 {
1399 m_dwFlags &= ~NF_IS_OSPF;
1400 }
1401 }
1402}