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