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