2 ** NetXMS - Network Management System
3 ** Copyright (C) 2003-2017 Raden Solutions
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.
24 #include <agent_tunnel.h>
29 extern UINT64 g_syslogMessagesReceived
;
30 extern UINT64 g_snmpTrapsReceived
;
33 * Node class default constructor
35 Node::Node() : DataCollectionTarget()
38 m_status
= STATUS_UNKNOWN
;
39 m_type
= NODE_TYPE_UNKNOWN
;
43 m_agentPort
= AGENT_LISTEN_PORT
;
44 m_agentAuthMethod
= AUTH_NONE
;
45 m_agentCacheMode
= AGENT_CACHE_DEFAULT
;
46 m_szSharedSecret
[0] = 0;
47 m_iStatusPollType
= POLL_ICMP_PING
;
48 m_snmpVersion
= SNMP_VERSION_1
;
49 m_snmpPort
= SNMP_DEFAULT_PORT
;
50 m_snmpSecurity
= new SNMP_SecurityContext("public");
51 m_snmpObjectId
[0] = 0;
52 m_lastDiscoveryPoll
= 0;
54 m_lastConfigurationPoll
= 0;
55 m_lastInstancePoll
= 0;
56 m_lastTopologyPoll
= 0;
61 m_hAgentAccessMutex
= MutexCreate();
62 m_hSmclpAccessMutex
= MutexCreate();
63 m_mutexRTAccess
= MutexCreate();
64 m_mutexTopoAccess
= MutexCreate();
65 m_agentConnection
= NULL
;
66 m_proxyConnections
= new ObjectLock
<AgentConnectionEx
>[MAX_PROXY_TYPE
];
67 m_smclpConnection
= NULL
;
68 m_lastAgentTrapId
= 0;
70 m_lastSyslogMessageId
= 0;
71 m_lastAgentPushRequestId
= 0;
72 m_agentVersion
[0] = 0;
73 m_platformName
[0] = 0;
74 m_sysDescription
= NULL
;
79 m_lldpLocalPortInfo
= NULL
;
86 memset(m_lastEvents
, 0, sizeof(QWORD
) * MAX_LAST_EVENTS
);
87 m_routingLoopEvents
= new ObjectArray
<RoutingLoopEvent
>(0, 16, true);
88 m_pRoutingTable
= NULL
;
91 m_lastAgentCommTime
= 0;
92 m_lastAgentConnectAttempt
= 0;
93 m_linkLayerNeighbors
= NULL
;
96 m_topologyRebuildTimestamp
= 0;
100 m_pollCountAllDown
= 0;
101 m_requiredPollCount
= 0; // Use system default
102 m_nUseIfXTable
= IFXTABLE_DEFAULT
; // Use system default
103 m_jobQueue
= new ServerJobQueue();
106 m_wirelessStations
= NULL
;
107 m_adoptedApCount
= 0;
112 m_softwarePackages
= NULL
;
113 m_winPerfObjects
= NULL
;
114 memset(m_baseBridgeAddress
, 0, MAC_ADDR_LENGTH
);
115 m_fileUpdateConn
= NULL
;
120 m_syslogMessageCount
= 0;
123 m_sshPassword
[0] = 0;
125 m_portNumberingScheme
= NDD_PN_UNKNOWN
;
127 m_agentCompressionMode
= NODE_AGENT_COMPRESSION_DEFAULT
;
131 * Constructor for new node object
133 Node::Node(const InetAddress
& addr
, UINT32 flags
, UINT32 capabilities
, UINT32 agentProxy
, UINT32 snmpProxy
, UINT32 icmpProxy
, UINT32 sshProxy
, UINT32 zoneUIN
) : DataCollectionTarget()
135 m_runtimeFlags
|= DCDF_CONFIGURATION_POLL_PENDING
;
136 addr
.toString(m_primaryName
);
137 m_status
= STATUS_UNKNOWN
;
138 m_type
= NODE_TYPE_UNKNOWN
;
141 m_capabilities
= capabilities
;
144 m_agentPort
= AGENT_LISTEN_PORT
;
145 m_agentAuthMethod
= AUTH_NONE
;
146 m_agentCacheMode
= AGENT_CACHE_DEFAULT
;
147 m_szSharedSecret
[0] = 0;
148 m_iStatusPollType
= POLL_ICMP_PING
;
149 m_snmpVersion
= SNMP_VERSION_1
;
150 m_snmpPort
= SNMP_DEFAULT_PORT
;
151 m_snmpSecurity
= new SNMP_SecurityContext("public");
152 addr
.toString(m_name
); // Make default name from IP address
153 m_snmpObjectId
[0] = 0;
154 m_lastDiscoveryPoll
= 0;
155 m_lastStatusPoll
= 0;
156 m_lastConfigurationPoll
= 0;
157 m_lastInstancePoll
= 0;
158 m_lastTopologyPoll
= 0;
163 m_hAgentAccessMutex
= MutexCreate();
164 m_hSmclpAccessMutex
= MutexCreate();
165 m_mutexRTAccess
= MutexCreate();
166 m_mutexTopoAccess
= MutexCreate();
167 m_agentConnection
= NULL
;
168 m_proxyConnections
= new ObjectLock
<AgentConnectionEx
>[MAX_PROXY_TYPE
];
169 m_smclpConnection
= NULL
;
170 m_lastAgentTrapId
= 0;
171 m_lastSNMPTrapId
= 0;
172 m_lastSyslogMessageId
= 0;
173 m_lastAgentPushRequestId
= 0;
174 m_agentVersion
[0] = 0;
175 m_platformName
[0] = 0;
176 m_sysDescription
= NULL
;
179 m_sysLocation
= NULL
;
181 m_lldpLocalPortInfo
= NULL
;
185 m_agentProxy
= agentProxy
;
186 m_snmpProxy
= snmpProxy
;
187 m_icmpProxy
= icmpProxy
;
188 memset(m_lastEvents
, 0, sizeof(QWORD
) * MAX_LAST_EVENTS
);
189 m_routingLoopEvents
= new ObjectArray
<RoutingLoopEvent
>(0, 16, true);
191 m_pRoutingTable
= NULL
;
194 m_lastAgentCommTime
= 0;
195 m_lastAgentConnectAttempt
= 0;
196 m_linkLayerNeighbors
= NULL
;
199 m_topologyRebuildTimestamp
= 0;
201 m_pollCountAgent
= 0;
203 m_pollCountAllDown
= 0;
204 m_requiredPollCount
= 0; // Use system default
205 m_nUseIfXTable
= IFXTABLE_DEFAULT
; // Use system default
206 m_jobQueue
= new ServerJobQueue();
209 m_wirelessStations
= NULL
;
210 m_adoptedApCount
= 0;
215 m_softwarePackages
= NULL
;
216 m_winPerfObjects
= NULL
;
217 memset(m_baseBridgeAddress
, 0, MAC_ADDR_LENGTH
);
218 m_fileUpdateConn
= NULL
;
223 m_syslogMessageCount
= 0;
226 m_sshPassword
[0] = 0;
227 m_sshProxy
= sshProxy
;
228 m_portNumberingScheme
= NDD_PN_UNKNOWN
;
230 m_agentCompressionMode
= NODE_AGENT_COMPRESSION_DEFAULT
;
239 MutexDestroy(m_hAgentAccessMutex
);
240 MutexDestroy(m_hSmclpAccessMutex
);
241 MutexDestroy(m_mutexRTAccess
);
242 MutexDestroy(m_mutexTopoAccess
);
243 if (m_agentConnection
!= NULL
)
244 m_agentConnection
->decRefCount();
245 for(int i
= 0; i
< MAX_PROXY_TYPE
; i
++)
246 if(m_proxyConnections
[i
].get() != NULL
)
247 m_proxyConnections
[i
].get()->decRefCount();
248 delete[] m_proxyConnections
;
249 delete m_smclpConnection
;
252 free(m_sysDescription
);
253 DestroyRoutingTable(m_pRoutingTable
);
254 if (m_linkLayerNeighbors
!= NULL
)
255 m_linkLayerNeighbors
->decRefCount();
259 delete m_snmpSecurity
;
261 m_fdb
->decRefCount();
263 m_vlans
->decRefCount();
264 delete m_wirelessStations
;
265 if (m_components
!= NULL
)
266 m_components
->decRefCount();
267 delete m_lldpLocalPortInfo
;
268 delete m_softwarePackages
;
269 delete m_winPerfObjects
;
273 delete m_routingLoopEvents
;
277 * Create object from database data
279 bool Node::loadFromDatabase(DB_HANDLE hdb
, UINT32 dwId
)
284 bool bResult
= false;
288 if (!loadCommonProperties(hdb
))
290 DbgPrintf(2, _T("Cannot load common properties for node object %d"), dwId
);
294 DB_STATEMENT hStmt
= DBPrepare(hdb
,
295 _T("SELECT primary_name,primary_ip,")
296 _T("snmp_version,auth_method,secret,")
297 _T("agent_port,status_poll_type,snmp_oid,agent_version,")
298 _T("platform_name,poller_node_id,zone_guid,")
299 _T("proxy_node,snmp_proxy,required_polls,uname,")
300 _T("use_ifxtable,snmp_port,community,usm_auth_password,")
301 _T("usm_priv_password,usm_methods,snmp_sys_name,bridge_base_addr,")
302 _T("down_since,boot_time,driver_name,icmp_proxy,")
303 _T("agent_cache_mode,snmp_sys_contact,snmp_sys_location,")
304 _T("rack_id,rack_image,rack_position,rack_height,")
305 _T("last_agent_comm_time,syslog_msg_count,snmp_trap_count,")
306 _T("node_type,node_subtype,ssh_login,ssh_password,ssh_proxy,")
307 _T("port_rows,port_numbering_scheme,agent_comp_mode,")
308 _T("tunnel_id,lldp_id,capabilities,fail_time_snmp,fail_time_agent FROM nodes WHERE id=?"));
312 DBBind(hStmt
, 1, DB_SQLTYPE_INTEGER
, dwId
);
313 DB_RESULT hResult
= DBSelectPrepared(hStmt
);
316 DBFreeStatement(hStmt
);
317 return false; // Query failed
320 if (DBGetNumRows(hResult
) == 0)
322 DBFreeResult(hResult
);
323 DBFreeStatement(hStmt
);
324 DbgPrintf(2, _T("Missing record in \"nodes\" table for node object %d"), dwId
);
328 DBGetField(hResult
, 0, 0, m_primaryName
, MAX_DNS_NAME
);
329 m_ipAddress
= DBGetFieldInetAddr(hResult
, 0, 1);
330 m_snmpVersion
= DBGetFieldLong(hResult
, 0, 2);
331 m_agentAuthMethod
= (WORD
)DBGetFieldLong(hResult
, 0, 3);
332 DBGetField(hResult
, 0, 4, m_szSharedSecret
, MAX_SECRET_LENGTH
);
333 m_agentPort
= (WORD
)DBGetFieldLong(hResult
, 0, 5);
334 m_iStatusPollType
= DBGetFieldLong(hResult
, 0, 6);
335 DBGetField(hResult
, 0, 7, m_snmpObjectId
, MAX_OID_LEN
* 4);
336 DBGetField(hResult
, 0, 8, m_agentVersion
, MAX_AGENT_VERSION_LEN
);
337 DBGetField(hResult
, 0, 9, m_platformName
, MAX_PLATFORM_NAME_LEN
);
338 m_pollerNode
= DBGetFieldULong(hResult
, 0, 10);
339 m_zoneUIN
= DBGetFieldULong(hResult
, 0, 11);
340 m_agentProxy
= DBGetFieldULong(hResult
, 0, 12);
341 m_snmpProxy
= DBGetFieldULong(hResult
, 0, 13);
342 m_requiredPollCount
= DBGetFieldLong(hResult
, 0, 14);
343 m_sysDescription
= DBGetField(hResult
, 0, 15, NULL
, 0);
344 m_nUseIfXTable
= (BYTE
)DBGetFieldLong(hResult
, 0, 16);
345 m_snmpPort
= (WORD
)DBGetFieldLong(hResult
, 0, 17);
347 // SNMP authentication parameters
348 char snmpAuthObject
[256], snmpAuthPassword
[256], snmpPrivPassword
[256];
349 DBGetFieldA(hResult
, 0, 18, snmpAuthObject
, 256);
350 DBGetFieldA(hResult
, 0, 19, snmpAuthPassword
, 256);
351 DBGetFieldA(hResult
, 0, 20, snmpPrivPassword
, 256);
352 int snmpMethods
= DBGetFieldLong(hResult
, 0, 21);
353 delete m_snmpSecurity
;
354 if (m_snmpVersion
== SNMP_VERSION_3
)
356 m_snmpSecurity
= new SNMP_SecurityContext(snmpAuthObject
, snmpAuthPassword
, snmpPrivPassword
, snmpMethods
& 0xFF, snmpMethods
>> 8);
360 // This will create security context with V2C security model
361 // USM fields will be loaded but keys will not be calculated
362 m_snmpSecurity
= new SNMP_SecurityContext(snmpAuthObject
);
363 m_snmpSecurity
->setAuthMethod(snmpMethods
& 0xFF);
364 m_snmpSecurity
->setAuthPassword(snmpAuthPassword
);
365 m_snmpSecurity
->setPrivMethod(snmpMethods
>> 8);
366 m_snmpSecurity
->setPrivPassword(snmpPrivPassword
);
369 m_sysName
= DBGetField(hResult
, 0, 22, NULL
, 0);
372 TCHAR
*value
= DBGetField(hResult
, 0, 23, baseAddr
, 16);
374 StrToBin(value
, m_baseBridgeAddress
, MAC_ADDR_LENGTH
);
376 m_downSince
= DBGetFieldLong(hResult
, 0, 24);
377 m_bootTime
= DBGetFieldLong(hResult
, 0, 25);
380 TCHAR driverName
[34];
381 DBGetField(hResult
, 0, 26, driverName
, 34);
382 StrStrip(driverName
);
383 if (driverName
[0] != 0)
384 m_driver
= FindDriverByName(driverName
);
386 m_icmpProxy
= DBGetFieldULong(hResult
, 0, 27);
387 m_agentCacheMode
= (INT16
)DBGetFieldLong(hResult
, 0, 28);
388 if ((m_agentCacheMode
!= AGENT_CACHE_ON
) && (m_agentCacheMode
!= AGENT_CACHE_OFF
))
389 m_agentCacheMode
= AGENT_CACHE_DEFAULT
;
391 m_sysContact
= DBGetField(hResult
, 0, 29, NULL
, 0);
392 m_sysLocation
= DBGetField(hResult
, 0, 30, NULL
, 0);
394 m_rackId
= DBGetFieldULong(hResult
, 0, 31);
395 m_rackImage
= DBGetFieldGUID(hResult
, 0, 32);
396 m_rackPosition
= (INT16
)DBGetFieldLong(hResult
, 0, 33);
397 m_rackHeight
= (INT16
)DBGetFieldLong(hResult
, 0, 34);
398 m_lastAgentCommTime
= DBGetFieldLong(hResult
, 0, 35);
399 m_syslogMessageCount
= DBGetFieldInt64(hResult
, 0, 36);
400 m_snmpTrapCount
= DBGetFieldInt64(hResult
, 0, 37);
401 m_type
= (NodeType
)DBGetFieldLong(hResult
, 0, 38);
402 DBGetField(hResult
, 0, 39, m_subType
, MAX_NODE_SUBTYPE_LENGTH
);
403 DBGetField(hResult
, 0, 40, m_sshLogin
, MAX_SSH_LOGIN_LEN
);
404 DBGetField(hResult
, 0, 41, m_sshPassword
, MAX_SSH_PASSWORD_LEN
);
405 m_sshProxy
= DBGetFieldULong(hResult
, 0, 42);
406 m_portRowCount
= DBGetFieldULong(hResult
, 0, 43);
407 m_portNumberingScheme
= DBGetFieldULong(hResult
, 0, 44);
408 m_agentCompressionMode
= (INT16
)DBGetFieldLong(hResult
, 0, 45);
409 m_tunnelId
= DBGetFieldGUID(hResult
, 0, 46);
410 m_lldpNodeId
= DBGetField(hResult
, 0, 47, NULL
, 0);
411 if ((m_lldpNodeId
!= NULL
) && (*m_lldpNodeId
== 0))
412 safe_free_and_null(m_lldpNodeId
);
413 m_capabilities
= DBGetFieldULong(hResult
, 0, 48);
414 m_failTimeSNMP
= DBGetFieldLong(hResult
, 0, 49);
415 m_failTimeAgent
= DBGetFieldLong(hResult
, 0, 50);
417 DBFreeResult(hResult
);
418 DBFreeStatement(hStmt
);
422 // Link node to subnets
423 hStmt
= DBPrepare(hdb
, _T("SELECT subnet_id FROM nsmap WHERE node_id=?"));
427 DBBind(hStmt
, 1, DB_SQLTYPE_INTEGER
, m_id
);
428 hResult
= DBSelectPrepared(hStmt
);
431 DBFreeStatement(hStmt
);
432 return false; // Query failed
435 iNumRows
= DBGetNumRows(hResult
);
436 for(i
= 0; i
< iNumRows
; i
++)
438 dwSubnetId
= DBGetFieldULong(hResult
, i
, 0);
439 pObject
= FindObjectById(dwSubnetId
);
442 nxlog_write(MSG_INVALID_SUBNET_ID
, EVENTLOG_ERROR_TYPE
, "dd", dwId
, dwSubnetId
);
445 else if (pObject
->getObjectClass() != OBJECT_SUBNET
)
447 nxlog_write(MSG_SUBNET_NOT_SUBNET
, EVENTLOG_ERROR_TYPE
, "dd", dwId
, dwSubnetId
);
452 pObject
->addChild(this);
457 DBFreeResult(hResult
);
458 DBFreeStatement(hStmt
);
460 loadItemsFromDB(hdb
);
463 // Walk through all items in the node and load appropriate thresholds
465 for(i
= 0; i
< m_dcObjects
->size(); i
++)
467 if (!m_dcObjects
->get(i
)->loadThresholdsFromDB(hdb
))
469 DbgPrintf(3, _T("Cannot load thresholds for DCI %d of node %d (%s)"),
470 m_dcObjects
->get(i
)->getId(), dwId
, m_name
);
475 updatePhysicalContainerBinding(OBJECT_RACK
, m_rackId
);
476 updatePhysicalContainerBinding(OBJECT_CHASSIS
, m_chassisId
);
487 * Save object to database
489 bool Node::saveToDatabase(DB_HANDLE hdb
)
491 // Lock object's access
494 bool success
= saveCommonProperties(hdb
);
496 if (success
&& (m_modified
& MODIFY_NODE_PROPERTIES
))
498 int snmpMethods
= m_snmpSecurity
->getAuthMethod() | (m_snmpSecurity
->getPrivMethod() << 8);
500 if (IsDatabaseRecordExist(hdb
, _T("nodes"), _T("id"), m_id
))
502 hStmt
= DBPrepare(hdb
,
503 _T("UPDATE nodes SET primary_ip=?,primary_name=?,snmp_port=?,capabilities=?,snmp_version=?,community=?,")
504 _T("status_poll_type=?,agent_port=?,auth_method=?,secret=?,snmp_oid=?,uname=?,agent_version=?,")
505 _T("platform_name=?,poller_node_id=?,zone_guid=?,proxy_node=?,snmp_proxy=?,icmp_proxy=?,required_polls=?,")
506 _T("use_ifxtable=?,usm_auth_password=?,usm_priv_password=?,usm_methods=?,snmp_sys_name=?,bridge_base_addr=?,")
507 _T("down_since=?,driver_name=?,rack_image=?,rack_position=?,rack_height=?,rack_id=?,boot_time=?,")
508 _T("agent_cache_mode=?,snmp_sys_contact=?,snmp_sys_location=?,last_agent_comm_time=?,")
509 _T("syslog_msg_count=?,snmp_trap_count=?,node_type=?,node_subtype=?,ssh_login=?,ssh_password=?,")
510 _T("ssh_proxy=?,chassis_id=?,port_rows=?,port_numbering_scheme=?,agent_comp_mode=?,tunnel_id=?,")
511 _T("lldp_id=?,fail_time_snmp=?,fail_time_agent=? WHERE id=?"));
515 hStmt
= DBPrepare(hdb
,
516 _T("INSERT INTO nodes (primary_ip,primary_name,snmp_port,capabilities,snmp_version,community,status_poll_type,")
517 _T("agent_port,auth_method,secret,snmp_oid,uname,agent_version,platform_name,poller_node_id,zone_guid,")
518 _T("proxy_node,snmp_proxy,icmp_proxy,required_polls,use_ifxtable,usm_auth_password,usm_priv_password,usm_methods,")
519 _T("snmp_sys_name,bridge_base_addr,down_since,driver_name,rack_image,rack_position,rack_height,rack_id,boot_time,")
520 _T("agent_cache_mode,snmp_sys_contact,snmp_sys_location,last_agent_comm_time,syslog_msg_count,snmp_trap_count,")
521 _T("node_type,node_subtype,ssh_login,ssh_password,ssh_proxy,chassis_id,port_rows,port_numbering_scheme,agent_comp_mode,")
522 _T("tunnel_id,lldp_id,fail_time_snmp,fail_time_agent,id) ")
523 _T("VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"));
527 TCHAR ipAddr
[64], baseAddress
[16], cacheMode
[16], compressionMode
[16];
529 DBBind(hStmt
, 1, DB_SQLTYPE_VARCHAR
, m_ipAddress
.toString(ipAddr
), DB_BIND_STATIC
);
530 DBBind(hStmt
, 2, DB_SQLTYPE_VARCHAR
, m_primaryName
, DB_BIND_STATIC
);
531 DBBind(hStmt
, 3, DB_SQLTYPE_INTEGER
, (LONG
)m_snmpPort
);
532 DBBind(hStmt
, 4, DB_SQLTYPE_INTEGER
, m_capabilities
);
533 DBBind(hStmt
, 5, DB_SQLTYPE_INTEGER
, (LONG
)m_snmpVersion
);
535 DBBind(hStmt
, 6, DB_SQLTYPE_VARCHAR
, WideStringFromMBString(m_snmpSecurity
->getCommunity()), DB_BIND_DYNAMIC
);
537 DBBind(hStmt
, 6, DB_SQLTYPE_VARCHAR
, m_snmpSecurity
->getCommunity(), DB_BIND_STATIC
);
539 DBBind(hStmt
, 7, DB_SQLTYPE_INTEGER
, (LONG
)m_iStatusPollType
);
540 DBBind(hStmt
, 8, DB_SQLTYPE_INTEGER
, (LONG
)m_agentPort
);
541 DBBind(hStmt
, 9, DB_SQLTYPE_INTEGER
, (LONG
)m_agentAuthMethod
);
542 DBBind(hStmt
, 10, DB_SQLTYPE_VARCHAR
, m_szSharedSecret
, DB_BIND_STATIC
);
543 DBBind(hStmt
, 11, DB_SQLTYPE_VARCHAR
, m_snmpObjectId
, DB_BIND_STATIC
);
544 DBBind(hStmt
, 12, DB_SQLTYPE_VARCHAR
, m_sysDescription
, DB_BIND_STATIC
);
545 DBBind(hStmt
, 13, DB_SQLTYPE_VARCHAR
, m_agentVersion
, DB_BIND_STATIC
);
546 DBBind(hStmt
, 14, DB_SQLTYPE_VARCHAR
, m_platformName
, DB_BIND_STATIC
);
547 DBBind(hStmt
, 15, DB_SQLTYPE_INTEGER
, m_pollerNode
);
548 DBBind(hStmt
, 16, DB_SQLTYPE_INTEGER
, m_zoneUIN
);
549 DBBind(hStmt
, 17, DB_SQLTYPE_INTEGER
, m_agentProxy
);
550 DBBind(hStmt
, 18, DB_SQLTYPE_INTEGER
, m_snmpProxy
);
551 DBBind(hStmt
, 19, DB_SQLTYPE_INTEGER
, m_icmpProxy
);
552 DBBind(hStmt
, 20, DB_SQLTYPE_INTEGER
, (LONG
)m_requiredPollCount
);
553 DBBind(hStmt
, 21, DB_SQLTYPE_INTEGER
, (LONG
)m_nUseIfXTable
);
555 DBBind(hStmt
, 22, DB_SQLTYPE_VARCHAR
, WideStringFromMBString(m_snmpSecurity
->getAuthPassword()), DB_BIND_DYNAMIC
);
556 DBBind(hStmt
, 23, DB_SQLTYPE_VARCHAR
, WideStringFromMBString(m_snmpSecurity
->getPrivPassword()), DB_BIND_DYNAMIC
);
558 DBBind(hStmt
, 22, DB_SQLTYPE_VARCHAR
, m_snmpSecurity
->getAuthPassword(), DB_BIND_STATIC
);
559 DBBind(hStmt
, 23, DB_SQLTYPE_VARCHAR
, m_snmpSecurity
->getPrivPassword(), DB_BIND_STATIC
);
561 DBBind(hStmt
, 24, DB_SQLTYPE_INTEGER
, (LONG
)snmpMethods
);
562 DBBind(hStmt
, 25, DB_SQLTYPE_VARCHAR
, m_sysName
, DB_BIND_STATIC
);
563 DBBind(hStmt
, 26, DB_SQLTYPE_VARCHAR
, BinToStr(m_baseBridgeAddress
, MAC_ADDR_LENGTH
, baseAddress
), DB_BIND_STATIC
);
564 DBBind(hStmt
, 27, DB_SQLTYPE_INTEGER
, (LONG
)m_downSince
);
565 DBBind(hStmt
, 28, DB_SQLTYPE_VARCHAR
, (m_driver
!= NULL
) ? m_driver
->getName() : _T(""), DB_BIND_STATIC
);
566 DBBind(hStmt
, 29, DB_SQLTYPE_VARCHAR
, m_rackImage
); // rack image
567 DBBind(hStmt
, 30, DB_SQLTYPE_INTEGER
, m_rackPosition
); // rack position
568 DBBind(hStmt
, 31, DB_SQLTYPE_INTEGER
, m_rackHeight
); // device height in rack units
569 DBBind(hStmt
, 32, DB_SQLTYPE_INTEGER
, m_rackId
); // rack ID
570 DBBind(hStmt
, 33, DB_SQLTYPE_INTEGER
, (LONG
)m_bootTime
);
571 DBBind(hStmt
, 34, DB_SQLTYPE_VARCHAR
, _itot(m_agentCacheMode
, cacheMode
, 10), DB_BIND_STATIC
, 1);
572 DBBind(hStmt
, 35, DB_SQLTYPE_VARCHAR
, m_sysContact
, DB_BIND_STATIC
);
573 DBBind(hStmt
, 36, DB_SQLTYPE_VARCHAR
, m_sysLocation
, DB_BIND_STATIC
);
574 DBBind(hStmt
, 37, DB_SQLTYPE_INTEGER
, (LONG
)m_lastAgentCommTime
);
575 DBBind(hStmt
, 38, DB_SQLTYPE_BIGINT
, m_syslogMessageCount
);
576 DBBind(hStmt
, 39, DB_SQLTYPE_BIGINT
, m_snmpTrapCount
);
577 DBBind(hStmt
, 40, DB_SQLTYPE_INTEGER
, (INT32
)m_type
);
578 DBBind(hStmt
, 41, DB_SQLTYPE_VARCHAR
, m_subType
, DB_BIND_STATIC
);
579 DBBind(hStmt
, 42, DB_SQLTYPE_VARCHAR
, m_sshLogin
, DB_BIND_STATIC
);
580 DBBind(hStmt
, 43, DB_SQLTYPE_VARCHAR
, m_sshPassword
, DB_BIND_STATIC
);
581 DBBind(hStmt
, 44, DB_SQLTYPE_INTEGER
, m_sshProxy
);
582 DBBind(hStmt
, 45, DB_SQLTYPE_INTEGER
, m_chassisId
);
583 DBBind(hStmt
, 46, DB_SQLTYPE_INTEGER
, m_portRowCount
);
584 DBBind(hStmt
, 47, DB_SQLTYPE_INTEGER
, m_portNumberingScheme
);
585 DBBind(hStmt
, 48, DB_SQLTYPE_VARCHAR
, _itot(m_agentCompressionMode
, compressionMode
, 10), DB_BIND_STATIC
, 1);
586 DBBind(hStmt
, 49, DB_SQLTYPE_VARCHAR
, m_tunnelId
);
587 DBBind(hStmt
, 50, DB_SQLTYPE_VARCHAR
, m_lldpNodeId
, DB_BIND_STATIC
);
588 DBBind(hStmt
, 51, DB_SQLTYPE_INTEGER
, (LONG
)m_failTimeSNMP
);
589 DBBind(hStmt
, 52, DB_SQLTYPE_INTEGER
, (LONG
)m_failTimeAgent
);
590 DBBind(hStmt
, 53, DB_SQLTYPE_INTEGER
, m_id
);
592 success
= DBExecute(hStmt
);
593 DBFreeStatement(hStmt
);
603 success
= saveACLToDB(hdb
);
607 // Save data collection items
608 if (success
&& (m_modified
& MODIFY_DATA_COLLECTION
))
610 lockDciAccess(false);
611 for(int i
= 0; success
&& (i
< m_dcObjects
->size()); i
++)
612 success
= m_dcObjects
->get(i
)->saveToDatabase(hdb
);
616 // Clear modifications flag
625 * Save runtime data to database. Called only on server shutdown to save
626 * less important but frequently changing runtime data when it is not feasible
627 * to mark object as modified on each change of such data.
629 bool Node::saveRuntimeData(DB_HANDLE hdb
)
631 if (!DataCollectionTarget::saveRuntimeData(hdb
))
634 DB_STATEMENT hStmt
= DBPrepare(hdb
, _T("UPDATE nodes SET last_agent_comm_time=?,syslog_msg_count=?,snmp_trap_count=? WHERE id=?"));
639 DBBind(hStmt
, 1, DB_SQLTYPE_INTEGER
, (INT32
)m_lastAgentCommTime
);
640 DBBind(hStmt
, 2, DB_SQLTYPE_BIGINT
, m_syslogMessageCount
);
641 DBBind(hStmt
, 3, DB_SQLTYPE_BIGINT
, m_snmpTrapCount
);
642 DBBind(hStmt
, 4, DB_SQLTYPE_INTEGER
, m_id
);
645 bool success
= DBExecute(hStmt
);
646 DBFreeStatement(hStmt
);
651 * Delete object from database
653 bool Node::deleteFromDatabase(DB_HANDLE hdb
)
655 bool success
= DataCollectionTarget::deleteFromDatabase(hdb
);
657 success
= executeQueryOnObject(hdb
, _T("DELETE FROM nodes WHERE id=?"));
659 success
= executeQueryOnObject(hdb
, _T("DELETE FROM nsmap WHERE node_id=?"));
664 * Get ARP cache from node
666 ARP_CACHE
*Node::getArpCache()
668 ARP_CACHE
*pArpCache
= NULL
;
670 if (m_capabilities
& NC_IS_LOCAL_MGMT
)
672 pArpCache
= GetLocalArpCache();
674 else if (m_capabilities
& NC_IS_NATIVE_AGENT
)
676 AgentConnectionEx
*conn
= getAgentConnection();
679 pArpCache
= conn
->getArpCache();
683 else if (m_capabilities
& NC_IS_SNMP
)
685 SNMP_Transport
*pTransport
;
687 pTransport
= createSnmpTransport();
688 if (pTransport
!= NULL
)
690 pArpCache
= SnmpGetArpCache(m_snmpVersion
, pTransport
);
699 * Get list of interfaces from node
701 InterfaceList
*Node::getInterfaceList()
703 InterfaceList
*pIfList
= NULL
;
705 if ((m_capabilities
& NC_IS_NATIVE_AGENT
) && (!(m_flags
& NF_DISABLE_NXCP
)))
707 AgentConnectionEx
*conn
= getAgentConnection();
710 pIfList
= conn
->getInterfaceList();
714 if ((pIfList
== NULL
) && (m_capabilities
& NC_IS_LOCAL_MGMT
))
716 pIfList
= GetLocalInterfaceList();
718 if ((pIfList
== NULL
) && (m_capabilities
& NC_IS_SNMP
) &&
719 (!(m_flags
& NF_DISABLE_SNMP
)) && (m_driver
!= NULL
))
721 SNMP_Transport
*pTransport
= createSnmpTransport();
722 if (pTransport
!= NULL
)
725 if (m_nUseIfXTable
== IFXTABLE_DEFAULT
)
727 useIfXTable
= (ConfigReadInt(_T("UseIfXTable"), 1) != 0) ? true : false;
731 useIfXTable
= (m_nUseIfXTable
== IFXTABLE_ENABLED
) ? true : false;
734 int useAliases
= ConfigReadInt(_T("UseInterfaceAliases"), 0);
735 pIfList
= m_driver
->getInterfaces(pTransport
, &m_customAttributes
, m_driverData
, useAliases
, useIfXTable
);
737 if ((pIfList
!= NULL
) && (m_capabilities
& NC_IS_BRIDGE
))
739 BridgeMapPorts(pTransport
, pIfList
);
747 checkInterfaceNames(pIfList
);
748 addVrrpInterfaces(pIfList
);
755 * Add VRRP interfaces to interface list
757 void Node::addVrrpInterfaces(InterfaceList
*ifList
)
763 if (m_vrrpInfo
!= NULL
)
765 DbgPrintf(6, _T("Node::addVrrpInterfaces(node=%s [%d]): m_vrrpInfo->size()=%d"), m_name
, (int)m_id
, m_vrrpInfo
->size());
767 for(i
= 0; i
< m_vrrpInfo
->size(); i
++)
769 VrrpRouter
*router
= m_vrrpInfo
->getRouter(i
);
770 DbgPrintf(6, _T("Node::addVrrpInterfaces(node=%s [%d]): vrouter %d state=%d"), m_name
, (int)m_id
, i
, router
->getState());
771 if (router
->getState() != VRRP_STATE_MASTER
)
772 continue; // Do not add interfaces if router is not in master state
774 // Get netmask for this VR
776 for(j
= 0; j
< ifList
->size(); j
++)
778 InterfaceInfo
*iface
= ifList
->get(j
);
779 if (iface
->index
== router
->getIfIndex())
781 for(int k
= 0; k
< iface
->ipAddrList
.size(); k
++)
783 const InetAddress
& addr
= iface
->ipAddrList
.get(k
);
784 if (addr
.getSubnetAddress().contain(router
->getVip(0)))
786 maskBits
= addr
.getMaskBits();
793 // Walk through all VR virtual IPs
794 for(j
= 0; j
< router
->getVipCount(); j
++)
796 UINT32 vip
= router
->getVip(j
);
797 DbgPrintf(6, _T("Node::addVrrpInterfaces(node=%s [%d]): checking VIP %s@%d"), m_name
, (int)m_id
, IpToStr(vip
, buffer
), i
);
800 for(k
= 0; k
< ifList
->size(); k
++)
801 if (ifList
->get(k
)->hasAddress(vip
))
803 if (k
== ifList
->size())
805 InterfaceInfo
*iface
= new InterfaceInfo(0);
806 _sntprintf(iface
->name
, MAX_DB_STRING
, _T("vrrp.%u.%u.%d"), router
->getId(), router
->getIfIndex(), j
);
807 memcpy(iface
->macAddr
, router
->getVirtualMacAddr(), MAC_ADDR_LENGTH
);
808 InetAddress
addr(vip
);
809 addr
.setMaskBits(maskBits
);
810 iface
->ipAddrList
.add(addr
);
812 DbgPrintf(6, _T("Node::addVrrpInterfaces(node=%s [%d]): added interface %s"), m_name
, (int)m_id
, iface
->name
);
822 * Find interface by index.
824 * @param ifIndex interface index to match
825 * @return pointer to interface object or NULL if appropriate interface couldn't be found
827 Interface
*Node::findInterfaceByIndex(UINT32 ifIndex
)
829 lockChildList(false);
830 for(int i
= 0; i
< m_childList
->size(); i
++)
831 if (m_childList
->get(i
)->getObjectClass() == OBJECT_INTERFACE
)
833 Interface
*pInterface
= (Interface
*)m_childList
->get(i
);
834 if (pInterface
->getIfIndex() == ifIndex
)
845 * Find interface by name or description
846 * Returns pointer to interface object or NULL if appropriate interface couldn't be found
848 Interface
*Node::findInterfaceByName(const TCHAR
*name
)
850 if ((name
== NULL
) || (name
[0] == 0))
853 Interface
*pInterface
;
855 lockChildList(false);
856 for(int i
= 0; i
< m_childList
->size(); i
++)
857 if (m_childList
->get(i
)->getObjectClass() == OBJECT_INTERFACE
)
859 pInterface
= (Interface
*)m_childList
->get(i
);
860 if (!_tcsicmp(pInterface
->getName(), name
) || !_tcsicmp(pInterface
->getDescription(), name
))
871 * Find interface by slot/port pair
872 * Returns pointer to interface object or NULL if appropriate interface couldn't be found
874 Interface
*Node::findInterfaceBySlotAndPort(UINT32 slot
, UINT32 port
)
876 lockChildList(false);
877 for(int i
= 0; i
< m_childList
->size(); i
++)
878 if (m_childList
->get(i
)->getObjectClass() == OBJECT_INTERFACE
)
880 Interface
*pInterface
= (Interface
*)m_childList
->get(i
);
881 if (pInterface
->isPhysicalPort() && (pInterface
->getSlotNumber() == slot
) && (pInterface
->getPortNumber() == port
))
892 * Find interface by MAC address
893 * Returns pointer to interface object or NULL if appropriate interface couldn't be found
895 Interface
*Node::findInterfaceByMAC(const BYTE
*macAddr
)
897 Interface
*iface
= NULL
;
898 lockChildList(false);
899 for(int i
= 0; i
< m_childList
->size(); i
++)
901 NetObj
*curr
= m_childList
->get(i
);
902 if (curr
->getObjectClass() == OBJECT_INTERFACE
)
904 if (!memcmp(((Interface
*)curr
)->getMacAddr(), macAddr
, MAC_ADDR_LENGTH
))
906 iface
= (Interface
*)curr
;
916 * Find interface by IP address
917 * Returns pointer to interface object or NULL if appropriate interface couldn't be found
919 Interface
*Node::findInterfaceByIP(const InetAddress
& addr
)
924 lockChildList(false);
925 for(int i
= 0; i
< m_childList
->size(); i
++)
926 if (m_childList
->get(i
)->getObjectClass() == OBJECT_INTERFACE
)
928 Interface
*pInterface
= (Interface
*)m_childList
->get(i
);
929 if (pInterface
->getIpAddressList()->hasAddress(addr
))
940 * Find interface by bridge port number
942 Interface
*Node::findBridgePort(UINT32 bridgePortNumber
)
944 lockChildList(false);
945 for(int i
= 0; i
< m_childList
->size(); i
++)
946 if (m_childList
->get(i
)->getObjectClass() == OBJECT_INTERFACE
)
948 Interface
*pInterface
= (Interface
*)m_childList
->get(i
);
949 if (pInterface
->getBridgePortNumber() == bridgePortNumber
)
960 * Find connection point for node
962 NetObj
*Node::findConnectionPoint(UINT32
*localIfId
, BYTE
*localMacAddr
, int *type
)
965 lockChildList(false);
966 for(int i
= 0; i
< m_childList
->size(); i
++)
968 if (m_childList
->get(i
)->getObjectClass() == OBJECT_INTERFACE
)
970 Interface
*iface
= (Interface
*)m_childList
->get(i
);
971 cp
= FindInterfaceConnectionPoint(iface
->getMacAddr(), type
);
974 *localIfId
= iface
->getId();
975 memcpy(localMacAddr
, iface
->getMacAddr(), MAC_ADDR_LENGTH
);
985 * Find attached access point by MAC address
987 AccessPoint
*Node::findAccessPointByMAC(const BYTE
*macAddr
)
989 AccessPoint
*ap
= NULL
;
990 lockChildList(false);
991 for(int i
= 0; i
< m_childList
->size(); i
++)
993 NetObj
*curr
= m_childList
->get(i
);
994 if (curr
->getObjectClass() == OBJECT_ACCESSPOINT
)
996 if (!memcmp(((AccessPoint
*)curr
)->getMacAddr(), macAddr
, MAC_ADDR_LENGTH
))
998 ap
= (AccessPoint
*)curr
;
1008 * Find access point by radio ID (radio interface index)
1010 AccessPoint
*Node::findAccessPointByRadioId(int rfIndex
)
1012 AccessPoint
*ap
= NULL
;
1013 lockChildList(false);
1014 for(int i
= 0; i
< m_childList
->size(); i
++)
1016 NetObj
*curr
= m_childList
->get(i
);
1017 if (curr
->getObjectClass() == OBJECT_ACCESSPOINT
)
1019 if (((AccessPoint
*)curr
)->isMyRadio(rfIndex
))
1021 ap
= (AccessPoint
*)curr
;
1031 * Find attached access point by BSSID
1033 AccessPoint
*Node::findAccessPointByBSSID(const BYTE
*bssid
)
1035 AccessPoint
*ap
= NULL
;
1036 lockChildList(false);
1037 for(int i
= 0; i
< m_childList
->size(); i
++)
1039 NetObj
*curr
= m_childList
->get(i
);
1040 if (curr
->getObjectClass() == OBJECT_ACCESSPOINT
)
1042 if (!memcmp(((AccessPoint
*)curr
)->getMacAddr(), bssid
, MAC_ADDR_LENGTH
) ||
1043 ((AccessPoint
*)curr
)->isMyRadio(bssid
))
1045 ap
= (AccessPoint
*)curr
;
1055 * Check if given IP address is one of node's interfaces
1057 bool Node::isMyIP(const InetAddress
& addr
)
1059 lockChildList(false);
1060 for(int i
= 0; i
< m_childList
->size(); i
++)
1061 if (m_childList
->get(i
)->getObjectClass() == OBJECT_INTERFACE
)
1063 if (((Interface
*)m_childList
->get(i
))->getIpAddressList()->hasAddress(addr
))
1074 * Filter interface - should return true if system should proceed with interface creation
1076 bool Node::filterInterface(InterfaceInfo
*info
)
1078 NXSL_VM
*vm
= CreateServerScriptVM(_T("Hook::CreateInterface"));
1081 DbgPrintf(7, _T("Node::filterInterface(%s [%u]): hook script \"Hook::CreateInterface\" not found"), m_name
, m_id
);
1086 if (info
->name
[0] != 0)
1088 iface
= new Interface(info
->name
, (info
->description
[0] != 0) ? info
->description
: info
->name
,
1089 info
->index
, info
->ipAddrList
, info
->type
, m_zoneUIN
);
1093 iface
= new Interface(info
->ipAddrList
, m_zoneUIN
, false);
1095 iface
->setMacAddr(info
->macAddr
, false);
1096 iface
->setBridgePortNumber(info
->bridgePort
);
1097 iface
->setSlotNumber(info
->slot
);
1098 iface
->setPortNumber(info
->port
);
1099 iface
->setPhysicalPortFlag(info
->isPhysicalPort
);
1100 iface
->setManualCreationFlag(false);
1101 iface
->setSystemFlag(info
->isSystem
);
1102 iface
->setMTU(info
->mtu
);
1103 iface
->setSpeed(info
->speed
);
1104 iface
->setIfTableSuffix(info
->ifTableSuffixLength
, info
->ifTableSuffix
);
1107 NXSL_Value
*argv
= new NXSL_Value(new NXSL_Object(&g_nxslInterfaceClass
, iface
));
1108 vm
->setGlobalVariable(_T("$node"), new NXSL_Value(new NXSL_Object(&g_nxslNodeClass
, this)));
1109 if (vm
->run(1, &argv
))
1111 NXSL_Value
*result
= vm
->getResult();
1112 if ((result
!= NULL
) && result
->isInteger())
1114 pass
= (result
->getValueAsInt32() != 0);
1119 DbgPrintf(4, _T("Node::filterInterface(%s [%u]): hook script execution error: %s"), m_name
, m_id
, vm
->getErrorText());
1124 DbgPrintf(6, _T("Node::filterInterface(%s [%u]): interface \"%s\" (ifIndex=%d) %s by filter"),
1125 m_name
, m_id
, info
->name
, info
->index
, pass
? _T("accepted") : _T("rejected"));
1130 * Create new interface - convenience wrapper
1132 Interface
*Node::createNewInterface(const InetAddress
& ipAddr
, BYTE
*macAddr
, bool fakeInterface
)
1134 InterfaceInfo
info(1);
1135 info
.ipAddrList
.add(ipAddr
);
1136 if (macAddr
!= NULL
)
1137 memcpy(info
.macAddr
, macAddr
, MAC_ADDR_LENGTH
);
1138 return createNewInterface(&info
, false, fakeInterface
);
1142 * Create new interface
1144 Interface
*Node::createNewInterface(InterfaceInfo
*info
, bool manuallyCreated
, bool fakeInterface
)
1146 bool bSyntheticMask
= false;
1149 DbgPrintf(5, _T("Node::createNewInterface(\"%s\", %d, %d, bp=%d, slot=%d, port=%d) called for node %s [%d]"),
1150 info
->name
, info
->index
, info
->type
, info
->bridgePort
, info
->slot
, info
->port
, m_name
, m_id
);
1151 for(int i
= 0; i
< info
->ipAddrList
.size(); i
++)
1153 const InetAddress
& addr
= info
->ipAddrList
.get(i
);
1154 DbgPrintf(5, _T("Node::createNewInterface(%s): IP address %s/%d"), info
->name
, addr
.toString(buffer
), addr
.getMaskBits());
1157 // Find subnet to place interface object to
1158 if (info
->type
!= IFTYPE_SOFTWARE_LOOPBACK
)
1160 Cluster
*pCluster
= getMyCluster();
1161 for(int i
= 0; i
< info
->ipAddrList
.size(); i
++)
1163 InetAddress addr
= info
->ipAddrList
.get(i
);
1164 bool addToSubnet
= addr
.isValidUnicast() && ((pCluster
== NULL
) || !pCluster
->isSyncAddr(addr
));
1165 DbgPrintf(5, _T("Node::createNewInterface: node=%s [%d] ip=%s/%d cluster=%s [%d] add=%s"),
1166 m_name
, m_id
, addr
.toString(buffer
), addr
.getMaskBits(),
1167 (pCluster
!= NULL
) ? pCluster
->getName() : _T("(null)"),
1168 (pCluster
!= NULL
) ? pCluster
->getId() : 0, addToSubnet
? _T("yes") : _T("no"));
1171 Subnet
*pSubnet
= FindSubnetForNode(m_zoneUIN
, addr
);
1172 if (pSubnet
== NULL
)
1174 // Check if netmask is 0 (detect), and if yes, create
1175 // new subnet with default mask
1176 if (addr
.getMaskBits() == 0)
1178 bSyntheticMask
= true;
1179 addr
.setMaskBits((addr
.getFamily() == AF_INET
) ? ConfigReadInt(_T("DefaultSubnetMaskIPv4"), 24) : ConfigReadInt(_T("DefaultSubnetMaskIPv6"), 64));
1180 info
->ipAddrList
.replace(addr
);
1183 // Create new subnet object
1184 if (addr
.getHostBits() >= 2)
1186 pSubnet
= createSubnet(addr
, bSyntheticMask
);
1189 // createSubnet may adjust address mask bits
1190 info
->ipAddrList
.replace(addr
);
1196 // Set correct netmask if we were asked for it
1197 if (addr
.getMaskBits() == 0)
1199 bSyntheticMask
= pSubnet
->isSyntheticMask();
1200 addr
.setMaskBits(pSubnet
->getIpAddress().getMaskBits());
1201 info
->ipAddrList
.replace(addr
);
1204 if (pSubnet
!= NULL
)
1206 pSubnet
->addNode(this);
1209 } // loop by address list
1212 // Create interface object
1214 if (info
->name
[0] != 0)
1215 iface
= new Interface(info
->name
, (info
->description
[0] != 0) ? info
->description
: info
->name
,
1216 info
->index
, info
->ipAddrList
, info
->type
, m_zoneUIN
);
1218 iface
= new Interface(info
->ipAddrList
, m_zoneUIN
, bSyntheticMask
);
1219 iface
->setMacAddr(info
->macAddr
, false);
1220 iface
->setBridgePortNumber(info
->bridgePort
);
1221 iface
->setSlotNumber(info
->slot
);
1222 iface
->setPortNumber(info
->port
);
1223 iface
->setPhysicalPortFlag(info
->isPhysicalPort
);
1224 iface
->setManualCreationFlag(manuallyCreated
);
1225 iface
->setSystemFlag(info
->isSystem
);
1226 iface
->setMTU(info
->mtu
);
1227 iface
->setSpeed(info
->speed
);
1228 iface
->setIfTableSuffix(info
->ifTableSuffixLength
, info
->ifTableSuffix
);
1230 int defaultExpectedState
= ConfigReadInt(_T("DefaultInterfaceExpectedState"), IF_DEFAULT_EXPECTED_STATE_UP
);
1231 switch(defaultExpectedState
)
1233 case IF_DEFAULT_EXPECTED_STATE_AUTO
:
1234 iface
->setExpectedState(fakeInterface
? IF_EXPECTED_STATE_UP
: IF_EXPECTED_STATE_AUTO
);
1236 case IF_DEFAULT_EXPECTED_STATE_IGNORE
:
1237 iface
->setExpectedState(IF_EXPECTED_STATE_IGNORE
);
1240 iface
->setExpectedState(IF_EXPECTED_STATE_UP
);
1244 // Insert to objects' list and generate event
1245 NetObjInsert(iface
, true, false);
1246 addInterface(iface
);
1249 if (!iface
->isSystem())
1251 const InetAddress
& addr
= iface
->getFirstIpAddress();
1252 PostEvent(EVENT_INTERFACE_ADDED
, m_id
, "dsAdd", iface
->getId(),
1253 iface
->getName(), &addr
, addr
.getMaskBits(), iface
->getIfIndex());
1260 * Delete interface from node
1262 void Node::deleteInterface(Interface
*iface
)
1264 DbgPrintf(5, _T("Node::deleteInterface(node=%s [%d], interface=%s [%d])"), m_name
, m_id
, iface
->getName(), iface
->getId());
1266 // Check if we should unlink node from interface's subnet
1267 if (!iface
->isExcludedFromTopology())
1269 const ObjectArray
<InetAddress
> *list
= iface
->getIpAddressList()->getList();
1270 for(int i
= 0; i
< list
->size(); i
++)
1272 bool doUnlink
= true;
1273 const InetAddress
*addr
= list
->get(i
);
1275 lockChildList(false);
1276 for(int j
= 0; j
< m_childList
->size(); j
++)
1278 NetObj
*curr
= m_childList
->get(j
);
1279 if ((curr
->getObjectClass() == OBJECT_INTERFACE
) && (curr
!= iface
) &&
1280 ((Interface
*)curr
)->getIpAddressList()->findSameSubnetAddress(*addr
).isValid())
1290 // Last interface in subnet, should unlink node
1291 Subnet
*pSubnet
= FindSubnetByIP(m_zoneUIN
, addr
->getSubnetAddress());
1292 if (pSubnet
!= NULL
)
1294 deleteParent(pSubnet
);
1295 pSubnet
->deleteChild(this);
1297 DbgPrintf(5, _T("Node::deleteInterface(node=%s [%d], interface=%s [%d]): unlinked from subnet %s [%d]"),
1298 m_name
, m_id
, iface
->getName(), iface
->getId(),
1299 (pSubnet
!= NULL
) ? pSubnet
->getName() : _T("(null)"),
1300 (pSubnet
!= NULL
) ? pSubnet
->getId() : 0);
1304 iface
->deleteObject();
1308 * Calculate node status based on child objects status
1310 void Node::calculateCompoundStatus(BOOL bForcedRecalc
)
1312 int iOldStatus
= m_status
;
1313 static UINT32 dwEventCodes
[] = { EVENT_NODE_NORMAL
, EVENT_NODE_WARNING
,
1314 EVENT_NODE_MINOR
, EVENT_NODE_MAJOR
, EVENT_NODE_CRITICAL
,
1315 EVENT_NODE_UNKNOWN
, EVENT_NODE_UNMANAGED
};
1317 DataCollectionTarget::calculateCompoundStatus(bForcedRecalc
);
1318 if (m_status
!= iOldStatus
)
1319 PostEvent(dwEventCodes
[m_status
], m_id
, "d", iOldStatus
);
1323 * Perform status poll on node
1325 void Node::statusPoll(PollerInfo
*poller
, ClientSession
*pSession
, UINT32 rqId
)
1327 if (m_runtimeFlags
& DCDF_DELETE_IN_PROGRESS
)
1330 m_runtimeFlags
&= ~DCDF_QUEUED_FOR_STATUS_POLL
;
1334 if (IsShutdownInProgress())
1337 UINT32 oldCapabilities
= m_capabilities
;
1338 UINT32 oldState
= m_state
;
1339 NetObj
*pPollerNode
= NULL
, **ppPollList
;
1340 SNMP_Transport
*pTransport
;
1342 time_t tNow
, tExpire
;
1344 Queue
*pQueue
= new Queue
; // Delayed event queue
1345 poller
->setStatus(_T("wait for lock"));
1348 if (IsShutdownInProgress())
1355 m_pollRequestor
= pSession
;
1356 sendPollerMsg(rqId
, _T("Starting status poll for node %s\r\n"), m_name
);
1357 nxlog_debug(5, _T("Starting status poll for node %s (ID: %d)"), m_name
, m_id
);
1359 // Read capability expiration time and current time
1360 tExpire
= (time_t)ConfigReadULong(_T("CapabilityExpirationTime"), 604800);
1363 bool agentConnected
= false;
1367 restart_agent_check
:
1368 if (g_flags
& AF_RESOLVE_IP_FOR_EACH_STATUS_POLL
)
1370 updatePrimaryIpAddr();
1373 int requiredPolls
= (m_requiredPollCount
> 0) ? m_requiredPollCount
: g_requiredPolls
;
1375 // Check SNMP agent connectivity
1376 if ((m_capabilities
& NC_IS_SNMP
) && (!(m_flags
& NF_DISABLE_SNMP
)) && m_ipAddress
.isValidUnicast())
1378 TCHAR szBuffer
[256];
1381 nxlog_debug(6, _T("StatusPoll(%s): check SNMP"), m_name
);
1382 pTransport
= createSnmpTransport();
1383 if (pTransport
!= NULL
)
1385 poller
->setStatus(_T("check SNMP"));
1386 sendPollerMsg(rqId
, _T("Checking SNMP agent connectivity\r\n"));
1387 const TCHAR
*testOid
= m_customAttributes
.get(_T("snmp.testoid"));
1388 if (testOid
== NULL
)
1390 testOid
= _T(".1.3.6.1.2.1.1.2.0");
1392 dwResult
= SnmpGet(m_snmpVersion
, pTransport
, testOid
, NULL
, 0, szBuffer
, sizeof(szBuffer
), 0);
1393 if ((dwResult
== SNMP_ERR_SUCCESS
) || (dwResult
== SNMP_ERR_NO_OBJECT
))
1395 if (m_state
& NSF_SNMP_UNREACHABLE
)
1398 if (m_pollCountSNMP
>= requiredPolls
)
1400 m_state
&= ~NSF_SNMP_UNREACHABLE
;
1401 PostEventEx(pQueue
, EVENT_SNMP_OK
, m_id
, NULL
);
1402 sendPollerMsg(rqId
, POLLER_INFO
_T("Connectivity with SNMP agent restored\r\n"));
1403 m_pollCountSNMP
= 0;
1408 m_pollCountSNMP
= 0;
1410 // Update authoritative engine data for SNMPv3
1411 if ((pTransport
->getSnmpVersion() == SNMP_VERSION_3
) && (pTransport
->getAuthoritativeEngine() != NULL
))
1414 m_snmpSecurity
->setAuthoritativeEngine(*pTransport
->getAuthoritativeEngine());
1418 else if ((dwResult
== SNMP_ERR_ENGINE_ID
) && (m_snmpVersion
== SNMP_VERSION_3
) && (retryCount
> 0))
1420 // Reset authoritative engine data
1422 m_snmpSecurity
->setAuthoritativeEngine(SNMP_Engine());
1426 goto restart_agent_check
;
1430 if (pTransport
->isProxyTransport() && (dwResult
== SNMP_ERR_COMM
))
1433 AgentConnectionEx
*pconn
= acquireProxyConnection(SNMP_PROXY
, true);
1436 pconn
->decRefCount();
1441 goto restart_agent_check
;
1446 nxlog_debug(6, _T("StatusPoll(%s): got communication error on proxy transport, checking connection to proxy. Poll count: %d of %d"), m_name
, m_pollCountSNMP
, m_requiredPollCount
);
1447 sendPollerMsg(rqId
, POLLER_ERROR
_T("SNMP agent unreachable\r\n"));
1448 if (m_state
& NSF_SNMP_UNREACHABLE
)
1450 if ((tNow
> m_failTimeSNMP
+ tExpire
) && (!(m_state
& DCSF_UNREACHABLE
)))
1452 m_capabilities
&= ~NC_IS_SNMP
;
1453 m_state
&= ~NSF_SNMP_UNREACHABLE
;
1454 m_snmpObjectId
[0] = 0;
1455 sendPollerMsg(rqId
, POLLER_WARNING
_T("Attribute isSNMP set to FALSE\r\n"));
1461 if (m_pollCountSNMP
>= requiredPolls
)
1463 m_state
|= NSF_SNMP_UNREACHABLE
;
1464 PostEventEx(pQueue
, EVENT_SNMP_FAIL
, m_id
, NULL
);
1465 m_failTimeSNMP
= tNow
;
1466 m_pollCountSNMP
= 0;
1474 nxlog_debug(6, _T("StatusPoll(%s): cannot create SNMP transport"), m_name
);
1476 nxlog_debug(6, _T("StatusPoll(%s): SNMP check finished"), m_name
);
1479 // Check native agent connectivity
1480 if ((m_capabilities
& NC_IS_NATIVE_AGENT
) && (!(m_flags
& NF_DISABLE_NXCP
)))
1482 nxlog_debug(6, _T("StatusPoll(%s): checking agent"), m_name
);
1483 poller
->setStatus(_T("check agent"));
1484 sendPollerMsg(rqId
, _T("Checking NetXMS agent connectivity\r\n"));
1486 UINT32 error
, socketError
;
1489 if (connectToAgent(&error
, &socketError
, &newConnection
, true))
1491 nxlog_debug(7, _T("StatusPoll(%s): connected to agent"), m_name
);
1492 if (m_state
& NSF_AGENT_UNREACHABLE
)
1495 if (m_pollCountAgent
>= requiredPolls
)
1497 m_state
&= ~NSF_AGENT_UNREACHABLE
;
1498 PostEventEx(pQueue
, EVENT_AGENT_OK
, m_id
, NULL
);
1499 sendPollerMsg(rqId
, POLLER_INFO
_T("Connectivity with NetXMS agent restored\r\n"));
1500 m_pollCountAgent
= 0;
1504 m_pollCountAgent
= 0;
1505 agentConnected
= true;
1509 nxlog_debug(6, _T("StatusPoll(%s): agent unreachable, error=%d, socketError=%d. Poll count %d of %d"), m_name
, (int)error
, (int)socketError
, m_pollCountAgent
, m_requiredPollCount
);
1510 sendPollerMsg(rqId
, POLLER_ERROR
_T("NetXMS agent unreachable\r\n"));
1511 if (m_state
& NSF_AGENT_UNREACHABLE
)
1513 if ((tNow
> m_failTimeAgent
+ tExpire
) && !(m_state
& DCSF_UNREACHABLE
))
1515 m_capabilities
&= ~NC_IS_NATIVE_AGENT
;
1516 m_state
&= ~NSF_AGENT_UNREACHABLE
;
1517 m_platformName
[0] = 0;
1518 m_agentVersion
[0] = 0;
1519 sendPollerMsg(rqId
, POLLER_WARNING
_T("Attribute isNetXMSAgent set to FALSE\r\n"));
1525 if (m_pollCountAgent
>= requiredPolls
)
1527 m_state
|= NSF_AGENT_UNREACHABLE
;
1528 PostEventEx(pQueue
, EVENT_AGENT_FAIL
, m_id
, NULL
);
1529 m_failTimeAgent
= tNow
;
1530 //cancel file monitoring locally(on agent it is canceled if agent have fallen)
1531 g_monitoringList
.removeDisconnectedNode(m_id
);
1532 m_pollCountAgent
= 0;
1537 nxlog_debug(7, _T("StatusPoll(%s): agent check finished"), m_name
);
1539 // If file update connection is active, send NOP command to prevent disconnection by idle timeout
1540 AgentConnection
*fileUpdateConnection
;
1542 fileUpdateConnection
= m_fileUpdateConn
;
1543 if (fileUpdateConnection
!= NULL
)
1544 fileUpdateConnection
->incRefCount();
1546 if (fileUpdateConnection
!= NULL
)
1548 nxlog_debug(6, _T("StatusPoll(%s): sending keepalive command on file monitoring connection"), m_name
);
1549 fileUpdateConnection
->nop();
1550 fileUpdateConnection
->decRefCount();
1554 poller
->setStatus(_T("prepare polling list"));
1556 // Find service poller node object
1558 if (m_pollerNode
!= 0)
1560 UINT32 id
= m_pollerNode
;
1562 pPollerNode
= FindObjectById(id
);
1563 if (pPollerNode
!= NULL
)
1565 if (pPollerNode
->getObjectClass() != OBJECT_NODE
)
1574 // If nothing found, use management server
1575 if (pPollerNode
== NULL
)
1577 pPollerNode
= FindObjectById(g_dwMgmtNode
);
1578 if (pPollerNode
!= NULL
)
1579 pPollerNode
->incRefCount();
1583 pPollerNode
->incRefCount();
1586 // Create polling list
1587 ppPollList
= (NetObj
**)malloc(sizeof(NetObj
*) * m_childList
->size());
1588 lockChildList(false);
1589 int pollListSize
= 0;
1590 for(int i
= 0; i
< m_childList
->size(); i
++)
1592 NetObj
*curr
= m_childList
->get(i
);
1593 if (curr
->getStatus() != STATUS_UNMANAGED
)
1595 curr
->incRefCount();
1596 ppPollList
[pollListSize
++] = curr
;
1601 // Poll interfaces and services
1602 poller
->setStatus(_T("child poll"));
1603 DbgPrintf(7, _T("StatusPoll(%s): starting child object poll"), m_name
);
1604 pCluster
= getMyCluster();
1605 pTransport
= createSnmpTransport();
1606 for(int i
= 0; i
< pollListSize
; i
++)
1608 switch(ppPollList
[i
]->getObjectClass())
1610 case OBJECT_INTERFACE
:
1611 DbgPrintf(7, _T("StatusPoll(%s): polling interface %d [%s]"), m_name
, ppPollList
[i
]->getId(), ppPollList
[i
]->getName());
1612 ((Interface
*)ppPollList
[i
])->statusPoll(pSession
, rqId
, pQueue
, pCluster
, pTransport
, m_icmpProxy
);
1614 case OBJECT_NETWORKSERVICE
:
1615 DbgPrintf(7, _T("StatusPoll(%s): polling network service %d [%s]"), m_name
, ppPollList
[i
]->getId(), ppPollList
[i
]->getName());
1616 ((NetworkService
*)ppPollList
[i
])->statusPoll(pSession
, rqId
, (Node
*)pPollerNode
, pQueue
);
1618 case OBJECT_ACCESSPOINT
:
1619 DbgPrintf(7, _T("StatusPoll(%s): polling access point %d [%s]"), m_name
, ppPollList
[i
]->getId(), ppPollList
[i
]->getName());
1620 ((AccessPoint
*)ppPollList
[i
])->statusPollFromController(pSession
, rqId
, pQueue
, this, pTransport
);
1623 DbgPrintf(7, _T("StatusPoll(%s): skipping object %d [%s] class %d"), m_name
, ppPollList
[i
]->getId(), ppPollList
[i
]->getName(), ppPollList
[i
]->getObjectClass());
1626 ppPollList
[i
]->decRefCount();
1630 DbgPrintf(7, _T("StatusPoll(%s): finished child object poll"), m_name
);
1632 // Check if entire node is down
1633 // This check is disabled for nodes without IP address
1634 // The only exception is node without valid address connected via agent tunnel
1635 if (m_ipAddress
.isValidUnicast() || agentConnected
)
1637 bool allDown
= true;
1638 lockChildList(false);
1639 for(int i
= 0; i
< m_childList
->size(); i
++)
1641 NetObj
*curr
= m_childList
->get(i
);
1642 if ((curr
->getObjectClass() == OBJECT_INTERFACE
) &&
1643 (((Interface
*)curr
)->getAdminState() != IF_ADMIN_STATE_DOWN
) &&
1644 (((Interface
*)curr
)->getConfirmedOperState() == IF_OPER_STATE_UP
) &&
1645 (curr
->getStatus() != STATUS_UNMANAGED
))
1652 if (allDown
&& (m_capabilities
& NC_IS_NATIVE_AGENT
) &&
1653 (!(m_flags
& NF_DISABLE_NXCP
)))
1654 if (!(m_state
& NSF_AGENT_UNREACHABLE
))
1656 if (allDown
&& (m_capabilities
& NC_IS_SNMP
) &&
1657 (!(m_flags
& NF_DISABLE_SNMP
)))
1658 if (!(m_state
& NSF_SNMP_UNREACHABLE
))
1661 DbgPrintf(2, _T("StatusPoll(%s): allDown=%s, statFlags=0x%08X"), m_name
, allDown
? _T("true") : _T("false"), m_state
);
1664 if (!(m_state
& DCSF_UNREACHABLE
))
1666 m_state
|= DCSF_UNREACHABLE
;
1667 m_downSince
= time(NULL
);
1668 poller
->setStatus(_T("check network path"));
1669 if (checkNetworkPath(rqId
))
1671 m_state
|= DCSF_NETWORK_PATH_PROBLEM
;
1673 // Set interfaces and network services to UNKNOWN state
1674 lockChildList(false);
1675 for(int i
= 0; i
< m_childList
->size(); i
++)
1677 NetObj
*curr
= m_childList
->get(i
);
1678 if ((curr
->getObjectClass() == OBJECT_INTERFACE
) || (curr
->getObjectClass() == OBJECT_NETWORKSERVICE
))
1680 curr
->resetStatus();
1685 // Clear delayed event queue
1688 Event
*e
= (Event
*)pQueue
->get();
1693 delete_and_null(pQueue
);
1695 PostEvent(EVENT_NODE_UNREACHABLE
, m_id
, NULL
);
1699 PostEvent(EVENT_NODE_DOWN
, m_id
, NULL
);
1701 g_monitoringList
.removeDisconnectedNode(m_id
);
1702 sendPollerMsg(rqId
, POLLER_ERROR
_T("Node is unreachable\r\n"));
1706 sendPollerMsg(rqId
, POLLER_WARNING
_T("Node is still unreachable\r\n"));
1712 if (m_state
& DCSF_UNREACHABLE
)
1714 int reason
= (m_state
& DCSF_NETWORK_PATH_PROBLEM
) ? 1 : 0;
1715 m_state
&= ~(DCSF_UNREACHABLE
| NSF_SNMP_UNREACHABLE
| NSF_AGENT_UNREACHABLE
| DCSF_NETWORK_PATH_PROBLEM
);
1716 PostEvent(EVENT_NODE_UP
, m_id
, "d", reason
);
1717 sendPollerMsg(rqId
, POLLER_INFO
_T("Node recovered from unreachable state\r\n"));
1718 goto restart_agent_check
;
1722 sendPollerMsg(rqId
, POLLER_INFO
_T("Node is connected\r\n"));
1727 // Get uptime and update boot time
1728 if (!(m_state
& DCSF_UNREACHABLE
))
1730 TCHAR buffer
[MAX_RESULT_LENGTH
];
1731 if (getItemFromAgent(_T("System.Uptime"), MAX_RESULT_LENGTH
, buffer
) == DCE_SUCCESS
)
1733 m_bootTime
= time(NULL
) - _tcstol(buffer
, NULL
, 0);
1734 DbgPrintf(5, _T("StatusPoll(%s [%d]): boot time set to %u from agent"), m_name
, m_id
, (UINT32
)m_bootTime
);
1736 else if (getItemFromSNMP(m_snmpPort
, _T(".1.3.6.1.2.1.1.3.0"), MAX_RESULT_LENGTH
, buffer
, SNMP_RAWTYPE_NONE
) == DCE_SUCCESS
)
1738 m_bootTime
= time(NULL
) - _tcstol(buffer
, NULL
, 0) / 100; // sysUpTime is in hundredths of a second
1739 DbgPrintf(5, _T("StatusPoll(%s [%d]): boot time set to %u from SNMP"), m_name
, m_id
, (UINT32
)m_bootTime
);
1743 DbgPrintf(5, _T("StatusPoll(%s [%d]): unable to get system uptime"), m_name
, m_id
);
1751 // Get agent uptime to check if it was restared
1752 if (!(m_state
& DCSF_UNREACHABLE
) && isNativeAgent())
1754 TCHAR buffer
[MAX_RESULT_LENGTH
];
1755 if (getItemFromAgent(_T("Agent.Uptime"), MAX_RESULT_LENGTH
, buffer
) == DCE_SUCCESS
)
1757 time_t oldAgentuptime
= m_agentUpTime
;
1758 m_agentUpTime
= _tcstol(buffer
, NULL
, 0);
1759 if ((UINT32
)oldAgentuptime
> (UINT32
)m_agentUpTime
)
1761 //cancel file monitoring locally(on agent it is canceled if agent have fallen)
1762 g_monitoringList
.removeDisconnectedNode(m_id
);
1767 DbgPrintf(5, _T("StatusPoll(%s [%d]): unable to get agent uptime"), m_name
, m_id
);
1768 g_monitoringList
.removeDisconnectedNode(m_id
);
1778 if (!(m_state
& DCSF_UNREACHABLE
) && isNativeAgent())
1780 TCHAR buffer
[MAX_RESULT_LENGTH
];
1781 if (getItemFromAgent(_T("GPS.LocationData"), MAX_RESULT_LENGTH
, buffer
) == DCE_SUCCESS
)
1783 GeoLocation loc
= GeoLocation::parseAgentData(buffer
);
1784 if (loc
.getType() != GL_UNSET
)
1786 DbgPrintf(5, _T("StatusPoll(%s [%d]): location set to %s, %s from agent"), m_name
, m_id
, loc
.getLatitudeAsString(), loc
.getLongitudeAsString());
1787 setGeoLocation(loc
);
1792 DbgPrintf(5, _T("StatusPoll(%s [%d]): unable to get system location"), m_name
, m_id
);
1796 // Get agent log and agent local database status
1797 if (!(m_state
& DCSF_UNREACHABLE
) && isNativeAgent())
1799 TCHAR buffer
[MAX_RESULT_LENGTH
];
1800 if (getItemFromAgent(_T("Agent.LogFile.Status"), MAX_RESULT_LENGTH
, buffer
) == DCE_SUCCESS
)
1802 UINT32 status
= _tcstol(buffer
, NULL
, 0);
1804 PostEvent(EVENT_AGENT_LOG_PROBLEM
, m_id
, "ds", status
, _T("could not open"));
1808 nxlog_debug(5, _T("StatusPoll(%s [%d]): unable to get agent log status"), m_name
, m_id
);
1811 if (getItemFromAgent(_T("Agent.LocalDatabase.Status"), MAX_RESULT_LENGTH
, buffer
) == DCE_SUCCESS
)
1813 UINT32 status
= _tcstol(buffer
, NULL
, 0);
1814 const TCHAR
*statusDescription
[3]= {
1816 _T("could not open database"),
1817 _T("could not update database"),
1820 PostEvent(EVENT_AGENT_LOCAL_DATABASE_PROBLEM
, m_id
, "ds", status
, statusDescription
[status
]);
1824 nxlog_debug(5, _T("StatusPoll(%s [%d]): unable to get agent local database status"), m_name
, m_id
);
1828 // Send delayed events and destroy delayed event queue
1831 ResendEvents(pQueue
);
1835 // Call hooks in loaded modules
1836 for(UINT32 i
= 0; i
< g_dwNumModules
; i
++)
1838 if (g_pModuleList
[i
].pfStatusPollHook
!= NULL
)
1840 DbgPrintf(5, _T("StatusPoll(%s [%d]): calling hook in module %s"), m_name
, m_id
, g_pModuleList
[i
].szName
);
1841 g_pModuleList
[i
].pfStatusPollHook(this, pSession
, rqId
, poller
);
1845 // Execute hook script
1846 poller
->setStatus(_T("hook"));
1847 executeHookScript(_T("StatusPoll"));
1849 poller
->setStatus(_T("cleanup"));
1850 if (pPollerNode
!= NULL
)
1851 pPollerNode
->decRefCount();
1853 if (oldCapabilities
!= m_capabilities
)
1854 PostEvent(EVENT_NODE_CAPABILITIES_CHANGED
, m_id
, "xx", oldCapabilities
, m_capabilities
);
1856 if (oldState
!= m_state
|| oldCapabilities
!= m_capabilities
)
1859 setModified(MODIFY_NODE_PROPERTIES
);
1863 calculateCompoundStatus();
1864 m_lastStatusPoll
= time(NULL
);
1865 sendPollerMsg(rqId
, _T("Finished status poll for node %s\r\n"), m_name
);
1866 sendPollerMsg(rqId
, _T("Node status after poll is %s\r\n"), GetStatusAsText(m_status
, true));
1867 m_pollRequestor
= NULL
;
1869 m_runtimeFlags
&= ~DCDF_QUEUED_FOR_STATUS_POLL
;
1871 DbgPrintf(5, _T("Finished status poll for node %s (ID: %d)"), m_name
, m_id
);
1873 // Check if the node has to be deleted due to long downtime
1876 time_t unreachableDeleteDays
= (time_t)ConfigReadInt(_T("DeleteUnreachableNodesPeriod"), 0);
1877 if ((unreachableDeleteDays
> 0) && (m_downSince
> 0) &&
1878 (time(NULL
) - m_downSince
> unreachableDeleteDays
* 24 * 3600))
1886 * Check single element of network path
1888 bool Node::checkNetworkPathElement(UINT32 nodeId
, const TCHAR
*nodeType
, bool isProxy
, UINT32 requestId
, bool secondPass
)
1890 Node
*node
= (Node
*)FindObjectById(nodeId
, OBJECT_NODE
);
1894 nxlog_debug(6, _T("Node::checkNetworkPathElement(%s [%d]): found %s: %s [%d]"), m_name
, m_id
, nodeType
, node
->getName(), node
->getId());
1896 if (secondPass
&& (node
->m_lastStatusPoll
< time(NULL
) - 1))
1898 DbgPrintf(6, _T("Node::checkNetworkPathElement(%s [%d]): forced status poll on node %s [%d]"),
1899 m_name
, m_id
, node
->getName(), node
->getId());
1900 PollerInfo
*poller
= RegisterPoller(POLLER_TYPE_STATUS
, node
);
1901 poller
->startExecution();
1902 node
->statusPoll(poller
, NULL
, 0);
1908 DbgPrintf(5, _T("Node::checkNetworkPathElement(%s [%d]): %s %s [%d] is down"),
1909 m_name
, m_id
, nodeType
, node
->getName(), node
->getId());
1910 sendPollerMsg(requestId
, POLLER_WARNING
_T(" %s %s is down\r\n"), nodeType
, node
->getName());
1913 if (isProxy
&& node
->isNativeAgent() && (node
->getState() & NSF_AGENT_UNREACHABLE
))
1915 DbgPrintf(5, _T("Node::checkNetworkPathElement(%s [%d]): agent on %s %s [%d] is down"),
1916 m_name
, m_id
, nodeType
, node
->getName(), node
->getId());
1917 sendPollerMsg(requestId
, POLLER_WARNING
_T(" Agent on %s %s is down\r\n"), nodeType
, node
->getName());
1924 * Check network path between node and management server to detect possible intermediate node failure - layer 2
1926 * @return true if network path problems found
1928 bool Node::checkNetworkPathLayer2(UINT32 requestId
, bool secondPass
)
1930 time_t now
= time(NULL
);
1932 // Check proxy node(s)
1933 if (IsZoningEnabled() && (m_zoneUIN
!= 0))
1935 Zone
*zone
= FindZoneByUIN(m_zoneUIN
);
1936 if ((zone
!= NULL
) && (zone
->getProxyNodeId() != 0) && (zone
->getProxyNodeId() != m_id
))
1938 if (checkNetworkPathElement(zone
->getProxyNodeId(), _T("zone proxy"), true, requestId
, secondPass
))
1943 // Check directly connected switch
1944 sendPollerMsg(requestId
, _T("Checking ethernet connectivity...\r\n"));
1945 Interface
*iface
= findInterfaceByIP(m_ipAddress
);
1948 if (iface
->getPeerNodeId() != 0)
1950 nxlog_debug(6, _T("Node::checkNetworkPath(%s [%d]): found interface object for primary IP: %s [%d]"), m_name
, m_id
, iface
->getName(), iface
->getId());
1951 if (checkNetworkPathElement(iface
->getPeerNodeId(), _T("upstream switch"), false, requestId
, secondPass
))
1954 Node
*switchNode
= (Node
*)FindObjectById(iface
->getPeerNodeId(), OBJECT_NODE
);
1955 Interface
*switchIface
= (Interface
*)FindObjectById(iface
->getPeerInterfaceId(), OBJECT_INTERFACE
);
1956 if ((switchNode
!= NULL
) && (switchIface
!= NULL
) && (switchIface
->getExpectedState() != IF_EXPECTED_STATE_IGNORE
) &&
1957 ((switchIface
->getAdminState() == IF_ADMIN_STATE_DOWN
) || (switchIface
->getAdminState() == IF_ADMIN_STATE_TESTING
) ||
1958 (switchIface
->getOperState() == IF_OPER_STATE_DOWN
) || (switchIface
->getOperState() == IF_OPER_STATE_TESTING
)))
1960 nxlog_debug(5, _T("Node::checkNetworkPath(%s [%d]): upstream interface %s [%d] on switch %s [%d] is down"),
1961 m_name
, m_id
, switchIface
->getName(), switchIface
->getId(), switchNode
->getName(), switchNode
->getId());
1962 sendPollerMsg(requestId
, POLLER_WARNING
_T(" Upstream interface %s on node %s is down\r\n"), switchIface
->getName(), switchNode
->getName());
1968 BYTE localMacAddr
[MAC_ADDR_LENGTH
];
1969 memcpy(localMacAddr
, iface
->getMacAddr(), MAC_ADDR_LENGTH
);
1971 NetObj
*cp
= FindInterfaceConnectionPoint(localMacAddr
, &type
);
1974 nxlog_debug(6, _T("Node::checkNetworkPath(%s [%d]): found connection point: %s [%d]"), m_name
, m_id
, cp
->getName(), cp
->getId());
1977 Node
*node
= (cp
->getObjectClass() == OBJECT_INTERFACE
) ? ((Interface
*)cp
)->getParentNode() : ((AccessPoint
*)cp
)->getParentNode();
1978 if ((node
!= NULL
) && !node
->isDown() && (node
->m_lastStatusPoll
< now
- 1))
1980 nxlog_debug(6, _T("Node::checkNetworkPath(%s [%d]): forced status poll on node %s [%d]"),
1981 m_name
, m_id
, node
->getName(), node
->getId());
1982 node
->statusPollWorkerEntry(RegisterPoller(POLLER_TYPE_STATUS
, node
), NULL
, 0);
1986 if (cp
->getObjectClass() == OBJECT_INTERFACE
)
1988 Interface
*iface
= (Interface
*)cp
;
1989 if ((iface
->getExpectedState() != IF_EXPECTED_STATE_IGNORE
) &&
1990 ((iface
->getAdminState() == IF_ADMIN_STATE_DOWN
) || (iface
->getAdminState() == IF_ADMIN_STATE_TESTING
) ||
1991 (iface
->getOperState() == IF_OPER_STATE_DOWN
) || (iface
->getOperState() == IF_OPER_STATE_TESTING
)))
1993 nxlog_debug(5, _T("Node::checkNetworkPath(%s [%d]): upstream interface %s [%d] on switch %s [%d] is down"),
1994 m_name
, m_id
, iface
->getName(), iface
->getId(), iface
->getParentNode()->getName(), iface
->getParentNode()->getId());
1995 sendPollerMsg(requestId
, POLLER_WARNING
_T(" Upstream interface %s on node %s is down\r\n"),
1996 iface
->getName(), iface
->getParentNode()->getName());
2000 else if (cp
->getObjectClass() == OBJECT_ACCESSPOINT
)
2002 AccessPoint
*ap
= (AccessPoint
*)cp
;
2003 if (ap
->getStatus() == STATUS_CRITICAL
) // FIXME: how to correctly determine if AP is down?
2005 nxlog_debug(5, _T("Node::checkNetworkPath(%s [%d]): wireless access point %s [%d] is down"),
2006 m_name
, m_id
, ap
->getName(), ap
->getId());
2007 sendPollerMsg(requestId
, POLLER_WARNING
_T(" Wireless access point %s is down\r\n"), ap
->getName());
2016 DbgPrintf(5, _T("Node::checkNetworkPath(%s [%d]): cannot find interface object for primary IP"), m_name
, m_id
);
2022 * Check network path between node and management server to detect possible intermediate node failure - layer 3
2024 * @return true if network path problems found
2026 bool Node::checkNetworkPathLayer3(UINT32 requestId
, bool secondPass
)
2028 Node
*mgmtNode
= (Node
*)FindObjectById(g_dwMgmtNode
);
2029 if (mgmtNode
== NULL
)
2031 DbgPrintf(5, _T("Node::checkNetworkPath(%s [%d]): cannot find management node"), m_name
, m_id
);
2035 NetworkPath
*trace
= TraceRoute(mgmtNode
, this);
2038 DbgPrintf(5, _T("Node::checkNetworkPath(%s [%d]): trace not available"), m_name
, m_id
);
2041 DbgPrintf(5, _T("Node::checkNetworkPath(%s [%d]): trace available, %d hops, %s"),
2042 m_name
, m_id
, trace
->getHopCount(), trace
->isComplete() ? _T("complete") : _T("incomplete"));
2044 // We will do path check in two passes
2045 // If unreachable intermediate node will be found on first pass,
2046 // then method will just return true. Otherwise, we will do
2047 // second pass, this time forcing status poll on each node in the path.
2048 sendPollerMsg(requestId
, _T("Checking network path (%s pass)...\r\n"), secondPass
? _T("second") : _T("first"));
2049 bool pathProblemFound
= false;
2050 for(int i
= 0; i
< trace
->getHopCount(); i
++)
2052 HOP_INFO
*hop
= trace
->getHopInfo(i
);
2053 if ((hop
->object
== NULL
) || (hop
->object
== this) || (hop
->object
->getObjectClass() != OBJECT_NODE
))
2059 for(int j
= i
- 1; j
>= 0; j
--)
2061 HOP_INFO
*prevHop
= trace
->getHopInfo(j
);
2062 if (prevHop
->object
== hop
->object
)
2064 prevHop
= trace
->getHopInfo(i
- 1);
2065 nxlog_debug(5, _T("Node::checkNetworkPath(%s [%d]): routing loop detected on upstream node %s [%d]"),
2066 m_name
, m_id
, prevHop
->object
->getName(), prevHop
->object
->getId());
2067 sendPollerMsg(requestId
, POLLER_WARNING
_T(" Routing loop detected on upstream node %s\r\n"), prevHop
->object
->getName());
2069 static const TCHAR
*names
[] =
2070 { _T("protocol"), _T("destNodeId"), _T("destAddress"),
2071 _T("sourceNodeId"), _T("sourceAddress"), _T("prefix"),
2072 _T("prefixLength"), _T("nextHopNodeId"), _T("nextHopAddress")
2074 PostEventWithNames(EVENT_ROUTING_LOOP_DETECTED
, prevHop
->object
->getId(), "siAiAAdiA", names
,
2075 (trace
->getSourceAddress().getFamily() == AF_INET6
) ? _T("IPv6") : _T("IPv4"),
2076 m_id
, &m_ipAddress
, g_dwMgmtNode
, &(trace
->getSourceAddress()),
2077 &prevHop
->route
, prevHop
->route
.getMaskBits(), hop
->object
->getId(), &prevHop
->nextHop
);
2079 pathProblemFound
= true;
2083 if (pathProblemFound
)
2087 nxlog_debug(6, _T("Node::checkNetworkPath(%s [%d]): checking upstream router %s [%d]"),
2088 m_name
, m_id
, hop
->object
->getName(), hop
->object
->getId());
2089 if (checkNetworkPathElement(hop
->object
->getId(), _T("upstream router"), false, requestId
, secondPass
))
2091 pathProblemFound
= true;
2097 // Next hop is behind VPN tunnel
2098 VPNConnector
*vpnConn
= (VPNConnector
*)FindObjectById(hop
->ifIndex
, OBJECT_VPNCONNECTOR
);
2099 if ((vpnConn
!= NULL
) && (vpnConn
->getStatus() == STATUS_CRITICAL
))
2101 /* TODO: mark as path problem */
2106 Interface
*iface
= ((Node
*)hop
->object
)->findInterfaceByIndex(hop
->ifIndex
);
2107 if ((iface
!= NULL
) && (iface
->getExpectedState() != IF_EXPECTED_STATE_IGNORE
) &&
2108 ((iface
->getAdminState() == IF_ADMIN_STATE_DOWN
) || (iface
->getAdminState() == IF_ADMIN_STATE_TESTING
) ||
2109 (iface
->getOperState() == IF_OPER_STATE_DOWN
) || (iface
->getOperState() == IF_OPER_STATE_TESTING
)))
2111 nxlog_debug(5, _T("Node::checkNetworkPath(%s [%d]): upstream interface %s [%d] on node %s [%d] is down"),
2112 m_name
, m_id
, iface
->getName(), iface
->getId(), hop
->object
->getName(), hop
->object
->getId());
2113 sendPollerMsg(requestId
, POLLER_WARNING
_T(" Upstream interface %s on node %s is down\r\n"), iface
->getName(), hop
->object
->getName());
2120 return pathProblemFound
;
2124 * Check network path between node and management server to detect possible intermediate node failure
2126 * @return true if network path problems found
2128 bool Node::checkNetworkPath(UINT32 requestId
)
2130 if (checkNetworkPathLayer2(requestId
, false))
2133 if (checkNetworkPathLayer3(requestId
, false))
2136 nxlog_debug(5, _T("Node::checkNetworkPath(%s [%d]): will do second pass"), m_name
, m_id
);
2138 if (checkNetworkPathLayer2(requestId
, true))
2141 if (checkNetworkPathLayer3(requestId
, true))
2148 * Check agent policy binding
2149 * Intended to be called only from configuration poller
2151 void Node::checkAgentPolicyBinding(AgentConnection
*conn
)
2153 AgentPolicyInfo
*ap
;
2154 UINT32 rcc
= conn
->getPolicyInventory(&ap
);
2155 if (rcc
== ERR_SUCCESS
)
2157 // Check for unbound but installed policies
2158 for(int i
= 0; i
< ap
->size(); i
++)
2160 uuid guid
= ap
->getGuid(i
);
2161 NetObj
*object
= FindObjectByGUID(guid
, -1);
2162 if ((object
!= NULL
) && (!object
->isChild(m_id
)))
2164 object
->addChild(this);
2166 DbgPrintf(5, _T("ConfPoll(%s): bound to policy object %s [%d]"), m_name
, object
->getName(), object
->getId());
2170 // Check for bound but not installed policies and schedule it's installation again
2171 //Job will be unbound if it was not possible to add job
2172 lockParentList(false);
2173 NetObj
**unbindList
= (NetObj
**)malloc(sizeof(NetObj
*) * m_parentList
->size());
2174 int unbindListSize
= 0;
2175 for(int i
= 0; i
< m_parentList
->size(); i
++)
2177 if (IsAgentPolicyObject(m_parentList
->get(i
)))
2179 const uuid
& guid
= m_parentList
->get(i
)->getGuid();
2181 for(j
= 0; j
< ap
->size(); j
++)
2183 if (ap
->getGuid(j
).equals(guid
))
2186 if (j
== ap
->size())
2188 ServerJob
*job
= new PolicyInstallJob(this, (AgentPolicy
*)m_parentList
->get(i
), 0);
2191 DbgPrintf(5, _T("ConfPoll(%s): \"%s\" policy deploy scheduled for \"%s\" node"), m_name
, m_parentList
->get(i
)->getName(), m_name
);
2195 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
);
2197 unbindList
[unbindListSize
++] = m_parentList
->get(i
);
2204 for(int i
= 0; i
< unbindListSize
; i
++)
2206 unbindList
[i
]->deleteChild(this);
2207 deleteParent(unbindList
[i
]);
2208 DbgPrintf(5, _T("ConfPoll(%s): unbound from policy object %s [%d]"), m_name
, unbindList
[i
]->getName(), unbindList
[i
]->getId());
2210 safe_free(unbindList
);
2216 DbgPrintf(5, _T("ConfPoll(%s): AgentConnection::getPolicyInventory() failed: rcc=%d"), m_name
, rcc
);
2221 * Update primary IP address from primary name
2223 void Node::updatePrimaryIpAddr()
2225 if (m_primaryName
[0] == 0)
2228 InetAddress ipAddr
= ResolveHostName(m_zoneUIN
, m_primaryName
);
2229 if (!ipAddr
.equals(m_ipAddress
) && (ipAddr
.isValidUnicast() || !_tcscmp(m_primaryName
, _T("0.0.0.0"))))
2231 TCHAR buffer1
[64], buffer2
[64];
2233 DbgPrintf(4, _T("IP address for node %s [%d] changed from %s to %s"),
2234 m_name
, (int)m_id
, m_ipAddress
.toString(buffer1
), ipAddr
.toString(buffer2
));
2235 PostEvent(EVENT_IP_ADDRESS_CHANGED
, m_id
, "AA", &ipAddr
, &m_ipAddress
);
2237 if (m_flags
& NF_REMOTE_AGENT
)
2240 m_ipAddress
= ipAddr
;
2241 setModified(MODIFY_NODE_PROPERTIES
);
2246 setPrimaryIPAddress(ipAddr
);
2250 deleteAgentConnection();
2256 * Comparator for package names
2258 static int PackageNameComparator(const SoftwarePackage
**p1
, const SoftwarePackage
**p2
)
2260 return _tcscmp((*p1
)->getName(), (*p2
)->getName());
2264 * Update list of software packages for node
2266 bool Node::updateSoftwarePackages(PollerInfo
*poller
, UINT32 requestId
)
2268 if (!(m_capabilities
& NC_IS_NATIVE_AGENT
))
2271 poller
->setStatus(_T("software check"));
2272 sendPollerMsg(requestId
, _T("Reading list of installed software packages\r\n"));
2275 if (getTableFromAgent(_T("System.InstalledProducts"), &table
) != DCE_SUCCESS
)
2277 sendPollerMsg(requestId
, POLLER_WARNING
_T("Unable to get information about installed software packages\r\n"));
2281 ObjectArray
<SoftwarePackage
> *packages
= new ObjectArray
<SoftwarePackage
>(table
->getNumRows(), 16, true);
2282 for(int i
= 0; i
< table
->getNumRows(); i
++)
2284 SoftwarePackage
*pkg
= SoftwarePackage::createFromTableRow(table
, i
);
2288 packages
->sort(PackageNameComparator
);
2290 sendPollerMsg(requestId
, POLLER_INFO
_T("Got information about %d installed software packages\r\n"), packages
->size());
2293 if (m_softwarePackages
!= NULL
)
2295 // Check for removed and updated packages
2296 for(int i
= 0; i
< m_softwarePackages
->size(); i
++)
2298 SoftwarePackage
*p
= m_softwarePackages
->get(i
);
2299 SoftwarePackage
*np
= (SoftwarePackage
*)packages
->find(p
, PackageNameComparator
);
2302 if (_tcscmp(p
->getVersion(), np
->getVersion()))
2304 nxlog_debug(5, _T("ConfPoll(%s): package %s updated (%s -> %s)"), m_name
, p
->getName(), p
->getVersion(), np
->getVersion());
2305 sendPollerMsg(requestId
, _T(" Package %s updated (%s -> %s)\r\n"), p
->getName(), p
->getVersion(), np
->getVersion());
2307 static const TCHAR
*names
[] = { _T("name"), _T("version"), _T("previousVersion") };
2308 PostEventWithNames(EVENT_PACKAGE_UPDATED
, m_id
, "sss", names
, p
->getName(), np
->getVersion(), p
->getVersion());
2313 nxlog_debug(5, _T("ConfPoll(%s): package %s removed (last installed version was %s)"), m_name
, p
->getName(), p
->getVersion());
2314 sendPollerMsg(requestId
, _T(" Package %s removed (last installed version was %s)\r\n"), p
->getName(), p
->getVersion());
2316 static const TCHAR
*names
[] = { _T("name"), _T("version") };
2317 PostEventWithNames(EVENT_PACKAGE_REMOVED
, m_id
, "ss", names
, p
->getName(), p
->getVersion());
2321 // Check for new packages
2322 for(int i
= 0; i
< packages
->size(); i
++)
2324 SoftwarePackage
*p
= packages
->get(i
);
2325 if (m_softwarePackages
->find(p
, PackageNameComparator
) == NULL
)
2327 nxlog_debug(5, _T("ConfPoll(%s): new package %s (version %s)"), m_name
, p
->getName(), p
->getVersion());
2328 sendPollerMsg(requestId
, _T(" New package %s (version %s)\r\n"), p
->getName(), p
->getVersion());
2330 static const TCHAR
*names
[] = { _T("name"), _T("version") };
2331 PostEventWithNames(EVENT_PACKAGE_INSTALLED
, m_id
, "ss", names
, p
->getName(), p
->getVersion());
2335 delete m_softwarePackages
;
2337 m_softwarePackages
= packages
;
2344 * Perform configuration poll on node
2346 void Node::configurationPoll(PollerInfo
*poller
, ClientSession
*session
, UINT32 rqId
)
2348 if (m_runtimeFlags
& DCDF_DELETE_IN_PROGRESS
)
2351 m_runtimeFlags
&= ~DCDF_QUEUED_FOR_CONFIGURATION_POLL
;
2355 if (IsShutdownInProgress())
2358 UINT32 oldCapabilities
= m_capabilities
;
2359 TCHAR szBuffer
[4096];
2360 UINT32 modified
= 0;
2362 poller
->setStatus(_T("wait for lock"));
2365 if (IsShutdownInProgress())
2371 m_pollRequestor
= session
;
2372 sendPollerMsg(rqId
, _T("Starting configuration poll for node %s\r\n"), m_name
);
2373 nxlog_debug(4, _T("Starting configuration poll for node %s (ID: %d)"), m_name
, m_id
);
2375 // Check for forced capabilities recheck
2376 if (m_runtimeFlags
& NDF_RECHECK_CAPABILITIES
)
2378 sendPollerMsg(rqId
, POLLER_WARNING
_T("Capability reset\r\n"));
2380 m_runtimeFlags
&= ~DCDF_CONFIGURATION_POLL_PASSED
;
2381 m_snmpObjectId
[0] = 0;
2382 m_platformName
[0] = 0;
2383 m_agentVersion
[0] = 0;
2384 safe_free_and_null(m_sysDescription
);
2385 safe_free_and_null(m_sysName
);
2386 safe_free_and_null(m_sysContact
);
2387 safe_free_and_null(m_sysLocation
);
2388 safe_free_and_null(m_lldpNodeId
);
2391 // Check if node is marked as unreachable
2392 if ((m_state
& DCSF_UNREACHABLE
) && !(m_runtimeFlags
& NDF_RECHECK_CAPABILITIES
))
2394 sendPollerMsg(rqId
, POLLER_WARNING
_T("Node is marked as unreachable, configuration poll aborted\r\n"));
2395 DbgPrintf(4, _T("Node is marked as unreachable, configuration poll aborted"));
2396 m_lastConfigurationPoll
= time(NULL
);
2400 updatePrimaryIpAddr();
2402 poller
->setStatus(_T("capability check"));
2403 sendPollerMsg(rqId
, _T("Checking node's capabilities...\r\n"));
2405 if (confPollAgent(rqId
))
2406 modified
|= MODIFY_NODE_PROPERTIES
;
2407 if (confPollSnmp(rqId
))
2408 modified
|= MODIFY_NODE_PROPERTIES
;
2410 // Check for CheckPoint SNMP agent on port 260
2411 if (ConfigReadInt(_T("EnableCheckPointSNMP"), 0))
2413 nxlog_debug(5, _T("ConfPoll(%s): checking for CheckPoint SNMP on port 260"), m_name
);
2414 if (!((m_capabilities
& NC_IS_CPSNMP
) && (m_state
& NSF_CPSNMP_UNREACHABLE
)) && m_ipAddress
.isValidUnicast())
2416 SNMP_Transport
*pTransport
= new SNMP_UDPTransport
;
2417 ((SNMP_UDPTransport
*)pTransport
)->createUDPTransport(m_ipAddress
, CHECKPOINT_SNMP_PORT
);
2418 if (SnmpGet(SNMP_VERSION_1
, pTransport
,
2419 _T(".1.3.6.1.4.1.2620.1.1.10.0"), NULL
, 0, szBuffer
, sizeof(szBuffer
), 0) == SNMP_ERR_SUCCESS
)
2422 m_capabilities
|= NC_IS_CPSNMP
| NC_IS_ROUTER
;
2423 m_state
&= ~NSF_CPSNMP_UNREACHABLE
;
2425 sendPollerMsg(rqId
, POLLER_INFO
_T(" CheckPoint SNMP agent on port 260 is active\r\n"));
2431 // Generate event if node flags has been changed
2432 if (oldCapabilities
!= m_capabilities
)
2434 PostEvent(EVENT_NODE_CAPABILITIES_CHANGED
, m_id
, "xx", oldCapabilities
, m_capabilities
);
2435 modified
|= MODIFY_NODE_PROPERTIES
;
2438 // Retrieve interface list
2439 poller
->setStatus(_T("interface check"));
2440 sendPollerMsg(rqId
, _T("Capability check finished\r\n"));
2442 if (updateInterfaceConfiguration(rqId
, 0)) // maskBits
2443 modified
|= MODIFY_NODE_PROPERTIES
;
2445 m_lastConfigurationPoll
= time(NULL
);
2448 sendPollerMsg(rqId
, _T("Checking node name\r\n"));
2449 UINT32 dwAddr
= ntohl(_t_inet_addr(m_name
));
2450 if ((g_flags
& AF_RESOLVE_NODE_NAMES
) &&
2451 (dwAddr
!= INADDR_NONE
) &&
2452 (dwAddr
!= INADDR_ANY
) &&
2455 sendPollerMsg(rqId
, _T("Node name is an IP address and need to be resolved\r\n"));
2456 poller
->setStatus(_T("resolving name"));
2457 if (resolveName(FALSE
))
2459 sendPollerMsg(rqId
, POLLER_INFO
_T("Node name resolved to %s\r\n"), m_name
);
2460 modified
|= MODIFY_COMMON_PROPERTIES
;
2464 sendPollerMsg(rqId
, POLLER_WARNING
_T("Node name cannot be resolved\r\n"));
2469 if (g_flags
& AF_SYNC_NODE_NAMES_WITH_DNS
)
2471 sendPollerMsg(rqId
, _T("Syncing node name with DNS\r\n"));
2472 poller
->setStatus(_T("resolving name"));
2473 if (resolveName(TRUE
))
2475 sendPollerMsg(rqId
, POLLER_INFO
_T("Node name resolved to %s\r\n"), m_name
);
2476 modified
|= MODIFY_COMMON_PROPERTIES
;
2481 sendPollerMsg(rqId
, _T("Node name is OK\r\n"));
2485 applyUserTemplates();
2486 updateContainerMembership();
2487 updateSoftwarePackages(poller
, rqId
);
2489 // Call hooks in loaded modules
2490 for(UINT32 i
= 0; i
< g_dwNumModules
; i
++)
2492 if (g_pModuleList
[i
].pfConfPollHook
!= NULL
)
2494 DbgPrintf(5, _T("ConfigurationPoll(%s [%d]): calling hook in module %s"), m_name
, m_id
, g_pModuleList
[i
].szName
);
2495 if (g_pModuleList
[i
].pfConfPollHook(this, session
, rqId
, poller
))
2496 modified
|= MODIFY_ALL
; // FIXME: change module call to get exact modifications
2500 // Setup permanent connection to agent if not present (needed for proper configuration re-sync)
2501 if (m_capabilities
& NC_IS_NATIVE_AGENT
)
2509 NodeType type
= detectNodeType();
2510 nxlog_debug(5, _T("ConfPoll(%s): detected node type: %d (%s)"), m_name
, type
, typeName(type
));
2512 if ((type
!= NODE_TYPE_UNKNOWN
) && (type
!= m_type
))
2515 modified
|= MODIFY_NODE_PROPERTIES
;
2516 nxlog_debug(5, _T("ConfPoll(%s): node type set to %d (%s)"), m_name
, type
, typeName(type
));
2517 sendPollerMsg(rqId
, _T(" Node type changed to %s\r\n"), typeName(type
));
2521 // Execute hook script
2522 poller
->setStatus(_T("hook"));
2523 executeHookScript(_T("ConfigurationPoll"));
2525 sendPollerMsg(rqId
, _T("Finished configuration poll for node %s\r\n"), m_name
);
2526 sendPollerMsg(rqId
, _T("Node configuration was%schanged after poll\r\n"), (modified
!= 0) ? _T(" ") : _T(" not "));
2528 m_runtimeFlags
&= ~DCDF_CONFIGURATION_POLL_PENDING
;
2529 m_runtimeFlags
|= DCDF_CONFIGURATION_POLL_PASSED
;
2532 // Finish configuration poll
2533 poller
->setStatus(_T("cleanup"));
2535 m_runtimeFlags
&= ~DCDF_QUEUED_FOR_CONFIGURATION_POLL
;
2536 m_runtimeFlags
&= ~NDF_RECHECK_CAPABILITIES
;
2538 DbgPrintf(4, _T("Finished configuration poll for node %s (ID: %d)"), m_name
, m_id
);
2543 setModified(modified
);
2551 NodeType
Node::detectNodeType()
2553 NodeType type
= NODE_TYPE_UNKNOWN
;
2554 if (m_capabilities
& NC_IS_SNMP
)
2556 nxlog_debug(6, _T("Node::detectNodeType(%s [%d]): SNMP node, driver name is %s"), m_name
, m_id
, m_driver
->getName());
2558 // Assume physical device if it supports SNMP and driver is not "GENERIC"
2559 // FIXME: add driver method to determine node type
2560 if (_tcscmp(m_driver
->getName(), _T("GENERIC")))
2562 type
= NODE_TYPE_PHYSICAL
;
2566 if (m_capabilities
& NC_IS_PRINTER
)
2568 // Assume that printers are physical devices
2569 type
= NODE_TYPE_PHYSICAL
;
2577 * Configuration poll: check for NetXMS agent
2579 bool Node::confPollAgent(UINT32 rqId
)
2581 nxlog_debug(5, _T("ConfPoll(%s): checking for NetXMS agent Flags={%08X} StateFlags={%08X} RuntimeFlags={%08X}"), m_name
, m_flags
, m_state
, m_runtimeFlags
);
2582 if (((m_capabilities
& NC_IS_NATIVE_AGENT
) && (m_state
& NSF_AGENT_UNREACHABLE
)) || (m_flags
& NF_DISABLE_NXCP
))
2585 bool hasChanges
= false;
2587 sendPollerMsg(rqId
, _T(" Checking NetXMS agent...\r\n"));
2588 AgentTunnel
*tunnel
= GetTunnelForNode(m_id
);
2589 AgentConnectionEx
*pAgentConn
;
2592 pAgentConn
= new AgentConnectionEx(m_id
, tunnel
, m_agentAuthMethod
, m_szSharedSecret
, isAgentCompressionAllowed());
2593 tunnel
->decRefCount();
2597 if (!m_ipAddress
.isValidUnicast())
2599 sendPollerMsg(rqId
, POLLER_ERROR
_T(" Node primary IP is invalid and there are no active tunnels\r\n"));
2600 nxlog_debug(5, _T("ConfPoll(%s): node primary IP is invalid and there are no active tunnels"), m_name
);
2603 pAgentConn
= new AgentConnectionEx(m_id
, m_ipAddress
, m_agentPort
, m_agentAuthMethod
, m_szSharedSecret
, isAgentCompressionAllowed());
2604 setAgentProxy(pAgentConn
);
2606 pAgentConn
->setCommandTimeout(g_agentCommandTimeout
);
2607 nxlog_debug(5, _T("ConfPoll(%s): checking for NetXMS agent - connecting"), m_name
);
2609 // Try to connect to agent
2611 if (!pAgentConn
->connect(g_pServerKey
, &rcc
))
2613 // If there are authentication problem, try default shared secret
2614 if ((rcc
== ERR_AUTH_REQUIRED
) || (rcc
== ERR_AUTH_FAILED
))
2616 TCHAR secret
[MAX_SECRET_LENGTH
];
2617 ConfigReadStr(_T("AgentDefaultSharedSecret"), secret
, MAX_SECRET_LENGTH
, _T("netxms"));
2618 DecryptPassword(_T("netxms"), secret
, secret
, MAX_SECRET_LENGTH
);
2619 pAgentConn
->setAuthData(AUTH_SHA1_HASH
, secret
);
2620 if (pAgentConn
->connect(g_pServerKey
, &rcc
))
2622 m_agentAuthMethod
= AUTH_SHA1_HASH
;
2623 nx_strncpy(m_szSharedSecret
, secret
, MAX_SECRET_LENGTH
);
2624 nxlog_debug(5, _T("ConfPoll(%s): checking for NetXMS agent - shared secret changed to system default"), m_name
);
2629 if (rcc
== ERR_SUCCESS
)
2631 nxlog_debug(5, _T("ConfPoll(%s): checking for NetXMS agent - connected"), m_name
);
2633 m_capabilities
|= NC_IS_NATIVE_AGENT
;
2634 if (m_state
& NSF_AGENT_UNREACHABLE
)
2636 m_state
&= ~NSF_AGENT_UNREACHABLE
;
2637 PostEvent(EVENT_AGENT_OK
, m_id
, NULL
);
2638 sendPollerMsg(rqId
, POLLER_INFO
_T(" Connectivity with NetXMS agent restored\r\n"));
2642 sendPollerMsg(rqId
, POLLER_INFO
_T(" NetXMS native agent is active\r\n"));
2646 TCHAR buffer
[MAX_RESULT_LENGTH
];
2647 if (pAgentConn
->getParameter(_T("Agent.Version"), MAX_AGENT_VERSION_LEN
, buffer
) == ERR_SUCCESS
)
2650 if (_tcscmp(m_agentVersion
, buffer
))
2652 _tcscpy(m_agentVersion
, buffer
);
2654 sendPollerMsg(rqId
, _T(" NetXMS agent version changed to %s\r\n"), m_agentVersion
);
2659 if (pAgentConn
->getParameter(_T("System.PlatformName"), MAX_PLATFORM_NAME_LEN
, buffer
) == ERR_SUCCESS
)
2662 if (_tcscmp(m_platformName
, buffer
))
2664 _tcscpy(m_platformName
, buffer
);
2666 sendPollerMsg(rqId
, _T(" Platform name changed to %s\r\n"), m_platformName
);
2671 // Check IP forwarding status
2672 if (pAgentConn
->getParameter(_T("Net.IP.Forwarding"), 16, buffer
) == ERR_SUCCESS
)
2674 if (_tcstoul(buffer
, NULL
, 10) != 0)
2675 m_capabilities
|= NC_IS_ROUTER
;
2677 m_capabilities
&= ~NC_IS_ROUTER
;
2681 if (pAgentConn
->getParameter(_T("System.Uname"), MAX_DB_STRING
, buffer
) == ERR_SUCCESS
)
2683 TranslateStr(buffer
, _T("\r\n"), _T(" "));
2684 TranslateStr(buffer
, _T("\n"), _T(" "));
2685 TranslateStr(buffer
, _T("\r"), _T(" "));
2687 if ((m_sysDescription
== NULL
) || _tcscmp(m_sysDescription
, buffer
))
2689 free(m_sysDescription
);
2690 m_sysDescription
= _tcsdup(buffer
);
2692 sendPollerMsg(rqId
, _T(" System description changed to %s\r\n"), m_sysDescription
);
2697 // Check for 64 bit counter support.
2698 // if Net.Interface.64BitCounters not supported by agent then use
2699 // only presence of 64 bit parameters as indicator
2700 bool netIf64bitCounters
= true;
2701 if (pAgentConn
->getParameter(_T("Net.Interface.64BitCounters"), MAX_DB_STRING
, buffer
) == ERR_SUCCESS
)
2703 netIf64bitCounters
= _tcstol(buffer
, NULL
, 10) ? true : false;
2706 ObjectArray
<AgentParameterDefinition
> *plist
;
2707 ObjectArray
<AgentTableDefinition
> *tlist
;
2708 UINT32 rcc
= pAgentConn
->getSupportedParameters(&plist
, &tlist
);
2709 if (rcc
== ERR_SUCCESS
)
2714 m_paramList
= plist
;
2715 m_tableList
= tlist
;
2717 // Check for 64-bit interface counters
2718 m_capabilities
&= ~NC_HAS_AGENT_IFXCOUNTERS
;
2719 if (netIf64bitCounters
)
2721 for(int i
= 0; i
< plist
->size(); i
++)
2723 if (!_tcsicmp(plist
->get(i
)->getName(), _T("Net.Interface.BytesIn64(*)")))
2725 m_capabilities
|= NC_HAS_AGENT_IFXCOUNTERS
;
2735 DbgPrintf(5, _T("ConfPoll(%s): AgentConnection::getSupportedParameters() failed: rcc=%d"), m_name
, rcc
);
2738 // Get supported Windows Performance Counters
2739 if (!_tcsncmp(m_platformName
, _T("windows-"), 8))
2741 sendPollerMsg(rqId
, _T(" Reading list of available Windows Performance Counters...\r\n"));
2742 ObjectArray
<WinPerfObject
> *perfObjects
= WinPerfObject::getWinPerfObjectsFromNode(this, pAgentConn
);
2744 delete m_winPerfObjects
;
2745 m_winPerfObjects
= perfObjects
;
2746 if (m_winPerfObjects
!= NULL
)
2748 sendPollerMsg(rqId
, POLLER_INFO
_T(" %d counters read\r\n"), m_winPerfObjects
->size());
2749 if (!(m_capabilities
& NC_HAS_WINPDH
))
2751 m_capabilities
|= NC_HAS_WINPDH
;
2757 sendPollerMsg(rqId
, POLLER_ERROR
_T(" unable to get Windows Performance Counters list\r\n"));
2758 if (m_capabilities
& NC_HAS_WINPDH
)
2760 m_capabilities
&= ~NC_HAS_WINPDH
;
2767 checkAgentPolicyBinding(pAgentConn
);
2769 pAgentConn
->disconnect();
2773 nxlog_debug(5, _T("ConfPoll(%s): checking for NetXMS agent - failed to connect (error %d)"), m_name
, rcc
);
2775 pAgentConn
->decRefCount();
2776 nxlog_debug(5, _T("ConfPoll(%s): checking for NetXMS agent - finished"), m_name
);
2781 * SNMP walker callback which sets indicator to true after first varbind and aborts walk
2783 static UINT32
IndicatorSnmpWalkerCallback(SNMP_Variable
*var
, SNMP_Transport
*transport
, void *arg
)
2785 (*((bool *)arg
)) = true;
2786 return SNMP_ERR_COMM
;
2790 * Configuration poll: check for SNMP
2792 bool Node::confPollSnmp(UINT32 rqId
)
2794 if (((m_capabilities
& NC_IS_SNMP
) && (m_state
& NSF_SNMP_UNREACHABLE
)) ||
2795 !m_ipAddress
.isValidUnicast() || (m_flags
& NF_DISABLE_SNMP
))
2798 bool hasChanges
= false;
2800 sendPollerMsg(rqId
, _T(" Checking SNMP...\r\n"));
2801 DbgPrintf(5, _T("ConfPoll(%s): calling SnmpCheckCommSettings()"), m_name
);
2803 const TCHAR
*customOid
= m_customAttributes
.get(_T("snmp.testoid"));
2804 if (customOid
!= NULL
)
2805 oids
.add(customOid
);
2806 oids
.add(_T(".1.3.6.1.2.1.1.2.0"));
2807 oids
.add(_T(".1.3.6.1.2.1.1.1.0"));
2808 AddDriverSpecificOids(&oids
);
2809 SNMP_Transport
*pTransport
= SnmpCheckCommSettings(getEffectiveSnmpProxy(), (getEffectiveSnmpProxy() == m_id
) ? InetAddress::LOOPBACK
: m_ipAddress
, &m_snmpVersion
, m_snmpPort
, m_snmpSecurity
, &oids
);
2810 if (pTransport
== NULL
)
2812 DbgPrintf(5, _T("ConfPoll(%s): unable to create SNMP transport"), m_name
);
2817 m_snmpPort
= pTransport
->getPort();
2818 delete m_snmpSecurity
;
2819 m_snmpSecurity
= new SNMP_SecurityContext(pTransport
->getSecurityContext());
2820 m_capabilities
|= NC_IS_SNMP
;
2821 if (m_state
& NSF_SNMP_UNREACHABLE
)
2823 m_state
&= ~NSF_SNMP_UNREACHABLE
;
2824 PostEvent(EVENT_SNMP_OK
, m_id
, NULL
);
2825 sendPollerMsg(rqId
, POLLER_INFO
_T(" Connectivity with SNMP agent restored\r\n"));
2828 sendPollerMsg(rqId
, _T(" SNMP agent is active (version %s)\r\n"),
2829 (m_snmpVersion
== SNMP_VERSION_3
) ? _T("3") : ((m_snmpVersion
== SNMP_VERSION_2C
) ? _T("2c") : _T("1")));
2831 TCHAR szBuffer
[4096];
2832 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
)
2834 // Set snmp object ID to .0.0 if it cannot be read
2835 _tcscpy(szBuffer
, _T(".0.0"));
2838 if (_tcscmp(m_snmpObjectId
, szBuffer
))
2840 _tcslcpy(m_snmpObjectId
, szBuffer
, MAX_OID_LEN
* 4);
2845 // Get system description
2846 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
)
2848 TranslateStr(szBuffer
, _T("\r\n"), _T(" "));
2849 TranslateStr(szBuffer
, _T("\n"), _T(" "));
2850 TranslateStr(szBuffer
, _T("\r"), _T(" "));
2852 if ((m_sysDescription
== NULL
) || _tcscmp(m_sysDescription
, szBuffer
))
2854 free(m_sysDescription
);
2855 m_sysDescription
= _tcsdup(szBuffer
);
2857 sendPollerMsg(rqId
, _T(" System description changed to %s\r\n"), m_sysDescription
);
2862 // Select device driver
2863 NetworkDeviceDriver
*driver
= FindDriverForNode(this, pTransport
);
2864 DbgPrintf(5, _T("ConfPoll(%s): selected device driver %s"), m_name
, driver
->getName());
2866 if (driver
!= m_driver
)
2869 sendPollerMsg(rqId
, _T(" New network device driver selected: %s\r\n"), m_driver
->getName());
2873 // Allow driver to gather additional info
2874 m_driver
->analyzeDevice(pTransport
, m_snmpObjectId
, &m_customAttributes
, &m_driverData
);
2875 NDD_MODULE_LAYOUT layout
;
2876 m_driver
->getModuleLayout(pTransport
, &m_customAttributes
, m_driverData
, 1, &layout
); // TODO module set to 1
2877 if (layout
.numberingScheme
== NDD_PN_UNKNOWN
)
2879 // Try to find port numbering information in database
2880 LookupDevicePortLayout(SNMP_ObjectId::parse(m_snmpObjectId
), &layout
);
2882 m_portRowCount
= layout
.rows
;
2883 m_portNumberingScheme
= layout
.numberingScheme
;
2885 // Get sysName, sysContact, sysLocation
2886 if (querySnmpSysProperty(pTransport
, _T(".1.3.6.1.2.1.1.5.0"), _T("name"), rqId
, &m_sysName
))
2888 if (querySnmpSysProperty(pTransport
, _T(".1.3.6.1.2.1.1.4.0"), _T("contact"), rqId
, &m_sysContact
))
2890 if (querySnmpSysProperty(pTransport
, _T(".1.3.6.1.2.1.1.6.0"), _T("location"), rqId
, &m_sysLocation
))
2893 // Check IP forwarding
2894 if (checkSNMPIntegerValue(pTransport
, _T(".1.3.6.1.2.1.4.1.0"), 1))
2897 m_capabilities
|= NC_IS_ROUTER
;
2903 m_capabilities
&= ~NC_IS_ROUTER
;
2907 checkIfXTable(pTransport
);
2908 checkBridgeMib(pTransport
);
2910 // Check for ENTITY-MIB support
2911 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
)
2914 m_capabilities
|= NC_HAS_ENTITY_MIB
;
2917 ComponentTree
*components
= BuildComponentTree(this, pTransport
);
2919 if (m_components
!= NULL
)
2920 m_components
->decRefCount();
2921 m_components
= components
;
2927 m_capabilities
&= ~NC_HAS_ENTITY_MIB
;
2928 if (m_components
!= NULL
)
2930 m_components
->decRefCount();
2931 m_components
= NULL
;
2936 // Check for printer MIB support
2937 bool present
= false;
2938 SnmpWalk(pTransport
, _T(".1.3.6.1.2.1.43"), IndicatorSnmpWalkerCallback
, &present
);
2942 m_capabilities
|= NC_IS_PRINTER
;
2948 m_capabilities
&= ~NC_IS_PRINTER
;
2952 // Check for CDP (Cisco Discovery Protocol) support
2953 if (checkSNMPIntegerValue(pTransport
, _T(".1.3.6.1.4.1.9.9.23.1.3.1.0"), 1))
2956 m_capabilities
|= NC_IS_CDP
;
2962 m_capabilities
&= ~NC_IS_CDP
;
2966 // Check for NDP (Nortel Discovery Protocol) support
2967 if (checkSNMPIntegerValue(pTransport
, _T(".1.3.6.1.4.1.45.1.6.13.1.2.0"), 1))
2970 m_capabilities
|= NC_IS_NDP
;
2976 m_capabilities
&= ~NC_IS_NDP
;
2980 // Check for LLDP (Link Layer Discovery Protocol) support
2981 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
)
2984 m_capabilities
|= NC_IS_LLDP
;
2990 if ((SnmpGetEx(pTransport
, _T(".1.0.8802.1.1.2.1.3.1.0"), NULL
, 0, &type
, sizeof(INT32
), 0, NULL
) == SNMP_ERR_SUCCESS
) &&
2991 (SnmpGetEx(pTransport
, _T(".1.0.8802.1.1.2.1.3.2.0"), NULL
, 0, data
, 256, SG_RAW_RESULT
, &dataLen
) == SNMP_ERR_SUCCESS
))
2993 BuildLldpId(type
, data
, dataLen
, szBuffer
, 1024);
2995 if ((m_lldpNodeId
== NULL
) || _tcscmp(m_lldpNodeId
, szBuffer
))
2998 m_lldpNodeId
= _tcsdup(szBuffer
);
3000 sendPollerMsg(rqId
, _T(" LLDP node ID changed to %s\r\n"), m_lldpNodeId
);
3005 ObjectArray
<LLDP_LOCAL_PORT_INFO
> *lldpPorts
= GetLLDPLocalPortInfo(pTransport
);
3007 delete m_lldpLocalPortInfo
;
3008 m_lldpLocalPortInfo
= lldpPorts
;
3014 m_capabilities
&= ~NC_IS_LLDP
;
3018 // Check for 802.1x support
3019 if (checkSNMPIntegerValue(pTransport
, _T(".1.0.8802.1.1.1.1.1.1.0"), 1))
3022 m_capabilities
|= NC_IS_8021X
;
3028 m_capabilities
&= ~NC_IS_8021X
;
3032 checkOSPFSupport(pTransport
);
3034 // Get VRRP information
3035 VrrpInfo
*vrrpInfo
= GetVRRPInfo(this);
3036 if (vrrpInfo
!= NULL
)
3039 m_capabilities
|= NC_IS_VRRP
;
3041 m_vrrpInfo
= vrrpInfo
;
3047 m_capabilities
&= ~NC_IS_VRRP
;
3051 // Get wireless controller data
3052 if ((m_driver
!= NULL
) && m_driver
->isWirelessController(pTransport
, &m_customAttributes
, m_driverData
))
3054 DbgPrintf(5, _T("ConfPoll(%s): node is wireless controller, reading access point information"), m_name
);
3055 sendPollerMsg(rqId
, _T(" Reading wireless access point information\r\n"));
3057 m_capabilities
|= NC_IS_WIFI_CONTROLLER
;
3060 int clusterMode
= m_driver
->getClusterMode(pTransport
, &m_customAttributes
, m_driverData
);
3062 ObjectArray
<AccessPointInfo
> *aps
= m_driver
->getAccessPoints(pTransport
, &m_customAttributes
, m_driverData
);
3065 sendPollerMsg(rqId
, POLLER_INFO
_T(" %d wireless access points found\r\n"), aps
->size());
3066 DbgPrintf(5, _T("ConfPoll(%s): got information about %d access points"), m_name
, aps
->size());
3068 for(int i
= 0; i
< aps
->size(); i
++)
3070 AccessPointInfo
*info
= aps
->get(i
);
3071 if (info
->getState() == AP_ADOPTED
)
3075 AccessPoint
*ap
= (clusterMode
== CLUSTER_MODE_STANDALONE
) ? findAccessPointByMAC(info
->getMacAddr()) : FindAccessPointByMAC(info
->getMacAddr());
3080 if (info
->getName() != NULL
)
3082 name
= info
->getName();
3086 for(int j
= 0; j
< info
->getRadioInterfaces()->size(); j
++)
3090 name
+= info
->getRadioInterfaces()->get(j
)->name
;
3093 ap
= new AccessPoint((const TCHAR
*)name
, info
->getIndex(), info
->getMacAddr());
3094 NetObjInsert(ap
, true, false);
3095 DbgPrintf(5, _T("ConfPoll(%s): created new access point object %s [%d]"), m_name
, ap
->getName(), ap
->getId());
3098 ap
->attachToNode(m_id
);
3099 ap
->setIpAddress(info
->getIpAddr());
3100 if ((info
->getState() == AP_ADOPTED
) || newAp
)
3102 ap
->updateRadioInterfaces(info
->getRadioInterfaces());
3103 ap
->updateInfo(info
->getVendor(), info
->getModel(), info
->getSerial());
3106 ap
->updateState(info
->getState());
3110 m_adoptedApCount
= adopted
;
3111 m_totalApCount
= aps
->size();
3118 DbgPrintf(5, _T("ConfPoll(%s): failed to read access point information"), m_name
);
3119 sendPollerMsg(rqId
, POLLER_ERROR
_T(" Failed to read access point information\r\n"));
3125 m_capabilities
&= ~NC_IS_WIFI_CONTROLLER
;
3129 if (ConfigReadInt(_T("EnableCheckPointSNMP"), 0))
3131 // Check for CheckPoint SNMP agent on port 161
3132 DbgPrintf(5, _T("ConfPoll(%s): checking for CheckPoint SNMP"), m_name
);
3133 TCHAR szBuffer
[4096];
3134 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
)
3137 if (_tcscmp(m_snmpObjectId
, _T(".1.3.6.1.4.1.2620.1.1")))
3139 nx_strncpy(m_snmpObjectId
, _T(".1.3.6.1.4.1.2620.1.1"), MAX_OID_LEN
* 4);
3143 m_capabilities
|= NC_IS_SNMP
| NC_IS_ROUTER
;
3144 m_state
&= ~NSF_SNMP_UNREACHABLE
;
3146 sendPollerMsg(rqId
, POLLER_INFO
_T(" CheckPoint SNMP agent on port 161 is active\r\n"));
3154 * Query SNMP sys property (sysName, sysLocation, etc.)
3156 bool Node::querySnmpSysProperty(SNMP_Transport
*snmp
, const TCHAR
*oid
, const TCHAR
*propName
, UINT32 pollRqId
, TCHAR
**value
)
3159 bool hasChanges
= false;
3161 if (SnmpGet(m_snmpVersion
, snmp
, oid
, NULL
, 0, buffer
, sizeof(buffer
), SG_STRING_RESULT
) == SNMP_ERR_SUCCESS
)
3164 if ((*value
== NULL
) || _tcscmp(*value
, buffer
))
3167 *value
= _tcsdup(buffer
);
3169 sendPollerMsg(pollRqId
, _T(" System %s changed to %s\r\n"), propName
, *value
);
3177 * Configuration poll: check for BRIDGE MIB
3179 void Node::checkBridgeMib(SNMP_Transport
*pTransport
)
3181 TCHAR szBuffer
[4096];
3182 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
)
3185 m_capabilities
|= NC_IS_BRIDGE
;
3186 memcpy(m_baseBridgeAddress
, szBuffer
, 6);
3189 // Check for Spanning Tree (IEEE 802.1d) MIB support
3190 if (checkSNMPIntegerValue(pTransport
, _T(".1.3.6.1.2.1.17.2.1.0"), 3))
3193 m_capabilities
|= NC_IS_STP
;
3199 m_capabilities
&= ~NC_IS_STP
;
3206 m_capabilities
&= ~(NC_IS_BRIDGE
| NC_IS_STP
);
3212 * Configuration poll: check for ifXTable
3214 void Node::checkIfXTable(SNMP_Transport
*pTransport
)
3216 bool present
= false;
3217 SnmpWalk(pTransport
, _T(".1.3.6.1.2.1.31.1.1.1.1"), IndicatorSnmpWalkerCallback
, &present
);
3221 m_capabilities
|= NC_HAS_IFXTABLE
;
3227 m_capabilities
&= ~NC_HAS_IFXTABLE
;
3233 * Delete duplicate interfaces
3234 * (find and delete multiple interfaces with same ifIndex value created by version prior to 2.0-M3)
3236 bool Node::deleteDuplicateInterfaces(UINT32 rqid
)
3238 ObjectArray
<Interface
> deleteList(16, 16, false);
3240 lockChildList(false);
3241 for(int i
= 0; i
< m_childList
->size(); i
++)
3243 NetObj
*curr
= m_childList
->get(i
);
3245 if ((curr
->getObjectClass() != OBJECT_INTERFACE
) ||
3246 ((Interface
*)curr
)->isManuallyCreated())
3248 Interface
*iface
= (Interface
*)curr
;
3249 for(int j
= i
+ 1; j
< m_childList
->size(); j
++)
3251 NetObj
*next
= m_childList
->get(j
);
3253 if ((next
->getObjectClass() != OBJECT_INTERFACE
) ||
3254 ((Interface
*)next
)->isManuallyCreated() ||
3255 (deleteList
.contains((Interface
*)next
)))
3257 if (iface
->getIfIndex() == ((Interface
*)next
)->getIfIndex())
3259 deleteList
.add((Interface
*)next
);
3260 DbgPrintf(6, _T("Node::deleteDuplicateInterfaces(%s [%d]): found duplicate interface %s [%d], original %s [%d], ifIndex=%d"),
3261 m_name
, m_id
, next
->getName(), next
->getId(), iface
->getName(), iface
->getId(), iface
->getIfIndex());
3267 for(int i
= 0; i
< deleteList
.size(); i
++)
3269 Interface
*iface
= deleteList
.get(i
);
3270 sendPollerMsg(rqid
, POLLER_WARNING
_T(" Duplicate interface \"%s\" deleted\r\n"), iface
->getName());
3271 deleteInterface(iface
);
3274 return deleteList
.size() > 0;
3278 * Update interface configuration
3280 bool Node::updateInterfaceConfiguration(UINT32 rqid
, int maskBits
)
3282 sendPollerMsg(rqid
, _T("Checking interface configuration...\r\n"));
3284 bool hasChanges
= deleteDuplicateInterfaces(rqid
);
3286 InterfaceList
*ifList
= getInterfaceList();
3289 nxlog_debug(6, _T("Node::updateInterfaceConfiguration(%s [%u]): got %d interfaces"), m_name
, m_id
, ifList
->size());
3291 // Find non-existing interfaces
3292 lockChildList(false);
3293 ObjectArray
<Interface
> deleteList(m_childList
->size(), 8, false);
3294 for(int i
= 0; i
< m_childList
->size(); i
++)
3296 if (m_childList
->get(i
)->getObjectClass() == OBJECT_INTERFACE
)
3298 Interface
*iface
= (Interface
*)m_childList
->get(i
);
3299 if (iface
->isFake())
3301 // always delete fake interfaces if we got actual interface list
3302 deleteList
.add(iface
);
3306 if (!iface
->isManuallyCreated())
3309 for(j
= 0; j
< ifList
->size(); j
++)
3311 if (ifList
->get(j
)->index
== iface
->getIfIndex())
3315 if (j
== ifList
->size())
3317 // No such interface in current configuration, add it to delete list
3318 deleteList
.add(iface
);
3325 // Delete non-existent interfaces
3326 if (deleteList
.size() > 0)
3328 for(int j
= 0; j
< deleteList
.size(); j
++)
3330 Interface
*iface
= deleteList
.get(j
);
3331 sendPollerMsg(rqid
, POLLER_WARNING
_T(" Interface \"%s\" is no longer exist\r\n"), iface
->getName());
3332 const InetAddress
& addr
= iface
->getFirstIpAddress();
3333 PostEvent(EVENT_INTERFACE_DELETED
, m_id
, "dsAd", iface
->getIfIndex(), iface
->getName(), &addr
, addr
.getMaskBits());
3334 deleteInterface(iface
);
3339 // Add new interfaces and check configuration of existing
3340 for(int j
= 0; j
< ifList
->size(); j
++)
3342 InterfaceInfo
*ifInfo
= ifList
->get(j
);
3343 bool isNewInterface
= true;
3345 lockChildList(false);
3346 for(int i
= 0; i
< m_childList
->size(); i
++)
3348 if (m_childList
->get(i
)->getObjectClass() == OBJECT_INTERFACE
)
3350 Interface
*pInterface
= (Interface
*)m_childList
->get(i
);
3352 if (ifInfo
->index
== pInterface
->getIfIndex())
3354 // Existing interface, check configuration
3355 if (memcmp(ifInfo
->macAddr
, "\x00\x00\x00\x00\x00\x00", MAC_ADDR_LENGTH
) &&
3356 memcmp(ifInfo
->macAddr
, pInterface
->getMacAddr(), MAC_ADDR_LENGTH
))
3358 TCHAR szOldMac
[16], szNewMac
[16];
3360 BinToStr((BYTE
*)pInterface
->getMacAddr(), MAC_ADDR_LENGTH
, szOldMac
);
3361 BinToStr(ifInfo
->macAddr
, MAC_ADDR_LENGTH
, szNewMac
);
3362 PostEvent(EVENT_MAC_ADDR_CHANGED
, m_id
, "idsss",
3363 pInterface
->getId(), pInterface
->getIfIndex(),
3364 pInterface
->getName(), szOldMac
, szNewMac
);
3365 pInterface
->setMacAddr(ifInfo
->macAddr
, true);
3367 if (_tcscmp(ifInfo
->name
, pInterface
->getName()))
3369 pInterface
->setName(ifInfo
->name
);
3371 if (_tcscmp(ifInfo
->description
, pInterface
->getDescription()))
3373 pInterface
->setDescription(ifInfo
->description
);
3375 if (_tcscmp(ifInfo
->alias
, pInterface
->getAlias()))
3377 pInterface
->setAlias(ifInfo
->alias
);
3379 if (ifInfo
->bridgePort
!= pInterface
->getBridgePortNumber())
3381 pInterface
->setBridgePortNumber(ifInfo
->bridgePort
);
3383 if (ifInfo
->slot
!= pInterface
->getSlotNumber())
3385 pInterface
->setSlotNumber(ifInfo
->slot
);
3387 if (ifInfo
->port
!= pInterface
->getPortNumber())
3389 pInterface
->setPortNumber(ifInfo
->port
);
3391 if (ifInfo
->isPhysicalPort
!= pInterface
->isPhysicalPort())
3393 pInterface
->setPhysicalPortFlag(ifInfo
->isPhysicalPort
);
3395 if (ifInfo
->mtu
!= pInterface
->getMTU())
3397 pInterface
->setMTU(ifInfo
->mtu
);
3399 if (ifInfo
->speed
!= pInterface
->getSpeed())
3401 pInterface
->setSpeed(ifInfo
->speed
);
3403 if ((ifInfo
->ifTableSuffixLength
!= pInterface
->getIfTableSuffixLen()) ||
3404 memcmp(ifInfo
->ifTableSuffix
, pInterface
->getIfTableSuffix(),
3405 std::min(ifInfo
->ifTableSuffixLength
, pInterface
->getIfTableSuffixLen())))
3407 pInterface
->setIfTableSuffix(ifInfo
->ifTableSuffixLength
, ifInfo
->ifTableSuffix
);
3410 // Check for deleted IPs and changed masks
3411 const InetAddressList
*ifList
= pInterface
->getIpAddressList();
3412 for(int n
= 0; n
< ifList
->size(); n
++)
3414 const InetAddress
& ifAddr
= ifList
->get(n
);
3415 const InetAddress
& addr
= ifInfo
->ipAddrList
.findAddress(ifAddr
);
3418 if (addr
.getMaskBits() != ifAddr
.getMaskBits())
3420 PostEvent(EVENT_IF_MASK_CHANGED
, m_id
, "dsAddd", pInterface
->getId(), pInterface
->getName(),
3421 &addr
, addr
.getMaskBits(), pInterface
->getIfIndex(), ifAddr
.getMaskBits());
3422 pInterface
->setNetMask(addr
);
3423 sendPollerMsg(rqid
, POLLER_INFO
_T(" IP network mask changed to /%d on interface \"%s\" address %s\r\n"),
3424 addr
.getMaskBits(), pInterface
->getName(), (const TCHAR
*)ifAddr
.toString());
3429 sendPollerMsg(rqid
, POLLER_WARNING
_T(" IP address %s removed from interface \"%s\"\r\n"),
3430 (const TCHAR
*)ifAddr
.toString(), pInterface
->getName());
3431 PostEvent(EVENT_IF_IPADDR_DELETED
, m_id
, "dsAdd", pInterface
->getId(), pInterface
->getName(),
3432 &ifAddr
, ifAddr
.getMaskBits(), pInterface
->getIfIndex());
3433 pInterface
->deleteIpAddress(ifAddr
);