Commit | Line | Data |
---|---|---|
4d2c3a54 | 1 | /* |
5039dede | 2 | ** NetXMS - Network Management System |
c908b63b | 3 | ** Copyright (C) 2003-2016 Victor Kirhenshtein |
5039dede AK |
4 | ** |
5 | ** This program is free software; you can redistribute it and/or modify | |
6 | ** it under the terms of the GNU General Public License as published by | |
7 | ** the Free Software Foundation; either version 2 of the License, or | |
8 | ** (at your option) any later version. | |
9 | ** | |
10 | ** This program is distributed in the hope that it will be useful, | |
11 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 | ** GNU General Public License for more details. | |
14 | ** | |
15 | ** You should have received a copy of the GNU General Public License | |
16 | ** along with this program; if not, write to the Free Software | |
17 | ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
18 | ** | |
19 | ** File: node.cpp | |
20 | ** | |
21 | **/ | |
22 | ||
23 | #include "nxcore.h" | |
24 | ||
ba756b1a VK |
25 | /** |
26 | * Externals | |
27 | */ | |
28 | extern UINT64 g_syslogMessagesReceived; | |
29 | extern UINT64 g_snmpTrapsReceived; | |
30 | ||
c50f77f7 VK |
31 | /** |
32 | * Node class default constructor | |
33 | */ | |
6fd6de0a | 34 | Node::Node() : DataCollectionTarget() |
5039dede | 35 | { |
5ad2167d | 36 | m_primaryName[0] = 0; |
db091a1f | 37 | m_status = STATUS_UNKNOWN; |
e980db40 VK |
38 | m_type = NODE_TYPE_UNKNOWN; |
39 | m_subType[0] = 0; | |
5039dede | 40 | m_dwDynamicFlags = 0; |
52c31148 | 41 | m_zoneId = 0; |
c42b4551 VK |
42 | m_agentPort = AGENT_LISTEN_PORT; |
43 | m_agentAuthMethod = AUTH_NONE; | |
9708eff4 | 44 | m_agentCacheMode = AGENT_CACHE_DEFAULT; |
5039dede AK |
45 | m_szSharedSecret[0] = 0; |
46 | m_iStatusPollType = POLL_ICMP_PING; | |
5d2c5741 | 47 | m_snmpVersion = SNMP_VERSION_1; |
296ae03d | 48 | m_snmpPort = SNMP_DEFAULT_PORT; |
9db92307 | 49 | m_snmpSecurity = new SNMP_SecurityContext("public"); |
5039dede | 50 | m_szObjectId[0] = 0; |
8573e935 VK |
51 | m_lastDiscoveryPoll = 0; |
52 | m_lastStatusPoll = 0; | |
53 | m_lastConfigurationPoll = 0; | |
805171de | 54 | m_lastInstancePoll = 0; |
8573e935 VK |
55 | m_lastTopologyPoll = 0; |
56 | m_lastRTUpdate = 0; | |
57 | m_downSince = 0; | |
71e4ed3a | 58 | m_bootTime = 0; |
0ab347c0 | 59 | m_agentUpTime = 0; |
5039dede AK |
60 | m_hPollerMutex = MutexCreate(); |
61 | m_hAgentAccessMutex = MutexCreate(); | |
1d0d82b3 | 62 | m_hSmclpAccessMutex = MutexCreate(); |
5039dede AK |
63 | m_mutexRTAccess = MutexCreate(); |
64 | m_mutexTopoAccess = MutexCreate(); | |
83191808 VK |
65 | m_snmpProxyConnectionLock = MutexCreate(); |
66 | m_agentConnection = NULL; | |
67 | m_snmpProxyConnection = NULL; | |
1d0d82b3 | 68 | m_smclpConnection = NULL; |
fed33789 | 69 | m_lastAgentTrapId = 0; |
489b117b | 70 | m_lastSNMPTrapId = 0; |
42a3be4f | 71 | m_lastAgentPushRequestId = 0; |
5039dede AK |
72 | m_szAgentVersion[0] = 0; |
73 | m_szPlatformName[0] = 0; | |
0ecc2200 VK |
74 | m_sysDescription = NULL; |
75 | m_sysName = NULL; | |
cf38357f VK |
76 | m_sysContact = NULL; |
77 | m_sysLocation = NULL; | |
0ecc2200 | 78 | m_lldpNodeId = NULL; |
3a82d5ae | 79 | m_lldpLocalPortInfo = NULL; |
cc8ce218 VK |
80 | m_paramList = NULL; |
81 | m_tableList = NULL; | |
9208c84b VK |
82 | m_pollerNode = 0; |
83 | m_agentProxy = 0; | |
84 | m_snmpProxy = 0; | |
85 | m_icmpProxy = 0; | |
5039dede AK |
86 | memset(m_qwLastEvents, 0, sizeof(QWORD) * MAX_LAST_EVENTS); |
87 | m_pRoutingTable = NULL; | |
8573e935 VK |
88 | m_failTimeSNMP = 0; |
89 | m_failTimeAgent = 0; | |
4e3133ee | 90 | m_lastAgentCommTime = 0; |
a01c2a20 | 91 | m_lastAgentConnectAttempt = 0; |
040c45fa | 92 | m_linkLayerNeighbors = NULL; |
0d75ea88 | 93 | m_vrrpInfo = NULL; |
040c45fa VK |
94 | m_pTopology = NULL; |
95 | m_topologyRebuildTimestamp = 0; | |
5039dede AK |
96 | m_iPendingStatus = -1; |
97 | m_iPollCount = 0; | |
98 | m_iRequiredPollCount = 0; // Use system default | |
99 | m_nUseIfXTable = IFXTABLE_DEFAULT; // Use system default | |
ab621f39 | 100 | m_jobQueue = new ServerJobQueue(); |
f42b8099 | 101 | m_fdb = NULL; |
7f632dfe | 102 | m_vlans = NULL; |
d5de1d1d | 103 | m_wirelessStations = NULL; |
f1989a3a VK |
104 | m_adoptedApCount = 0; |
105 | m_totalApCount = 0; | |
9796ce45 | 106 | m_driver = NULL; |
ae32341d | 107 | m_driverData = NULL; |
50d0de67 | 108 | m_components = NULL; |
caa04e26 | 109 | m_softwarePackages = NULL; |
46ee6286 | 110 | m_winPerfObjects = NULL; |
3eab63f2 | 111 | memset(m_baseBridgeAddress, 0, MAC_ADDR_LENGTH); |
e13420c1 | 112 | m_fileUpdateConn = NULL; |
de674bb6 VK |
113 | m_rackId = 0; |
114 | m_rackPosition = 0; | |
115 | m_rackHeight = 1; | |
e4926628 | 116 | m_chassisId = 0; |
ba756b1a VK |
117 | m_syslogMessageCount = 0; |
118 | m_snmpTrapCount = 0; | |
241541f4 VK |
119 | m_sshLogin[0] = 0; |
120 | m_sshPassword[0] = 0; | |
121 | m_sshProxy = 0; | |
5039dede AK |
122 | } |
123 | ||
c50f77f7 VK |
124 | /** |
125 | * Constructor for new node object | |
126 | */ | |
de4c3060 | 127 | Node::Node(const InetAddress& addr, UINT32 dwFlags, UINT32 agentProxy, UINT32 snmpProxy, UINT32 icmpProxy, UINT32 sshProxy, UINT32 zoneId) : DataCollectionTarget() |
5039dede | 128 | { |
c75e9ee4 | 129 | addr.toString(m_primaryName); |
db091a1f | 130 | m_status = STATUS_UNKNOWN; |
e980db40 VK |
131 | m_type = NODE_TYPE_UNKNOWN; |
132 | m_subType[0] = 0; | |
c75e9ee4 | 133 | m_ipAddress = addr; |
487cde95 | 134 | m_flags = dwFlags; |
5039dede | 135 | m_dwDynamicFlags = 0; |
de4c3060 | 136 | m_zoneId = zoneId; |
c42b4551 VK |
137 | m_agentPort = AGENT_LISTEN_PORT; |
138 | m_agentAuthMethod = AUTH_NONE; | |
9708eff4 | 139 | m_agentCacheMode = AGENT_CACHE_DEFAULT; |
5039dede AK |
140 | m_szSharedSecret[0] = 0; |
141 | m_iStatusPollType = POLL_ICMP_PING; | |
5d2c5741 | 142 | m_snmpVersion = SNMP_VERSION_1; |
296ae03d | 143 | m_snmpPort = SNMP_DEFAULT_PORT; |
9db92307 | 144 | m_snmpSecurity = new SNMP_SecurityContext("public"); |
c75e9ee4 | 145 | addr.toString(m_name); // Make default name from IP address |
5039dede | 146 | m_szObjectId[0] = 0; |
8573e935 VK |
147 | m_lastDiscoveryPoll = 0; |
148 | m_lastStatusPoll = 0; | |
149 | m_lastConfigurationPoll = 0; | |
805171de | 150 | m_lastInstancePoll = 0; |
8573e935 VK |
151 | m_lastTopologyPoll = 0; |
152 | m_lastRTUpdate = 0; | |
153 | m_downSince = 0; | |
71e4ed3a | 154 | m_bootTime = 0; |
0ab347c0 | 155 | m_agentUpTime = 0; |
5039dede AK |
156 | m_hPollerMutex = MutexCreate(); |
157 | m_hAgentAccessMutex = MutexCreate(); | |
1d0d82b3 | 158 | m_hSmclpAccessMutex = MutexCreate(); |
5039dede AK |
159 | m_mutexRTAccess = MutexCreate(); |
160 | m_mutexTopoAccess = MutexCreate(); | |
83191808 VK |
161 | m_snmpProxyConnectionLock = MutexCreate(); |
162 | m_agentConnection = NULL; | |
163 | m_snmpProxyConnection = NULL; | |
1d0d82b3 | 164 | m_smclpConnection = NULL; |
fed33789 | 165 | m_lastAgentTrapId = 0; |
489b117b | 166 | m_lastSNMPTrapId = 0; |
42a3be4f | 167 | m_lastAgentPushRequestId = 0; |
5039dede AK |
168 | m_szAgentVersion[0] = 0; |
169 | m_szPlatformName[0] = 0; | |
0ecc2200 VK |
170 | m_sysDescription = NULL; |
171 | m_sysName = NULL; | |
cf38357f VK |
172 | m_sysContact = NULL; |
173 | m_sysLocation = NULL; | |
0ecc2200 | 174 | m_lldpNodeId = NULL; |
3a82d5ae | 175 | m_lldpLocalPortInfo = NULL; |
cc8ce218 VK |
176 | m_paramList = NULL; |
177 | m_tableList = NULL; | |
9208c84b VK |
178 | m_pollerNode = 0; |
179 | m_agentProxy = agentProxy; | |
180 | m_snmpProxy = snmpProxy; | |
de4c3060 | 181 | m_icmpProxy = icmpProxy; |
5039dede | 182 | memset(m_qwLastEvents, 0, sizeof(QWORD) * MAX_LAST_EVENTS); |
01152a54 | 183 | m_isHidden = true; |
5039dede | 184 | m_pRoutingTable = NULL; |
8573e935 VK |
185 | m_failTimeSNMP = 0; |
186 | m_failTimeAgent = 0; | |
4e3133ee | 187 | m_lastAgentCommTime = 0; |
a01c2a20 | 188 | m_lastAgentConnectAttempt = 0; |
040c45fa | 189 | m_linkLayerNeighbors = NULL; |
0d75ea88 | 190 | m_vrrpInfo = NULL; |
040c45fa VK |
191 | m_pTopology = NULL; |
192 | m_topologyRebuildTimestamp = 0; | |
5039dede AK |
193 | m_iPendingStatus = -1; |
194 | m_iPollCount = 0; | |
195 | m_iRequiredPollCount = 0; // Use system default | |
196 | m_nUseIfXTable = IFXTABLE_DEFAULT; // Use system default | |
ab621f39 | 197 | m_jobQueue = new ServerJobQueue(); |
f42b8099 | 198 | m_fdb = NULL; |
7f632dfe | 199 | m_vlans = NULL; |
d5de1d1d | 200 | m_wirelessStations = NULL; |
f1989a3a VK |
201 | m_adoptedApCount = 0; |
202 | m_totalApCount = 0; | |
9796ce45 | 203 | m_driver = NULL; |
ae32341d | 204 | m_driverData = NULL; |
50d0de67 | 205 | m_components = NULL; |
caa04e26 | 206 | m_softwarePackages = NULL; |
46ee6286 | 207 | m_winPerfObjects = NULL; |
3eab63f2 | 208 | memset(m_baseBridgeAddress, 0, MAC_ADDR_LENGTH); |
e13420c1 | 209 | m_fileUpdateConn = NULL; |
de674bb6 VK |
210 | m_rackId = 0; |
211 | m_rackPosition = 0; | |
212 | m_rackHeight = 1; | |
e4926628 | 213 | m_chassisId = 0; |
ba756b1a VK |
214 | m_syslogMessageCount = 0; |
215 | m_snmpTrapCount = 0; | |
241541f4 VK |
216 | m_sshLogin[0] = 0; |
217 | m_sshPassword[0] = 0; | |
de4c3060 | 218 | m_sshProxy = sshProxy; |
5039dede AK |
219 | } |
220 | ||
c50f77f7 VK |
221 | /** |
222 | * Node destructor | |
223 | */ | |
5039dede AK |
224 | Node::~Node() |
225 | { | |
225b92bc | 226 | delete m_driverData; |
5039dede AK |
227 | MutexDestroy(m_hPollerMutex); |
228 | MutexDestroy(m_hAgentAccessMutex); | |
1d0d82b3 | 229 | MutexDestroy(m_hSmclpAccessMutex); |
5039dede AK |
230 | MutexDestroy(m_mutexRTAccess); |
231 | MutexDestroy(m_mutexTopoAccess); | |
83191808 VK |
232 | MutexDestroy(m_snmpProxyConnectionLock); |
233 | if (m_agentConnection != NULL) | |
234 | m_agentConnection->decRefCount(); | |
235 | if (m_snmpProxyConnection != NULL) | |
236 | m_snmpProxyConnection->decRefCount(); | |
1d0d82b3 | 237 | delete m_smclpConnection; |
cc8ce218 VK |
238 | delete m_paramList; |
239 | delete m_tableList; | |
bb151059 | 240 | safe_free(m_sysDescription); |
5039dede | 241 | DestroyRoutingTable(m_pRoutingTable); |
a9ad9f61 VK |
242 | if (m_linkLayerNeighbors != NULL) |
243 | m_linkLayerNeighbors->decRefCount(); | |
0d75ea88 | 244 | delete m_vrrpInfo; |
5039dede | 245 | delete m_pTopology; |
ab621f39 | 246 | delete m_jobQueue; |
5d2c5741 | 247 | delete m_snmpSecurity; |
f42b8099 VK |
248 | if (m_fdb != NULL) |
249 | m_fdb->decRefCount(); | |
7f632dfe VK |
250 | if (m_vlans != NULL) |
251 | m_vlans->decRefCount(); | |
d5de1d1d | 252 | delete m_wirelessStations; |
33dfe57e VK |
253 | if (m_components != NULL) |
254 | m_components->decRefCount(); | |
3a82d5ae | 255 | delete m_lldpLocalPortInfo; |
caa04e26 | 256 | delete m_softwarePackages; |
46ee6286 | 257 | delete m_winPerfObjects; |
4671afeb | 258 | safe_free(m_sysName); |
cf38357f VK |
259 | safe_free(m_sysContact); |
260 | safe_free(m_sysLocation); | |
5039dede AK |
261 | } |
262 | ||
c50f77f7 VK |
263 | /** |
264 | * Create object from database data | |
265 | */ | |
9bd1bace | 266 | bool Node::loadFromDatabase(DB_HANDLE hdb, UINT32 dwId) |
5039dede | 267 | { |
5039dede | 268 | int i, iNumRows; |
967893bb | 269 | UINT32 dwSubnetId; |
5039dede | 270 | NetObj *pObject; |
9bd1bace | 271 | bool bResult = false; |
5039dede | 272 | |
c42b4551 | 273 | m_id = dwId; |
5039dede | 274 | |
9bd1bace | 275 | if (!loadCommonProperties(hdb)) |
5039dede | 276 | { |
35f836fe | 277 | DbgPrintf(2, _T("Cannot load common properties for node object %d"), dwId); |
9bd1bace | 278 | return false; |
5039dede AK |
279 | } |
280 | ||
9bd1bace | 281 | DB_STATEMENT hStmt = DBPrepare(hdb, |
4866d57b VK |
282 | _T("SELECT primary_name,primary_ip,node_flags,") |
283 | _T("snmp_version,auth_method,secret,") | |
284 | _T("agent_port,status_poll_type,snmp_oid,agent_version,") | |
285 | _T("platform_name,poller_node_id,zone_guid,") | |
286 | _T("proxy_node,snmp_proxy,required_polls,uname,") | |
287 | _T("use_ifxtable,snmp_port,community,usm_auth_password,") | |
288 | _T("usm_priv_password,usm_methods,snmp_sys_name,bridge_base_addr,") | |
9708eff4 | 289 | _T("runtime_flags,down_since,boot_time,driver_name,icmp_proxy,") |
de674bb6 | 290 | _T("agent_cache_mode,snmp_sys_contact,snmp_sys_location,") |
4e3133ee | 291 | _T("rack_id,rack_image,rack_position,rack_height,") |
e980db40 | 292 | _T("last_agent_comm_time,syslog_msg_count,snmp_trap_count,") |
241541f4 | 293 | _T("node_type,node_subtype,ssh_login,ssh_password,ssh_proxy FROM nodes WHERE id=?")); |
4866d57b | 294 | if (hStmt == NULL) |
9bd1bace | 295 | return false; |
4866d57b VK |
296 | |
297 | DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, dwId); | |
92c51b1d | 298 | DB_RESULT hResult = DBSelectPrepared(hStmt); |
e2babedf | 299 | if (hResult == NULL) |
b1789b80 VK |
300 | { |
301 | DBFreeStatement(hStmt); | |
9bd1bace | 302 | return false; // Query failed |
b1789b80 | 303 | } |
5039dede AK |
304 | |
305 | if (DBGetNumRows(hResult) == 0) | |
306 | { | |
307 | DBFreeResult(hResult); | |
b1789b80 | 308 | DBFreeStatement(hStmt); |
5d2c5741 | 309 | DbgPrintf(2, _T("Missing record in \"nodes\" table for node object %d"), dwId); |
9bd1bace | 310 | return false; |
5039dede AK |
311 | } |
312 | ||
5ad2167d | 313 | DBGetField(hResult, 0, 0, m_primaryName, MAX_DNS_NAME); |
c75e9ee4 | 314 | m_ipAddress = DBGetFieldInetAddr(hResult, 0, 1); |
487cde95 | 315 | m_flags = DBGetFieldULong(hResult, 0, 2); |
5ad2167d | 316 | m_snmpVersion = DBGetFieldLong(hResult, 0, 3); |
c42b4551 | 317 | m_agentAuthMethod = (WORD)DBGetFieldLong(hResult, 0, 4); |
5ad2167d | 318 | DBGetField(hResult, 0, 5, m_szSharedSecret, MAX_SECRET_LENGTH); |
c42b4551 | 319 | m_agentPort = (WORD)DBGetFieldLong(hResult, 0, 6); |
5ad2167d VK |
320 | m_iStatusPollType = DBGetFieldLong(hResult, 0, 7); |
321 | DBGetField(hResult, 0, 8, m_szObjectId, MAX_OID_LEN * 4); | |
5d2c5741 | 322 | DBGetField(hResult, 0, 9, m_szAgentVersion, MAX_AGENT_VERSION_LEN); |
5d2c5741 | 323 | DBGetField(hResult, 0, 10, m_szPlatformName, MAX_PLATFORM_NAME_LEN); |
9208c84b | 324 | m_pollerNode = DBGetFieldULong(hResult, 0, 11); |
52c31148 | 325 | m_zoneId = DBGetFieldULong(hResult, 0, 12); |
9208c84b VK |
326 | m_agentProxy = DBGetFieldULong(hResult, 0, 13); |
327 | m_snmpProxy = DBGetFieldULong(hResult, 0, 14); | |
5d2c5741 | 328 | m_iRequiredPollCount = DBGetFieldLong(hResult, 0, 15); |
0ecc2200 | 329 | m_sysDescription = DBGetField(hResult, 0, 16, NULL, 0); |
5d2c5741 | 330 | m_nUseIfXTable = (BYTE)DBGetFieldLong(hResult, 0, 17); |
296ae03d | 331 | m_snmpPort = (WORD)DBGetFieldLong(hResult, 0, 18); |
5039dede | 332 | |
5d2c5741 | 333 | // SNMP authentication parameters |
35f836fe VK |
334 | char snmpAuthObject[256], snmpAuthPassword[256], snmpPrivPassword[256]; |
335 | DBGetFieldA(hResult, 0, 19, snmpAuthObject, 256); | |
336 | DBGetFieldA(hResult, 0, 20, snmpAuthPassword, 256); | |
337 | DBGetFieldA(hResult, 0, 21, snmpPrivPassword, 256); | |
3408b115 | 338 | int snmpMethods = DBGetFieldLong(hResult, 0, 22); |
5d2c5741 VK |
339 | delete m_snmpSecurity; |
340 | m_snmpSecurity = new SNMP_SecurityContext(snmpAuthObject, snmpAuthPassword, snmpPrivPassword, snmpMethods & 0xFF, snmpMethods >> 8); | |
14b98b3a | 341 | m_snmpSecurity->setSecurityModel((m_snmpVersion == SNMP_VERSION_3) ? SNMP_SECURITY_MODEL_USM : SNMP_SECURITY_MODEL_V2C); |
5d2c5741 | 342 | |
88ac8e88 | 343 | m_sysName = DBGetField(hResult, 0, 23, NULL, 0); |
d74c80ea | 344 | |
3eab63f2 VK |
345 | TCHAR baseAddr[16]; |
346 | TCHAR *value = DBGetField(hResult, 0, 24, baseAddr, 16); | |
347 | if (value != NULL) | |
348 | StrToBin(value, m_baseBridgeAddress, MAC_ADDR_LENGTH); | |
349 | ||
4866d57b | 350 | m_dwDynamicFlags = DBGetFieldULong(hResult, 0, 25); |
b6ead716 | 351 | m_dwDynamicFlags &= NDF_PERSISTENT; // Clear out all non-persistent runtime flags |
4866d57b | 352 | |
8573e935 | 353 | m_downSince = DBGetFieldLong(hResult, 0, 26); |
71e4ed3a | 354 | m_bootTime = DBGetFieldLong(hResult, 0, 27); |
dd42ad0a | 355 | |
28e1575f VK |
356 | // Setup driver |
357 | TCHAR driverName[34]; | |
71e4ed3a | 358 | DBGetField(hResult, 0, 28, driverName, 34); |
28e1575f VK |
359 | StrStrip(driverName); |
360 | if (driverName[0] != 0) | |
361 | m_driver = FindDriverByName(driverName); | |
362 | ||
9208c84b | 363 | m_icmpProxy = DBGetFieldULong(hResult, 0, 29); |
9708eff4 VK |
364 | m_agentCacheMode = (INT16)DBGetFieldLong(hResult, 0, 30); |
365 | if ((m_agentCacheMode != AGENT_CACHE_ON) && (m_agentCacheMode != AGENT_CACHE_OFF)) | |
366 | m_agentCacheMode = AGENT_CACHE_DEFAULT; | |
9208c84b | 367 | |
cf38357f VK |
368 | m_sysContact = DBGetField(hResult, 0, 31, NULL, 0); |
369 | m_sysLocation = DBGetField(hResult, 0, 32, NULL, 0); | |
370 | ||
de674bb6 VK |
371 | m_rackId = DBGetFieldULong(hResult, 0, 33); |
372 | m_rackImage = DBGetFieldGUID(hResult, 0, 34); | |
373 | m_rackPosition = (INT16)DBGetFieldLong(hResult, 0, 35); | |
374 | m_rackHeight = (INT16)DBGetFieldLong(hResult, 0, 36); | |
4e3133ee | 375 | m_lastAgentCommTime = DBGetFieldLong(hResult, 0, 37); |
ba756b1a VK |
376 | m_syslogMessageCount = DBGetFieldInt64(hResult, 0, 38); |
377 | m_snmpTrapCount = DBGetFieldInt64(hResult, 0, 39); | |
e980db40 VK |
378 | m_type = (NodeType)DBGetFieldLong(hResult, 0, 40); |
379 | DBGetField(hResult, 0, 41, m_subType, MAX_NODE_SUBTYPE_LENGTH); | |
2223a4d7 VK |
380 | DBGetField(hResult, 0, 42, m_sshLogin, MAX_SSH_LOGIN_LEN); |
381 | DBGetField(hResult, 0, 43, m_sshPassword, MAX_SSH_PASSWORD_LEN); | |
241541f4 | 382 | m_sshProxy = DBGetFieldULong(hResult, 0, 44); |
de674bb6 | 383 | |
5039dede | 384 | DBFreeResult(hResult); |
b1789b80 | 385 | DBFreeStatement(hStmt); |
5039dede | 386 | |
01152a54 | 387 | if (!m_isDeleted) |
5039dede AK |
388 | { |
389 | // Link node to subnets | |
9bd1bace | 390 | hStmt = DBPrepare(hdb, _T("SELECT subnet_id FROM nsmap WHERE node_id=?")); |
92c51b1d | 391 | if (hStmt == NULL) |
9bd1bace | 392 | return false; |
92c51b1d | 393 | |
c42b4551 | 394 | DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, m_id); |
92c51b1d | 395 | hResult = DBSelectPrepared(hStmt); |
5039dede | 396 | if (hResult == NULL) |
92c51b1d VK |
397 | { |
398 | DBFreeStatement(hStmt); | |
9bd1bace | 399 | return false; // Query failed |
92c51b1d | 400 | } |
5039dede AK |
401 | |
402 | iNumRows = DBGetNumRows(hResult); | |
5039dede AK |
403 | for(i = 0; i < iNumRows; i++) |
404 | { | |
405 | dwSubnetId = DBGetFieldULong(hResult, i, 0); | |
406 | pObject = FindObjectById(dwSubnetId); | |
407 | if (pObject == NULL) | |
408 | { | |
409 | nxlog_write(MSG_INVALID_SUBNET_ID, EVENTLOG_ERROR_TYPE, "dd", dwId, dwSubnetId); | |
410 | break; | |
411 | } | |
c42b4551 | 412 | else if (pObject->getObjectClass() != OBJECT_SUBNET) |
5039dede AK |
413 | { |
414 | nxlog_write(MSG_SUBNET_NOT_SUBNET, EVENTLOG_ERROR_TYPE, "dd", dwId, dwSubnetId); | |
415 | break; | |
416 | } | |
417 | else | |
418 | { | |
1f8be1f4 VK |
419 | pObject->addChild(this); |
420 | addParent(pObject); | |
5039dede AK |
421 | } |
422 | } | |
423 | ||
424 | DBFreeResult(hResult); | |
92c51b1d VK |
425 | DBFreeStatement(hStmt); |
426 | ||
9bd1bace VK |
427 | loadItemsFromDB(hdb); |
428 | loadACLFromDB(hdb); | |
5039dede AK |
429 | |
430 | // Walk through all items in the node and load appropriate thresholds | |
9bd1bace | 431 | bResult = true; |
16d6f798 | 432 | for(i = 0; i < m_dcObjects->size(); i++) |
de674bb6 | 433 | { |
9bd1bace | 434 | if (!m_dcObjects->get(i)->loadThresholdsFromDB(hdb)) |
5039dede | 435 | { |
5d2c5741 | 436 | DbgPrintf(3, _T("Cannot load thresholds for DCI %d of node %d (%s)"), |
c42b4551 | 437 | m_dcObjects->get(i)->getId(), dwId, m_name); |
9bd1bace | 438 | bResult = false; |
5039dede | 439 | } |
de674bb6 VK |
440 | } |
441 | ||
e4926628 VK |
442 | updatePhysicalContainerBinding(OBJECT_RACK, m_rackId); |
443 | updatePhysicalContainerBinding(OBJECT_CHASSIS, m_chassisId); | |
5039dede AK |
444 | } |
445 | else | |
446 | { | |
9bd1bace | 447 | bResult = true; |
5039dede AK |
448 | } |
449 | ||
450 | return bResult; | |
451 | } | |
452 | ||
c50f77f7 VK |
453 | /** |
454 | * Save object to database | |
455 | */ | |
c42b4551 | 456 | BOOL Node::saveToDatabase(DB_HANDLE hdb) |
5039dede | 457 | { |
5039dede | 458 | // Lock object's access |
c42b4551 | 459 | lockProperties(); |
5039dede | 460 | |
28e1575f VK |
461 | if (!saveCommonProperties(hdb)) |
462 | { | |
c42b4551 | 463 | unlockProperties(); |
28e1575f VK |
464 | return FALSE; |
465 | } | |
5039dede | 466 | |
5039dede | 467 | // Form and execute INSERT or UPDATE query |
4b7d8903 | 468 | int snmpMethods = m_snmpSecurity->getAuthMethod() | (m_snmpSecurity->getPrivMethod() << 8); |
28e1575f | 469 | DB_STATEMENT hStmt; |
c42b4551 | 470 | if (IsDatabaseRecordExist(hdb, _T("nodes"), _T("id"), m_id)) |
ba89fed2 | 471 | { |
28e1575f VK |
472 | hStmt = DBPrepare(hdb, |
473 | _T("UPDATE nodes SET primary_ip=?,primary_name=?,snmp_port=?,node_flags=?,snmp_version=?,community=?,") | |
474 | _T("status_poll_type=?,agent_port=?,auth_method=?,secret=?,snmp_oid=?,uname=?,agent_version=?,") | |
9208c84b | 475 | _T("platform_name=?,poller_node_id=?,zone_guid=?,proxy_node=?,snmp_proxy=?,icmp_proxy=?,required_polls=?,") |
28e1575f | 476 | _T("use_ifxtable=?,usm_auth_password=?,usm_priv_password=?,usm_methods=?,snmp_sys_name=?,bridge_base_addr=?,") |
de674bb6 | 477 | _T("runtime_flags=?,down_since=?,driver_name=?,rack_image=?,rack_position=?,rack_height=?,rack_id=?,boot_time=?,") |
ba756b1a | 478 | _T("agent_cache_mode=?,snmp_sys_contact=?,snmp_sys_location=?,last_agent_comm_time=?,") |
86339b28 VK |
479 | _T("syslog_msg_count=?,snmp_trap_count=?,node_type=?,node_subtype=?,ssh_login=?,ssh_password=?,") |
480 | _T("ssh_proxy=?,chassis_id=? WHERE id=?")); | |
ba89fed2 VK |
481 | } |
482 | else | |
65e2005b | 483 | { |
28e1575f VK |
484 | hStmt = DBPrepare(hdb, |
485 | _T("INSERT INTO nodes (primary_ip,primary_name,snmp_port,node_flags,snmp_version,community,status_poll_type,") | |
486 | _T("agent_port,auth_method,secret,snmp_oid,uname,agent_version,platform_name,poller_node_id,zone_guid,") | |
9208c84b | 487 | _T("proxy_node,snmp_proxy,icmp_proxy,required_polls,use_ifxtable,usm_auth_password,usm_priv_password,usm_methods,") |
de674bb6 | 488 | _T("snmp_sys_name,bridge_base_addr,runtime_flags,down_since,driver_name,rack_image,rack_position,rack_height,rack_id,boot_time,") |
e980db40 | 489 | _T("agent_cache_mode,snmp_sys_contact,snmp_sys_location,last_agent_comm_time,syslog_msg_count,snmp_trap_count,") |
86339b28 VK |
490 | _T("node_type,node_subtype,ssh_login,ssh_password,ssh_proxy,chassis_id,id) ") |
491 | _T("VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)")); | |
65e2005b | 492 | } |
28e1575f VK |
493 | if (hStmt == NULL) |
494 | { | |
c42b4551 | 495 | unlockProperties(); |
28e1575f VK |
496 | return FALSE; |
497 | } | |
498 | ||
9708eff4 | 499 | TCHAR ipAddr[64], baseAddress[16], cacheMode[16]; |
28e1575f | 500 | |
c75e9ee4 | 501 | DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, m_ipAddress.toString(ipAddr), DB_BIND_STATIC); |
28e1575f | 502 | DBBind(hStmt, 2, DB_SQLTYPE_VARCHAR, m_primaryName, DB_BIND_STATIC); |
296ae03d | 503 | DBBind(hStmt, 3, DB_SQLTYPE_INTEGER, (LONG)m_snmpPort); |
487cde95 | 504 | DBBind(hStmt, 4, DB_SQLTYPE_INTEGER, m_flags); |
28e1575f VK |
505 | DBBind(hStmt, 5, DB_SQLTYPE_INTEGER, (LONG)m_snmpVersion); |
506 | #ifdef UNICODE | |
507 | DBBind(hStmt, 6, DB_SQLTYPE_VARCHAR, WideStringFromMBString(m_snmpSecurity->getCommunity()), DB_BIND_DYNAMIC); | |
508 | #else | |
509 | DBBind(hStmt, 6, DB_SQLTYPE_VARCHAR, m_snmpSecurity->getCommunity(), DB_BIND_STATIC); | |
510 | #endif | |
511 | DBBind(hStmt, 7, DB_SQLTYPE_INTEGER, (LONG)m_iStatusPollType); | |
c42b4551 VK |
512 | DBBind(hStmt, 8, DB_SQLTYPE_INTEGER, (LONG)m_agentPort); |
513 | DBBind(hStmt, 9, DB_SQLTYPE_INTEGER, (LONG)m_agentAuthMethod); | |
28e1575f VK |
514 | DBBind(hStmt, 10, DB_SQLTYPE_VARCHAR, m_szSharedSecret, DB_BIND_STATIC); |
515 | DBBind(hStmt, 11, DB_SQLTYPE_VARCHAR, m_szObjectId, DB_BIND_STATIC); | |
516 | DBBind(hStmt, 12, DB_SQLTYPE_VARCHAR, m_sysDescription, DB_BIND_STATIC); | |
517 | DBBind(hStmt, 13, DB_SQLTYPE_VARCHAR, m_szAgentVersion, DB_BIND_STATIC); | |
518 | DBBind(hStmt, 14, DB_SQLTYPE_VARCHAR, m_szPlatformName, DB_BIND_STATIC); | |
9208c84b | 519 | DBBind(hStmt, 15, DB_SQLTYPE_INTEGER, m_pollerNode); |
28e1575f | 520 | DBBind(hStmt, 16, DB_SQLTYPE_INTEGER, m_zoneId); |
9208c84b VK |
521 | DBBind(hStmt, 17, DB_SQLTYPE_INTEGER, m_agentProxy); |
522 | DBBind(hStmt, 18, DB_SQLTYPE_INTEGER, m_snmpProxy); | |
523 | DBBind(hStmt, 19, DB_SQLTYPE_INTEGER, m_icmpProxy); | |
524 | DBBind(hStmt, 20, DB_SQLTYPE_INTEGER, (LONG)m_iRequiredPollCount); | |
525 | DBBind(hStmt, 21, DB_SQLTYPE_INTEGER, (LONG)m_nUseIfXTable); | |
28e1575f | 526 | #ifdef UNICODE |
9208c84b VK |
527 | DBBind(hStmt, 22, DB_SQLTYPE_VARCHAR, WideStringFromMBString(m_snmpSecurity->getAuthPassword()), DB_BIND_DYNAMIC); |
528 | DBBind(hStmt, 23, DB_SQLTYPE_VARCHAR, WideStringFromMBString(m_snmpSecurity->getPrivPassword()), DB_BIND_DYNAMIC); | |
28e1575f | 529 | #else |
9208c84b VK |
530 | DBBind(hStmt, 22, DB_SQLTYPE_VARCHAR, m_snmpSecurity->getAuthPassword(), DB_BIND_STATIC); |
531 | DBBind(hStmt, 23, DB_SQLTYPE_VARCHAR, m_snmpSecurity->getPrivPassword(), DB_BIND_STATIC); | |
28e1575f | 532 | #endif |
9208c84b VK |
533 | DBBind(hStmt, 24, DB_SQLTYPE_INTEGER, (LONG)snmpMethods); |
534 | DBBind(hStmt, 25, DB_SQLTYPE_VARCHAR, m_sysName, DB_BIND_STATIC); | |
535 | DBBind(hStmt, 26, DB_SQLTYPE_VARCHAR, BinToStr(m_baseBridgeAddress, MAC_ADDR_LENGTH, baseAddress), DB_BIND_STATIC); | |
536 | DBBind(hStmt, 27, DB_SQLTYPE_INTEGER, m_dwDynamicFlags); | |
537 | DBBind(hStmt, 28, DB_SQLTYPE_INTEGER, (LONG)m_downSince); | |
538 | DBBind(hStmt, 29, DB_SQLTYPE_VARCHAR, (m_driver != NULL) ? m_driver->getName() : _T(""), DB_BIND_STATIC); | |
de674bb6 VK |
539 | DBBind(hStmt, 30, DB_SQLTYPE_VARCHAR, m_rackImage); // rack image |
540 | DBBind(hStmt, 31, DB_SQLTYPE_INTEGER, m_rackPosition); // rack position | |
541 | DBBind(hStmt, 32, DB_SQLTYPE_INTEGER, m_rackHeight); // device height in rack units | |
542 | DBBind(hStmt, 33, DB_SQLTYPE_INTEGER, m_rackId); // rack ID | |
6f77fadd | 543 | DBBind(hStmt, 34, DB_SQLTYPE_INTEGER, (LONG)m_bootTime); |
de674bb6 VK |
544 | DBBind(hStmt, 35, DB_SQLTYPE_VARCHAR, _itot(m_agentCacheMode, cacheMode, 10), DB_BIND_STATIC); |
545 | DBBind(hStmt, 36, DB_SQLTYPE_VARCHAR, m_sysContact, DB_BIND_STATIC); | |
546 | DBBind(hStmt, 37, DB_SQLTYPE_VARCHAR, m_sysLocation, DB_BIND_STATIC); | |
6f77fadd | 547 | DBBind(hStmt, 38, DB_SQLTYPE_INTEGER, (LONG)m_lastAgentCommTime); |
ba756b1a VK |
548 | DBBind(hStmt, 39, DB_SQLTYPE_BIGINT, m_syslogMessageCount); |
549 | DBBind(hStmt, 40, DB_SQLTYPE_BIGINT, m_snmpTrapCount); | |
e980db40 VK |
550 | DBBind(hStmt, 41, DB_SQLTYPE_INTEGER, (INT32)m_type); |
551 | DBBind(hStmt, 42, DB_SQLTYPE_VARCHAR, m_subType, DB_BIND_STATIC); | |
241541f4 VK |
552 | DBBind(hStmt, 43, DB_SQLTYPE_VARCHAR, m_sshLogin, DB_BIND_STATIC); |
553 | DBBind(hStmt, 44, DB_SQLTYPE_VARCHAR, m_sshPassword, DB_BIND_STATIC); | |
554 | DBBind(hStmt, 45, DB_SQLTYPE_INTEGER, m_sshProxy); | |
86339b28 VK |
555 | DBBind(hStmt, 46, DB_SQLTYPE_INTEGER, m_chassisId); |
556 | DBBind(hStmt, 47, DB_SQLTYPE_INTEGER, m_id); | |
28e1575f VK |
557 | |
558 | BOOL bResult = DBExecute(hStmt); | |
559 | DBFreeStatement(hStmt); | |
5039dede | 560 | |
7c521895 | 561 | // Save access list |
89135050 | 562 | saveACLToDB(hdb); |
7c521895 | 563 | |
c42b4551 | 564 | unlockProperties(); |
7c521895 | 565 | |
5039dede AK |
566 | // Save data collection items |
567 | if (bResult) | |
568 | { | |
b06436f4 | 569 | lockDciAccess(false); |
16d6f798 | 570 | for(int i = 0; i < m_dcObjects->size(); i++) |
e7450f3b | 571 | m_dcObjects->get(i)->saveToDatabase(hdb); |
7c521895 | 572 | unlockDciAccess(); |
5039dede AK |
573 | } |
574 | ||
7c521895 | 575 | // Clear modifications flag |
c42b4551 | 576 | lockProperties(); |
01152a54 | 577 | m_isModified = false; |
c42b4551 | 578 | unlockProperties(); |
5039dede | 579 | |
7c521895 | 580 | return bResult; |
5039dede AK |
581 | } |
582 | ||
171c2fd6 VK |
583 | /** |
584 | * Delete object from database | |
585 | */ | |
c42b4551 | 586 | bool Node::deleteFromDatabase(DB_HANDLE hdb) |
5039dede | 587 | { |
c42b4551 | 588 | bool success = DataCollectionTarget::deleteFromDatabase(hdb); |
22ee6d97 VK |
589 | if (success) |
590 | success = executeQueryOnObject(hdb, _T("DELETE FROM nodes WHERE id=?")); | |
591 | if (success) | |
592 | success = executeQueryOnObject(hdb, _T("DELETE FROM nsmap WHERE node_id=?")); | |
593 | return success; | |
5039dede AK |
594 | } |
595 | ||
80e0db05 VK |
596 | /** |
597 | * Get ARP cache from node | |
598 | */ | |
7c521895 | 599 | ARP_CACHE *Node::getArpCache() |
5039dede AK |
600 | { |
601 | ARP_CACHE *pArpCache = NULL; | |
602 | ||
487cde95 | 603 | if (m_flags & NF_IS_LOCAL_MGMT) |
5039dede AK |
604 | { |
605 | pArpCache = GetLocalArpCache(); | |
606 | } | |
487cde95 | 607 | else if (m_flags & NF_IS_NATIVE_AGENT) |
5039dede | 608 | { |
7c521895 VK |
609 | agentLock(); |
610 | if (connectToAgent()) | |
83191808 | 611 | pArpCache = m_agentConnection->getArpCache(); |
7c521895 | 612 | agentUnlock(); |
5039dede | 613 | } |
487cde95 | 614 | else if (m_flags & NF_IS_SNMP) |
5039dede AK |
615 | { |
616 | SNMP_Transport *pTransport; | |
617 | ||
cd9f247e | 618 | pTransport = createSnmpTransport(); |
803d47be VK |
619 | if (pTransport != NULL) |
620 | { | |
621 | pArpCache = SnmpGetArpCache(m_snmpVersion, pTransport); | |
622 | delete pTransport; | |
623 | } | |
5039dede AK |
624 | } |
625 | ||
626 | return pArpCache; | |
627 | } | |
628 | ||
80e0db05 VK |
629 | /** |
630 | * Get list of interfaces from node | |
631 | */ | |
98762401 | 632 | InterfaceList *Node::getInterfaceList() |
5039dede | 633 | { |
98762401 | 634 | InterfaceList *pIfList = NULL; |
5039dede | 635 | |
487cde95 | 636 | if ((m_flags & NF_IS_NATIVE_AGENT) && (!(m_flags & NF_DISABLE_NXCP))) |
5039dede | 637 | { |
7c521895 VK |
638 | agentLock(); |
639 | if (connectToAgent()) | |
5039dede | 640 | { |
83191808 | 641 | pIfList = m_agentConnection->getInterfaceList(); |
5039dede | 642 | } |
7c521895 | 643 | agentUnlock(); |
5039dede | 644 | } |
487cde95 | 645 | if ((pIfList == NULL) && (m_flags & NF_IS_LOCAL_MGMT)) |
b741f151 VK |
646 | { |
647 | pIfList = GetLocalInterfaceList(); | |
648 | } | |
487cde95 VK |
649 | if ((pIfList == NULL) && (m_flags & NF_IS_SNMP) && |
650 | (!(m_flags & NF_DISABLE_SNMP)) && (m_driver != NULL)) | |
5039dede | 651 | { |
2fbf7e1c | 652 | SNMP_Transport *pTransport = createSnmpTransport(); |
803d47be | 653 | if (pTransport != NULL) |
5039dede | 654 | { |
2fbf7e1c | 655 | bool useIfXTable; |
803d47be VK |
656 | if (m_nUseIfXTable == IFXTABLE_DEFAULT) |
657 | { | |
9796ce45 | 658 | useIfXTable = (ConfigReadInt(_T("UseIfXTable"), 1) != 0) ? true : false; |
803d47be VK |
659 | } |
660 | else | |
661 | { | |
9796ce45 | 662 | useIfXTable = (m_nUseIfXTable == IFXTABLE_ENABLED) ? true : false; |
803d47be | 663 | } |
9796ce45 VK |
664 | |
665 | int useAliases = ConfigReadInt(_T("UseInterfaceAliases"), 0); | |
ae32341d | 666 | pIfList = m_driver->getInterfaces(pTransport, &m_customAttributes, m_driverData, useAliases, useIfXTable); |
eec253a8 | 667 | |
487cde95 | 668 | if ((pIfList != NULL) && (m_flags & NF_IS_BRIDGE)) |
eec253a8 | 669 | { |
9c5ebc32 | 670 | BridgeMapPorts(pTransport, pIfList); |
eec253a8 | 671 | } |
803d47be | 672 | delete pTransport; |
5039dede | 673 | } |
5039dede AK |
674 | } |
675 | ||
676 | if (pIfList != NULL) | |
0d75ea88 | 677 | { |
024c3faf | 678 | checkInterfaceNames(pIfList); |
0d75ea88 VK |
679 | addVrrpInterfaces(pIfList); |
680 | } | |
5039dede AK |
681 | |
682 | return pIfList; | |
683 | } | |
684 | ||
6fd6de0a VK |
685 | /** |
686 | * Add VRRP interfaces to interface list | |
687 | */ | |
98762401 | 688 | void Node::addVrrpInterfaces(InterfaceList *ifList) |
0d75ea88 VK |
689 | { |
690 | int i, j, k; | |
691 | TCHAR buffer[32]; | |
692 | ||
c42b4551 | 693 | lockProperties(); |
0d75ea88 VK |
694 | if (m_vrrpInfo != NULL) |
695 | { | |
c42b4551 | 696 | DbgPrintf(6, _T("Node::addVrrpInterfaces(node=%s [%d]): m_vrrpInfo->size()=%d"), m_name, (int)m_id, m_vrrpInfo->size()); |
0d75ea88 | 697 | |
a6312bd6 | 698 | for(i = 0; i < m_vrrpInfo->size(); i++) |
0d75ea88 VK |
699 | { |
700 | VrrpRouter *router = m_vrrpInfo->getRouter(i); | |
c42b4551 | 701 | DbgPrintf(6, _T("Node::addVrrpInterfaces(node=%s [%d]): vrouter %d state=%d"), m_name, (int)m_id, i, router->getState()); |
0d75ea88 VK |
702 | if (router->getState() != VRRP_STATE_MASTER) |
703 | continue; // Do not add interfaces if router is not in master state | |
704 | ||
705 | // Get netmask for this VR | |
c30c0c0f | 706 | int maskBits = 0; |
a6312bd6 | 707 | for(j = 0; j < ifList->size(); j++) |
c30c0c0f VK |
708 | { |
709 | InterfaceInfo *iface = ifList->get(j); | |
710 | if (iface->index == router->getIfIndex()) | |
0d75ea88 | 711 | { |
c30c0c0f VK |
712 | for(int k = 0; k < iface->ipAddrList.size(); k++) |
713 | { | |
714 | const InetAddress& addr = iface->ipAddrList.get(k); | |
715 | if (addr.getSubnetAddress().contain(router->getVip(0))) | |
716 | { | |
717 | maskBits = addr.getMaskBits(); | |
718 | } | |
719 | } | |
0d75ea88 VK |
720 | break; |
721 | } | |
c30c0c0f | 722 | } |
0d75ea88 VK |
723 | |
724 | // Walk through all VR virtual IPs | |
725 | for(j = 0; j < router->getVipCount(); j++) | |
726 | { | |
967893bb | 727 | UINT32 vip = router->getVip(j); |
c42b4551 | 728 | DbgPrintf(6, _T("Node::addVrrpInterfaces(node=%s [%d]): checking VIP %s@%d"), m_name, (int)m_id, IpToStr(vip, buffer), i); |
0d75ea88 VK |
729 | if (vip != 0) |
730 | { | |
a6312bd6 | 731 | for(k = 0; k < ifList->size(); k++) |
c30c0c0f | 732 | if (ifList->get(k)->hasAddress(vip)) |
0d75ea88 | 733 | break; |
a6312bd6 | 734 | if (k == ifList->size()) |
0d75ea88 | 735 | { |
c30c0c0f VK |
736 | InterfaceInfo *iface = new InterfaceInfo(0); |
737 | _sntprintf(iface->name, MAX_DB_STRING, _T("vrrp.%u.%u.%d"), router->getId(), router->getIfIndex(), j); | |
738 | memcpy(iface->macAddr, router->getVirtualMacAddr(), MAC_ADDR_LENGTH); | |
739 | InetAddress addr(vip); | |
740 | addr.setMaskBits(maskBits); | |
741 | iface->ipAddrList.add(addr); | |
742 | ifList->add(iface); | |
743 | DbgPrintf(6, _T("Node::addVrrpInterfaces(node=%s [%d]): added interface %s"), m_name, (int)m_id, iface->name); | |
0d75ea88 VK |
744 | } |
745 | } | |
746 | } | |
747 | } | |
748 | } | |
c42b4551 | 749 | unlockProperties(); |
0d75ea88 VK |
750 | } |
751 | ||
7946bd7c | 752 | /** |
14228410 | 753 | * Find interface by index. |
71ea7674 | 754 | * |
14228410 | 755 | * @param ifIndex interface index to match |
71ea7674 | 756 | * @return pointer to interface object or NULL if appropriate interface couldn't be found |
7946bd7c | 757 | */ |
c75e9ee4 | 758 | Interface *Node::findInterfaceByIndex(UINT32 ifIndex) |
5039dede | 759 | { |
db091a1f | 760 | lockChildList(false); |
274d9c7a | 761 | for(int i = 0; i < m_childList->size(); i++) |
db091a1f | 762 | if (m_childList->get(i)->getObjectClass() == OBJECT_INTERFACE) |
5039dede | 763 | { |
274d9c7a | 764 | Interface *pInterface = (Interface *)m_childList->get(i); |
c75e9ee4 | 765 | if (pInterface->getIfIndex() == ifIndex) |
5039dede | 766 | { |
db091a1f | 767 | unlockChildList(); |
c75e9ee4 | 768 | return pInterface; |
5039dede AK |
769 | } |
770 | } | |
db091a1f | 771 | unlockChildList(); |
5039dede AK |
772 | return NULL; |
773 | } | |
774 | ||
7946bd7c VK |
775 | /** |
776 | * Find interface by name or description | |
777 | * Returns pointer to interface object or NULL if appropriate interface couldn't be found | |
778 | */ | |
c75e9ee4 | 779 | Interface *Node::findInterfaceByName(const TCHAR *name) |
630e15d6 | 780 | { |
cf1d689e VK |
781 | if ((name == NULL) || (name[0] == 0)) |
782 | return NULL; | |
783 | ||
630e15d6 VK |
784 | Interface *pInterface; |
785 | ||
db091a1f | 786 | lockChildList(false); |
274d9c7a | 787 | for(int i = 0; i < m_childList->size(); i++) |
db091a1f | 788 | if (m_childList->get(i)->getObjectClass() == OBJECT_INTERFACE) |
630e15d6 | 789 | { |
db091a1f | 790 | pInterface = (Interface *)m_childList->get(i); |
c42b4551 | 791 | if (!_tcsicmp(pInterface->getName(), name) || !_tcsicmp(pInterface->getDescription(), name)) |
630e15d6 | 792 | { |
db091a1f | 793 | unlockChildList(); |
630e15d6 VK |
794 | return pInterface; |
795 | } | |
796 | } | |
db091a1f | 797 | unlockChildList(); |
630e15d6 VK |
798 | return NULL; |
799 | } | |
800 | ||
7946bd7c VK |
801 | /** |
802 | * Find interface by slot/port pair | |
803 | * Returns pointer to interface object or NULL if appropriate interface couldn't be found | |
804 | */ | |
967893bb | 805 | Interface *Node::findInterfaceBySlotAndPort(UINT32 slot, UINT32 port) |
3f8c54e7 | 806 | { |
db091a1f | 807 | lockChildList(false); |
274d9c7a | 808 | for(int i = 0; i < m_childList->size(); i++) |
db091a1f | 809 | if (m_childList->get(i)->getObjectClass() == OBJECT_INTERFACE) |
3f8c54e7 | 810 | { |
274d9c7a | 811 | Interface *pInterface = (Interface *)m_childList->get(i); |
4c16cdc7 | 812 | if (pInterface->isPhysicalPort() && (pInterface->getSlotNumber() == slot) && (pInterface->getPortNumber() == port)) |
3f8c54e7 | 813 | { |
db091a1f | 814 | unlockChildList(); |
3f8c54e7 VK |
815 | return pInterface; |
816 | } | |
817 | } | |
db091a1f | 818 | unlockChildList(); |
3f8c54e7 VK |
819 | return NULL; |
820 | } | |
821 | ||
7946bd7c VK |
822 | /** |
823 | * Find interface by MAC address | |
824 | * Returns pointer to interface object or NULL if appropriate interface couldn't be found | |
825 | */ | |
eec253a8 VK |
826 | Interface *Node::findInterfaceByMAC(const BYTE *macAddr) |
827 | { | |
8f26db67 | 828 | Interface *iface = NULL; |
db091a1f VK |
829 | lockChildList(false); |
830 | for(int i = 0; i < m_childList->size(); i++) | |
831 | { | |
832 | NetObj *curr = m_childList->get(i); | |
833 | if (curr->getObjectClass() == OBJECT_INTERFACE) | |
eec253a8 | 834 | { |
db091a1f | 835 | if (!memcmp(((Interface *)curr)->getMacAddr(), macAddr, MAC_ADDR_LENGTH)) |
eec253a8 | 836 | { |
db091a1f | 837 | iface = (Interface *)curr; |
8f26db67 | 838 | break; |
eec253a8 VK |
839 | } |
840 | } | |
db091a1f VK |
841 | } |
842 | unlockChildList(); | |
8f26db67 | 843 | return iface; |
eec253a8 VK |
844 | } |
845 | ||
7946bd7c VK |
846 | /** |
847 | * Find interface by IP address | |
848 | * Returns pointer to interface object or NULL if appropriate interface couldn't be found | |
849 | */ | |
c75e9ee4 | 850 | Interface *Node::findInterfaceByIP(const InetAddress& addr) |
eec253a8 | 851 | { |
c75e9ee4 | 852 | if (!addr.isValid()) |
eec253a8 VK |
853 | return NULL; |
854 | ||
db091a1f VK |
855 | lockChildList(false); |
856 | for(int i = 0; i < m_childList->size(); i++) | |
857 | if (m_childList->get(i)->getObjectClass() == OBJECT_INTERFACE) | |
eec253a8 | 858 | { |
db091a1f | 859 | Interface *pInterface = (Interface *)m_childList->get(i); |
c30c0c0f | 860 | if (pInterface->getIpAddressList()->hasAddress(addr)) |
eec253a8 | 861 | { |
db091a1f | 862 | unlockChildList(); |
eec253a8 VK |
863 | return pInterface; |
864 | } | |
865 | } | |
db091a1f | 866 | unlockChildList(); |
eec253a8 VK |
867 | return NULL; |
868 | } | |
869 | ||
7946bd7c VK |
870 | /** |
871 | * Find interface by bridge port number | |
872 | */ | |
967893bb | 873 | Interface *Node::findBridgePort(UINT32 bridgePortNumber) |
eec253a8 | 874 | { |
db091a1f VK |
875 | lockChildList(false); |
876 | for(int i = 0; i < m_childList->size(); i++) | |
877 | if (m_childList->get(i)->getObjectClass() == OBJECT_INTERFACE) | |
eec253a8 | 878 | { |
db091a1f | 879 | Interface *pInterface = (Interface *)m_childList->get(i); |
eec253a8 VK |
880 | if (pInterface->getBridgePortNumber() == bridgePortNumber) |
881 | { | |
db091a1f | 882 | unlockChildList(); |
eec253a8 VK |
883 | return pInterface; |
884 | } | |
885 | } | |
db091a1f | 886 | unlockChildList(); |
eec253a8 VK |
887 | return NULL; |
888 | } | |
889 | ||
7946bd7c VK |
890 | /** |
891 | * Find connection point for node | |
892 | */ | |
75ebb063 | 893 | NetObj *Node::findConnectionPoint(UINT32 *localIfId, BYTE *localMacAddr, int *type) |
f42b8099 | 894 | { |
75ebb063 | 895 | NetObj *cp = NULL; |
db091a1f VK |
896 | lockChildList(false); |
897 | for(int i = 0; i < m_childList->size(); i++) | |
d0b5d358 | 898 | { |
db091a1f | 899 | if (m_childList->get(i)->getObjectClass() == OBJECT_INTERFACE) |
f42b8099 | 900 | { |
db091a1f | 901 | Interface *iface = (Interface *)m_childList->get(i); |
75ebb063 | 902 | cp = FindInterfaceConnectionPoint(iface->getMacAddr(), type); |
f42b8099 | 903 | if (cp != NULL) |
06a93345 | 904 | { |
c42b4551 | 905 | *localIfId = iface->getId(); |
eec253a8 | 906 | memcpy(localMacAddr, iface->getMacAddr(), MAC_ADDR_LENGTH); |
f42b8099 | 907 | break; |
06a93345 | 908 | } |
f42b8099 | 909 | } |
d0b5d358 | 910 | } |
db091a1f | 911 | unlockChildList(); |
f42b8099 VK |
912 | return cp; |
913 | } | |
914 | ||
8f26db67 VK |
915 | /** |
916 | * Find attached access point by MAC address | |
917 | */ | |
918 | AccessPoint *Node::findAccessPointByMAC(const BYTE *macAddr) | |
919 | { | |
920 | AccessPoint *ap = NULL; | |
db091a1f VK |
921 | lockChildList(false); |
922 | for(int i = 0; i < m_childList->size(); i++) | |
923 | { | |
924 | NetObj *curr = m_childList->get(i); | |
925 | if (curr->getObjectClass() == OBJECT_ACCESSPOINT) | |
8f26db67 | 926 | { |
db091a1f | 927 | if (!memcmp(((AccessPoint *)curr)->getMacAddr(), macAddr, MAC_ADDR_LENGTH)) |
8f26db67 | 928 | { |
db091a1f | 929 | ap = (AccessPoint *)curr; |
8f26db67 VK |
930 | break; |
931 | } | |
932 | } | |
db091a1f VK |
933 | } |
934 | unlockChildList(); | |
8f26db67 VK |
935 | return ap; |
936 | } | |
937 | ||
938 | /** | |
939 | * Find access point by radio ID (radio interface index) | |
940 | */ | |
941 | AccessPoint *Node::findAccessPointByRadioId(int rfIndex) | |
942 | { | |
943 | AccessPoint *ap = NULL; | |
db091a1f VK |
944 | lockChildList(false); |
945 | for(int i = 0; i < m_childList->size(); i++) | |
946 | { | |
947 | NetObj *curr = m_childList->get(i); | |
948 | if (curr->getObjectClass() == OBJECT_ACCESSPOINT) | |
8f26db67 | 949 | { |
db091a1f | 950 | if (((AccessPoint *)curr)->isMyRadio(rfIndex)) |
8f26db67 | 951 | { |
db091a1f | 952 | ap = (AccessPoint *)curr; |
8f26db67 VK |
953 | break; |
954 | } | |
955 | } | |
db091a1f VK |
956 | } |
957 | unlockChildList(); | |
8f26db67 VK |
958 | return ap; |
959 | } | |
960 | ||
386f88e3 VK |
961 | /** |
962 | * Find attached access point by BSSID | |
963 | */ | |
964 | AccessPoint *Node::findAccessPointByBSSID(const BYTE *bssid) | |
965 | { | |
966 | AccessPoint *ap = NULL; | |
db091a1f VK |
967 | lockChildList(false); |
968 | for(int i = 0; i < m_childList->size(); i++) | |
969 | { | |
970 | NetObj *curr = m_childList->get(i); | |
971 | if (curr->getObjectClass() == OBJECT_ACCESSPOINT) | |
386f88e3 | 972 | { |
db091a1f VK |
973 | if (!memcmp(((AccessPoint *)curr)->getMacAddr(), bssid, MAC_ADDR_LENGTH) || |
974 | ((AccessPoint *)curr)->isMyRadio(bssid)) | |
386f88e3 | 975 | { |
db091a1f | 976 | ap = (AccessPoint *)curr; |
386f88e3 VK |
977 | break; |
978 | } | |
979 | } | |
db091a1f VK |
980 | } |
981 | unlockChildList(); | |
386f88e3 VK |
982 | return ap; |
983 | } | |
984 | ||
a3050773 VK |
985 | /** |
986 | * Check if given IP address is one of node's interfaces | |
987 | */ | |
c75e9ee4 | 988 | bool Node::isMyIP(const InetAddress& addr) |
5039dede | 989 | { |
db091a1f VK |
990 | lockChildList(false); |
991 | for(int i = 0; i < m_childList->size(); i++) | |
992 | if (m_childList->get(i)->getObjectClass() == OBJECT_INTERFACE) | |
5039dede | 993 | { |
db091a1f | 994 | if (((Interface *)m_childList->get(i))->getIpAddressList()->hasAddress(addr)) |
5039dede | 995 | { |
db091a1f | 996 | unlockChildList(); |
c75e9ee4 | 997 | return true; |
5039dede AK |
998 | } |
999 | } | |
db091a1f | 1000 | unlockChildList(); |
c75e9ee4 | 1001 | return false; |
5039dede AK |
1002 | } |
1003 | ||
e55ff6f9 VK |
1004 | /** |
1005 | * Filter interface - should return true if system should proceed with interface creation | |
1006 | */ | |
1007 | bool Node::filterInterface(InterfaceInfo *info) | |
1008 | { | |
1009 | NXSL_VM *vm = g_pScriptLibrary->createVM(_T("Hook::CreateInterface"), new NXSL_ServerEnv); | |
1010 | if (vm == NULL) | |
1011 | { | |
1012 | DbgPrintf(7, _T("Node::filterInterface(%s [%u]): hook script \"Hook::CreateInterface\" not found"), m_name, m_id); | |
1013 | return true; | |
1014 | } | |
1015 | ||
1016 | Interface *iface; | |
1017 | if (info->name[0] != 0) | |
1018 | iface = new Interface(info->name, (info->description[0] != 0) ? info->description : info->name, | |
1019 | info->index, info->ipAddrList, info->type, m_zoneId); | |
1020 | else | |
1021 | iface = new Interface(info->ipAddrList, m_zoneId, false); | |
1022 | iface->setMacAddr(info->macAddr, false); | |
1023 | iface->setBridgePortNumber(info->bridgePort); | |
1024 | iface->setSlotNumber(info->slot); | |
1025 | iface->setPortNumber(info->port); | |
1026 | iface->setPhysicalPortFlag(info->isPhysicalPort); | |
1027 | iface->setManualCreationFlag(false); | |
1028 | iface->setSystemFlag(info->isSystem); | |
1029 | iface->setMTU(info->mtu); | |
1030 | iface->setSpeed(info->speed); | |
1031 | iface->setIfTableSuffix(info->ifTableSuffixLength, info->ifTableSuffix); | |
1032 | ||
1033 | bool pass = true; | |
1034 | NXSL_Value *argv = new NXSL_Value(new NXSL_Object(&g_nxslInterfaceClass, iface)); | |
1035 | vm->setGlobalVariable(_T("$node"), new NXSL_Value(new NXSL_Object(&g_nxslNodeClass, this))); | |
1036 | if (vm->run(1, &argv)) | |
1037 | { | |
1038 | NXSL_Value *result = vm->getResult(); | |
1039 | if ((result != NULL) && result->isInteger()) | |
1040 | { | |
1041 | pass = (result->getValueAsInt32() != 0); | |
1042 | } | |
1043 | } | |
1044 | else | |
1045 | { | |
1046 | DbgPrintf(4, _T("Node::filterInterface(%s [%u]): hook script execution error: %s"), m_name, m_id, vm->getErrorText()); | |
1047 | } | |
1048 | delete vm; | |
1049 | delete iface; | |
1050 | ||
1051 | DbgPrintf(6, _T("Node::filterInterface(%s [%u]): interface \"%s\" (ifIndex=%d) %s by filter"), | |
1052 | m_name, m_id, info->name, info->index, pass ? _T("accepted") : _T("rejected")); | |
1053 | return pass; | |
1054 | } | |
1055 | ||
e95680e5 VK |
1056 | /** |
1057 | * Create new interface - convenience wrapper | |
1058 | */ | |
c77bdd19 | 1059 | Interface *Node::createNewInterface(const InetAddress& ipAddr, BYTE *macAddr, bool fakeInterface) |
e95680e5 | 1060 | { |
c30c0c0f VK |
1061 | InterfaceInfo info(1); |
1062 | info.ipAddrList.add(ipAddr); | |
e95680e5 VK |
1063 | if (macAddr != NULL) |
1064 | memcpy(info.macAddr, macAddr, MAC_ADDR_LENGTH); | |
c77bdd19 | 1065 | return createNewInterface(&info, false, fakeInterface); |
e95680e5 VK |
1066 | } |
1067 | ||
a3050773 VK |
1068 | /** |
1069 | * Create new interface | |
1070 | */ | |
c77bdd19 | 1071 | Interface *Node::createNewInterface(InterfaceInfo *info, bool manuallyCreated, bool fakeInterface) |
5039dede | 1072 | { |
e95680e5 | 1073 | bool bSyntheticMask = false; |
c30c0c0f | 1074 | TCHAR buffer[64]; |
5039dede | 1075 | |
5cf8497c | 1076 | DbgPrintf(5, _T("Node::createNewInterface(\"%s\", %d, %d, bp=%d, slot=%d, port=%d) called for node %s [%d]"), |
c30c0c0f VK |
1077 | info->name, info->index, info->type, info->bridgePort, info->slot, info->port, m_name, m_id); |
1078 | for(int i = 0; i < info->ipAddrList.size(); i++) | |
1079 | { | |
1080 | const InetAddress& addr = info->ipAddrList.get(i); | |
1081 | DbgPrintf(5, _T("Node::createNewInterface(%s): IP address %s/%d"), info->name, addr.toString(buffer), addr.getMaskBits()); | |
1082 | } | |
5039dede AK |
1083 | |
1084 | // Find subnet to place interface object to | |
c30c0c0f | 1085 | if (info->type != IFTYPE_SOFTWARE_LOOPBACK) |
5039dede | 1086 | { |
c30c0c0f VK |
1087 | Cluster *pCluster = getMyCluster(); |
1088 | for(int i = 0; i < info->ipAddrList.size(); i++) | |
1089 | { | |
1090 | InetAddress addr = info->ipAddrList.get(i); | |
1091 | bool addToSubnet = addr.isValidUnicast() && ((pCluster == NULL) || !pCluster->isSyncAddr(addr)); | |
1092 | DbgPrintf(5, _T("Node::createNewInterface: node=%s [%d] ip=%s/%d cluster=%s [%d] add=%s"), | |
e83d726c | 1093 | m_name, m_id, addr.toString(buffer), addr.getMaskBits(), |
c30c0c0f VK |
1094 | (pCluster != NULL) ? pCluster->getName() : _T("(null)"), |
1095 | (pCluster != NULL) ? pCluster->getId() : 0, addToSubnet ? _T("yes") : _T("no")); | |
1096 | if (addToSubnet) | |
1097 | { | |
1098 | Subnet *pSubnet = FindSubnetForNode(m_zoneId, addr); | |
1099 | if (pSubnet == NULL) | |
1100 | { | |
1101 | // Check if netmask is 0 (detect), and if yes, create | |
64478dc4 | 1102 | // new subnet with default mask |
c30c0c0f VK |
1103 | if (addr.getMaskBits() == 0) |
1104 | { | |
1105 | bSyntheticMask = true; | |
9d7771b8 | 1106 | addr.setMaskBits((addr.getFamily() == AF_INET) ? ConfigReadInt(_T("DefaultSubnetMaskIPv4"), 24) : ConfigReadInt(_T("DefaultSubnetMaskIPv6"), 64)); |
5cf8497c | 1107 | info->ipAddrList.replace(addr); |
c30c0c0f | 1108 | } |
5039dede | 1109 | |
c30c0c0f VK |
1110 | // Create new subnet object |
1111 | if (addr.getHostBits() >= 2) | |
1112 | { | |
1113 | pSubnet = createSubnet(addr, bSyntheticMask); | |
64478dc4 VK |
1114 | if (bSyntheticMask) |
1115 | { | |
1116 | // createSubnet may adjust address mask bits | |
1117 | info->ipAddrList.replace(addr); | |
1118 | } | |
c30c0c0f VK |
1119 | } |
1120 | } | |
1121 | else | |
1122 | { | |
64478dc4 | 1123 | // Set correct netmask if we were asked for it |
c30c0c0f VK |
1124 | if (addr.getMaskBits() == 0) |
1125 | { | |
c30c0c0f | 1126 | bSyntheticMask = pSubnet->isSyntheticMask(); |
5cf8497c VK |
1127 | addr.setMaskBits(pSubnet->getIpAddress().getMaskBits()); |
1128 | info->ipAddrList.replace(addr); | |
c30c0c0f VK |
1129 | } |
1130 | } | |
1131 | if (pSubnet != NULL) | |
1132 | { | |
1133 | pSubnet->addNode(this); | |
1134 | } | |
1135 | } // addToSubnet | |
1136 | } // loop by address list | |
5039dede AK |
1137 | } |
1138 | ||
1139 | // Create interface object | |
c30c0c0f | 1140 | Interface *pInterface; |
e95680e5 | 1141 | if (info->name[0] != 0) |
e83d726c | 1142 | pInterface = new Interface(info->name, (info->description[0] != 0) ? info->description : info->name, |
c30c0c0f | 1143 | info->index, info->ipAddrList, info->type, m_zoneId); |
5039dede | 1144 | else |
c30c0c0f | 1145 | pInterface = new Interface(info->ipAddrList, m_zoneId, bSyntheticMask); |
e55ff6f9 | 1146 | pInterface->setMacAddr(info->macAddr, false); |
e95680e5 VK |
1147 | pInterface->setBridgePortNumber(info->bridgePort); |
1148 | pInterface->setSlotNumber(info->slot); | |
1149 | pInterface->setPortNumber(info->port); | |
1150 | pInterface->setPhysicalPortFlag(info->isPhysicalPort); | |
9214177b | 1151 | pInterface->setManualCreationFlag(manuallyCreated); |
e95680e5 | 1152 | pInterface->setSystemFlag(info->isSystem); |
33560996 | 1153 | pInterface->setMTU(info->mtu); |
e5f4e3ac VK |
1154 | pInterface->setSpeed(info->speed); |
1155 | pInterface->setIfTableSuffix(info->ifTableSuffixLength, info->ifTableSuffix); | |
5039dede | 1156 | |
c908b63b VK |
1157 | int defaultExpectedState = ConfigReadInt(_T("DefaultInterfaceExpectedState"), IF_DEFAULT_EXPECTED_STATE_UP); |
1158 | switch(defaultExpectedState) | |
1159 | { | |
1160 | case IF_DEFAULT_EXPECTED_STATE_AUTO: | |
c77bdd19 | 1161 | pInterface->setExpectedState(fakeInterface ? IF_EXPECTED_STATE_UP : IF_EXPECTED_STATE_AUTO); |
c908b63b VK |
1162 | break; |
1163 | case IF_DEFAULT_EXPECTED_STATE_IGNORE: | |
1164 | pInterface->setExpectedState(IF_EXPECTED_STATE_IGNORE); | |
1165 | break; | |
1166 | default: | |
1167 | pInterface->setExpectedState(IF_EXPECTED_STATE_UP); | |
1168 | break; | |
1169 | } | |
1170 | ||
5039dede | 1171 | // Insert to objects' list and generate event |
e7450f3b | 1172 | NetObjInsert(pInterface, true, false); |
eec253a8 | 1173 | addInterface(pInterface); |
01152a54 | 1174 | if (!m_isHidden) |
478d4ff4 | 1175 | pInterface->unhide(); |
01152a54 | 1176 | if (!pInterface->isSystem()) |
5039dede | 1177 | { |
c30c0c0f VK |
1178 | const InetAddress& addr = pInterface->getFirstIpAddress(); |
1179 | PostEvent(EVENT_INTERFACE_ADDED, m_id, "dsAdd", pInterface->getId(), | |
1180 | pInterface->getName(), &addr, addr.getMaskBits(), pInterface->getIfIndex()); | |
5039dede | 1181 | } |
9214177b VK |
1182 | |
1183 | return pInterface; | |
5039dede AK |
1184 | } |
1185 | ||
a3050773 VK |
1186 | /** |
1187 | * Delete interface from node | |
1188 | */ | |
c30c0c0f | 1189 | void Node::deleteInterface(Interface *iface) |
5039dede | 1190 | { |
c30c0c0f | 1191 | DbgPrintf(5, _T("Node::deleteInterface(node=%s [%d], interface=%s [%d])"), m_name, m_id, iface->getName(), iface->getId()); |
dfb38baf | 1192 | |
5039dede | 1193 | // Check if we should unlink node from interface's subnet |
c30c0c0f | 1194 | if (!iface->isExcludedFromTopology()) |
5039dede | 1195 | { |
c30c0c0f VK |
1196 | const ObjectArray<InetAddress> *list = iface->getIpAddressList()->getList(); |
1197 | for(int i = 0; i < list->size(); i++) | |
1198 | { | |
1199 | bool doUnlink = true; | |
1200 | const InetAddress *addr = list->get(i); | |
5039dede | 1201 | |
db091a1f VK |
1202 | lockChildList(false); |
1203 | for(int j = 0; j < m_childList->size(); j++) | |
1204 | { | |
6e81bd95 | 1205 | NetObj *curr = m_childList->get(j); |
db091a1f VK |
1206 | if ((curr->getObjectClass() == OBJECT_INTERFACE) && (curr != iface) && |
1207 | ((Interface *)curr)->getIpAddressList()->findSameSubnetAddress(*addr).isValid()) | |
c30c0c0f VK |
1208 | { |
1209 | doUnlink = false; | |
1210 | break; | |
1211 | } | |
db091a1f VK |
1212 | } |
1213 | unlockChildList(); | |
4d2c3a54 | 1214 | |
c30c0c0f | 1215 | if (doUnlink) |
5039dede | 1216 | { |
c30c0c0f VK |
1217 | // Last interface in subnet, should unlink node |
1218 | Subnet *pSubnet = FindSubnetByIP(m_zoneId, addr->getSubnetAddress()); | |
1219 | if (pSubnet != NULL) | |
1220 | { | |
1f8be1f4 VK |
1221 | deleteParent(pSubnet); |
1222 | pSubnet->deleteChild(this); | |
c30c0c0f VK |
1223 | } |
1224 | DbgPrintf(5, _T("Node::deleteInterface(node=%s [%d], interface=%s [%d]): unlinked from subnet %s [%d]"), | |
1225 | m_name, m_id, iface->getName(), iface->getId(), | |
1226 | (pSubnet != NULL) ? pSubnet->getName() : _T("(null)"), | |
1227 | (pSubnet != NULL) ? pSubnet->getId() : 0); | |
5039dede AK |
1228 | } |
1229 | } | |
1230 | } | |
c30c0c0f | 1231 | iface->deleteObject(); |
5039dede AK |
1232 | } |
1233 | ||
7946bd7c VK |
1234 | /** |
1235 | * Calculate node status based on child objects status | |
1236 | */ | |
27f9598d | 1237 | void Node::calculateCompoundStatus(BOOL bForcedRecalc) |
5039dede | 1238 | { |
db091a1f | 1239 | int iOldStatus = m_status; |
967893bb | 1240 | static UINT32 dwEventCodes[] = { EVENT_NODE_NORMAL, EVENT_NODE_WARNING, |
67c45b4d | 1241 | EVENT_NODE_MINOR, EVENT_NODE_MAJOR, EVENT_NODE_CRITICAL, |
5039dede AK |
1242 | EVENT_NODE_UNKNOWN, EVENT_NODE_UNMANAGED }; |
1243 | ||
f94d5259 | 1244 | DataCollectionTarget::calculateCompoundStatus(bForcedRecalc); |
db091a1f VK |
1245 | if (m_status != iOldStatus) |
1246 | PostEvent(dwEventCodes[m_status], m_id, "d", iOldStatus); | |
5039dede AK |
1247 | } |
1248 | ||
208d7427 VK |
1249 | /** |
1250 | * Status poller entry point | |
1251 | */ | |
1252 | void Node::statusPoll(PollerInfo *poller) | |
1253 | { | |
1254 | poller->startExecution(); | |
1255 | statusPoll(NULL, 0, poller); | |
1256 | ||
1257 | // Check if the node has to be deleted due to long downtime | |
1258 | time_t unreachableDeleteDays = (time_t)ConfigReadInt(_T("DeleteUnreachableNodesPeriod"), 0); | |
9db92307 | 1259 | if ((unreachableDeleteDays > 0) && (m_downSince > 0) && |
208d7427 VK |
1260 | (time(NULL) - m_downSince > unreachableDeleteDays * 24 * 3600)) |
1261 | { | |
1262 | deleteObject(); | |
1263 | } | |
1264 | delete poller; | |
1265 | } | |
1266 | ||
a5ee7b3b VK |
1267 | /** |
1268 | * Perform status poll on node | |
1269 | */ | |
208d7427 | 1270 | void Node::statusPoll(ClientSession *pSession, UINT32 dwRqId, PollerInfo *poller) |
5039dede | 1271 | { |
46117060 VK |
1272 | if (m_dwDynamicFlags & NDF_DELETE_IN_PROGRESS) |
1273 | { | |
1274 | if (dwRqId == 0) | |
1275 | m_dwDynamicFlags &= ~NDF_QUEUED_FOR_STATUS_POLL; | |
1276 | return; | |
1277 | } | |
1278 | ||
88dc9091 | 1279 | if (IsShutdownInProgress()) |
9fc9ec2c VK |
1280 | return; |
1281 | ||
487cde95 | 1282 | UINT32 dwOldFlags = m_flags; |
5039dede | 1283 | NetObj *pPollerNode = NULL, **ppPollList; |
5039dede AK |
1284 | SNMP_Transport *pTransport; |
1285 | Cluster *pCluster; | |
1286 | time_t tNow, tExpire; | |
1287 | ||
c1482463 | 1288 | Queue *pQueue = new Queue; // Delayed event queue |
208d7427 | 1289 | poller->setStatus(_T("wait for lock")); |
7c521895 | 1290 | pollerLock(); |
88dc9091 VK |
1291 | |
1292 | if (IsShutdownInProgress()) | |
1293 | { | |
1294 | delete pQueue; | |
1295 | pollerUnlock(); | |
1296 | return; | |
1297 | } | |
1298 | ||
c59466d2 | 1299 | m_pollRequestor = pSession; |
c42b4551 VK |
1300 | sendPollerMsg(dwRqId, _T("Starting status poll for node %s\r\n"), m_name); |
1301 | DbgPrintf(5, _T("Starting status poll for node %s (ID: %d)"), m_name, m_id); | |
5039dede AK |
1302 | |
1303 | // Read capability expiration time and current time | |
1304 | tExpire = (time_t)ConfigReadULong(_T("CapabilityExpirationTime"), 604800); | |
1305 | tNow = time(NULL); | |
1306 | ||
5039dede | 1307 | restart_agent_check: |
69a4eaa6 | 1308 | if (g_flags & AF_RESOLVE_IP_FOR_EACH_STATUS_POLL) |
385b1f20 | 1309 | { |
1310 | updatePrimaryIpAddr(); | |
1311 | } | |
1312 | ||
1313 | // Check SNMP agent connectivity | |
487cde95 | 1314 | if ((m_flags & NF_IS_SNMP) && (!(m_flags & NF_DISABLE_SNMP)) && m_ipAddress.isValidUnicast()) |
5039dede AK |
1315 | { |
1316 | TCHAR szBuffer[256]; | |
967893bb | 1317 | UINT32 dwResult; |
5039dede | 1318 | |
c42b4551 | 1319 | DbgPrintf(6, _T("StatusPoll(%s): check SNMP"), m_name); |
cd9f247e | 1320 | pTransport = createSnmpTransport(); |
61b359bc | 1321 | if (pTransport != NULL) |
5039dede | 1322 | { |
208d7427 | 1323 | poller->setStatus(_T("check SNMP")); |
61b359bc | 1324 | sendPollerMsg(dwRqId, _T("Checking SNMP agent connectivity\r\n")); |
9eeed592 VK |
1325 | const TCHAR *testOid = m_customAttributes.get(_T("snmp.testoid")); |
1326 | if (testOid == NULL) | |
1327 | { | |
1328 | testOid = _T(".1.3.6.1.2.1.1.2.0"); | |
1329 | } | |
1330 | dwResult = SnmpGet(m_snmpVersion, pTransport, testOid, NULL, 0, szBuffer, sizeof(szBuffer), 0); | |
61b359bc | 1331 | if ((dwResult == SNMP_ERR_SUCCESS) || (dwResult == SNMP_ERR_NO_OBJECT)) |
5039dede | 1332 | { |
61b359bc | 1333 | if (m_dwDynamicFlags & NDF_SNMP_UNREACHABLE) |
5039dede | 1334 | { |
5039dede | 1335 | m_dwDynamicFlags &= ~NDF_SNMP_UNREACHABLE; |
c42b4551 | 1336 | PostEventEx(pQueue, EVENT_SNMP_OK, m_id, NULL); |
61b359bc | 1337 | sendPollerMsg(dwRqId, POLLER_INFO _T("Connectivity with SNMP agent restored\r\n")); |
5039dede | 1338 | } |
aa379fa0 VK |
1339 | |
1340 | // Update authoritative engine data for SNMPv3 | |
1341 | if ((pTransport->getSnmpVersion() == SNMP_VERSION_3) && (pTransport->getAuthoritativeEngine() != NULL)) | |
1342 | { | |
1343 | lockProperties(); | |
1344 | m_snmpSecurity->setAuthoritativeEngine(*pTransport->getAuthoritativeEngine()); | |
1345 | unlockProperties(); | |
1346 | } | |
5039dede | 1347 | } |
23c1cb5d VK |
1348 | else if ((dwResult == SNMP_ERR_ENGINE_ID) && (m_snmpVersion == SNMP_VERSION_3)) |
1349 | { | |
1350 | // Reset authoritative engine data | |
1351 | lockProperties(); | |
1352 | m_snmpSecurity->setAuthoritativeEngine(SNMP_Engine()); | |
1353 | unlockProperties(); | |
1354 | goto restart_agent_check; | |
1355 | } | |
5039dede AK |
1356 | else |
1357 | { | |
61b359bc VK |
1358 | sendPollerMsg(dwRqId, POLLER_ERROR _T("SNMP agent unreachable\r\n")); |
1359 | if (m_dwDynamicFlags & NDF_SNMP_UNREACHABLE) | |
1360 | { | |
1361 | if ((tNow > m_failTimeSNMP + tExpire) && | |
1362 | (!(m_dwDynamicFlags & NDF_UNREACHABLE))) | |
1363 | { | |
487cde95 | 1364 | m_flags &= ~NF_IS_SNMP; |
61b359bc VK |
1365 | m_dwDynamicFlags &= ~NDF_SNMP_UNREACHABLE; |
1366 | m_szObjectId[0] = 0; | |
1367 | sendPollerMsg(dwRqId, POLLER_WARNING _T("Attribute isSNMP set to FALSE\r\n")); | |
1368 | } | |
1369 | } | |
1370 | else | |
1371 | { | |
1372 | m_dwDynamicFlags |= NDF_SNMP_UNREACHABLE; | |
c42b4551 | 1373 | PostEventEx(pQueue, EVENT_SNMP_FAIL, m_id, NULL); |
61b359bc VK |
1374 | m_failTimeSNMP = tNow; |
1375 | } | |
5039dede | 1376 | } |
61b359bc VK |
1377 | delete pTransport; |
1378 | } | |
1379 | else | |
1380 | { | |
c42b4551 | 1381 | DbgPrintf(6, _T("StatusPoll(%s): cannot create SNMP transport"), m_name); |
5039dede | 1382 | } |
c42b4551 | 1383 | DbgPrintf(6, _T("StatusPoll(%s): SNMP check finished"), m_name); |
5039dede AK |
1384 | } |
1385 | ||
1386 | // Check native agent connectivity | |
487cde95 | 1387 | if ((m_flags & NF_IS_NATIVE_AGENT) && (!(m_flags & NF_DISABLE_NXCP)) && m_ipAddress.isValidUnicast()) |
5039dede | 1388 | { |
c42b4551 | 1389 | DbgPrintf(6, _T("StatusPoll(%s): checking agent"), m_name); |
208d7427 | 1390 | poller->setStatus(_T("check agent")); |
21c9acce | 1391 | sendPollerMsg(dwRqId, _T("Checking NetXMS agent connectivity\r\n")); |
c3acd0f6 | 1392 | |
967893bb | 1393 | UINT32 error, socketError; |
a01c2a20 | 1394 | bool newConnection; |
a4569c4d | 1395 | agentLock(); |
a01c2a20 | 1396 | if (connectToAgent(&error, &socketError, &newConnection, true)) |
5039dede | 1397 | { |
c42b4551 | 1398 | DbgPrintf(7, _T("StatusPoll(%s): connected to agent"), m_name); |
5039dede AK |
1399 | if (m_dwDynamicFlags & NDF_AGENT_UNREACHABLE) |
1400 | { | |
1401 | m_dwDynamicFlags &= ~NDF_AGENT_UNREACHABLE; | |
c42b4551 | 1402 | PostEventEx(pQueue, EVENT_AGENT_OK, m_id, NULL); |
21c9acce | 1403 | sendPollerMsg(dwRqId, POLLER_INFO _T("Connectivity with NetXMS agent restored\r\n")); |
5039dede | 1404 | } |
5039dede AK |
1405 | } |
1406 | else | |
1407 | { | |
c42b4551 | 1408 | DbgPrintf(6, _T("StatusPoll(%s): agent unreachable, error=%d, socketError=%d"), m_name, (int)error, (int)socketError); |
21c9acce | 1409 | sendPollerMsg(dwRqId, POLLER_ERROR _T("NetXMS agent unreachable\r\n")); |
5039dede AK |
1410 | if (m_dwDynamicFlags & NDF_AGENT_UNREACHABLE) |
1411 | { | |
71e4ed3a | 1412 | if ((tNow > m_failTimeAgent + tExpire) && !(m_dwDynamicFlags & NDF_UNREACHABLE)) |
5039dede | 1413 | { |
487cde95 | 1414 | m_flags &= ~NF_IS_NATIVE_AGENT; |
5039dede AK |
1415 | m_dwDynamicFlags &= ~NDF_AGENT_UNREACHABLE; |
1416 | m_szPlatformName[0] = 0; | |
1417 | m_szAgentVersion[0] = 0; | |
21c9acce | 1418 | sendPollerMsg(dwRqId, POLLER_WARNING _T("Attribute isNetXMSAgent set to FALSE\r\n")); |
5039dede AK |
1419 | } |
1420 | } | |
1421 | else | |
1422 | { | |
1423 | m_dwDynamicFlags |= NDF_AGENT_UNREACHABLE; | |
c42b4551 | 1424 | PostEventEx(pQueue, EVENT_AGENT_FAIL, m_id, NULL); |
8573e935 | 1425 | m_failTimeAgent = tNow; |
0ab347c0 | 1426 | //cancel file monitoring locally(on agent it is canceled if agent have fallen) |
f9f79a93 | 1427 | g_monitoringList.removeDisconnectedNode(m_id); |
5039dede AK |
1428 | } |
1429 | } | |
a4569c4d | 1430 | agentUnlock(); |
c42b4551 | 1431 | DbgPrintf(7, _T("StatusPoll(%s): agent check finished"), m_name); |
f9f79a93 VK |
1432 | |
1433 | // If file update connection is active, send NOP command to prevent disconnection by idle timeout | |
1434 | AgentConnection *fileUpdateConnection; | |
1435 | lockProperties(); | |
1436 | fileUpdateConnection = m_fileUpdateConn; | |
1437 | if (fileUpdateConnection != NULL) | |
1438 | fileUpdateConnection->incRefCount(); | |
1439 | unlockProperties(); | |
1440 | if (fileUpdateConnection != NULL) | |
1441 | { | |
1442 | nxlog_debug(6, _T("StatusPoll(%s): sending keepalive command on file monitoring connection"), m_name); | |
1443 | fileUpdateConnection->nop(); | |
1444 | fileUpdateConnection->decRefCount(); | |
1445 | } | |
5039dede AK |
1446 | } |
1447 | ||
208d7427 | 1448 | poller->setStatus(_T("prepare polling list")); |
5039dede AK |
1449 | |
1450 | // Find service poller node object | |
c42b4551 | 1451 | lockProperties(); |
9208c84b | 1452 | if (m_pollerNode != 0) |
5039dede | 1453 | { |
9208c84b | 1454 | UINT32 id = m_pollerNode; |
c42b4551 | 1455 | unlockProperties(); |
f3218755 | 1456 | pPollerNode = FindObjectById(id); |
5039dede AK |
1457 | if (pPollerNode != NULL) |
1458 | { | |
c42b4551 | 1459 | if (pPollerNode->getObjectClass() != OBJECT_NODE) |
5039dede AK |
1460 | pPollerNode = NULL; |
1461 | } | |
1462 | } | |
f3218755 VK |
1463 | else |
1464 | { | |
c42b4551 | 1465 | unlockProperties(); |
f3218755 | 1466 | } |
5039dede AK |
1467 | |
1468 | // If nothing found, use management server | |
1469 | if (pPollerNode == NULL) | |
1470 | { | |
1471 | pPollerNode = FindObjectById(g_dwMgmtNode); | |
1472 | if (pPollerNode != NULL) | |
21c9acce | 1473 | pPollerNode->incRefCount(); |
5039dede AK |
1474 | } |
1475 | else | |
1476 | { | |
21c9acce | 1477 | pPollerNode->incRefCount(); |
5039dede AK |
1478 | } |
1479 | ||
1480 | // Create polling list | |
db091a1f VK |
1481 | ppPollList = (NetObj **)malloc(sizeof(NetObj *) * m_childList->size()); |
1482 | lockChildList(false); | |
274d9c7a VK |
1483 | int pollListSize = 0; |
1484 | for(int i = 0; i < m_childList->size(); i++) | |
db091a1f VK |
1485 | { |
1486 | NetObj *curr = m_childList->get(i); | |
1487 | if (curr->getStatus() != STATUS_UNMANAGED) | |
5039dede | 1488 | { |
db091a1f | 1489 | curr->incRefCount(); |
274d9c7a | 1490 | ppPollList[pollListSize++] = curr; |
5039dede | 1491 | } |
db091a1f VK |
1492 | } |
1493 | unlockChildList(); | |
5039dede AK |
1494 | |
1495 | // Poll interfaces and services | |
208d7427 | 1496 | poller->setStatus(_T("child poll")); |
c42b4551 | 1497 | DbgPrintf(7, _T("StatusPoll(%s): starting child object poll"), m_name); |
7c521895 | 1498 | pCluster = getMyCluster(); |
cd9f247e | 1499 | pTransport = createSnmpTransport(); |
274d9c7a | 1500 | for(int i = 0; i < pollListSize; i++) |
5039dede | 1501 | { |
c42b4551 | 1502 | switch(ppPollList[i]->getObjectClass()) |
5039dede AK |
1503 | { |
1504 | case OBJECT_INTERFACE: | |
c42b4551 | 1505 | DbgPrintf(7, _T("StatusPoll(%s): polling interface %d [%s]"), m_name, ppPollList[i]->getId(), ppPollList[i]->getName()); |
c30c0c0f | 1506 | ((Interface *)ppPollList[i])->statusPoll(pSession, dwRqId, pQueue, pCluster, pTransport, m_icmpProxy); |
5039dede AK |
1507 | break; |
1508 | case OBJECT_NETWORKSERVICE: | |
c42b4551 | 1509 | DbgPrintf(7, _T("StatusPoll(%s): polling network service %d [%s]"), m_name, ppPollList[i]->getId(), ppPollList[i]->getName()); |
0910fe05 | 1510 | ((NetworkService *)ppPollList[i])->statusPoll(pSession, dwRqId, (Node *)pPollerNode, pQueue); |
5039dede | 1511 | break; |
56d5289b | 1512 | case OBJECT_ACCESSPOINT: |
c42b4551 | 1513 | DbgPrintf(7, _T("StatusPoll(%s): polling access point %d [%s]"), m_name, ppPollList[i]->getId(), ppPollList[i]->getName()); |
ac58ffe9 | 1514 | ((AccessPoint *)ppPollList[i])->statusPoll(pSession, dwRqId, pQueue, this, pTransport); |
56d5289b | 1515 | break; |
5039dede | 1516 | default: |
c42b4551 | 1517 | DbgPrintf(7, _T("StatusPoll(%s): skipping object %d [%s] class %d"), m_name, ppPollList[i]->getId(), ppPollList[i]->getName(), ppPollList[i]->getObjectClass()); |
5039dede AK |
1518 | break; |
1519 | } | |
21c9acce | 1520 | ppPollList[i]->decRefCount(); |
5039dede AK |
1521 | } |
1522 | delete pTransport; | |
1523 | safe_free(ppPollList); | |
c42b4551 | 1524 | DbgPrintf(7, _T("StatusPoll(%s): finished child object poll"), m_name); |
5039dede AK |
1525 | |
1526 | // Check if entire node is down | |
15d6f8c9 | 1527 | // This check is disabled for nodes without IP address |
c75e9ee4 | 1528 | if (m_ipAddress.isValidUnicast()) |
5039dede | 1529 | { |
59176978 | 1530 | bool allDown = true; |
db091a1f | 1531 | lockChildList(false); |
274d9c7a | 1532 | for(int i = 0; i < m_childList->size(); i++) |
db091a1f VK |
1533 | { |
1534 | NetObj *curr = m_childList->get(i); | |
1535 | if ((curr->getObjectClass() == OBJECT_INTERFACE) && | |
1536 | (((Interface *)curr)->getAdminState() != IF_ADMIN_STATE_DOWN) && | |
1537 | (((Interface *)curr)->getConfirmedOperState() == IF_OPER_STATE_UP) && | |
1538 | (curr->getStatus() != STATUS_UNMANAGED)) | |
1539 | { | |
1540 | allDown = false; | |
1541 | break; | |
1542 | } | |
1543 | } | |
1544 | unlockChildList(); | |
487cde95 VK |
1545 | if (allDown && (m_flags & NF_IS_NATIVE_AGENT) && |
1546 | (!(m_flags & NF_DISABLE_NXCP))) | |
15d6f8c9 | 1547 | if (!(m_dwDynamicFlags & NDF_AGENT_UNREACHABLE)) |
59176978 | 1548 | allDown = false; |
487cde95 VK |
1549 | if (allDown && (m_flags & NF_IS_SNMP) && |
1550 | (!(m_flags & NF_DISABLE_SNMP))) | |
15d6f8c9 | 1551 | if (!(m_dwDynamicFlags & NDF_SNMP_UNREACHABLE)) |
59176978 | 1552 | allDown = false; |
c1482463 | 1553 | |
59176978 VK |
1554 | DbgPrintf(6, _T("StatusPoll(%s): allDown=%s, dynFlags=0x%08X"), m_name, allDown ? _T("true") : _T("false"), m_dwDynamicFlags); |
1555 | if (allDown) | |
15d6f8c9 VK |
1556 | { |
1557 | if (!(m_dwDynamicFlags & NDF_UNREACHABLE)) | |
1558 | { | |
1559 | m_dwDynamicFlags |= NDF_UNREACHABLE; | |
8573e935 | 1560 | m_downSince = time(NULL); |
208d7427 | 1561 | poller->setStatus(_T("check network path")); |
c1482463 VK |
1562 | if (checkNetworkPath(dwRqId)) |
1563 | { | |
1564 | m_dwDynamicFlags |= NDF_NETWORK_PATH_PROBLEM; | |
1565 | ||
1566 | // Set interfaces and network services to UNKNOWN state | |
db091a1f | 1567 | lockChildList(false); |
274d9c7a | 1568 | for(int i = 0; i < m_childList->size(); i++) |
db091a1f VK |
1569 | { |
1570 | NetObj *curr = m_childList->get(i); | |
1571 | if (((curr->getObjectClass() == OBJECT_INTERFACE) || (curr->getObjectClass() == OBJECT_NETWORKSERVICE)) && | |
1572 | (curr->getStatus() == STATUS_CRITICAL)) | |
c1482463 | 1573 | { |
db091a1f | 1574 | curr->resetStatus(); |
c1482463 | 1575 | } |
db091a1f VK |
1576 | } |
1577 | unlockChildList(); | |
c1482463 VK |
1578 | |
1579 | // Clear delayed event queue | |
1580 | while(1) | |
1581 | { | |
19dbc8ef | 1582 | Event *pEvent = (Event *)pQueue->get(); |
c1482463 VK |
1583 | if (pEvent == NULL) |
1584 | break; | |
1585 | delete pEvent; | |
1586 | } | |
1587 | delete_and_null(pQueue); | |
1588 | ||
c42b4551 | 1589 | PostEvent(EVENT_NODE_UNREACHABLE, m_id, NULL); |
c1482463 VK |
1590 | } |
1591 | else | |
1592 | { | |
c42b4551 | 1593 | PostEvent(EVENT_NODE_DOWN, m_id, NULL); |
c1482463 | 1594 | } |
21c9acce | 1595 | sendPollerMsg(dwRqId, POLLER_ERROR _T("Node is unreachable\r\n")); |
15d6f8c9 VK |
1596 | } |
1597 | else | |
1598 | { | |
21c9acce | 1599 | sendPollerMsg(dwRqId, POLLER_WARNING _T("Node is still unreachable\r\n")); |
15d6f8c9 VK |
1600 | } |
1601 | } | |
1602 | else | |
1603 | { | |
8573e935 | 1604 | m_downSince = 0; |
15d6f8c9 VK |
1605 | if (m_dwDynamicFlags & NDF_UNREACHABLE) |
1606 | { | |
a26861ad | 1607 | int reason = (m_dwDynamicFlags & NDF_NETWORK_PATH_PROBLEM) ? 1 : 0; |
c1482463 | 1608 | m_dwDynamicFlags &= ~(NDF_UNREACHABLE | NDF_SNMP_UNREACHABLE | NDF_AGENT_UNREACHABLE | NDF_NETWORK_PATH_PROBLEM); |
c42b4551 | 1609 | PostEvent(EVENT_NODE_UP, m_id, "d", reason); |
21c9acce | 1610 | sendPollerMsg(dwRqId, POLLER_INFO _T("Node recovered from unreachable state\r\n")); |
15d6f8c9 VK |
1611 | goto restart_agent_check; |
1612 | } | |
1613 | else | |
1614 | { | |
21c9acce | 1615 | sendPollerMsg(dwRqId, POLLER_INFO _T("Node is connected\r\n")); |
15d6f8c9 VK |
1616 | } |
1617 | } | |
5039dede | 1618 | } |
5039dede | 1619 | |
71e4ed3a VK |
1620 | // Get uptime and update boot time |
1621 | if (!(m_dwDynamicFlags & NDF_UNREACHABLE)) | |
1622 | { | |
1623 | TCHAR buffer[MAX_RESULT_LENGTH]; | |
1624 | if (getItemFromAgent(_T("System.Uptime"), MAX_RESULT_LENGTH, buffer) == DCE_SUCCESS) | |
1625 | { | |
1626 | m_bootTime = time(NULL) - _tcstol(buffer, NULL, 0); | |
c42b4551 | 1627 | DbgPrintf(5, _T("StatusPoll(%s [%d]): boot time set to %u from agent"), m_name, m_id, (UINT32)m_bootTime); |
71e4ed3a | 1628 | } |
296ae03d | 1629 | else if (getItemFromSNMP(m_snmpPort, _T(".1.3.6.1.2.1.1.3.0"), MAX_RESULT_LENGTH, buffer, SNMP_RAWTYPE_NONE) == DCE_SUCCESS) |
71e4ed3a VK |
1630 | { |
1631 | m_bootTime = time(NULL) - _tcstol(buffer, NULL, 0) / 100; // sysUpTime is in hundredths of a second | |
c42b4551 | 1632 | DbgPrintf(5, _T("StatusPoll(%s [%d]): boot time set to %u from SNMP"), m_name, m_id, (UINT32)m_bootTime); |
71e4ed3a VK |
1633 | } |
1634 | else | |
1635 | { | |
c42b4551 | 1636 | DbgPrintf(5, _T("StatusPoll(%s [%d]): unable to get system uptime"), m_name, m_id); |
71e4ed3a VK |
1637 | } |
1638 | } | |
1639 | else | |
1640 | { | |
1641 | m_bootTime = 0; | |
1642 | } | |
1643 | ||
0ab347c0 | 1644 | // Get agent uptime to check if it was restared |
1645 | if (!(m_dwDynamicFlags & NDF_UNREACHABLE)) | |
1646 | { | |
1647 | TCHAR buffer[MAX_RESULT_LENGTH]; | |
1648 | if (getItemFromAgent(_T("Agent.Uptime"), MAX_RESULT_LENGTH, buffer) == DCE_SUCCESS) | |
1649 | { | |
1650 | time_t oldAgentuptime = m_agentUpTime; | |
1651 | m_agentUpTime = _tcstol(buffer, NULL, 0); | |
2e22746d | 1652 | if ((UINT32)oldAgentuptime > (UINT32)m_agentUpTime) |
0ab347c0 | 1653 | { |
1654 | //cancel file monitoring locally(on agent it is canceled if agent have fallen) | |
f9f79a93 | 1655 | g_monitoringList.removeDisconnectedNode(m_id); |
0ab347c0 | 1656 | } |
1657 | } | |
1658 | else | |
1659 | { | |
c42b4551 | 1660 | DbgPrintf(5, _T("StatusPoll(%s [%d]): unable to get agent uptime"), m_name, m_id); |
f9f79a93 | 1661 | g_monitoringList.removeDisconnectedNode(m_id); |
0ab347c0 | 1662 | m_agentUpTime = 0; |
1663 | } | |
1664 | } | |
1665 | else | |
1666 | { | |
f9f79a93 | 1667 | g_monitoringList.removeDisconnectedNode(m_id); |
0ab347c0 | 1668 | m_agentUpTime = 0; |
1669 | } | |
1670 | ||
2e22746d VK |
1671 | // Get geolocation |
1672 | if (!(m_dwDynamicFlags & NDF_UNREACHABLE)) | |
1673 | { | |
1674 | TCHAR buffer[MAX_RESULT_LENGTH]; | |
1675 | if (getItemFromAgent(_T("GPS.LocationData"), MAX_RESULT_LENGTH, buffer) == DCE_SUCCESS) | |
1676 | { | |
1677 | GeoLocation loc = GeoLocation::parseAgentData(buffer); | |
1678 | if (loc.getType() != GL_UNSET) | |
1679 | { | |
1680 | DbgPrintf(5, _T("StatusPoll(%s [%d]): location set to %s, %s from agent"), m_name, m_id, loc.getLatitudeAsString(), loc.getLongitudeAsString()); | |
1681 | lockProperties(); | |
1682 | m_geoLocation = loc; | |
1683 | setModified(); | |
1684 | unlockProperties(); | |
1685 | } | |
1686 | } | |
1687 | else | |
1688 | { | |
1689 | DbgPrintf(5, _T("StatusPoll(%s [%d]): unable to get system location"), m_name, m_id); | |
1690 | } | |
1691 | } | |
1692 | ||
849e464d | 1693 | // Get agent log and agent local database status |
b123ecb3 | 1694 | if (!(m_dwDynamicFlags & NDF_UNREACHABLE)) |
1695 | { | |
1696 | TCHAR buffer[MAX_RESULT_LENGTH]; | |
7b30e5ae | 1697 | if (getItemFromAgent(_T("Agent.LogFile.Status"), MAX_RESULT_LENGTH, buffer) == DCE_SUCCESS) |
b123ecb3 | 1698 | { |
1699 | UINT32 status = _tcstol(buffer, NULL, 0); | |
7b30e5ae VK |
1700 | if (status != 0) |
1701 | PostEvent(EVENT_AGENT_LOG_PROBLEM, m_id, "ds", status, _T("could not open")); | |
b123ecb3 | 1702 | } |
1703 | else | |
1704 | { | |
7b30e5ae | 1705 | nxlog_debug(5, _T("StatusPoll(%s [%d]): unable to get agent log status"), m_name, m_id); |
b123ecb3 | 1706 | } |
1707 | ||
7b30e5ae | 1708 | if (getItemFromAgent(_T("Agent.LocalDatabase.Status"), MAX_RESULT_LENGTH, buffer) == DCE_SUCCESS) |
b123ecb3 | 1709 | { |
1710 | UINT32 status = _tcstol(buffer, NULL, 0); | |
1711 | const TCHAR *statusDescription[3]= { | |
1712 | _T("normal"), | |
1713 | _T("could not open database"), | |
1714 | _T("could not update database"), | |
1715 | }; | |
7b30e5ae VK |
1716 | if (status != 0) |
1717 | PostEvent(EVENT_AGENT_LOCAL_DATABASE_PROBLEM, m_id, "ds", status, statusDescription[status]); | |
b123ecb3 | 1718 | } |
1719 | else | |
1720 | { | |
7b30e5ae | 1721 | nxlog_debug(5, _T("StatusPoll(%s [%d]): unable to get agent local database status"), m_name, m_id); |
b123ecb3 | 1722 | } |
1723 | } | |
1724 | ||
5039dede | 1725 | // Send delayed events and destroy delayed event queue |
c1482463 VK |
1726 | if (pQueue != NULL) |
1727 | { | |
1728 | ResendEvents(pQueue); | |
1729 | delete pQueue; | |
1730 | } | |
a5ee7b3b VK |
1731 | |
1732 | // Call hooks in loaded modules | |
967893bb | 1733 | for(UINT32 i = 0; i < g_dwNumModules; i++) |
a5ee7b3b VK |
1734 | { |
1735 | if (g_pModuleList[i].pfStatusPollHook != NULL) | |
1736 | { | |
c42b4551 | 1737 | DbgPrintf(5, _T("StatusPoll(%s [%d]): calling hook in module %s"), m_name, m_id, g_pModuleList[i].szName); |
208d7427 | 1738 | g_pModuleList[i].pfStatusPollHook(this, pSession, dwRqId, poller); |
a5ee7b3b VK |
1739 | } |
1740 | } | |
4d2c3a54 | 1741 | |
a5ee7b3b | 1742 | // Execute hook script |
208d7427 | 1743 | poller->setStatus(_T("hook")); |
a5ee7b3b VK |
1744 | executeHookScript(_T("StatusPoll")); |
1745 | ||
208d7427 | 1746 | poller->setStatus(_T("cleanup")); |
5039dede | 1747 | if (pPollerNode != NULL) |
21c9acce | 1748 | pPollerNode->decRefCount(); |
5039dede | 1749 | |
487cde95 | 1750 | if (dwOldFlags != m_flags) |
5039dede | 1751 | { |
487cde95 | 1752 | PostEvent(EVENT_NODE_FLAGS_CHANGED, m_id, "xx", dwOldFlags, m_flags); |
c42b4551 VK |
1753 | lockProperties(); |
1754 | setModified(); | |
1755 | unlockProperties(); | |
5039dede AK |
1756 | } |
1757 | ||
27f9598d | 1758 | calculateCompoundStatus(); |
8573e935 | 1759 | m_lastStatusPoll = time(NULL); |
c42b4551 | 1760 | sendPollerMsg(dwRqId, _T("Finished status poll for node %s\r\n"), m_name); |
db091a1f | 1761 | sendPollerMsg(dwRqId, _T("Node status after poll is %s\r\n"), GetStatusAsText(m_status, true)); |
c59466d2 | 1762 | m_pollRequestor = NULL; |
5039dede AK |
1763 | if (dwRqId == 0) |
1764 | m_dwDynamicFlags &= ~NDF_QUEUED_FOR_STATUS_POLL; | |
7c521895 | 1765 | pollerUnlock(); |
c42b4551 | 1766 | DbgPrintf(5, _T("Finished status poll for node %s (ID: %d)"), m_name, m_id); |
5039dede AK |
1767 | } |
1768 | ||
beae365a | 1769 | /** |
1babf64d | 1770 | * Check single element of network path |
beae365a | 1771 | */ |
967893bb | 1772 | bool Node::checkNetworkPathElement(UINT32 nodeId, const TCHAR *nodeType, bool isProxy, UINT32 dwRqId) |
beae365a VK |
1773 | { |
1774 | Node *node = (Node *)FindObjectById(nodeId, OBJECT_NODE); | |
1775 | if (node == NULL) | |
1776 | return false; | |
1777 | ||
c42b4551 | 1778 | DbgPrintf(6, _T("Node::checkNetworkPathElement(%s [%d]): found %s: %s [%d]"), m_name, m_id, nodeType, node->getName(), node->getId()); |
beae365a VK |
1779 | if (node->isDown()) |
1780 | { | |
1781 | DbgPrintf(5, _T("Node::checkNetworkPathElement(%s [%d]): %s %s [%d] is down"), | |
c42b4551 VK |
1782 | m_name, m_id, nodeType, node->getName(), node->getId()); |
1783 | sendPollerMsg(dwRqId, POLLER_WARNING _T(" %s %s is down\r\n"), nodeType, node->getName()); | |
beae365a VK |
1784 | return true; |
1785 | } | |
66d15dff VK |
1786 | if (isProxy && node->isNativeAgent() && (node->getRuntimeFlags() & NDF_AGENT_UNREACHABLE)) |
1787 | { | |
1788 | DbgPrintf(5, _T("Node::checkNetworkPathElement(%s [%d]): agent on %s %s [%d] is down"), | |
c42b4551 VK |
1789 | m_name, m_id, nodeType, node->getName(), node->getId()); |
1790 | sendPollerMsg(dwRqId, POLLER_WARNING _T(" Agent on %s %s is down\r\n"), nodeType, node->getName()); | |
66d15dff VK |
1791 | return true; |
1792 | } | |
8573e935 | 1793 | if (node->m_lastStatusPoll < time(NULL) - 1) |
beae365a VK |
1794 | { |
1795 | DbgPrintf(6, _T("Node::checkNetworkPathElement(%s [%d]): forced status poll on node %s [%d]"), | |
c42b4551 | 1796 | m_name, m_id, node->getName(), node->getId()); |
208d7427 VK |
1797 | PollerInfo *poller = RegisterPoller(POLLER_TYPE_STATUS, node); |
1798 | poller->startExecution(); | |
1799 | node->statusPoll(NULL, 0, poller); | |
1800 | delete poller; | |
beae365a VK |
1801 | if (node->isDown()) |
1802 | { | |
1803 | DbgPrintf(5, _T("Node::checkNetworkPathElement(%s [%d]): %s %s [%d] is down"), | |
c42b4551 VK |
1804 | m_name, m_id, nodeType, node->getName(), node->getId()); |
1805 | sendPollerMsg(dwRqId, POLLER_WARNING _T(" %s %s is down\r\n"), nodeType, node->getName()); | |
beae365a VK |
1806 | return true; |
1807 | } | |
66d15dff VK |
1808 | if (isProxy && node->isNativeAgent() && (node->getRuntimeFlags() & NDF_AGENT_UNREACHABLE)) |
1809 | { | |
1810 | DbgPrintf(5, _T("Node::checkNetworkPathElement(%s [%d]): agent on %s %s [%d] is down"), | |
c42b4551 VK |
1811 | m_name, m_id, nodeType, node->getName(), node->getId()); |
1812 | sendPollerMsg(dwRqId, POLLER_WARNING _T(" Agent on %s %s is down\r\n"), nodeType, node->getName()); | |
66d15dff VK |
1813 | return true; |
1814 | } | |
beae365a VK |
1815 | } |
1816 | return false; | |
1817 | } | |
1818 | ||
7946bd7c VK |
1819 | /** |
1820 | * Check network path between node and management server to detect possible intermediate node failure | |
c1482463 VK |
1821 | * |
1822 | * @return true if network path problems found | |
7946bd7c | 1823 | */ |
967893bb | 1824 | bool Node::checkNetworkPath(UINT32 dwRqId) |
7946bd7c | 1825 | { |
67c45b4d VK |
1826 | time_t now = time(NULL); |
1827 | ||
beae365a VK |
1828 | // Check proxy node(s) |
1829 | if (IsZoningEnabled() && (m_zoneId != 0)) | |
1830 | { | |
1831 | Zone *zone = (Zone *)g_idxZoneByGUID.get(m_zoneId); | |
1832 | if ((zone != NULL) && ((zone->getAgentProxy() != 0) || (zone->getSnmpProxy() != 0) || (zone->getIcmpProxy() != 0))) | |
1833 | { | |
1834 | bool allProxyDown = true; | |
1835 | if (zone->getIcmpProxy() != 0) | |
66d15dff | 1836 | allProxyDown = checkNetworkPathElement(zone->getIcmpProxy(), _T("ICMP proxy"), true, dwRqId); |
beae365a | 1837 | if (allProxyDown && (zone->getSnmpProxy() != 0) && (zone->getSnmpProxy() != zone->getIcmpProxy())) |
66d15dff | 1838 | allProxyDown = checkNetworkPathElement(zone->getSnmpProxy(), _T("SNMP proxy"), true, dwRqId); |
beae365a | 1839 | if (allProxyDown && (zone->getAgentProxy() != 0) && (zone->getAgentProxy() != zone->getIcmpProxy()) && (zone->getAgentProxy() != zone->getSnmpProxy())) |
66d15dff | 1840 | allProxyDown = checkNetworkPathElement(zone->getAgentProxy(), _T("agent proxy"), true, dwRqId); |
beae365a VK |
1841 | if (allProxyDown) |
1842 | return true; | |
1843 | } | |
1844 | } | |
1845 | ||
67c45b4d VK |
1846 | // Check directly connected switch |
1847 | sendPollerMsg(dwRqId, _T("Checking ethernet connectivity...\r\n")); | |
c75e9ee4 | 1848 | Interface *iface = findInterfaceByIP(m_ipAddress); |
664b42a4 | 1849 | if ((iface != NULL) && (iface->getPeerNodeId() != 0)) |
67c45b4d | 1850 | { |
c42b4551 | 1851 | DbgPrintf(6, _T("Node::checkNetworkPath(%s [%d]): found interface object for primary IP: %s [%d]"), m_name, m_id, iface->getName(), iface->getId()); |
66d15dff | 1852 | if (checkNetworkPathElement(iface->getPeerNodeId(), _T("upstream switch"), false, dwRqId)) |
beae365a | 1853 | return true; |
67c45b4d | 1854 | } |
664b42a4 VK |
1855 | else |
1856 | { | |
c42b4551 | 1857 | DbgPrintf(5, _T("Node::checkNetworkPath(%s [%d]): cannot find interface object for primary IP"), m_name, m_id); |
664b42a4 | 1858 | } |
67c45b4d | 1859 | |
7946bd7c VK |
1860 | Node *mgmtNode = (Node *)FindObjectById(g_dwMgmtNode); |
1861 | if (mgmtNode == NULL) | |
1862 | { | |
c42b4551 | 1863 | DbgPrintf(5, _T("Node::checkNetworkPath(%s [%d]): cannot find management node"), m_name, m_id); |
c1482463 | 1864 | return false; |
7946bd7c | 1865 | } |
5039dede | 1866 | |
7946bd7c VK |
1867 | NetworkPath *trace = TraceRoute(mgmtNode, this); |
1868 | if (trace == NULL) | |
1869 | { | |
c42b4551 | 1870 | DbgPrintf(5, _T("Node::checkNetworkPath(%s [%d]): trace not available"), m_name, m_id); |
c1482463 | 1871 | return false; |
7946bd7c VK |
1872 | } |
1873 | DbgPrintf(5, _T("Node::checkNetworkPath(%s [%d]): trace available, %d hops, %s"), | |
c42b4551 | 1874 | m_name, m_id, trace->getHopCount(), trace->isComplete() ? _T("complete") : _T("incomplete")); |
7946bd7c VK |
1875 | |
1876 | // We will do path check in two passes | |
1877 | // If unreachable intermediate node will be found on first pass, | |
1878 | // then method will just return true. Otherwise, we will do | |
1879 | // second pass, this time forcing status poll on each node in the path. | |
21c9acce | 1880 | sendPollerMsg(dwRqId, _T("Checking network path...\r\n")); |
7946bd7c VK |
1881 | bool secondPass = false; |
1882 | bool pathProblemFound = false; | |
1883 | restart: | |
1884 | for(int i = 0; i < trace->getHopCount(); i++) | |
1885 | { | |
1886 | HOP_INFO *hop = trace->getHopInfo(i); | |
c42b4551 | 1887 | if ((hop->object == NULL) || (hop->object == this) || (hop->object->getObjectClass() != OBJECT_NODE)) |
7946bd7c VK |
1888 | continue; |
1889 | ||
1890 | DbgPrintf(6, _T("Node::checkNetworkPath(%s [%d]): checking upstream node %s [%d]"), | |
c42b4551 | 1891 | m_name, m_id, hop->object->getName(), hop->object->getId()); |
8573e935 | 1892 | if (secondPass && !((Node *)hop->object)->isDown() && (((Node *)hop->object)->m_lastStatusPoll < now - 1)) |
7946bd7c VK |
1893 | { |
1894 | DbgPrintf(6, _T("Node::checkNetworkPath(%s [%d]): forced status poll on node %s [%d]"), | |
c42b4551 | 1895 | m_name, m_id, hop->object->getName(), hop->object->getId()); |
208d7427 VK |
1896 | PollerInfo *poller = RegisterPoller(POLLER_TYPE_STATUS, (Node *)hop->object); |
1897 | poller->startExecution(); | |
1898 | ((Node *)hop->object)->statusPoll(NULL, 0, poller); | |
1899 | delete poller; | |
7946bd7c | 1900 | } |
1f385e47 | 1901 | |
7946bd7c VK |
1902 | if (((Node *)hop->object)->isDown()) |
1903 | { | |
1904 | DbgPrintf(5, _T("Node::checkNetworkPath(%s [%d]): upstream node %s [%d] is down"), | |
c42b4551 VK |
1905 | m_name, m_id, hop->object->getName(), hop->object->getId()); |
1906 | sendPollerMsg(dwRqId, POLLER_WARNING _T(" Upstream node %s is down\r\n"), hop->object->getName()); | |
7946bd7c VK |
1907 | pathProblemFound = true; |
1908 | break; | |
1909 | } | |
1910 | } | |
1911 | if (!secondPass && !pathProblemFound) | |
1912 | { | |
c42b4551 | 1913 | DbgPrintf(5, _T("Node::checkNetworkPath(%s [%d]): will do second pass"), m_name, m_id); |
7946bd7c VK |
1914 | secondPass = true; |
1915 | goto restart; | |
1916 | } | |
1917 | delete trace; | |
c1482463 | 1918 | return pathProblemFound; |
7946bd7c VK |
1919 | } |
1920 | ||
1921 | /** | |
1922 | * Check agent policy binding | |
1923 | * Intended to be called only from configuration poller | |
1924 | */ | |
1f385e47 VK |
1925 | void Node::checkAgentPolicyBinding(AgentConnection *conn) |
1926 | { | |
1927 | AgentPolicyInfo *ap; | |
967893bb | 1928 | UINT32 rcc = conn->getPolicyInventory(&ap); |
1f385e47 VK |
1929 | if (rcc == ERR_SUCCESS) |
1930 | { | |
1931 | // Check for unbound but installed policies | |
a6312bd6 | 1932 | for(int i = 0; i < ap->size(); i++) |
1f385e47 | 1933 | { |
de4af576 | 1934 | uuid guid = ap->getGuid(i); |
1f385e47 | 1935 | NetObj *object = FindObjectByGUID(guid, -1); |
c42b4551 | 1936 | if ((object != NULL) && (!object->isChild(m_id))) |
1f385e47 | 1937 | { |
1f8be1f4 VK |
1938 | object->addChild(this); |
1939 | addParent(object); | |
c42b4551 | 1940 | DbgPrintf(5, _T("ConfPoll(%s): bound to policy object %s [%d]"), m_name, object->getName(), object->getId()); |
1f385e47 VK |
1941 | } |
1942 | } | |
1943 | ||
28e59088 TD |
1944 | // Check for bound but not installed policies and schedule it's installation again |
1945 | //Job will be unbound if it was not possible to add job | |
db091a1f VK |
1946 | lockParentList(false); |
1947 | NetObj **unbindList = (NetObj **)malloc(sizeof(NetObj *) * m_parentList->size()); | |
28e59088 | 1948 | int unbindListSize = 0; |
db091a1f | 1949 | for(int i = 0; i < m_parentList->size(); i++) |
1f385e47 | 1950 | { |
db091a1f | 1951 | if (IsAgentPolicyObject(m_parentList->get(i))) |
1f385e47 | 1952 | { |
db091a1f | 1953 | const uuid& guid = m_parentList->get(i)->getGuid(); |
de4af576 | 1954 | int j; |
a6312bd6 | 1955 | for(j = 0; j < ap->size(); j++) |
1f385e47 | 1956 | { |
4e5e861c | 1957 | if (ap->getGuid(j).equals(guid)) |
1f385e47 VK |
1958 | break; |
1959 | } | |
a6312bd6 | 1960 | if (j == ap->size()) |
28e59088 | 1961 | { |
db091a1f | 1962 | ServerJob *job = new PolicyDeploymentJob(this, (AgentPolicy *)m_parentList->get(i), 0); //TODO: change to system user |
28e59088 TD |
1963 | if (AddJob(job)) |
1964 | { | |
db091a1f | 1965 | DbgPrintf(5, _T("ConfPoll(%s): \"%s\" policy deploy scheduled for \"%s\" node"), m_name, m_parentList->get(i)->getName(), m_name ); |
28e59088 TD |
1966 | } |
1967 | else | |
1968 | { | |
db091a1f | 1969 | 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); |
28e59088 | 1970 | delete job; |
db091a1f | 1971 | unbindList[unbindListSize++] = m_parentList->get(i); |
28e59088 TD |
1972 | } |
1973 | } | |
1f385e47 VK |
1974 | } |
1975 | } | |
db091a1f | 1976 | unlockParentList(); |
1f385e47 VK |
1977 | |
1978 | for(int i = 0; i < unbindListSize; i++) | |
1979 | { | |
1f8be1f4 VK |
1980 | unbindList[i]->deleteChild(this); |
1981 | deleteParent(unbindList[i]); | |
c42b4551 | 1982 | DbgPrintf(5, _T("ConfPoll(%s): unbound from policy object %s [%d]"), m_name, unbindList[i]->getName(), unbindList[i]->getId()); |
1f385e47 VK |
1983 | } |
1984 | safe_free(unbindList); | |
1985 | ||
1986 | delete ap; | |
1987 | } | |
1988 | else | |
1989 | { | |
c42b4551 | 1990 | DbgPrintf(5, _T("ConfPoll(%s): AgentConnection::getPolicyInventory() failed: rcc=%d"), m_name, rcc); |
1f385e47 VK |
1991 | } |
1992 | } | |
1993 | ||
a3050773 VK |
1994 | /** |
1995 | * Update primary IP address from primary name | |
1996 | */ | |
5a7d6a10 VK |
1997 | void Node::updatePrimaryIpAddr() |
1998 | { | |
1999 | if (m_primaryName[0] == 0) | |
2000 | return; | |
2001 | ||
b4cf3199 | 2002 | InetAddress ipAddr = ResolveHostName(m_zoneId, m_primaryName); |
c75e9ee4 | 2003 | if (!ipAddr.equals(m_ipAddress) && (ipAddr.isValidUnicast() || !_tcscmp(m_primaryName, _T("0.0.0.0")))) |
5a7d6a10 | 2004 | { |
c75e9ee4 | 2005 | TCHAR buffer1[64], buffer2[64]; |
5a7d6a10 | 2006 | |
4d2c3a54 | 2007 | DbgPrintf(4, _T("IP address for node %s [%d] changed from %s to %s"), |
c75e9ee4 VK |
2008 | m_name, (int)m_id, m_ipAddress.toString(buffer1), ipAddr.toString(buffer2)); |
2009 | PostEvent(EVENT_IP_ADDRESS_CHANGED, m_id, "AA", &ipAddr, &m_ipAddress); | |
2467ed57 | 2010 | |
487cde95 | 2011 | if (m_flags & NF_REMOTE_AGENT) |
dbe28185 | 2012 | { |
c42b4551 | 2013 | lockProperties(); |
c75e9ee4 | 2014 | m_ipAddress = ipAddr; |
c42b4551 VK |
2015 | setModified(); |
2016 | unlockProperties(); | |
dbe28185 VK |
2017 | } |
2018 | else | |
2019 | { | |
2020 | setPrimaryIPAddress(ipAddr); | |
2021 | } | |
a3050773 VK |
2022 | |
2023 | agentLock(); | |
a416f8f6 | 2024 | deleteAgentConnection(); |
a3050773 | 2025 | agentUnlock(); |
5a7d6a10 VK |
2026 | } |
2027 | } | |
2028 | ||
208d7427 VK |
2029 | /** |
2030 | * Entry point for configuration poller | |
2031 | */ | |
2032 | void Node::configurationPoll(PollerInfo *poller) | |
2033 | { | |
2034 | poller->startExecution(); | |
2035 | ObjectTransactionStart(); | |
2036 | configurationPoll(NULL, 0, poller, 0); | |
2037 | ObjectTransactionEnd(); | |
2038 | delete poller; | |
2039 | } | |
2040 | ||
76720a09 VK |
2041 | /** |
2042 | * Perform configuration poll on node | |
2043 | */ | |
208d7427 | 2044 | void Node::configurationPoll(ClientSession *pSession, UINT32 dwRqId, PollerInfo *poller, int maskBits) |
5039dede | 2045 | { |
46117060 VK |
2046 | if (m_dwDynamicFlags & NDF_DELETE_IN_PROGRESS) |
2047 | { | |
2048 | if (dwRqId == 0) | |
2049 | m_dwDynamicFlags &= ~NDF_QUEUED_FOR_CONFIG_POLL; | |
2050 | return; | |
2051 | } | |
2052 | ||
88dc9091 | 2053 | if (IsShutdownInProgress()) |
9fc9ec2c VK |
2054 | return; |
2055 | ||
487cde95 | 2056 | UINT32 dwOldFlags = m_flags; |
35f836fe | 2057 | TCHAR szBuffer[4096]; |
76720a09 | 2058 | bool hasChanges = false; |
5039dede | 2059 | |
208d7427 | 2060 | poller->setStatus(_T("wait for lock")); |
7c521895 | 2061 | pollerLock(); |
88dc9091 VK |
2062 | |
2063 | if (IsShutdownInProgress()) | |
2064 | { | |
2065 | pollerUnlock(); | |
2066 | return; | |
2067 | } | |
2068 | ||
c59466d2 | 2069 | m_pollRequestor = pSession; |
c42b4551 VK |
2070 | sendPollerMsg(dwRqId, _T("Starting configuration poll for node %s\r\n"), m_name); |
2071 | DbgPrintf(4, _T("Starting configuration poll for node %s (ID: %d)"), m_name, m_id); | |
5039dede AK |
2072 | |
2073 | // Check for forced capabilities recheck | |
2074 | if (m_dwDynamicFlags & NDF_RECHECK_CAPABILITIES) | |
2075 | { | |
f7e3eb5a | 2076 | sendPollerMsg(dwRqId, POLLER_WARNING _T("Capability reset\r\n")); |
487cde95 | 2077 | m_flags &= ~(NF_IS_NATIVE_AGENT | NF_IS_SNMP | NF_IS_CPSNMP | |
0ecc2200 | 2078 | NF_IS_BRIDGE | NF_IS_ROUTER | NF_IS_OSPF | NF_IS_PRINTER | |
76720a09 | 2079 | NF_IS_CDP | NF_IS_LLDP | NF_IS_SONMP | NF_IS_VRRP | NF_HAS_VLANS | |
46ee6286 VK |
2080 | NF_IS_8021X | NF_IS_STP | NF_HAS_ENTITY_MIB | NF_HAS_IFXTABLE | |
2081 | NF_HAS_WINPDH); | |
e4a64da2 | 2082 | m_dwDynamicFlags &= ~NDF_CONFIGURATION_POLL_PASSED; |
5039dede AK |
2083 | m_szObjectId[0] = 0; |
2084 | m_szPlatformName[0] = 0; | |
2085 | m_szAgentVersion[0] = 0; | |
0ecc2200 VK |
2086 | safe_free_and_null(m_sysDescription); |
2087 | safe_free_and_null(m_sysName); | |
cf38357f VK |
2088 | safe_free_and_null(m_sysContact); |
2089 | safe_free_and_null(m_sysLocation); | |
0ecc2200 | 2090 | safe_free_and_null(m_lldpNodeId); |
5039dede AK |
2091 | } |
2092 | ||
2093 | // Check if node is marked as unreachable | |
2094 | if ((m_dwDynamicFlags & NDF_UNREACHABLE) && !(m_dwDynamicFlags & NDF_RECHECK_CAPABILITIES)) | |
2095 | { | |
21c9acce | 2096 | sendPollerMsg(dwRqId, POLLER_WARNING _T("Node is marked as unreachable, configuration poll aborted\r\n")); |
35f836fe | 2097 | DbgPrintf(4, _T("Node is marked as unreachable, configuration poll aborted")); |
8573e935 | 2098 | m_lastConfigurationPoll = time(NULL); |
5039dede AK |
2099 | } |
2100 | else | |
2101 | { | |
5a7d6a10 VK |
2102 | updatePrimaryIpAddr(); |
2103 | ||
208d7427 | 2104 | poller->setStatus(_T("capability check")); |
21c9acce | 2105 | sendPollerMsg(dwRqId, _T("Checking node's capabilities...\r\n")); |
5039dede | 2106 | |
99058170 VK |
2107 | if (confPollAgent(dwRqId)) |
2108 | hasChanges = true; | |
2109 | if (confPollSnmp(dwRqId)) | |
2110 | hasChanges = true; | |
5039dede AK |
2111 | |
2112 | // Check for CheckPoint SNMP agent on port 260 | |
9a1f7c45 | 2113 | if (ConfigReadInt(_T("EnableCheckPointSNMP"), 0)) |
5039dede | 2114 | { |
c42b4551 | 2115 | DbgPrintf(5, _T("ConfPoll(%s): checking for CheckPoint SNMP on port 260"), m_name); |
487cde95 | 2116 | if (!((m_flags & NF_IS_CPSNMP) && (m_dwDynamicFlags & NDF_CPSNMP_UNREACHABLE)) && m_ipAddress.isValidUnicast()) |
5039dede | 2117 | { |
2fbf7e1c | 2118 | SNMP_Transport *pTransport = new SNMP_UDPTransport; |
c75e9ee4 | 2119 | ((SNMP_UDPTransport *)pTransport)->createUDPTransport(m_ipAddress, CHECKPOINT_SNMP_PORT); |
9a1f7c45 VK |
2120 | if (SnmpGet(SNMP_VERSION_1, pTransport, |
2121 | _T(".1.3.6.1.4.1.2620.1.1.10.0"), NULL, 0, szBuffer, sizeof(szBuffer), 0) == SNMP_ERR_SUCCESS) | |
2122 | { | |
c42b4551 | 2123 | lockProperties(); |
487cde95 | 2124 | m_flags |= NF_IS_CPSNMP | NF_IS_ROUTER; |
9a1f7c45 | 2125 | m_dwDynamicFlags &= ~NDF_CPSNMP_UNREACHABLE; |
c42b4551 | 2126 | unlockProperties(); |
9a1f7c45 VK |
2127 | sendPollerMsg(dwRqId, POLLER_INFO _T(" CheckPoint SNMP agent on port 260 is active\r\n")); |
2128 | } | |
2129 | delete pTransport; | |
5039dede | 2130 | } |
5039dede AK |
2131 | } |
2132 | ||
2133 | // Generate event if node flags has been changed | |
487cde95 | 2134 | if (dwOldFlags != m_flags) |
5039dede | 2135 | { |
487cde95 | 2136 | PostEvent(EVENT_NODE_FLAGS_CHANGED, m_id, "xx", dwOldFlags, m_flags); |
76720a09 | 2137 | hasChanges = true; |
5039dede AK |
2138 | } |
2139 | ||
5039dede | 2140 | // Retrieve interface list |
208d7427 | 2141 | poller->setStatus(_T("interface check")); |
21c9acce | 2142 | sendPollerMsg(dwRqId, _T("Capability check finished\r\n")); |
5039dede | 2143 | |
bf2ad753 | 2144 | if (updateInterfaceConfiguration(dwRqId, maskBits)) |
76720a09 | 2145 | hasChanges = true; |
5039dede | 2146 | |
8573e935 | 2147 | m_lastConfigurationPoll = time(NULL); |
5039dede AK |
2148 | |
2149 | // Check node name | |
21c9acce | 2150 | sendPollerMsg(dwRqId, _T("Checking node name\r\n")); |
c42b4551 | 2151 | UINT32 dwAddr = ntohl(_t_inet_addr(m_name)); |
c8076b19 | 2152 | if ((g_flags & AF_RESOLVE_NODE_NAMES) && |
4d2c3a54 | 2153 | (dwAddr != INADDR_NONE) && |
5039dede | 2154 | (dwAddr != INADDR_ANY) && |
58b3e451 | 2155 | isMyIP(dwAddr)) |
5039dede | 2156 | { |
21c9acce | 2157 | sendPollerMsg(dwRqId, _T("Node name is an IP address and need to be resolved\r\n")); |
208d7427 | 2158 | poller->setStatus(_T("resolving name")); |
024c3faf | 2159 | if (resolveName(FALSE)) |
5039dede | 2160 | { |
c42b4551 | 2161 | sendPollerMsg(dwRqId, POLLER_INFO _T("Node name resolved to %s\r\n"), m_name); |
76720a09 | 2162 | hasChanges = true; |
5039dede AK |
2163 | } |
2164 | else | |
2165 | { | |
21c9acce | 2166 | sendPollerMsg(dwRqId, POLLER_WARNING _T("Node name cannot be resolved\r\n")); |
5039dede AK |
2167 | } |
2168 | } | |
2169 | else | |
2170 | { | |
c8076b19 | 2171 | if (g_flags & AF_SYNC_NODE_NAMES_WITH_DNS) |
5039dede | 2172 | { |
21c9acce | 2173 | sendPollerMsg(dwRqId, _T("Syncing node name with DNS\r\n")); |
208d7427 | 2174 | poller->setStatus(_T("resolving name")); |
024c3faf | 2175 | if (resolveName(TRUE)) |
5039dede | 2176 | { |
c42b4551 | 2177 | sendPollerMsg(dwRqId, POLLER_INFO _T("Node name resolved to %s\r\n"), m_name); |
76720a09 | 2178 | hasChanges = true; |
5039dede AK |
2179 | } |
2180 | } | |
2181 | else | |
2182 | { | |
21c9acce | 2183 | sendPollerMsg(dwRqId, _T("Node name is OK\r\n")); |
5039dede AK |
2184 | } |
2185 | } | |
2186 | ||
6fd6de0a | 2187 | applyUserTemplates(); |
7c521895 | 2188 | updateContainerMembership(); |
4d0c32f3 | 2189 | |
caa04e26 | 2190 | // Get list of installed products |
487cde95 | 2191 | if (m_flags & NF_IS_NATIVE_AGENT) |
caa04e26 | 2192 | { |
208d7427 | 2193 | poller->setStatus(_T("software check")); |
caa04e26 VK |
2194 | sendPollerMsg(dwRqId, _T("Reading list of installed software packages\r\n")); |
2195 | ||
2196 | Table *table; | |
2197 | if (getTableFromAgent(_T("System.InstalledProducts"), &table) == DCE_SUCCESS) | |
2198 | { | |
c42b4551 | 2199 | lockProperties(); |
caa04e26 VK |
2200 | delete m_softwarePackages; |
2201 | m_softwarePackages = new ObjectArray<SoftwarePackage>(table->getNumRows(), 16, true); | |
2202 | for(int i = 0; i < table->getNumRows(); i++) | |
2203 | m_softwarePackages->add(new SoftwarePackage(table, i)); | |
c42b4551 | 2204 | unlockProperties(); |
caa04e26 VK |
2205 | delete table; |
2206 | sendPollerMsg(dwRqId, POLLER_INFO _T("Got information about %d installed software packages\r\n"), m_softwarePackages->size()); | |
2207 | } | |
2208 | else | |
2209 | { | |
2210 | delete_and_null(m_softwarePackages); | |
2211 | sendPollerMsg(dwRqId, POLLER_WARNING _T("Unable to get information about installed software packages\r\n")); | |
2212 | } | |
2213 | } | |
2214 | ||
a3050773 | 2215 | // Call hooks in loaded modules |
967893bb | 2216 | for(UINT32 i = 0; i < g_dwNumModules; i++) |
a5ee7b3b | 2217 | { |
a3050773 VK |
2218 | if (g_pModuleList[i].pfConfPollHook != NULL) |
2219 | { | |
c42b4551 | 2220 | DbgPrintf(5, _T("ConfigurationPoll(%s [%d]): calling hook in module %s"), m_name, m_id, g_pModuleList[i].szName); |
208d7427 | 2221 | if (g_pModuleList[i].pfConfPollHook(this, pSession, dwRqId, poller)) |
3368b8b7 | 2222 | hasChanges = true; |
a3050773 | 2223 | } |
a5ee7b3b | 2224 | } |
a5ee7b3b | 2225 | |
270c946c | 2226 | // Setup permanent connection to agent if not present (needed for proper configuration re-sync) |
487cde95 | 2227 | if (m_flags & NF_IS_NATIVE_AGENT) |
270c946c VK |
2228 | { |
2229 | agentLock(); | |
2230 | connectToAgent(); | |
2231 | agentUnlock(); | |
2232 | } | |
2233 | ||
e980db40 VK |
2234 | // Update node type |
2235 | NodeType type = detectNodeType(); | |
2236 | nxlog_debug(5, _T("ConfPoll(%s): detected node type: %d (%s)"), m_name, type, typeName(type)); | |
2237 | lockProperties(); | |
2238 | if ((type != NODE_TYPE_UNKNOWN) && (type != m_type)) | |
2239 | { | |
2240 | m_type = type; | |
2241 | hasChanges = true; | |
2242 | nxlog_debug(5, _T("ConfPoll(%s): node type set to %d (%s)"), m_name, type, typeName(type)); | |
2243 | sendPollerMsg(dwRqId, _T(" Node type changed to %s\r\n"), typeName(type)); | |
2244 | } | |
2245 | unlockProperties(); | |
2246 | ||
a3050773 | 2247 | // Execute hook script |
208d7427 | 2248 | poller->setStatus(_T("hook")); |
a3050773 VK |
2249 | executeHookScript(_T("ConfigurationPoll")); |
2250 | ||
270c946c VK |
2251 | sendPollerMsg(dwRqId, _T("Finished configuration poll for node %s\r\n"), m_name); |
2252 | sendPollerMsg(dwRqId, _T("Node configuration was%schanged after poll\r\n"), hasChanges ? _T(" ") : _T(" not ")); | |
2253 | ||
a3050773 VK |
2254 | m_dwDynamicFlags |= NDF_CONFIGURATION_POLL_PASSED; |
2255 | } | |
1824629a | 2256 | |
4d0c32f3 | 2257 | // Finish configuration poll |
208d7427 | 2258 | poller->setStatus(_T("cleanup")); |
4d0c32f3 VK |
2259 | if (dwRqId == 0) |
2260 | m_dwDynamicFlags &= ~NDF_QUEUED_FOR_CONFIG_POLL; | |
2261 | m_dwDynamicFlags &= ~NDF_RECHECK_CAPABILITIES; | |
7c521895 | 2262 | pollerUnlock(); |
c42b4551 | 2263 | DbgPrintf(4, _T("Finished configuration poll for node %s (ID: %d)"), m_name, m_id); |
4d0c32f3 | 2264 | |
76720a09 | 2265 | if (hasChanges) |
4d0c32f3 | 2266 | { |
c42b4551 VK |
2267 | lockProperties(); |
2268 | setModified(); | |
2269 | unlockProperties(); | |
4d0c32f3 VK |
2270 | } |
2271 | } | |
2272 | ||
e980db40 VK |
2273 | /** |
2274 | * Detect node type | |
2275 | */ | |
2276 | NodeType Node::detectNodeType() | |
2277 | { | |
2278 | NodeType type = NODE_TYPE_UNKNOWN; | |
487cde95 | 2279 | if (m_flags & NF_IS_SNMP) |
e980db40 VK |
2280 | { |
2281 | nxlog_debug(6, _T("Node::detectNodeType(%s [%d]): SNMP node, driver name is %s"), m_name, m_id, m_driver->getName()); | |
2282 | ||
2283 | // Assume physical device if it supports SNMP and driver is not "GENERIC" | |
2284 | // FIXME: add driver method to determine node type | |
2285 | if (_tcscmp(m_driver->getName(), _T("GENERIC"))) | |
2286 | { | |
2287 | type = NODE_TYPE_PHYSICAL; | |
2288 | } | |
2289 | else | |
2290 | { | |
487cde95 | 2291 | if (m_flags & NF_IS_PRINTER) |
e980db40 VK |
2292 | { |
2293 | // Assume that printers are physical devices | |
2294 | type = NODE_TYPE_PHYSICAL; | |
2295 | } | |
2296 | } | |
2297 | } | |
2298 | return type; | |
2299 | } | |
2300 | ||
76720a09 VK |
2301 | /** |
2302 | * Configuration poll: check for NetXMS agent | |
2303 | */ | |
967893bb | 2304 | bool Node::confPollAgent(UINT32 dwRqId) |
76720a09 | 2305 | { |
487cde95 VK |
2306 | DbgPrintf(5, _T("ConfPoll(%s): checking for NetXMS agent Flags={%08X} DynamicFlags={%08X}"), m_name, m_flags, m_dwDynamicFlags); |
2307 | if (((m_flags & NF_IS_NATIVE_AGENT) && (m_dwDynamicFlags & NDF_AGENT_UNREACHABLE)) || | |
2308 | !m_ipAddress.isValidUnicast() || (m_flags & NF_DISABLE_NXCP)) | |
76720a09 VK |
2309 | return false; |
2310 | ||
2311 | bool hasChanges = false; | |
2312 | ||
21c9acce | 2313 | sendPollerMsg(dwRqId, _T(" Checking NetXMS agent...\r\n")); |
c75e9ee4 | 2314 | AgentConnection *pAgentConn = new AgentConnectionEx(m_id, m_ipAddress, m_agentPort, m_agentAuthMethod, m_szSharedSecret); |
76720a09 | 2315 | setAgentProxy(pAgentConn); |
c42b4551 | 2316 | DbgPrintf(5, _T("ConfPoll(%s): checking for NetXMS agent - connecting"), m_name); |
af21affe VK |
2317 | |
2318 | // Try to connect to agent | |
2319 | UINT32 rcc; | |
2320 | if (!pAgentConn->connect(g_pServerKey, FALSE, &rcc)) | |
2321 | { | |
2322 | // If there are authentication problem, try default shared secret | |
2323 | if ((rcc == ERR_AUTH_REQUIRED) || (rcc == ERR_AUTH_FAILED)) | |
2324 | { | |
2325 | TCHAR secret[MAX_SECRET_LENGTH]; | |
2326 | ConfigReadStr(_T("AgentDefaultSharedSecret"), secret, MAX_SECRET_LENGTH, _T("netxms")); | |
ce9783d2 | 2327 | DecryptPassword(_T("netxms"), secret, secret, MAX_SECRET_LENGTH); |
af21affe VK |
2328 | pAgentConn->setAuthData(AUTH_SHA1_HASH, secret); |
2329 | if (pAgentConn->connect(g_pServerKey, FALSE, &rcc)) | |
2330 | { | |
c42b4551 | 2331 | m_agentAuthMethod = AUTH_SHA1_HASH; |
af21affe | 2332 | nx_strncpy(m_szSharedSecret, secret, MAX_SECRET_LENGTH); |
c42b4551 | 2333 | DbgPrintf(5, _T("ConfPoll(%s): checking for NetXMS agent - shared secret changed to system default"), m_name); |
af21affe VK |
2334 | } |
2335 | } | |
2336 | } | |
2337 | ||
2338 | if (rcc == ERR_SUCCESS) | |
76720a09 | 2339 | { |
c42b4551 VK |
2340 | DbgPrintf(5, _T("ConfPoll(%s): checking for NetXMS agent - connected"), m_name); |
2341 | lockProperties(); | |
487cde95 | 2342 | m_flags |= NF_IS_NATIVE_AGENT; |
76720a09 VK |
2343 | if (m_dwDynamicFlags & NDF_AGENT_UNREACHABLE) |
2344 | { | |
2345 | m_dwDynamicFlags &= ~NDF_AGENT_UNREACHABLE; | |
c42b4551 | 2346 | PostEvent(EVENT_AGENT_OK, m_id, NULL); |
21c9acce | 2347 | sendPollerMsg(dwRqId, POLLER_INFO _T(" Connectivity with NetXMS agent restored\r\n")); |
76720a09 VK |
2348 | } |
2349 | else | |
2350 | { | |
21c9acce | 2351 | sendPollerMsg(dwRqId, POLLER_INFO _T(" NetXMS native agent is active\r\n")); |
76720a09 | 2352 | } |
c42b4551 | 2353 | unlockProperties(); |
4d0c32f3 | 2354 | |
76720a09 VK |
2355 | TCHAR buffer[MAX_RESULT_LENGTH]; |
2356 | if (pAgentConn->getParameter(_T("Agent.Version"), MAX_AGENT_VERSION_LEN, buffer) == ERR_SUCCESS) | |
2357 | { | |
c42b4551 | 2358 | lockProperties(); |
76720a09 VK |
2359 | if (_tcscmp(m_szAgentVersion, buffer)) |
2360 | { | |
2361 | _tcscpy(m_szAgentVersion, buffer); | |
2362 | hasChanges = true; | |
21c9acce | 2363 | sendPollerMsg(dwRqId, _T(" NetXMS agent version changed to %s\r\n"), m_szAgentVersion); |
76720a09 | 2364 | } |
c42b4551 | 2365 | unlockProperties(); |
76720a09 VK |
2366 | } |
2367 | ||
2368 | if (pAgentConn->getParameter(_T("System.PlatformName"), MAX_PLATFORM_NAME_LEN, buffer) == ERR_SUCCESS) | |
2369 | { | |
c42b4551 | 2370 | lockProperties(); |
76720a09 VK |
2371 | if (_tcscmp(m_szPlatformName, buffer)) |
2372 | { | |
2373 | _tcscpy(m_szPlatformName, buffer); | |
2374 | hasChanges = true; | |
21c9acce | 2375 | sendPollerMsg(dwRqId, _T(" Platform name changed to %s\r\n"), m_szPlatformName); |
76720a09 | 2376 | } |
c42b4551 | 2377 | unlockProperties(); |
76720a09 VK |
2378 | } |
2379 | ||
2380 | // Check IP forwarding status | |
2381 | if (pAgentConn->getParameter(_T("Net.IP.Forwarding"), 16, buffer) == ERR_SUCCESS) | |
2382 | { | |
2383 | if (_tcstoul(buffer, NULL, 10) != 0) | |
487cde95 | 2384 | m_flags |= NF_IS_ROUTER; |
76720a09 | 2385 | else |
487cde95 | 2386 | m_flags &= ~NF_IS_ROUTER; |
76720a09 VK |
2387 | } |
2388 | ||
2389 | // Get uname | |
2390 | if (pAgentConn->getParameter(_T("System.Uname"), MAX_DB_STRING, buffer) == ERR_SUCCESS) | |
2391 | { | |
2392 | TranslateStr(buffer, _T("\r\n"), _T(" ")); | |
2393 | TranslateStr(buffer, _T("\n"), _T(" ")); | |
2394 | TranslateStr(buffer, _T("\r"), _T(" ")); | |
c42b4551 | 2395 | lockProperties(); |
76720a09 VK |
2396 | if ((m_sysDescription == NULL) || _tcscmp(m_sysDescription, buffer)) |
2397 | { | |
2398 | safe_free(m_sysDescription); | |
2399 | m_sysDescription = _tcsdup(buffer); | |
2400 | hasChanges = true; | |
21c9acce | 2401 | sendPollerMsg(dwRqId, _T(" System description changed to %s\r\n"), m_sysDescription); |
76720a09 | 2402 | } |
c42b4551 | 2403 | unlockProperties(); |
76720a09 VK |
2404 | } |
2405 | ||
11b75b2e | 2406 | // Check for 64 bit counter support. |
acf01215 | 2407 | // if Net.Interface.64BitCounters not supported by agent then use |
11b75b2e VK |
2408 | // only presence of 64 bit parameters as indicator |
2409 | bool netIf64bitCounters = true; | |
2410 | if (pAgentConn->getParameter(_T("Net.Interface.64BitCounters"), MAX_DB_STRING, buffer) == ERR_SUCCESS) | |
2411 | { | |
2412 | netIf64bitCounters = _tcstol(buffer, NULL, 10) ? true : false; | |
2413 | } | |
2414 | ||
86c126f5 VK |
2415 | ObjectArray<AgentParameterDefinition> *plist; |
2416 | ObjectArray<AgentTableDefinition> *tlist; | |
967893bb | 2417 | UINT32 rcc = pAgentConn->getSupportedParameters(&plist, &tlist); |
76720a09 VK |
2418 | if (rcc == ERR_SUCCESS) |
2419 | { | |
c42b4551 | 2420 | lockProperties(); |
76720a09 VK |
2421 | delete m_paramList; |
2422 | delete m_tableList; | |
2423 | m_paramList = plist; | |
2424 | m_tableList = tlist; | |
084fb4c1 VK |
2425 | |
2426 | // Check for 64-bit interface counters | |
487cde95 | 2427 | m_flags &= ~NF_HAS_AGENT_IFXCOUNTERS; |
11b75b2e VK |
2428 | if (netIf64bitCounters) |
2429 | { | |
2430 | for(int i = 0; i < plist->size(); i++) | |
2431 | { | |
2432 | if (!_tcsicmp(plist->get(i)->getName(), _T("Net.Interface.BytesIn64(*)"))) | |
2433 | { | |
487cde95 | 2434 | m_flags |= NF_HAS_AGENT_IFXCOUNTERS; |
11b75b2e VK |
2435 | break; |
2436 | } | |
2437 | } | |
2438 | } | |
084fb4c1 | 2439 | |
c42b4551 | 2440 | unlockProperties(); |
76720a09 VK |
2441 | } |
2442 | else | |
2443 | { | |
c42b4551 | 2444 | DbgPrintf(5, _T("ConfPoll(%s): AgentConnection::getSupportedParameters() failed: rcc=%d"), m_name, rcc); |
76720a09 VK |
2445 | } |
2446 | ||
46ee6286 VK |
2447 | // Get supported Windows Performance Counters |
2448 | if (!_tcsncmp(m_szPlatformName, _T("windows-"), 8)) | |
2449 | { | |
2450 | sendPollerMsg(dwRqId, _T(" Reading list of available Windows Performance Counters...\r\n")); | |
2451 | ObjectArray<WinPerfObject> *perfObjects = WinPerfObject::getWinPerfObjectsFromNode(this, pAgentConn); | |
c42b4551 | 2452 | lockProperties(); |
46ee6286 VK |
2453 | delete m_winPerfObjects; |
2454 | m_winPerfObjects = perfObjects; | |
2455 | if (m_winPerfObjects != NULL) | |
2456 | { | |
2457 | sendPollerMsg(dwRqId, POLLER_INFO _T(" %d counters read\r\n"), m_winPerfObjects->size()); | |
487cde95 | 2458 | if (!(m_flags & NF_HAS_WINPDH)) |
46ee6286 | 2459 | { |
487cde95 | 2460 | m_flags |= NF_HAS_WINPDH; |
46ee6286 VK |
2461 | hasChanges = true; |
2462 | } | |
2463 | } | |
2464 | else | |
2465 | { | |
2466 | sendPollerMsg(dwRqId, POLLER_ERROR _T(" unable to get Windows Performance Counters list\r\n")); | |
487cde95 | 2467 | if (m_flags & NF_HAS_WINPDH) |
46ee6286 | 2468 | { |
487cde95 | 2469 | m_flags &= ~NF_HAS_WINPDH; |
46ee6286 VK |
2470 | hasChanges = true; |
2471 | } | |
2472 | } | |
c42b4551 | 2473 | unlockProperties(); |
46ee6286 VK |
2474 | } |
2475 | ||
76720a09 VK |
2476 | checkAgentPolicyBinding(pAgentConn); |
2477 | ||
2478 | pAgentConn->disconnect(); | |
2479 | } | |
2480 | else | |
2481 | { | |
c42b4551 | 2482 | DbgPrintf(5, _T("ConfPoll(%s): checking for NetXMS agent - failed to connect (error %d)"), m_name, rcc); |
76720a09 | 2483 | } |
da4a8dfe | 2484 | pAgentConn->decRefCount(); |
c42b4551 | 2485 | DbgPrintf(5, _T("ConfPoll(%s): checking for NetXMS agent - finished"), m_name); |
76720a09 VK |
2486 | return hasChanges; |
2487 | } | |
2488 | ||
2489 | /** | |
a93aa634 | 2490 | * SNMP walker callback which sets indicator to true after first varbind and aborts walk |
76720a09 | 2491 | */ |
9c5ebc32 | 2492 | static UINT32 IndicatorSnmpWalkerCallback(SNMP_Variable *var, SNMP_Transport *transport, void *arg) |
76720a09 | 2493 | { |
a93aa634 VK |
2494 | (*((bool *)arg)) = true; |
2495 | return SNMP_ERR_COMM; | |
76720a09 VK |
2496 | } |
2497 | ||
2498 | /** | |
2499 | * Configuration poll: check for SNMP | |
2500 | */ | |
967893bb | 2501 | bool Node::confPollSnmp(UINT32 dwRqId) |
76720a09 | 2502 | { |
487cde95 VK |
2503 | if (((m_flags & NF_IS_SNMP) && (m_dwDynamicFlags & NDF_SNMP_UNREACHABLE)) || |
2504 | !m_ipAddress.isValidUnicast() || (m_flags & NF_DISABLE_SNMP)) | |
76720a09 VK |
2505 | return false; |
2506 | ||
2507 | bool hasChanges = false; | |
2508 | ||
21c9acce | 2509 | sendPollerMsg(dwRqId, _T(" Checking SNMP...\r\n")); |
c42b4551 | 2510 | DbgPrintf(5, _T("ConfPoll(%s): calling SnmpCheckCommSettings()"), m_name); |
1f4c37ee VK |
2511 | StringList oids; |
2512 | const TCHAR *customOid = m_customAttributes.get(_T("snmp.testoid")); | |
2513 | if (customOid != NULL) | |
2514 | oids.add(customOid); | |
2515 | oids.add(_T(".1.3.6.1.2.1.1.2.0")); | |
2516 | oids.add(_T(".1.3.6.1.2.1.1.1.0")); | |
2517 | AddDriverSpecificOids(&oids); | |
d0a2ada6 | 2518 | SNMP_Transport *pTransport = SnmpCheckCommSettings(getEffectiveSnmpProxy(), (getEffectiveSnmpProxy() == m_id) ? InetAddress::LOOPBACK : m_ipAddress, &m_snmpVersion, m_snmpPort, m_snmpSecurity, &oids); |
af7ca382 | 2519 | if (pTransport == NULL) |
76720a09 | 2520 | { |
d0a2ada6 | 2521 | DbgPrintf(5, _T("ConfPoll(%s): unable to create SNMP transport"), m_name); |
2522 | return false; | |
2523 | } | |
76720a09 | 2524 | |
d0a2ada6 | 2525 | lockProperties(); |
2526 | m_snmpPort = pTransport->getPort(); | |
2527 | delete m_snmpSecurity; | |
2528 | m_snmpSecurity = new SNMP_SecurityContext(pTransport->getSecurityContext()); | |
487cde95 | 2529 | m_flags |= NF_IS_SNMP; |
d0a2ada6 | 2530 | if (m_dwDynamicFlags & NDF_SNMP_UNREACHABLE) |
2531 | { | |
2532 | m_dwDynamicFlags &= ~NDF_SNMP_UNREACHABLE; | |
2533 | PostEvent(EVENT_SNMP_OK, m_id, NULL); | |
2534 | sendPollerMsg(dwRqId, POLLER_INFO _T(" Connectivity with SNMP agent restored\r\n")); | |
2535 | } | |
2536 | unlockProperties(); | |
2537 | sendPollerMsg(dwRqId, _T(" SNMP agent is active (version %s)\r\n"), | |
2538 | (m_snmpVersion == SNMP_VERSION_3) ? _T("3") : ((m_snmpVersion == SNMP_VERSION_2C) ? _T("2c") : _T("1"))); | |
76720a09 | 2539 | |
d0a2ada6 | 2540 | TCHAR szBuffer[4096]; |
2541 | 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) | |
2542 | { | |
2543 | // Set snmp object ID to .0.0 if it cannot be read | |
2544 | _tcscpy(szBuffer, _T(".0.0")); | |
2545 | } | |
2546 | lockProperties(); | |
2547 | if (_tcscmp(m_szObjectId, szBuffer)) | |
2548 | { | |
2549 | nx_strncpy(m_szObjectId, szBuffer, MAX_OID_LEN * 4); | |
2550 | hasChanges = true; | |
2551 | } | |
2552 | unlockProperties(); | |
76720a09 | 2553 | |
d0a2ada6 | 2554 | // Get system description |
2555 | 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) | |
2556 | { | |
2557 | TranslateStr(szBuffer, _T("\r\n"), _T(" ")); | |
2558 | TranslateStr(szBuffer, _T("\n"), _T(" ")); | |
2559 | TranslateStr(szBuffer, _T("\r"), _T(" ")); | |
2560 | lockProperties(); | |
2561 | if ((m_sysDescription == NULL) || _tcscmp(m_sysDescription, szBuffer)) | |
76720a09 | 2562 | { |
d0a2ada6 | 2563 | safe_free(m_sysDescription); |
2564 | m_sysDescription = _tcsdup(szBuffer); | |
2565 | hasChanges = true; | |
2566 | sendPollerMsg(dwRqId, _T(" System description changed to %s\r\n"), m_sysDescription); | |
76720a09 | 2567 | } |
d0a2ada6 | 2568 | unlockProperties(); |
2569 | } | |
76720a09 | 2570 | |
d0a2ada6 | 2571 | // Select device driver |
2572 | NetworkDeviceDriver *driver = FindDriverForNode(this, pTransport); | |
2573 | DbgPrintf(5, _T("ConfPoll(%s): selected device driver %s"), m_name, driver->getName()); | |
2574 | lockProperties(); | |
2575 | if (driver != m_driver) | |
2576 | { | |
2577 | m_driver = driver; | |
2578 | sendPollerMsg(dwRqId, _T(" New network device driver selected: %s\r\n"), m_driver->getName()); | |
2579 | } | |
2580 | unlockProperties(); | |
eec253a8 | 2581 | |
d0a2ada6 | 2582 | // Allow driver to gather additional info |
2583 | m_driver->analyzeDevice(pTransport, m_szObjectId, &m_customAttributes, &m_driverData); | |
76720a09 | 2584 | |
cf38357f VK |
2585 | // Get sysName, sysContact, sysLocation |
2586 | if (querySnmpSysProperty(pTransport, _T(".1.3.6.1.2.1.1.5.0"), _T("name"), dwRqId, &m_sysName)) | |
2587 | hasChanges = true; | |
2588 | if (querySnmpSysProperty(pTransport, _T(".1.3.6.1.2.1.1.4.0"), _T("contact"), dwRqId, &m_sysContact)) | |
2589 | hasChanges = true; | |
2590 | if (querySnmpSysProperty(pTransport, _T(".1.3.6.1.2.1.1.6.0"), _T("location"), dwRqId, &m_sysLocation)) | |
2591 | hasChanges = true; | |
76720a09 | 2592 | |
d0a2ada6 | 2593 | // Check IP forwarding |
2594 | if (checkSNMPIntegerValue(pTransport, _T(".1.3.6.1.2.1.4.1.0"), 1)) | |
2595 | { | |
2596 | lockProperties(); | |
487cde95 | 2597 | m_flags |= NF_IS_ROUTER; |
d0a2ada6 | 2598 | unlockProperties(); |
2599 | } | |
2600 | else | |
2601 | { | |
2602 | lockProperties(); | |
487cde95 | 2603 | m_flags &= ~NF_IS_ROUTER; |
d0a2ada6 | 2604 | unlockProperties(); |
2605 | } | |
76720a09 | 2606 | |
d0a2ada6 | 2607 | checkIfXTable(pTransport); |
2608 | checkBridgeMib(pTransport); | |
76720a09 | 2609 | |
d0a2ada6 | 2610 | // Check for ENTITY-MIB support |
2611 | 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) | |
2612 | { | |
2613 | lockProperties(); | |
487cde95 | 2614 | m_flags |= NF_HAS_ENTITY_MIB; |
d0a2ada6 | 2615 | unlockProperties(); |
2616 | ||
2617 | ComponentTree *components = BuildComponentTree(this, pTransport); | |
2618 | lockProperties(); | |
2619 | if (m_components != NULL) | |
2620 | m_components->decRefCount(); | |
2621 | m_components = components; | |
2622 | unlockProperties(); | |
2623 | } | |
2624 | else | |
2625 | { | |
2626 | lockProperties(); | |
487cde95 | 2627 | m_flags &= ~NF_HAS_ENTITY_MIB; |
d0a2ada6 | 2628 | if (m_components != NULL) |
76720a09 | 2629 | { |
d0a2ada6 | 2630 | m_components->decRefCount(); |
2631 | m_components = NULL; | |
76720a09 | 2632 | } |
d0a2ada6 | 2633 | unlockProperties(); |
2634 | } | |
76720a09 | 2635 | |
d0a2ada6 | 2636 | // Check for printer MIB support |
a93aa634 | 2637 | bool present = false; |
9c5ebc32 | 2638 | SnmpWalk(pTransport, _T(".1.3.6.1.2.1.43"), IndicatorSnmpWalkerCallback, &present); |
a93aa634 | 2639 | if (present) |
d0a2ada6 | 2640 | { |
2641 | lockProperties(); | |
487cde95 | 2642 | m_flags |= NF_IS_PRINTER; |
d0a2ada6 | 2643 | unlockProperties(); |
2644 | } | |
2645 | else | |
2646 | { | |
2647 | lockProperties(); | |
487cde95 | 2648 | m_flags &= ~NF_IS_PRINTER; |
d0a2ada6 | 2649 | unlockProperties(); |
2650 | } | |
76720a09 | 2651 | |
d0a2ada6 | 2652 | // Check for CDP (Cisco Discovery Protocol) support |
2653 | if (checkSNMPIntegerValue(pTransport, _T(".1.3.6.1.4.1.9.9.23.1.3.1.0"), 1)) | |
2654 | { | |
2655 | lockProperties(); | |
487cde95 | 2656 | m_flags |= NF_IS_CDP; |
d0a2ada6 | 2657 | unlockProperties(); |
2658 | } | |
2659 | else | |
2660 | { | |
2661 | lockProperties(); | |
487cde95 | 2662 | m_flags &= ~NF_IS_CDP; |
d0a2ada6 | 2663 | unlockProperties(); |
2664 | } | |
3a82d5ae | 2665 | |
d0a2ada6 | 2666 | // Check for NDP (Nortel Discovery Protocol) support |
2667 | if (checkSNMPIntegerValue(pTransport, _T(".1.3.6.1.4.1.45.1.6.13.1.2.0"), 1)) | |
2668 | { | |
2669 | lockProperties(); | |
487cde95 | 2670 | m_flags |= NF_IS_NDP; |
d0a2ada6 | 2671 | unlockProperties(); |
2672 | } | |
2673 | else | |
2674 | { | |
2675 | lockProperties(); | |
487cde95 | 2676 | m_flags &= ~NF_IS_NDP; |
d0a2ada6 | 2677 | unlockProperties(); |
2678 | } | |
76720a09 | 2679 | |
d0a2ada6 | 2680 | // Check for LLDP (Link Layer Discovery Protocol) support |
2681 | 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) | |
2682 | { | |
2683 | lockProperties(); | |
487cde95 | 2684 | m_flags |= NF_IS_LLDP; |
d0a2ada6 | 2685 | unlockProperties(); |
2686 | ||
2687 | INT32 type; | |
2688 | BYTE data[256]; | |
2689 | UINT32 dataLen; | |
2690 | if ((SnmpGetEx(pTransport, _T(".1.0.8802.1.1.2.1.3.1.0"), NULL, 0, &type, sizeof(INT32), 0, NULL) == SNMP_ERR_SUCCESS) && | |
2691 | (SnmpGetEx(pTransport, _T(".1.0.8802.1.1.2.1.3.2.0"), NULL, 0, data, 256, SG_RAW_RESULT, &dataLen) == SNMP_ERR_SUCCESS)) | |
76720a09 | 2692 | { |
d0a2ada6 | 2693 | BuildLldpId(type, data, dataLen, szBuffer, 1024); |
2694 | lockProperties(); | |
2695 | if ((m_lldpNodeId == NULL) || _tcscmp(m_lldpNodeId, szBuffer)) | |
2696 | { | |
2697 | safe_free(m_lldpNodeId); | |
2698 | m_lldpNodeId = _tcsdup(szBuffer); | |
2699 | hasChanges = true; | |
2700 | sendPollerMsg(dwRqId, _T(" LLDP node ID changed to %s\r\n"), m_lldpNodeId); | |
2701 | } | |
2702 | unlockProperties(); | |
76720a09 VK |
2703 | } |
2704 | ||
d0a2ada6 | 2705 | ObjectArray<LLDP_LOCAL_PORT_INFO> *lldpPorts = GetLLDPLocalPortInfo(pTransport); |
2706 | lockProperties(); | |
2707 | delete m_lldpLocalPortInfo; | |
2708 | m_lldpLocalPortInfo = lldpPorts; | |
2709 | unlockProperties(); | |
2710 | } | |
2711 | else | |
2712 | { | |
2713 | lockProperties(); | |
487cde95 | 2714 | m_flags &= ~NF_IS_LLDP; |
d0a2ada6 | 2715 | unlockProperties(); |
2716 | } | |
76720a09 | 2717 | |
d0a2ada6 | 2718 | // Check for 802.1x support |
2719 | if (checkSNMPIntegerValue(pTransport, _T(".1.0.8802.1.1.1.1.1.1.0"), 1)) | |
2720 | { | |
2721 | lockProperties(); | |
487cde95 | 2722 | m_flags |= NF_IS_8021X; |
d0a2ada6 | 2723 | unlockProperties(); |
2724 | } | |
2725 | else | |
2726 | { | |
2727 | lockProperties(); | |
487cde95 | 2728 | m_flags &= ~NF_IS_8021X; |
d0a2ada6 | 2729 | unlockProperties(); |
2730 | } | |
c6afd26a | 2731 | |
d0a2ada6 | 2732 | checkOSPFSupport(pTransport); |
c6afd26a | 2733 | |
d0a2ada6 | 2734 | // Get VRRP information |
2735 | VrrpInfo *vrrpInfo = GetVRRPInfo(this); | |
2736 | if (vrrpInfo != NULL) | |
2737 | { | |
2738 | lockProperties(); | |
487cde95 | 2739 | m_flags |= NF_IS_VRRP; |
d0a2ada6 | 2740 | delete m_vrrpInfo; |
2741 | m_vrrpInfo = vrrpInfo; | |
2742 | unlockProperties(); | |
2743 | } | |
2744 | else | |
2745 | { | |
2746 | lockProperties(); | |
487cde95 | 2747 | m_flags &= ~NF_IS_VRRP; |
d0a2ada6 | 2748 | unlockProperties(); |
2749 | } | |
8f26db67 | 2750 | |
d0a2ada6 | 2751 | // Get wireless controller data |
2752 | if ((m_driver != NULL) && m_driver->isWirelessController(pTransport, &m_customAttributes, m_driverData)) | |
2753 | { | |
2754 | DbgPrintf(5, _T("ConfPoll(%s): node is wireless controller, reading access point information"), m_name); | |
2755 | sendPollerMsg(dwRqId, _T(" Reading wireless access point information\r\n")); | |
2756 | lockProperties(); | |
487cde95 | 2757 | m_flags |= NF_IS_WIFI_CONTROLLER; |
d0a2ada6 | 2758 | unlockProperties(); |
f1989a3a | 2759 | |
d0a2ada6 | 2760 | int clusterMode = m_driver->getClusterMode(pTransport, &m_customAttributes, m_driverData); |
4d2c3a54 | 2761 | |
d0a2ada6 | 2762 | ObjectArray<AccessPointInfo> *aps = m_driver->getAccessPoints(pTransport, &m_customAttributes, m_driverData); |
2763 | if (aps != NULL) | |
2764 | { | |
2765 | sendPollerMsg(dwRqId, POLLER_INFO _T(" %d wireless access points found\r\n"), aps->size()); | |
2766 | DbgPrintf(5, _T("ConfPoll(%s): got information about %d access points"), m_name, aps->size()); | |
2767 | int adopted = 0; | |
2768 | for(int i = 0; i < aps->size(); i++) | |
2769 | { | |
2770 | AccessPointInfo *info = aps->get(i); | |
2771 | if (info->getState() == AP_ADOPTED) | |
2772 | adopted++; | |
2773 | ||
2774 | bool newAp = false; | |
2775 | AccessPoint *ap = (clusterMode == CLUSTER_MODE_STANDALONE) ? findAccessPointByMAC(info->getMacAddr()) : FindAccessPointByMAC(info->getMacAddr()); | |
2776 | if (ap == NULL) | |
2777 | { | |
2778 | String name; | |
2779 | ||
2780 | if (info->getName() != NULL) | |
2781 | { | |
2782 | name = info->getName(); | |
2783 | } | |
2784 | else | |
2785 | { | |
2786 | for(int j = 0; j < info->getRadioInterfaces()->size(); j++) | |
ffb44442 | 2787 | { |
d0a2ada6 | 2788 | if (j > 0) |
2789 | name += _T("/"); | |
2790 | name += info->getRadioInterfaces()->get(j)->name; | |
ffb44442 | 2791 | } |
23ed00c4 | 2792 | } |
d0a2ada6 | 2793 | ap = new AccessPoint((const TCHAR *)name, info->getIndex(), info->getMacAddr()); |
e7450f3b | 2794 | NetObjInsert(ap, true, false); |
d0a2ada6 | 2795 | DbgPrintf(5, _T("ConfPoll(%s): created new access point object %s [%d]"), m_name, ap->getName(), ap->getId()); |
2796 | newAp = true; | |
2797 | } | |
2798 | ap->attachToNode(m_id); | |
2799 | ap->setIpAddress(info->getIpAddr()); | |
2800 | if ((info->getState() == AP_ADOPTED) || newAp) | |
2801 | { | |
2802 | ap->updateRadioInterfaces(info->getRadioInterfaces()); | |
2803 | ap->updateInfo(info->getVendor(), info->getModel(), info->getSerial()); | |
2804 | } | |
2805 | ap->unhide(); | |
2806 | ap->updateState(info->getState()); | |
2807 | } | |
f1989a3a | 2808 | |
d0a2ada6 | 2809 | lockProperties(); |
2810 | m_adoptedApCount = adopted; | |
2811 | m_totalApCount = aps->size(); | |
2812 | unlockProperties(); | |
f1989a3a | 2813 | |
d0a2ada6 | 2814 | delete aps; |
2815 | } | |
2816 | else | |
2817 | { | |
2818 | DbgPrintf(5, _T("ConfPoll(%s): failed to read access point information"), m_name); | |
2819 | sendPollerMsg(dwRqId, POLLER_ERROR _T(" Failed to read access point information\r\n")); | |
2820 | } | |
2821 | } | |
2822 | else | |
2823 | { | |
2824 | lockProperties(); | |
487cde95 | 2825 | m_flags &= ~NF_IS_WIFI_CONTROLLER; |
d0a2ada6 | 2826 | unlockProperties(); |
76720a09 | 2827 | } |
d0a2ada6 | 2828 | |
2829 | if (ConfigReadInt(_T("EnableCheckPointSNMP"), 0)) | |
76720a09 VK |
2830 | { |
2831 | // Check for CheckPoint SNMP agent on port 161 | |
c42b4551 | 2832 | DbgPrintf(5, _T("ConfPoll(%s): checking for CheckPoint SNMP"), m_name); |
76720a09 | 2833 | TCHAR szBuffer[4096]; |
d525c9ed | 2834 | 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) |
76720a09 | 2835 | { |
c42b4551 | 2836 | lockProperties(); |
76720a09 VK |
2837 | if (_tcscmp(m_szObjectId, _T(".1.3.6.1.4.1.2620.1.1"))) |
2838 | { | |
2839 | nx_strncpy(m_szObjectId, _T(".1.3.6.1.4.1.2620.1.1"), MAX_OID_LEN * 4); | |
2840 | hasChanges = true; | |
2841 | } | |
2842 | ||
487cde95 | 2843 | m_flags |= NF_IS_SNMP | NF_IS_ROUTER; |
76720a09 | 2844 | m_dwDynamicFlags &= ~NDF_SNMP_UNREACHABLE; |
c42b4551 | 2845 | unlockProperties(); |
21c9acce | 2846 | sendPollerMsg(dwRqId, POLLER_INFO _T(" CheckPoint SNMP agent on port 161 is active\r\n")); |
76720a09 VK |
2847 | } |
2848 | } | |
2849 | delete pTransport; | |
2850 | return hasChanges; | |
2851 | } | |
2852 | ||
cf38357f VK |
2853 | /** |
2854 | * Query SNMP sys property (sysName, sysLocation, etc.) | |
2855 | */ | |
2856 | bool Node::querySnmpSysProperty(SNMP_Transport *snmp, const TCHAR *oid, const TCHAR *propName, UINT32 pollRqId, TCHAR **value) | |
2857 | { | |
2858 | TCHAR buffer[256]; | |
2859 | bool hasChanges = false; | |
2860 | ||
2861 | if (SnmpGet(m_snmpVersion, snmp, oid, NULL, 0, buffer, sizeof(buffer), SG_STRING_RESULT) == SNMP_ERR_SUCCESS) | |
2862 | { | |
2863 | lockProperties(); | |
2864 | if ((*value == NULL) || _tcscmp(*value, buffer)) | |
2865 | { | |
2866 | safe_free(*value); | |
2867 | *value = _tcsdup(buffer); | |
2868 | hasChanges = true; | |
2869 | sendPollerMsg(pollRqId, _T(" System %s changed to %s\r\n"), propName, *value); | |
2870 | } | |
2871 | unlockProperties(); | |
2872 | } | |
2873 | return hasChanges; | |
2874 | } | |
2875 | ||
76720a09 VK |
2876 | /** |
2877 | * Configuration poll: check for BRIDGE MIB | |
2878 | */ | |
2879 | void Node::checkBridgeMib(SNMP_Transport *pTransport) | |
2880 | { | |
2881 | TCHAR szBuffer[4096]; | |
d525c9ed | 2882 | 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) |
76720a09 | 2883 | { |
c42b4551 | 2884 | lockProperties(); |
487cde95 | 2885 | m_flags |= NF_IS_BRIDGE; |
76720a09 | 2886 | memcpy(m_baseBridgeAddress, szBuffer, 6); |
c42b4551 | 2887 | unlockProperties(); |
76720a09 VK |
2888 | |
2889 | // Check for Spanning Tree (IEEE 802.1d) MIB support | |
074498ac | 2890 | if (checkSNMPIntegerValue(pTransport, _T(".1.3.6.1.2.1.17.2.1.0"), 3)) |
76720a09 | 2891 | { |
c42b4551 | 2892 | lockProperties(); |
487cde95 | 2893 | m_flags |= NF_IS_STP; |
c42b4551 | 2894 | unlockProperties(); |
76720a09 VK |
2895 | } |
2896 | else | |
2897 | { | |
c42b4551 | 2898 | lockProperties(); |
487cde95 | 2899 | m_flags &= ~NF_IS_STP; |
c42b4551 | 2900 | unlockProperties(); |
76720a09 VK |
2901 | } |
2902 | } | |
2903 | else | |
2904 | { | |
c42b4551 | 2905 | lockProperties(); |
487cde95 | 2906 | m_flags &= ~(NF_IS_BRIDGE | NF_IS_STP); |
c42b4551 | 2907 | unlockProperties(); |
76720a09 VK |
2908 | } |
2909 | } | |
2910 | ||
2911 | /** | |
2912 | * Configuration poll: check for ifXTable | |
2913 | */ | |
2914 | void Node::checkIfXTable(SNMP_Transport *pTransport) | |
2915 | { | |
a93aa634 | 2916 | bool present = false; |
9c5ebc32 | 2917 | SnmpWalk(pTransport, _T(".1.3.6.1.2.1.31.1.1.1.1"), IndicatorSnmpWalkerCallback, &present); |
a93aa634 | 2918 | if (present) |
76720a09 | 2919 | { |
c42b4551 | 2920 | lockProperties(); |
487cde95 | 2921 | m_flags |= NF_HAS_IFXTABLE; |
c42b4551 | 2922 | unlockProperties(); |
76720a09 VK |
2923 | } |
2924 | else | |
2925 | { | |
c42b4551 | 2926 | lockProperties(); |
487cde95 | 2927 | m_flags &= ~NF_HAS_IFXTABLE; |
c42b4551 | 2928 | unlockProperties(); |
76720a09 VK |
2929 | } |
2930 | } | |
2931 | ||
dfed892b VK |
2932 | /** |
2933 | * Delete duplicate interfaces | |
2934 | * (find and delete multiple interfaces with same ifIndex value created by version prior to 2.0-M3) | |
2935 | */ | |
2936 | bool Node::deleteDuplicateInterfaces(UINT32 rqid) | |
2937 | { | |
2938 | ObjectArray<Interface> deleteList(16, 16, false); | |
2939 | ||
db091a1f VK |
2940 | lockChildList(false); |
2941 | for(int i = 0; i < m_childList->size(); i++) | |
dfed892b | 2942 | { |
db091a1f VK |
2943 | NetObj *curr = m_childList->get(i); |
2944 | ||
2945 | if ((curr->getObjectClass() != OBJECT_INTERFACE) || | |
2946 | ((Interface *)curr)->isManuallyCreated()) | |
dfed892b | 2947 | continue; |
db091a1f VK |
2948 | Interface *iface = (Interface *)curr; |
2949 | for(int j = i + 1; j < m_childList->size(); j++) | |
dfed892b | 2950 | { |
db091a1f VK |
2951 | NetObj *next = m_childList->get(j); |
2952 | ||
2953 | if ((next->getObjectClass() != OBJECT_INTERFACE) || | |
2954 | ((Interface *)next)->isManuallyCreated() || | |
2955 | (deleteList.contains((Interface *)next))) | |
dfed892b | 2956 | continue; |
db091a1f | 2957 | if (iface->getIfIndex() == ((Interface *)next)->getIfIndex()) |
dfed892b | 2958 | { |
db091a1f | 2959 | deleteList.add((Interface *)next); |
dfed892b | 2960 | DbgPrintf(6, _T("Node::deleteDuplicateInterfaces(%s [%d]): found duplicate interface %s [%d], original %s [%d], ifIndex=%d"), |
db091a1f | 2961 | m_name, m_id, next->getName(), next->getId(), iface->getName(), iface->getId(), iface->getIfIndex()); |
dfed892b VK |
2962 | } |
2963 | } | |
2964 | } | |
db091a1f | 2965 | unlockChildList(); |
dfed892b VK |
2966 | |
2967 | for(int i = 0; i < deleteList.size(); i++) | |
2968 | { | |
2969 | Interface *iface = deleteList.get(i); | |
2970 | sendPollerMsg(rqid, POLLER_WARNING _T(" Duplicate interface \"%s\" deleted\r\n"), iface->getName()); | |
2971 | deleteInterface(iface); | |
2972 | } | |
2973 | ||
2974 | return deleteList.size() > 0; | |
2975 | } | |
2976 | ||
76720a09 VK |
2977 | /** |
2978 | * Update interface configuration | |
2979 | */ | |
dfed892b | 2980 | bool Node::updateInterfaceConfiguration(UINT32 rqid, int maskBits) |
eec253a8 | 2981 | { |
dfed892b VK |
2982 | sendPollerMsg(rqid, _T("Checking interface configuration...\r\n")); |
2983 | ||
2984 | bool hasChanges = deleteDuplicateInterfaces(rqid); | |
2985 | ||
2986 | InterfaceList *pIfList = getInterfaceList(); | |
eec253a8 VK |
2987 | if (pIfList != NULL) |
2988 | { | |
c42b4551 | 2989 | DbgPrintf(6, _T("Node::updateInterfaceConfiguration(%s [%u]): got %d interfaces"), m_name, m_id, pIfList->size()); |
eec253a8 VK |
2990 | |
2991 | // Find non-existing interfaces | |
db091a1f VK |
2992 | lockChildList(false); |
2993 | ObjectArray<Interface> deleteList(m_childList->size(), 8, false); | |
2994 | for(int i = 0; i < m_childList->size(); i++) | |
eec253a8 | 2995 | { |
db091a1f | 2996 | if (m_childList->get(i)->getObjectClass() == OBJECT_INTERFACE) |
eec253a8 | 2997 | { |
db091a1f | 2998 | Interface *pInterface = (Interface *)m_childList->get(i); |
9214177b VK |
2999 | if (!pInterface->isManuallyCreated()) |
3000 | { | |
dfed892b | 3001 | int j; |
a6312bd6 | 3002 | for(j = 0; j < pIfList->size(); j++) |
9214177b | 3003 | { |