06c376b87f07e606d0d270042c28401395bbffc5
[public/netxms.git] / src / server / core / objects.cpp
1 /*
2 ** NetXMS - Network Management System
3 ** Copyright (C) 2003-2017 Raden Solutions
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: objects.cpp
20 **
21 **/
22
23 #include "nxcore.h"
24
25 /**
26 * Global data
27 */
28 BOOL g_bModificationsLocked = FALSE;
29
30 Network NXCORE_EXPORTABLE *g_pEntireNet = NULL;
31 ServiceRoot NXCORE_EXPORTABLE *g_pServiceRoot = NULL;
32 TemplateRoot NXCORE_EXPORTABLE *g_pTemplateRoot = NULL;
33 PolicyRoot NXCORE_EXPORTABLE *g_pPolicyRoot = NULL;
34 NetworkMapRoot NXCORE_EXPORTABLE *g_pMapRoot = NULL;
35 DashboardRoot NXCORE_EXPORTABLE *g_pDashboardRoot = NULL;
36 BusinessServiceRoot NXCORE_EXPORTABLE *g_pBusinessServiceRoot = NULL;
37
38 UINT32 NXCORE_EXPORTABLE g_dwMgmtNode = 0;
39
40 Queue *g_pTemplateUpdateQueue = NULL;
41
42 ObjectIndex g_idxObjectById;
43 InetAddressIndex g_idxSubnetByAddr;
44 InetAddressIndex g_idxInterfaceByAddr;
45 ObjectIndex g_idxZoneByUIN;
46 ObjectIndex g_idxNodeById;
47 InetAddressIndex g_idxNodeByAddr;
48 ObjectIndex g_idxClusterById;
49 ObjectIndex g_idxMobileDeviceById;
50 ObjectIndex g_idxAccessPointById;
51 ObjectIndex g_idxConditionById;
52 ObjectIndex g_idxServiceCheckById;
53 ObjectIndex g_idxNetMapById;
54 ObjectIndex g_idxChassisById;
55 ObjectIndex g_idxSensorById;
56
57 /**
58 * Static data
59 */
60 static int m_iStatusCalcAlg = SA_CALCULATE_MOST_CRITICAL;
61 static int m_iStatusPropAlg = SA_PROPAGATE_UNCHANGED;
62 static int m_iFixedStatus; // Status if propagation is "Fixed"
63 static int m_iStatusShift; // Shift value for "shifted" status propagation
64 static int m_iStatusTranslation[4];
65 static int m_iStatusSingleThreshold;
66 static int m_iStatusThresholds[4];
67
68 /**
69 * Thread which apply template updates
70 */
71 static THREAD_RESULT THREAD_CALL ApplyTemplateThread(void *pArg)
72 {
73 DbgPrintf(1, _T("Apply template thread started"));
74 while(1)
75 {
76 TEMPLATE_UPDATE_INFO *pInfo = (TEMPLATE_UPDATE_INFO *)g_pTemplateUpdateQueue->getOrBlock();
77 if (pInfo == INVALID_POINTER_VALUE)
78 break;
79
80 DbgPrintf(5, _T("ApplyTemplateThread: template=%d(%s) updateType=%d target=%d removeDci=%s"),
81 pInfo->pTemplate->getId(), pInfo->pTemplate->getName(), pInfo->updateType, pInfo->targetId, pInfo->removeDCI ? _T("true") : _T("false"));
82 BOOL bSuccess = FALSE;
83 NetObj *dcTarget = FindObjectById(pInfo->targetId);
84 if (dcTarget != NULL)
85 {
86 if (dcTarget->isDataCollectionTarget())
87 {
88 BOOL lock1, lock2;
89
90 switch(pInfo->updateType)
91 {
92 case APPLY_TEMPLATE:
93 lock1 = pInfo->pTemplate->lockDCIList(0x7FFFFFFF, _T("SYSTEM"), NULL);
94 lock2 = ((DataCollectionTarget *)dcTarget)->lockDCIList(0x7FFFFFFF, _T("SYSTEM"), NULL);
95 if (lock1 && lock2)
96 {
97 pInfo->pTemplate->applyToTarget((DataCollectionTarget *)dcTarget);
98 bSuccess = TRUE;
99 }
100 if (lock1)
101 pInfo->pTemplate->unlockDCIList(0x7FFFFFFF);
102 if (lock2)
103 ((DataCollectionTarget *)dcTarget)->unlockDCIList(0x7FFFFFFF);
104 break;
105 case REMOVE_TEMPLATE:
106 if (((DataCollectionTarget *)dcTarget)->lockDCIList(0x7FFFFFFF, _T("SYSTEM"), NULL))
107 {
108 ((DataCollectionTarget *)dcTarget)->unbindFromTemplate(pInfo->pTemplate->getId(), pInfo->removeDCI);
109 ((DataCollectionTarget *)dcTarget)->unlockDCIList(0x7FFFFFFF);
110 bSuccess = TRUE;
111 }
112 break;
113 default:
114 bSuccess = TRUE;
115 break;
116 }
117 }
118 }
119
120 if (bSuccess)
121 {
122 DbgPrintf(8, _T("ApplyTemplateThread: success"));
123 pInfo->pTemplate->decRefCount();
124 free(pInfo);
125 }
126 else
127 {
128 DbgPrintf(8, _T("ApplyTemplateThread: failed"));
129 g_pTemplateUpdateQueue->put(pInfo); // Requeue
130 ThreadSleepMs(500);
131 }
132 }
133
134 DbgPrintf(1, _T("Apply template thread stopped"));
135 return THREAD_OK;
136 }
137
138 /**
139 * Update DCI cache for all data collection targets referenced by given index
140 */
141 static void UpdateDataCollectionCache(ObjectIndex *idx)
142 {
143 ObjectArray<NetObj> *objects = idx->getObjects(true);
144 for(int i = 0; i < objects->size(); i++)
145 {
146 DataCollectionTarget *t = (DataCollectionTarget *)objects->get(i);
147 t->updateDciCache();
148 t->decRefCount();
149 }
150 delete objects;
151 }
152
153 /**
154 * DCI cache loading thread
155 */
156 static THREAD_RESULT THREAD_CALL CacheLoadingThread(void *pArg)
157 {
158 DbgPrintf(1, _T("Started caching of DCI values"));
159
160 UpdateDataCollectionCache(&g_idxNodeById);
161 UpdateDataCollectionCache(&g_idxClusterById);
162 UpdateDataCollectionCache(&g_idxMobileDeviceById);
163 UpdateDataCollectionCache(&g_idxAccessPointById);
164 UpdateDataCollectionCache(&g_idxChassisById);
165 UpdateDataCollectionCache(&g_idxSensorById);
166
167 DbgPrintf(1, _T("Finished caching of DCI values"));
168 return THREAD_OK;
169 }
170
171 /**
172 * Callback for map update thread
173 */
174 static void UpdateMapCallback(NetObj *object, void *data)
175 {
176 ((NetworkMap *)object)->updateContent();
177 ((NetworkMap *)object)->calculateCompoundStatus();
178 }
179
180 /**
181 * Map update thread
182 */
183 static THREAD_RESULT THREAD_CALL MapUpdateThread(void *pArg)
184 {
185 DbgPrintf(2, _T("Map update thread started"));
186 while(!SleepAndCheckForShutdown(60))
187 {
188 DbgPrintf(5, _T("Updating maps..."));
189 g_idxNetMapById.forEach(UpdateMapCallback, NULL);
190 DbgPrintf(5, _T("Map update completed"));
191 }
192 DbgPrintf(2, _T("Map update thread stopped"));
193 return THREAD_OK;
194 }
195
196 /**
197 * Initialize objects infrastructure
198 */
199 void ObjectsInit()
200 {
201 // Load default status calculation info
202 m_iStatusCalcAlg = ConfigReadInt(_T("StatusCalculationAlgorithm"), SA_CALCULATE_MOST_CRITICAL);
203 m_iStatusPropAlg = ConfigReadInt(_T("StatusPropagationAlgorithm"), SA_PROPAGATE_UNCHANGED);
204 m_iFixedStatus = ConfigReadInt(_T("FixedStatusValue"), STATUS_NORMAL);
205 m_iStatusShift = ConfigReadInt(_T("StatusShift"), 0);
206 ConfigReadByteArray(_T("StatusTranslation"), m_iStatusTranslation, 4, STATUS_WARNING);
207 m_iStatusSingleThreshold = ConfigReadInt(_T("StatusSingleThreshold"), 75);
208 ConfigReadByteArray(_T("StatusThresholds"), m_iStatusThresholds, 4, 50);
209
210 g_pTemplateUpdateQueue = new Queue;
211
212 // Create "Entire Network" object
213 g_pEntireNet = new Network;
214 NetObjInsert(g_pEntireNet, false, false);
215
216 // Create "Service Root" object
217 g_pServiceRoot = new ServiceRoot;
218 NetObjInsert(g_pServiceRoot, false, false);
219
220 // Create "Template Root" object
221 g_pTemplateRoot = new TemplateRoot;
222 NetObjInsert(g_pTemplateRoot, false, false);
223
224 // Create "Policy Root" object
225 g_pPolicyRoot = new PolicyRoot;
226 NetObjInsert(g_pPolicyRoot, false, false);
227
228 // Create "Network Maps Root" object
229 g_pMapRoot = new NetworkMapRoot;
230 NetObjInsert(g_pMapRoot, false, false);
231
232 // Create "Dashboard Root" object
233 g_pDashboardRoot = new DashboardRoot;
234 NetObjInsert(g_pDashboardRoot, false, false);
235
236 // Create "Business Service Root" object
237 g_pBusinessServiceRoot = new BusinessServiceRoot;
238 NetObjInsert(g_pBusinessServiceRoot, false, false);
239
240 DbgPrintf(1, _T("Built-in objects created"));
241
242 // Initialize service checks
243 SlmCheck::init();
244 }
245
246 /**
247 * Insert new object into network
248 */
249 void NetObjInsert(NetObj *pObject, bool newObject, bool importedObject)
250 {
251 if (newObject)
252 {
253 // Assign unique ID to new object
254 pObject->setId(CreateUniqueId(IDG_NETWORK_OBJECT));
255 if (!importedObject && pObject->getGuid().isNull()) // imported objects already have valid GUID
256 pObject->generateGuid();
257
258 // Create tables for storing data collection values
259 if (pObject->isDataCollectionTarget())
260 {
261 TCHAR szQuery[256], szQueryTemplate[256];
262 UINT32 i;
263
264 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
265
266 MetaDataReadStr(_T("IDataTableCreationCommand"), szQueryTemplate, 255, _T(""));
267 _sntprintf(szQuery, sizeof(szQuery) / sizeof(TCHAR), szQueryTemplate, pObject->getId());
268 DBQuery(hdb, szQuery);
269
270 for(i = 0; i < 10; i++)
271 {
272 _sntprintf(szQuery, sizeof(szQuery) / sizeof(TCHAR), _T("IDataIndexCreationCommand_%d"), i);
273 MetaDataReadStr(szQuery, szQueryTemplate, 255, _T(""));
274 if (szQueryTemplate[0] != 0)
275 {
276 _sntprintf(szQuery, sizeof(szQuery) / sizeof(TCHAR), szQueryTemplate, pObject->getId(), pObject->getId());
277 DBQuery(hdb, szQuery);
278 }
279 }
280
281 for(i = 0; i < 10; i++)
282 {
283 _sntprintf(szQuery, sizeof(szQuery) / sizeof(TCHAR), _T("TDataTableCreationCommand_%d"), i);
284 MetaDataReadStr(szQuery, szQueryTemplate, 255, _T(""));
285 if (szQueryTemplate[0] != 0)
286 {
287 _sntprintf(szQuery, sizeof(szQuery) / sizeof(TCHAR), szQueryTemplate, pObject->getId(), pObject->getId());
288 DBQuery(hdb, szQuery);
289 }
290 }
291
292 for(i = 0; i < 10; i++)
293 {
294 _sntprintf(szQuery, sizeof(szQuery) / sizeof(TCHAR), _T("TDataIndexCreationCommand_%d"), i);
295 MetaDataReadStr(szQuery, szQueryTemplate, 255, _T(""));
296 if (szQueryTemplate[0] != 0)
297 {
298 _sntprintf(szQuery, sizeof(szQuery) / sizeof(TCHAR), szQueryTemplate, pObject->getId(), pObject->getId());
299 DBQuery(hdb, szQuery);
300 }
301 }
302
303 DBConnectionPoolReleaseConnection(hdb);
304 }
305 }
306 g_idxObjectById.put(pObject->getId(), pObject);
307 if (!pObject->isDeleted())
308 {
309 switch(pObject->getObjectClass())
310 {
311 case OBJECT_GENERIC:
312 case OBJECT_NETWORK:
313 case OBJECT_CONTAINER:
314 case OBJECT_SERVICEROOT:
315 case OBJECT_NETWORKSERVICE:
316 case OBJECT_TEMPLATE:
317 case OBJECT_TEMPLATEGROUP:
318 case OBJECT_TEMPLATEROOT:
319 case OBJECT_VPNCONNECTOR:
320 case OBJECT_POLICYGROUP:
321 case OBJECT_POLICYROOT:
322 case OBJECT_AGENTPOLICY:
323 case OBJECT_AGENTPOLICY_CONFIG:
324 case OBJECT_AGENTPOLICY_LOGPARSER:
325 case OBJECT_NETWORKMAPROOT:
326 case OBJECT_NETWORKMAPGROUP:
327 case OBJECT_DASHBOARDROOT:
328 case OBJECT_DASHBOARDGROUP:
329 case OBJECT_DASHBOARD:
330 case OBJECT_BUSINESSSERVICEROOT:
331 case OBJECT_BUSINESSSERVICE:
332 case OBJECT_NODELINK:
333 case OBJECT_RACK:
334 break;
335 case OBJECT_NODE:
336 g_idxNodeById.put(pObject->getId(), pObject);
337 if (!(((Node *)pObject)->getFlags() & NF_REMOTE_AGENT))
338 {
339 if (IsZoningEnabled())
340 {
341 Zone *zone = (Zone *)g_idxZoneByUIN.get(((Node *)pObject)->getZoneUIN());
342 if (zone != NULL)
343 {
344 zone->addToIndex((Node *)pObject);
345 }
346 else
347 {
348 DbgPrintf(2, _T("Cannot find zone object with GUID=%d for node object %s [%d]"),
349 (int)((Node *)pObject)->getZoneUIN(), pObject->getName(), (int)pObject->getId());
350 }
351 }
352 else
353 {
354 if (((Node *)pObject)->getIpAddress().isValidUnicast())
355 g_idxNodeByAddr.put(((Node *)pObject)->getIpAddress(), pObject);
356 }
357 }
358 break;
359 case OBJECT_CLUSTER:
360 g_idxClusterById.put(pObject->getId(), pObject);
361 break;
362 case OBJECT_MOBILEDEVICE:
363 g_idxMobileDeviceById.put(pObject->getId(), pObject);
364 break;
365 case OBJECT_ACCESSPOINT:
366 g_idxAccessPointById.put(pObject->getId(), pObject);
367 MacDbAddAccessPoint((AccessPoint *)pObject);
368 break;
369 case OBJECT_CHASSIS:
370 g_idxChassisById.put(pObject->getId(), pObject);
371 break;
372 case OBJECT_SUBNET:
373 if (((Subnet *)pObject)->getIpAddress().isValidUnicast())
374 {
375 if (IsZoningEnabled())
376 {
377 Zone *zone = (Zone *)g_idxZoneByUIN.get(((Subnet *)pObject)->getZoneUIN());
378 if (zone != NULL)
379 {
380 zone->addToIndex((Subnet *)pObject);
381 }
382 else
383 {
384 DbgPrintf(2, _T("Cannot find zone object with GUID=%d for subnet object %s [%d]"),
385 (int)((Subnet *)pObject)->getZoneUIN(), pObject->getName(), (int)pObject->getId());
386 }
387 }
388 else
389 {
390 g_idxSubnetByAddr.put(((Subnet *)pObject)->getIpAddress(), pObject);
391 }
392 if (newObject)
393 {
394 PostEvent(EVENT_SUBNET_ADDED, g_dwMgmtNode, "isAd", pObject->getId(), pObject->getName(),
395 &((Subnet *)pObject)->getIpAddress(), ((Subnet *)pObject)->getIpAddress().getMaskBits());
396 }
397 }
398 break;
399 case OBJECT_INTERFACE:
400 if (!((Interface *)pObject)->isExcludedFromTopology())
401 {
402 if (IsZoningEnabled())
403 {
404 Zone *zone = (Zone *)g_idxZoneByUIN.get(((Interface *)pObject)->getZoneUIN());
405 if (zone != NULL)
406 {
407 zone->addToIndex((Interface *)pObject);
408 }
409 else
410 {
411 DbgPrintf(2, _T("Cannot find zone object with GUID=%d for interface object %s [%d]"),
412 (int)((Interface *)pObject)->getZoneUIN(), pObject->getName(), (int)pObject->getId());
413 }
414 }
415 else
416 {
417 g_idxInterfaceByAddr.put(((Interface *)pObject)->getIpAddressList(), pObject);
418 }
419 }
420 MacDbAddInterface((Interface *)pObject);
421 break;
422 case OBJECT_ZONE:
423 g_idxZoneByUIN.put(((Zone *)pObject)->getUIN(), pObject);
424 break;
425 case OBJECT_CONDITION:
426 g_idxConditionById.put(pObject->getId(), pObject);
427 break;
428 case OBJECT_SLMCHECK:
429 g_idxServiceCheckById.put(pObject->getId(), pObject);
430 break;
431 case OBJECT_NETWORKMAP:
432 g_idxNetMapById.put(pObject->getId(), pObject);
433 break;
434 case OBJECT_SENSOR:
435 g_idxSensorById.put(pObject->getId(), pObject);
436 break;
437 default:
438 {
439 bool processed = false;
440 for(UINT32 i = 0; i < g_dwNumModules; i++)
441 {
442 if (g_pModuleList[i].pfNetObjInsert != NULL)
443 {
444 if (g_pModuleList[i].pfNetObjInsert(pObject))
445 processed = true;
446 }
447 }
448 if (!processed)
449 nxlog_write(MSG_BAD_NETOBJ_TYPE, EVENTLOG_ERROR_TYPE, "d", pObject->getObjectClass());
450 }
451 break;
452 }
453 }
454
455 // Notify modules about object creation
456 if (newObject)
457 {
458 CALL_ALL_MODULES(pfPostObjectCreate, (pObject));
459 }
460 else
461 {
462 CALL_ALL_MODULES(pfPostObjectLoad, (pObject));
463 }
464 }
465
466 /**
467 * Delete object from indexes
468 * If object has an IP address, this function will delete it from
469 * appropriate index. Normally this function should be called from
470 * NetObj::deleteObject() method.
471 */
472 void NetObjDeleteFromIndexes(NetObj *pObject)
473 {
474 switch(pObject->getObjectClass())
475 {
476 case OBJECT_GENERIC:
477 case OBJECT_NETWORK:
478 case OBJECT_CONTAINER:
479 case OBJECT_SERVICEROOT:
480 case OBJECT_NETWORKSERVICE:
481 case OBJECT_TEMPLATE:
482 case OBJECT_TEMPLATEGROUP:
483 case OBJECT_TEMPLATEROOT:
484 case OBJECT_VPNCONNECTOR:
485 case OBJECT_POLICYGROUP:
486 case OBJECT_POLICYROOT:
487 case OBJECT_AGENTPOLICY:
488 case OBJECT_AGENTPOLICY_CONFIG:
489 case OBJECT_NETWORKMAPROOT:
490 case OBJECT_NETWORKMAPGROUP:
491 case OBJECT_DASHBOARDROOT:
492 case OBJECT_DASHBOARDGROUP:
493 case OBJECT_DASHBOARD:
494 case OBJECT_BUSINESSSERVICEROOT:
495 case OBJECT_BUSINESSSERVICE:
496 case OBJECT_NODELINK:
497 case OBJECT_RACK:
498 break;
499 case OBJECT_NODE:
500 g_idxNodeById.remove(pObject->getId());
501 if (!(((Node *)pObject)->getFlags() & NF_REMOTE_AGENT))
502 {
503 if (IsZoningEnabled())
504 {
505 Zone *zone = (Zone *)g_idxZoneByUIN.get(((Node *)pObject)->getZoneUIN());
506 if (zone != NULL)
507 {
508 zone->removeFromIndex((Node *)pObject);
509 }
510 else
511 {
512 DbgPrintf(2, _T("Cannot find zone object with GUID=%d for node object %s [%d]"),
513 (int)((Node *)pObject)->getZoneUIN(), pObject->getName(), (int)pObject->getId());
514 }
515 }
516 else
517 {
518 if (((Node *)pObject)->getIpAddress().isValidUnicast())
519 g_idxNodeByAddr.remove(((Node *)pObject)->getIpAddress());
520 }
521 }
522 break;
523 case OBJECT_CLUSTER:
524 g_idxClusterById.remove(pObject->getId());
525 break;
526 case OBJECT_MOBILEDEVICE:
527 g_idxMobileDeviceById.remove(pObject->getId());
528 break;
529 case OBJECT_ACCESSPOINT:
530 g_idxAccessPointById.remove(pObject->getId());
531 MacDbRemove(((AccessPoint *)pObject)->getMacAddr());
532 break;
533 case OBJECT_CHASSIS:
534 g_idxChassisById.remove(pObject->getId());
535 break;
536 case OBJECT_SUBNET:
537 if (((Subnet *)pObject)->getIpAddress().isValidUnicast())
538 {
539 if (IsZoningEnabled())
540 {
541 Zone *zone = (Zone *)g_idxZoneByUIN.get(((Subnet *)pObject)->getZoneUIN());
542 if (zone != NULL)
543 {
544 zone->removeFromIndex((Subnet *)pObject);
545 }
546 else
547 {
548 DbgPrintf(2, _T("Cannot find zone object with GUID=%d for subnet object %s [%d]"),
549 (int)((Subnet *)pObject)->getZoneUIN(), pObject->getName(), (int)pObject->getId());
550 }
551 }
552 else
553 {
554 g_idxSubnetByAddr.remove(((Subnet *)pObject)->getIpAddress());
555 }
556 }
557 break;
558 case OBJECT_INTERFACE:
559 if (IsZoningEnabled())
560 {
561 Zone *zone = (Zone *)g_idxZoneByUIN.get(((Interface *)pObject)->getZoneUIN());
562 if (zone != NULL)
563 {
564 zone->removeFromIndex((Interface *)pObject);
565 }
566 else
567 {
568 DbgPrintf(2, _T("Cannot find zone object with GUID=%d for interface object %s [%d]"),
569 (int)((Interface *)pObject)->getZoneUIN(), pObject->getName(), (int)pObject->getId());
570 }
571 }
572 else
573 {
574 const ObjectArray<InetAddress> *list = ((Interface *)pObject)->getIpAddressList()->getList();
575 for(int i = 0; i < list->size(); i++)
576 {
577 InetAddress *addr = list->get(i);
578 if (addr->isValidUnicast())
579 {
580 NetObj *o = g_idxInterfaceByAddr.get(*addr);
581 if ((o != NULL) && (o->getId() == pObject->getId()))
582 {
583 g_idxInterfaceByAddr.remove(*addr);
584 }
585 }
586 }
587 }
588 MacDbRemove(((Interface *)pObject)->getMacAddr());
589 break;
590 case OBJECT_ZONE:
591 g_idxZoneByUIN.remove(((Zone *)pObject)->getUIN());
592 break;
593 case OBJECT_CONDITION:
594 g_idxConditionById.remove(pObject->getId());
595 break;
596 case OBJECT_SLMCHECK:
597 g_idxServiceCheckById.remove(pObject->getId());
598 break;
599 case OBJECT_NETWORKMAP:
600 g_idxNetMapById.remove(pObject->getId());
601 break;
602 case OBJECT_SENSOR:
603 g_idxSensorById.remove(pObject->getId());
604 break;
605 default:
606 {
607 bool processed = false;
608 for(UINT32 i = 0; i < g_dwNumModules; i++)
609 {
610 if (g_pModuleList[i].pfNetObjDelete != NULL)
611 {
612 if (g_pModuleList[i].pfNetObjDelete(pObject))
613 processed = true;
614 }
615 }
616 if (!processed)
617 nxlog_write(MSG_BAD_NETOBJ_TYPE, EVENTLOG_ERROR_TYPE, "d", pObject->getObjectClass());
618 }
619 break;
620 }
621 }
622
623 /**
624 * Find access point by MAC address
625 */
626 AccessPoint NXCORE_EXPORTABLE *FindAccessPointByMAC(const BYTE *macAddr)
627 {
628 if (!memcmp(macAddr, "\x00\x00\x00\x00\x00\x00", 6))
629 return NULL;
630
631 NetObj *object = MacDbFind(macAddr);
632 return ((object != NULL) && (object->getObjectClass() == OBJECT_ACCESSPOINT)) ? (AccessPoint *)object : NULL;
633 }
634
635 /**
636 * Mobile device id comparator
637 */
638 static bool DeviceIdComparator(NetObj *object, void *deviceId)
639 {
640 return ((object->getObjectClass() == OBJECT_MOBILEDEVICE) && !object->isDeleted() &&
641 !_tcscmp((const TCHAR *)deviceId, ((MobileDevice *)object)->getDeviceId()));
642 }
643
644 /**
645 * Find mobile device by device ID
646 */
647 MobileDevice NXCORE_EXPORTABLE *FindMobileDeviceByDeviceID(const TCHAR *deviceId)
648 {
649 if ((deviceId == NULL) || (*deviceId == 0))
650 return NULL;
651
652 return (MobileDevice *)g_idxMobileDeviceById.find(DeviceIdComparator, (void *)deviceId);
653 }
654
655 static Node *FindNodeByIPInternal(UINT32 zoneUIN, const InetAddress& ipAddr)
656 {
657 Zone *zone = IsZoningEnabled() ? (Zone *)g_idxZoneByUIN.get(zoneUIN) : NULL;
658
659 Node *node = NULL;
660 if (IsZoningEnabled())
661 {
662 if (zone != NULL)
663 {
664 node = zone->getNodeByAddr(ipAddr);
665 }
666 }
667 else
668 {
669 node = (Node *)g_idxNodeByAddr.get(ipAddr);
670 }
671 if (node != NULL)
672 return node;
673
674 Interface *iface = NULL;
675 if (IsZoningEnabled())
676 {
677 if (zone != NULL)
678 {
679 iface = zone->getInterfaceByAddr(ipAddr);
680 }
681 }
682 else
683 {
684 iface = (Interface *)g_idxInterfaceByAddr.get(ipAddr);
685 }
686 return (iface != NULL) ? iface->getParentNode() : NULL;
687 }
688
689 /**
690 * Data for node find callback
691 */
692 struct NodeFindCBData
693 {
694 const InetAddress *addr;
695 Node *node;
696 };
697
698 /**
699 * Callback for finding node in all zones
700 */
701 static bool NodeFindCB(NetObj *zone, void *data)
702 {
703 Node *node = ((Zone *)zone)->getNodeByAddr(*((NodeFindCBData *)data)->addr);
704 if (node == NULL)
705 {
706 Interface *iface = ((Zone *)zone)->getInterfaceByAddr(*((NodeFindCBData *)data)->addr);
707 if (iface != NULL)
708 node = iface->getParentNode();
709 }
710
711 if (node == NULL)
712 return false;
713
714 ((NodeFindCBData *)data)->node = node;
715 return true;
716 }
717
718 /**
719 * Find node by IP address
720 */
721 Node NXCORE_EXPORTABLE *FindNodeByIP(UINT32 zoneUIN, const InetAddress& ipAddr)
722 {
723 if (!ipAddr.isValidUnicast())
724 return NULL;
725
726 if ((zoneUIN == ALL_ZONES) && IsZoningEnabled())
727 {
728 NodeFindCBData data;
729 data.addr = &ipAddr;
730 data.node = NULL;
731 g_idxZoneByUIN.find(NodeFindCB, &data);
732 return data.node;
733 }
734 else
735 {
736 return FindNodeByIPInternal(zoneUIN, ipAddr);
737 }
738 }
739
740 /**
741 * Find node by IP address using first match from IP address list
742 */
743 Node NXCORE_EXPORTABLE *FindNodeByIP(UINT32 zoneUIN, const InetAddressList *ipAddrList)
744 {
745 for(int i = 0; i < ipAddrList->size(); i++)
746 {
747 Node *node = FindNodeByIP(zoneUIN, ipAddrList->get(i));
748 if (node != NULL)
749 return node;
750 }
751 return NULL;
752 }
753
754 /**
755 * Find interface by IP address
756 */
757 Interface NXCORE_EXPORTABLE *FindInterfaceByIP(UINT32 zoneUIN, const InetAddress& ipAddr)
758 {
759 if (!ipAddr.isValidUnicast())
760 return NULL;
761
762 Interface *iface = NULL;
763 if (IsZoningEnabled())
764 {
765 Zone *zone = (Zone *)g_idxZoneByUIN.get(zoneUIN);
766 if (zone != NULL)
767 {
768 iface = zone->getInterfaceByAddr(ipAddr);
769 }
770 }
771 else
772 {
773 iface = (Interface *)g_idxInterfaceByAddr.get(ipAddr);
774 }
775 return iface;
776 }
777
778 /**
779 * Find node by MAC address
780 */
781 Node NXCORE_EXPORTABLE *FindNodeByMAC(const BYTE *macAddr)
782 {
783 Interface *pInterface = FindInterfaceByMAC(macAddr);
784 return (pInterface != NULL) ? pInterface->getParentNode() : NULL;
785 }
786
787 /**
788 * Find interface by MAC address
789 */
790 Interface NXCORE_EXPORTABLE *FindInterfaceByMAC(const BYTE *macAddr)
791 {
792 if (!memcmp(macAddr, "\x00\x00\x00\x00\x00\x00", 6))
793 return NULL;
794
795 NetObj *object = MacDbFind(macAddr);
796 return ((object != NULL) && (object->getObjectClass() == OBJECT_INTERFACE)) ? (Interface *)object : NULL;
797 }
798
799 struct NodeFindHostnameData
800 {
801 TCHAR *hostname;
802 UINT32 zoneUIN;
803 };
804
805 /**
806 * Interface description comparator
807 */
808 static bool HostnameComparator(NetObj *object, void *data)
809 {
810 TCHAR primaryName[MAX_DNS_NAME];
811 if ((object->getObjectClass() == OBJECT_NODE) && !object->isDeleted())
812 {
813 _tcscpy(primaryName, ((Node *)object)->getPrimaryName());
814 _tcsupr(primaryName);
815 _tcsupr(((NodeFindHostnameData *)data)->hostname);
816 }
817 else
818 return false;
819
820 return ((_tcsstr(primaryName, ((NodeFindHostnameData *)data)->hostname) != NULL) &&
821 (IsZoningEnabled() ? (((Node *)object)->getZoneUIN() == ((NodeFindHostnameData *)data)->zoneUIN) : true));
822 }
823
824 /**
825 * Find a list of nodes that contain the hostname
826 */
827 ObjectArray<NetObj> *FindNodesByHostname(TCHAR *hostname, UINT32 zoneUIN)
828 {
829 NodeFindHostnameData data;
830 data.hostname = hostname;
831 data.zoneUIN = zoneUIN;
832
833 ObjectArray<NetObj> *nodes = g_idxNodeById.findObjects(HostnameComparator, &data);
834 return nodes;
835 }
836
837 /**
838 * Interface description comparator
839 */
840 static bool DescriptionComparator(NetObj *object, void *description)
841 {
842 return ((object->getObjectClass() == OBJECT_INTERFACE) && !object->isDeleted() &&
843 !_tcscmp((const TCHAR *)description, ((Interface *)object)->getDescription()));
844 }
845
846 /**
847 * Find interface by description
848 */
849 Interface NXCORE_EXPORTABLE *FindInterfaceByDescription(const TCHAR *description)
850 {
851 return (Interface *)g_idxObjectById.find(DescriptionComparator, (void *)description);
852 }
853
854 /**
855 * LLDP ID comparator
856 */
857 static bool LldpIdComparator(NetObj *object, void *lldpId)
858 {
859 const TCHAR *id = ((Node *)object)->getLLDPNodeId();
860 return (id != NULL) && !_tcscmp(id, (const TCHAR *)lldpId);
861 }
862
863 /**
864 * Find node by LLDP ID
865 */
866 Node NXCORE_EXPORTABLE *FindNodeByLLDPId(const TCHAR *lldpId)
867 {
868 return (Node *)g_idxNodeById.find(LldpIdComparator, (void *)lldpId);
869 }
870
871 /**
872 * SNMP sysName comparator
873 */
874 static bool SysNameComparator(NetObj *object, void *sysName)
875 {
876 const TCHAR *n = ((Node *)object)->getSysName();
877 return (n != NULL) && !_tcscmp(n, (const TCHAR *)sysName);
878 }
879
880 /**
881 * Find node by SNMP sysName
882 */
883 Node NXCORE_EXPORTABLE *FindNodeBySysName(const TCHAR *sysName)
884 {
885 if ((sysName == NULL) || (sysName[0] == 0))
886 return NULL;
887
888 // return NULL if multiple nodes with same sysName found
889 ObjectArray<NetObj> *objects = g_idxNodeById.findObjects(SysNameComparator, (void *)sysName);
890 Node *node = (objects->size() == 1) ? (Node *)objects->get(0) : NULL;
891 delete objects;
892 return node;
893 }
894
895 /**
896 * Bridge ID comparator
897 */
898 static bool BridgeIdComparator(NetObj *object, void *bridgeId)
899 {
900 return ((Node *)object)->isBridge() && !memcmp(((Node *)object)->getBridgeId(), bridgeId, MAC_ADDR_LENGTH);
901 }
902
903 /**
904 * Find node by bridge ID (bridge base address)
905 */
906 Node NXCORE_EXPORTABLE *FindNodeByBridgeId(const BYTE *bridgeId)
907 {
908 return (Node *)g_idxNodeById.find(BridgeIdComparator, (void *)bridgeId);
909 }
910
911 /**
912 * Find subnet by IP address
913 */
914 Subnet NXCORE_EXPORTABLE *FindSubnetByIP(UINT32 zoneUIN, const InetAddress& ipAddr)
915 {
916 if (!ipAddr.isValidUnicast())
917 return NULL;
918
919 Subnet *subnet = NULL;
920 if (IsZoningEnabled())
921 {
922 Zone *zone = (Zone *)g_idxZoneByUIN.get(zoneUIN);
923 if (zone != NULL)
924 {
925 subnet = zone->getSubnetByAddr(ipAddr);
926 }
927 }
928 else
929 {
930 subnet = (Subnet *)g_idxSubnetByAddr.get(ipAddr);
931 }
932 return subnet;
933 }
934
935 /**
936 * Subnet matching data
937 */
938 struct SUBNET_MATCHING_DATA
939 {
940 InetAddress ipAddr; // IP address to find subnet for
941 int maskLen; // Current match mask length
942 Subnet *subnet; // search result
943 };
944
945 /**
946 * Subnet matching callback
947 */
948 static void SubnetMatchCallback(const InetAddress& addr, NetObj *object, void *arg)
949 {
950 SUBNET_MATCHING_DATA *data = (SUBNET_MATCHING_DATA *)arg;
951 if (((Subnet *)object)->getIpAddress().contain(data->ipAddr))
952 {
953 int maskLen = ((Subnet *)object)->getIpAddress().getMaskBits();
954 if (maskLen > data->maskLen)
955 {
956 data->maskLen = maskLen;
957 data->subnet = (Subnet *)object;
958 }
959 }
960 }
961
962 /**
963 * Find subnet for given IP address
964 */
965 Subnet NXCORE_EXPORTABLE *FindSubnetForNode(UINT32 zoneUIN, const InetAddress& nodeAddr)
966 {
967 if (!nodeAddr.isValidUnicast())
968 return NULL;
969
970 SUBNET_MATCHING_DATA matchData;
971 matchData.ipAddr = nodeAddr;
972 matchData.maskLen = -1;
973 matchData.subnet = NULL;
974 if (IsZoningEnabled())
975 {
976 Zone *zone = (Zone *)g_idxZoneByUIN.get(zoneUIN);
977 if (zone != NULL)
978 {
979 zone->forEachSubnet(SubnetMatchCallback, &matchData);
980 }
981 }
982 else
983 {
984 g_idxSubnetByAddr.forEach(SubnetMatchCallback, &matchData);
985 }
986 return matchData.subnet;
987 }
988
989 /**
990 * Find object by ID
991 */
992 NetObj NXCORE_EXPORTABLE *FindObjectById(UINT32 dwId, int objClass)
993 {
994 NetObj *object = g_idxObjectById.get(dwId);
995 if ((object == NULL) || (objClass == -1))
996 return object;
997 return (objClass == object->getObjectClass()) ? object : NULL;
998 }
999
1000 /**
1001 * Get object name by ID
1002 */
1003 const TCHAR NXCORE_EXPORTABLE *GetObjectName(DWORD id, const TCHAR *defaultName)
1004 {
1005 NetObj *object = g_idxObjectById.get(id);
1006 return (object != NULL) ? object->getName() : defaultName;
1007 }
1008
1009 /**
1010 * Generic object finding method
1011 */
1012 NetObj NXCORE_EXPORTABLE *FindObject(bool (* comparator)(NetObj *, void *), void *userData, int objClass)
1013 {
1014 ObjectIndex *index;
1015 switch(objClass)
1016 {
1017 case OBJECT_ACCESSPOINT:
1018 index = &g_idxAccessPointById;
1019 break;
1020 case OBJECT_CLUSTER:
1021 index = &g_idxClusterById;
1022 break;
1023 case OBJECT_MOBILEDEVICE:
1024 index = &g_idxMobileDeviceById;
1025 break;
1026 case OBJECT_NODE:
1027 index = &g_idxNodeById;
1028 break;
1029 case OBJECT_ZONE:
1030 index = &g_idxZoneByUIN;
1031 break;
1032 case OBJECT_SENSOR:
1033 index = &g_idxSensorById;
1034 break;
1035 default:
1036 index = &g_idxObjectById;
1037 break;
1038 }
1039 NetObj *object = index->find(comparator, userData);
1040 return ((object == NULL) || (objClass == -1)) ? object : ((object->getObjectClass() == objClass) ? object : NULL);
1041 }
1042
1043 /**
1044 * Callback data for FindObjectByName
1045 */
1046 struct __find_object_by_name_data
1047 {
1048 int objClass;
1049 const TCHAR *name;
1050 };
1051
1052 /**
1053 * Object name comparator for FindObjectByName
1054 */
1055 static bool ObjectNameComparator(NetObj *object, void *data)
1056 {
1057 struct __find_object_by_name_data *fd = (struct __find_object_by_name_data *)data;
1058 return ((fd->objClass == -1) || (fd->objClass == object->getObjectClass())) &&
1059 !object->isDeleted() && !_tcsicmp(object->getName(), fd->name);
1060 }
1061
1062 /**
1063 * Find object by name
1064 */
1065 NetObj NXCORE_EXPORTABLE *FindObjectByName(const TCHAR *name, int objClass)
1066 {
1067 struct __find_object_by_name_data data;
1068 data.objClass = objClass;
1069 data.name = name;
1070 return FindObject(ObjectNameComparator, &data, objClass);
1071 }
1072
1073 /**
1074 * Callback data for FindObjectByGUID
1075 */
1076 struct __find_object_by_guid_data
1077 {
1078 int objClass;
1079 uuid guid;
1080 };
1081
1082 /**
1083 * GUID comparator for FindObjectByGUID
1084 */
1085 static bool ObjectGuidComparator(NetObj *object, void *data)
1086 {
1087 struct __find_object_by_guid_data *fd = (struct __find_object_by_guid_data *)data;
1088 return ((fd->objClass == -1) || (fd->objClass == object->getObjectClass())) &&
1089 !object->isDeleted() && object->getGuid().equals(fd->guid);
1090 }
1091
1092 /**
1093 * Find object by GUID
1094 */
1095 NetObj NXCORE_EXPORTABLE *FindObjectByGUID(const uuid& guid, int objClass)
1096 {
1097 struct __find_object_by_guid_data data;
1098 data.objClass = objClass;
1099 data.guid = guid;
1100 return FindObject(ObjectGuidComparator, &data, objClass);
1101 }
1102
1103 /**
1104 * Template name comparator for FindTemplateByName
1105 */
1106 static bool TemplateNameComparator(NetObj *object, void *name)
1107 {
1108 return (object->getObjectClass() == OBJECT_TEMPLATE) && !object->isDeleted() && !_tcsicmp(object->getName(), (const TCHAR *)name);
1109 }
1110
1111 /**
1112 * Find template object by name
1113 */
1114 Template NXCORE_EXPORTABLE *FindTemplateByName(const TCHAR *pszName)
1115 {
1116 return (Template *)g_idxObjectById.find(TemplateNameComparator, (void *)pszName);
1117 }
1118
1119 /**
1120 * Data structure for IsClusterIP callback
1121 */
1122 struct __cluster_ip_data
1123 {
1124 InetAddress ipAddr;
1125 UINT32 zoneUIN;
1126 };
1127
1128 /**
1129 * Cluster IP comparator - returns true if given address in given zone is cluster IP address
1130 */
1131 static bool ClusterIPComparator(NetObj *object, void *data)
1132 {
1133 struct __cluster_ip_data *d = (struct __cluster_ip_data *)data;
1134 return (object->getObjectClass() == OBJECT_CLUSTER) && !object->isDeleted() &&
1135 (((Cluster *)object)->getZoneUIN() == d->zoneUIN) &&
1136 (((Cluster *)object)->isVirtualAddr(d->ipAddr) ||
1137 ((Cluster *)object)->isSyncAddr(d->ipAddr));
1138 }
1139
1140 /**
1141 * Check if given IP address is used by cluster (it's either
1142 * resource IP or located on one of sync subnets)
1143 */
1144 bool NXCORE_EXPORTABLE IsClusterIP(UINT32 zoneUIN, const InetAddress& ipAddr)
1145 {
1146 struct __cluster_ip_data data;
1147 data.zoneUIN = zoneUIN;
1148 data.ipAddr = ipAddr;
1149 return g_idxObjectById.find(ClusterIPComparator, &data) != NULL;
1150 }
1151
1152 /**
1153 * Find zone object by UIN (unique identification number)
1154 */
1155 Zone NXCORE_EXPORTABLE *FindZoneByUIN(UINT32 uin)
1156 {
1157 return (Zone *)g_idxZoneByUIN.get(uin);
1158 }
1159
1160 /**
1161 * Zone ID selector data
1162 */
1163 static Mutex s_zoneUinSelectorLock;
1164 static IntegerArray<UINT32> s_zoneUinSelectorHistory;
1165
1166 /**
1167 * Find unused zone UIN
1168 */
1169 UINT32 FindUnusedZoneUIN()
1170 {
1171 UINT32 uin = 0;
1172 s_zoneUinSelectorLock.lock();
1173 for(UINT32 i = 1; i < 0x7FFFFFFF; i++)
1174 {
1175 if (g_idxZoneByUIN.get(i) != NULL)
1176 continue;
1177 if (s_zoneUinSelectorHistory.contains(i))
1178 continue;
1179 s_zoneUinSelectorHistory.add(i);
1180 uin = i;
1181 break;
1182 }
1183 s_zoneUinSelectorLock.unlock();
1184 return uin;
1185 }
1186
1187 /**
1188 * Object comparator for FindLocalMgmtNode()
1189 */
1190 static bool LocalMgmtNodeComparator(NetObj *object, void *data)
1191 {
1192 return (((Node *)object)->getCapabilities() & NC_IS_LOCAL_MGMT) ? true : false;
1193 }
1194
1195 /**
1196 * Find local management node ID
1197 */
1198 UINT32 FindLocalMgmtNode()
1199 {
1200 NetObj *object = g_idxNodeById.find(LocalMgmtNodeComparator, NULL);
1201 return (object != NULL) ? object->getId() : 0;
1202 }
1203
1204 /**
1205 * ObjectIndex::forEach callback which recalculates object's status
1206 */
1207 static void RecalcStatusCallback(NetObj *object, void *data)
1208 {
1209 object->calculateCompoundStatus();
1210 }
1211
1212 /**
1213 * ObjectIndex::forEach callback which links objects after loading
1214 */
1215 static void LinkObjects(NetObj *object, void *data)
1216 {
1217 object->linkObjects();
1218 }
1219
1220 /**
1221 * Load objects from database at stratup
1222 */
1223 BOOL LoadObjects()
1224 {
1225 // Prevent objects to change it's modification flag
1226 g_bModificationsLocked = TRUE;
1227
1228 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
1229
1230 // Load built-in object properties
1231 DbgPrintf(2, _T("Loading built-in object properties..."));
1232 g_pEntireNet->loadFromDatabase(hdb);
1233 g_pServiceRoot->loadFromDatabase(hdb);
1234 g_pTemplateRoot->loadFromDatabase(hdb);
1235 g_pPolicyRoot->loadFromDatabase(hdb);
1236 g_pMapRoot->loadFromDatabase(hdb);
1237 g_pDashboardRoot->loadFromDatabase(hdb);
1238 g_pBusinessServiceRoot->loadFromDatabase(hdb);
1239
1240 // Load zones
1241 if (g_flags & AF_ENABLE_ZONING)
1242 {
1243 Zone *pZone;
1244
1245 DbgPrintf(2, _T("Loading zones..."));
1246
1247 // Load (or create) default zone
1248 pZone = new Zone;
1249 pZone->generateGuid();
1250 pZone->loadFromDatabase(hdb, BUILTIN_OID_ZONE0);
1251 NetObjInsert(pZone, false, false);
1252 g_pEntireNet->AddZone(pZone);
1253
1254 DB_RESULT hResult = DBSelect(hdb, _T("SELECT id FROM zones WHERE id<>4"));
1255 if (hResult != NULL)
1256 {
1257 int count = DBGetNumRows(hResult);
1258 for(int i = 0; i < count; i++)
1259 {
1260 UINT32 id = DBGetFieldULong(hResult, i, 0);
1261 pZone = new Zone;
1262 if (pZone->loadFromDatabase(hdb, id))
1263 {
1264 if (!pZone->isDeleted())
1265 g_pEntireNet->AddZone(pZone);
1266 NetObjInsert(pZone, false, false); // Insert into indexes
1267 }
1268 else // Object load failed
1269 {
1270 delete pZone;
1271 nxlog_write(MSG_ZONE_LOAD_FAILED, NXLOG_ERROR, "d", id);
1272 }
1273 }
1274 DBFreeResult(hResult);
1275 }
1276 }
1277
1278 // Load conditions
1279 // We should load conditions before nodes because
1280 // DCI cache size calculation uses information from condition objects
1281 DbgPrintf(2, _T("Loading conditions..."));
1282 DB_RESULT hResult = DBSelect(hdb, _T("SELECT id FROM conditions"));
1283 if (hResult != NULL)
1284 {
1285 int count = DBGetNumRows(hResult);
1286 for(int i = 0; i < count; i++)
1287 {
1288 UINT32 id = DBGetFieldULong(hResult, i, 0);
1289 ConditionObject *condition = new ConditionObject();
1290 if (condition->loadFromDatabase(hdb, id))
1291 {
1292 NetObjInsert(condition, false, false); // Insert into indexes
1293 }
1294 else // Object load failed
1295 {
1296 delete condition;
1297 nxlog_write(MSG_CONDITION_LOAD_FAILED, NXLOG_ERROR, "d", id);
1298 }
1299 }
1300 DBFreeResult(hResult);
1301 }
1302
1303 // Load subnets
1304 DbgPrintf(2, _T("Loading subnets..."));
1305 hResult = DBSelect(hdb, _T("SELECT id FROM subnets"));
1306 if (hResult != NULL)
1307 {
1308 int count = DBGetNumRows(hResult);
1309 for(int i = 0; i < count; i++)
1310 {
1311 UINT32 id = DBGetFieldULong(hResult, i, 0);
1312 Subnet *subnet = new Subnet;
1313 if (subnet->loadFromDatabase(hdb, id))
1314 {
1315 if (!subnet->isDeleted())
1316 {
1317 if (g_flags & AF_ENABLE_ZONING)
1318 {
1319 Zone *zone = FindZoneByUIN(subnet->getZoneUIN());
1320 if (zone != NULL)
1321 zone->addSubnet(subnet);
1322 }
1323 else
1324 {
1325 g_pEntireNet->AddSubnet(subnet);
1326 }
1327 }
1328 NetObjInsert(subnet, false, false); // Insert into indexes
1329 }
1330 else // Object load failed
1331 {
1332 delete subnet;
1333 nxlog_write(MSG_SUBNET_LOAD_FAILED, NXLOG_ERROR, "d", id);
1334 }
1335 }
1336 DBFreeResult(hResult);
1337 }
1338
1339 // Load racks
1340 DbgPrintf(2, _T("Loading racks..."));
1341 hResult = DBSelect(hdb, _T("SELECT id FROM racks"));
1342 if (hResult != NULL)
1343 {
1344 int count = DBGetNumRows(hResult);
1345 for(int i = 0; i < count; i++)
1346 {
1347 UINT32 id = DBGetFieldULong(hResult, i, 0);
1348 Rack *rack = new Rack;
1349 if (rack->loadFromDatabase(hdb, id))
1350 {
1351 NetObjInsert(rack, false, false); // Insert into indexes
1352 }
1353 else // Object load failed
1354 {
1355 nxlog_write(MSG_RACK_LOAD_FAILED, NXLOG_ERROR, "d", id);
1356 delete rack;
1357 }
1358 }
1359 DBFreeResult(hResult);
1360 }
1361
1362 // Load chassis
1363 DbgPrintf(2, _T("Loading chassis..."));
1364 hResult = DBSelect(hdb, _T("SELECT id FROM chassis"));
1365 if (hResult != NULL)
1366 {
1367 int count = DBGetNumRows(hResult);
1368 for(int i = 0; i < count; i++)
1369 {
1370 UINT32 id = DBGetFieldULong(hResult, i, 0);
1371 Chassis *chassis = new Chassis;
1372 if (chassis->loadFromDatabase(hdb, id))
1373 {
1374 NetObjInsert(chassis, false, false); // Insert into indexes
1375 }
1376 else // Object load failed
1377 {
1378 nxlog_write(MSG_CHASSIS_LOAD_FAILED, NXLOG_ERROR, "d", id);
1379 delete chassis;
1380 }
1381 }
1382 DBFreeResult(hResult);
1383 }
1384
1385 // Load mobile devices
1386 DbgPrintf(2, _T("Loading mobile devices..."));
1387 hResult = DBSelect(hdb, _T("SELECT id FROM mobile_devices"));
1388 if (hResult != NULL)
1389 {
1390 int count = DBGetNumRows(hResult);
1391 for(int i = 0; i < count; i++)
1392 {
1393 UINT32 id = DBGetFieldULong(hResult, i, 0);
1394 MobileDevice *md = new MobileDevice;
1395 if (md->loadFromDatabase(hdb, id))
1396 {
1397 NetObjInsert(md, false, false); // Insert into indexes
1398 }
1399 else // Object load failed
1400 {
1401 delete md;
1402 nxlog_write(MSG_MOBILEDEVICE_LOAD_FAILED, NXLOG_ERROR, "d", id);
1403 }
1404 }
1405 DBFreeResult(hResult);
1406 }
1407
1408 // Load sensors
1409 DbgPrintf(2, _T("Loading sensors..."));
1410 hResult = DBSelect(hdb, _T("SELECT id FROM sensors"));
1411 if (hResult != NULL)
1412 {
1413 int count = DBGetNumRows(hResult);
1414 for(int i = 0; i < count; i++)
1415 {
1416 UINT32 id = DBGetFieldULong(hResult, i, 0);
1417 Sensor *sensor = new Sensor;
1418 if (sensor->loadFromDatabase(hdb, id))
1419 {
1420 NetObjInsert(sensor, false, false); // Insert into indexes
1421 }
1422 else // Object load failed
1423 {
1424 delete sensor;
1425 nxlog_write(MSG_SENSOR_LOAD_FAILED, NXLOG_ERROR, "d", id);
1426 }
1427 }
1428 DBFreeResult(hResult);
1429 }
1430
1431 // Load nodes
1432 DbgPrintf(2, _T("Loading nodes..."));
1433 hResult = DBSelect(hdb, _T("SELECT id FROM nodes"));
1434 if (hResult != NULL)
1435 {
1436 int count = DBGetNumRows(hResult);
1437 for(int i = 0; i < count; i++)
1438 {
1439 UINT32 id = DBGetFieldULong(hResult, i, 0);
1440 Node *node = new Node;
1441 if (node->loadFromDatabase(hdb, id))
1442 {
1443 NetObjInsert(node, false, false); // Insert into indexes
1444 }
1445 else // Object load failed
1446 {
1447 delete node;
1448 nxlog_write(MSG_NODE_LOAD_FAILED, NXLOG_ERROR, "d", id);
1449 }
1450 }
1451 DBFreeResult(hResult);
1452 }
1453
1454 // Load access points
1455 DbgPrintf(2, _T("Loading access points..."));
1456 hResult = DBSelect(hdb, _T("SELECT id FROM access_points"));
1457 if (hResult != NULL)
1458 {
1459 int count = DBGetNumRows(hResult);
1460 for(int i = 0; i < count; i++)
1461 {
1462 UINT32 id = DBGetFieldULong(hResult, i, 0);
1463 AccessPoint *ap = new AccessPoint;
1464 if (ap->loadFromDatabase(hdb, id))
1465 {
1466 NetObjInsert(ap, false, false); // Insert into indexes
1467 }
1468 else // Object load failed
1469 {
1470 nxlog_write(MSG_AP_LOAD_FAILED, NXLOG_ERROR, "d", id);
1471 delete ap;
1472 }
1473 }
1474 DBFreeResult(hResult);
1475 }
1476
1477 // Load interfaces
1478 DbgPrintf(2, _T("Loading interfaces..."));
1479 hResult = DBSelect(hdb, _T("SELECT id FROM interfaces"));
1480 if (hResult != NULL)
1481 {
1482 int count = DBGetNumRows(hResult);
1483 for(int i = 0; i < count; i++)
1484 {
1485 UINT32 id = DBGetFieldULong(hResult, i, 0);
1486 Interface *iface = new Interface;
1487 if (iface->loadFromDatabase(hdb, id))
1488 {
1489 NetObjInsert(iface, false, false); // Insert into indexes
1490 }
1491 else // Object load failed
1492 {
1493 nxlog_write(MSG_INTERFACE_LOAD_FAILED, NXLOG_ERROR, "d", id);
1494 delete iface;
1495 }
1496 }
1497 DBFreeResult(hResult);
1498 }
1499
1500 // Load network services
1501 DbgPrintf(2, _T("Loading network services..."));
1502 hResult = DBSelect(hdb, _T("SELECT id FROM network_services"));
1503 if (hResult != NULL)
1504 {
1505 int count = DBGetNumRows(hResult);
1506 for(int i = 0; i < count; i++)
1507 {
1508 UINT32 id = DBGetFieldULong(hResult, i, 0);
1509 NetworkService *service = new NetworkService;
1510 if (service->loadFromDatabase(hdb, id))
1511 {
1512 NetObjInsert(service, false, false); // Insert into indexes
1513 }
1514 else // Object load failed
1515 {
1516 delete service;
1517 nxlog_write(MSG_NETSRV_LOAD_FAILED, NXLOG_ERROR, "d", id);
1518 }
1519 }
1520 DBFreeResult(hResult);
1521 }
1522
1523 // Load VPN connectors
1524 DbgPrintf(2, _T("Loading VPN connectors..."));
1525 hResult = DBSelect(hdb, _T("SELECT id FROM vpn_connectors"));
1526 if (hResult != NULL)
1527 {
1528 int count = DBGetNumRows(hResult);
1529 for(int i = 0; i < count; i++)
1530 {
1531 UINT32 id = DBGetFieldULong(hResult, i, 0);
1532 VPNConnector *connector = new VPNConnector;
1533 if (connector->loadFromDatabase(hdb, id))
1534 {
1535 NetObjInsert(connector, false, false); // Insert into indexes
1536 }
1537 else // Object load failed
1538 {
1539 delete connector;
1540 nxlog_write(MSG_VPNC_LOAD_FAILED, NXLOG_ERROR, "d", id);
1541 }
1542 }
1543 DBFreeResult(hResult);
1544 }
1545
1546 // Load clusters
1547 DbgPrintf(2, _T("Loading clusters..."));
1548 hResult = DBSelect(hdb, _T("SELECT id FROM clusters"));
1549 if (hResult != NULL)
1550 {
1551 int count = DBGetNumRows(hResult);
1552 for(int i = 0; i < count; i++)
1553 {
1554 UINT32 id = DBGetFieldULong(hResult, i, 0);
1555 Cluster *cluster = new Cluster;
1556 if (cluster->loadFromDatabase(hdb, id))
1557 {
1558 NetObjInsert(cluster, false, false); // Insert into indexes
1559 }
1560 else // Object load failed
1561 {
1562 delete cluster;
1563 nxlog_write(MSG_CLUSTER_LOAD_FAILED, NXLOG_ERROR, "d", id);
1564 }
1565 }
1566 DBFreeResult(hResult);
1567 }
1568
1569 // Start cache loading thread.
1570 // All data collection targets must be loaded at this point.
1571 ThreadCreate(CacheLoadingThread, 0, NULL);
1572
1573 // Load templates
1574 DbgPrintf(2, _T("Loading templates..."));
1575 hResult = DBSelect(hdb, _T("SELECT id FROM templates"));
1576 if (hResult != NULL)
1577 {
1578 int count = DBGetNumRows(hResult);
1579 for(int i = 0; i < count; i++)
1580 {
1581 UINT32 id = DBGetFieldULong(hResult, i, 0);
1582 Template *tmpl = new Template;
1583 if (tmpl->loadFromDatabase(hdb, id))
1584 {
1585 NetObjInsert(tmpl, false, false); // Insert into indexes
1586 tmpl->calculateCompoundStatus(); // Force status change to NORMAL
1587 }
1588 else // Object load failed
1589 {
1590 delete tmpl;
1591 nxlog_write(MSG_TEMPLATE_LOAD_FAILED, NXLOG_ERROR, "d", id);
1592 }
1593 }
1594 DBFreeResult(hResult);
1595 }
1596
1597 // Load agent policies
1598 DbgPrintf(2, _T("Loading agent policies..."));
1599 hResult = DBSelect(hdb, _T("SELECT id,policy_type FROM ap_common"));
1600 if (hResult != NULL)
1601 {
1602 int count = DBGetNumRows(hResult);
1603 for(int i = 0; i < count; i++)
1604 {
1605 AgentPolicy *policy;
1606
1607 UINT32 id = DBGetFieldULong(hResult, i, 0);
1608 int type = DBGetFieldLong(hResult, i, 1);
1609 switch(type)
1610 {
1611 case AGENT_POLICY_CONFIG:
1612 policy = new AgentPolicyConfig();
1613 break;
1614 case AGENT_POLICY_LOG_PARSER:
1615 policy = new AgentPolicyLogParser();
1616 break;
1617 default:
1618 policy = new AgentPolicy(type);
1619 break;
1620 }
1621 if (policy->loadFromDatabase(hdb, id))
1622 {
1623 NetObjInsert(policy, false, false); // Insert into indexes
1624 policy->calculateCompoundStatus(); // Force status change to NORMAL
1625 }
1626 else // Object load failed
1627 {
1628 delete policy;
1629 nxlog_write(MSG_AGENTPOLICY_LOAD_FAILED, NXLOG_ERROR, "d", id);
1630 }
1631 }
1632 DBFreeResult(hResult);
1633 }
1634
1635 // Load network maps
1636 DbgPrintf(2, _T("Loading network maps..."));
1637 hResult = DBSelect(hdb, _T("SELECT id FROM network_maps"));
1638 if (hResult != NULL)
1639 {
1640 int count = DBGetNumRows(hResult);
1641 for(int i = 0; i < count; i++)
1642 {
1643 UINT32 id = DBGetFieldULong(hResult, i, 0);
1644 NetworkMap *map = new NetworkMap;
1645 if (map->loadFromDatabase(hdb, id))
1646 {
1647 NetObjInsert(map, false, false); // Insert into indexes
1648 }
1649 else // Object load failed
1650 {
1651 delete map;
1652 nxlog_write(MSG_NETMAP_LOAD_FAILED, NXLOG_ERROR, "d", id);
1653 }
1654 }
1655 DBFreeResult(hResult);
1656 }
1657
1658 // Load container objects
1659 DbgPrintf(2, _T("Loading containers..."));
1660 TCHAR query[256];
1661 _sntprintf(query, sizeof(query) / sizeof(TCHAR), _T("SELECT id FROM object_containers WHERE object_class=%d"), OBJECT_CONTAINER);
1662 hResult = DBSelect(hdb, query);
1663 if (hResult != NULL)
1664 {
1665 Container *pContainer;
1666
1667 int count = DBGetNumRows(hResult);
1668 for(int i = 0; i < count; i++)
1669 {
1670 UINT32 id = DBGetFieldULong(hResult, i, 0);
1671 pContainer = new Container;
1672 if (pContainer->loadFromDatabase(hdb, id))
1673 {
1674 NetObjInsert(pContainer, false, false); // Insert into indexes
1675 }
1676 else // Object load failed
1677 {
1678 delete pContainer;
1679 nxlog_write(MSG_CONTAINER_LOAD_FAILED, NXLOG_ERROR, "d", id);
1680 }
1681 }
1682 DBFreeResult(hResult);
1683 }
1684
1685 // Load template group objects
1686 DbgPrintf(2, _T("Loading template groups..."));
1687 _sntprintf(query, sizeof(query) / sizeof(TCHAR), _T("SELECT id FROM object_containers WHERE object_class=%d"), OBJECT_TEMPLATEGROUP);
1688 hResult = DBSelect(hdb, query);
1689 if (hResult != NULL)
1690 {
1691 TemplateGroup *pGroup;
1692
1693 int count = DBGetNumRows(hResult);
1694 for(int i = 0; i < count; i++)
1695 {
1696 UINT32 id = DBGetFieldULong(hResult, i, 0);
1697 pGroup = new TemplateGroup;
1698 if (pGroup->loadFromDatabase(hdb, id))
1699 {
1700 NetObjInsert(pGroup, false, false); // Insert into indexes
1701 }
1702 else // Object load failed
1703 {
1704 delete pGroup;
1705 nxlog_write(MSG_TG_LOAD_FAILED, NXLOG_ERROR, "d", id);
1706 }
1707 }
1708 DBFreeResult(hResult);
1709 }
1710
1711 // Load policy group objects
1712 DbgPrintf(2, _T("Loading policy groups..."));
1713 _sntprintf(query, sizeof(query) / sizeof(TCHAR), _T("SELECT id FROM object_containers WHERE object_class=%d"), OBJECT_POLICYGROUP);
1714 hResult = DBSelect(hdb, query);
1715 if (hResult != NULL)
1716 {
1717 int count = DBGetNumRows(hResult);
1718 for(int i = 0; i < count; i++)
1719 {
1720 UINT32 id = DBGetFieldULong(hResult, i, 0);
1721 PolicyGroup *group = new PolicyGroup;
1722 if (group->loadFromDatabase(hdb, id))
1723 {
1724 NetObjInsert(group, false, false); // Insert into indexes
1725 }
1726 else // Object load failed
1727 {
1728 delete group;
1729 nxlog_write(MSG_PG_LOAD_FAILED, NXLOG_ERROR, "d", id);
1730 }
1731 }
1732 DBFreeResult(hResult);
1733 }
1734
1735 // Load map group objects
1736 DbgPrintf(2, _T("Loading map groups..."));
1737 _sntprintf(query, sizeof(query) / sizeof(TCHAR), _T("SELECT id FROM object_containers WHERE object_class=%d"), OBJECT_NETWORKMAPGROUP);
1738 hResult = DBSelect(hdb, query);
1739 if (hResult != NULL)
1740 {
1741 int count = DBGetNumRows(hResult);
1742 for(int i = 0; i < count; i++)
1743 {
1744 UINT32 id = DBGetFieldULong(hResult, i, 0);
1745 NetworkMapGroup *group = new NetworkMapGroup;
1746 if (group->loadFromDatabase(hdb, id))
1747 {
1748 NetObjInsert(group, false, false); // Insert into indexes
1749 }
1750 else // Object load failed
1751 {
1752 delete group;
1753 nxlog_write(MSG_MG_LOAD_FAILED, NXLOG_ERROR, "d", id);
1754 }
1755 }
1756 DBFreeResult(hResult);
1757 }
1758
1759 // Load dashboard objects
1760 DbgPrintf(2, _T("Loading dashboards..."));
1761 hResult = DBSelect(hdb, _T("SELECT id FROM dashboards"));
1762 if (hResult != NULL)
1763 {
1764 int count = DBGetNumRows(hResult);
1765 for(int i = 0; i < count; i++)
1766 {
1767 UINT32 id = DBGetFieldULong(hResult, i, 0);
1768 Dashboard *dashboard = new Dashboard;
1769 if (dashboard->loadFromDatabase(hdb, id))
1770 {
1771 NetObjInsert(dashboard, false, false); // Insert into indexes
1772 }
1773 else // Object load failed
1774 {
1775 delete dashboard;
1776 nxlog_write(MSG_DASHBOARD_LOAD_FAILED, NXLOG_ERROR, "d", id);
1777 }
1778 }
1779 DBFreeResult(hResult);
1780 }
1781
1782 // Load dashboard group objects
1783 DbgPrintf(2, _T("Loading dashboard groups..."));
1784 _sntprintf(query, sizeof(query) / sizeof(TCHAR), _T("SELECT id FROM object_containers WHERE object_class=%d"), OBJECT_DASHBOARDGROUP);
1785 hResult = DBSelect(hdb, query);
1786 if (hResult != NULL)
1787 {
1788 int count = DBGetNumRows(hResult);
1789 for(int i = 0; i < count; i++)
1790 {
1791 UINT32 id = DBGetFieldULong(hResult, i, 0);
1792 DashboardGroup *group = new DashboardGroup;
1793 if (group->loadFromDatabase(hdb, id))
1794 {
1795 NetObjInsert(group, false, false); // Insert into indexes
1796 }
1797 else // Object load failed
1798 {
1799 delete group;
1800 nxlog_write(MSG_MG_LOAD_FAILED, NXLOG_ERROR, "d", id);
1801 }
1802 }
1803 DBFreeResult(hResult);
1804 }
1805
1806 // Loading business service objects
1807 DbgPrintf(2, _T("Loading business services..."));
1808 _sntprintf(query, sizeof(query) / sizeof(TCHAR), _T("SELECT id FROM object_containers WHERE object_class=%d"), OBJECT_BUSINESSSERVICE);
1809 hResult = DBSelect(hdb, query);
1810 if (hResult != NULL)
1811 {
1812 int count = DBGetNumRows(hResult);
1813 for(int i = 0; i < count; i++)
1814 {
1815 UINT32 id = DBGetFieldULong(hResult, i, 0);
1816 BusinessService *service = new BusinessService;
1817 if (service->loadFromDatabase(hdb, id))
1818 {
1819 NetObjInsert(service, false, false); // Insert into indexes
1820 }
1821 else // Object load failed
1822 {
1823 delete service;
1824 nxlog_write(MSG_BUSINESS_SERVICE_LOAD_FAILED, NXLOG_ERROR, "d", id);
1825 }
1826 }
1827 DBFreeResult(hResult);
1828 }
1829
1830 // Loading business service objects
1831 DbgPrintf(2, _T("Loading node links..."));
1832 _sntprintf(query, sizeof(query) / sizeof(TCHAR), _T("SELECT id FROM object_containers WHERE object_class=%d"), OBJECT_NODELINK);
1833 hResult = DBSelect(hdb, query);
1834 if (hResult != NULL)
1835 {
1836 int count = DBGetNumRows(hResult);
1837 for(int i = 0; i < count; i++)
1838 {
1839 UINT32 id = DBGetFieldULong(hResult, i, 0);
1840 NodeLink *nl = new NodeLink;
1841 if (nl->loadFromDatabase(hdb, id))
1842 {
1843 NetObjInsert(nl, false, false); // Insert into indexes
1844 }
1845 else // Object load failed
1846 {
1847 delete nl;
1848 nxlog_write(MSG_NODE_LINK_LOAD_FAILED, NXLOG_ERROR, "d", id);
1849 }
1850 }
1851 DBFreeResult(hResult);
1852 }
1853
1854 // Load service check objects
1855 DbgPrintf(2, _T("Loading service checks..."));
1856 hResult = DBSelect(hdb, _T("SELECT id FROM slm_checks"));
1857 if (hResult != NULL)
1858 {
1859 int count = DBGetNumRows(hResult);
1860 for(int i = 0; i < count; i++)
1861 {
1862 UINT32 id = DBGetFieldULong(hResult, i, 0);
1863 SlmCheck *check = new SlmCheck;
1864 if (check->loadFromDatabase(hdb, id))
1865 {
1866 NetObjInsert(check, false, false); // Insert into indexes
1867 }
1868 else // Object load failed
1869 {
1870 delete check;
1871 nxlog_write(MSG_SERVICE_CHECK_LOAD_FAILED, NXLOG_ERROR, "d", id);
1872 }
1873 }
1874 DBFreeResult(hResult);
1875 }
1876
1877 DBConnectionPoolReleaseConnection(hdb);
1878
1879 // Load custom object classes provided by modules
1880 CALL_ALL_MODULES(pfLoadObjects, ());
1881
1882 // Link children to container and template group objects
1883 DbgPrintf(2, _T("Linking objects..."));
1884 g_idxObjectById.forEach(LinkObjects, NULL);
1885
1886 // Link custom object classes provided by modules
1887 CALL_ALL_MODULES(pfLinkObjects, ());
1888
1889 // Allow objects to change it's modification flag
1890 g_bModificationsLocked = FALSE;
1891
1892 // Recalculate status for built-in objects
1893 g_pEntireNet->calculateCompoundStatus();
1894 g_pServiceRoot->calculateCompoundStatus();
1895 g_pTemplateRoot->calculateCompoundStatus();
1896 g_pPolicyRoot->calculateCompoundStatus();
1897 g_pMapRoot->calculateCompoundStatus();
1898 g_pBusinessServiceRoot->calculateCompoundStatus();
1899
1900 // Recalculate status for zone objects
1901 if (g_flags & AF_ENABLE_ZONING)
1902 {
1903 g_idxZoneByUIN.forEach(RecalcStatusCallback, NULL);
1904 }
1905
1906 // Start map update thread
1907 ThreadCreate(MapUpdateThread, 0, NULL);
1908
1909 // Start template update applying thread
1910 ThreadCreate(ApplyTemplateThread, 0, NULL);
1911
1912 return TRUE;
1913 }
1914
1915 /**
1916 * Callback for DeleteUserFromAllObjects
1917 */
1918 static void DropUserAccess(NetObj *object, void *userId)
1919 {
1920 object->dropUserAccess(CAST_FROM_POINTER(userId, UINT32));
1921 }
1922
1923 /**
1924 * Delete user or group from all objects' ACLs
1925 */
1926 void DeleteUserFromAllObjects(UINT32 dwUserId)
1927 {
1928 g_idxObjectById.forEach(DropUserAccess, CAST_TO_POINTER(dwUserId, void *));
1929 }
1930
1931 /**
1932 * User data for DumpObjectCallback
1933 */
1934 struct __dump_objects_data
1935 {
1936 CONSOLE_CTX console;
1937 TCHAR *buffer;
1938 const TCHAR *filter;
1939 };
1940
1941 /**
1942 * Enumeration callback for DumpObjects
1943 */
1944 static void DumpObjectCallback(NetObj *object, void *data)
1945 {
1946 struct __dump_objects_data *dd = (struct __dump_objects_data *)data;
1947
1948 // Apply name filter
1949 if ((dd->filter != NULL) && !MatchString(dd->filter, object->getName(), false))
1950 return;
1951
1952 CONSOLE_CTX pCtx = dd->console;
1953
1954 ConsolePrintf(pCtx, _T("Object ID %d \"%s\"\n")
1955 _T(" Class: %s Status: %s IsModified: %d IsDeleted: %d\n"),
1956 object->getId(), object->getName(), object->getObjectClassName(),
1957 GetStatusAsText(object->getStatus(), true),
1958 object->isModified(), object->isDeleted());
1959 ConsolePrintf(pCtx, _T(" Parents: <%s>\n Childs: <%s>\n"),
1960 object->dbgGetParentList(dd->buffer), object->dbgGetChildList(&dd->buffer[4096]));
1961 time_t t = object->getTimeStamp();
1962 #if HAVE_LOCALTIME_R
1963 struct tm tmbuffer;
1964 struct tm *ltm = localtime_r(&t, &tmbuffer);
1965 #else
1966 struct tm *ltm = localtime(&t);
1967 #endif
1968 _tcsftime(dd->buffer, 256, _T("%d.%b.%Y %H:%M:%S"), ltm);
1969 ConsolePrintf(pCtx, _T(" Last change: %s\n"), dd->buffer);
1970 if (object->isDataCollectionTarget())
1971 ConsolePrintf(pCtx, _T(" State flags: 0x%08x\n"), ((DataCollectionTarget *)object)->getState());
1972 switch(object->getObjectClass())
1973 {
1974 case OBJECT_NODE:
1975 ConsolePrintf(pCtx, _T(" Primary IP: %s\n IsSNMP: %d IsAgent: %d IsLocal: %d OID: %s\n"),
1976 ((Node *)object)->getIpAddress().toString(dd->buffer),
1977 ((Node *)object)->isSNMPSupported(),
1978 ((Node *)object)->isNativeAgent(),
1979 ((Node *)object)->isLocalManagement(),
1980 ((Node *)object)->getSNMPObjectId());
1981 break;
1982 case OBJECT_SUBNET:
1983 ConsolePrintf(pCtx, _T(" IP address: %s/%d\n"), ((Subnet *)object)->getIpAddress().toString(dd->buffer), ((Subnet *)object)->getIpAddress().getMaskBits());
1984 break;
1985 case OBJECT_ACCESSPOINT:
1986 ConsolePrintf(pCtx, _T(" IP address: %s\n"), ((AccessPoint *)object)->getIpAddress().toString(dd->buffer));
1987 break;
1988 case OBJECT_INTERFACE:
1989 ConsolePrintf(pCtx, _T(" MAC address: %s\n"), MACToStr(((Interface *)object)->getMacAddr(), dd->buffer));
1990 for(int n = 0; n < ((Interface *)object)->getIpAddressList()->size(); n++)
1991 {
1992 const InetAddress& a = ((Interface *)object)->getIpAddressList()->get(n);
1993 ConsolePrintf(pCtx, _T(" IP address: %s/%d\n"), a.toString(dd->buffer), a.getMaskBits());
1994 }
1995 break;
1996 case OBJECT_TEMPLATE:
1997 ConsolePrintf(pCtx, _T(" Version: %d.%d\n"),
1998 ((Template *)(object))->getVersionMajor(),
1999 ((Template *)(object))->getVersionMinor());
2000 break;
2001 }
2002 }
2003
2004 /**
2005 * Dump objects to debug console
2006 */
2007 void DumpObjects(CONSOLE_CTX pCtx, const TCHAR *filter)
2008 {
2009 struct __dump_objects_data data;
2010
2011 data.buffer = (TCHAR *)malloc(128000 * sizeof(TCHAR));
2012 data.console = pCtx;
2013 data.filter = filter;
2014 g_idxObjectById.forEach(DumpObjectCallback, &data);
2015 free(data.buffer);
2016 }
2017
2018 /**
2019 * Check is given object class is a valid parent class for other object
2020 * This function is used to check manually created bindings, so it won't
2021 * return TRUE for node -- subnet for example
2022 */
2023 bool IsValidParentClass(int childClass, int parentClass)
2024 {
2025 switch(parentClass)
2026 {
2027 case OBJECT_NETWORK:
2028 if ((childClass == OBJECT_ZONE) && (g_flags & AF_ENABLE_ZONING))
2029 return true;
2030 break;
2031 case OBJECT_SERVICEROOT:
2032 case OBJECT_CONTAINER:
2033 if ((childClass == OBJECT_CHASSIS) ||
2034 (childClass == OBJECT_CLUSTER) ||
2035 (childClass == OBJECT_CONDITION) ||
2036 (childClass == OBJECT_CONTAINER) ||
2037 (childClass == OBJECT_MOBILEDEVICE) ||
2038 (childClass == OBJECT_NODE) ||
2039 (childClass == OBJECT_RACK) ||
2040 (childClass == OBJECT_SUBNET) ||
2041 (childClass == OBJECT_SENSOR))
2042 return true;
2043 break;
2044 case OBJECT_CHASSIS:
2045 case OBJECT_RACK:
2046 if (childClass == OBJECT_NODE)
2047 return true;
2048 break;
2049 case OBJECT_TEMPLATEROOT:
2050 case OBJECT_TEMPLATEGROUP:
2051 if ((childClass == OBJECT_TEMPLATEGROUP) ||
2052 (childClass == OBJECT_TEMPLATE))
2053 return true;
2054 break;
2055 case OBJECT_TEMPLATE:
2056 if ((childClass == OBJECT_NODE) ||
2057 (childClass == OBJECT_CLUSTER) ||
2058 (childClass == OBJECT_MOBILEDEVICE) ||
2059 (childClass == OBJECT_SENSOR))
2060 return true;
2061 break;
2062 case OBJECT_NETWORKMAPROOT:
2063 case OBJECT_NETWORKMAPGROUP:
2064 if ((childClass == OBJECT_NETWORKMAPGROUP) ||
2065 (childClass == OBJECT_NETWORKMAP))
2066 return true;
2067 break;
2068 case OBJECT_DASHBOARDROOT:
2069 case OBJECT_DASHBOARDGROUP:
2070 case OBJECT_DASHBOARD:
2071 if ((childClass == OBJECT_DASHBOARDGROUP) ||
2072 (childClass == OBJECT_DASHBOARD))
2073 return true;
2074 break;
2075 case OBJECT_POLICYROOT:
2076 case OBJECT_POLICYGROUP:
2077 if ((childClass == OBJECT_POLICYGROUP) ||
2078 (childClass == OBJECT_AGENTPOLICY) ||
2079 (childClass == OBJECT_AGENTPOLICY_CONFIG) ||
2080 (childClass == OBJECT_AGENTPOLICY_LOGPARSER))
2081 return true;
2082 break;
2083 case OBJECT_NODE:
2084 if ((childClass == OBJECT_NETWORKSERVICE) ||
2085 (childClass == OBJECT_VPNCONNECTOR) ||
2086 (childClass == OBJECT_INTERFACE))
2087 return true;
2088 break;
2089 case OBJECT_CLUSTER:
2090 if (childClass == OBJECT_NODE)
2091 return true;
2092 break;
2093 case OBJECT_BUSINESSSERVICEROOT:
2094 if ((childClass == OBJECT_BUSINESSSERVICE) ||
2095 (childClass == OBJECT_NODELINK))
2096 return true;
2097 break;
2098 case OBJECT_BUSINESSSERVICE:
2099 if ((childClass == OBJECT_BUSINESSSERVICE) ||
2100 (childClass == OBJECT_NODELINK) ||
2101 (childClass == OBJECT_SLMCHECK))
2102 return true;
2103 break;
2104 case OBJECT_NODELINK:
2105 if (childClass == OBJECT_SLMCHECK)
2106 return true;
2107 break;
2108 case -1: // Creating object without parent
2109 if (childClass == OBJECT_NODE)
2110 return true; // OK only for nodes, because parent subnet will be created automatically
2111 break;
2112 }
2113
2114 // Additional check by loaded modules
2115 for(UINT32 i = 0; i < g_dwNumModules; i++)
2116 {
2117 if (g_pModuleList[i].pfIsValidParentClass != NULL)
2118 {
2119 if (g_pModuleList[i].pfIsValidParentClass(childClass, parentClass))
2120 return true; // accepted by module
2121 }
2122 }
2123
2124 return false;
2125 }
2126
2127 /**
2128 * Callback for postponed object deletion
2129 */
2130 static void DeleteObjectCallback(void *arg)
2131 {
2132 NetObj *object = (NetObj *)arg;
2133 while(object->getRefCount() > 0)
2134 ThreadSleep(1);
2135 DbgPrintf(4, _T("Executing postponed delete of object %s [%d]"), object->getName(), object->getId());
2136 delete object;
2137 }
2138
2139 /**
2140 * Delete object (final step)
2141 * This function should be called ONLY from syncer thread
2142 * Object will be removed from index by ID and destroyed.
2143 */
2144 void NetObjDelete(NetObj *object)
2145 {
2146 DbgPrintf(4, _T("Final delete step for object %s [%d]"), object->getName(), object->getId());
2147
2148 // Delete object from index by ID and object itself
2149 g_idxObjectById.remove(object->getId());
2150 if (object->getRefCount() == 0)
2151 {
2152 delete object;
2153 }
2154 else
2155 {
2156 DbgPrintf(4, _T("Object %s [%d] has %d references at final delete step - postpone deletion"), object->getName(), object->getId());
2157 ThreadPoolExecuteSerialized(g_mainThreadPool, _T("DeleteObject"), DeleteObjectCallback, object);
2158 }
2159 }
2160
2161 /**
2162 * Update interface index when IP address changes
2163 */
2164 void UpdateInterfaceIndex(const InetAddress& oldIpAddr, const InetAddress& newIpAddr, Interface *iface)
2165 {
2166 if (IsZoningEnabled())
2167 {
2168 Zone *zone = (Zone *)g_idxZoneByUIN.get(iface->getZoneUIN());
2169 if (zone != NULL)
2170 {
2171 zone->updateInterfaceIndex(oldIpAddr, newIpAddr, iface);
2172 }
2173 else
2174 {
2175 DbgPrintf(1, _T("UpdateInterfaceIndex: Cannot find zone object for interface %s [%d] (zone id %d)"),
2176 iface->getName(), (int)iface->getId(), (int)iface->getZoneUIN());
2177 }
2178 }
2179 else
2180 {
2181 g_idxInterfaceByAddr.remove(oldIpAddr);
2182 g_idxInterfaceByAddr.put(newIpAddr, iface);
2183 }
2184 }
2185
2186 /**
2187 * Calculate propagated status for object using default algorithm
2188 */
2189 int DefaultPropagatedStatus(int iObjectStatus)
2190 {
2191 int iStatus;
2192
2193 switch(m_iStatusPropAlg)
2194 {
2195 case SA_PROPAGATE_UNCHANGED:
2196 iStatus = iObjectStatus;
2197 break;
2198 case SA_PROPAGATE_FIXED:
2199 iStatus = ((iObjectStatus > STATUS_NORMAL) && (iObjectStatus < STATUS_UNKNOWN)) ? m_iFixedStatus : iObjectStatus;
2200 break;
2201 case SA_PROPAGATE_RELATIVE:
2202 if ((iObjectStatus > STATUS_NORMAL) && (iObjectStatus < STATUS_UNKNOWN))
2203 {
2204 iStatus = iObjectStatus + m_iStatusShift;
2205 if (iStatus < 0)
2206 iStatus = 0;
2207 if (iStatus > STATUS_CRITICAL)
2208 iStatus = STATUS_CRITICAL;
2209 }
2210 else
2211 {
2212 iStatus = iObjectStatus;
2213 }
2214 break;
2215 case SA_PROPAGATE_TRANSLATED:
2216 if ((iObjectStatus > STATUS_NORMAL) && (iObjectStatus < STATUS_UNKNOWN))
2217 {
2218 iStatus = m_iStatusTranslation[iObjectStatus - 1];
2219 }
2220 else
2221 {
2222 iStatus = iObjectStatus;
2223 }
2224 break;
2225 default:
2226 iStatus = STATUS_UNKNOWN;
2227 break;
2228 }
2229 return iStatus;
2230 }
2231
2232 /**
2233 * Get default data for status calculation
2234 */
2235 int GetDefaultStatusCalculation(int *pnSingleThreshold, int **ppnThresholds)
2236 {
2237 *pnSingleThreshold = m_iStatusSingleThreshold;
2238 *ppnThresholds = m_iStatusThresholds;
2239 return m_iStatusCalcAlg;
2240 }
2241
2242 /**
2243 * Check if given object is an agent policy object
2244 */
2245 bool IsAgentPolicyObject(NetObj *object)
2246 {
2247 return (object->getObjectClass() == OBJECT_AGENTPOLICY) || (object->getObjectClass() == OBJECT_AGENTPOLICY_CONFIG) || (object->getObjectClass() == OBJECT_AGENTPOLICY_LOGPARSER);
2248 }
2249
2250 /**
2251 * Returns true if object of given class can be event source
2252 */
2253 bool IsEventSource(int objectClass)
2254 {
2255 return (objectClass == OBJECT_NODE) ||
2256 (objectClass == OBJECT_CONTAINER) ||
2257 (objectClass == OBJECT_CLUSTER) ||
2258 (objectClass == OBJECT_MOBILEDEVICE ||
2259 (objectClass == OBJECT_SENSOR));
2260 }
2261
2262 /**
2263 * Check of object1 is parent of object2 (also indirect parent)
2264 */
2265 bool NXCORE_EXPORTABLE IsParentObject(UINT32 object1, UINT32 object2)
2266 {
2267 NetObj *p = FindObjectById(object1);
2268 return (p != NULL) ? p->isChild(object2) : false;
2269 }
2270
2271 /**
2272 * Callback data for CreateObjectAccessSnapshot
2273 */
2274 struct CreateObjectAccessSnapshot_CallbackData
2275 {
2276 UINT32 userId;
2277 StructArray<ACL_ELEMENT> *accessList;
2278 };
2279
2280 /**
2281 * Callback for CreateObjectAccessSnapshot
2282 */
2283 static void CreateObjectAccessSnapshot_Callback(NetObj *object, void *arg)
2284 {
2285 CreateObjectAccessSnapshot_CallbackData *data = (CreateObjectAccessSnapshot_CallbackData *)arg;
2286 UINT32 accessRights = object->getUserRights(data->userId);
2287 if (accessRights != 0)
2288 {
2289 ACL_ELEMENT e;
2290 e.dwUserId = object->getId();
2291 e.dwAccessRights = accessRights;
2292 data->accessList->add(&e);
2293 }
2294 }
2295
2296 /**
2297 * Create access snapshot for given user and object class
2298 */
2299 bool NXCORE_EXPORTABLE CreateObjectAccessSnapshot(UINT32 userId, int objClass)
2300 {
2301 ObjectIndex *index;
2302 switch(objClass)
2303 {
2304 case OBJECT_ACCESSPOINT:
2305 index = &g_idxAccessPointById;
2306 break;
2307 case OBJECT_CLUSTER:
2308 index = &g_idxClusterById;
2309 break;
2310 case OBJECT_MOBILEDEVICE:
2311 index = &g_idxMobileDeviceById;
2312 break;
2313 case OBJECT_NODE:
2314 index = &g_idxNodeById;
2315 break;
2316 case OBJECT_ZONE:
2317 index = &g_idxZoneByUIN;
2318 break;
2319 case OBJECT_SENSOR:
2320 index = &g_idxSensorById;
2321 break;
2322 default:
2323 index = &g_idxObjectById;
2324 break;
2325 }
2326
2327 StructArray<ACL_ELEMENT> accessList;
2328 CreateObjectAccessSnapshot_CallbackData data;
2329 data.userId = userId;
2330 data.accessList = &accessList;
2331 index->forEach(CreateObjectAccessSnapshot_Callback, &data);
2332
2333 bool success = false;
2334 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
2335 if (DBBegin(hdb))
2336 {
2337 success = ExecuteQueryOnObject(hdb, userId, _T("DELETE FROM object_access_snapshot WHERE user_id=?"));
2338 if (success && (accessList.size() > 0))
2339 {
2340 DB_STATEMENT hStmt = DBPrepare(hdb, _T("INSERT INTO object_access_snapshot (user_id,object_id,access_rights) VALUES (?,?,?)"));
2341 if (hStmt != NULL)
2342 {
2343 DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, userId);
2344 for(int i = 0; (i < accessList.size()) && success; i++)
2345 {
2346 DBBind(hStmt, 2, DB_SQLTYPE_INTEGER, accessList.get(i)->dwUserId);
2347 DBBind(hStmt, 3, DB_SQLTYPE_INTEGER, accessList.get(i)->dwAccessRights);
2348 success = DBExecute(hStmt);
2349 }
2350 DBFreeStatement(hStmt);
2351 }
2352 else
2353 {
2354 success = false;
2355 }
2356 }
2357 if (success)
2358 DBCommit(hdb);
2359 else
2360 DBRollback(hdb);
2361 }
2362 DBConnectionPoolReleaseConnection(hdb);
2363 return success;
2364 }