2 ** NetXMS - Network Management System
3 ** Copyright (C) 2003-2016 Victor Kirhenshtein
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.
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.
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.
28 extern UINT64 g_syslogMessagesReceived
;
29 extern UINT64 g_snmpTrapsReceived
;
32 * Node class default constructor
34 Node::Node() : DataCollectionTarget()
37 m_status
= STATUS_UNKNOWN
;
38 m_type
= NODE_TYPE_UNKNOWN
;
42 m_agentPort
= AGENT_LISTEN_PORT
;
43 m_agentAuthMethod
= AUTH_NONE
;
44 m_agentCacheMode
= AGENT_CACHE_DEFAULT
;
45 m_szSharedSecret
[0] = 0;
46 m_iStatusPollType
= POLL_ICMP_PING
;
47 m_snmpVersion
= SNMP_VERSION_1
;
48 m_snmpPort
= SNMP_DEFAULT_PORT
;
49 m_snmpSecurity
= new SNMP_SecurityContext("public");
51 m_lastDiscoveryPoll
= 0;
53 m_lastConfigurationPoll
= 0;
54 m_lastInstancePoll
= 0;
55 m_lastTopologyPoll
= 0;
60 m_hPollerMutex
= MutexCreate();
61 m_hAgentAccessMutex
= MutexCreate();
62 m_hSmclpAccessMutex
= MutexCreate();
63 m_mutexRTAccess
= MutexCreate();
64 m_mutexTopoAccess
= MutexCreate();
65 m_snmpProxyConnectionLock
= MutexCreate();
66 m_agentConnection
= NULL
;
67 m_snmpProxyConnection
= NULL
;
68 m_smclpConnection
= NULL
;
69 m_lastAgentTrapId
= 0;
71 m_lastAgentPushRequestId
= 0;
72 m_szAgentVersion
[0] = 0;
73 m_szPlatformName
[0] = 0;
74 m_sysDescription
= NULL
;
79 m_lldpLocalPortInfo
= NULL
;
86 memset(m_qwLastEvents
, 0, sizeof(QWORD
) * MAX_LAST_EVENTS
);
87 m_pRoutingTable
= NULL
;
90 m_lastAgentCommTime
= 0;
91 m_lastAgentConnectAttempt
= 0;
92 m_linkLayerNeighbors
= NULL
;
95 m_topologyRebuildTimestamp
= 0;
96 m_iPendingStatus
= -1;
98 m_iRequiredPollCount
= 0; // Use system default
99 m_nUseIfXTable
= IFXTABLE_DEFAULT
; // Use system default
100 m_jobQueue
= new ServerJobQueue();
103 m_wirelessStations
= NULL
;
104 m_adoptedApCount
= 0;
109 m_softwarePackages
= NULL
;
110 m_winPerfObjects
= NULL
;
111 memset(m_baseBridgeAddress
, 0, MAC_ADDR_LENGTH
);
112 m_fileUpdateConn
= NULL
;
117 m_syslogMessageCount
= 0;
120 m_sshPassword
[0] = 0;
125 * Constructor for new node object
127 Node::Node(const InetAddress
& addr
, UINT32 dwFlags
, UINT32 agentProxy
, UINT32 snmpProxy
, UINT32 icmpProxy
, UINT32 sshProxy
, UINT32 zoneId
) : DataCollectionTarget()
129 addr
.toString(m_primaryName
);
130 m_status
= STATUS_UNKNOWN
;
131 m_type
= NODE_TYPE_UNKNOWN
;
135 m_dwDynamicFlags
= 0;
137 m_agentPort
= AGENT_LISTEN_PORT
;
138 m_agentAuthMethod
= AUTH_NONE
;
139 m_agentCacheMode
= AGENT_CACHE_DEFAULT
;
140 m_szSharedSecret
[0] = 0;
141 m_iStatusPollType
= POLL_ICMP_PING
;
142 m_snmpVersion
= SNMP_VERSION_1
;
143 m_snmpPort
= SNMP_DEFAULT_PORT
;
144 m_snmpSecurity
= new SNMP_SecurityContext("public");
145 addr
.toString(m_name
); // Make default name from IP address
147 m_lastDiscoveryPoll
= 0;
148 m_lastStatusPoll
= 0;
149 m_lastConfigurationPoll
= 0;
150 m_lastInstancePoll
= 0;
151 m_lastTopologyPoll
= 0;
156 m_hPollerMutex
= MutexCreate();
157 m_hAgentAccessMutex
= MutexCreate();
158 m_hSmclpAccessMutex
= MutexCreate();
159 m_mutexRTAccess
= MutexCreate();
160 m_mutexTopoAccess
= MutexCreate();
161 m_snmpProxyConnectionLock
= MutexCreate();
162 m_agentConnection
= NULL
;
163 m_snmpProxyConnection
= NULL
;
164 m_smclpConnection
= NULL
;
165 m_lastAgentTrapId
= 0;
166 m_lastSNMPTrapId
= 0;
167 m_lastAgentPushRequestId
= 0;
168 m_szAgentVersion
[0] = 0;
169 m_szPlatformName
[0] = 0;
170 m_sysDescription
= NULL
;
173 m_sysLocation
= NULL
;
175 m_lldpLocalPortInfo
= NULL
;
179 m_agentProxy
= agentProxy
;
180 m_snmpProxy
= snmpProxy
;
181 m_icmpProxy
= icmpProxy
;
182 memset(m_qwLastEvents
, 0, sizeof(QWORD
) * MAX_LAST_EVENTS
);
184 m_pRoutingTable
= NULL
;
187 m_lastAgentCommTime
= 0;
188 m_lastAgentConnectAttempt
= 0;
189 m_linkLayerNeighbors
= NULL
;
192 m_topologyRebuildTimestamp
= 0;
193 m_iPendingStatus
= -1;
195 m_iRequiredPollCount
= 0; // Use system default
196 m_nUseIfXTable
= IFXTABLE_DEFAULT
; // Use system default
197 m_jobQueue
= new ServerJobQueue();
200 m_wirelessStations
= NULL
;
201 m_adoptedApCount
= 0;
206 m_softwarePackages
= NULL
;
207 m_winPerfObjects
= NULL
;
208 memset(m_baseBridgeAddress
, 0, MAC_ADDR_LENGTH
);
209 m_fileUpdateConn
= NULL
;
214 m_syslogMessageCount
= 0;
217 m_sshPassword
[0] = 0;
218 m_sshProxy
= sshProxy
;
227 MutexDestroy(m_hPollerMutex
);
228 MutexDestroy(m_hAgentAccessMutex
);
229 MutexDestroy(m_hSmclpAccessMutex
);
230 MutexDestroy(m_mutexRTAccess
);
231 MutexDestroy(m_mutexTopoAccess
);
232 MutexDestroy(m_snmpProxyConnectionLock
);
233 if (m_agentConnection
!= NULL
)
234 m_agentConnection
->decRefCount();
235 if (m_snmpProxyConnection
!= NULL
)
236 m_snmpProxyConnection
->decRefCount();
237 delete m_smclpConnection
;
240 safe_free(m_sysDescription
);
241 DestroyRoutingTable(m_pRoutingTable
);
242 if (m_linkLayerNeighbors
!= NULL
)
243 m_linkLayerNeighbors
->decRefCount();
247 delete m_snmpSecurity
;
249 m_fdb
->decRefCount();
251 m_vlans
->decRefCount();
252 delete m_wirelessStations
;
253 if (m_components
!= NULL
)
254 m_components
->decRefCount();
255 delete m_lldpLocalPortInfo
;
256 delete m_softwarePackages
;
257 delete m_winPerfObjects
;
258 safe_free(m_sysName
);
259 safe_free(m_sysContact
);
260 safe_free(m_sysLocation
);
264 * Create object from database data
266 bool Node::loadFromDatabase(DB_HANDLE hdb
, UINT32 dwId
)
271 bool bResult
= false;
275 if (!loadCommonProperties(hdb
))
277 DbgPrintf(2, _T("Cannot load common properties for node object %d"), dwId
);
281 DB_STATEMENT hStmt
= DBPrepare(hdb
,
282 _T("SELECT primary_name,primary_ip,node_flags,")
283 _T("snmp_version,auth_method,secret,")
284 _T("agent_port,status_poll_type,snmp_oid,agent_version,")
285 _T("platform_name,poller_node_id,zone_guid,")
286 _T("proxy_node,snmp_proxy,required_polls,uname,")
287 _T("use_ifxtable,snmp_port,community,usm_auth_password,")
288 _T("usm_priv_password,usm_methods,snmp_sys_name,bridge_base_addr,")
289 _T("runtime_flags,down_since,boot_time,driver_name,icmp_proxy,")
290 _T("agent_cache_mode,snmp_sys_contact,snmp_sys_location,")
291 _T("rack_id,rack_image,rack_position,rack_height,")
292 _T("last_agent_comm_time,syslog_msg_count,snmp_trap_count,")
293 _T("node_type,node_subtype,ssh_login,ssh_password,ssh_proxy FROM nodes WHERE id=?"));
297 DBBind(hStmt
, 1, DB_SQLTYPE_INTEGER
, dwId
);
298 DB_RESULT hResult
= DBSelectPrepared(hStmt
);
301 DBFreeStatement(hStmt
);
302 return false; // Query failed
305 if (DBGetNumRows(hResult
) == 0)
307 DBFreeResult(hResult
);
308 DBFreeStatement(hStmt
);
309 DbgPrintf(2, _T("Missing record in \"nodes\" table for node object %d"), dwId
);
313 DBGetField(hResult
, 0, 0, m_primaryName
, MAX_DNS_NAME
);
314 m_ipAddress
= DBGetFieldInetAddr(hResult
, 0, 1);
315 m_flags
= DBGetFieldULong(hResult
, 0, 2);
316 m_snmpVersion
= DBGetFieldLong(hResult
, 0, 3);
317 m_agentAuthMethod
= (WORD
)DBGetFieldLong(hResult
, 0, 4);
318 DBGetField(hResult
, 0, 5, m_szSharedSecret
, MAX_SECRET_LENGTH
);
319 m_agentPort
= (WORD
)DBGetFieldLong(hResult
, 0, 6);
320 m_iStatusPollType
= DBGetFieldLong(hResult
, 0, 7);
321 DBGetField(hResult
, 0, 8, m_szObjectId
, MAX_OID_LEN
* 4);
322 DBGetField(hResult
, 0, 9, m_szAgentVersion
, MAX_AGENT_VERSION_LEN
);
323 DBGetField(hResult
, 0, 10, m_szPlatformName
, MAX_PLATFORM_NAME_LEN
);
324 m_pollerNode
= DBGetFieldULong(hResult
, 0, 11);
325 m_zoneId
= DBGetFieldULong(hResult
, 0, 12);
326 m_agentProxy
= DBGetFieldULong(hResult
, 0, 13);
327 m_snmpProxy
= DBGetFieldULong(hResult
, 0, 14);
328 m_iRequiredPollCount
= DBGetFieldLong(hResult
, 0, 15);
329 m_sysDescription
= DBGetField(hResult
, 0, 16, NULL
, 0);
330 m_nUseIfXTable
= (BYTE
)DBGetFieldLong(hResult
, 0, 17);
331 m_snmpPort
= (WORD
)DBGetFieldLong(hResult
, 0, 18);
333 // SNMP authentication parameters
334 char snmpAuthObject
[256], snmpAuthPassword
[256], snmpPrivPassword
[256];
335 DBGetFieldA(hResult
, 0, 19, snmpAuthObject
, 256);
336 DBGetFieldA(hResult
, 0, 20, snmpAuthPassword
, 256);
337 DBGetFieldA(hResult
, 0, 21, snmpPrivPassword
, 256);
338 int snmpMethods
= DBGetFieldLong(hResult
, 0, 22);
339 delete m_snmpSecurity
;
340 m_snmpSecurity
= new SNMP_SecurityContext(snmpAuthObject
, snmpAuthPassword
, snmpPrivPassword
, snmpMethods
& 0xFF, snmpMethods
>> 8);
341 m_snmpSecurity
->setSecurityModel((m_snmpVersion
== SNMP_VERSION_3
) ? SNMP_SECURITY_MODEL_USM
: SNMP_SECURITY_MODEL_V2C
);
343 m_sysName
= DBGetField(hResult
, 0, 23, NULL
, 0);
346 TCHAR
*value
= DBGetField(hResult
, 0, 24, baseAddr
, 16);
348 StrToBin(value
, m_baseBridgeAddress
, MAC_ADDR_LENGTH
);
350 m_dwDynamicFlags
= DBGetFieldULong(hResult
, 0, 25);
351 m_dwDynamicFlags
&= NDF_PERSISTENT
; // Clear out all non-persistent runtime flags
353 m_downSince
= DBGetFieldLong(hResult
, 0, 26);
354 m_bootTime
= DBGetFieldLong(hResult
, 0, 27);
357 TCHAR driverName
[34];
358 DBGetField(hResult
, 0, 28, driverName
, 34);
359 StrStrip(driverName
);
360 if (driverName
[0] != 0)
361 m_driver
= FindDriverByName(driverName
);
363 m_icmpProxy
= DBGetFieldULong(hResult
, 0, 29);
364 m_agentCacheMode
= (INT16
)DBGetFieldLong(hResult
, 0, 30);
365 if ((m_agentCacheMode
!= AGENT_CACHE_ON
) && (m_agentCacheMode
!= AGENT_CACHE_OFF
))
366 m_agentCacheMode
= AGENT_CACHE_DEFAULT
;
368 m_sysContact
= DBGetField(hResult
, 0, 31, NULL
, 0);
369 m_sysLocation
= DBGetField(hResult
, 0, 32, NULL
, 0);
371 m_rackId
= DBGetFieldULong(hResult
, 0, 33);
372 m_rackImage
= DBGetFieldGUID(hResult
, 0, 34);
373 m_rackPosition
= (INT16
)DBGetFieldLong(hResult
, 0, 35);
374 m_rackHeight
= (INT16
)DBGetFieldLong(hResult
, 0, 36);
375 m_lastAgentCommTime
= DBGetFieldLong(hResult
, 0, 37);
376 m_syslogMessageCount
= DBGetFieldInt64(hResult
, 0, 38);
377 m_snmpTrapCount
= DBGetFieldInt64(hResult
, 0, 39);
378 m_type
= (NodeType
)DBGetFieldLong(hResult
, 0, 40);
379 DBGetField(hResult
, 0, 41, m_subType
, MAX_NODE_SUBTYPE_LENGTH
);
380 DBGetField(hResult
, 0, 42, m_sshLogin
, MAX_SSH_LOGIN_LEN
);
381 DBGetField(hResult
, 0, 43, m_sshPassword
, MAX_SSH_PASSWORD_LEN
);
382 m_sshProxy
= DBGetFieldULong(hResult
, 0, 44);
384 DBFreeResult(hResult
);
385 DBFreeStatement(hStmt
);
389 // Link node to subnets
390 hStmt
= DBPrepare(hdb
, _T("SELECT subnet_id FROM nsmap WHERE node_id=?"));
394 DBBind(hStmt
, 1, DB_SQLTYPE_INTEGER
, m_id
);
395 hResult
= DBSelectPrepared(hStmt
);
398 DBFreeStatement(hStmt
);
399 return false; // Query failed
402 iNumRows
= DBGetNumRows(hResult
);
403 for(i
= 0; i
< iNumRows
; i
++)
405 dwSubnetId
= DBGetFieldULong(hResult
, i
, 0);
406 pObject
= FindObjectById(dwSubnetId
);
409 nxlog_write(MSG_INVALID_SUBNET_ID
, EVENTLOG_ERROR_TYPE
, "dd", dwId
, dwSubnetId
);
412 else if (pObject
->getObjectClass() != OBJECT_SUBNET
)
414 nxlog_write(MSG_SUBNET_NOT_SUBNET
, EVENTLOG_ERROR_TYPE
, "dd", dwId
, dwSubnetId
);
419 pObject
->addChild(this);
424 DBFreeResult(hResult
);
425 DBFreeStatement(hStmt
);
427 loadItemsFromDB(hdb
);
430 // Walk through all items in the node and load appropriate thresholds
432 for(i
= 0; i
< m_dcObjects
->size(); i
++)
434 if (!m_dcObjects
->get(i
)->loadThresholdsFromDB(hdb
))
436 DbgPrintf(3, _T("Cannot load thresholds for DCI %d of node %d (%s)"),
437 m_dcObjects
->get(i
)->getId(), dwId
, m_name
);
442 updatePhysicalContainerBinding(OBJECT_RACK
, m_rackId
);
443 updatePhysicalContainerBinding(OBJECT_CHASSIS
, m_chassisId
);
454 * Save object to database
456 BOOL
Node::saveToDatabase(DB_HANDLE hdb
)
458 // Lock object's access
461 if (!saveCommonProperties(hdb
))
467 // Form and execute INSERT or UPDATE query
468 int snmpMethods
= m_snmpSecurity
->getAuthMethod() | (m_snmpSecurity
->getPrivMethod() << 8);
470 if (IsDatabaseRecordExist(hdb
, _T("nodes"), _T("id"), m_id
))
472 hStmt
= DBPrepare(hdb
,
473 _T("UPDATE nodes SET primary_ip=?,primary_name=?,snmp_port=?,node_flags=?,snmp_version=?,community=?,")
474 _T("status_poll_type=?,agent_port=?,auth_method=?,secret=?,snmp_oid=?,uname=?,agent_version=?,")
475 _T("platform_name=?,poller_node_id=?,zone_guid=?,proxy_node=?,snmp_proxy=?,icmp_proxy=?,required_polls=?,")
476 _T("use_ifxtable=?,usm_auth_password=?,usm_priv_password=?,usm_methods=?,snmp_sys_name=?,bridge_base_addr=?,")
477 _T("runtime_flags=?,down_since=?,driver_name=?,rack_image=?,rack_position=?,rack_height=?,rack_id=?,boot_time=?,")
478 _T("agent_cache_mode=?,snmp_sys_contact=?,snmp_sys_location=?,last_agent_comm_time=?,")
479 _T("syslog_msg_count=?,snmp_trap_count=?,node_type=?,node_subtype=?,ssh_login=?,ssh_password=?,")
480 _T("ssh_proxy=?,chassis_id=? WHERE id=?"));
484 hStmt
= DBPrepare(hdb
,
485 _T("INSERT INTO nodes (primary_ip,primary_name,snmp_port,node_flags,snmp_version,community,status_poll_type,")
486 _T("agent_port,auth_method,secret,snmp_oid,uname,agent_version,platform_name,poller_node_id,zone_guid,")
487 _T("proxy_node,snmp_proxy,icmp_proxy,required_polls,use_ifxtable,usm_auth_password,usm_priv_password,usm_methods,")
488 _T("snmp_sys_name,bridge_base_addr,runtime_flags,down_since,driver_name,rack_image,rack_position,rack_height,rack_id,boot_time,")
489 _T("agent_cache_mode,snmp_sys_contact,snmp_sys_location,last_agent_comm_time,syslog_msg_count,snmp_trap_count,")
490 _T("node_type,node_subtype,ssh_login,ssh_password,ssh_proxy,chassis_id,id) ")
491 _T("VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"));
499 TCHAR ipAddr
[64], baseAddress
[16], cacheMode
[16];
501 DBBind(hStmt
, 1, DB_SQLTYPE_VARCHAR
, m_ipAddress
.toString(ipAddr
), DB_BIND_STATIC
);
502 DBBind(hStmt
, 2, DB_SQLTYPE_VARCHAR
, m_primaryName
, DB_BIND_STATIC
);
503 DBBind(hStmt
, 3, DB_SQLTYPE_INTEGER
, (LONG
)m_snmpPort
);
504 DBBind(hStmt
, 4, DB_SQLTYPE_INTEGER
, m_flags
);
505 DBBind(hStmt
, 5, DB_SQLTYPE_INTEGER
, (LONG
)m_snmpVersion
);
507 DBBind(hStmt
, 6, DB_SQLTYPE_VARCHAR
, WideStringFromMBString(m_snmpSecurity
->getCommunity()), DB_BIND_DYNAMIC
);
509 DBBind(hStmt
, 6, DB_SQLTYPE_VARCHAR
, m_snmpSecurity
->getCommunity(), DB_BIND_STATIC
);
511 DBBind(hStmt
, 7, DB_SQLTYPE_INTEGER
, (LONG
)m_iStatusPollType
);
512 DBBind(hStmt
, 8, DB_SQLTYPE_INTEGER
, (LONG
)m_agentPort
);
513 DBBind(hStmt
, 9, DB_SQLTYPE_INTEGER
, (LONG
)m_agentAuthMethod
);
514 DBBind(hStmt
, 10, DB_SQLTYPE_VARCHAR
, m_szSharedSecret
, DB_BIND_STATIC
);
515 DBBind(hStmt
, 11, DB_SQLTYPE_VARCHAR
, m_szObjectId
, DB_BIND_STATIC
);
516 DBBind(hStmt
, 12, DB_SQLTYPE_VARCHAR
, m_sysDescription
, DB_BIND_STATIC
);
517 DBBind(hStmt
, 13, DB_SQLTYPE_VARCHAR
, m_szAgentVersion
, DB_BIND_STATIC
);
518 DBBind(hStmt
, 14, DB_SQLTYPE_VARCHAR
, m_szPlatformName
, DB_BIND_STATIC
);
519 DBBind(hStmt
, 15, DB_SQLTYPE_INTEGER
, m_pollerNode
);
520 DBBind(hStmt
, 16, DB_SQLTYPE_INTEGER
, m_zoneId
);
521 DBBind(hStmt
, 17, DB_SQLTYPE_INTEGER
, m_agentProxy
);
522 DBBind(hStmt
, 18, DB_SQLTYPE_INTEGER
, m_snmpProxy
);
523 DBBind(hStmt
, 19, DB_SQLTYPE_INTEGER
, m_icmpProxy
);
524 DBBind(hStmt
, 20, DB_SQLTYPE_INTEGER
, (LONG
)m_iRequiredPollCount
);
525 DBBind(hStmt
, 21, DB_SQLTYPE_INTEGER
, (LONG
)m_nUseIfXTable
);
527 DBBind(hStmt
, 22, DB_SQLTYPE_VARCHAR
, WideStringFromMBString(m_snmpSecurity
->getAuthPassword()), DB_BIND_DYNAMIC
);
528 DBBind(hStmt
, 23, DB_SQLTYPE_VARCHAR
, WideStringFromMBString(m_snmpSecurity
->getPrivPassword()), DB_BIND_DYNAMIC
);
530 DBBind(hStmt
, 22, DB_SQLTYPE_VARCHAR
, m_snmpSecurity
->getAuthPassword(), DB_BIND_STATIC
);
531 DBBind(hStmt
, 23, DB_SQLTYPE_VARCHAR
, m_snmpSecurity
->getPrivPassword(), DB_BIND_STATIC
);
533 DBBind(hStmt
, 24, DB_SQLTYPE_INTEGER
, (LONG
)snmpMethods
);
534 DBBind(hStmt
, 25, DB_SQLTYPE_VARCHAR
, m_sysName
, DB_BIND_STATIC
);
535 DBBind(hStmt
, 26, DB_SQLTYPE_VARCHAR
, BinToStr(m_baseBridgeAddress
, MAC_ADDR_LENGTH
, baseAddress
), DB_BIND_STATIC
);
536 DBBind(hStmt
, 27, DB_SQLTYPE_INTEGER
, m_dwDynamicFlags
);
537 DBBind(hStmt
, 28, DB_SQLTYPE_INTEGER
, (LONG
)m_downSince
);
538 DBBind(hStmt
, 29, DB_SQLTYPE_VARCHAR
, (m_driver
!= NULL
) ? m_driver
->getName() : _T(""), DB_BIND_STATIC
);
539 DBBind(hStmt
, 30, DB_SQLTYPE_VARCHAR
, m_rackImage
); // rack image
540 DBBind(hStmt
, 31, DB_SQLTYPE_INTEGER
, m_rackPosition
); // rack position
541 DBBind(hStmt
, 32, DB_SQLTYPE_INTEGER
, m_rackHeight
); // device height in rack units
542 DBBind(hStmt
, 33, DB_SQLTYPE_INTEGER
, m_rackId
); // rack ID
543 DBBind(hStmt
, 34, DB_SQLTYPE_INTEGER
, (LONG
)m_bootTime
);
544 DBBind(hStmt
, 35, DB_SQLTYPE_VARCHAR
, _itot(m_agentCacheMode
, cacheMode
, 10), DB_BIND_STATIC
);
545 DBBind(hStmt
, 36, DB_SQLTYPE_VARCHAR
, m_sysContact
, DB_BIND_STATIC
);
546 DBBind(hStmt
, 37, DB_SQLTYPE_VARCHAR
, m_sysLocation
, DB_BIND_STATIC
);
547 DBBind(hStmt
, 38, DB_SQLTYPE_INTEGER
, (LONG
)m_lastAgentCommTime
);
548 DBBind(hStmt
, 39, DB_SQLTYPE_BIGINT
, m_syslogMessageCount
);
549 DBBind(hStmt
, 40, DB_SQLTYPE_BIGINT
, m_snmpTrapCount
);
550 DBBind(hStmt
, 41, DB_SQLTYPE_INTEGER
, (INT32
)m_type
);
551 DBBind(hStmt
, 42, DB_SQLTYPE_VARCHAR
, m_subType
, DB_BIND_STATIC
);
552 DBBind(hStmt
, 43, DB_SQLTYPE_VARCHAR
, m_sshLogin
, DB_BIND_STATIC
);
553 DBBind(hStmt
, 44, DB_SQLTYPE_VARCHAR
, m_sshPassword
, DB_BIND_STATIC
);
554 DBBind(hStmt
, 45, DB_SQLTYPE_INTEGER
, m_sshProxy
);
555 DBBind(hStmt
, 46, DB_SQLTYPE_INTEGER
, m_chassisId
);
556 DBBind(hStmt
, 47, DB_SQLTYPE_INTEGER
, m_id
);
558 BOOL bResult
= DBExecute(hStmt
);
559 DBFreeStatement(hStmt
);
566 // Save data collection items
569 lockDciAccess(false);
570 for(int i
= 0; i
< m_dcObjects
->size(); i
++)
571 m_dcObjects
->get(i
)->saveToDatabase(hdb
);
575 // Clear modifications flag
577 m_isModified
= false;
584 * Delete object from database
586 bool Node::deleteFromDatabase(DB_HANDLE hdb
)
588 bool success
= DataCollectionTarget::deleteFromDatabase(hdb
);
590 success
= executeQueryOnObject(hdb
, _T("DELETE FROM nodes WHERE id=?"));
592 success
= executeQueryOnObject(hdb
, _T("DELETE FROM nsmap WHERE node_id=?"));
597 * Get ARP cache from node
599 ARP_CACHE
*Node::getArpCache()
601 ARP_CACHE
*pArpCache
= NULL
;
603 if (m_flags
& NF_IS_LOCAL_MGMT
)
605 pArpCache
= GetLocalArpCache();
607 else if (m_flags
& NF_IS_NATIVE_AGENT
)
610 if (connectToAgent())
611 pArpCache
= m_agentConnection
->getArpCache();
614 else if (m_flags
& NF_IS_SNMP
)
616 SNMP_Transport
*pTransport
;
618 pTransport
= createSnmpTransport();
619 if (pTransport
!= NULL
)
621 pArpCache
= SnmpGetArpCache(m_snmpVersion
, pTransport
);
630 * Get list of interfaces from node
632 InterfaceList
*Node::getInterfaceList()
634 InterfaceList
*pIfList
= NULL
;
636 if ((m_flags
& NF_IS_NATIVE_AGENT
) && (!(m_flags
& NF_DISABLE_NXCP
)))
639 if (connectToAgent())
641 pIfList
= m_agentConnection
->getInterfaceList();
645 if ((pIfList
== NULL
) && (m_flags
& NF_IS_LOCAL_MGMT
))
647 pIfList
= GetLocalInterfaceList();
649 if ((pIfList
== NULL
) && (m_flags
& NF_IS_SNMP
) &&
650 (!(m_flags
& NF_DISABLE_SNMP
)) && (m_driver
!= NULL
))
652 SNMP_Transport
*pTransport
= createSnmpTransport();
653 if (pTransport
!= NULL
)
656 if (m_nUseIfXTable
== IFXTABLE_DEFAULT
)
658 useIfXTable
= (ConfigReadInt(_T("UseIfXTable"), 1) != 0) ? true : false;
662 useIfXTable
= (m_nUseIfXTable
== IFXTABLE_ENABLED
) ? true : false;
665 int useAliases
= ConfigReadInt(_T("UseInterfaceAliases"), 0);
666 pIfList
= m_driver
->getInterfaces(pTransport
, &m_customAttributes
, m_driverData
, useAliases
, useIfXTable
);
668 if ((pIfList
!= NULL
) && (m_flags
& NF_IS_BRIDGE
))
670 BridgeMapPorts(pTransport
, pIfList
);
678 checkInterfaceNames(pIfList
);
679 addVrrpInterfaces(pIfList
);
686 * Add VRRP interfaces to interface list
688 void Node::addVrrpInterfaces(InterfaceList
*ifList
)
694 if (m_vrrpInfo
!= NULL
)
696 DbgPrintf(6, _T("Node::addVrrpInterfaces(node=%s [%d]): m_vrrpInfo->size()=%d"), m_name
, (int)m_id
, m_vrrpInfo
->size());
698 for(i
= 0; i
< m_vrrpInfo
->size(); i
++)
700 VrrpRouter
*router
= m_vrrpInfo
->getRouter(i
);
701 DbgPrintf(6, _T("Node::addVrrpInterfaces(node=%s [%d]): vrouter %d state=%d"), m_name
, (int)m_id
, i
, router
->getState());
702 if (router
->getState() != VRRP_STATE_MASTER
)
703 continue; // Do not add interfaces if router is not in master state
705 // Get netmask for this VR
707 for(j
= 0; j
< ifList
->size(); j
++)
709 InterfaceInfo
*iface
= ifList
->get(j
);
710 if (iface
->index
== router
->getIfIndex())
712 for(int k
= 0; k
< iface
->ipAddrList
.size(); k
++)
714 const InetAddress
& addr
= iface
->ipAddrList
.get(k
);
715 if (addr
.getSubnetAddress().contain(router
->getVip(0)))
717 maskBits
= addr
.getMaskBits();
724 // Walk through all VR virtual IPs
725 for(j
= 0; j
< router
->getVipCount(); j
++)
727 UINT32 vip
= router
->getVip(j
);
728 DbgPrintf(6, _T("Node::addVrrpInterfaces(node=%s [%d]): checking VIP %s@%d"), m_name
, (int)m_id
, IpToStr(vip
, buffer
), i
);
731 for(k
= 0; k
< ifList
->size(); k
++)
732 if (ifList
->get(k
)->hasAddress(vip
))
734 if (k
== ifList
->size())
736 InterfaceInfo
*iface
= new InterfaceInfo(0);
737 _sntprintf(iface
->name
, MAX_DB_STRING
, _T("vrrp.%u.%u.%d"), router
->getId(), router
->getIfIndex(), j
);
738 memcpy(iface
->macAddr
, router
->getVirtualMacAddr(), MAC_ADDR_LENGTH
);
739 InetAddress
addr(vip
);
740 addr
.setMaskBits(maskBits
);
741 iface
->ipAddrList
.add(addr
);
743 DbgPrintf(6, _T("Node::addVrrpInterfaces(node=%s [%d]): added interface %s"), m_name
, (int)m_id
, iface
->name
);
753 * Find interface by index.
755 * @param ifIndex interface index to match
756 * @return pointer to interface object or NULL if appropriate interface couldn't be found
758 Interface
*Node::findInterfaceByIndex(UINT32 ifIndex
)
760 lockChildList(false);
761 for(int i
= 0; i
< m_childList
->size(); i
++)
762 if (m_childList
->get(i
)->getObjectClass() == OBJECT_INTERFACE
)
764 Interface
*pInterface
= (Interface
*)m_childList
->get(i
);
765 if (pInterface
->getIfIndex() == ifIndex
)
776 * Find interface by name or description
777 * Returns pointer to interface object or NULL if appropriate interface couldn't be found
779 Interface
*Node::findInterfaceByName(const TCHAR
*name
)
781 if ((name
== NULL
) || (name
[0] == 0))
784 Interface
*pInterface
;
786 lockChildList(false);
787 for(int i
= 0; i
< m_childList
->size(); i
++)
788 if (m_childList
->get(i
)->getObjectClass() == OBJECT_INTERFACE
)
790 pInterface
= (Interface
*)m_childList
->get(i
);
791 if (!_tcsicmp(pInterface
->getName(), name
) || !_tcsicmp(pInterface
->getDescription(), name
))
802 * Find interface by slot/port pair
803 * Returns pointer to interface object or NULL if appropriate interface couldn't be found
805 Interface
*Node::findInterfaceBySlotAndPort(UINT32 slot
, UINT32 port
)
807 lockChildList(false);
808 for(int i
= 0; i
< m_childList
->size(); i
++)
809 if (m_childList
->get(i
)->getObjectClass() == OBJECT_INTERFACE
)
811 Interface
*pInterface
= (Interface
*)m_childList
->get(i
);
812 if (pInterface
->isPhysicalPort() && (pInterface
->getSlotNumber() == slot
) && (pInterface
->getPortNumber() == port
))
823 * Find interface by MAC address
824 * Returns pointer to interface object or NULL if appropriate interface couldn't be found
826 Interface
*Node::findInterfaceByMAC(const BYTE
*macAddr
)
828 Interface
*iface
= NULL
;
829 lockChildList(false);
830 for(int i
= 0; i
< m_childList
->size(); i
++)
832 NetObj
*curr
= m_childList
->get(i
);
833 if (curr
->getObjectClass() == OBJECT_INTERFACE
)
835 if (!memcmp(((Interface
*)curr
)->getMacAddr(), macAddr
, MAC_ADDR_LENGTH
))
837 iface
= (Interface
*)curr
;
847 * Find interface by IP address
848 * Returns pointer to interface object or NULL if appropriate interface couldn't be found
850 Interface
*Node::findInterfaceByIP(const InetAddress
& addr
)
855 lockChildList(false);
856 for(int i
= 0; i
< m_childList
->size(); i
++)
857 if (m_childList
->get(i
)->getObjectClass() == OBJECT_INTERFACE
)
859 Interface
*pInterface
= (Interface
*)m_childList
->get(i
);
860 if (pInterface
->getIpAddressList()->hasAddress(addr
))
871 * Find interface by bridge port number
873 Interface
*Node::findBridgePort(UINT32 bridgePortNumber
)
875 lockChildList(false);
876 for(int i
= 0; i
< m_childList
->size(); i
++)
877 if (m_childList
->get(i
)->getObjectClass() == OBJECT_INTERFACE
)
879 Interface
*pInterface
= (Interface
*)m_childList
->get(i
);
880 if (pInterface
->getBridgePortNumber() == bridgePortNumber
)
891 * Find connection point for node
893 NetObj
*Node::findConnectionPoint(UINT32
*localIfId
, BYTE
*localMacAddr
, int *type
)
896 lockChildList(false);
897 for(int i
= 0; i
< m_childList
->size(); i
++)
899 if (m_childList
->get(i
)->getObjectClass() == OBJECT_INTERFACE
)
901 Interface
*iface
= (Interface
*)m_childList
->get(i
);
902 cp
= FindInterfaceConnectionPoint(iface
->getMacAddr(), type
);
905 *localIfId
= iface
->getId();
906 memcpy(localMacAddr
, iface
->getMacAddr(), MAC_ADDR_LENGTH
);
916 * Find attached access point by MAC address
918 AccessPoint
*Node::findAccessPointByMAC(const BYTE
*macAddr
)
920 AccessPoint
*ap
= NULL
;
921 lockChildList(false);
922 for(int i
= 0; i
< m_childList
->size(); i
++)
924 NetObj
*curr
= m_childList
->get(i
);
925 if (curr
->getObjectClass() == OBJECT_ACCESSPOINT
)
927 if (!memcmp(((AccessPoint
*)curr
)->getMacAddr(), macAddr
, MAC_ADDR_LENGTH
))
929 ap
= (AccessPoint
*)curr
;
939 * Find access point by radio ID (radio interface index)
941 AccessPoint
*Node::findAccessPointByRadioId(int rfIndex
)
943 AccessPoint
*ap
= NULL
;
944 lockChildList(false);
945 for(int i
= 0; i
< m_childList
->size(); i
++)
947 NetObj
*curr
= m_childList
->get(i
);
948 if (curr
->getObjectClass() == OBJECT_ACCESSPOINT
)
950 if (((AccessPoint
*)curr
)->isMyRadio(rfIndex
))
952 ap
= (AccessPoint
*)curr
;
962 * Find attached access point by BSSID
964 AccessPoint
*Node::findAccessPointByBSSID(const BYTE
*bssid
)
966 AccessPoint
*ap
= NULL
;
967 lockChildList(false);
968 for(int i
= 0; i
< m_childList
->size(); i
++)
970 NetObj
*curr
= m_childList
->get(i
);
971 if (curr
->getObjectClass() == OBJECT_ACCESSPOINT
)
973 if (!memcmp(((AccessPoint
*)curr
)->getMacAddr(), bssid
, MAC_ADDR_LENGTH
) ||
974 ((AccessPoint
*)curr
)->isMyRadio(bssid
))
976 ap
= (AccessPoint
*)curr
;
986 * Check if given IP address is one of node's interfaces
988 bool Node::isMyIP(const InetAddress
& addr
)
990 lockChildList(false);
991 for(int i
= 0; i
< m_childList
->size(); i
++)
992 if (m_childList
->get(i
)->getObjectClass() == OBJECT_INTERFACE
)
994 if (((Interface
*)m_childList
->get(i
))->getIpAddressList()->hasAddress(addr
))
1005 * Filter interface - should return true if system should proceed with interface creation
1007 bool Node::filterInterface(InterfaceInfo
*info
)
1009 NXSL_VM
*vm
= g_pScriptLibrary
->createVM(_T("Hook::CreateInterface"), new NXSL_ServerEnv
);
1012 DbgPrintf(7, _T("Node::filterInterface(%s [%u]): hook script \"Hook::CreateInterface\" not found"), m_name
, m_id
);
1017 if (info
->name
[0] != 0)
1018 iface
= new Interface(info
->name
, (info
->description
[0] != 0) ? info
->description
: info
->name
,
1019 info
->index
, info
->ipAddrList
, info
->type
, m_zoneId
);
1021 iface
= new Interface(info
->ipAddrList
, m_zoneId
, false);
1022 iface
->setMacAddr(info
->macAddr
, false);
1023 iface
->setBridgePortNumber(info
->bridgePort
);
1024 iface
->setSlotNumber(info
->slot
);
1025 iface
->setPortNumber(info
->port
);
1026 iface
->setPhysicalPortFlag(info
->isPhysicalPort
);
1027 iface
->setManualCreationFlag(false);
1028 iface
->setSystemFlag(info
->isSystem
);
1029 iface
->setMTU(info
->mtu
);
1030 iface
->setSpeed(info
->speed
);
1031 iface
->setIfTableSuffix(info
->ifTableSuffixLength
, info
->ifTableSuffix
);
1034 NXSL_Value
*argv
= new NXSL_Value(new NXSL_Object(&g_nxslInterfaceClass
, iface
));
1035 vm
->setGlobalVariable(_T("$node"), new NXSL_Value(new NXSL_Object(&g_nxslNodeClass
, this)));
1036 if (vm
->run(1, &argv
))
1038 NXSL_Value
*result
= vm
->getResult();
1039 if ((result
!= NULL
) && result
->isInteger())
1041 pass
= (result
->getValueAsInt32() != 0);
1046 DbgPrintf(4, _T("Node::filterInterface(%s [%u]): hook script execution error: %s"), m_name
, m_id
, vm
->getErrorText());
1051 DbgPrintf(6, _T("Node::filterInterface(%s [%u]): interface \"%s\" (ifIndex=%d) %s by filter"),
1052 m_name
, m_id
, info
->name
, info
->index
, pass
? _T("accepted") : _T("rejected"));
1057 * Create new interface - convenience wrapper
1059 Interface
*Node::createNewInterface(const InetAddress
& ipAddr
, BYTE
*macAddr
, bool fakeInterface
)
1061 InterfaceInfo
info(1);
1062 info
.ipAddrList
.add(ipAddr
);
1063 if (macAddr
!= NULL
)
1064 memcpy(info
.macAddr
, macAddr
, MAC_ADDR_LENGTH
);
1065 return createNewInterface(&info
, false, fakeInterface
);
1069 * Create new interface
1071 Interface
*Node::createNewInterface(InterfaceInfo
*info
, bool manuallyCreated
, bool fakeInterface
)
1073 bool bSyntheticMask
= false;
1076 DbgPrintf(5, _T("Node::createNewInterface(\"%s\", %d, %d, bp=%d, slot=%d, port=%d) called for node %s [%d]"),
1077 info
->name
, info
->index
, info
->type
, info
->bridgePort
, info
->slot
, info
->port
, m_name
, m_id
);
1078 for(int i
= 0; i
< info
->ipAddrList
.size(); i
++)
1080 const InetAddress
& addr
= info
->ipAddrList
.get(i
);
1081 DbgPrintf(5, _T("Node::createNewInterface(%s): IP address %s/%d"), info
->name
, addr
.toString(buffer
), addr
.getMaskBits());
1084 // Find subnet to place interface object to
1085 if (info
->type
!= IFTYPE_SOFTWARE_LOOPBACK
)
1087 Cluster
*pCluster
= getMyCluster();
1088 for(int i
= 0; i
< info
->ipAddrList
.size(); i
++)
1090 InetAddress addr
= info
->ipAddrList
.get(i
);
1091 bool addToSubnet
= addr
.isValidUnicast() && ((pCluster
== NULL
) || !pCluster
->isSyncAddr(addr
));
1092 DbgPrintf(5, _T("Node::createNewInterface: node=%s [%d] ip=%s/%d cluster=%s [%d] add=%s"),
1093 m_name
, m_id
, addr
.toString(buffer
), addr
.getMaskBits(),
1094 (pCluster
!= NULL
) ? pCluster
->getName() : _T("(null)"),
1095 (pCluster
!= NULL
) ? pCluster
->getId() : 0, addToSubnet
? _T("yes") : _T("no"));
1098 Subnet
*pSubnet
= FindSubnetForNode(m_zoneId
, addr
);
1099 if (pSubnet
== NULL
)
1101 // Check if netmask is 0 (detect), and if yes, create
1102 // new subnet with default mask
1103 if (addr
.getMaskBits() == 0)
1105 bSyntheticMask
= true;
1106 addr
.setMaskBits((addr
.getFamily() == AF_INET
) ? ConfigReadInt(_T("DefaultSubnetMaskIPv4"), 24) : ConfigReadInt(_T("DefaultSubnetMaskIPv6"), 64));
1107 info
->ipAddrList
.replace(addr
);
1110 // Create new subnet object
1111 if (addr
.getHostBits() >= 2)
1113 pSubnet
= createSubnet(addr
, bSyntheticMask
);
1116 // createSubnet may adjust address mask bits
1117 info
->ipAddrList
.replace(addr
);
1123 // Set correct netmask if we were asked for it
1124 if (addr
.getMaskBits() == 0)
1126 bSyntheticMask
= pSubnet
->isSyntheticMask();
1127 addr
.setMaskBits(pSubnet
->getIpAddress().getMaskBits());
1128 info
->ipAddrList
.replace(addr
);
1131 if (pSubnet
!= NULL
)
1133 pSubnet
->addNode(this);
1136 } // loop by address list
1139 // Create interface object
1140 Interface
*pInterface
;
1141 if (info
->name
[0] != 0)
1142 pInterface
= new Interface(info
->name
, (info
->description
[0] != 0) ? info
->description
: info
->name
,
1143 info
->index
, info
->ipAddrList
, info
->type
, m_zoneId
);
1145 pInterface
= new Interface(info
->ipAddrList
, m_zoneId
, bSyntheticMask
);
1146 pInterface
->setMacAddr(info
->macAddr
, false);
1147 pInterface
->setBridgePortNumber(info
->bridgePort
);
1148 pInterface
->setSlotNumber(info
->slot
);
1149 pInterface
->setPortNumber(info
->port
);
1150 pInterface
->setPhysicalPortFlag(info
->isPhysicalPort
);
1151 pInterface
->setManualCreationFlag(manuallyCreated
);
1152 pInterface
->setSystemFlag(info
->isSystem
);
1153 pInterface
->setMTU(info
->mtu
);
1154 pInterface
->setSpeed(info
->speed
);
1155 pInterface
->setIfTableSuffix(info
->ifTableSuffixLength
, info
->ifTableSuffix
);
1157 int defaultExpectedState
= ConfigReadInt(_T("DefaultInterfaceExpectedState"), IF_DEFAULT_EXPECTED_STATE_UP
);
1158 switch(defaultExpectedState
)
1160 case IF_DEFAULT_EXPECTED_STATE_AUTO
:
1161 pInterface
->setExpectedState(fakeInterface
? IF_EXPECTED_STATE_UP
: IF_EXPECTED_STATE_AUTO
);
1163 case IF_DEFAULT_EXPECTED_STATE_IGNORE
:
1164 pInterface
->setExpectedState(IF_EXPECTED_STATE_IGNORE
);
1167 pInterface
->setExpectedState(IF_EXPECTED_STATE_UP
);
1171 // Insert to objects' list and generate event
1172 NetObjInsert(pInterface
, true, false);
1173 addInterface(pInterface
);
1175 pInterface
->unhide();
1176 if (!pInterface
->isSystem())
1178 const InetAddress
& addr
= pInterface
->getFirstIpAddress();
1179 PostEvent(EVENT_INTERFACE_ADDED
, m_id
, "dsAdd", pInterface
->getId(),
1180 pInterface
->getName(), &addr
, addr
.getMaskBits(), pInterface
->getIfIndex());
1187 * Delete interface from node
1189 void Node::deleteInterface(Interface
*iface
)
1191 DbgPrintf(5, _T("Node::deleteInterface(node=%s [%d], interface=%s [%d])"), m_name
, m_id
, iface
->getName(), iface
->getId());
1193 // Check if we should unlink node from interface's subnet
1194 if (!iface
->isExcludedFromTopology())
1196 const ObjectArray
<InetAddress
> *list
= iface
->getIpAddressList()->getList();
1197 for(int i
= 0; i
< list
->size(); i
++)
1199 bool doUnlink
= true;
1200 const InetAddress
*addr
= list
->get(i
);
1202 lockChildList(false);
1203 for(int j
= 0; j
< m_childList
->size(); j
++)
1205 NetObj
*curr
= m_childList
->get(j
);
1206 if ((curr
->getObjectClass() == OBJECT_INTERFACE
) && (curr
!= iface
) &&
1207 ((Interface
*)curr
)->getIpAddressList()->findSameSubnetAddress(*addr
).isValid())
1217 // Last interface in subnet, should unlink node
1218 Subnet
*pSubnet
= FindSubnetByIP(m_zoneId
, addr
->getSubnetAddress());
1219 if (pSubnet
!= NULL
)
1221 deleteParent(pSubnet
);
1222 pSubnet
->deleteChild(this);
1224 DbgPrintf(5, _T("Node::deleteInterface(node=%s [%d], interface=%s [%d]): unlinked from subnet %s [%d]"),
1225 m_name
, m_id
, iface
->getName(), iface
->getId(),
1226 (pSubnet
!= NULL
) ? pSubnet
->getName() : _T("(null)"),
1227 (pSubnet
!= NULL
) ? pSubnet
->getId() : 0);
1231 iface
->deleteObject();
1235 * Calculate node status based on child objects status
1237 void Node::calculateCompoundStatus(BOOL bForcedRecalc
)
1239 int iOldStatus
= m_status
;
1240 static UINT32 dwEventCodes
[] = { EVENT_NODE_NORMAL
, EVENT_NODE_WARNING
,
1241 EVENT_NODE_MINOR
, EVENT_NODE_MAJOR
, EVENT_NODE_CRITICAL
,
1242 EVENT_NODE_UNKNOWN
, EVENT_NODE_UNMANAGED
};
1244 DataCollectionTarget::calculateCompoundStatus(bForcedRecalc
);
1245 if (m_status
!= iOldStatus
)
1246 PostEvent(dwEventCodes
[m_status
], m_id
, "d", iOldStatus
);
1250 * Status poller entry point
1252 void Node::statusPoll(PollerInfo
*poller
)
1254 poller
->startExecution();
1255 statusPoll(NULL
, 0, poller
);
1257 // Check if the node has to be deleted due to long downtime
1258 time_t unreachableDeleteDays
= (time_t)ConfigReadInt(_T("DeleteUnreachableNodesPeriod"), 0);
1259 if ((unreachableDeleteDays
> 0) && (m_downSince
> 0) &&
1260 (time(NULL
) - m_downSince
> unreachableDeleteDays
* 24 * 3600))
1268 * Perform status poll on node
1270 void Node::statusPoll(ClientSession
*pSession
, UINT32 dwRqId
, PollerInfo
*poller
)
1272 if (m_dwDynamicFlags
& NDF_DELETE_IN_PROGRESS
)
1275 m_dwDynamicFlags
&= ~NDF_QUEUED_FOR_STATUS_POLL
;
1279 if (IsShutdownInProgress())
1282 UINT32 dwOldFlags
= m_flags
;
1283 NetObj
*pPollerNode
= NULL
, **ppPollList
;
1284 SNMP_Transport
*pTransport
;
1286 time_t tNow
, tExpire
;
1288 Queue
*pQueue
= new Queue
; // Delayed event queue
1289 poller
->setStatus(_T("wait for lock"));
1292 if (IsShutdownInProgress())
1299 m_pollRequestor
= pSession
;
1300 sendPollerMsg(dwRqId
, _T("Starting status poll for node %s\r\n"), m_name
);
1301 DbgPrintf(5, _T("Starting status poll for node %s (ID: %d)"), m_name
, m_id
);
1303 // Read capability expiration time and current time
1304 tExpire
= (time_t)ConfigReadULong(_T("CapabilityExpirationTime"), 604800);
1307 restart_agent_check
:
1308 if (g_flags
& AF_RESOLVE_IP_FOR_EACH_STATUS_POLL
)
1310 updatePrimaryIpAddr();
1313 // Check SNMP agent connectivity
1314 if ((m_flags
& NF_IS_SNMP
) && (!(m_flags
& NF_DISABLE_SNMP
)) && m_ipAddress
.isValidUnicast())
1316 TCHAR szBuffer
[256];
1319 DbgPrintf(6, _T("StatusPoll(%s): check SNMP"), m_name
);
1320 pTransport
= createSnmpTransport();
1321 if (pTransport
!= NULL
)
1323 poller
->setStatus(_T("check SNMP"));
1324 sendPollerMsg(dwRqId
, _T("Checking SNMP agent connectivity\r\n"));
1325 const TCHAR
*testOid
= m_customAttributes
.get(_T("snmp.testoid"));
1326 if (testOid
== NULL
)
1328 testOid
= _T(".1.3.6.1.2.1.1.2.0");
1330 dwResult
= SnmpGet(m_snmpVersion
, pTransport
, testOid
, NULL
, 0, szBuffer
, sizeof(szBuffer
), 0);
1331 if ((dwResult
== SNMP_ERR_SUCCESS
) || (dwResult
== SNMP_ERR_NO_OBJECT
))
1333 if (m_dwDynamicFlags
& NDF_SNMP_UNREACHABLE
)
1335 m_dwDynamicFlags
&= ~NDF_SNMP_UNREACHABLE
;
1336 PostEventEx(pQueue
, EVENT_SNMP_OK
, m_id
, NULL
);
1337 sendPollerMsg(dwRqId
, POLLER_INFO
_T("Connectivity with SNMP agent restored\r\n"));
1340 // Update authoritative engine data for SNMPv3
1341 if ((pTransport
->getSnmpVersion() == SNMP_VERSION_3
) && (pTransport
->getAuthoritativeEngine() != NULL
))
1344 m_snmpSecurity
->setAuthoritativeEngine(*pTransport
->getAuthoritativeEngine());
1348 else if ((dwResult
== SNMP_ERR_ENGINE_ID
) && (m_snmpVersion
== SNMP_VERSION_3
))
1350 // Reset authoritative engine data
1352 m_snmpSecurity
->setAuthoritativeEngine(SNMP_Engine());
1354 goto restart_agent_check
;
1358 sendPollerMsg(dwRqId
, POLLER_ERROR
_T("SNMP agent unreachable\r\n"));
1359 if (m_dwDynamicFlags
& NDF_SNMP_UNREACHABLE
)
1361 if ((tNow
> m_failTimeSNMP
+ tExpire
) &&
1362 (!(m_dwDynamicFlags
& NDF_UNREACHABLE
)))
1364 m_flags
&= ~NF_IS_SNMP
;
1365 m_dwDynamicFlags
&= ~NDF_SNMP_UNREACHABLE
;
1366 m_szObjectId
[0] = 0;
1367 sendPollerMsg(dwRqId
, POLLER_WARNING
_T("Attribute isSNMP set to FALSE\r\n"));
1372 m_dwDynamicFlags
|= NDF_SNMP_UNREACHABLE
;
1373 PostEventEx(pQueue
, EVENT_SNMP_FAIL
, m_id
, NULL
);
1374 m_failTimeSNMP
= tNow
;
1381 DbgPrintf(6, _T("StatusPoll(%s): cannot create SNMP transport"), m_name
);
1383 DbgPrintf(6, _T("StatusPoll(%s): SNMP check finished"), m_name
);
1386 // Check native agent connectivity
1387 if ((m_flags
& NF_IS_NATIVE_AGENT
) && (!(m_flags
& NF_DISABLE_NXCP
)) && m_ipAddress
.isValidUnicast())
1389 DbgPrintf(6, _T("StatusPoll(%s): checking agent"), m_name
);
1390 poller
->setStatus(_T("check agent"));
1391 sendPollerMsg(dwRqId
, _T("Checking NetXMS agent connectivity\r\n"));
1393 UINT32 error
, socketError
;
1396 if (connectToAgent(&error
, &socketError
, &newConnection
, true))
1398 DbgPrintf(7, _T("StatusPoll(%s): connected to agent"), m_name
);
1399 if (m_dwDynamicFlags
& NDF_AGENT_UNREACHABLE
)
1401 m_dwDynamicFlags
&= ~NDF_AGENT_UNREACHABLE
;
1402 PostEventEx(pQueue
, EVENT_AGENT_OK
, m_id
, NULL
);
1403 sendPollerMsg(dwRqId
, POLLER_INFO
_T("Connectivity with NetXMS agent restored\r\n"));
1408 DbgPrintf(6, _T("StatusPoll(%s): agent unreachable, error=%d, socketError=%d"), m_name
, (int)error
, (int)socketError
);
1409 sendPollerMsg(dwRqId
, POLLER_ERROR
_T("NetXMS agent unreachable\r\n"));
1410 if (m_dwDynamicFlags
& NDF_AGENT_UNREACHABLE
)
1412 if ((tNow
> m_failTimeAgent
+ tExpire
) && !(m_dwDynamicFlags
& NDF_UNREACHABLE
))
1414 m_flags
&= ~NF_IS_NATIVE_AGENT
;
1415 m_dwDynamicFlags
&= ~NDF_AGENT_UNREACHABLE
;
1416 m_szPlatformName
[0] = 0;
1417 m_szAgentVersion
[0] = 0;
1418 sendPollerMsg(dwRqId
, POLLER_WARNING
_T("Attribute isNetXMSAgent set to FALSE\r\n"));
1423 m_dwDynamicFlags
|= NDF_AGENT_UNREACHABLE
;
1424 PostEventEx(pQueue
, EVENT_AGENT_FAIL
, m_id
, NULL
);
1425 m_failTimeAgent
= tNow
;
1426 //cancel file monitoring locally(on agent it is canceled if agent have fallen)
1427 g_monitoringList
.removeDisconnectedNode(m_id
);
1431 DbgPrintf(7, _T("StatusPoll(%s): agent check finished"), m_name
);
1433 // If file update connection is active, send NOP command to prevent disconnection by idle timeout
1434 AgentConnection
*fileUpdateConnection
;
1436 fileUpdateConnection
= m_fileUpdateConn
;
1437 if (fileUpdateConnection
!= NULL
)
1438 fileUpdateConnection
->incRefCount();
1440 if (fileUpdateConnection
!= NULL
)
1442 nxlog_debug(6, _T("StatusPoll(%s): sending keepalive command on file monitoring connection"), m_name
);
1443 fileUpdateConnection
->nop();
1444 fileUpdateConnection
->decRefCount();
1448 poller
->setStatus(_T("prepare polling list"));
1450 // Find service poller node object
1452 if (m_pollerNode
!= 0)
1454 UINT32 id
= m_pollerNode
;
1456 pPollerNode
= FindObjectById(id
);
1457 if (pPollerNode
!= NULL
)
1459 if (pPollerNode
->getObjectClass() != OBJECT_NODE
)
1468 // If nothing found, use management server
1469 if (pPollerNode
== NULL
)
1471 pPollerNode
= FindObjectById(g_dwMgmtNode
);
1472 if (pPollerNode
!= NULL
)
1473 pPollerNode
->incRefCount();
1477 pPollerNode
->incRefCount();
1480 // Create polling list
1481 ppPollList
= (NetObj
**)malloc(sizeof(NetObj
*) * m_childList
->size());
1482 lockChildList(false);
1483 int pollListSize
= 0;
1484 for(int i
= 0; i
< m_childList
->size(); i
++)
1486 NetObj
*curr
= m_childList
->get(i
);
1487 if (curr
->getStatus() != STATUS_UNMANAGED
)
1489 curr
->incRefCount();
1490 ppPollList
[pollListSize
++] = curr
;
1495 // Poll interfaces and services
1496 poller
->setStatus(_T("child poll"));
1497 DbgPrintf(7, _T("StatusPoll(%s): starting child object poll"), m_name
);
1498 pCluster
= getMyCluster();
1499 pTransport
= createSnmpTransport();
1500 for(int i
= 0; i
< pollListSize
; i
++)
1502 switch(ppPollList
[i
]->getObjectClass())
1504 case OBJECT_INTERFACE
:
1505 DbgPrintf(7, _T("StatusPoll(%s): polling interface %d [%s]"), m_name
, ppPollList
[i
]->getId(), ppPollList
[i
]->getName());
1506 ((Interface
*)ppPollList
[i
])->statusPoll(pSession
, dwRqId
, pQueue
, pCluster
, pTransport
, m_icmpProxy
);
1508 case OBJECT_NETWORKSERVICE
:
1509 DbgPrintf(7, _T("StatusPoll(%s): polling network service %d [%s]"), m_name
, ppPollList
[i
]->getId(), ppPollList
[i
]->getName());
1510 ((NetworkService
*)ppPollList
[i
])->statusPoll(pSession
, dwRqId
, (Node
*)pPollerNode
, pQueue
);
1512 case OBJECT_ACCESSPOINT
:
1513 DbgPrintf(7, _T("StatusPoll(%s): polling access point %d [%s]"), m_name
, ppPollList
[i
]->getId(), ppPollList
[i
]->getName());
1514 ((AccessPoint
*)ppPollList
[i
])->statusPoll(pSession
, dwRqId
, pQueue
, this, pTransport
);
1517 DbgPrintf(7, _T("StatusPoll(%s): skipping object %d [%s] class %d"), m_name
, ppPollList
[i
]->getId(), ppPollList
[i
]->getName(), ppPollList
[i
]->getObjectClass());
1520 ppPollList
[i
]->decRefCount();
1523 safe_free(ppPollList
);
1524 DbgPrintf(7, _T("StatusPoll(%s): finished child object poll"), m_name
);
1526 // Check if entire node is down
1527 // This check is disabled for nodes without IP address
1528 if (m_ipAddress
.isValidUnicast())
1530 bool allDown
= true;
1531 lockChildList(false);
1532 for(int i
= 0; i
< m_childList
->size(); i
++)
1534 NetObj
*curr
= m_childList
->get(i
);
1535 if ((curr
->getObjectClass() == OBJECT_INTERFACE
) &&
1536 (((Interface
*)curr
)->getAdminState() != IF_ADMIN_STATE_DOWN
) &&
1537 (((Interface
*)curr
)->getConfirmedOperState() == IF_OPER_STATE_UP
) &&
1538 (curr
->getStatus() != STATUS_UNMANAGED
))
1545 if (allDown
&& (m_flags
& NF_IS_NATIVE_AGENT
) &&
1546 (!(m_flags
& NF_DISABLE_NXCP
)))
1547 if (!(m_dwDynamicFlags
& NDF_AGENT_UNREACHABLE
))
1549 if (allDown
&& (m_flags
& NF_IS_SNMP
) &&
1550 (!(m_flags
& NF_DISABLE_SNMP
)))
1551 if (!(m_dwDynamicFlags
& NDF_SNMP_UNREACHABLE
))
1554 DbgPrintf(6, _T("StatusPoll(%s): allDown=%s, dynFlags=0x%08X"), m_name
, allDown
? _T("true") : _T("false"), m_dwDynamicFlags
);
1557 if (!(m_dwDynamicFlags
& NDF_UNREACHABLE
))
1559 m_dwDynamicFlags
|= NDF_UNREACHABLE
;
1560 m_downSince
= time(NULL
);
1561 poller
->setStatus(_T("check network path"));
1562 if (checkNetworkPath(dwRqId
))
1564 m_dwDynamicFlags
|= NDF_NETWORK_PATH_PROBLEM
;
1566 // Set interfaces and network services to UNKNOWN state
1567 lockChildList(false);
1568 for(int i
= 0; i
< m_childList
->size(); i
++)
1570 NetObj
*curr
= m_childList
->get(i
);
1571 if (((curr
->getObjectClass() == OBJECT_INTERFACE
) || (curr
->getObjectClass() == OBJECT_NETWORKSERVICE
)) &&
1572 (curr
->getStatus() == STATUS_CRITICAL
))
1574 curr
->resetStatus();
1579 // Clear delayed event queue
1582 Event
*pEvent
= (Event
*)pQueue
->get();
1587 delete_and_null(pQueue
);
1589 PostEvent(EVENT_NODE_UNREACHABLE
, m_id
, NULL
);
1593 PostEvent(EVENT_NODE_DOWN
, m_id
, NULL
);
1595 sendPollerMsg(dwRqId
, POLLER_ERROR
_T("Node is unreachable\r\n"));
1599 sendPollerMsg(dwRqId
, POLLER_WARNING
_T("Node is still unreachable\r\n"));
1605 if (m_dwDynamicFlags
& NDF_UNREACHABLE
)
1607 int reason
= (m_dwDynamicFlags
& NDF_NETWORK_PATH_PROBLEM
) ? 1 : 0;
1608 m_dwDynamicFlags
&= ~(NDF_UNREACHABLE
| NDF_SNMP_UNREACHABLE
| NDF_AGENT_UNREACHABLE
| NDF_NETWORK_PATH_PROBLEM
);
1609 PostEvent(EVENT_NODE_UP
, m_id
, "d", reason
);
1610 sendPollerMsg(dwRqId
, POLLER_INFO
_T("Node recovered from unreachable state\r\n"));
1611 goto restart_agent_check
;
1615 sendPollerMsg(dwRqId
, POLLER_INFO
_T("Node is connected\r\n"));
1620 // Get uptime and update boot time
1621 if (!(m_dwDynamicFlags
& NDF_UNREACHABLE
))
1623 TCHAR buffer
[MAX_RESULT_LENGTH
];
1624 if (getItemFromAgent(_T("System.Uptime"), MAX_RESULT_LENGTH
, buffer
) == DCE_SUCCESS
)
1626 m_bootTime
= time(NULL
) - _tcstol(buffer
, NULL
, 0);
1627 DbgPrintf(5, _T("StatusPoll(%s [%d]): boot time set to %u from agent"), m_name
, m_id
, (UINT32
)m_bootTime
);
1629 else if (getItemFromSNMP(m_snmpPort
, _T(".1.3.6.1.2.1.1.3.0"), MAX_RESULT_LENGTH
, buffer
, SNMP_RAWTYPE_NONE
) == DCE_SUCCESS
)
1631 m_bootTime
= time(NULL
) - _tcstol(buffer
, NULL
, 0) / 100; // sysUpTime is in hundredths of a second
1632 DbgPrintf(5, _T("StatusPoll(%s [%d]): boot time set to %u from SNMP"), m_name
, m_id
, (UINT32
)m_bootTime
);
1636 DbgPrintf(5, _T("StatusPoll(%s [%d]): unable to get system uptime"), m_name
, m_id
);
1644 // Get agent uptime to check if it was restared
1645 if (!(m_dwDynamicFlags
& NDF_UNREACHABLE
))
1647 TCHAR buffer
[MAX_RESULT_LENGTH
];
1648 if (getItemFromAgent(_T("Agent.Uptime"), MAX_RESULT_LENGTH
, buffer
) == DCE_SUCCESS
)
1650 time_t oldAgentuptime
= m_agentUpTime
;
1651 m_agentUpTime
= _tcstol(buffer
, NULL
, 0);
1652 if ((UINT32
)oldAgentuptime
> (UINT32
)m_agentUpTime
)
1654 //cancel file monitoring locally(on agent it is canceled if agent have fallen)
1655 g_monitoringList
.removeDisconnectedNode(m_id
);
1660 DbgPrintf(5, _T("StatusPoll(%s [%d]): unable to get agent uptime"), m_name
, m_id
);
1661 g_monitoringList
.removeDisconnectedNode(m_id
);
1667 g_monitoringList
.removeDisconnectedNode(m_id
);
1672 if (!(m_dwDynamicFlags
& NDF_UNREACHABLE
))
1674 TCHAR buffer
[MAX_RESULT_LENGTH
];
1675 if (getItemFromAgent(_T("GPS.LocationData"), MAX_RESULT_LENGTH
, buffer
) == DCE_SUCCESS
)
1677 GeoLocation loc
= GeoLocation::parseAgentData(buffer
);
1678 if (loc
.getType() != GL_UNSET
)
1680 DbgPrintf(5, _T("StatusPoll(%s [%d]): location set to %s, %s from agent"), m_name
, m_id
, loc
.getLatitudeAsString(), loc
.getLongitudeAsString());
1682 m_geoLocation
= loc
;
1689 DbgPrintf(5, _T("StatusPoll(%s [%d]): unable to get system location"), m_name
, m_id
);
1693 // Get agent log and agent local database status
1694 if (!(m_dwDynamicFlags
& NDF_UNREACHABLE
))
1696 TCHAR buffer
[MAX_RESULT_LENGTH
];
1697 if (getItemFromAgent(_T("Agent.LogFile.Status"), MAX_RESULT_LENGTH
, buffer
) == DCE_SUCCESS
)
1699 UINT32 status
= _tcstol(buffer
, NULL
, 0);
1701 PostEvent(EVENT_AGENT_LOG_PROBLEM
, m_id
, "ds", status
, _T("could not open"));
1705 nxlog_debug(5, _T("StatusPoll(%s [%d]): unable to get agent log status"), m_name
, m_id
);
1708 if (getItemFromAgent(_T("Agent.LocalDatabase.Status"), MAX_RESULT_LENGTH
, buffer
) == DCE_SUCCESS
)
1710 UINT32 status
= _tcstol(buffer
, NULL
, 0);
1711 const TCHAR
*statusDescription
[3]= {
1713 _T("could not open database"),
1714 _T("could not update database"),
1717 PostEvent(EVENT_AGENT_LOCAL_DATABASE_PROBLEM
, m_id
, "ds", status
, statusDescription
[status
]);
1721 nxlog_debug(5, _T("StatusPoll(%s [%d]): unable to get agent local database status"), m_name
, m_id
);
1725 // Send delayed events and destroy delayed event queue
1728 ResendEvents(pQueue
);
1732 // Call hooks in loaded modules
1733 for(UINT32 i
= 0; i
< g_dwNumModules
; i
++)
1735 if (g_pModuleList
[i
].pfStatusPollHook
!= NULL
)
1737 DbgPrintf(5, _T("StatusPoll(%s [%d]): calling hook in module %s"), m_name
, m_id
, g_pModuleList
[i
].szName
);
1738 g_pModuleList
[i
].pfStatusPollHook(this, pSession
, dwRqId
, poller
);
1742 // Execute hook script
1743 poller
->setStatus(_T("hook"));
1744 executeHookScript(_T("StatusPoll"));
1746 poller
->setStatus(_T("cleanup"));
1747 if (pPollerNode
!= NULL
)
1748 pPollerNode
->decRefCount();
1750 if (dwOldFlags
!= m_flags
)
1752 PostEvent(EVENT_NODE_FLAGS_CHANGED
, m_id
, "xx", dwOldFlags
, m_flags
);
1758 calculateCompoundStatus();
1759 m_lastStatusPoll
= time(NULL
);
1760 sendPollerMsg(dwRqId
, _T("Finished status poll for node %s\r\n"), m_name
);
1761 sendPollerMsg(dwRqId
, _T("Node status after poll is %s\r\n"), GetStatusAsText(m_status
, true));
1762 m_pollRequestor
= NULL
;
1764 m_dwDynamicFlags
&= ~NDF_QUEUED_FOR_STATUS_POLL
;
1766 DbgPrintf(5, _T("Finished status poll for node %s (ID: %d)"), m_name
, m_id
);
1770 * Check single element of network path
1772 bool Node::checkNetworkPathElement(UINT32 nodeId
, const TCHAR
*nodeType
, bool isProxy
, UINT32 dwRqId
)
1774 Node
*node
= (Node
*)FindObjectById(nodeId
, OBJECT_NODE
);
1778 DbgPrintf(6, _T("Node::checkNetworkPathElement(%s [%d]): found %s: %s [%d]"), m_name
, m_id
, nodeType
, node
->getName(), node
->getId());
1781 DbgPrintf(5, _T("Node::checkNetworkPathElement(%s [%d]): %s %s [%d] is down"),
1782 m_name
, m_id
, nodeType
, node
->getName(), node
->getId());
1783 sendPollerMsg(dwRqId
, POLLER_WARNING
_T(" %s %s is down\r\n"), nodeType
, node
->getName());
1786 if (isProxy
&& node
->isNativeAgent() && (node
->getRuntimeFlags() & NDF_AGENT_UNREACHABLE
))
1788 DbgPrintf(5, _T("Node::checkNetworkPathElement(%s [%d]): agent on %s %s [%d] is down"),
1789 m_name
, m_id
, nodeType
, node
->getName(), node
->getId());
1790 sendPollerMsg(dwRqId
, POLLER_WARNING
_T(" Agent on %s %s is down\r\n"), nodeType
, node
->getName());
1793 if (node
->m_lastStatusPoll
< time(NULL
) - 1)
1795 DbgPrintf(6, _T("Node::checkNetworkPathElement(%s [%d]): forced status poll on node %s [%d]"),
1796 m_name
, m_id
, node
->getName(), node
->getId());
1797 PollerInfo
*poller
= RegisterPoller(POLLER_TYPE_STATUS
, node
);
1798 poller
->startExecution();
1799 node
->statusPoll(NULL
, 0, poller
);
1803 DbgPrintf(5, _T("Node::checkNetworkPathElement(%s [%d]): %s %s [%d] is down"),
1804 m_name
, m_id
, nodeType
, node
->getName(), node
->getId());
1805 sendPollerMsg(dwRqId
, POLLER_WARNING
_T(" %s %s is down\r\n"), nodeType
, node
->getName());
1808 if (isProxy
&& node
->isNativeAgent() && (node
->getRuntimeFlags() & NDF_AGENT_UNREACHABLE
))
1810 DbgPrintf(5, _T("Node::checkNetworkPathElement(%s [%d]): agent on %s %s [%d] is down"),
1811 m_name
, m_id
, nodeType
, node
->getName(), node
->getId());
1812 sendPollerMsg(dwRqId
, POLLER_WARNING
_T(" Agent on %s %s is down\r\n"), nodeType
, node
->getName());
1820 * Check network path between node and management server to detect possible intermediate node failure
1822 * @return true if network path problems found
1824 bool Node::checkNetworkPath(UINT32 dwRqId
)
1826 time_t now
= time(NULL
);
1828 // Check proxy node(s)
1829 if (IsZoningEnabled() && (m_zoneId
!= 0))
1831 Zone
*zone
= (Zone
*)g_idxZoneByGUID
.get(m_zoneId
);
1832 if ((zone
!= NULL
) && (zone
->getProxyNodeId() != 0) &&
1833 checkNetworkPathElement(zone
->getProxyNodeId(), _T("zone proxy"), true, dwRqId
))
1837 // Check directly connected switch
1838 sendPollerMsg(dwRqId
, _T("Checking ethernet connectivity...\r\n"));
1839 Interface
*iface
= findInterfaceByIP(m_ipAddress
);
1840 if ((iface
!= NULL
) && (iface
->getPeerNodeId() != 0))
1842 DbgPrintf(6, _T("Node::checkNetworkPath(%s [%d]): found interface object for primary IP: %s [%d]"), m_name
, m_id
, iface
->getName(), iface
->getId());
1843 if (checkNetworkPathElement(iface
->getPeerNodeId(), _T("upstream switch"), false, dwRqId
))
1848 DbgPrintf(5, _T("Node::checkNetworkPath(%s [%d]): cannot find interface object for primary IP"), m_name
, m_id
);
1851 Node
*mgmtNode
= (Node
*)FindObjectById(g_dwMgmtNode
);
1852 if (mgmtNode
== NULL
)
1854 DbgPrintf(5, _T("Node::checkNetworkPath(%s [%d]): cannot find management node"), m_name
, m_id
);
1858 NetworkPath
*trace
= TraceRoute(mgmtNode
, this);
1861 DbgPrintf(5, _T("Node::checkNetworkPath(%s [%d]): trace not available"), m_name
, m_id
);
1864 DbgPrintf(5, _T("Node::checkNetworkPath(%s [%d]): trace available, %d hops, %s"),
1865 m_name
, m_id
, trace
->getHopCount(), trace
->isComplete() ? _T("complete") : _T("incomplete"));
1867 // We will do path check in two passes
1868 // If unreachable intermediate node will be found on first pass,
1869 // then method will just return true. Otherwise, we will do
1870 // second pass, this time forcing status poll on each node in the path.
1871 sendPollerMsg(dwRqId
, _T("Checking network path...\r\n"));
1872 bool secondPass
= false;
1873 bool pathProblemFound
= false;
1875 for(int i
= 0; i
< trace
->getHopCount(); i
++)
1877 HOP_INFO
*hop
= trace
->getHopInfo(i
);
1878 if ((hop
->object
== NULL
) || (hop
->object
== this) || (hop
->object
->getObjectClass() != OBJECT_NODE
))
1881 DbgPrintf(6, _T("Node::checkNetworkPath(%s [%d]): checking upstream node %s [%d]"),
1882 m_name
, m_id
, hop
->object
->getName(), hop
->object
->getId());
1883 if (secondPass
&& !((Node
*)hop
->object
)->isDown() && (((Node
*)hop
->object
)->m_lastStatusPoll
< now
- 1))
1885 DbgPrintf(6, _T("Node::checkNetworkPath(%s [%d]): forced status poll on node %s [%d]"),
1886 m_name
, m_id
, hop
->object
->getName(), hop
->object
->getId());
1887 PollerInfo
*poller
= RegisterPoller(POLLER_TYPE_STATUS
, (Node
*)hop
->object
);
1888 poller
->startExecution();
1889 ((Node
*)hop
->object
)->statusPoll(NULL
, 0, poller
);
1893 if (((Node
*)hop
->object
)->isDown())
1895 DbgPrintf(5, _T("Node::checkNetworkPath(%s [%d]): upstream node %s [%d] is down"),
1896 m_name
, m_id
, hop
->object
->getName(), hop
->object
->getId());
1897 sendPollerMsg(dwRqId
, POLLER_WARNING
_T(" Upstream node %s is down\r\n"), hop
->object
->getName());
1898 pathProblemFound
= true;
1902 if (!secondPass
&& !pathProblemFound
)
1904 DbgPrintf(5, _T("Node::checkNetworkPath(%s [%d]): will do second pass"), m_name
, m_id
);
1909 return pathProblemFound
;
1913 * Check agent policy binding
1914 * Intended to be called only from configuration poller
1916 void Node::checkAgentPolicyBinding(AgentConnection
*conn
)
1918 AgentPolicyInfo
*ap
;
1919 UINT32 rcc
= conn
->getPolicyInventory(&ap
);
1920 if (rcc
== ERR_SUCCESS
)
1922 // Check for unbound but installed policies
1923 for(int i
= 0; i
< ap
->size(); i
++)
1925 uuid guid
= ap
->getGuid(i
);
1926 NetObj
*object
= FindObjectByGUID(guid
, -1);
1927 if ((object
!= NULL
) && (!object
->isChild(m_id
)))
1929 object
->addChild(this);
1931 DbgPrintf(5, _T("ConfPoll(%s): bound to policy object %s [%d]"), m_name
, object
->getName(), object
->getId());
1935 // Check for bound but not installed policies and schedule it's installation again
1936 //Job will be unbound if it was not possible to add job
1937 lockParentList(false);
1938 NetObj
**unbindList
= (NetObj
**)malloc(sizeof(NetObj
*) * m_parentList
->size());
1939 int unbindListSize
= 0;
1940 for(int i
= 0; i
< m_parentList
->size(); i
++)
1942 if (IsAgentPolicyObject(m_parentList
->get(i
)))
1944 const uuid
& guid
= m_parentList
->get(i
)->getGuid();
1946 for(j
= 0; j
< ap
->size(); j
++)
1948 if (ap
->getGuid(j
).equals(guid
))
1951 if (j
== ap
->size())
1953 ServerJob
*job
= new PolicyDeploymentJob(this, (AgentPolicy
*)m_parentList
->get(i
), 0); //TODO: change to system user
1956 DbgPrintf(5, _T("ConfPoll(%s): \"%s\" policy deploy scheduled for \"%s\" node"), m_name
, m_parentList
->get(i
)->getName(), m_name
);
1960 DbgPrintf(5, _T("ConfPoll(%s): \"%s\" policy deploy is not possible to scheduled for \"%s\" node"), m_name
, m_parentList
->get(i
)->getName(), m_name
);
1962 unbindList
[unbindListSize
++] = m_parentList
->get(i
);
1969 for(int i
= 0; i
< unbindListSize
; i
++)
1971 unbindList
[i
]->deleteChild(this);
1972 deleteParent(unbindList
[i
]);
1973 DbgPrintf(5, _T("ConfPoll(%s): unbound from policy object %s [%d]"), m_name
, unbindList
[i
]->getName(), unbindList
[i
]->getId());
1975 safe_free(unbindList
);
1981 DbgPrintf(5, _T("ConfPoll(%s): AgentConnection::getPolicyInventory() failed: rcc=%d"), m_name
, rcc
);
1986 * Update primary IP address from primary name
1988 void Node::updatePrimaryIpAddr()
1990 if (m_primaryName
[0] == 0)
1993 InetAddress ipAddr
= ResolveHostName(m_zoneId
, m_primaryName
);
1994 if (!ipAddr
.equals(m_ipAddress
) && (ipAddr
.isValidUnicast() || !_tcscmp(m_primaryName
, _T("0.0.0.0"))))
1996 TCHAR buffer1
[64], buffer2
[64];
1998 DbgPrintf(4, _T("IP address for node %s [%d] changed from %s to %s"),
1999 m_name
, (int)m_id
, m_ipAddress
.toString(buffer1
), ipAddr
.toString(buffer2
));
2000 PostEvent(EVENT_IP_ADDRESS_CHANGED
, m_id
, "AA", &ipAddr
, &m_ipAddress
);
2002 if (m_flags
& NF_REMOTE_AGENT
)
2005 m_ipAddress
= ipAddr
;
2011 setPrimaryIPAddress(ipAddr
);
2015 deleteAgentConnection();
2021 * Entry point for configuration poller
2023 void Node::configurationPoll(PollerInfo
*poller
)
2025 poller
->startExecution();
2026 ObjectTransactionStart();
2027 configurationPoll(NULL
, 0, poller
, 0);
2028 ObjectTransactionEnd();
2033 * Perform configuration poll on node
2035 void Node::configurationPoll(ClientSession
*pSession
, UINT32 dwRqId
, PollerInfo
*poller
, int maskBits
)
2037 if (m_dwDynamicFlags
& NDF_DELETE_IN_PROGRESS
)
2040 m_dwDynamicFlags
&= ~NDF_QUEUED_FOR_CONFIG_POLL
;
2044 if (IsShutdownInProgress())
2047 UINT32 dwOldFlags
= m_flags
;
2048 TCHAR szBuffer
[4096];
2049 bool hasChanges
= false;
2051 poller
->setStatus(_T("wait for lock"));
2054 if (IsShutdownInProgress())
2060 m_pollRequestor
= pSession
;
2061 sendPollerMsg(dwRqId
, _T("Starting configuration poll for node %s\r\n"), m_name
);
2062 DbgPrintf(4, _T("Starting configuration poll for node %s (ID: %d)"), m_name
, m_id
);
2064 // Check for forced capabilities recheck
2065 if (m_dwDynamicFlags
& NDF_RECHECK_CAPABILITIES
)
2067 sendPollerMsg(dwRqId
, POLLER_WARNING
_T("Capability reset\r\n"));
2068 m_flags
&= ~(NF_IS_NATIVE_AGENT
| NF_IS_SNMP
| NF_IS_CPSNMP
|
2069 NF_IS_BRIDGE
| NF_IS_ROUTER
| NF_IS_OSPF
| NF_IS_PRINTER
|
2070 NF_IS_CDP
| NF_IS_LLDP
| NF_IS_SONMP
| NF_IS_VRRP
| NF_HAS_VLANS
|
2071 NF_IS_8021X
| NF_IS_STP
| NF_HAS_ENTITY_MIB
| NF_HAS_IFXTABLE
|
2073 m_dwDynamicFlags
&= ~NDF_CONFIGURATION_POLL_PASSED
;
2074 m_szObjectId
[0] = 0;
2075 m_szPlatformName
[0] = 0;
2076 m_szAgentVersion
[0] = 0;
2077 safe_free_and_null(m_sysDescription
);
2078 safe_free_and_null(m_sysName
);
2079 safe_free_and_null(m_sysContact
);
2080 safe_free_and_null(m_sysLocation
);
2081 safe_free_and_null(m_lldpNodeId
);
2084 // Check if node is marked as unreachable
2085 if ((m_dwDynamicFlags
& NDF_UNREACHABLE
) && !(m_dwDynamicFlags
& NDF_RECHECK_CAPABILITIES
))
2087 sendPollerMsg(dwRqId
, POLLER_WARNING
_T("Node is marked as unreachable, configuration poll aborted\r\n"));
2088 DbgPrintf(4, _T("Node is marked as unreachable, configuration poll aborted"));
2089 m_lastConfigurationPoll
= time(NULL
);
2093 updatePrimaryIpAddr();
2095 poller
->setStatus(_T("capability check"));
2096 sendPollerMsg(dwRqId
, _T("Checking node's capabilities...\r\n"));
2098 if (confPollAgent(dwRqId
))
2100 if (confPollSnmp(dwRqId
))
2103 // Check for CheckPoint SNMP agent on port 260
2104 if (ConfigReadInt(_T("EnableCheckPointSNMP"), 0))
2106 DbgPrintf(5, _T("ConfPoll(%s): checking for CheckPoint SNMP on port 260"), m_name
);
2107 if (!((m_flags
& NF_IS_CPSNMP
) && (m_dwDynamicFlags
& NDF_CPSNMP_UNREACHABLE
)) && m_ipAddress
.isValidUnicast())
2109 SNMP_Transport
*pTransport
= new SNMP_UDPTransport
;
2110 ((SNMP_UDPTransport
*)pTransport
)->createUDPTransport(m_ipAddress
, CHECKPOINT_SNMP_PORT
);
2111 if (SnmpGet(SNMP_VERSION_1
, pTransport
,
2112 _T(".1.3.6.1.4.1.2620.1.1.10.0"), NULL
, 0, szBuffer
, sizeof(szBuffer
), 0) == SNMP_ERR_SUCCESS
)
2115 m_flags
|= NF_IS_CPSNMP
| NF_IS_ROUTER
;
2116 m_dwDynamicFlags
&= ~NDF_CPSNMP_UNREACHABLE
;
2118 sendPollerMsg(dwRqId
, POLLER_INFO
_T(" CheckPoint SNMP agent on port 260 is active\r\n"));
2124 // Generate event if node flags has been changed
2125 if (dwOldFlags
!= m_flags
)
2127 PostEvent(EVENT_NODE_FLAGS_CHANGED
, m_id
, "xx", dwOldFlags
, m_flags
);
2131 // Retrieve interface list
2132 poller
->setStatus(_T("interface check"));
2133 sendPollerMsg(dwRqId
, _T("Capability check finished\r\n"));
2135 if (updateInterfaceConfiguration(dwRqId
, maskBits
))
2138 m_lastConfigurationPoll
= time(NULL
);
2141 sendPollerMsg(dwRqId
, _T("Checking node name\r\n"));
2142 UINT32 dwAddr
= ntohl(_t_inet_addr(m_name
));
2143 if ((g_flags
& AF_RESOLVE_NODE_NAMES
) &&
2144 (dwAddr
!= INADDR_NONE
) &&
2145 (dwAddr
!= INADDR_ANY
) &&
2148 sendPollerMsg(dwRqId
, _T("Node name is an IP address and need to be resolved\r\n"));
2149 poller
->setStatus(_T("resolving name"));
2150 if (resolveName(FALSE
))
2152 sendPollerMsg(dwRqId
, POLLER_INFO
_T("Node name resolved to %s\r\n"), m_name
);
2157 sendPollerMsg(dwRqId
, POLLER_WARNING
_T("Node name cannot be resolved\r\n"));
2162 if (g_flags
& AF_SYNC_NODE_NAMES_WITH_DNS
)
2164 sendPollerMsg(dwRqId
, _T("Syncing node name with DNS\r\n"));
2165 poller
->setStatus(_T("resolving name"));
2166 if (resolveName(TRUE
))
2168 sendPollerMsg(dwRqId
, POLLER_INFO
_T("Node name resolved to %s\r\n"), m_name
);
2174 sendPollerMsg(dwRqId
, _T("Node name is OK\r\n"));
2178 applyUserTemplates();
2179 updateContainerMembership();
2181 // Get list of installed products
2182 if (m_flags
& NF_IS_NATIVE_AGENT
)
2184 poller
->setStatus(_T("software check"));
2185 sendPollerMsg(dwRqId
, _T("Reading list of installed software packages\r\n"));
2188 if (getTableFromAgent(_T("System.InstalledProducts"), &table
) == DCE_SUCCESS
)
2191 delete m_softwarePackages
;
2192 m_softwarePackages
= new ObjectArray
<SoftwarePackage
>(table
->getNumRows(), 16, true);
2193 for(int i
= 0; i
< table
->getNumRows(); i
++)
2194 m_softwarePackages
->add(new SoftwarePackage(table
, i
));
2197 sendPollerMsg(dwRqId
, POLLER_INFO
_T("Got information about %d installed software packages\r\n"), m_softwarePackages
->size());
2201 delete_and_null(m_softwarePackages
);
2202 sendPollerMsg(dwRqId
, POLLER_WARNING
_T("Unable to get information about installed software packages\r\n"));
2206 // Call hooks in loaded modules
2207 for(UINT32 i
= 0; i
< g_dwNumModules
; i
++)
2209 if (g_pModuleList
[i
].pfConfPollHook
!= NULL
)
2211 DbgPrintf(5, _T("ConfigurationPoll(%s [%d]): calling hook in module %s"), m_name
, m_id
, g_pModuleList
[i
].szName
);
2212 if (g_pModuleList
[i
].pfConfPollHook(this, pSession
, dwRqId
, poller
))
2217 // Setup permanent connection to agent if not present (needed for proper configuration re-sync)
2218 if (m_flags
& NF_IS_NATIVE_AGENT
)
2226 NodeType type
= detectNodeType();
2227 nxlog_debug(5, _T("ConfPoll(%s): detected node type: %d (%s)"), m_name
, type
, typeName(type
));
2229 if ((type
!= NODE_TYPE_UNKNOWN
) && (type
!= m_type
))
2233 nxlog_debug(5, _T("ConfPoll(%s): node type set to %d (%s)"), m_name
, type
, typeName(type
));
2234 sendPollerMsg(dwRqId
, _T(" Node type changed to %s\r\n"), typeName(type
));
2238 // Execute hook script
2239 poller
->setStatus(_T("hook"));
2240 executeHookScript(_T("ConfigurationPoll"));
2242 sendPollerMsg(dwRqId
, _T("Finished configuration poll for node %s\r\n"), m_name
);
2243 sendPollerMsg(dwRqId
, _T("Node configuration was%schanged after poll\r\n"), hasChanges
? _T(" ") : _T(" not "));
2245 m_dwDynamicFlags
|= NDF_CONFIGURATION_POLL_PASSED
;
2248 // Finish configuration poll
2249 poller
->setStatus(_T("cleanup"));
2251 m_dwDynamicFlags
&= ~NDF_QUEUED_FOR_CONFIG_POLL
;
2252 m_dwDynamicFlags
&= ~NDF_RECHECK_CAPABILITIES
;
2254 DbgPrintf(4, _T("Finished configuration poll for node %s (ID: %d)"), m_name
, m_id
);
2267 NodeType
Node::detectNodeType()
2269 NodeType type
= NODE_TYPE_UNKNOWN
;
2270 if (m_flags
& NF_IS_SNMP
)
2272 nxlog_debug(6, _T("Node::detectNodeType(%s [%d]): SNMP node, driver name is %s"), m_name
, m_id
, m_driver
->getName());
2274 // Assume physical device if it supports SNMP and driver is not "GENERIC"
2275 // FIXME: add driver method to determine node type
2276 if (_tcscmp(m_driver
->getName(), _T("GENERIC")))
2278 type
= NODE_TYPE_PHYSICAL
;
2282 if (m_flags
& NF_IS_PRINTER
)
2284 // Assume that printers are physical devices
2285 type
= NODE_TYPE_PHYSICAL
;
2293 * Configuration poll: check for NetXMS agent
2295 bool Node::confPollAgent(UINT32 dwRqId
)
2297 DbgPrintf(5, _T("ConfPoll(%s): checking for NetXMS agent Flags={%08X} DynamicFlags={%08X}"), m_name
, m_flags
, m_dwDynamicFlags
);
2298 if (((m_flags
& NF_IS_NATIVE_AGENT
) && (m_dwDynamicFlags
& NDF_AGENT_UNREACHABLE
)) ||
2299 !m_ipAddress
.isValidUnicast() || (m_flags
& NF_DISABLE_NXCP
))
2302 bool hasChanges
= false;
2304 sendPollerMsg(dwRqId
, _T(" Checking NetXMS agent...\r\n"));
2305 AgentConnection
*pAgentConn
= new AgentConnectionEx(m_id
, m_ipAddress
, m_agentPort
, m_agentAuthMethod
, m_szSharedSecret
);
2306 setAgentProxy(pAgentConn
);
2307 DbgPrintf(5, _T("ConfPoll(%s): checking for NetXMS agent - connecting"), m_name
);
2309 // Try to connect to agent
2311 if (!pAgentConn
->connect(g_pServerKey
, FALSE
, &rcc
))
2313 // If there are authentication problem, try default shared secret
2314 if ((rcc
== ERR_AUTH_REQUIRED
) || (rcc
== ERR_AUTH_FAILED
))
2316 TCHAR secret
[MAX_SECRET_LENGTH
];
2317 ConfigReadStr(_T("AgentDefaultSharedSecret"), secret
, MAX_SECRET_LENGTH
, _T("netxms"));
2318 DecryptPassword(_T("netxms"), secret
, secret
, MAX_SECRET_LENGTH
);
2319 pAgentConn
->setAuthData(AUTH_SHA1_HASH
, secret
);
2320 if (pAgentConn
->connect(g_pServerKey
, FALSE
, &rcc
))
2322 m_agentAuthMethod
= AUTH_SHA1_HASH
;
2323 nx_strncpy(m_szSharedSecret
, secret
, MAX_SECRET_LENGTH
);
2324 DbgPrintf(5, _T("ConfPoll(%s): checking for NetXMS agent - shared secret changed to system default"), m_name
);
2329 if (rcc
== ERR_SUCCESS
)
2331 DbgPrintf(5, _T("ConfPoll(%s): checking for NetXMS agent - connected"), m_name
);
2333 m_flags
|= NF_IS_NATIVE_AGENT
;
2334 if (m_dwDynamicFlags
& NDF_AGENT_UNREACHABLE
)
2336 m_dwDynamicFlags
&= ~NDF_AGENT_UNREACHABLE
;
2337 PostEvent(EVENT_AGENT_OK
, m_id
, NULL
);
2338 sendPollerMsg(dwRqId
, POLLER_INFO
_T(" Connectivity with NetXMS agent restored\r\n"));
2342 sendPollerMsg(dwRqId
, POLLER_INFO
_T(" NetXMS native agent is active\r\n"));
2346 TCHAR buffer
[MAX_RESULT_LENGTH
];
2347 if (pAgentConn
->getParameter(_T("Agent.Version"), MAX_AGENT_VERSION_LEN
, buffer
) == ERR_SUCCESS
)
2350 if (_tcscmp(m_szAgentVersion
, buffer
))
2352 _tcscpy(m_szAgentVersion
, buffer
);
2354 sendPollerMsg(dwRqId
, _T(" NetXMS agent version changed to %s\r\n"), m_szAgentVersion
);
2359 if (pAgentConn
->getParameter(_T("System.PlatformName"), MAX_PLATFORM_NAME_LEN
, buffer
) == ERR_SUCCESS
)
2362 if (_tcscmp(m_szPlatformName
, buffer
))
2364 _tcscpy(m_szPlatformName
, buffer
);
2366 sendPollerMsg(dwRqId
, _T(" Platform name changed to %s\r\n"), m_szPlatformName
);
2371 // Check IP forwarding status
2372 if (pAgentConn
->getParameter(_T("Net.IP.Forwarding"), 16, buffer
) == ERR_SUCCESS
)
2374 if (_tcstoul(buffer
, NULL
, 10) != 0)
2375 m_flags
|= NF_IS_ROUTER
;
2377 m_flags
&= ~NF_IS_ROUTER
;
2381 if (pAgentConn
->getParameter(_T("System.Uname"), MAX_DB_STRING
, buffer
) == ERR_SUCCESS
)
2383 TranslateStr(buffer
, _T("\r\n"), _T(" "));
2384 TranslateStr(buffer
, _T("\n"), _T(" "));
2385 TranslateStr(buffer
, _T("\r"), _T(" "));
2387 if ((m_sysDescription
== NULL
) || _tcscmp(m_sysDescription
, buffer
))
2389 safe_free(m_sysDescription
);
2390 m_sysDescription
= _tcsdup(buffer
);
2392 sendPollerMsg(dwRqId
, _T(" System description changed to %s\r\n"), m_sysDescription
);
2397 // Check for 64 bit counter support.
2398 // if Net.Interface.64BitCounters not supported by agent then use
2399 // only presence of 64 bit parameters as indicator
2400 bool netIf64bitCounters
= true;
2401 if (pAgentConn
->getParameter(_T("Net.Interface.64BitCounters"), MAX_DB_STRING
, buffer
) == ERR_SUCCESS
)
2403 netIf64bitCounters
= _tcstol(buffer
, NULL
, 10) ? true : false;
2406 ObjectArray
<AgentParameterDefinition
> *plist
;
2407 ObjectArray
<AgentTableDefinition
> *tlist
;
2408 UINT32 rcc
= pAgentConn
->getSupportedParameters(&plist
, &tlist
);
2409 if (rcc
== ERR_SUCCESS
)
2414 m_paramList
= plist
;
2415 m_tableList
= tlist
;
2417 // Check for 64-bit interface counters
2418 m_flags
&= ~NF_HAS_AGENT_IFXCOUNTERS
;
2419 if (netIf64bitCounters
)
2421 for(int i
= 0; i
< plist
->size(); i
++)
2423 if (!_tcsicmp(plist
->get(i
)->getName(), _T("Net.Interface.BytesIn64(*)")))
2425 m_flags
|= NF_HAS_AGENT_IFXCOUNTERS
;
2435 DbgPrintf(5, _T("ConfPoll(%s): AgentConnection::getSupportedParameters() failed: rcc=%d"), m_name
, rcc
);
2438 // Get supported Windows Performance Counters
2439 if (!_tcsncmp(m_szPlatformName
, _T("windows-"), 8))
2441 sendPollerMsg(dwRqId
, _T(" Reading list of available Windows Performance Counters...\r\n"));
2442 ObjectArray
<WinPerfObject
> *perfObjects
= WinPerfObject::getWinPerfObjectsFromNode(this, pAgentConn
);
2444 delete m_winPerfObjects
;
2445 m_winPerfObjects
= perfObjects
;
2446 if (m_winPerfObjects
!= NULL
)
2448 sendPollerMsg(dwRqId
, POLLER_INFO
_T(" %d counters read\r\n"), m_winPerfObjects
->size());
2449 if (!(m_flags
& NF_HAS_WINPDH
))
2451 m_flags
|= NF_HAS_WINPDH
;
2457 sendPollerMsg(dwRqId
, POLLER_ERROR
_T(" unable to get Windows Performance Counters list\r\n"));
2458 if (m_flags
& NF_HAS_WINPDH
)
2460 m_flags
&= ~NF_HAS_WINPDH
;
2467 checkAgentPolicyBinding(pAgentConn
);
2469 pAgentConn
->disconnect();
2473 DbgPrintf(5, _T("ConfPoll(%s): checking for NetXMS agent - failed to connect (error %d)"), m_name
, rcc
);
2475 pAgentConn
->decRefCount();
2476 DbgPrintf(5, _T("ConfPoll(%s): checking for NetXMS agent - finished"), m_name
);
2481 * SNMP walker callback which sets indicator to true after first varbind and aborts walk
2483 static UINT32
IndicatorSnmpWalkerCallback(SNMP_Variable
*var
, SNMP_Transport
*transport
, void *arg
)
2485 (*((bool *)arg
)) = true;
2486 return SNMP_ERR_COMM
;
2490 * Configuration poll: check for SNMP
2492 bool Node::confPollSnmp(UINT32 dwRqId
)
2494 if (((m_flags
& NF_IS_SNMP
) && (m_dwDynamicFlags
& NDF_SNMP_UNREACHABLE
)) ||
2495 !m_ipAddress
.isValidUnicast() || (m_flags
& NF_DISABLE_SNMP
))
2498 bool hasChanges
= false;
2500 sendPollerMsg(dwRqId
, _T(" Checking SNMP...\r\n"));
2501 DbgPrintf(5, _T("ConfPoll(%s): calling SnmpCheckCommSettings()"), m_name
);
2503 const TCHAR
*customOid
= m_customAttributes
.get(_T("snmp.testoid"));
2504 if (customOid
!= NULL
)
2505 oids
.add(customOid
);
2506 oids
.add(_T(".1.3.6.1.2.1.1.2.0"));
2507 oids
.add(_T(".1.3.6.1.2.1.1.1.0"));
2508 AddDriverSpecificOids(&oids
);
2509 SNMP_Transport
*pTransport
= SnmpCheckCommSettings(getEffectiveSnmpProxy(), (getEffectiveSnmpProxy() == m_id
) ? InetAddress::LOOPBACK
: m_ipAddress
, &m_snmpVersion
, m_snmpPort
, m_snmpSecurity
, &oids
);
2510 if (pTransport
== NULL
)
2512 DbgPrintf(5, _T("ConfPoll(%s): unable to create SNMP transport"), m_name
);
2517 m_snmpPort
= pTransport
->getPort();
2518 delete m_snmpSecurity
;
2519 m_snmpSecurity
= new SNMP_SecurityContext(pTransport
->getSecurityContext());
2520 m_flags
|= NF_IS_SNMP
;
2521 if (m_dwDynamicFlags
& NDF_SNMP_UNREACHABLE
)
2523 m_dwDynamicFlags
&= ~NDF_SNMP_UNREACHABLE
;
2524 PostEvent(EVENT_SNMP_OK
, m_id
, NULL
);
2525 sendPollerMsg(dwRqId
, POLLER_INFO
_T(" Connectivity with SNMP agent restored\r\n"));
2528 sendPollerMsg(dwRqId
, _T(" SNMP agent is active (version %s)\r\n"),
2529 (m_snmpVersion
== SNMP_VERSION_3
) ? _T("3") : ((m_snmpVersion
== SNMP_VERSION_2C
) ? _T("2c") : _T("1")));
2531 TCHAR szBuffer
[4096];
2532 if (SnmpGet(m_snmpVersion
, pTransport
, _T(".1.3.6.1.2.1.1.2.0"), NULL
, 0, szBuffer
, sizeof(szBuffer
), SG_STRING_RESULT
) != SNMP_ERR_SUCCESS
)
2534 // Set snmp object ID to .0.0 if it cannot be read
2535 _tcscpy(szBuffer
, _T(".0.0"));
2538 if (_tcscmp(m_szObjectId
, szBuffer
))
2540 nx_strncpy(m_szObjectId
, szBuffer
, MAX_OID_LEN
* 4);
2545 // Get system description
2546 if (SnmpGet(m_snmpVersion
, pTransport
, _T(".1.3.6.1.2.1.1.1.0"), NULL
, 0, szBuffer
, sizeof(szBuffer
), SG_STRING_RESULT
) == SNMP_ERR_SUCCESS
)
2548 TranslateStr(szBuffer
, _T("\r\n"), _T(" "));
2549 TranslateStr(szBuffer
, _T("\n"), _T(" "));
2550 TranslateStr(szBuffer
, _T("\r"), _T(" "));
2552 if ((m_sysDescription
== NULL
) || _tcscmp(m_sysDescription
, szBuffer
))
2554 safe_free(m_sysDescription
);
2555 m_sysDescription
= _tcsdup(szBuffer
);
2557 sendPollerMsg(dwRqId
, _T(" System description changed to %s\r\n"), m_sysDescription
);
2562 // Select device driver
2563 NetworkDeviceDriver
*driver
= FindDriverForNode(this, pTransport
);
2564 DbgPrintf(5, _T("ConfPoll(%s): selected device driver %s"), m_name
, driver
->getName());
2566 if (driver
!= m_driver
)
2569 sendPollerMsg(dwRqId
, _T(" New network device driver selected: %s\r\n"), m_driver
->getName());
2573 // Allow driver to gather additional info
2574 m_driver
->analyzeDevice(pTransport
, m_szObjectId
, &m_customAttributes
, &m_driverData
);
2576 // Get sysName, sysContact, sysLocation
2577 if (querySnmpSysProperty(pTransport
, _T(".1.3.6.1.2.1.1.5.0"), _T("name"), dwRqId
, &m_sysName
))
2579 if (querySnmpSysProperty(pTransport
, _T(".1.3.6.1.2.1.1.4.0"), _T("contact"), dwRqId
, &m_sysContact
))
2581 if (querySnmpSysProperty(pTransport
, _T(".1.3.6.1.2.1.1.6.0"), _T("location"), dwRqId
, &m_sysLocation
))
2584 // Check IP forwarding
2585 if (checkSNMPIntegerValue(pTransport
, _T(".1.3.6.1.2.1.4.1.0"), 1))
2588 m_flags
|= NF_IS_ROUTER
;
2594 m_flags
&= ~NF_IS_ROUTER
;
2598 checkIfXTable(pTransport
);
2599 checkBridgeMib(pTransport
);
2601 // Check for ENTITY-MIB support
2602 if (SnmpGet(m_snmpVersion
, pTransport
, _T(".1.3.6.1.2.1.47.1.4.1.0"), NULL
, 0, szBuffer
, sizeof(szBuffer
), SG_RAW_RESULT
) == SNMP_ERR_SUCCESS
)
2605 m_flags
|= NF_HAS_ENTITY_MIB
;
2608 ComponentTree
*components
= BuildComponentTree(this, pTransport
);
2610 if (m_components
!= NULL
)
2611 m_components
->decRefCount();
2612 m_components
= components
;
2618 m_flags
&= ~NF_HAS_ENTITY_MIB
;
2619 if (m_components
!= NULL
)
2621 m_components
->decRefCount();
2622 m_components
= NULL
;
2627 // Check for printer MIB support
2628 bool present
= false;
2629 SnmpWalk(pTransport
, _T(".1.3.6.1.2.1.43"), IndicatorSnmpWalkerCallback
, &present
);
2633 m_flags
|= NF_IS_PRINTER
;
2639 m_flags
&= ~NF_IS_PRINTER
;
2643 // Check for CDP (Cisco Discovery Protocol) support
2644 if (checkSNMPIntegerValue(pTransport
, _T(".1.3.6.1.4.1.9.9.23.1.3.1.0"), 1))
2647 m_flags
|= NF_IS_CDP
;
2653 m_flags
&= ~NF_IS_CDP
;
2657 // Check for NDP (Nortel Discovery Protocol) support
2658 if (checkSNMPIntegerValue(pTransport
, _T(".1.3.6.1.4.1.45.1.6.13.1.2.0"), 1))
2661 m_flags
|= NF_IS_NDP
;
2667 m_flags
&= ~NF_IS_NDP
;
2671 // Check for LLDP (Link Layer Discovery Protocol) support
2672 if (SnmpGet(m_snmpVersion
, pTransport
, _T(".1.0.8802.1.1.2.1.3.2.0"), NULL
, 0, szBuffer
, sizeof(szBuffer
), 0) == SNMP_ERR_SUCCESS
)
2675 m_flags
|= NF_IS_LLDP
;
2681 if ((SnmpGetEx(pTransport
, _T(".1.0.8802.1.1.2.1.3.1.0"), NULL
, 0, &type
, sizeof(INT32
), 0, NULL
) == SNMP_ERR_SUCCESS
) &&
2682 (SnmpGetEx(pTransport
, _T(".1.0.8802.1.1.2.1.3.2.0"), NULL
, 0, data
, 256, SG_RAW_RESULT
, &dataLen
) == SNMP_ERR_SUCCESS
))
2684 BuildLldpId(type
, data
, dataLen
, szBuffer
, 1024);
2686 if ((m_lldpNodeId
== NULL
) || _tcscmp(m_lldpNodeId
, szBuffer
))
2688 safe_free(m_lldpNodeId
);
2689 m_lldpNodeId
= _tcsdup(szBuffer
);
2691 sendPollerMsg(dwRqId
, _T(" LLDP node ID changed to %s\r\n"), m_lldpNodeId
);
2696 ObjectArray
<LLDP_LOCAL_PORT_INFO
> *lldpPorts
= GetLLDPLocalPortInfo(pTransport
);
2698 delete m_lldpLocalPortInfo
;
2699 m_lldpLocalPortInfo
= lldpPorts
;
2705 m_flags
&= ~NF_IS_LLDP
;
2709 // Check for 802.1x support
2710 if (checkSNMPIntegerValue(pTransport
, _T(".1.0.8802.1.1.1.1.1.1.0"), 1))
2713 m_flags
|= NF_IS_8021X
;
2719 m_flags
&= ~NF_IS_8021X
;
2723 checkOSPFSupport(pTransport
);
2725 // Get VRRP information
2726 VrrpInfo
*vrrpInfo
= GetVRRPInfo(this);
2727 if (vrrpInfo
!= NULL
)
2730 m_flags
|= NF_IS_VRRP
;
2732 m_vrrpInfo
= vrrpInfo
;
2738 m_flags
&= ~NF_IS_VRRP
;
2742 // Get wireless controller data
2743 if ((m_driver
!= NULL
) && m_driver
->isWirelessController(pTransport
, &m_customAttributes
, m_driverData
))
2745 DbgPrintf(5, _T("ConfPoll(%s): node is wireless controller, reading access point information"), m_name
);
2746 sendPollerMsg(dwRqId
, _T(" Reading wireless access point information\r\n"));
2748 m_flags
|= NF_IS_WIFI_CONTROLLER
;
2751 int clusterMode
= m_driver
->getClusterMode(pTransport
, &m_customAttributes
, m_driverData
);
2753 ObjectArray
<AccessPointInfo
> *aps
= m_driver
->getAccessPoints(pTransport
, &m_customAttributes
, m_driverData
);
2756 sendPollerMsg(dwRqId
, POLLER_INFO
_T(" %d wireless access points found\r\n"), aps
->size());
2757 DbgPrintf(5, _T("ConfPoll(%s): got information about %d access points"), m_name
, aps
->size());
2759 for(int i
= 0; i
< aps
->size(); i
++)
2761 AccessPointInfo
*info
= aps
->get(i
);
2762 if (info
->getState() == AP_ADOPTED
)
2766 AccessPoint
*ap
= (clusterMode
== CLUSTER_MODE_STANDALONE
) ? findAccessPointByMAC(info
->getMacAddr()) : FindAccessPointByMAC(info
->getMacAddr());
2771 if (info
->getName() != NULL
)
2773 name
= info
->getName();
2777 for(int j
= 0; j
< info
->getRadioInterfaces()->size(); j
++)
2781 name
+= info
->getRadioInterfaces()->get(j
)->name
;
2784 ap
= new AccessPoint((const TCHAR
*)name
, info
->getIndex(), info
->getMacAddr());
2785 NetObjInsert(ap
, true, false);
2786 DbgPrintf(5, _T("ConfPoll(%s): created new access point object %s [%d]"), m_name
, ap
->getName(), ap
->getId());
2789 ap
->attachToNode(m_id
);
2790 ap
->setIpAddress(info
->getIpAddr());
2791 if ((info
->getState() == AP_ADOPTED
) || newAp
)
2793 ap
->updateRadioInterfaces(info
->getRadioInterfaces());
2794 ap
->updateInfo(info
->getVendor(), info
->getModel(), info
->getSerial());
2797 ap
->updateState(info
->getState());
2801 m_adoptedApCount
= adopted
;
2802 m_totalApCount
= aps
->size();
2809 DbgPrintf(5, _T("ConfPoll(%s): failed to read access point information"), m_name
);
2810 sendPollerMsg(dwRqId
, POLLER_ERROR
_T(" Failed to read access point information\r\n"));
2816 m_flags
&= ~NF_IS_WIFI_CONTROLLER
;
2820 if (ConfigReadInt(_T("EnableCheckPointSNMP"), 0))
2822 // Check for CheckPoint SNMP agent on port 161
2823 DbgPrintf(5, _T("ConfPoll(%s): checking for CheckPoint SNMP"), m_name
);
2824 TCHAR szBuffer
[4096];
2825 if (SnmpGet(SNMP_VERSION_1
, pTransport
, _T(".1.3.6.1.4.1.2620.1.1.10.0"), NULL
, 0, szBuffer
, sizeof(szBuffer
), 0) == SNMP_ERR_SUCCESS
)
2828 if (_tcscmp(m_szObjectId
, _T(".1.3.6.1.4.1.2620.1.1")))
2830 nx_strncpy(m_szObjectId
, _T(".1.3.6.1.4.1.2620.1.1"), MAX_OID_LEN
* 4);
2834 m_flags
|= NF_IS_SNMP
| NF_IS_ROUTER
;
2835 m_dwDynamicFlags
&= ~NDF_SNMP_UNREACHABLE
;
2837 sendPollerMsg(dwRqId
, POLLER_INFO
_T(" CheckPoint SNMP agent on port 161 is active\r\n"));
2845 * Query SNMP sys property (sysName, sysLocation, etc.)
2847 bool Node::querySnmpSysProperty(SNMP_Transport
*snmp
, const TCHAR
*oid
, const TCHAR
*propName
, UINT32 pollRqId
, TCHAR
**value
)
2850 bool hasChanges
= false;
2852 if (SnmpGet(m_snmpVersion
, snmp
, oid
, NULL
, 0, buffer
, sizeof(buffer
), SG_STRING_RESULT
) == SNMP_ERR_SUCCESS
)
2855 if ((*value
== NULL
) || _tcscmp(*value
, buffer
))
2858 *value
= _tcsdup(buffer
);
2860 sendPollerMsg(pollRqId
, _T(" System %s changed to %s\r\n"), propName
, *value
);
2868 * Configuration poll: check for BRIDGE MIB
2870 void Node::checkBridgeMib(SNMP_Transport
*pTransport
)
2872 TCHAR szBuffer
[4096];
2873 if (SnmpGet(m_snmpVersion
, pTransport
, _T(".1.3.6.1.2.1.17.1.1.0"), NULL
, 0, szBuffer
, sizeof(szBuffer
), SG_RAW_RESULT
) == SNMP_ERR_SUCCESS
)
2876 m_flags
|= NF_IS_BRIDGE
;
2877 memcpy(m_baseBridgeAddress
, szBuffer
, 6);
2880 // Check for Spanning Tree (IEEE 802.1d) MIB support
2881 if (checkSNMPIntegerValue(pTransport
, _T(".1.3.6.1.2.1.17.2.1.0"), 3))
2884 m_flags
|= NF_IS_STP
;
2890 m_flags
&= ~NF_IS_STP
;
2897 m_flags
&= ~(NF_IS_BRIDGE
| NF_IS_STP
);
2903 * Configuration poll: check for ifXTable
2905 void Node::checkIfXTable(SNMP_Transport
*pTransport
)
2907 bool present
= false;
2908 SnmpWalk(pTransport
, _T(".1.3.6.1.2.1.31.1.1.1.1"), IndicatorSnmpWalkerCallback
, &present
);
2912 m_flags
|= NF_HAS_IFXTABLE
;
2918 m_flags
&= ~NF_HAS_IFXTABLE
;
2924 * Delete duplicate interfaces
2925 * (find and delete multiple interfaces with same ifIndex value created by version prior to 2.0-M3)
2927 bool Node::deleteDuplicateInterfaces(UINT32 rqid
)
2929 ObjectArray
<Interface
> deleteList(16, 16, false);
2931 lockChildList(false);
2932 for(int i
= 0; i
< m_childList
->size(); i
++)
2934 NetObj
*curr
= m_childList
->get(i
);
2936 if ((curr
->getObjectClass() != OBJECT_INTERFACE
) ||
2937 ((Interface
*)curr
)->isManuallyCreated())
2939 Interface
*iface
= (Interface
*)curr
;
2940 for(int j
= i
+ 1; j
< m_childList
->size(); j
++)
2942 NetObj
*next
= m_childList
->get(j
);
2944 if ((next
->getObjectClass() != OBJECT_INTERFACE
) ||
2945 ((Interface
*)next
)->isManuallyCreated() ||
2946 (deleteList
.contains((Interface
*)next
)))
2948 if (iface
->getIfIndex() == ((Interface
*)next
)->getIfIndex())
2950 deleteList
.add((Interface
*)next
);
2951 DbgPrintf(6, _T("Node::deleteDuplicateInterfaces(%s [%d]): found duplicate interface %s [%d], original %s [%d], ifIndex=%d"),
2952 m_name
, m_id
, next
->getName(), next
->getId(), iface
->getName(), iface
->getId(), iface
->getIfIndex());
2958 for(int i
= 0; i
< deleteList
.size(); i
++)
2960 Interface
*iface
= deleteList
.get(i
);
2961 sendPollerMsg(rqid
, POLLER_WARNING
_T(" Duplicate interface \"%s\" deleted\r\n"), iface
->getName());
2962 deleteInterface(iface
);
2965 return deleteList
.size() > 0;
2969 * Update interface configuration
2971 bool Node::updateInterfaceConfiguration(UINT32 rqid
, int maskBits
)
2973 sendPollerMsg(rqid
, _T("Checking interface configuration...\r\n"));
2975 bool hasChanges
= deleteDuplicateInterfaces(rqid
);
2977 InterfaceList
*pIfList
= getInterfaceList();
2978 if (pIfList
!= NULL
)
2980 DbgPrintf(6, _T("Node::updateInterfaceConfiguration(%s [%u]): got %d interfaces"), m_name
, m_id
, pIfList
->size());
2982 // Find non-existing interfaces
2983 lockChildList(false);
2984 ObjectArray
<Interface
> deleteList(m_childList
->size(), 8, false);
2985 for(int i
= 0; i
< m_childList
->size(); i
++)
2987 if (m_childList
->get(i
)->getObjectClass() == OBJECT_INTERFACE
)
2989 Interface
*pInterface
= (Interface
*)m_childList
->get(i
);
2990 if (!pInterface
->isManuallyCreated())
2993 for(j
= 0; j
< pIfList
->size(); j
++)
2995 if (pIfList
->get(j
)->index
== pInterface
->getIfIndex())
2999 if (j
== pIfList
->size())
3001 // No such interface in current configuration, add it to delete list
3002 deleteList
.add(pInterface
);
3009 // Delete non-existent interfaces
3010 if (deleteList
.size() > 0)
3012 for(int j
= 0; j
< deleteList
.size(); j
++)
3014 Interface
*iface
= deleteList
.get(j
);
3015 sendPollerMsg(rqid
, POLLER_WARNING
_T(" Interface \"%s\" is no longer exist\r\n"), iface
->getName());
3016 const InetAddress
& addr
= iface
->getFirstIpAddress();
3017 PostEvent(EVENT_INTERFACE_DELETED
, m_id
, "dsAd", iface
->getIfIndex(), iface
->getName(), &addr
, addr
.getMaskBits());
3018 deleteInterface(iface
);
3023 // Add new interfaces and check configuration of existing
3024 for(int j
= 0; j
< pIfList
->size(); j
++)
3026 InterfaceInfo
*ifInfo
= pIfList
->get(j
);
3027 BOOL bNewInterface
= TRUE
;
3029 lockChildList(false);
3030 for(int i
= 0; i
< m_childList
->size(); i
++)
3032 if (m_childList
->get(i
)->getObjectClass() == OBJECT_INTERFACE
)
3034 Interface
*pInterface
= (Interface
*)m_childList
->get(i
);
3036 if (ifInfo
->index
== pInterface
->getIfIndex())
3038 // Existing interface, check configuration
3039 if (memcmp(ifInfo
->macAddr
, "\x00\x00\x00\x00\x00\x00", MAC_ADDR_LENGTH
) &&
3040 memcmp(ifInfo
->macAddr
, pInterface
->getMacAddr(), MAC_ADDR_LENGTH
))
3042 TCHAR szOldMac
[16], szNewMac
[16];
3044 BinToStr((BYTE
*)pInterface
->getMacAddr(), MAC_ADDR_LENGTH
, szOldMac
);
3045 BinToStr(ifInfo
->macAddr
, MAC_ADDR_LENGTH
, szNewMac
);
3046 PostEvent(EVENT_MAC_ADDR_CHANGED
, m_id
, "idsss",
3047 pInterface
->getId(), pInterface
->getIfIndex(),
3048 pInterface
->getName(), szOldMac
, szNewMac
);
3049 pInterface
->setMacAddr(ifInfo
->macAddr
, true);
3051 if (_tcscmp(ifInfo
->name
, pInterface
->getName()))
3053 pInterface
->setName(ifInfo
->name
);
3055 if (_tcscmp(ifInfo
->description
, pInterface
->getDescription()))
3057 pInterface
->setDescription(ifInfo
->description
);
3059 if (_tcscmp(ifInfo
->alias
, pInterface
->getAlias()))
3061 pInterface
->setAlias(ifInfo
->alias
);
3063 if (ifInfo
->bridgePort
!= pInterface
->getBridgePortNumber())
3065 pInterface
->setBridgePortNumber(ifInfo
->bridgePort
);
3067 if (ifInfo
->slot
!= pInterface
->getSlotNumber())
3069 pInterface
->setSlotNumber(ifInfo
->slot
);
3071 if (ifInfo
->port
!= pInterface
->getPortNumber())
3073 pInterface
->setPortNumber(ifInfo
->port
);
3075 if (ifInfo
->isPhysicalPort
!= pInterface
->isPhysicalPort())
3077 pInterface
->setPhysicalPortFlag(ifInfo
->isPhysicalPort
);
3079 if (ifInfo
->mtu
!= pInterface
->getMTU())
3081 pInterface
->setMTU(ifInfo
->mtu
);
3083 if (ifInfo
->speed
!= pInterface
->getSpeed())
3085 pInterface
->setSpeed(ifInfo
->speed
);
3087 if ((ifInfo
->ifTableSuffixLength
!= pInterface
->getIfTableSuffixLen()) ||
3088 memcmp(ifInfo
->ifTableSuffix
, pInterface
->getIfTableSuffix(),
3089 min(ifInfo
->ifTableSuffixLength
, pInterface
->getIfTableSuffixLen())))
3091 pInterface
->setIfTableSuffix(ifInfo
->ifTableSuffixLength
, ifInfo
->ifTableSuffix
);
3094 // Check for deleted IPs and changed masks
3095 const InetAddressList
*ifList
= pInterface
->getIpAddressList();
3096 for(int n
= 0; n
< ifList
->size(); n
++)
3098 const InetAddress
& ifAddr
= ifList
->get(n
);
3099 const InetAddress
& addr
= ifInfo
->ipAddrList
.findAddress(ifAddr
);
3102 if (addr
.getMaskBits() != ifAddr
.getMaskBits())
3104 PostEvent(EVENT_IF_MASK_CHANGED
, m_id
, "dsAddd", pInterface
->getId(), pInterface
->getName(),
3105 &addr
, addr
.getMaskBits(), pInterface
->getIfIndex(), ifAddr
.getMaskBits());
3106 pInterface
->setNetMask(addr
);
3107 sendPollerMsg(rqid
, POLLER_INFO
_T(" IP network mask changed to /%d on interface \"%s\" address %s\r\n"),
3108 addr
.getMaskBits(), pInterface
->getName(), (const TCHAR
*)ifAddr
.toString());
3113 sendPollerMsg(rqid
, POLLER_WARNING
_T(" IP address %s removed from interface \"%s\"\r\n"),
3114 (const TCHAR
*)ifAddr
.toString(), pInterface
->getName());
3115 PostEvent(EVENT_IF_IPADDR_DELETED
, m_id
, "dsAdd", pInterface
->getId(), pInterface
->getName(),
3116 &ifAddr
, ifAddr
.getMaskBits(), pInterface
->getIfIndex());
3117 pInterface
->deleteIpAddress(ifAddr
);
3121 // Check for added IPs
3122 for(int m
= 0; m
< ifInfo
->ipAddrList
.size(); m
++)
3124 const InetAddress
& addr
= ifInfo
->ipAddrList
.get(m
);
3125 if (!ifList
->hasAddress(addr
))
3127 pInterface
->addIpAddress(addr
);
3128 PostEvent(EVENT_IF_IPADDR_ADDED
, m_id
, "dsAdd", pInterface
->getId(), pInterface
->getName(),
3129 &addr
, addr
.getMaskBits(), pInterface
->getIfIndex());
3130 sendPollerMsg(rqid
, POLLER_INFO
_T(" IP address %s added to interface \"%s\"\r\n"),
3131 (const TCHAR
*)addr
.toString(), pInterface
->getName());
3135 bNewInterface
= FALSE
;
3145 sendPollerMsg(rqid
, POLLER_INFO
_T(" Found new interface \"%s\"\r\n"), ifInfo
->name
);
3146 if (filterInterface(ifInfo
))
3148 createNewInterface(ifInfo
, false, false);
3153 sendPollerMsg(rqid
, POLLER_WARNING
_T(" Creation of interface object \"%s\" blocked by filter\r\n"), ifInfo
->name
);
3158 else if (!(m_flags
& NF_REMOTE_AGENT
)) /* pIfList == NULL */
3160 Interface
*pInterface
;
3163 sendPollerMsg(rqid
, POLLER_ERROR
_T("Unable to get interface list from node\r\n"));
3164 DbgPrintf(6, _T("Node::updateInterfaceConfiguration(%s [%u]): Unable to get interface list from node"), m_name
, m_id
);
3166 // Delete all existing interfaces in case of forced capability recheck
3167 if (m_dwDynamicFlags
& NDF_RECHECK_CAPABILITIES
)
3169 lockChildList(false);
3170 Interface
**ppDeleteList
= (Interface
**)malloc(sizeof(Interface
*) * m_childList
->size());
3172 for(int i
= 0; i
< m_childList
->size(); i
++)
3174 NetObj
*curr
= m_childList
->get(i
);
3175 if ((curr
->getObjectClass() == OBJECT_INTERFACE
) && !((Interface
*)curr
)->isManuallyCreated())
3176 ppDeleteList
[delCount
++] = (Interface
*)curr
;
3179 for(int j
= 0; j
< delCount
; j
++)
3181 sendPollerMsg(rqid
, POLLER_WARNING
_T(" Interface \"%s\" is no longer exist\r\n"),
3182 ppDeleteList
[j
]->getName());
3183 const InetAddress
& addr
= ppDeleteList
[j
]->getIpAddressList()->getFirstUnicastAddress();
3184 PostEvent(EVENT_INTERFACE_DELETED
, m_id
, "dsAd", ppDeleteList
[j
]->getIfIndex(),
3185 ppDeleteList
[j
]->getName(), &addr
, addr
.getMaskBits());
3186 deleteInterface(ppDeleteList
[j
]);
3188 safe_free(ppDeleteList
);
3191 // Check if we have pseudo-interface object
3192 BYTE macAddr
[MAC_ADDR_LENGTH
];
3194 dwCount
= getInterfaceCount(&pInterface
);
3197 if (pInterface
->isFake())
3199 // Check if primary IP is different from interface's IP
3200 if (!pInterface
->getIpAddressList()->hasAddress(m_ipAddress
))
3202 deleteInterface(pInterface
);
3203 if (m_ipAddress
.isValidUnicast())
3205 memset(macAddr
, 0, MAC_ADDR_LENGTH
);
3206 Subnet
*pSubnet
= FindSubnetForNode(m_zoneId
, m_ipAddress
);
3207 if (pSubnet
!= NULL
)
3208 pSubnet
->findMacAddress(m_ipAddress
, macAddr
);
3209 pMacAddr
= !memcmp(macAddr
, "\x00\x00\x00\x00\x00\x00", MAC_ADDR_LENGTH
) ? NULL
: macAddr
;
3211 MACToStr(macAddr
, szMac
);
3212 DbgPrintf(5, _T("Node::updateInterfaceConfiguration(%s [%u]): got MAC for unknown interface: %s"), m_name
, m_id
, szMac
);
3213 InetAddress ifaceAddr
= m_ipAddress
;
3214 ifaceAddr
.setMaskBits(maskBits
);
3215 createNewInterface(ifaceAddr
, pMacAddr
, true);
3220 // check MAC address
3221 memset(macAddr
, 0, MAC_ADDR_LENGTH
);
3222 Subnet
*pSubnet
= FindSubnetForNode(m_zoneId
, m_ipAddress
);
3223 if (pSubnet
!= NULL
)
3224 pSubnet
->findMacAddress(m_ipAddress
, macAddr
);
3225 if (memcmp(macAddr
, "\x00\x00\x00\x00\x00\x00", MAC_ADDR_LENGTH
) && memcmp(macAddr
, pInterface
->getMacAddr(), MAC_ADDR_LENGTH
))
3227 TCHAR szOldMac
[16], szNewMac
[16];
3229 BinToStr((BYTE
*)pInterface
->getMacAddr(), MAC_ADDR_LENGTH
, szOldMac
);
3230 BinToStr(macAddr
, MAC_ADDR_LENGTH
, szNewMac
);
3231 DbgPrintf(5, _T("Node::updateInterfaceConfiguration(%s [%u]): MAC change for unknown interface: %s to %s"),
3232 m_name
, m_id
, szOldMac
, szNewMac
);
3233 PostEvent(EVENT_MAC_ADDR_CHANGED
, m_id
, "idsss",
3234 pInterface
->getId(), pInterface
->getIfIndex(),
3235 pInterface
->getName(), szOldMac
, szNewMac
);
3236 pInterface
->setMacAddr(macAddr
, true);
3241 else if (dwCount
== 0)
3243 // No interfaces at all, create pseudo-interface
3244 if (m_ipAddress
.isValidUnicast())
3246 memset(macAddr
, 0, MAC_ADDR_LENGTH
);
3247 Subnet
*pSubnet
= FindSubnetForNode(m_zoneId
, m_ipAddress
);
3248 if (pSubnet
!= NULL
)
3249 pSubnet
->findMacAddress(m_ipAddress
, macAddr
);
3250 pMacAddr
= !memcmp(macAddr
, "\x00\x00\x00\x00\x00\x00", MAC_ADDR_LENGTH
) ? NULL
: macAddr
;
3252 MACToStr(macAddr
, szMac
);
3253 DbgPrintf(5, _T("Node::updateInterfaceConfiguration(%s [%u]): got MAC for unknown interface: %s"), m_name
, m_id
, szMac
);
3254 InetAddress ifaceAddr
= m_ipAddress
;
3255 ifaceAddr
.setMaskBits(maskBits
);
3256 createNewInterface(ifaceAddr
, pMacAddr
, true);
3259 DbgPrintf(6, _T("Node::updateInterfaceConfiguration(%s [%u]): pIfList == NULL, dwCount = %u"), m_name
, m_id
, dwCount
);
3263 checkSubnetBinding();
3265 sendPollerMsg(rqid
, _T("Interface configuration check finished\r\n"));
3270 * Filter for selecting templates from objects
3272 static bool TemplateSelectionFilter(NetObj
*object
, void *userData
)
3274 return (object
->getObjectClass() == OBJECT_TEMPLATE
) && !object
->isDeleted() && ((Template
*)object
)->isAutoApplyEnabled();
3278 * Apply user templates
3280 void Node::applyUserTemplates()
3282 if (IsShutdownInProgress())
3285 ObjectArray
<NetObj
> *templates
= g_idxObjectById
.getObjects(true, TemplateSelectionFilter
);
3286 for(int i
= 0; i
< templates
->size(); i
++)
3288 Template
*pTemplate
= (Template
*)templates
->get(i
);
3289 AutoBindDecision decision
= pTemplate
->isApplicable(this);
3290 if (decision
== AutoBindDecision_Bind
)
3292 if (!pTemplate
->isChild(m_id
))
3294 DbgPrintf(4, _T("Node::ApplyUserTemplates(): applying template %d \"%s\" to node %d \"%s\""),
3295 pTemplate
->getId(), pTemplate
->getName(), m_id
, m_name
);
3296 pTemplate
->applyToTarget(this);
3297 PostEvent(EVENT_TEMPLATE_AUTOAPPLY
, g_dwMgmtNode
, "isis", m_id
, m_name
, pTemplate
->getId(), pTemplate
->getName());
3300 else if (decision
== AutoBindDecision_Unbind
)
3302 if (pTemplate
->isAutoRemoveEnabled() && pTemplate
->isChild(m_id
))
3304 DbgPrintf(4, _T("Node::ApplyUserTemplates(): removing template %d \"%s\" from node %d \"%s\""),
3305 pTemplate
->getId(), pTemplate
->getName(), m_id
, m_name
);
3306 pTemplate
->deleteChild(this);
3307 deleteParent(pTemplate
);
3308 pTemplate
->queueRemoveFromTarget(m_id
, true);
3309 PostEvent(EVENT_TEMPLATE_AUTOREMOVE
, g_dwMgmtNode
, "isis", m_id
, m_name
, pTemplate
->getId(), pTemplate
->getName());
3312 pTemplate
->decRefCount();
3318 * Filter for selecting containers from objects
3320 static bool ContainerSelectionFilter(NetObj
*object
, void *userData
)
3322 return (object
->getObjectClass() == OBJECT_CONTAINER
) && !object
->isDeleted() && ((Container
*)object
)->isAutoBindEnabled();
3326 * Update container membership
3328 void Node::updateContainerMembership()
3330 if (IsShutdownInProgress())
3333 ObjectArray
<NetObj
> *containers
= g_idxObjectById
.getObjects(true, ContainerSelectionFilter
);
3334 for(int i
= 0; i
< containers
->size(); i
++)
3336 Container
*pContainer
= (Container
*)containers
->get(i
);
3337 AutoBindDecision decision
= pContainer
->isSuitableForNode(this);
3338 if (decision
== AutoBindDecision_Bind
)
3340 if (!pContainer
->isChild(m_id
))
3342 DbgPrintf(4, _T("Node::updateContainerMembership(): binding node %d \"%s\" to container %d \"%s\""),
3343 m_id
, m_name
, pContainer
->getId(), pContainer
->getName());
3344 pContainer
->addChild(this);
3345 addParent(pContainer
);
3346 PostEvent(EVENT_CONTAINER_AUTOBIND
, g_dwMgmtNode
, "isis", m_id
, m_name
, pContainer
->getId(), pContainer
->getName());
3347 pContainer
->calculateCompoundStatus();
3350 else if (decision
== AutoBindDecision_Unbind
)
3352 if (pContainer
->isAutoUnbindEnabled() && pContainer
->isChild(m_id
))
3354 DbgPrintf(4, _T("Node::updateContainerMembership(): removing node %d \"%s\" from container %d \"%s\""),
3355 m_id
, m_name
, pContainer
->getId(), pContainer
->getName());
3356 pContainer
->deleteChild(this);
3357 deleteParent(pContainer
);
3358 PostEvent(EVENT_CONTAINER_AUTOUNBIND
, g_dwMgmtNode
, "isis", m_id
, m_name
, pContainer
->getId(), pContainer
->getName());
3359 pContainer
->calculateCompoundStatus();
3362 pContainer
->decRefCount();
3368 * Entry point for instance discovery poller
3370 void Node::instanceDiscoveryPoll(PollerInfo
*poller
)
3372 poller
->startExecution();
3373 ObjectTransactionStart();
3374 instanceDiscoveryPoll(NULL
, 0, poller
);
3375 ObjectTransactionEnd();
3380 * Perform instance discovery poll on node
3382 void Node::instanceDiscoveryPoll(ClientSession
*session
, UINT32 requestId
, PollerInfo
*poller
)
3384 if (m_dwDynamicFlags
& NDF_DELETE_IN_PROGRESS
)
3387 m_dwDynamicFlags
&= ~NDF_QUEUED_FOR_INSTANCE_POLL
;
3391 if (IsShutdownInProgress())
3394 poller
->setStatus(_T("wait for lock"));
3397 if (IsShutdownInProgress())
3403 m_pollRequestor
= session
;
3404 sendPollerMsg(requestId
, _T("Starting instance discovery poll for node %s\r\n"