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