efbc913214c6608fa3cf8d02ff7ae468011ca8c6
[public/netxms.git] / src / server / core / objects.cpp
1 /*
2 ** NetXMS - Network Management System
3 ** Copyright (C) 2003-2011 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: objects.cpp
20 **
21 **/
22
23 #include "nxcore.h"
24
25
26 //
27 // Global data
28 //
29
30 BOOL g_bModificationsLocked = FALSE;
31
32 Network NXCORE_EXPORTABLE *g_pEntireNet = NULL;
33 ServiceRoot NXCORE_EXPORTABLE *g_pServiceRoot = NULL;
34 TemplateRoot NXCORE_EXPORTABLE *g_pTemplateRoot = NULL;
35 PolicyRoot NXCORE_EXPORTABLE *g_pPolicyRoot = NULL;
36 NetworkMapRoot NXCORE_EXPORTABLE *g_pMapRoot = NULL;
37
38 DWORD NXCORE_EXPORTABLE g_dwMgmtNode = 0;
39 INDEX NXCORE_EXPORTABLE *g_pIndexById = NULL;
40 DWORD NXCORE_EXPORTABLE g_dwIdIndexSize = 0;
41 INDEX NXCORE_EXPORTABLE *g_pSubnetIndexByAddr = NULL;
42 DWORD NXCORE_EXPORTABLE g_dwSubnetAddrIndexSize = 0;
43 INDEX NXCORE_EXPORTABLE *g_pNodeIndexByAddr = NULL;
44 DWORD NXCORE_EXPORTABLE g_dwNodeAddrIndexSize = 0;
45 INDEX NXCORE_EXPORTABLE *g_pInterfaceIndexByAddr = NULL;
46 DWORD NXCORE_EXPORTABLE g_dwInterfaceAddrIndexSize = 0;
47 INDEX NXCORE_EXPORTABLE *g_pZoneIndexByGUID = NULL;
48 DWORD NXCORE_EXPORTABLE g_dwZoneGUIDIndexSize = 0;
49 INDEX NXCORE_EXPORTABLE *g_pConditionIndex = NULL;
50 DWORD NXCORE_EXPORTABLE g_dwConditionIndexSize = 0;
51
52 RWLOCK NXCORE_EXPORTABLE g_rwlockIdIndex;
53 RWLOCK NXCORE_EXPORTABLE g_rwlockNodeIndex;
54 RWLOCK NXCORE_EXPORTABLE g_rwlockSubnetIndex;
55 RWLOCK NXCORE_EXPORTABLE g_rwlockInterfaceIndex;
56 RWLOCK NXCORE_EXPORTABLE g_rwlockZoneIndex;
57 RWLOCK NXCORE_EXPORTABLE g_rwlockConditionIndex;
58
59 DWORD g_dwNumCategories = 0;
60 CONTAINER_CATEGORY *g_pContainerCatList = NULL;
61
62 Queue *g_pTemplateUpdateQueue = NULL;
63
64 const TCHAR *g_szClassName[]={ _T("Generic"), _T("Subnet"), _T("Node"), _T("Interface"),
65 _T("Network"), _T("Container"), _T("Zone"), _T("ServiceRoot"),
66 _T("Template"), _T("TemplateGroup"), _T("TemplateRoot"),
67 _T("NetworkService"), _T("VPNConnector"), _T("Condition"),
68 _T("Cluster"), _T("PolicyGroup"), _T("PolicyRoot"),
69 _T("AgentPolicy"), _T("AgentPolicyConfig"), _T("NetworkMapRoot"),
70 _T("NetworkMapGroup"), _T("NetworkMap") };
71
72
73 //
74 // Static data
75 //
76
77 static int m_iStatusCalcAlg = SA_CALCULATE_MOST_CRITICAL;
78 static int m_iStatusPropAlg = SA_PROPAGATE_UNCHANGED;
79 static int m_iFixedStatus; // Status if propagation is "Fixed"
80 static int m_iStatusShift; // Shift value for "shifted" status propagation
81 static int m_iStatusTranslation[4];
82 static int m_iStatusSingleThreshold;
83 static int m_iStatusThresholds[4];
84
85
86 //
87 // Thread which apply template updates
88 //
89
90 static THREAD_RESULT THREAD_CALL ApplyTemplateThread(void *pArg)
91 {
92 TEMPLATE_UPDATE_INFO *pInfo;
93 NetObj *pNode;
94 BOOL bSuccess, bLock1, bLock2;
95
96 DbgPrintf(1, _T("Apply template thread started"));
97 while(1)
98 {
99 pInfo = (TEMPLATE_UPDATE_INFO *)g_pTemplateUpdateQueue->GetOrBlock();
100 if (pInfo == INVALID_POINTER_VALUE)
101 break;
102
103 DbgPrintf(5, _T("ApplyTemplateThread: template=%d(%s) updateType=%d node=%d removeDci=%d"),
104 pInfo->pTemplate->Id(), pInfo->pTemplate->Name(), pInfo->iUpdateType, pInfo->dwNodeId, pInfo->bRemoveDCI);
105 bSuccess = FALSE;
106 pNode = FindObjectById(pInfo->dwNodeId);
107 if (pNode != NULL)
108 {
109 if (pNode->Type() == OBJECT_NODE)
110 {
111 switch(pInfo->iUpdateType)
112 {
113 case APPLY_TEMPLATE:
114 bLock1 = pInfo->pTemplate->LockDCIList(0x7FFFFFFF, _T("SYSTEM"), NULL);
115 bLock2 = ((Node *)pNode)->LockDCIList(0x7FFFFFFF, _T("SYSTEM"), NULL);
116 if (bLock1 && bLock2)
117 {
118 pInfo->pTemplate->ApplyToNode((Node *)pNode);
119 bSuccess = TRUE;
120 }
121 if (bLock1)
122 pInfo->pTemplate->UnlockDCIList(0x7FFFFFFF);
123 if (bLock2)
124 ((Node *)pNode)->UnlockDCIList(0x7FFFFFFF);
125 break;
126 case REMOVE_TEMPLATE:
127 if (((Node *)pNode)->LockDCIList(0x7FFFFFFF, _T("SYSTEM"), NULL))
128 {
129 ((Node *)pNode)->unbindFromTemplate(pInfo->pTemplate->Id(), pInfo->bRemoveDCI);
130 ((Node *)pNode)->UnlockDCIList(0x7FFFFFFF);
131 bSuccess = TRUE;
132 }
133 break;
134 default:
135 bSuccess = TRUE;
136 break;
137 }
138 }
139 }
140
141 if (bSuccess)
142 {
143 DbgPrintf(8, _T("ApplyTemplateThread: success"));
144 pInfo->pTemplate->DecRefCount();
145 free(pInfo);
146 }
147 else
148 {
149 DbgPrintf(8, _T("ApplyTemplateThread: failed"));
150 g_pTemplateUpdateQueue->Put(pInfo); // Requeue
151 ThreadSleepMs(500);
152 }
153 }
154
155 DbgPrintf(1, _T("Apply template thread stopped"));
156 return THREAD_OK;
157 }
158
159
160 //
161 // DCI cache loading thread
162 //
163
164 static THREAD_RESULT THREAD_CALL CacheLoadingThread(void *pArg)
165 {
166 DWORD i;
167
168 DbgPrintf(1, _T("Started caching of DCI values"));
169 RWLockReadLock(g_rwlockNodeIndex, INFINITE);
170 for(i = 0; i < g_dwIdIndexSize; i++)
171 {
172 if (((NetObj *)g_pIndexById[i].pObject)->Type() == OBJECT_NODE)
173 {
174 ((Node *)g_pIndexById[i].pObject)->updateDciCache();
175 ThreadSleepMs(50); // Give a chance to other threads to do something with database
176 }
177 }
178 RWLockUnlock(g_rwlockNodeIndex);
179 DbgPrintf(1, _T("Finished caching of DCI values"));
180 return THREAD_OK;
181 }
182
183
184 //
185 // Initialize objects infrastructure
186 //
187
188 void ObjectsInit()
189 {
190 // Load default status calculation info
191 m_iStatusCalcAlg = ConfigReadInt(_T("StatusCalculationAlgorithm"), SA_CALCULATE_MOST_CRITICAL);
192 m_iStatusPropAlg = ConfigReadInt(_T("StatusPropagationAlgorithm"), SA_PROPAGATE_UNCHANGED);
193 m_iFixedStatus = ConfigReadInt(_T("FixedStatusValue"), STATUS_NORMAL);
194 m_iStatusShift = ConfigReadInt(_T("StatusShift"), 0);
195 ConfigReadByteArray(_T("StatusTranslation"), m_iStatusTranslation, 4, STATUS_WARNING);
196 m_iStatusSingleThreshold = ConfigReadInt(_T("StatusSingleThreshold"), 75);
197 ConfigReadByteArray(_T("StatusThresholds"), m_iStatusThresholds, 4, 50);
198
199 g_pTemplateUpdateQueue = new Queue;
200
201 g_rwlockIdIndex = RWLockCreate();
202 g_rwlockNodeIndex = RWLockCreate();
203 g_rwlockSubnetIndex = RWLockCreate();
204 g_rwlockInterfaceIndex = RWLockCreate();
205 g_rwlockZoneIndex = RWLockCreate();
206 g_rwlockConditionIndex = RWLockCreate();
207
208 // Create _T("Entire Network") object
209 g_pEntireNet = new Network;
210 NetObjInsert(g_pEntireNet, FALSE);
211
212 // Create _T("Service Root") object
213 g_pServiceRoot = new ServiceRoot;
214 NetObjInsert(g_pServiceRoot, FALSE);
215
216 // Create _T("Template Root") object
217 g_pTemplateRoot = new TemplateRoot;
218 NetObjInsert(g_pTemplateRoot, FALSE);
219
220 // Create _T("Policy Root") object
221 g_pPolicyRoot = new PolicyRoot;
222 NetObjInsert(g_pPolicyRoot, FALSE);
223
224 // Create _T("Network Maps Root") object
225 g_pMapRoot = new NetworkMapRoot;
226 NetObjInsert(g_pMapRoot, FALSE);
227
228 DbgPrintf(1, _T("Built-in objects created"));
229
230 // Start template update applying thread
231 ThreadCreate(ApplyTemplateThread, 0, NULL);
232 }
233
234
235 //
236 // Function to compare two indexes
237 //
238
239 static int IndexCompare(const void *pArg1, const void *pArg2)
240 {
241 return (((INDEX *)pArg1)->dwKey < ((INDEX *)pArg2)->dwKey) ? -1 :
242 ((((INDEX *)pArg1)->dwKey > ((INDEX *)pArg2)->dwKey) ? 1 : 0);
243 }
244
245
246 //
247 // Add new object to index
248 //
249
250 void AddObjectToIndex(INDEX **ppIndex, DWORD *pdwIndexSize, DWORD dwKey, void *pObject)
251 {
252 *ppIndex = (INDEX *)realloc(*ppIndex, sizeof(INDEX) * ((*pdwIndexSize) + 1));
253 (*ppIndex)[*pdwIndexSize].dwKey = dwKey;
254 (*ppIndex)[*pdwIndexSize].pObject = pObject;
255 (*pdwIndexSize)++;
256 qsort(*ppIndex, *pdwIndexSize, sizeof(INDEX), IndexCompare);
257 }
258
259
260 //
261 // Perform binary search on index
262 // Returns INVALID_INDEX if key not found or position of appropriate network object
263 // We assume that pIndex == NULL will not be passed
264 //
265
266 DWORD SearchIndex(INDEX *pIndex, DWORD dwIndexSize, DWORD dwKey)
267 {
268 DWORD dwFirst, dwLast, dwMid;
269
270 if (dwIndexSize == 0)
271 return INVALID_INDEX;
272
273 dwFirst = 0;
274 dwLast = dwIndexSize - 1;
275
276 if ((dwKey < pIndex[0].dwKey) || (dwKey > pIndex[dwLast].dwKey))
277 return INVALID_INDEX;
278
279 while(dwFirst < dwLast)
280 {
281 dwMid = (dwFirst + dwLast) / 2;
282 if (dwKey == pIndex[dwMid].dwKey)
283 return dwMid;
284 if (dwKey < pIndex[dwMid].dwKey)
285 dwLast = dwMid - 1;
286 else
287 dwFirst = dwMid + 1;
288 }
289
290 if (dwKey == pIndex[dwLast].dwKey)
291 return dwLast;
292
293 return INVALID_INDEX;
294 }
295
296
297 //
298 // Delete object from index
299 //
300
301 void DeleteObjectFromIndex(INDEX **ppIndex, DWORD *pdwIndexSize, DWORD dwKey)
302 {
303 DWORD dwPos;
304 INDEX *pIndex = *ppIndex;
305
306 dwPos = SearchIndex(pIndex, *pdwIndexSize, dwKey);
307 if (dwPos != INVALID_INDEX)
308 {
309 (*pdwIndexSize)--;
310 memmove(&pIndex[dwPos], &pIndex[dwPos + 1], sizeof(INDEX) * (*pdwIndexSize - dwPos));
311 }
312 }
313
314
315 //
316 // Insert new object into network
317 //
318
319 void NetObjInsert(NetObj *pObject, BOOL bNewObject)
320 {
321 if (bNewObject)
322 {
323 // Assign unique ID to new object
324 pObject->setId(CreateUniqueId(IDG_NETWORK_OBJECT));
325 pObject->generateGuid();
326
327 // Create table for storing data collection values
328 if (pObject->Type() == OBJECT_NODE)
329 {
330 TCHAR szQuery[256], szQueryTemplate[256];
331 DWORD i;
332
333 MetaDataReadStr(_T("IDataTableCreationCommand"), szQueryTemplate, 255, _T(""));
334 _sntprintf(szQuery, sizeof(szQuery) / sizeof(TCHAR), szQueryTemplate, pObject->Id());
335 DBQuery(g_hCoreDB, szQuery);
336
337 for(i = 0; i < 10; i++)
338 {
339 _sntprintf(szQuery, sizeof(szQuery) / sizeof(TCHAR), _T("IDataIndexCreationCommand_%d"), i);
340 MetaDataReadStr(szQuery, szQueryTemplate, 255, _T(""));
341 if (szQueryTemplate[0] != 0)
342 {
343 _sntprintf(szQuery, sizeof(szQuery) / sizeof(TCHAR), szQueryTemplate, pObject->Id(), pObject->Id());
344 DBQuery(g_hCoreDB, szQuery);
345 }
346 }
347 }
348 }
349 RWLockPreemptiveWriteLock(g_rwlockIdIndex, 1000, 500);
350 AddObjectToIndex(&g_pIndexById, &g_dwIdIndexSize, pObject->Id(), pObject);
351 RWLockUnlock(g_rwlockIdIndex);
352 if (!pObject->IsDeleted())
353 {
354 switch(pObject->Type())
355 {
356 case OBJECT_GENERIC:
357 case OBJECT_NETWORK:
358 case OBJECT_CONTAINER:
359 case OBJECT_SERVICEROOT:
360 case OBJECT_NETWORKSERVICE:
361 case OBJECT_TEMPLATE:
362 case OBJECT_TEMPLATEGROUP:
363 case OBJECT_TEMPLATEROOT:
364 case OBJECT_CLUSTER:
365 case OBJECT_VPNCONNECTOR:
366 case OBJECT_POLICYGROUP:
367 case OBJECT_POLICYROOT:
368 case OBJECT_AGENTPOLICY:
369 case OBJECT_AGENTPOLICY_CONFIG:
370 case OBJECT_NETWORKMAPROOT:
371 case OBJECT_NETWORKMAPGROUP:
372 case OBJECT_NETWORKMAP:
373 break;
374 case OBJECT_SUBNET:
375 if (pObject->IpAddr() != 0)
376 {
377 RWLockWriteLock(g_rwlockSubnetIndex, INFINITE);
378 AddObjectToIndex(&g_pSubnetIndexByAddr, &g_dwSubnetAddrIndexSize, pObject->IpAddr(), pObject);
379 RWLockUnlock(g_rwlockSubnetIndex);
380 if (bNewObject)
381 PostEvent(EVENT_SUBNET_ADDED, pObject->Id(), NULL);
382 }
383 break;
384 case OBJECT_NODE:
385 if (pObject->IpAddr() != 0)
386 {
387 RWLockWriteLock(g_rwlockNodeIndex, INFINITE);
388 AddObjectToIndex(&g_pNodeIndexByAddr, &g_dwNodeAddrIndexSize, pObject->IpAddr(), pObject);
389 RWLockUnlock(g_rwlockNodeIndex);
390 }
391 break;
392 case OBJECT_INTERFACE:
393 if (pObject->IpAddr() != 0)
394 {
395 RWLockWriteLock(g_rwlockInterfaceIndex, INFINITE);
396 if (SearchIndex(g_pInterfaceIndexByAddr, g_dwInterfaceAddrIndexSize, pObject->IpAddr()) == INVALID_INDEX)
397 AddObjectToIndex(&g_pInterfaceIndexByAddr, &g_dwInterfaceAddrIndexSize, pObject->IpAddr(), pObject);
398 else
399 DbgPrintf(1, _T("WARNING: duplicate interface IP address %08X (interface object %s [%d])"),
400 pObject->IpAddr(), pObject->Name(), (int)pObject->Id());
401 RWLockUnlock(g_rwlockInterfaceIndex);
402 }
403 break;
404 case OBJECT_ZONE:
405 RWLockWriteLock(g_rwlockZoneIndex, INFINITE);
406 AddObjectToIndex(&g_pZoneIndexByGUID, &g_dwZoneGUIDIndexSize, ((Zone *)pObject)->GUID(), pObject);
407 RWLockUnlock(g_rwlockZoneIndex);
408 break;
409 case OBJECT_CONDITION:
410 RWLockWriteLock(g_rwlockConditionIndex, INFINITE);
411 AddObjectToIndex(&g_pConditionIndex, &g_dwConditionIndexSize, pObject->Id(), pObject);
412 RWLockUnlock(g_rwlockConditionIndex);
413 break;
414 default:
415 nxlog_write(MSG_BAD_NETOBJ_TYPE, EVENTLOG_ERROR_TYPE, "d", pObject->Type());
416 break;
417 }
418 }
419 }
420
421
422 //
423 // Delete object from indexes
424 // If object has an IP address, this function will delete it from
425 // appropriate index. Normally this function should be called from
426 // NetObj::Delete() method.
427 //
428
429 void NetObjDeleteFromIndexes(NetObj *pObject)
430 {
431 switch(pObject->Type())
432 {
433 case OBJECT_GENERIC:
434 case OBJECT_NETWORK:
435 case OBJECT_CONTAINER:
436 case OBJECT_SERVICEROOT:
437 case OBJECT_NETWORKSERVICE:
438 case OBJECT_TEMPLATE:
439 case OBJECT_TEMPLATEGROUP:
440 case OBJECT_TEMPLATEROOT:
441 case OBJECT_CLUSTER:
442 case OBJECT_VPNCONNECTOR:
443 case OBJECT_POLICYGROUP:
444 case OBJECT_POLICYROOT:
445 case OBJECT_AGENTPOLICY:
446 case OBJECT_AGENTPOLICY_CONFIG:
447 case OBJECT_NETWORKMAPROOT:
448 case OBJECT_NETWORKMAPGROUP:
449 case OBJECT_NETWORKMAP:
450 break;
451 case OBJECT_SUBNET:
452 if (pObject->IpAddr() != 0)
453 {
454 RWLockWriteLock(g_rwlockSubnetIndex, INFINITE);
455 DeleteObjectFromIndex(&g_pSubnetIndexByAddr, &g_dwSubnetAddrIndexSize, pObject->IpAddr());
456 RWLockUnlock(g_rwlockSubnetIndex);
457 }
458 break;
459 case OBJECT_NODE:
460 if (pObject->IpAddr() != 0)
461 {
462 RWLockWriteLock(g_rwlockNodeIndex, INFINITE);
463 DeleteObjectFromIndex(&g_pNodeIndexByAddr, &g_dwNodeAddrIndexSize, pObject->IpAddr());
464 RWLockUnlock(g_rwlockNodeIndex);
465 }
466 break;
467 case OBJECT_INTERFACE:
468 if (pObject->IpAddr() != 0)
469 {
470 RWLockWriteLock(g_rwlockInterfaceIndex, INFINITE);
471 DeleteObjectFromIndex(&g_pInterfaceIndexByAddr, &g_dwInterfaceAddrIndexSize, pObject->IpAddr());
472 RWLockUnlock(g_rwlockInterfaceIndex);
473 }
474 break;
475 case OBJECT_ZONE:
476 RWLockWriteLock(g_rwlockZoneIndex, INFINITE);
477 DeleteObjectFromIndex(&g_pZoneIndexByGUID, &g_dwZoneGUIDIndexSize, ((Zone *)pObject)->GUID());
478 RWLockUnlock(g_rwlockZoneIndex);
479 break;
480 case OBJECT_CONDITION:
481 RWLockWriteLock(g_rwlockConditionIndex, INFINITE);
482 DeleteObjectFromIndex(&g_pConditionIndex, &g_dwConditionIndexSize, pObject->Id());
483 RWLockUnlock(g_rwlockConditionIndex);
484 break;
485 default:
486 nxlog_write(MSG_BAD_NETOBJ_TYPE, EVENTLOG_ERROR_TYPE, "d", pObject->Type());
487 break;
488 }
489 }
490
491
492 //
493 // Get IP netmask for object of any class
494 //
495
496 static DWORD GetObjectNetmask(NetObj *pObject)
497 {
498 switch(pObject->Type())
499 {
500 case OBJECT_INTERFACE:
501 return ((Interface *)pObject)->getIpNetMask();
502 case OBJECT_SUBNET:
503 return ((Subnet *)pObject)->getIpNetMask();
504 default:
505 return 0;
506 }
507 }
508
509
510 //
511 // Find node by IP address
512 //
513
514 Node NXCORE_EXPORTABLE *FindNodeByIP(DWORD dwAddr)
515 {
516 DWORD dwPos;
517 Node *pNode;
518
519 if ((g_pInterfaceIndexByAddr == NULL) || (dwAddr == 0))
520 return NULL;
521
522 RWLockReadLock(g_rwlockInterfaceIndex, INFINITE);
523 dwPos = SearchIndex(g_pInterfaceIndexByAddr, g_dwInterfaceAddrIndexSize, dwAddr);
524 pNode = (dwPos == INVALID_INDEX) ? NULL : ((Interface *)g_pInterfaceIndexByAddr[dwPos].pObject)->getParentNode();
525 RWLockUnlock(g_rwlockInterfaceIndex);
526 return pNode;
527 }
528
529
530 //
531 // Find node by MAC address
532 //
533
534 Node NXCORE_EXPORTABLE *FindNodeByMAC(const BYTE *macAddr)
535 {
536 Interface *pInterface = FindInterfaceByMAC(macAddr);
537 return (pInterface != NULL) ? pInterface->getParentNode() : NULL;
538 }
539
540
541 //
542 // Find interface by MAC address
543 //
544
545 Interface NXCORE_EXPORTABLE *FindInterfaceByMAC(const BYTE *macAddr)
546 {
547 if (!memcmp(macAddr, "\x00\x00\x00\x00\x00\x00", 6))
548 return NULL;
549
550 Interface *pInterface = NULL;
551 RWLockReadLock(g_rwlockIdIndex, INFINITE);
552 for(DWORD i = 0; i < g_dwIdIndexSize; i++)
553 {
554 if ((((NetObj *)g_pIndexById[i].pObject)->Type() == OBJECT_INTERFACE) &&
555 !memcmp(macAddr, ((Interface *)g_pIndexById[i].pObject)->getMacAddr(), 6))
556 {
557 pInterface = ((Interface *)g_pIndexById[i].pObject);
558 break;
559 }
560 }
561 RWLockUnlock(g_rwlockIdIndex);
562 return pInterface;
563 }
564
565
566 //
567 // Find node by LLDP ID
568 //
569
570 Node NXCORE_EXPORTABLE *FindNodeByLLDPId(const TCHAR *lldpId)
571 {
572 Node *node = NULL;
573 RWLockReadLock(g_rwlockIdIndex, INFINITE);
574 for(DWORD i = 0; i < g_dwIdIndexSize; i++)
575 {
576 if (((NetObj *)g_pIndexById[i].pObject)->Type() == OBJECT_NODE)
577 {
578 const TCHAR *id = ((Node *)g_pIndexById[i].pObject)->getLLDPNodeId();
579 if ((id != NULL) && !_tcscmp(id, lldpId))
580 {
581 node = (Node *)g_pIndexById[i].pObject;
582 break;
583 }
584 }
585 }
586 RWLockUnlock(g_rwlockIdIndex);
587 return node;
588 }
589
590
591 //
592 // Find subnet by IP address
593 //
594
595 Subnet NXCORE_EXPORTABLE *FindSubnetByIP(DWORD dwAddr)
596 {
597 DWORD dwPos;
598 Subnet *pSubnet;
599
600 if ((g_pSubnetIndexByAddr == NULL) || (dwAddr == 0))
601 return NULL;
602
603 RWLockReadLock(g_rwlockSubnetIndex, INFINITE);
604 dwPos = SearchIndex(g_pSubnetIndexByAddr, g_dwSubnetAddrIndexSize, dwAddr);
605 pSubnet = (dwPos == INVALID_INDEX) ? NULL : (Subnet *)g_pSubnetIndexByAddr[dwPos].pObject;
606 RWLockUnlock(g_rwlockSubnetIndex);
607 return pSubnet;
608 }
609
610
611 //
612 // Find subnet for given IP address
613 //
614
615 Subnet NXCORE_EXPORTABLE *FindSubnetForNode(DWORD dwNodeAddr)
616 {
617 DWORD i;
618 Subnet *pSubnet = NULL;
619
620 if ((g_pSubnetIndexByAddr == NULL) || (dwNodeAddr == 0))
621 return NULL;
622
623 RWLockReadLock(g_rwlockSubnetIndex, INFINITE);
624 for(i = 0; i < g_dwSubnetAddrIndexSize; i++)
625 if ((dwNodeAddr & ((Subnet *)g_pSubnetIndexByAddr[i].pObject)->getIpNetMask()) ==
626 ((Subnet *)g_pSubnetIndexByAddr[i].pObject)->IpAddr())
627 {
628 pSubnet = (Subnet *)g_pSubnetIndexByAddr[i].pObject;
629 break;
630 }
631 RWLockUnlock(g_rwlockSubnetIndex);
632 return pSubnet;
633 }
634
635
636 //
637 // Find object by ID
638 //
639
640 NetObj NXCORE_EXPORTABLE *FindObjectById(DWORD dwId)
641 {
642 DWORD dwPos;
643 NetObj *pObject;
644
645 if (g_pIndexById == NULL)
646 return NULL;
647
648 RWLockReadLock(g_rwlockIdIndex, INFINITE);
649 dwPos = SearchIndex(g_pIndexById, g_dwIdIndexSize, dwId);
650 pObject = (dwPos == INVALID_INDEX) ? NULL : (NetObj *)g_pIndexById[dwPos].pObject;
651 RWLockUnlock(g_rwlockIdIndex);
652 return pObject;
653 }
654
655
656 //
657 // Find object by name
658 //
659
660 NetObj NXCORE_EXPORTABLE *FindObjectByName(const TCHAR *name, int objClass)
661 {
662 DWORD i;
663 NetObj *pObject = NULL;
664
665 if (g_pIndexById == NULL)
666 return NULL;
667
668 RWLockReadLock(g_rwlockIdIndex, INFINITE);
669 for(i = 0; i < g_dwIdIndexSize; i++)
670 {
671 if ((!_tcsicmp(((NetObj *)g_pIndexById[i].pObject)->Name(), name)) &&
672 ((objClass == -1) || (objClass == ((NetObj *)g_pIndexById[i].pObject)->Type())))
673 {
674 pObject = (NetObj *)g_pIndexById[i].pObject;
675 break;
676 }
677 }
678 RWLockUnlock(g_rwlockIdIndex);
679 return pObject;
680 }
681
682
683 //
684 // Find object by GUID
685 //
686
687 NetObj NXCORE_EXPORTABLE *FindObjectByGUID(uuid_t guid, int objClass)
688 {
689 DWORD i;
690 uuid_t temp;
691 NetObj *pObject = NULL;
692
693 if (g_pIndexById == NULL)
694 return NULL;
695
696 RWLockReadLock(g_rwlockIdIndex, INFINITE);
697 for(i = 0; i < g_dwIdIndexSize; i++)
698 {
699 ((NetObj *)g_pIndexById[i].pObject)->getGuid(temp);
700 if (!uuid_compare(guid, temp) && ((objClass == -1) || (objClass == ((NetObj *)g_pIndexById[i].pObject)->Type())))
701 {
702 pObject = (NetObj *)g_pIndexById[i].pObject;
703 break;
704 }
705 }
706 RWLockUnlock(g_rwlockIdIndex);
707 return pObject;
708 }
709
710
711 //
712 // Find template object by name
713 //
714
715 Template NXCORE_EXPORTABLE *FindTemplateByName(const TCHAR *pszName)
716 {
717 DWORD i;
718 Template *pObject = NULL;
719
720 if (g_pIndexById == NULL)
721 return NULL;
722
723 RWLockReadLock(g_rwlockIdIndex, INFINITE);
724 for(i = 0; i < g_dwIdIndexSize; i++)
725 {
726 if ((((NetObj *)g_pIndexById[i].pObject)->Type() == OBJECT_TEMPLATE) &&
727 (!_tcsicmp(((NetObj *)g_pIndexById[i].pObject)->Name(), pszName)))
728 {
729 pObject = (Template *)g_pIndexById[i].pObject;
730 break;
731 }
732 }
733 RWLockUnlock(g_rwlockIdIndex);
734 return pObject;
735 }
736
737
738 //
739 // Find cluster by resource IP
740 //
741
742 Cluster NXCORE_EXPORTABLE *FindClusterByResourceIP(DWORD ipAddr)
743 {
744 Cluster *cluster = NULL;
745 RWLockReadLock(g_rwlockIdIndex, INFINITE);
746 for(DWORD i = 0; i < g_dwIdIndexSize; i++)
747 {
748 if (((NetObj *)g_pIndexById[i].pObject)->Type() == OBJECT_CLUSTER)
749 {
750 if (((Cluster *)g_pIndexById[i].pObject)->isVirtualAddr(ipAddr))
751 {
752 cluster = (Cluster *)g_pIndexById[i].pObject;
753 break;
754 }
755 }
756 }
757 RWLockUnlock(g_rwlockIdIndex);
758 return cluster;
759 }
760
761
762 //
763 // Check if given IP address is used by cluster (it's either
764 // resource IP or located on one of sync subnets)
765 //
766
767 bool NXCORE_EXPORTABLE IsClusterIP(DWORD ipAddr)
768 {
769 bool result = false;
770 RWLockReadLock(g_rwlockIdIndex, INFINITE);
771 for(DWORD i = 0; i < g_dwIdIndexSize; i++)
772 {
773 if (((NetObj *)g_pIndexById[i].pObject)->Type() == OBJECT_CLUSTER)
774 {
775 if (((Cluster *)g_pIndexById[i].pObject)->isVirtualAddr(ipAddr) ||
776 ((Cluster *)g_pIndexById[i].pObject)->isSyncAddr(ipAddr))
777 {
778 result = true;
779 break;
780 }
781 }
782 }
783 RWLockUnlock(g_rwlockIdIndex);
784 return result;
785 }
786
787
788 //
789 // Find zone object by GUID
790 //
791
792 Zone NXCORE_EXPORTABLE *FindZoneByGUID(DWORD dwZoneGUID)
793 {
794 DWORD dwPos;
795 NetObj *pObject;
796
797 if (g_pZoneIndexByGUID == NULL)
798 return NULL;
799
800 RWLockReadLock(g_rwlockZoneIndex, INFINITE);
801 dwPos = SearchIndex(g_pZoneIndexByGUID, g_dwZoneGUIDIndexSize, dwZoneGUID);
802 pObject = (dwPos == INVALID_INDEX) ? NULL : (NetObj *)g_pZoneIndexByGUID[dwPos].pObject;
803 RWLockUnlock(g_rwlockZoneIndex);
804 return (pObject->Type() == OBJECT_ZONE) ? (Zone *)pObject : NULL;
805 }
806
807
808 //
809 // Find local management node ID
810 //
811
812 DWORD FindLocalMgmtNode()
813 {
814 DWORD i, dwId = 0;
815
816 if (g_pNodeIndexByAddr == NULL)
817 return 0;
818
819 RWLockReadLock(g_rwlockNodeIndex, INFINITE);
820 for(i = 0; i < g_dwNodeAddrIndexSize; i++)
821 if (((Node *)g_pNodeIndexByAddr[i].pObject)->getFlags() & NF_IS_LOCAL_MGMT)
822 {
823 dwId = ((Node *)g_pNodeIndexByAddr[i].pObject)->Id();
824 break;
825 }
826 RWLockUnlock(g_rwlockNodeIndex);
827 return dwId;
828 }
829
830
831 //
832 // Load objects from database at stratup
833 //
834
835 BOOL LoadObjects()
836 {
837 DB_RESULT hResult;
838 DWORD i, dwNumRows;
839 DWORD dwId;
840 Template *pTemplate;
841 TCHAR szQuery[256];
842
843 // Prevent objects to change it's modification flag
844 g_bModificationsLocked = TRUE;
845
846 // Load container categories
847 DbgPrintf(2, _T("Loading container categories..."));
848 hResult = DBSelect(g_hCoreDB, _T("SELECT category,name,image_id,description FROM container_categories"));
849 if (hResult != NULL)
850 {
851 g_dwNumCategories = DBGetNumRows(hResult);
852 g_pContainerCatList = (CONTAINER_CATEGORY *)malloc(sizeof(CONTAINER_CATEGORY) * g_dwNumCategories);
853 for(i = 0; i < (int)g_dwNumCategories; i++)
854 {
855 g_pContainerCatList[i].dwCatId = DBGetFieldULong(hResult, i, 0);
856 DBGetField(hResult, i, 1, g_pContainerCatList[i].szName, MAX_OBJECT_NAME);
857 g_pContainerCatList[i].dwImageId = DBGetFieldULong(hResult, i, 2);
858 g_pContainerCatList[i].pszDescription = DBGetField(hResult, i, 3, NULL, 0);
859 DecodeSQLString(g_pContainerCatList[i].pszDescription);
860 }
861 DBFreeResult(hResult);
862 }
863
864 // Load built-in object properties
865 DbgPrintf(2, _T("Loading built-in object properties..."));
866 g_pEntireNet->LoadFromDB();
867 g_pServiceRoot->LoadFromDB();
868 g_pTemplateRoot->LoadFromDB();
869 g_pPolicyRoot->LoadFromDB();
870 g_pMapRoot->LoadFromDB();
871
872 // Load zones
873 if (g_dwFlags & AF_ENABLE_ZONING)
874 {
875 Zone *pZone;
876
877 DbgPrintf(2, _T("Loading zones..."));
878
879 // Load (or create) default zone
880 pZone = new Zone;
881 pZone->CreateFromDB(BUILTIN_OID_ZONE0);
882 NetObjInsert(pZone, FALSE);
883 g_pEntireNet->AddZone(pZone);
884
885 hResult = DBSelect(g_hCoreDB, _T("SELECT id FROM zones WHERE id<>4"));
886 if (hResult != 0)
887 {
888 dwNumRows = DBGetNumRows(hResult);
889 for(i = 0; i < dwNumRows; i++)
890 {
891 dwId = DBGetFieldULong(hResult, i, 0);
892 pZone = new Zone;
893 if (pZone->CreateFromDB(dwId))
894 {
895 if (!pZone->IsDeleted())
896 g_pEntireNet->AddZone(pZone);
897 NetObjInsert(pZone, FALSE); // Insert into indexes
898 }
899 else // Object load failed
900 {
901 delete pZone;
902 nxlog_write(MSG_ZONE_LOAD_FAILED, EVENTLOG_ERROR_TYPE, "d", dwId);
903 }
904 }
905 DBFreeResult(hResult);
906 }
907 }
908
909 // Load conditions
910 // We should load conditions before nodes because
911 // DCI cache size calculation uses information from condition objects
912 DbgPrintf(2, _T("Loading conditions..."));
913 hResult = DBSelect(g_hCoreDB, _T("SELECT id FROM conditions"));
914 if (hResult != NULL)
915 {
916 Condition *pCondition;
917
918 dwNumRows = DBGetNumRows(hResult);
919 for(i = 0; i < dwNumRows; i++)
920 {
921 dwId = DBGetFieldULong(hResult, i, 0);
922 pCondition = new Condition;
923 if (pCondition->CreateFromDB(dwId))
924 {
925 NetObjInsert(pCondition, FALSE); // Insert into indexes
926 }
927 else // Object load failed
928 {
929 delete pCondition;
930 nxlog_write(MSG_CONDITION_LOAD_FAILED, EVENTLOG_ERROR_TYPE, "d", dwId);
931 }
932 }
933 DBFreeResult(hResult);
934 }
935
936 // Load subnets
937 DbgPrintf(2, _T("Loading subnets..."));
938 hResult = DBSelect(g_hCoreDB, _T("SELECT id FROM subnets"));
939 if (hResult != 0)
940 {
941 Subnet *pSubnet;
942
943 dwNumRows = DBGetNumRows(hResult);
944 for(i = 0; i < dwNumRows; i++)
945 {
946 dwId = DBGetFieldULong(hResult, i, 0);
947 pSubnet = new Subnet;
948 if (pSubnet->CreateFromDB(dwId))
949 {
950 if (!pSubnet->IsDeleted())
951 {
952 if (g_dwFlags & AF_ENABLE_ZONING)
953 {
954 Zone *pZone;
955
956 pZone = FindZoneByGUID(pSubnet->getZoneGUID());
957 if (pZone != NULL)
958 pZone->AddSubnet(pSubnet);
959 }
960 else
961 {
962 g_pEntireNet->AddSubnet(pSubnet);
963 }
964 }
965 NetObjInsert(pSubnet, FALSE); // Insert into indexes
966 }
967 else // Object load failed
968 {
969 delete pSubnet;
970 nxlog_write(MSG_SUBNET_LOAD_FAILED, EVENTLOG_ERROR_TYPE, "d", dwId);
971 }
972 }
973 DBFreeResult(hResult);
974 }
975
976 // Load nodes
977 DbgPrintf(2, _T("Loading nodes..."));
978 hResult = DBSelect(g_hCoreDB, _T("SELECT id FROM nodes"));
979 if (hResult != 0)
980 {
981 Node *pNode;
982
983 dwNumRows = DBGetNumRows(hResult);
984 for(i = 0; i < dwNumRows; i++)
985 {
986 dwId = DBGetFieldULong(hResult, i, 0);
987 pNode = new Node;
988 if (pNode->CreateFromDB(dwId))
989 {
990 NetObjInsert(pNode, FALSE); // Insert into indexes
991 }
992 else // Object load failed
993 {
994 delete pNode;
995 nxlog_write(MSG_NODE_LOAD_FAILED, EVENTLOG_ERROR_TYPE, "d", dwId);
996 }
997 }
998 DBFreeResult(hResult);
999
1000 // Start cache loading thread
1001 ThreadCreate(CacheLoadingThread, 0, NULL);
1002 }
1003
1004 // Load interfaces
1005 DbgPrintf(2, _T("Loading interfaces..."));
1006 hResult = DBSelect(g_hCoreDB, _T("SELECT id FROM interfaces"));
1007 if (hResult != 0)
1008 {
1009 Interface *pInterface;
1010
1011 dwNumRows = DBGetNumRows(hResult);
1012 for(i = 0; i < dwNumRows; i++)
1013 {
1014 dwId = DBGetFieldULong(hResult, i, 0);
1015 pInterface = new Interface;
1016 if (pInterface->CreateFromDB(dwId))
1017 {
1018 NetObjInsert(pInterface, FALSE); // Insert into indexes
1019 }
1020 else // Object load failed
1021 {
1022 delete pInterface;
1023 nxlog_write(MSG_INTERFACE_LOAD_FAILED, EVENTLOG_ERROR_TYPE, "d", dwId);
1024 }
1025 }
1026 DBFreeResult(hResult);
1027 }
1028
1029 // Load network services
1030 DbgPrintf(2, _T("Loading network services..."));
1031 hResult = DBSelect(g_hCoreDB, _T("SELECT id FROM network_services"));
1032 if (hResult != 0)
1033 {
1034 NetworkService *pService;
1035
1036 dwNumRows = DBGetNumRows(hResult);
1037 for(i = 0; i < dwNumRows; i++)
1038 {
1039 dwId = DBGetFieldULong(hResult, i, 0);
1040 pService = new NetworkService;
1041 if (pService->CreateFromDB(dwId))
1042 {
1043 NetObjInsert(pService, FALSE); // Insert into indexes
1044 }
1045 else // Object load failed
1046 {
1047 delete pService;
1048 nxlog_write(MSG_NETSRV_LOAD_FAILED, EVENTLOG_ERROR_TYPE, "d", dwId);
1049 }
1050 }
1051 DBFreeResult(hResult);
1052 }
1053
1054 // Load VPN connectors
1055 DbgPrintf(2, _T("Loading VPN connectors..."));
1056 hResult = DBSelect(g_hCoreDB, _T("SELECT id FROM vpn_connectors"));
1057 if (hResult != NULL)
1058 {
1059 VPNConnector *pConnector;
1060
1061 dwNumRows = DBGetNumRows(hResult);
1062 for(i = 0; i < dwNumRows; i++)
1063 {
1064 dwId = DBGetFieldULong(hResult, i, 0);
1065 pConnector = new VPNConnector;
1066 if (pConnector->CreateFromDB(dwId))
1067 {
1068 NetObjInsert(pConnector, FALSE); // Insert into indexes
1069 }
1070 else // Object load failed
1071 {
1072 delete pConnector;
1073 nxlog_write(MSG_VPNC_LOAD_FAILED, EVENTLOG_ERROR_TYPE, "d", dwId);
1074 }
1075 }
1076 DBFreeResult(hResult);
1077 }
1078
1079 // Load clusters
1080 DbgPrintf(2, _T("Loading clusters..."));
1081 hResult = DBSelect(g_hCoreDB, _T("SELECT id FROM clusters"));
1082 if (hResult != NULL)
1083 {
1084 Cluster *pCluster;
1085
1086 dwNumRows = DBGetNumRows(hResult);
1087 for(i = 0; i < dwNumRows; i++)
1088 {
1089 dwId = DBGetFieldULong(hResult, i, 0);
1090 pCluster = new Cluster;
1091 if (pCluster->CreateFromDB(dwId))
1092 {
1093 NetObjInsert(pCluster, FALSE); // Insert into indexes
1094 }
1095 else // Object load failed
1096 {
1097 delete pCluster;
1098 nxlog_write(MSG_CLUSTER_LOAD_FAILED, EVENTLOG_ERROR_TYPE, "d", dwId);
1099 }
1100 }
1101 DBFreeResult(hResult);
1102 }
1103
1104 // Load templates
1105 DbgPrintf(2, _T("Loading templates..."));
1106 hResult = DBSelect(g_hCoreDB, _T("SELECT id FROM templates"));
1107 if (hResult != NULL)
1108 {
1109 dwNumRows = DBGetNumRows(hResult);
1110 for(i = 0; i < dwNumRows; i++)
1111 {
1112 dwId = DBGetFieldULong(hResult, i, 0);
1113 pTemplate = new Template;
1114 if (pTemplate->CreateFromDB(dwId))
1115 {
1116 NetObjInsert(pTemplate, FALSE); // Insert into indexes
1117 pTemplate->CalculateCompoundStatus(); // Force status change to NORMAL
1118 }
1119 else // Object load failed
1120 {
1121 delete pTemplate;
1122 nxlog_write(MSG_TEMPLATE_LOAD_FAILED, EVENTLOG_ERROR_TYPE, "d", dwId);
1123 }
1124 }
1125 DBFreeResult(hResult);
1126 }
1127
1128 // Load agent policies
1129 DbgPrintf(2, _T("Loading agent policies..."));
1130 hResult = DBSelect(g_hCoreDB, _T("SELECT id,policy_type FROM ap_common"));
1131 if (hResult != NULL)
1132 {
1133 dwNumRows = DBGetNumRows(hResult);
1134 for(i = 0; i < dwNumRows; i++)
1135 {
1136 AgentPolicy *policy;
1137
1138 dwId = DBGetFieldULong(hResult, i, 0);
1139 int type = DBGetFieldLong(hResult, i, 1);
1140 switch(type)
1141 {
1142 case AGENT_POLICY_CONFIG:
1143 policy = new AgentPolicyConfig();
1144 break;
1145 default:
1146 policy = new AgentPolicy(type);
1147 break;
1148 }
1149 if (policy->CreateFromDB(dwId))
1150 {
1151 NetObjInsert(policy, FALSE); // Insert into indexes
1152 policy->CalculateCompoundStatus(); // Force status change to NORMAL
1153 }
1154 else // Object load failed
1155 {
1156 delete policy;
1157 nxlog_write(MSG_AGENTPOLICY_LOAD_FAILED, EVENTLOG_ERROR_TYPE, "d", dwId);
1158 }
1159 }
1160 DBFreeResult(hResult);
1161 }
1162
1163 // Load agent policies
1164 DbgPrintf(2, _T("Loading network maps..."));
1165 hResult = DBSelect(g_hCoreDB, _T("SELECT id FROM network_maps"));
1166 if (hResult != NULL)
1167 {
1168 dwNumRows = DBGetNumRows(hResult);
1169 for(i = 0; i < dwNumRows; i++)
1170 {
1171 dwId = DBGetFieldULong(hResult, i, 0);
1172 NetworkMap *map = new NetworkMap;
1173 if (map->CreateFromDB(dwId))
1174 {
1175 NetObjInsert(map, FALSE); // Insert into indexes
1176 }
1177 else // Object load failed
1178 {
1179 delete map;
1180 nxlog_write(MSG_NETMAP_LOAD_FAILED, EVENTLOG_ERROR_TYPE, "d", dwId);
1181 }
1182 }
1183 DBFreeResult(hResult);
1184 }
1185
1186 // Load container objects
1187 DbgPrintf(2, _T("Loading containers..."));
1188 _sntprintf(szQuery, sizeof(szQuery) / sizeof(TCHAR), _T("SELECT id FROM containers WHERE object_class=%d"), OBJECT_CONTAINER);
1189 hResult = DBSelect(g_hCoreDB, szQuery);
1190 if (hResult != 0)
1191 {
1192 Container *pContainer;
1193
1194 dwNumRows = DBGetNumRows(hResult);
1195 for(i = 0; i < dwNumRows; i++)
1196 {
1197 dwId = DBGetFieldULong(hResult, i, 0);
1198 pContainer = new Container;
1199 if (pContainer->CreateFromDB(dwId))
1200 {
1201 NetObjInsert(pContainer, FALSE); // Insert into indexes
1202 }
1203 else // Object load failed
1204 {
1205 delete pContainer;
1206 nxlog_write(MSG_CONTAINER_LOAD_FAILED, EVENTLOG_ERROR_TYPE, "d", dwId);
1207 }
1208 }
1209 DBFreeResult(hResult);
1210 }
1211
1212 // Load template group objects
1213 DbgPrintf(2, _T("Loading template groups..."));
1214 _sntprintf(szQuery, sizeof(szQuery) / sizeof(TCHAR), _T("SELECT id FROM containers WHERE object_class=%d"), OBJECT_TEMPLATEGROUP);
1215 hResult = DBSelect(g_hCoreDB, szQuery);
1216 if (hResult != 0)
1217 {
1218 TemplateGroup *pGroup;
1219
1220 dwNumRows = DBGetNumRows(hResult);
1221 for(i = 0; i < dwNumRows; i++)
1222 {
1223 dwId = DBGetFieldULong(hResult, i, 0);
1224 pGroup = new TemplateGroup;
1225 if (pGroup->CreateFromDB(dwId))
1226 {
1227 NetObjInsert(pGroup, FALSE); // Insert into indexes
1228 }
1229 else // Object load failed
1230 {
1231 delete pGroup;
1232 nxlog_write(MSG_TG_LOAD_FAILED, EVENTLOG_ERROR_TYPE, "d", dwId);
1233 }
1234 }
1235 DBFreeResult(hResult);
1236 }
1237
1238 // Load policy group objects
1239 DbgPrintf(2, _T("Loading policy groups..."));
1240 _sntprintf(szQuery, sizeof(szQuery) / sizeof(TCHAR), _T("SELECT id FROM containers WHERE object_class=%d"), OBJECT_POLICYGROUP);
1241 hResult = DBSelect(g_hCoreDB, szQuery);
1242 if (hResult != 0)
1243 {
1244 PolicyGroup *pGroup;
1245
1246 dwNumRows = DBGetNumRows(hResult);
1247 for(i = 0; i < dwNumRows; i++)
1248 {
1249 dwId = DBGetFieldULong(hResult, i, 0);
1250 pGroup = new PolicyGroup;
1251 if (pGroup->CreateFromDB(dwId))
1252 {
1253 NetObjInsert(pGroup, FALSE); // Insert into indexes
1254 }
1255 else // Object load failed
1256 {
1257 delete pGroup;
1258 nxlog_write(MSG_PG_LOAD_FAILED, EVENTLOG_ERROR_TYPE, "d", dwId);
1259 }
1260 }
1261 DBFreeResult(hResult);
1262 }
1263
1264 // Load map group objects
1265 DbgPrintf(2, _T("Loading map groups..."));
1266 _sntprintf(szQuery, sizeof(szQuery) / sizeof(TCHAR), _T("SELECT id FROM containers WHERE object_class=%d"), OBJECT_NETWORKMAPGROUP);
1267 hResult = DBSelect(g_hCoreDB, szQuery);
1268 if (hResult != 0)
1269 {
1270 NetworkMapGroup *pGroup;
1271
1272 dwNumRows = DBGetNumRows(hResult);
1273 for(i = 0; i < dwNumRows; i++)
1274 {
1275 dwId = DBGetFieldULong(hResult, i, 0);
1276 pGroup = new NetworkMapGroup;
1277 if (pGroup->CreateFromDB(dwId))
1278 {
1279 NetObjInsert(pGroup, FALSE); // Insert into indexes
1280 }
1281 else // Object load failed
1282 {
1283 delete pGroup;
1284 nxlog_write(MSG_MG_LOAD_FAILED, EVENTLOG_ERROR_TYPE, "d", dwId);
1285 }
1286 }
1287 DBFreeResult(hResult);
1288 }
1289
1290 // Link childs to container and template group objects
1291 DbgPrintf(2, _T("Linking objects..."));
1292 for(i = 0; i < g_dwIdIndexSize; i++)
1293 if ((((NetObj *)g_pIndexById[i].pObject)->Type() == OBJECT_CONTAINER) ||
1294 (((NetObj *)g_pIndexById[i].pObject)->Type() == OBJECT_TEMPLATEGROUP) ||
1295 (((NetObj *)g_pIndexById[i].pObject)->Type() == OBJECT_POLICYGROUP) ||
1296 (((NetObj *)g_pIndexById[i].pObject)->Type() == OBJECT_NETWORKMAPGROUP))
1297 ((Container *)g_pIndexById[i].pObject)->LinkChildObjects();
1298
1299 // Link childs to _T("Service Root" and "Template Root") objects
1300 g_pServiceRoot->LinkChildObjects();
1301 g_pTemplateRoot->LinkChildObjects();
1302 g_pPolicyRoot->LinkChildObjects();
1303 g_pMapRoot->LinkChildObjects();
1304
1305 // Allow objects to change it's modification flag
1306 g_bModificationsLocked = FALSE;
1307
1308 // Recalculate status for built-in objects
1309 g_pEntireNet->CalculateCompoundStatus();
1310 g_pServiceRoot->CalculateCompoundStatus();
1311 g_pTemplateRoot->CalculateCompoundStatus();
1312 g_pPolicyRoot->CalculateCompoundStatus();
1313 g_pMapRoot->CalculateCompoundStatus();
1314
1315 // Recalculate status for zone objects
1316 if (g_dwFlags & AF_ENABLE_ZONING)
1317 {
1318 for(i = 0; i < g_dwZoneGUIDIndexSize; i++)
1319 ((NetObj *)g_pZoneIndexByGUID[i].pObject)->CalculateCompoundStatus();
1320 }
1321
1322 // Validate system templates and create when needed
1323 DbgPrintf(2, _T("Validating system templates..."));
1324
1325 pTemplate = FindTemplateByName(_T("@System.Agent"));
1326 if (pTemplate == NULL)
1327 {
1328 pTemplate = new Template(_T("@System.Agent"));
1329 pTemplate->SetSystemFlag(TRUE);
1330 NetObjInsert(pTemplate, TRUE);
1331 g_pTemplateRoot->AddChild(pTemplate);
1332 pTemplate->AddParent(g_pTemplateRoot);
1333 pTemplate->CalculateCompoundStatus();
1334 pTemplate->Unhide();
1335 }
1336 pTemplate->ValidateSystemTemplate();
1337
1338 /*
1339 TODO: probably system templates must be removed completely
1340
1341 pTemplate = FindTemplateByName(_T("@System.SNMP"));
1342 if (pTemplate == NULL)
1343 {
1344 pTemplate = new Template(_T("@System.SNMP"));
1345 pTemplate->SetSystemFlag(TRUE);
1346 NetObjInsert(pTemplate, TRUE);
1347 g_pTemplateRoot->AddChild(pTemplate);
1348 pTemplate->AddParent(g_pTemplateRoot);
1349 pTemplate->CalculateCompoundStatus();
1350 pTemplate->Unhide();
1351 }
1352 pTemplate->ValidateSystemTemplate();
1353 */
1354
1355 return TRUE;
1356 }
1357
1358
1359 //
1360 // Delete user or group from all objects' ACLs
1361 //
1362
1363 void DeleteUserFromAllObjects(DWORD dwUserId)
1364 {
1365 DWORD i;
1366
1367 // Walk through all objects
1368 RWLockReadLock(g_rwlockIdIndex, INFINITE);
1369 for(i = 0; i < g_dwIdIndexSize; i++)
1370 ((NetObj *)g_pIndexById[i].pObject)->DropUserAccess(dwUserId);
1371 RWLockUnlock(g_rwlockIdIndex);
1372 }
1373
1374
1375 //
1376 // Dump objects to console in standalone mode
1377 //
1378
1379 void DumpObjects(CONSOLE_CTX pCtx)
1380 {
1381 DWORD i;
1382 TCHAR *pBuffer;
1383 CONTAINER_CATEGORY *pCat;
1384 NetObj *pObject;
1385 time_t t;
1386 struct tm *ltm;
1387
1388 pBuffer = (TCHAR *)malloc(128000 * sizeof(TCHAR));
1389 RWLockReadLock(g_rwlockIdIndex, INFINITE);
1390 for(i = 0; i < g_dwIdIndexSize; i++)
1391 {
1392 pObject = (NetObj *)g_pIndexById[i].pObject;
1393 ConsolePrintf(pCtx, _T("Object ID %d \"%s\"\n")
1394 _T(" Class: %s Primary IP: %s Status: %s IsModified: %d IsDeleted: %d\n"),
1395 pObject->Id(), pObject->Name(), g_szClassName[pObject->Type()],
1396 IpToStr(pObject->IpAddr(), pBuffer),
1397 g_szStatusTextSmall[pObject->Status()],
1398 pObject->IsModified(), pObject->IsDeleted());
1399 ConsolePrintf(pCtx, _T(" Parents: <%s>\n Childs: <%s>\n"),
1400 pObject->ParentList(pBuffer), pObject->ChildList(&pBuffer[4096]));
1401 t = pObject->TimeStamp();
1402 ltm = localtime(&t);
1403 _tcsftime(pBuffer, 256, _T("%d.%b.%Y %H:%M:%S"), ltm);
1404 ConsolePrintf(pCtx, _T(" Last change: %s\n"), pBuffer);
1405 switch(pObject->Type())
1406 {
1407 case OBJECT_NODE:
1408 ConsolePrintf(pCtx, _T(" IsSNMP: %d IsAgent: %d IsLocal: %d OID: %s\n"),
1409 ((Node *)pObject)->isSNMPSupported(),
1410 ((Node *)pObject)->isNativeAgent(),
1411 ((Node *)pObject)->isLocalManagement(),
1412 ((Node *)pObject)->getObjectId());
1413 break;
1414 case OBJECT_SUBNET:
1415 ConsolePrintf(pCtx, _T(" Network mask: %s\n"),
1416 IpToStr(((Subnet *)pObject)->getIpNetMask(), pBuffer));
1417 break;
1418 case OBJECT_CONTAINER:
1419 pCat = FindContainerCategory(((Container *)pObject)->Category());
1420 ConsolePrintf(pCtx, _T(" Category: %s\n"), pCat ? pCat->szName : _T("<unknown>"));
1421 break;
1422 case OBJECT_TEMPLATE:
1423 ConsolePrintf(pCtx, _T(" Version: %d.%d\n"),
1424 ((Template *)(pObject))->getVersionMajor(),
1425 ((Template *)(pObject))->getVersionMinor());
1426 break;
1427 }
1428 }
1429 RWLockUnlock(g_rwlockIdIndex);
1430 free(pBuffer);
1431 }
1432
1433
1434 //
1435 // Check is given object class is a valid parent class for other object
1436 // This function is used to check manually created bindings, so it won't
1437 // return TRUE for node -- subnet for example
1438 //
1439
1440 BOOL IsValidParentClass(int iChildClass, int iParentClass)
1441 {
1442 switch(iParentClass)
1443 {
1444 case OBJECT_SERVICEROOT:
1445 case OBJECT_CONTAINER:
1446 if ((iChildClass == OBJECT_CONTAINER) ||
1447 (iChildClass == OBJECT_NODE) ||
1448 (iChildClass == OBJECT_CLUSTER) ||
1449 (iChildClass == OBJECT_CONDITION))
1450 return TRUE;
1451 break;
1452 case OBJECT_TEMPLATEROOT:
1453 case OBJECT_TEMPLATEGROUP:
1454 if ((iChildClass == OBJECT_TEMPLATEGROUP) ||
1455 (iChildClass == OBJECT_TEMPLATE))
1456 return TRUE;
1457 break;
1458 case OBJECT_NETWORKMAPROOT:
1459 case OBJECT_NETWORKMAPGROUP:
1460 if ((iChildClass == OBJECT_NETWORKMAPGROUP) ||
1461 (iChildClass == OBJECT_NETWORKMAP))
1462 return TRUE;
1463 break;
1464 case OBJECT_POLICYROOT:
1465 case OBJECT_POLICYGROUP:
1466 if ((iChildClass == OBJECT_POLICYGROUP) ||
1467 (iChildClass == OBJECT_AGENTPOLICY) ||
1468 (iChildClass == OBJECT_AGENTPOLICY_CONFIG))
1469 return TRUE;
1470 break;
1471 case OBJECT_NODE:
1472 if ((iChildClass == OBJECT_NETWORKSERVICE) ||
1473 (iChildClass == OBJECT_VPNCONNECTOR))
1474 return TRUE;
1475 break;
1476 case OBJECT_CLUSTER:
1477 if (iChildClass == OBJECT_NODE)
1478 return TRUE;
1479 break;
1480 case -1: // Creating object without parent
1481 if (iChildClass == OBJECT_NODE)
1482 return TRUE; // OK only for nodes, because parent subnet will be created automatically
1483 break;
1484 }
1485 return FALSE;
1486 }
1487
1488
1489 //
1490 // Delete object (final step)
1491 // This function should be called ONLY from syncer thread
1492 // Access to object index by id are write-locked when this function is called
1493 // Object will be removed from index by ID and destroyed.
1494 //
1495
1496 void NetObjDelete(NetObj *pObject)
1497 {
1498 TCHAR szQuery[256], szIpAddr[16], szNetMask[16];
1499
1500 // Write object to deleted objects table
1501 _sntprintf(szQuery, 256, _T("INSERT INTO deleted_objects (object_id,object_class,name,"
1502 _T("ip_addr,ip_netmask) VALUES (%d,%d,'%s','%s','%s')")),
1503 pObject->Id(), pObject->Type(), pObject->Name(),
1504 IpToStr(pObject->IpAddr(), szIpAddr),
1505 IpToStr(GetObjectNetmask(pObject), szNetMask));
1506 QueueSQLRequest(szQuery);
1507
1508 // Delete object from index by ID and object itself
1509 DeleteObjectFromIndex(&g_pIndexById, &g_dwIdIndexSize, pObject->Id());
1510 delete pObject;
1511 }
1512
1513
1514 //
1515 // Update node index when primary IP address changes
1516 //
1517
1518 void UpdateNodeIndex(DWORD dwOldIpAddr, DWORD dwNewIpAddr, NetObj *pObject)
1519 {
1520 DWORD dwPos;
1521
1522 RWLockWriteLock(g_rwlockNodeIndex, INFINITE);
1523 dwPos = SearchIndex(g_pNodeIndexByAddr, g_dwNodeAddrIndexSize, dwOldIpAddr);
1524 if (dwPos != INVALID_INDEX)
1525 {
1526 g_pNodeIndexByAddr[dwPos].dwKey = dwNewIpAddr;
1527 qsort(g_pNodeIndexByAddr, g_dwNodeAddrIndexSize, sizeof(INDEX), IndexCompare);
1528 }
1529 else
1530 {
1531 AddObjectToIndex(&g_pNodeIndexByAddr, &g_dwNodeAddrIndexSize, dwNewIpAddr, pObject);
1532 }
1533 RWLockUnlock(g_rwlockNodeIndex);
1534 }
1535
1536
1537 //
1538 // Update interface index when IP address changes
1539 //
1540
1541 void UpdateInterfaceIndex(DWORD dwOldIpAddr, DWORD dwNewIpAddr, NetObj *pObject)
1542 {
1543 DWORD dwPos;
1544
1545 RWLockWriteLock(g_rwlockInterfaceIndex, INFINITE);
1546 dwPos = SearchIndex(g_pInterfaceIndexByAddr, g_dwInterfaceAddrIndexSize, dwOldIpAddr);
1547 if (dwPos != INVALID_INDEX)
1548 {
1549 g_pInterfaceIndexByAddr[dwPos].dwKey = dwNewIpAddr;
1550 qsort(g_pInterfaceIndexByAddr, g_dwInterfaceAddrIndexSize, sizeof(INDEX), IndexCompare);
1551 }
1552 else
1553 {
1554 AddObjectToIndex(&g_pInterfaceIndexByAddr, &g_dwInterfaceAddrIndexSize, dwNewIpAddr, pObject);
1555 }
1556 RWLockUnlock(g_rwlockInterfaceIndex);
1557 }
1558
1559
1560 //
1561 // Calculate propagated status for object using default algorithm
1562 //
1563
1564 int DefaultPropagatedStatus(int iObjectStatus)
1565 {
1566 int iStatus;
1567
1568 switch(m_iStatusPropAlg)
1569 {
1570 case SA_PROPAGATE_UNCHANGED:
1571 iStatus = iObjectStatus;
1572 break;
1573 case SA_PROPAGATE_FIXED:
1574 iStatus = ((iObjectStatus > STATUS_NORMAL) && (iObjectStatus < STATUS_UNKNOWN)) ? m_iFixedStatus : iObjectStatus;
1575 break;
1576 case SA_PROPAGATE_RELATIVE:
1577 if ((iObjectStatus > STATUS_NORMAL) && (iObjectStatus < STATUS_UNKNOWN))
1578 {
1579 iStatus = iObjectStatus + m_iStatusShift;
1580 if (iStatus < 0)
1581 iStatus = 0;
1582 if (iStatus > STATUS_CRITICAL)
1583 iStatus = STATUS_CRITICAL;
1584 }
1585 else
1586 {
1587 iStatus = iObjectStatus;
1588 }
1589 break;
1590 case SA_PROPAGATE_TRANSLATED:
1591 if ((iObjectStatus > STATUS_NORMAL) && (iObjectStatus < STATUS_UNKNOWN))
1592 {
1593 iStatus = m_iStatusTranslation[iObjectStatus - 1];
1594 }
1595 else
1596 {
1597 iStatus = iObjectStatus;
1598 }
1599 break;
1600 default:
1601 iStatus = STATUS_UNKNOWN;
1602 break;
1603 }
1604 return iStatus;
1605 }
1606
1607
1608 //
1609 // Get default data for status calculation
1610 //
1611
1612 int GetDefaultStatusCalculation(int *pnSingleThreshold, int **ppnThresholds)
1613 {
1614 *pnSingleThreshold = m_iStatusSingleThreshold;
1615 *ppnThresholds = m_iStatusThresholds;
1616 return m_iStatusCalcAlg;
1617 }
1618
1619
1620 //
1621 // Check if given object is an agent policy object
1622 //
1623
1624 bool IsAgentPolicyObject(NetObj *object)
1625 {
1626 return (object->Type() == OBJECT_AGENTPOLICY) || (object->Type() == OBJECT_AGENTPOLICY_CONFIG);
1627 }