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