outdated object image stuff removed
[public/netxms.git] / src / libnxcl / objects.cpp
1 /*
2 ** NetXMS - Network Management System
3 ** Client Library
4 ** Copyright (C) 2004-2009 Victor Kirhenshtein
5 **
6 ** This program is free software; you can redistribute it and/or modify
7 ** it under the terms of the GNU General Public License as published by
8 ** the Free Software Foundation; either version 2 of the License, or
9 ** (at your option) any later version.
10 **
11 ** This program is distributed in the hope that it will be useful,
12 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 ** GNU General Public License for more details.
15 **
16 ** You should have received a copy of the GNU General Public License
17 ** along with this program; if not, write to the Free Software
18 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 **
20 ** File: objects.cpp
21 **
22 **/
23
24 #include "libnxcl.h"
25
26
27 //
28 // Destroy object
29 //
30
31 void DestroyObject(NXC_OBJECT *pObject)
32 {
33 DebugPrintf(_T("DestroyObject(id:%d, name:\"%s\")"), pObject->dwId, pObject->szName);
34 switch(pObject->iClass)
35 {
36 case OBJECT_NETWORKSERVICE:
37 safe_free(pObject->netsrv.pszRequest);
38 safe_free(pObject->netsrv.pszResponse);
39 break;
40 case OBJECT_ZONE:
41 safe_free(pObject->zone.pdwAddrList);
42 break;
43 case OBJECT_VPNCONNECTOR:
44 safe_free(pObject->vpnc.pLocalNetList);
45 safe_free(pObject->vpnc.pRemoteNetList);
46 break;
47 case OBJECT_CONDITION:
48 safe_free(pObject->cond.pszScript);
49 safe_free(pObject->cond.pDCIList);
50 break;
51 case OBJECT_CLUSTER:
52 safe_free(pObject->cluster.pSyncNetList);
53 safe_free(pObject->cluster.pResourceList);
54 break;
55 case OBJECT_TEMPLATE:
56 safe_free(pObject->dct.pszAutoApplyFilter);
57 break;
58 case OBJECT_CONTAINER:
59 safe_free(pObject->container.pszAutoBindFilter);
60 break;
61 }
62 safe_free(pObject->pdwChildList);
63 safe_free(pObject->pdwParentList);
64 safe_free(pObject->pAccessList);
65 safe_free(pObject->pszComments);
66 safe_free(pObject->pdwTrustedNodes);
67 delete pObject->pCustomAttrs;
68 free(pObject);
69 }
70
71
72 //
73 // Perform binary search on index
74 // Returns INVALID_INDEX if key not found or position of appropriate network object
75 // We assume that pIndex == NULL will not be passed
76 //
77
78 static DWORD SearchIndex(INDEX *pIndex, DWORD dwIndexSize, DWORD dwKey)
79 {
80 DWORD dwFirst, dwLast, dwMid;
81
82 if (dwIndexSize == 0)
83 return INVALID_INDEX;
84
85 dwFirst = 0;
86 dwLast = dwIndexSize - 1;
87
88 if ((dwKey < pIndex[0].dwKey) || (dwKey > pIndex[dwLast].dwKey))
89 return INVALID_INDEX;
90
91 while(dwFirst < dwLast)
92 {
93 dwMid = (dwFirst + dwLast) / 2;
94 if (dwKey == pIndex[dwMid].dwKey)
95 return dwMid;
96 if (dwKey < pIndex[dwMid].dwKey)
97 dwLast = dwMid - 1;
98 else
99 dwFirst = dwMid + 1;
100 }
101
102 if (dwKey == pIndex[dwLast].dwKey)
103 return dwLast;
104
105 return INVALID_INDEX;
106 }
107
108
109 //
110 // Index comparision callback for qsort()
111 //
112
113 static int IndexCompare(const void *pArg1, const void *pArg2)
114 {
115 return ((INDEX *)pArg1)->dwKey < ((INDEX *)pArg2)->dwKey ? -1 :
116 (((INDEX *)pArg1)->dwKey > ((INDEX *)pArg2)->dwKey ? 1 : 0);
117 }
118
119
120 //
121 // Add object to list
122 //
123
124 void NXCL_Session::AddObject(NXC_OBJECT *pObject, BOOL bSortIndex)
125 {
126 DebugPrintf(_T("AddObject(id:%d, name:\"%s\")"), pObject->dwId, pObject->szName);
127 LockObjectIndex();
128 m_pIndexById = (INDEX *)realloc(m_pIndexById, sizeof(INDEX) * (m_dwNumObjects + 1));
129 m_pIndexById[m_dwNumObjects].dwKey = pObject->dwId;
130 m_pIndexById[m_dwNumObjects].pObject = pObject;
131 m_dwNumObjects++;
132 if (bSortIndex)
133 qsort(m_pIndexById, m_dwNumObjects, sizeof(INDEX), IndexCompare);
134 UnlockObjectIndex();
135 }
136
137
138 //
139 // Replace object's data in list
140 //
141
142 static void ReplaceObject(NXC_OBJECT *pObject, NXC_OBJECT *pNewObject)
143 {
144 DebugPrintf(_T("ReplaceObject(id:%d, name:\"%s\")"), pObject->dwId, pObject->szName);
145 switch(pObject->iClass)
146 {
147 case OBJECT_NETWORKSERVICE:
148 safe_free(pObject->netsrv.pszRequest);
149 safe_free(pObject->netsrv.pszResponse);
150 break;
151 case OBJECT_ZONE:
152 safe_free(pObject->zone.pdwAddrList);
153 break;
154 case OBJECT_VPNCONNECTOR:
155 safe_free(pObject->vpnc.pLocalNetList);
156 safe_free(pObject->vpnc.pRemoteNetList);
157 break;
158 case OBJECT_CONDITION:
159 safe_free(pObject->cond.pszScript);
160 safe_free(pObject->cond.pDCIList);
161 break;
162 case OBJECT_CLUSTER:
163 safe_free(pObject->cluster.pSyncNetList);
164 safe_free(pObject->cluster.pResourceList);
165 break;
166 case OBJECT_TEMPLATE:
167 safe_free(pObject->dct.pszAutoApplyFilter);
168 break;
169 case OBJECT_CONTAINER:
170 safe_free(pObject->container.pszAutoBindFilter);
171 break;
172 }
173 safe_free(pObject->pdwChildList);
174 safe_free(pObject->pdwParentList);
175 safe_free(pObject->pAccessList);
176 safe_free(pObject->pszComments);
177 safe_free(pObject->pdwTrustedNodes);
178 delete pObject->pCustomAttrs;
179 memcpy(pObject, pNewObject, sizeof(NXC_OBJECT));
180 free(pNewObject);
181 }
182
183
184 //
185 // Create new object from message
186 //
187
188 static NXC_OBJECT *NewObjectFromMsg(CSCPMessage *pMsg)
189 {
190 NXC_OBJECT *pObject;
191 DWORD i, dwId1, dwId2, dwCount;
192
193 // Allocate memory for new object structure
194 pObject = (NXC_OBJECT *)malloc(sizeof(NXC_OBJECT));
195 memset(pObject, 0, sizeof(NXC_OBJECT));
196
197 // Common attributes
198 pObject->dwId = pMsg->GetVariableLong(VID_OBJECT_ID);
199 pObject->iClass = pMsg->GetVariableShort(VID_OBJECT_CLASS);
200 pMsg->GetVariableStr(VID_OBJECT_NAME, pObject->szName, MAX_OBJECT_NAME);
201 pObject->iStatus = pMsg->GetVariableShort(VID_OBJECT_STATUS);
202 pObject->dwIpAddr = pMsg->GetVariableLong(VID_IP_ADDRESS);
203 pObject->bIsDeleted = pMsg->GetVariableShort(VID_IS_DELETED);
204 pObject->iStatusCalcAlg = (int)pMsg->GetVariableShort(VID_STATUS_CALCULATION_ALG);
205 pObject->iStatusPropAlg = (int)pMsg->GetVariableShort(VID_STATUS_PROPAGATION_ALG);
206 pObject->iFixedStatus = (int)pMsg->GetVariableShort(VID_FIXED_STATUS);
207 pObject->iStatusShift = pMsg->GetVariableShortAsInt32(VID_STATUS_SHIFT);
208 pObject->iStatusTrans[0] = (int)pMsg->GetVariableShort(VID_STATUS_TRANSLATION_1);
209 pObject->iStatusTrans[1] = (int)pMsg->GetVariableShort(VID_STATUS_TRANSLATION_2);
210 pObject->iStatusTrans[2] = (int)pMsg->GetVariableShort(VID_STATUS_TRANSLATION_3);
211 pObject->iStatusTrans[3] = (int)pMsg->GetVariableShort(VID_STATUS_TRANSLATION_4);
212 pObject->iStatusSingleTh = (int)pMsg->GetVariableShort(VID_STATUS_SINGLE_THRESHOLD);
213 pObject->iStatusThresholds[0] = (int)pMsg->GetVariableShort(VID_STATUS_THRESHOLD_1);
214 pObject->iStatusThresholds[1] = (int)pMsg->GetVariableShort(VID_STATUS_THRESHOLD_2);
215 pObject->iStatusThresholds[2] = (int)pMsg->GetVariableShort(VID_STATUS_THRESHOLD_3);
216 pObject->iStatusThresholds[3] = (int)pMsg->GetVariableShort(VID_STATUS_THRESHOLD_4);
217 pObject->pszComments = pMsg->GetVariableStr(VID_COMMENTS);
218 pObject->dwNumTrustedNodes = pMsg->GetVariableLong(VID_NUM_TRUSTED_NODES);
219 if (pObject->dwNumTrustedNodes > 0)
220 {
221 pObject->pdwTrustedNodes = (DWORD *)malloc(sizeof(DWORD) * pObject->dwNumTrustedNodes);
222 pMsg->GetVariableInt32Array(VID_TRUSTED_NODES, pObject->dwNumTrustedNodes, pObject->pdwTrustedNodes);
223 }
224
225 // Custom attributes
226 pObject->pCustomAttrs = new StringMap;
227 dwCount = pMsg->GetVariableLong(VID_NUM_CUSTOM_ATTRIBUTES);
228 for(i = 0, dwId1 = VID_CUSTOM_ATTRIBUTES_BASE; i < dwCount; i++, dwId1 += 2)
229 {
230 pObject->pCustomAttrs->SetPreallocated(pMsg->GetVariableStr(dwId1), pMsg->GetVariableStr(dwId1 + 1));
231 }
232
233 // Parents
234 pObject->dwNumParents = pMsg->GetVariableLong(VID_PARENT_CNT);
235 pObject->pdwParentList = (DWORD *)malloc(sizeof(DWORD) * pObject->dwNumParents);
236 for(i = 0, dwId1 = VID_PARENT_ID_BASE; i < pObject->dwNumParents; i++, dwId1++)
237 pObject->pdwParentList[i] = pMsg->GetVariableLong(dwId1);
238
239 // Childs
240 pObject->dwNumChilds = pMsg->GetVariableLong(VID_CHILD_CNT);
241 pObject->pdwChildList = (DWORD *)malloc(sizeof(DWORD) * pObject->dwNumChilds);
242 for(i = 0, dwId1 = VID_CHILD_ID_BASE; i < pObject->dwNumChilds; i++, dwId1++)
243 pObject->pdwChildList[i] = pMsg->GetVariableLong(dwId1);
244
245 // Access control
246 pObject->bInheritRights = pMsg->GetVariableShort(VID_INHERIT_RIGHTS);
247 pObject->dwAclSize = pMsg->GetVariableLong(VID_ACL_SIZE);
248 pObject->pAccessList = (NXC_ACL_ENTRY *)malloc(sizeof(NXC_ACL_ENTRY) * pObject->dwAclSize);
249 for(i = 0, dwId1 = VID_ACL_USER_BASE, dwId2 = VID_ACL_RIGHTS_BASE;
250 i < pObject->dwAclSize; i++, dwId1++, dwId2++)
251 {
252 pObject->pAccessList[i].dwUserId = pMsg->GetVariableLong(dwId1);
253 pObject->pAccessList[i].dwAccessRights = pMsg->GetVariableLong(dwId2);
254 }
255
256 // Class-specific attributes
257 switch(pObject->iClass)
258 {
259 case OBJECT_INTERFACE:
260 pObject->iface.dwIpNetMask = pMsg->GetVariableLong(VID_IP_NETMASK);
261 pObject->iface.dwIfIndex = pMsg->GetVariableLong(VID_IF_INDEX);
262 pObject->iface.dwIfType = pMsg->GetVariableLong(VID_IF_TYPE);
263 pMsg->GetVariableBinary(VID_MAC_ADDR, pObject->iface.bMacAddr, MAC_ADDR_LENGTH);
264 pObject->iface.wRequiredPollCount = pMsg->GetVariableShort(VID_REQUIRED_POLLS);
265 break;
266 case OBJECT_NODE:
267 pObject->node.dwFlags = pMsg->GetVariableLong(VID_FLAGS);
268 pObject->node.dwNodeType = pMsg->GetVariableLong(VID_NODE_TYPE);
269 pObject->node.dwPollerNode = pMsg->GetVariableLong(VID_POLLER_NODE_ID);
270 pObject->node.dwProxyNode = pMsg->GetVariableLong(VID_PROXY_NODE);
271 pObject->node.dwSNMPProxy = pMsg->GetVariableLong(VID_SNMP_PROXY);
272 pObject->node.dwZoneGUID = pMsg->GetVariableLong(VID_ZONE_GUID);
273 pObject->node.wAgentPort = pMsg->GetVariableShort(VID_AGENT_PORT);
274 pObject->node.wAuthMethod = pMsg->GetVariableShort(VID_AUTH_METHOD);
275 pMsg->GetVariableStr(VID_SHARED_SECRET, pObject->node.szSharedSecret, MAX_SECRET_LENGTH);
276 pMsg->GetVariableStr(VID_COMMUNITY_STRING, pObject->node.szCommunityString, MAX_COMMUNITY_LENGTH);
277 pMsg->GetVariableStr(VID_SNMP_OID, pObject->node.szObjectId, MAX_OID_LENGTH);
278 pObject->node.nSNMPVersion = (BYTE)pMsg->GetVariableShort(VID_SNMP_VERSION);
279 pMsg->GetVariableStr(VID_AGENT_VERSION, pObject->node.szAgentVersion, MAX_AGENT_VERSION_LEN);
280 pMsg->GetVariableStr(VID_PLATFORM_NAME, pObject->node.szPlatformName, MAX_PLATFORM_NAME_LEN);
281 pObject->node.wRequiredPollCount = pMsg->GetVariableShort(VID_REQUIRED_POLLS);
282 pMsg->GetVariableStr(VID_SYS_DESCRIPTION, pObject->node.szSysDescription, MAX_DB_STRING);
283 pObject->node.nUseIfXTable = (BYTE)pMsg->GetVariableShort(VID_USE_IFXTABLE);
284 break;
285 case OBJECT_SUBNET:
286 pObject->subnet.dwIpNetMask = pMsg->GetVariableLong(VID_IP_NETMASK);
287 pObject->subnet.dwZoneGUID = pMsg->GetVariableLong(VID_ZONE_GUID);
288 break;
289 case OBJECT_CONTAINER:
290 pObject->container.dwCategory = pMsg->GetVariableLong(VID_CATEGORY);
291 pObject->container.isAutoBindEnabled = pMsg->GetVariableShort(VID_ENABLE_AUTO_BIND);
292 pObject->container.pszAutoBindFilter = pMsg->GetVariableStr(VID_AUTO_BIND_FILTER);
293 break;
294 case OBJECT_TEMPLATE:
295 pObject->dct.dwVersion = pMsg->GetVariableLong(VID_TEMPLATE_VERSION);
296 pObject->dct.isAutoApplyEnabled = pMsg->GetVariableShort(VID_AUTO_APPLY);
297 pObject->dct.pszAutoApplyFilter = pMsg->GetVariableStr(VID_APPLY_FILTER);
298 break;
299 case OBJECT_NETWORKSERVICE:
300 pObject->netsrv.iServiceType = (int)pMsg->GetVariableShort(VID_SERVICE_TYPE);
301 pObject->netsrv.wProto = pMsg->GetVariableShort(VID_IP_PROTO);
302 pObject->netsrv.wPort = pMsg->GetVariableShort(VID_IP_PORT);
303 pObject->netsrv.dwPollerNode = pMsg->GetVariableLong(VID_POLLER_NODE_ID);
304 pObject->netsrv.pszRequest = pMsg->GetVariableStr(VID_SERVICE_REQUEST);
305 pObject->netsrv.pszResponse = pMsg->GetVariableStr(VID_SERVICE_RESPONSE);
306 pObject->netsrv.wRequiredPollCount = pMsg->GetVariableShort(VID_REQUIRED_POLLS);
307 break;
308 case OBJECT_ZONE:
309 pObject->zone.dwZoneGUID = pMsg->GetVariableLong(VID_ZONE_GUID);
310 pObject->zone.wZoneType = pMsg->GetVariableShort(VID_ZONE_TYPE);
311 pObject->zone.dwControllerIpAddr = pMsg->GetVariableLong(VID_CONTROLLER_IP_ADDR);
312 pObject->zone.dwAddrListSize = pMsg->GetVariableLong(VID_ADDR_LIST_SIZE);
313 pObject->zone.pdwAddrList = (DWORD *)malloc(sizeof(DWORD) * pObject->zone.dwAddrListSize);
314 pMsg->GetVariableInt32Array(VID_IP_ADDR_LIST, pObject->zone.dwAddrListSize, pObject->zone.pdwAddrList);
315 break;
316 case OBJECT_VPNCONNECTOR:
317 pObject->vpnc.dwPeerGateway = pMsg->GetVariableLong(VID_PEER_GATEWAY);
318 pObject->vpnc.dwNumLocalNets = pMsg->GetVariableLong(VID_NUM_LOCAL_NETS);
319 pObject->vpnc.pLocalNetList = (IP_NETWORK *)malloc(sizeof(IP_NETWORK) * pObject->vpnc.dwNumLocalNets);
320 for(i = 0, dwId1 = VID_VPN_NETWORK_BASE; i < pObject->vpnc.dwNumLocalNets; i++)
321 {
322 pObject->vpnc.pLocalNetList[i].dwAddr = pMsg->GetVariableLong(dwId1++);
323 pObject->vpnc.pLocalNetList[i].dwMask = pMsg->GetVariableLong(dwId1++);
324 }
325 pObject->vpnc.dwNumRemoteNets = pMsg->GetVariableLong(VID_NUM_REMOTE_NETS);
326 pObject->vpnc.pRemoteNetList = (IP_NETWORK *)malloc(sizeof(IP_NETWORK) * pObject->vpnc.dwNumRemoteNets);
327 for(i = 0; i < pObject->vpnc.dwNumRemoteNets; i++)
328 {
329 pObject->vpnc.pRemoteNetList[i].dwAddr = pMsg->GetVariableLong(dwId1++);
330 pObject->vpnc.pRemoteNetList[i].dwMask = pMsg->GetVariableLong(dwId1++);
331 }
332 break;
333 case OBJECT_CONDITION:
334 pObject->cond.dwActivationEvent = pMsg->GetVariableLong(VID_ACTIVATION_EVENT);
335 pObject->cond.dwDeactivationEvent = pMsg->GetVariableLong(VID_DEACTIVATION_EVENT);
336 pObject->cond.dwSourceObject = pMsg->GetVariableLong(VID_SOURCE_OBJECT);
337 pObject->cond.pszScript = pMsg->GetVariableStr(VID_SCRIPT);
338 pObject->cond.wActiveStatus = pMsg->GetVariableShort(VID_ACTIVE_STATUS);
339 pObject->cond.wInactiveStatus = pMsg->GetVariableShort(VID_INACTIVE_STATUS);
340 pObject->cond.dwNumDCI = pMsg->GetVariableLong(VID_NUM_ITEMS);
341 pObject->cond.pDCIList = (INPUT_DCI *)malloc(sizeof(INPUT_DCI) * pObject->cond.dwNumDCI);
342 for(i = 0, dwId1 = VID_DCI_LIST_BASE; i < pObject->cond.dwNumDCI; i++)
343 {
344 pObject->cond.pDCIList[i].dwId = pMsg->GetVariableLong(dwId1++);
345 pObject->cond.pDCIList[i].dwNodeId = pMsg->GetVariableLong(dwId1++);
346 pObject->cond.pDCIList[i].nFunction = pMsg->GetVariableShort(dwId1++);
347 pObject->cond.pDCIList[i].nPolls = pMsg->GetVariableShort(dwId1++);
348 dwId1 += 6;
349 }
350 break;
351 case OBJECT_CLUSTER:
352 pObject->cluster.dwClusterType = pMsg->GetVariableLong(VID_CLUSTER_TYPE);
353 pObject->cluster.dwNumSyncNets = pMsg->GetVariableLong(VID_NUM_SYNC_SUBNETS);
354 pObject->cluster.pSyncNetList = (IP_NETWORK *)malloc(sizeof(IP_NETWORK) * pObject->cluster.dwNumSyncNets);
355 pMsg->GetVariableInt32Array(VID_SYNC_SUBNETS, pObject->cluster.dwNumSyncNets * 2, (DWORD *)pObject->cluster.pSyncNetList);
356 pObject->cluster.dwNumResources = pMsg->GetVariableLong(VID_NUM_RESOURCES);
357 if (pObject->cluster.dwNumResources > 0)
358 {
359 pObject->cluster.pResourceList = (CLUSTER_RESOURCE *)malloc(sizeof(CLUSTER_RESOURCE) * pObject->cluster.dwNumResources);
360 for(i = 0, dwId1 = VID_RESOURCE_LIST_BASE; i < pObject->cluster.dwNumResources; i++, dwId1 += 6)
361 {
362 pObject->cluster.pResourceList[i].dwId = pMsg->GetVariableLong(dwId1++);
363 pMsg->GetVariableStr(dwId1++, pObject->cluster.pResourceList[i].szName, MAX_DB_STRING);
364 pObject->cluster.pResourceList[i].dwIpAddr = pMsg->GetVariableLong(dwId1++);
365 pObject->cluster.pResourceList[i].dwCurrOwner = pMsg->GetVariableLong(dwId1++);
366 }
367 }
368 break;
369 default:
370 break;
371 }
372
373 return pObject;
374 }
375
376
377 //
378 // Process object information received from server
379 //
380
381 void NXCL_Session::ProcessObjectUpdate(CSCPMessage *pMsg)
382 {
383 NXC_OBJECT *pObject, *pNewObject;
384 TCHAR *pTmp;
385
386 switch(pMsg->GetCode())
387 {
388 case CMD_OBJECT_LIST_END:
389 if (!(m_dwFlags & NXC_SF_HAS_OBJECT_CACHE))
390 {
391 LockObjectIndex();
392 qsort(m_pIndexById, m_dwNumObjects, sizeof(INDEX), IndexCompare);
393 UnlockObjectIndex();
394 }
395 CompleteSync(SYNC_OBJECTS, RCC_SUCCESS);
396 break;
397 case CMD_OBJECT:
398 pTmp = pMsg->GetVariableStr(VID_OBJECT_NAME);
399 DebugPrintf(_T("RECV_OBJECT: ID=%d Name=\"%s\" Class=%d"), pMsg->GetVariableLong(VID_OBJECT_ID),
400 pTmp, pMsg->GetVariableShort(VID_OBJECT_CLASS));
401 free(pTmp);
402
403 // Create new object from message and add it to list
404 pNewObject = NewObjectFromMsg(pMsg);
405 if (m_dwFlags & NXC_SF_HAS_OBJECT_CACHE)
406 {
407 // We already have some objects loaded from cache file
408 pObject = FindObjectById(pNewObject->dwId, TRUE);
409 if (pObject == NULL)
410 {
411 AddObject(pNewObject, TRUE);
412 }
413 else
414 {
415 ReplaceObject(pObject, pNewObject);
416 }
417 }
418 else
419 {
420 // No cache file, all objects are new
421 AddObject(pNewObject, FALSE);
422 }
423 break;
424 case CMD_OBJECT_UPDATE:
425 pNewObject = NewObjectFromMsg(pMsg);
426 pObject = FindObjectById(pNewObject->dwId, TRUE);
427 if (pObject == NULL)
428 {
429 AddObject(pNewObject, TRUE);
430 pObject = pNewObject;
431 }
432 else
433 {
434 ReplaceObject(pObject, pNewObject);
435 }
436 CallEventHandler(NXC_EVENT_OBJECT_CHANGED, pObject->dwId, pObject);
437 break;
438 default:
439 break;
440 }
441 }
442
443
444 //
445 // Synchronize objects with the server
446 // This function is NOT REENTRANT
447 //
448
449 DWORD NXCL_Session::SyncObjects(const TCHAR *pszCacheFile, BOOL bSyncComments)
450 {
451 CSCPMessage msg;
452 DWORD dwRetCode, dwRqId;
453
454 dwRqId = CreateRqId();
455 PrepareForSync(SYNC_OBJECTS);
456
457 DestroyAllObjects();
458
459 m_dwFlags &= ~NXC_SF_HAS_OBJECT_CACHE;
460 if (pszCacheFile != NULL)
461 LoadObjectsFromCache(pszCacheFile);
462
463 msg.SetCode(CMD_GET_OBJECTS);
464 msg.SetId(dwRqId);
465 msg.SetVariable(VID_TIMESTAMP, m_dwTimeStamp);
466 msg.SetVariable(VID_SYNC_COMMENTS, (WORD)bSyncComments);
467 SendMsg(&msg);
468
469 dwRetCode = WaitForRCC(dwRqId);
470
471 // If request was successful, wait for object list end or for disconnection
472 if (dwRetCode == RCC_SUCCESS)
473 dwRetCode = WaitForSync(SYNC_OBJECTS, INFINITE);
474 else
475 UnlockSyncOp(SYNC_OBJECTS);
476
477 return dwRetCode;
478 }
479
480
481 //
482 // Wrappers for NXCL_Session::SyncObjects()
483 //
484
485 DWORD LIBNXCL_EXPORTABLE NXCSyncObjects(NXC_SESSION hSession)
486 {
487 return ((NXCL_Session *)hSession)->SyncObjects(NULL, FALSE);
488 }
489
490 DWORD LIBNXCL_EXPORTABLE NXCSyncObjectsEx(NXC_SESSION hSession, const TCHAR *pszCacheFile,
491 BOOL bSyncComments)
492 {
493 return ((NXCL_Session *)hSession)->SyncObjects(pszCacheFile, bSyncComments);
494 }
495
496
497 //
498 // Find object by ID
499 //
500
501 NXC_OBJECT *NXCL_Session::FindObjectById(DWORD dwId, BOOL bLock)
502 {
503 DWORD dwPos;
504 NXC_OBJECT *pObject;
505
506 if (bLock)
507 LockObjectIndex();
508
509 dwPos = SearchIndex(m_pIndexById, m_dwNumObjects, dwId);
510 pObject = (dwPos == INVALID_INDEX) ? NULL : m_pIndexById[dwPos].pObject;
511
512 if (bLock)
513 UnlockObjectIndex();
514
515 return pObject;
516 }
517
518 NXC_OBJECT LIBNXCL_EXPORTABLE *NXCFindObjectById(NXC_SESSION hSession, DWORD dwId)
519 {
520 return ((NXCL_Session *)hSession)->FindObjectById(dwId, TRUE);
521 }
522
523 NXC_OBJECT LIBNXCL_EXPORTABLE *NXCFindObjectByIdNoLock(NXC_SESSION hSession, DWORD dwId)
524 {
525 return ((NXCL_Session *)hSession)->FindObjectById(dwId, FALSE);
526 }
527
528
529 //
530 // Find object by name
531 //
532
533 NXC_OBJECT *NXCL_Session::FindObjectByName(TCHAR *pszName, DWORD dwCurrObject)
534 {
535 NXC_OBJECT *pObject = NULL;
536 DWORD i;
537
538 if (pszName != NULL)
539 if (*pszName != 0)
540 {
541 LockObjectIndex();
542
543 if (dwCurrObject != 0)
544 {
545 pObject = FindObjectById(dwCurrObject, FALSE);
546 if (pObject != NULL)
547 {
548 if (!RegexpMatch(pObject->szName, pszName, FALSE))
549 {
550 // Current object doesn't match, start search from the beginning
551 dwCurrObject = 0;
552 }
553 }
554 else
555 {
556 dwCurrObject = 0;
557 }
558 pObject = NULL;
559 }
560
561 for(i = 0; i < m_dwNumObjects; i++)
562 if (RegexpMatch(m_pIndexById[i].pObject->szName, pszName, FALSE))
563 {
564 if (dwCurrObject == 0)
565 {
566 pObject = m_pIndexById[i].pObject;
567 break;
568 }
569 else
570 {
571 if (m_pIndexById[i].dwKey == dwCurrObject)
572 {
573 dwCurrObject = 0; // Next match will stop the loop
574 }
575 }
576 }
577
578 UnlockObjectIndex();
579 }
580 return pObject;
581 }
582
583 NXC_OBJECT LIBNXCL_EXPORTABLE *NXCFindObjectByName(NXC_SESSION hSession, TCHAR *pszName, DWORD dwCurrObject)
584 {
585 return ((NXCL_Session *)hSession)->FindObjectByName(pszName, dwCurrObject);
586 }
587
588
589 //
590 // Find object by IP address
591 //
592
593 NXC_OBJECT *NXCL_Session::FindObjectByIPAddress(DWORD dwIpAddr, DWORD dwCurrObject)
594 {
595 NXC_OBJECT *pObject = NULL;
596 DWORD i;
597
598 LockObjectIndex();
599
600 if (dwCurrObject != 0)
601 {
602 pObject = FindObjectById(dwCurrObject, FALSE);
603 if (pObject != NULL)
604 {
605 if (pObject->dwIpAddr != dwIpAddr)
606 {
607 // Current object doesn't match, start search from the beginning
608 dwCurrObject = 0;
609 }
610 }
611 else
612 {
613 dwCurrObject = 0;
614 }
615 pObject = NULL;
616 }
617
618 for(i = 0; i < m_dwNumObjects; i++)
619 if (m_pIndexById[i].pObject->dwIpAddr == dwIpAddr)
620 {
621 if (dwCurrObject == 0)
622 {
623 pObject = m_pIndexById[i].pObject;
624 break;
625 }
626 else
627 {
628 if (m_pIndexById[i].dwKey == dwCurrObject)
629 {
630 dwCurrObject = 0; // Next match will stop the loop
631 }
632 }
633 }
634
635 UnlockObjectIndex();
636 return pObject;
637 }
638
639 NXC_OBJECT LIBNXCL_EXPORTABLE *NXCFindObjectByIPAddress(NXC_SESSION hSession, DWORD dwIpAddr, DWORD dwCurrObject)
640 {
641 return ((NXCL_Session *)hSession)->FindObjectByIPAddress(dwIpAddr, dwCurrObject);
642 }
643
644
645 //
646 // Enumerate all objects
647 //
648
649 void NXCL_Session::EnumerateObjects(BOOL (* pHandler)(NXC_OBJECT *))
650 {
651 DWORD i;
652
653 LockObjectIndex();
654 for(i = 0; i < m_dwNumObjects; i++)
655 if (!pHandler(m_pIndexById[i].pObject))
656 break;
657 UnlockObjectIndex();
658 }
659
660 void LIBNXCL_EXPORTABLE NXCEnumerateObjects(NXC_SESSION hSession, BOOL (* pHandler)(NXC_OBJECT *))
661 {
662 ((NXCL_Session *)hSession)->EnumerateObjects(pHandler);
663 }
664
665
666 //
667 // Get root object
668 //
669
670 NXC_OBJECT *NXCL_Session::GetRootObject(DWORD dwId, DWORD dwIndex)
671 {
672 if (m_dwNumObjects > dwIndex)
673 if (m_pIndexById[dwIndex].dwKey == dwId)
674 return m_pIndexById[dwIndex].pObject;
675 return NULL;
676 }
677
678
679 //
680 // Get topology root ("Entire Network") object
681 //
682
683 NXC_OBJECT LIBNXCL_EXPORTABLE *NXCGetTopologyRootObject(NXC_SESSION hSession)
684 {
685 return ((NXCL_Session *)hSession)->GetRootObject(1, 0);
686 }
687
688
689 //
690 // Get service tree root ("All Services") object
691 //
692
693 NXC_OBJECT LIBNXCL_EXPORTABLE *NXCGetServiceRootObject(NXC_SESSION hSession)
694 {
695 return ((NXCL_Session *)hSession)->GetRootObject(2, 1);
696 }
697
698
699 //
700 // Get template tree root ("Templates") object
701 //
702
703 NXC_OBJECT LIBNXCL_EXPORTABLE *NXCGetTemplateRootObject(NXC_SESSION hSession)
704 {
705 return ((NXCL_Session *)hSession)->GetRootObject(3, 2);
706 }
707
708
709 //
710 // Get pointer to first object on objects' list and entire number of objects
711 //
712
713 void *NXCL_Session::GetObjectIndex(DWORD *pdwNumObjects)
714 {
715 if (pdwNumObjects != NULL)
716 *pdwNumObjects = m_dwNumObjects;
717 return m_pIndexById;
718 }
719
720 void LIBNXCL_EXPORTABLE *NXCGetObjectIndex(NXC_SESSION hSession, DWORD *pdwNumObjects)
721 {
722 return ((NXCL_Session *)hSession)->GetObjectIndex(pdwNumObjects);
723 }
724
725
726 //
727 // Lock object index
728 //
729
730 void LIBNXCL_EXPORTABLE NXCLockObjectIndex(NXC_SESSION hSession)
731 {
732 ((NXCL_Session *)hSession)->LockObjectIndex();
733 }
734
735
736 //
737 // Unlock object index
738 //
739
740 void LIBNXCL_EXPORTABLE NXCUnlockObjectIndex(NXC_SESSION hSession)
741 {
742 ((NXCL_Session *)hSession)->UnlockObjectIndex();
743 }
744
745
746 //
747 // Modify object
748 //
749
750 DWORD LIBNXCL_EXPORTABLE NXCModifyObject(NXC_SESSION hSession, NXC_OBJECT_UPDATE *pUpdate)
751 {
752 CSCPMessage msg;
753 DWORD dwRqId, i, dwId1, dwId2;
754
755 dwRqId = ((NXCL_Session *)hSession)->CreateRqId();
756
757 // Build request message
758 msg.SetCode(CMD_MODIFY_OBJECT);
759 msg.SetId(dwRqId);
760 msg.SetVariable(VID_OBJECT_ID, pUpdate->dwObjectId);
761 if (pUpdate->qwFlags & OBJ_UPDATE_NAME)
762 msg.SetVariable(VID_OBJECT_NAME, pUpdate->pszName);
763 if (pUpdate->qwFlags & OBJ_UPDATE_AGENT_PORT)
764 msg.SetVariable(VID_AGENT_PORT, (WORD)pUpdate->iAgentPort);
765 if (pUpdate->qwFlags & OBJ_UPDATE_AGENT_AUTH)
766 msg.SetVariable(VID_AUTH_METHOD, (WORD)pUpdate->iAuthType);
767 if (pUpdate->qwFlags & OBJ_UPDATE_AGENT_SECRET)
768 msg.SetVariable(VID_SHARED_SECRET, pUpdate->pszSecret);
769 if (pUpdate->qwFlags & OBJ_UPDATE_SNMP_COMMUNITY)
770 msg.SetVariable(VID_COMMUNITY_STRING, pUpdate->pszCommunity);
771 if (pUpdate->qwFlags & OBJ_UPDATE_SNMP_VERSION)
772 msg.SetVariable(VID_SNMP_VERSION, pUpdate->wSNMPVersion);
773 if (pUpdate->qwFlags & OBJ_UPDATE_CHECK_REQUEST)
774 msg.SetVariable(VID_SERVICE_REQUEST, pUpdate->pszRequest);
775 if (pUpdate->qwFlags & OBJ_UPDATE_CHECK_RESPONSE)
776 msg.SetVariable(VID_SERVICE_RESPONSE, pUpdate->pszResponse);
777 if (pUpdate->qwFlags & OBJ_UPDATE_IP_PROTO)
778 msg.SetVariable(VID_IP_PROTO, pUpdate->wProto);
779 if (pUpdate->qwFlags & OBJ_UPDATE_IP_PORT)
780 msg.SetVariable(VID_IP_PORT, pUpdate->wPort);
781 if (pUpdate->qwFlags & OBJ_UPDATE_SERVICE_TYPE)
782 msg.SetVariable(VID_SERVICE_TYPE, (WORD)pUpdate->iServiceType);
783 if (pUpdate->qwFlags & OBJ_UPDATE_POLLER_NODE)
784 msg.SetVariable(VID_POLLER_NODE_ID, pUpdate->dwPollerNode);
785 if (pUpdate->qwFlags & OBJ_UPDATE_PROXY_NODE)
786 msg.SetVariable(VID_PROXY_NODE, pUpdate->dwProxyNode);
787 if (pUpdate->qwFlags & OBJ_UPDATE_SNMP_PROXY)
788 msg.SetVariable(VID_SNMP_PROXY, pUpdate->dwSNMPProxy);
789 if (pUpdate->qwFlags & OBJ_UPDATE_IP_ADDR)
790 msg.SetVariable(VID_IP_ADDRESS, pUpdate->dwIpAddr);
791 if (pUpdate->qwFlags & OBJ_UPDATE_PEER_GATEWAY)
792 msg.SetVariable(VID_PEER_GATEWAY, pUpdate->dwPeerGateway);
793 if (pUpdate->qwFlags & OBJ_UPDATE_NODE_FLAGS)
794 msg.SetVariable(VID_FLAGS, pUpdate->dwNodeFlags);
795 if (pUpdate->qwFlags & OBJ_UPDATE_ACT_EVENT)
796 msg.SetVariable(VID_ACTIVATION_EVENT, pUpdate->dwActivationEvent);
797 if (pUpdate->qwFlags & OBJ_UPDATE_DEACT_EVENT)
798 msg.SetVariable(VID_DEACTIVATION_EVENT, pUpdate->dwDeactivationEvent);
799 if (pUpdate->qwFlags & OBJ_UPDATE_SOURCE_OBJECT)
800 msg.SetVariable(VID_SOURCE_OBJECT, pUpdate->dwSourceObject);
801 if (pUpdate->qwFlags & OBJ_UPDATE_ACTIVE_STATUS)
802 msg.SetVariable(VID_ACTIVE_STATUS, (WORD)pUpdate->nActiveStatus);
803 if (pUpdate->qwFlags & OBJ_UPDATE_INACTIVE_STATUS)
804 msg.SetVariable(VID_INACTIVE_STATUS, (WORD)pUpdate->nInactiveStatus);
805 if (pUpdate->qwFlags & OBJ_UPDATE_SCRIPT)
806 msg.SetVariable(VID_SCRIPT, pUpdate->pszScript);
807 if (pUpdate->qwFlags & OBJ_UPDATE_CLUSTER_TYPE)
808 msg.SetVariable(VID_CLUSTER_TYPE, pUpdate->dwClusterType);
809 if (pUpdate->qwFlags & OBJ_UPDATE_REQUIRED_POLLS)
810 msg.SetVariable(VID_REQUIRED_POLLS, pUpdate->wRequiredPollCount);
811 if (pUpdate->qwFlags & OBJ_UPDATE_USE_IFXTABLE)
812 msg.SetVariable(VID_USE_IFXTABLE, (WORD)pUpdate->nUseIfXTable);
813 if (pUpdate->qwFlags & OBJ_UPDATE_STATUS_ALG)
814 {
815 msg.SetVariable(VID_STATUS_CALCULATION_ALG, (WORD)pUpdate->iStatusCalcAlg);
816 msg.SetVariable(VID_STATUS_PROPAGATION_ALG, (WORD)pUpdate->iStatusPropAlg);
817 msg.SetVariable(VID_FIXED_STATUS, (WORD)pUpdate->iFixedStatus);
818 msg.SetVariable(VID_STATUS_SHIFT, (WORD)pUpdate->iStatusShift);
819 msg.SetVariable(VID_STATUS_TRANSLATION_1, (WORD)pUpdate->iStatusTrans[0]);
820 msg.SetVariable(VID_STATUS_TRANSLATION_2, (WORD)pUpdate->iStatusTrans[1]);
821 msg.SetVariable(VID_STATUS_TRANSLATION_3, (WORD)pUpdate->iStatusTrans[2]);
822 msg.SetVariable(VID_STATUS_TRANSLATION_4, (WORD)pUpdate->iStatusTrans[3]);
823 msg.SetVariable(VID_STATUS_SINGLE_THRESHOLD, (WORD)pUpdate->iStatusSingleTh);
824 msg.SetVariable(VID_STATUS_THRESHOLD_1, (WORD)pUpdate->iStatusThresholds[0]);
825 msg.SetVariable(VID_STATUS_THRESHOLD_2, (WORD)pUpdate->iStatusThresholds[1]);
826 msg.SetVariable(VID_STATUS_THRESHOLD_3, (WORD)pUpdate->iStatusThresholds[2]);
827 msg.SetVariable(VID_STATUS_THRESHOLD_4, (WORD)pUpdate->iStatusThresholds[3]);
828 }
829 if (pUpdate->qwFlags & OBJ_UPDATE_NETWORK_LIST)
830 {
831 msg.SetVariable(VID_NUM_LOCAL_NETS, pUpdate->dwNumLocalNets);
832 msg.SetVariable(VID_NUM_REMOTE_NETS, pUpdate->dwNumRemoteNets);
833 for(i = 0, dwId1 = VID_VPN_NETWORK_BASE; i < pUpdate->dwNumLocalNets; i++)
834 {
835 msg.SetVariable(dwId1++, pUpdate->pLocalNetList[i].dwAddr);
836 msg.SetVariable(dwId1++, pUpdate->pLocalNetList[i].dwMask);
837 }
838 for(i = 0; i < pUpdate->dwNumRemoteNets; i++)
839 {
840 msg.SetVariable(dwId1++, pUpdate->pRemoteNetList[i].dwAddr);
841 msg.SetVariable(dwId1++, pUpdate->pRemoteNetList[i].dwMask);
842 }
843 }
844 if (pUpdate->qwFlags & OBJ_UPDATE_ACL)
845 {
846 msg.SetVariable(VID_ACL_SIZE, pUpdate->dwAclSize);
847 msg.SetVariable(VID_INHERIT_RIGHTS, (WORD)pUpdate->bInheritRights);
848 for(i = 0, dwId1 = VID_ACL_USER_BASE, dwId2 = VID_ACL_RIGHTS_BASE;
849 i < pUpdate->dwAclSize; i++, dwId1++, dwId2++)
850 {
851 msg.SetVariable(dwId1, pUpdate->pAccessList[i].dwUserId);
852 msg.SetVariable(dwId2, pUpdate->pAccessList[i].dwAccessRights);
853 }
854 }
855 if (pUpdate->qwFlags & OBJ_UPDATE_DCI_LIST)
856 {
857 msg.SetVariable(VID_NUM_ITEMS, pUpdate->dwNumDCI);
858 for(i = 0, dwId1 = VID_DCI_LIST_BASE; i < pUpdate->dwNumDCI; i++)
859 {
860 msg.SetVariable(dwId1++, pUpdate->pDCIList[i].dwId);
861 msg.SetVariable(dwId1++, pUpdate->pDCIList[i].dwNodeId);
862 msg.SetVariable(dwId1++, (WORD)pUpdate->pDCIList[i].nFunction);
863 msg.SetVariable(dwId1++, (WORD)pUpdate->pDCIList[i].nPolls);
864 dwId1 += 6;
865 }
866 }
867 if (pUpdate->qwFlags & OBJ_UPDATE_SYNC_NETS)
868 {
869 msg.SetVariable(VID_NUM_SYNC_SUBNETS, pUpdate->dwNumSyncNets);
870 msg.SetVariableToInt32Array(VID_SYNC_SUBNETS, pUpdate->dwNumSyncNets * 2, (DWORD *)pUpdate->pSyncNetList);
871 }
872 if (pUpdate->qwFlags & OBJ_UPDATE_RESOURCES)
873 {
874 msg.SetVariable(VID_NUM_RESOURCES, pUpdate->dwNumResources);
875 for(i = 0, dwId1 = VID_RESOURCE_LIST_BASE; i < pUpdate->dwNumResources; i++, dwId1 += 7)
876 {
877 msg.SetVariable(dwId1++, pUpdate->pResourceList[i].dwId);
878 msg.SetVariable(dwId1++, pUpdate->pResourceList[i].szName);
879 msg.SetVariable(dwId1++, pUpdate->pResourceList[i].dwIpAddr);
880 }
881 }
882 if (pUpdate->qwFlags & OBJ_UPDATE_TRUSTED_NODES)
883 {
884 msg.SetVariable(VID_NUM_TRUSTED_NODES, pUpdate->dwNumTrustedNodes);
885 msg.SetVariableToInt32Array(VID_TRUSTED_NODES, pUpdate->dwNumTrustedNodes, pUpdate->pdwTrustedNodes);
886 }
887 if (pUpdate->qwFlags & OBJ_UPDATE_CUSTOM_ATTRS)
888 {
889 msg.SetVariable(VID_NUM_CUSTOM_ATTRIBUTES, pUpdate->pCustomAttrs->Size());
890 for(i = 0, dwId1 = VID_CUSTOM_ATTRIBUTES_BASE; i < pUpdate->pCustomAttrs->Size(); i++)
891 {
892 msg.SetVariable(dwId1++, pUpdate->pCustomAttrs->GetKeyByIndex(i));
893 msg.SetVariable(dwId1++, pUpdate->pCustomAttrs->GetValueByIndex(i));
894 }
895 }
896 if (pUpdate->qwFlags & OBJ_UPDATE_AUTO_APPLY)
897 {
898 msg.SetVariable(VID_AUTO_APPLY, (WORD)pUpdate->isAutoApplyEnabled);
899 msg.SetVariable(VID_APPLY_FILTER, CHECK_NULL_EX(pUpdate->pszAutoApplyFilter));
900 }
901 if (pUpdate->qwFlags & OBJ_UPDATE_AUTO_BIND)
902 {
903 msg.SetVariable(VID_ENABLE_AUTO_BIND, (WORD)pUpdate->isAutoBindEnabled);
904 msg.SetVariable(VID_AUTO_BIND_FILTER, CHECK_NULL_EX(pUpdate->pszAutoBindFilter));
905 }
906
907 // Send request
908 ((NXCL_Session *)hSession)->SendMsg(&msg);
909
910 // Wait for reply
911 return ((NXCL_Session *)hSession)->WaitForRCC(dwRqId);
912 }
913
914
915 //
916 // Set object's mamagement status
917 //
918
919 DWORD LIBNXCL_EXPORTABLE NXCSetObjectMgmtStatus(NXC_SESSION hSession, DWORD dwObjectId,
920 BOOL bIsManaged)
921 {
922 CSCPMessage msg;
923 DWORD dwRqId;
924
925 dwRqId = ((NXCL_Session *)hSession)->CreateRqId();
926
927 // Build request message
928 msg.SetCode(CMD_SET_OBJECT_MGMT_STATUS);
929 msg.SetId(dwRqId);
930 msg.SetVariable(VID_OBJECT_ID, dwObjectId);
931 msg.SetVariable(VID_MGMT_STATUS, (WORD)bIsManaged);
932
933 // Send request
934 ((NXCL_Session *)hSession)->SendMsg(&msg);
935
936 // Wait for reply
937 return ((NXCL_Session *)hSession)->WaitForRCC(dwRqId);
938 }
939
940
941 //
942 // Create new object
943 //
944
945 DWORD LIBNXCL_EXPORTABLE NXCCreateObject(NXC_SESSION hSession,
946 NXC_OBJECT_CREATE_INFO *pCreateInfo,
947 DWORD *pdwObjectId)
948 {
949 CSCPMessage msg, *pResponse;
950 DWORD dwRqId, dwRetCode;
951
952 dwRqId = ((NXCL_Session *)hSession)->CreateRqId();
953
954 // Build request message
955 msg.SetCode(CMD_CREATE_OBJECT);
956 msg.SetId(dwRqId);
957 msg.SetVariable(VID_PARENT_ID, pCreateInfo->dwParentId);
958 msg.SetVariable(VID_OBJECT_CLASS, (WORD)pCreateInfo->iClass);
959 msg.SetVariable(VID_OBJECT_NAME, pCreateInfo->pszName);
960 if (pCreateInfo->pszComments != NULL)
961 msg.SetVariable(VID_COMMENTS, pCreateInfo->pszComments);
962 switch(pCreateInfo->iClass)
963 {
964 case OBJECT_NODE:
965 msg.SetVariable(VID_IP_ADDRESS, pCreateInfo->cs.node.dwIpAddr);
966 msg.SetVariable(VID_IP_NETMASK, pCreateInfo->cs.node.dwNetMask);
967 msg.SetVariable(VID_CREATION_FLAGS, pCreateInfo->cs.node.dwCreationFlags);
968 msg.SetVariable(VID_PROXY_NODE, pCreateInfo->cs.node.dwProxyNode);
969 msg.SetVariable(VID_SNMP_PROXY, pCreateInfo->cs.node.dwSNMPProxy);
970 break;
971 case OBJECT_CONTAINER:
972 msg.SetVariable(VID_CATEGORY, pCreateInfo->cs.container.dwCategory);
973 break;
974 case OBJECT_NETWORKSERVICE:
975 msg.SetVariable(VID_SERVICE_TYPE, (WORD)pCreateInfo->cs.netsrv.iServiceType);
976 msg.SetVariable(VID_IP_PROTO, pCreateInfo->cs.netsrv.wProto);
977 msg.SetVariable(VID_IP_PORT, pCreateInfo->cs.netsrv.wPort);
978 msg.SetVariable(VID_SERVICE_REQUEST, pCreateInfo->cs.netsrv.pszRequest);
979 msg.SetVariable(VID_SERVICE_RESPONSE, pCreateInfo->cs.netsrv.pszResponse);
980 break;
981 default:
982 break;
983 }
984
985 // Send request
986 ((NXCL_Session *)hSession)->SendMsg(&msg);
987
988 // Wait for response. Creating node object can include polling,
989 // which can take a minute or even more in worst cases
990 pResponse = ((NXCL_Session *)hSession)->WaitForMessage(CMD_REQUEST_COMPLETED, dwRqId, 300000);
991 if (pResponse != NULL)
992 {
993 dwRetCode = pResponse->GetVariableLong(VID_RCC);
994 if (dwRetCode == RCC_SUCCESS)
995 {
996 *pdwObjectId = pResponse->GetVariableLong(VID_OBJECT_ID);
997 }
998 delete pResponse;
999 }
1000 else
1001 {
1002 dwRetCode = RCC_TIMEOUT;
1003 }
1004
1005 return dwRetCode;
1006 }
1007
1008
1009 //
1010 // Bind/unbind objects
1011 //
1012
1013 static DWORD ChangeObjectBinding(NXCL_Session *pSession, DWORD dwParentObject,
1014 DWORD dwChildObject, BOOL bBind, BOOL bRemoveDCI)
1015 {
1016 CSCPMessage msg;
1017 DWORD dwRqId;
1018
1019 dwRqId = pSession->CreateRqId();
1020
1021 // Build request message
1022 msg.SetCode(bBind ? CMD_BIND_OBJECT : CMD_UNBIND_OBJECT);
1023 msg.SetId(dwRqId);
1024 msg.SetVariable(VID_PARENT_ID, dwParentObject);
1025 msg.SetVariable(VID_CHILD_ID, dwChildObject);
1026 if (!bBind)
1027 msg.SetVariable(VID_REMOVE_DCI, (WORD)bRemoveDCI);
1028
1029 // Send request
1030 pSession->SendMsg(&msg);
1031
1032 // Wait for reply
1033 return pSession->WaitForRCC(dwRqId);
1034 }
1035
1036
1037 //
1038 // Bind object
1039 //
1040
1041 DWORD LIBNXCL_EXPORTABLE NXCBindObject(NXC_SESSION hSession, DWORD dwParentObject,
1042 DWORD dwChildObject)
1043 {
1044 return ChangeObjectBinding((NXCL_Session *)hSession, dwParentObject,
1045 dwChildObject, TRUE, FALSE);
1046 }
1047
1048
1049 //
1050 // Unbind object
1051 //
1052
1053 DWORD LIBNXCL_EXPORTABLE NXCUnbindObject(NXC_SESSION hSession, DWORD dwParentObject,
1054 DWORD dwChildObject)
1055 {
1056 return ChangeObjectBinding((NXCL_Session *)hSession, dwParentObject,
1057 dwChildObject, FALSE, FALSE);
1058 }
1059
1060
1061 //
1062 // Remove template from node
1063 //
1064
1065 DWORD LIBNXCL_EXPORTABLE NXCRemoveTemplate(NXC_SESSION hSession, DWORD dwTemplateId,
1066 DWORD dwNodeId, BOOL bRemoveDCI)
1067 {
1068 return ChangeObjectBinding((NXCL_Session *)hSession, dwTemplateId,
1069 dwNodeId, FALSE, bRemoveDCI);
1070 }
1071
1072
1073 //
1074 // Delete object
1075 //
1076
1077 DWORD LIBNXCL_EXPORTABLE NXCDeleteObject(NXC_SESSION hSession, DWORD dwObject)
1078 {
1079 CSCPMessage msg;
1080 DWORD dwRqId;
1081
1082 dwRqId = ((NXCL_Session *)hSession)->CreateRqId();
1083
1084 // Build request message
1085 msg.SetCode(CMD_DELETE_OBJECT);
1086 msg.SetId(dwRqId);
1087 msg.SetVariable(VID_OBJECT_ID, dwObject);
1088
1089 // Send request
1090 ((NXCL_Session *)hSession)->SendMsg(&msg);
1091
1092 // Wait for reply
1093 // For node objects, deletion may take long time if object
1094 // is currently polled
1095 return ((NXCL_Session *)hSession)->WaitForRCC(dwRqId, 300000);
1096 }
1097
1098
1099 //
1100 // Load container categories
1101 //
1102
1103 DWORD LIBNXCL_EXPORTABLE NXCLoadCCList(NXC_SESSION hSession, NXC_CC_LIST **ppList)
1104 {
1105 CSCPMessage msg, *pResponse;
1106 DWORD dwRqId, dwRetCode = RCC_SUCCESS, dwNumCats = 0, dwCatId = 0;
1107
1108 dwRqId = ((NXCL_Session *)hSession)->CreateRqId();
1109
1110 msg.SetCode(CMD_GET_CONTAINER_CAT_LIST);
1111 msg.SetId(dwRqId);
1112 ((NXCL_Session *)hSession)->SendMsg(&msg);
1113
1114 *ppList = (NXC_CC_LIST *)malloc(sizeof(NXC_CC_LIST));
1115 (*ppList)->dwNumElements = 0;
1116 (*ppList)->pElements = NULL;
1117
1118 do
1119 {
1120 pResponse = ((NXCL_Session *)hSession)->WaitForMessage(CMD_CONTAINER_CAT_DATA, dwRqId);
1121 if (pResponse != NULL)
1122 {
1123 dwCatId = pResponse->GetVariableLong(VID_CATEGORY_ID);
1124 if (dwCatId != 0) // 0 is end of list indicator
1125 {
1126 (*ppList)->pElements = (NXC_CONTAINER_CATEGORY *)realloc((*ppList)->pElements,
1127 sizeof(NXC_CONTAINER_CATEGORY) * ((*ppList)->dwNumElements + 1));
1128 (*ppList)->pElements[(*ppList)->dwNumElements].dwId = dwCatId;
1129 pResponse->GetVariableStr(VID_CATEGORY_NAME,
1130 (*ppList)->pElements[(*ppList)->dwNumElements].szName, MAX_OBJECT_NAME);
1131 (*ppList)->pElements[(*ppList)->dwNumElements].pszDescription =
1132 pResponse->GetVariableStr(VID_DESCRIPTION);
1133 (*ppList)->dwNumElements++;
1134 }
1135 delete pResponse;
1136 }
1137 else
1138 {
1139 dwRetCode = RCC_TIMEOUT;
1140 dwCatId = 0;
1141 }
1142 }
1143 while(dwCatId != 0);
1144
1145 // Destroy results on failure
1146 if (dwRetCode != RCC_SUCCESS)
1147 {
1148 safe_free((*ppList)->pElements);
1149 free(*ppList);
1150 *ppList = NULL;
1151 }
1152
1153 return dwRetCode;
1154 }
1155
1156
1157 //
1158 // Destroy list of container categories
1159 //
1160
1161 void LIBNXCL_EXPORTABLE NXCDestroyCCList(NXC_CC_LIST *pList)
1162 {
1163 DWORD i;
1164
1165 if (pList == NULL)
1166 return;
1167
1168 for(i = 0; i < pList->dwNumElements; i++)
1169 safe_free(pList->pElements[i].pszDescription);
1170 safe_free(pList->pElements);
1171 free(pList);
1172 }
1173
1174
1175 //
1176 // Perform a forced node poll
1177 //
1178
1179 DWORD LIBNXCL_EXPORTABLE NXCPollNode(NXC_SESSION hSession, DWORD dwObjectId, int iPollType,
1180 void (* pfCallback)(TCHAR *, void *), void *pArg)
1181 {
1182 DWORD dwRetCode, dwRqId;
1183 CSCPMessage msg, *pResponse;
1184 TCHAR *pszMsg;
1185
1186 dwRqId = ((NXCL_Session *)hSession)->CreateRqId();
1187
1188 msg.SetCode(CMD_POLL_NODE);
1189 msg.SetId(dwRqId);
1190 msg.SetVariable(VID_OBJECT_ID, dwObjectId);
1191 msg.SetVariable(VID_POLL_TYPE, (WORD)iPollType);
1192 ((NXCL_Session *)hSession)->SendMsg(&msg);
1193
1194 do
1195 {
1196 // Polls can take a long time, so we wait up to 120 seconds for each message
1197 pResponse = ((NXCL_Session *)hSession)->WaitForMessage(CMD_POLLING_INFO, dwRqId, 120000);
1198 if (pResponse != NULL)
1199 {
1200 dwRetCode = pResponse->GetVariableLong(VID_RCC);
1201 if ((dwRetCode == RCC_OPERATION_IN_PROGRESS) && (pfCallback != NULL))
1202 {
1203 pszMsg = pResponse->GetVariableStr(VID_POLLER_MESSAGE);
1204 pfCallback(pszMsg, pArg);
1205 free(pszMsg);
1206 }
1207 delete pResponse;
1208 }
1209 else
1210 {
1211 dwRetCode = RCC_TIMEOUT;
1212 }
1213 }
1214 while(dwRetCode == RCC_OPERATION_IN_PROGRESS);
1215
1216 return dwRetCode;
1217 }
1218
1219
1220 //
1221 // Wake up node by sending magic packet
1222 //
1223
1224 DWORD LIBNXCL_EXPORTABLE NXCWakeUpNode(NXC_SESSION hSession, DWORD dwObjectId)
1225 {
1226 DWORD dwRqId;
1227 CSCPMessage msg;
1228
1229 dwRqId = ((NXCL_Session *)hSession)->CreateRqId();
1230
1231 msg.SetCode(CMD_WAKEUP_NODE);
1232 msg.SetId(dwRqId);
1233 msg.SetVariable(VID_OBJECT_ID, dwObjectId);
1234 ((NXCL_Session *)hSession)->SendMsg(&msg);
1235 return ((NXCL_Session *)hSession)->WaitForRCC(dwRqId);
1236 }
1237
1238
1239 //
1240 // Retrieve list of supported agent parameters
1241 //
1242
1243 DWORD LIBNXCL_EXPORTABLE NXCGetSupportedParameters(NXC_SESSION hSession, DWORD dwNodeId,
1244 DWORD *pdwNumParams,
1245 NXC_AGENT_PARAM **ppParamList)
1246 {
1247 CSCPMessage msg, *pResponse;
1248 DWORD i, dwId, dwRqId, dwRetCode;
1249
1250 dwRqId = ((NXCL_Session *)hSession)->CreateRqId();
1251
1252 *pdwNumParams = 0;
1253 *ppParamList = NULL;
1254
1255 // Build request message
1256 msg.SetCode(CMD_GET_PARAMETER_LIST);
1257 msg.SetId(dwRqId);
1258 msg.SetVariable(VID_OBJECT_ID, dwNodeId);
1259
1260 // Send request
1261 ((NXCL_Session *)hSession)->SendMsg(&msg);
1262
1263 // Wait for response
1264 pResponse = ((NXCL_Session *)hSession)->WaitForMessage(CMD_REQUEST_COMPLETED, dwRqId);
1265 if (pResponse != NULL)
1266 {
1267 dwRetCode = pResponse->GetVariableLong(VID_RCC);
1268 if (dwRetCode == RCC_SUCCESS)
1269 {
1270 *pdwNumParams = pResponse->GetVariableLong(VID_NUM_PARAMETERS);
1271 *ppParamList = (NXC_AGENT_PARAM *)malloc(sizeof(NXC_AGENT_PARAM) * *pdwNumParams);
1272 for(i = 0, dwId = VID_PARAM_LIST_BASE; i < *pdwNumParams; i++)
1273 {
1274 pResponse->GetVariableStr(dwId++, (*ppParamList)[i].szName, MAX_PARAM_NAME);
1275 pResponse->GetVariableStr(dwId++, (*ppParamList)[i].szDescription, MAX_DB_STRING);
1276 (*ppParamList)[i].iDataType = (int)pResponse->GetVariableShort(dwId++);
1277 }
1278 }
1279 delete pResponse;
1280 }
1281 else
1282 {
1283 dwRetCode = RCC_TIMEOUT;
1284 }
1285
1286 return dwRetCode;
1287 }
1288
1289
1290 //
1291 // Check if object has default name formed from IP address
1292 //
1293
1294 static BOOL ObjectHasDefaultName(NXC_OBJECT *pObject)
1295 {
1296 if (pObject->iClass == OBJECT_SUBNET)
1297 {
1298 TCHAR szBuffer[64], szIpAddr[32];
1299 _sntprintf(szBuffer, 64, _T("%s/%d"), IpToStr(pObject->dwIpAddr, szIpAddr),
1300 BitsInMask(pObject->subnet.dwIpNetMask));
1301 return !_tcscmp(szBuffer, pObject->szName);
1302 }
1303 else
1304 {
1305 return ((pObject->dwIpAddr != 0) &&
1306 (ntohl(_t_inet_addr(pObject->szName)) == pObject->dwIpAddr));
1307 }
1308 }
1309
1310
1311 //
1312 // Get object name suitable for comparision
1313 //
1314
1315 void LIBNXCL_EXPORTABLE NXCGetComparableObjectName(NXC_SESSION hSession, DWORD dwObjectId, TCHAR *pszName)
1316 {
1317 NXCGetComparableObjectNameEx(((NXCL_Session *)hSession)->FindObjectById(dwObjectId, TRUE), pszName);
1318 }
1319
1320
1321 //
1322 // Get object name suitable for comparision
1323 //
1324
1325 void LIBNXCL_EXPORTABLE NXCGetComparableObjectNameEx(NXC_OBJECT *pObject, TCHAR *pszName)
1326 {
1327 if (pObject != NULL)
1328 {
1329 // If object has an IP address as name, we sort as numbers
1330 // otherwise in alphabetical order
1331 if (ObjectHasDefaultName(pObject))
1332 {
1333 _sntprintf(pszName, MAX_OBJECT_NAME, _T("\x01%03d%03d%03d%03d"),
1334 pObject->dwIpAddr >> 24, (pObject->dwIpAddr >> 16) & 255,
1335 (pObject->dwIpAddr >> 8) & 255, pObject->dwIpAddr & 255);
1336 }
1337 else
1338 {
1339 _tcscpy(pszName, pObject->szName);
1340 }
1341 }
1342 else
1343 {
1344 *pszName = 0;
1345 }
1346 }
1347
1348
1349 //
1350 // Save object's cache to file
1351 //
1352
1353 DWORD LIBNXCL_EXPORTABLE NXCSaveObjectCache(NXC_SESSION hSession, const TCHAR *pszFile)
1354 {
1355 FILE *hFile;
1356 OBJECT_CACHE_HEADER hdr;
1357 DWORD i, j, dwResult, dwNumObjects, dwSize;
1358 INDEX *pList;
1359
1360 hFile = _tfopen(pszFile, _T("wb"));
1361 if (hFile != NULL)
1362 {
1363 ((NXCL_Session *)hSession)->LockObjectIndex();
1364 pList = (INDEX *)((NXCL_Session *)hSession)->GetObjectIndex(&dwNumObjects);
1365
1366 // Write cache file header
1367 hdr.dwMagic = OBJECT_CACHE_MAGIC;
1368 hdr.dwStructSize = sizeof(NXC_OBJECT);
1369 hdr.dwTimeStamp = ((NXCL_Session *)hSession)->GetTimeStamp();
1370 hdr.dwNumObjects = dwNumObjects;
1371 memcpy(hdr.bsServerId, ((NXCL_Session *)hSession)->m_bsServerId, 8);
1372 fwrite(&hdr, 1, sizeof(OBJECT_CACHE_HEADER), hFile);
1373
1374 // Write all objects
1375 for(i = 0; i < dwNumObjects; i++)
1376 {
1377 fwrite(pList[i].pObject, 1, sizeof(NXC_OBJECT), hFile);
1378 fwrite(pList[i].pObject->pdwChildList, 1,
1379 sizeof(DWORD) * pList[i].pObject->dwNumChilds, hFile);
1380 fwrite(pList[i].pObject->pdwParentList, 1,
1381 sizeof(DWORD) * pList[i].pObject->dwNumParents, hFile);
1382 fwrite(pList[i].pObject->pAccessList, 1,
1383 sizeof(NXC_ACL_ENTRY) * pList[i].pObject->dwAclSize, hFile);
1384
1385 dwSize = (DWORD)_tcslen(pList[i].pObject->pszComments) * sizeof(TCHAR);
1386 fwrite(&dwSize, 1, sizeof(DWORD), hFile);
1387 fwrite(pList[i].pObject->pszComments, 1, dwSize, hFile);
1388
1389 if (pList[i].pObject->dwNumTrustedNodes > 0)
1390 fwrite(pList[i].pObject->pdwTrustedNodes, pList[i].pObject->dwNumTrustedNodes, sizeof(DWORD), hFile);
1391
1392 // Custom attributes
1393 dwSize = pList[i].pObject->pCustomAttrs->Size();
1394 fwrite(&dwSize, 1, sizeof(DWORD), hFile);
1395 for(j = 0; j < pList[i].pObject->pCustomAttrs->Size(); j++)
1396 {
1397 dwSize = (DWORD)_tcslen(pList[i].pObject->pCustomAttrs->GetKeyByIndex(j)) * sizeof(TCHAR);
1398 fwrite(&dwSize, 1, sizeof(DWORD), hFile);
1399 fwrite(pList[i].pObject->pCustomAttrs->GetKeyByIndex(j), 1, dwSize, hFile);
1400
1401 dwSize = (DWORD)_tcslen(pList[i].pObject->pCustomAttrs->GetValueByIndex(j)) * sizeof(TCHAR);
1402 fwrite(&dwSize, 1, sizeof(DWORD), hFile);
1403 fwrite(pList[i].pObject->pCustomAttrs->GetValueByIndex(j), 1, dwSize, hFile);
1404 }
1405
1406 switch(pList[i].pObject->iClass)
1407 {
1408 case OBJECT_NETWORKSERVICE:
1409 dwSize = (DWORD)_tcslen(pList[i].pObject->netsrv.pszRequest) * sizeof(TCHAR);
1410 fwrite(&dwSize, 1, sizeof(DWORD), hFile);
1411 fwrite(pList[i].pObject->netsrv.pszRequest, 1, dwSize, hFile);
1412
1413 dwSize = (DWORD)_tcslen(pList[i].pObject->netsrv.pszResponse) * sizeof(TCHAR);
1414 fwrite(&dwSize, 1, sizeof(DWORD), hFile);
1415 fwrite(pList[i].pObject->netsrv.pszResponse, 1, dwSize, hFile);
1416 break;
1417 case OBJECT_ZONE:
1418 if (pList[i].pObject->zone.dwAddrListSize > 0)
1419 fwrite(pList[i].pObject->zone.pdwAddrList, sizeof(DWORD),
1420 pList[i].pObject->zone.dwAddrListSize, hFile);
1421 break;
1422 case OBJECT_VPNCONNECTOR:
1423 fwrite(pList[i].pObject->vpnc.pLocalNetList, 1,
1424 pList[i].pObject->vpnc.dwNumLocalNets * sizeof(IP_NETWORK), hFile);
1425 fwrite(pList[i].pObject->vpnc.pRemoteNetList, 1,
1426 pList[i].pObject->vpnc.dwNumRemoteNets * sizeof(IP_NETWORK), hFile);
1427 break;
1428 case OBJECT_CONDITION:
1429 dwSize = (DWORD)_tcslen(pList[i].pObject->cond.pszScript) * sizeof(TCHAR);
1430 fwrite(&dwSize, 1, sizeof(DWORD), hFile);
1431 fwrite(pList[i].pObject->cond.pszScript, 1, dwSize, hFile);
1432
1433 fwrite(pList[i].pObject->cond.pDCIList, 1,
1434 pList[i].pObject->cond.dwNumDCI * sizeof(INPUT_DCI), hFile);
1435 break;
1436 case OBJECT_CLUSTER:
1437 fwrite(pList[i].pObject->cluster.pResourceList, 1,
1438 pList[i].pObject->cluster.dwNumResources * sizeof(CLUSTER_RESOURCE), hFile);
1439 fwrite(pList[i].pObject->cluster.pSyncNetList, 1,
1440 pList[i].pObject->cluster.dwNumSyncNets * sizeof(IP_NETWORK), hFile);
1441 break;
1442 default:
1443 break;
1444 }
1445 }
1446
1447 ((NXCL_Session *)hSession)->UnlockObjectIndex();
1448 fclose(hFile);
1449 dwResult = RCC_SUCCESS;
1450 }
1451 else
1452 {
1453 dwResult = RCC_IO_ERROR;
1454 }
1455
1456 return dwResult;
1457 }
1458
1459
1460 //
1461 // Load objects from cache file
1462 //
1463
1464 void NXCL_Session::LoadObjectsFromCache(const TCHAR *pszFile)
1465 {
1466 FILE *hFile;
1467 OBJECT_CACHE_HEADER hdr;
1468 NXC_OBJECT object;
1469 DWORD i, j, dwSize, dwCount;
1470 TCHAR *key, *value;
1471
1472 hFile = _tfopen(pszFile, _T("rb"));
1473 if (hFile != NULL)
1474 {
1475 // Read header
1476 DebugPrintf(_T("Checking cache file %s"), pszFile);
1477 if (fread(&hdr, 1, sizeof(OBJECT_CACHE_HEADER), hFile) == sizeof(OBJECT_CACHE_HEADER))
1478 {
1479 if ((hdr.dwMagic == OBJECT_CACHE_MAGIC) &&
1480 (hdr.dwStructSize == sizeof(NXC_OBJECT)) &&
1481 (!memcmp(hdr.bsServerId, m_bsServerId, 8)))
1482 {
1483 DebugPrintf(_T("Cache file OK, loading objects"));
1484 m_dwTimeStamp = hdr.dwTimeStamp;
1485 for(i = 0; i < hdr.dwNumObjects; i++)
1486 {
1487 if (fread(&object, 1, sizeof(NXC_OBJECT), hFile) == sizeof(NXC_OBJECT))
1488 {
1489 object.pdwChildList = (DWORD *)malloc(sizeof(DWORD) * object.dwNumChilds);
1490 fread(object.pdwChildList, 1, sizeof(DWORD) * object.dwNumChilds, hFile);
1491
1492 object.pdwParentList = (DWORD *)malloc(sizeof(DWORD) * object.dwNumParents);
1493 fread(object.pdwParentList, 1, sizeof(DWORD) * object.dwNumParents, hFile);
1494
1495 object.pAccessList = (NXC_ACL_ENTRY *)malloc(sizeof(NXC_ACL_ENTRY) * object.dwAclSize);
1496 fread(object.pAccessList, 1, sizeof(NXC_ACL_ENTRY) * object.dwAclSize, hFile);
1497
1498 fread(&dwSize, 1, sizeof(DWORD), hFile);
1499 object.pszComments = (TCHAR *)malloc(dwSize + sizeof(TCHAR));
1500 fread(object.pszComments, 1, dwSize, hFile);
1501 object.pszComments[dwSize / sizeof(TCHAR)] = 0;
1502
1503 if (object.dwNumTrustedNodes > 0)
1504 {
1505 object.pdwTrustedNodes = (DWORD *)malloc(sizeof(DWORD) * object.dwNumTrustedNodes);
1506 fread(object.pdwTrustedNodes, sizeof(DWORD), object.dwNumTrustedNodes, hFile);
1507 }
1508 else
1509 {
1510 object.pdwTrustedNodes = NULL;
1511 }
1512
1513 // Custom attributes
1514 object.pCustomAttrs = new StringMap;
1515 fread(&dwCount, 1, sizeof(DWORD), hFile);
1516 for(j = 0; j < dwCount; j++)
1517 {
1518 fread(&dwSize, 1, sizeof(DWORD), hFile);
1519 key = (TCHAR *)malloc(dwSize + sizeof(TCHAR));
1520 fread(key, 1, dwSize, hFile);
1521 key[dwSize / sizeof(TCHAR)] = 0;
1522
1523 fread(&dwSize, 1, sizeof(DWORD), hFile);
1524 value = (TCHAR *)malloc(dwSize + sizeof(TCHAR));
1525 fread(value, 1, dwSize, hFile);
1526 value[dwSize / sizeof(TCHAR)] = 0;
1527
1528 object.pCustomAttrs->SetPreallocated(key, value);
1529 }
1530
1531 switch(object.iClass)
1532 {
1533 case OBJECT_NETWORKSERVICE:
1534 fread(&dwSize, 1, sizeof(DWORD), hFile);
1535 object.netsrv.pszRequest = (TCHAR *)malloc(dwSize + sizeof(TCHAR));
1536 fread(object.netsrv.pszRequest, 1, dwSize, hFile);
1537 object.netsrv.pszRequest[dwSize / sizeof(TCHAR)] = 0;
1538
1539 fread(&dwSize, 1, sizeof(DWORD), hFile);
1540 object.netsrv.pszResponse = (TCHAR *)malloc(dwSize + sizeof(TCHAR));
1541 fread(object.netsrv.pszResponse, 1, dwSize, hFile);
1542 object.netsrv.pszResponse[dwSize / sizeof(TCHAR)] = 0;
1543 break;
1544 case OBJECT_ZONE:
1545 if (object.zone.dwAddrListSize > 0)
1546 {
1547 object.zone.pdwAddrList = (DWORD *)malloc(object.zone.dwAddrListSize * sizeof(DWORD));
1548 fread(object.zone.pdwAddrList, sizeof(DWORD), object.zone.dwAddrListSize, hFile);
1549 }
1550 else
1551 {
1552 object.zone.pdwAddrList = NULL;
1553 }
1554 break;
1555 case OBJECT_VPNCONNECTOR:
1556 dwSize = object.vpnc.dwNumLocalNets * sizeof(IP_NETWORK);
1557 object.vpnc.pLocalNetList = (IP_NETWORK *)malloc(dwSize);
1558 fread(object.vpnc.pLocalNetList, 1, dwSize, hFile);
1559
1560 dwSize = object.vpnc.dwNumRemoteNets * sizeof(IP_NETWORK);
1561 object.vpnc.pRemoteNetList = (IP_NETWORK *)malloc(dwSize);
1562 fread(object.vpnc.pRemoteNetList, 1, dwSize, hFile);
1563 break;
1564 case OBJECT_CONDITION:
1565 fread(&dwSize, 1, sizeof(DWORD), hFile);
1566 object.cond.pszScript = (TCHAR *)malloc(dwSize + sizeof(TCHAR));
1567 fread(object.cond.pszScript, 1, dwSize, hFile);
1568 object.cond.pszScript[dwSize / sizeof(TCHAR)] = 0;
1569
1570 dwSize = object.cond.dwNumDCI * sizeof(INPUT_DCI);
1571 object.cond.pDCIList = (INPUT_DCI *)malloc(dwSize);
1572 fread(object.cond.pDCIList, 1, dwSize, hFile);
1573 break;
1574 case OBJECT_CLUSTER:
1575 if (object.cluster.dwNumResources > 0)
1576 {
1577 object.cluster.pResourceList = (CLUSTER_RESOURCE *)malloc(sizeof(CLUSTER_RESOURCE) * object.cluster.dwNumResources);
1578 fread(object.cluster.pResourceList, 1, sizeof(CLUSTER_RESOURCE) * object.cluster.dwNumResources, hFile);
1579 }
1580 else
1581 {
1582 object.cluster.pResourceList = NULL;
1583 }
1584 if (object.cluster.dwNumSyncNets > 0)
1585 {
1586 object.cluster.pSyncNetList = (IP_NETWORK *)malloc(sizeof(IP_NETWORK) * object.cluster.dwNumSyncNets);
1587 fread(object.cluster.pSyncNetList, 1, sizeof(IP_NETWORK) * object.cluster.dwNumSyncNets, hFile);
1588 }
1589 else
1590 {
1591 object.cluster.pSyncNetList = NULL;
1592 }
1593 break;
1594 default:
1595 break;
1596 }
1597
1598 AddObject((NXC_OBJECT *)nx_memdup(&object, sizeof(NXC_OBJECT)), FALSE);
1599 }
1600 }
1601 LockObjectIndex();
1602 qsort(m_pIndexById, m_dwNumObjects, sizeof(INDEX), IndexCompare);
1603 UnlockObjectIndex();
1604 m_dwFlags |= NXC_SF_HAS_OBJECT_CACHE;
1605 }
1606 }
1607
1608 fclose(hFile);
1609 }
1610 }
1611
1612
1613 //
1614 // Change node's IP address
1615 //
1616
1617 DWORD LIBNXCL_EXPORTABLE NXCChangeNodeIP(NXC_SESSION hSession, DWORD dwNodeId, DWORD dwIpAddr)
1618 {
1619 DWORD dwRqId;
1620 CSCPMessage msg;
1621
1622 dwRqId = ((NXCL_Session *)hSession)->CreateRqId();
1623
1624 msg.SetCode(CMD_CHANGE_IP_ADDR);
1625 msg.SetId(dwRqId);
1626 msg.SetVariable(VID_OBJECT_ID, dwNodeId);
1627 msg.SetVariable(VID_IP_ADDRESS, dwIpAddr);
1628 ((NXCL_Session *)hSession)->SendMsg(&msg);
1629 return ((NXCL_Session *)hSession)->WaitForRCC(dwRqId, 300000);
1630 }
1631
1632
1633 //
1634 // Read agent's configuration file
1635 //
1636
1637 DWORD LIBNXCL_EXPORTABLE NXCGetAgentConfig(NXC_SESSION hSession, DWORD dwNodeId,
1638 TCHAR **ppszConfig)
1639 {
1640 CSCPMessage msg, *pResponse;
1641 DWORD dwRqId, dwRetCode;
1642
1643 dwRqId = ((NXCL_Session *)hSession)->CreateRqId();
1644
1645 *ppszConfig = NULL;
1646
1647 // Build request message
1648 msg.SetCode(CMD_GET_AGENT_CONFIG);
1649 msg.SetId(dwRqId);
1650 msg.SetVariable(VID_OBJECT_ID, dwNodeId);
1651
1652 // Send request
1653 ((NXCL_Session *)hSession)->SendMsg(&msg);
1654
1655 // Wait for response
1656 pResponse = ((NXCL_Session *)hSession)->WaitForMessage(CMD_REQUEST_COMPLETED, dwRqId, 60000);
1657 if (pResponse != NULL)
1658 {
1659 dwRetCode = pResponse->GetVariableLong(VID_RCC);
1660 if (dwRetCode == RCC_SUCCESS)
1661 {
1662 *ppszConfig = pResponse->GetVariableStr(VID_CONFIG_FILE);
1663 }
1664 delete pResponse;
1665 }
1666 else
1667 {
1668 dwRetCode = RCC_TIMEOUT;
1669 }
1670
1671 return dwRetCode;
1672 }
1673
1674
1675 //
1676 // Update agent's configuration file
1677 //
1678
1679 DWORD LIBNXCL_EXPORTABLE NXCUpdateAgentConfig(NXC_SESSION hSession, DWORD dwNodeId,
1680 TCHAR *pszConfig, BOOL bApply)
1681 {
1682 CSCPMessage msg;
1683 DWORD dwRqId;
1684
1685 dwRqId = ((NXCL_Session *)hSession)->CreateRqId();
1686
1687 // Build request message
1688 msg.SetCode(CMD_UPDATE_AGENT_CONFIG);
1689 msg.SetId(dwRqId);
1690 msg.SetVariable(VID_OBJECT_ID, dwNodeId);
1691 msg.SetVariable(VID_CONFIG_FILE, pszConfig);
1692 msg.SetVariable(VID_APPLY_FLAG, (WORD)bApply);
1693
1694 // Send request
1695 ((NXCL_Session *)hSession)->SendMsg(&msg);
1696
1697 return ((NXCL_Session *)hSession)->WaitForRCC(dwRqId, 60000);
1698 }
1699
1700
1701 //
1702 // Execute action on agent
1703 //
1704
1705 DWORD LIBNXCL_EXPORTABLE NXCExecuteAction(NXC_SESSION hSession, DWORD dwObjectId,
1706 TCHAR *pszAction)
1707 {
1708 DWORD dwRqId;
1709 CSCPMessage msg;
1710
1711 dwRqId = ((NXCL_Session *)hSession)->CreateRqId();
1712
1713 msg.SetCode(CMD_EXECUTE_ACTION);
1714 msg.SetId(dwRqId);
1715 msg.SetVariable(VID_OBJECT_ID, dwObjectId);
1716 msg.SetVariable(VID_ACTION_NAME, pszAction);
1717 ((NXCL_Session *)hSession)->SendMsg(&msg);
1718 return ((NXCL_Session *)hSession)->WaitForRCC(dwRqId);
1719 }
1720
1721
1722 //
1723 // Get object's comments
1724 //
1725
1726 DWORD LIBNXCL_EXPORTABLE NXCGetObjectComments(NXC_SESSION hSession,
1727 DWORD dwObjectId, TCHAR **ppszText)
1728 {
1729 DWORD dwRqId, dwResult;
1730 CSCPMessage msg, *pResponse;
1731
1732 dwRqId = ((NXCL_Session *)hSession)->CreateRqId();
1733
1734 msg.SetCode(CMD_GET_OBJECT_COMMENTS);
1735 msg.SetId(dwRqId);
1736 msg.SetVariable(VID_OBJECT_ID, dwObjectId);
1737 ((NXCL_Session *)hSession)->SendMsg(&msg);
1738
1739 pResponse = ((NXCL_Session *)hSession)->WaitForMessage(CMD_REQUEST_COMPLETED, dwRqId);
1740 if (pResponse != NULL)
1741 {
1742 dwResult = pResponse->GetVariableLong(VID_RCC);
1743 if (dwResult == RCC_SUCCESS)
1744 *ppszText = pResponse->GetVariableStr(VID_COMMENTS);
1745 }
1746 else
1747 {
1748 dwResult = RCC_TIMEOUT;
1749 }
1750 return dwResult;
1751 }
1752
1753
1754 //
1755 // Update object's comments
1756 //
1757
1758 DWORD LIBNXCL_EXPORTABLE NXCUpdateObjectComments(NXC_SESSION hSession,
1759 DWORD dwObjectId, TCHAR *pszText)
1760 {
1761 DWORD dwRqId;
1762 CSCPMessage msg;
1763
1764 dwRqId = ((NXCL_Session *)hSession)->CreateRqId();
1765
1766 msg.SetCode(CMD_UPDATE_OBJECT_COMMENTS);
1767 msg.SetId(dwRqId);
1768 msg.SetVariable(VID_OBJECT_ID, dwObjectId);
1769 msg.SetVariable(VID_COMMENTS, pszText);
1770 ((NXCL_Session *)hSession)->SendMsg(&msg);
1771 return ((NXCL_Session *)hSession)->WaitForRCC(dwRqId);
1772 }
1773
1774
1775 //
1776 // Actual check for parent-child relation
1777 //
1778
1779 static BOOL IsParent(NXC_SESSION hSession, DWORD dwParent, DWORD dwChild)
1780 {
1781 DWORD i;
1782 NXC_OBJECT *pObject;
1783 BOOL bRet = FALSE;
1784
1785 pObject = ((NXCL_Session *)hSession)->FindObjectById(dwChild, FALSE);
1786 if (pObject != NULL)
1787 {
1788 for(i = 0; i < pObject->dwNumParents; i++)
1789 {
1790 if (pObject->pdwParentList[i] == dwParent)
1791 {
1792 bRet = TRUE;
1793 break;
1794 }
1795 }
1796
1797 if (!bRet)
1798 {
1799 for(i = 0; i < pObject->dwNumParents; i++)
1800 {
1801 if (IsParent(hSession, dwParent, pObject->pdwParentList[i]))
1802 {
1803 bRet = TRUE;
1804 break;
1805 }
1806 }
1807 }
1808 }
1809 return bRet;
1810 }
1811
1812
1813 //
1814 // Check if first object is a parent of second object
1815 //
1816
1817 BOOL LIBNXCL_EXPORTABLE NXCIsParent(NXC_SESSION hSession, DWORD dwParent, DWORD dwChild)
1818 {
1819 BOOL bRet;
1820
1821 ((NXCL_Session *)hSession)->LockObjectIndex();
1822 bRet = IsParent(hSession, dwParent, dwChild);
1823 ((NXCL_Session *)hSession)->UnlockObjectIndex();
1824 return bRet;
1825 }
1826
1827
1828 //
1829 // Get list of events used by template's or node's DCIs
1830 //
1831
1832 DWORD LIBNXCL_EXPORTABLE NXCGetDCIEventsList(NXC_SESSION hSession, DWORD dwObjectId,
1833 DWORD **ppdwList, DWORD *pdwListSize)
1834 {
1835 DWORD dwRqId, dwResult;
1836 CSCPMessage msg, *pResponse;
1837
1838 *ppdwList = NULL;
1839 *pdwListSize = 0;
1840
1841 dwRqId = ((NXCL_Session *)hSession)->CreateRqId();
1842
1843 msg.SetCode(CMD_GET_DCI_EVENTS_LIST);
1844 msg.SetId(dwRqId);
1845 msg.SetVariable(VID_OBJECT_ID, dwObjectId);
1846 ((NXCL_Session *)hSession)->SendMsg(&msg);
1847
1848 pResponse = ((NXCL_Session *)hSession)->WaitForMessage(CMD_REQUEST_COMPLETED, dwRqId);
1849 if (pResponse != NULL)
1850 {
1851 dwResult = pResponse->GetVariableLong(VID_RCC);
1852 if (dwResult == RCC_SUCCESS)
1853 {
1854 *pdwListSize = pResponse->GetVariableLong(VID_NUM_EVENTS);
1855 if (*pdwListSize > 0)
1856 {
1857 *ppdwList = (DWORD *)malloc(sizeof(DWORD) * (*pdwListSize));
1858 pResponse->GetVariableInt32Array(VID_EVENT_LIST, *pdwListSize, *ppdwList);
1859 }
1860 }
1861 delete pResponse;
1862 }
1863 else
1864 {
1865 dwResult = RCC_TIMEOUT;
1866 }
1867 return dwResult;
1868 }