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