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