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