f59a6d24186d73c41c80e6ad2184c8899f177efc
[public/netxms.git] / src / libnxcl / objects.cpp
1 /*
2 ** NetXMS - Network Management System
3 ** Client Library
4 ** Copyright (C) 2004 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 ** $module: 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:%ld, name:\"%s\")"), pObject->dwId, pObject->szName);
34 switch(pObject->iClass)
35 {
36 case OBJECT_CONTAINER:
37 safe_free(pObject->container.pszDescription);
38 break;
39 case OBJECT_NODE:
40 safe_free(pObject->node.pszDescription);
41 break;
42 case OBJECT_TEMPLATE:
43 safe_free(pObject->dct.pszDescription);
44 break;
45 case OBJECT_NETWORKSERVICE:
46 safe_free(pObject->netsrv.pszRequest);
47 safe_free(pObject->netsrv.pszResponse);
48 break;
49 case OBJECT_ZONE:
50 safe_free(pObject->zone.pszDescription);
51 safe_free(pObject->zone.pdwAddrList);
52 break;
53 case OBJECT_VPNCONNECTOR:
54 safe_free(pObject->vpnc.pLocalNetList);
55 safe_free(pObject->vpnc.pRemoteNetList);
56 break;
57 }
58 safe_free(pObject->pdwChildList);
59 safe_free(pObject->pdwParentList);
60 safe_free(pObject->pAccessList);
61 free(pObject);
62 }
63
64
65 //
66 // Perform binary search on index
67 // Returns INVALID_INDEX if key not found or position of appropriate network object
68 // We assume that pIndex == NULL will not be passed
69 //
70
71 static DWORD SearchIndex(INDEX *pIndex, DWORD dwIndexSize, DWORD dwKey)
72 {
73 DWORD dwFirst, dwLast, dwMid;
74
75 if (dwIndexSize == 0)
76 return INVALID_INDEX;
77
78 dwFirst = 0;
79 dwLast = dwIndexSize - 1;
80
81 if ((dwKey < pIndex[0].dwKey) || (dwKey > pIndex[dwLast].dwKey))
82 return INVALID_INDEX;
83
84 while(dwFirst < dwLast)
85 {
86 dwMid = (dwFirst + dwLast) / 2;
87 if (dwKey == pIndex[dwMid].dwKey)
88 return dwMid;
89 if (dwKey < pIndex[dwMid].dwKey)
90 dwLast = dwMid - 1;
91 else
92 dwFirst = dwMid + 1;
93 }
94
95 if (dwKey == pIndex[dwLast].dwKey)
96 return dwLast;
97
98 return INVALID_INDEX;
99 }
100
101
102 //
103 // Index comparision callback for qsort()
104 //
105
106 static int IndexCompare(const void *pArg1, const void *pArg2)
107 {
108 return ((INDEX *)pArg1)->dwKey < ((INDEX *)pArg2)->dwKey ? -1 :
109 (((INDEX *)pArg1)->dwKey > ((INDEX *)pArg2)->dwKey ? 1 : 0);
110 }
111
112
113 //
114 // Add object to list
115 //
116
117 void NXCL_Session::AddObject(NXC_OBJECT *pObject, BOOL bSortIndex)
118 {
119 DebugPrintf(_T("AddObject(id:%ld, name:\"%s\")"), pObject->dwId, pObject->szName);
120 LockObjectIndex();
121 m_pIndexById = (INDEX *)realloc(m_pIndexById, sizeof(INDEX) * (m_dwNumObjects + 1));
122 m_pIndexById[m_dwNumObjects].dwKey = pObject->dwId;
123 m_pIndexById[m_dwNumObjects].pObject = pObject;
124 m_dwNumObjects++;
125 if (bSortIndex)
126 qsort(m_pIndexById, m_dwNumObjects, sizeof(INDEX), IndexCompare);
127 UnlockObjectIndex();
128 }
129
130
131 //
132 // Replace object's data in list
133 //
134
135 static void ReplaceObject(NXC_OBJECT *pObject, NXC_OBJECT *pNewObject)
136 {
137 DebugPrintf(_T("ReplaceObject(id:%ld, name:\"%s\")"), pObject->dwId, pObject->szName);
138 switch(pObject->iClass)
139 {
140 case OBJECT_CONTAINER:
141 safe_free(pObject->container.pszDescription);
142 break;
143 case OBJECT_NODE:
144 safe_free(pObject->node.pszDescription);
145 break;
146 case OBJECT_TEMPLATE:
147 safe_free(pObject->dct.pszDescription);
148 break;
149 case OBJECT_NETWORKSERVICE:
150 safe_free(pObject->netsrv.pszRequest);
151 safe_free(pObject->netsrv.pszResponse);
152 break;
153 case OBJECT_ZONE:
154 safe_free(pObject->zone.pszDescription);
155 safe_free(pObject->zone.pdwAddrList);
156 break;
157 case OBJECT_VPNCONNECTOR:
158 safe_free(pObject->vpnc.pLocalNetList);
159 safe_free(pObject->vpnc.pRemoteNetList);
160 break;
161 }
162 safe_free(pObject->pdwChildList);
163 safe_free(pObject->pdwParentList);
164 safe_free(pObject->pAccessList);
165 memcpy(pObject, pNewObject, sizeof(NXC_OBJECT));
166 free(pNewObject);
167 }
168
169
170 //
171 // Create new object from message
172 //
173
174 static NXC_OBJECT *NewObjectFromMsg(CSCPMessage *pMsg)
175 {
176 NXC_OBJECT *pObject;
177 DWORD i, dwId1, dwId2;
178
179 // Allocate memory for new object structure
180 pObject = (NXC_OBJECT *)malloc(sizeof(NXC_OBJECT));
181 memset(pObject, 0, sizeof(NXC_OBJECT));
182
183 // Common attributes
184 pObject->dwId = pMsg->GetVariableLong(VID_OBJECT_ID);
185 pObject->iClass = pMsg->GetVariableShort(VID_OBJECT_CLASS);
186 pMsg->GetVariableStr(VID_OBJECT_NAME, pObject->szName, MAX_OBJECT_NAME);
187 pObject->iStatus = pMsg->GetVariableShort(VID_OBJECT_STATUS);
188 pObject->dwIpAddr = pMsg->GetVariableLong(VID_IP_ADDRESS);
189 pObject->bIsDeleted = pMsg->GetVariableShort(VID_IS_DELETED);
190 pObject->dwImage = pMsg->GetVariableLong(VID_IMAGE_ID);
191 pObject->iStatusCalcAlg = (int)pMsg->GetVariableShort(VID_STATUS_CALCULATION_ALG);
192 pObject->iStatusPropAlg = (int)pMsg->GetVariableShort(VID_STATUS_PROPAGATION_ALG);
193 pObject->iFixedStatus = (int)pMsg->GetVariableShort(VID_FIXED_STATUS);
194 pObject->iStatusShift = (int)pMsg->GetVariableShort(VID_STATUS_SHIFT);
195 pObject->iStatusTrans[0] = (int)pMsg->GetVariableShort(VID_STATUS_TRANSLATION_1);
196 pObject->iStatusTrans[1] = (int)pMsg->GetVariableShort(VID_STATUS_TRANSLATION_2);
197 pObject->iStatusTrans[2] = (int)pMsg->GetVariableShort(VID_STATUS_TRANSLATION_3);
198 pObject->iStatusTrans[3] = (int)pMsg->GetVariableShort(VID_STATUS_TRANSLATION_4);
199 pObject->iStatusSingleTh = (int)pMsg->GetVariableShort(VID_STATUS_SINGLE_THRESHOLD);
200 pObject->iStatusThresholds[0] = (int)pMsg->GetVariableShort(VID_STATUS_THRESHOLD_1);
201 pObject->iStatusThresholds[1] = (int)pMsg->GetVariableShort(VID_STATUS_THRESHOLD_2);
202 pObject->iStatusThresholds[2] = (int)pMsg->GetVariableShort(VID_STATUS_THRESHOLD_3);
203 pObject->iStatusThresholds[3] = (int)pMsg->GetVariableShort(VID_STATUS_THRESHOLD_4);
204
205 // Parents
206 pObject->dwNumParents = pMsg->GetVariableLong(VID_PARENT_CNT);
207 pObject->pdwParentList = (DWORD *)malloc(sizeof(DWORD) * pObject->dwNumParents);
208 for(i = 0, dwId1 = VID_PARENT_ID_BASE; i < pObject->dwNumParents; i++, dwId1++)
209 pObject->pdwParentList[i] = pMsg->GetVariableLong(dwId1);
210
211 // Childs
212 pObject->dwNumChilds = pMsg->GetVariableLong(VID_CHILD_CNT);
213 pObject->pdwChildList = (DWORD *)malloc(sizeof(DWORD) * pObject->dwNumChilds);
214 for(i = 0, dwId1 = VID_CHILD_ID_BASE; i < pObject->dwNumChilds; i++, dwId1++)
215 pObject->pdwChildList[i] = pMsg->GetVariableLong(dwId1);
216
217 // Access control
218 pObject->bInheritRights = pMsg->GetVariableShort(VID_INHERIT_RIGHTS);
219 pObject->dwAclSize = pMsg->GetVariableLong(VID_ACL_SIZE);
220 pObject->pAccessList = (NXC_ACL_ENTRY *)malloc(sizeof(NXC_ACL_ENTRY) * pObject->dwAclSize);
221 for(i = 0, dwId1 = VID_ACL_USER_BASE, dwId2 = VID_ACL_RIGHTS_BASE;
222 i < pObject->dwAclSize; i++, dwId1++, dwId2++)
223 {
224 pObject->pAccessList[i].dwUserId = pMsg->GetVariableLong(dwId1);
225 pObject->pAccessList[i].dwAccessRights = pMsg->GetVariableLong(dwId2);
226 }
227
228 // Class-specific attributes
229 switch(pObject->iClass)
230 {
231 case OBJECT_INTERFACE:
232 pObject->iface.dwIpNetMask = pMsg->GetVariableLong(VID_IP_NETMASK);
233 pObject->iface.dwIfIndex = pMsg->GetVariableLong(VID_IF_INDEX);
234 pObject->iface.dwIfType = pMsg->GetVariableLong(VID_IF_TYPE);
235 pMsg->GetVariableBinary(VID_MAC_ADDR, pObject->iface.bMacAddr, MAC_ADDR_LENGTH);
236 break;
237 case OBJECT_NODE:
238 pObject->node.dwFlags = pMsg->GetVariableLong(VID_FLAGS);
239 pObject->node.dwDiscoveryFlags = pMsg->GetVariableLong(VID_DISCOVERY_FLAGS);
240 pObject->node.dwNodeType = pMsg->GetVariableLong(VID_NODE_TYPE);
241 pObject->node.dwPollerNode = pMsg->GetVariableLong(VID_POLLER_NODE_ID);
242 pObject->node.dwZoneGUID = pMsg->GetVariableLong(VID_ZONE_GUID);
243 pObject->node.wAgentPort = pMsg->GetVariableShort(VID_AGENT_PORT);
244 pObject->node.wAuthMethod = pMsg->GetVariableShort(VID_AUTH_METHOD);
245 pMsg->GetVariableStr(VID_SHARED_SECRET, pObject->node.szSharedSecret, MAX_SECRET_LENGTH);
246 pMsg->GetVariableStr(VID_COMMUNITY_STRING, pObject->node.szCommunityString, MAX_COMMUNITY_LENGTH);
247 pMsg->GetVariableStr(VID_SNMP_OID, pObject->node.szObjectId, MAX_OID_LENGTH);
248 pObject->node.pszDescription = pMsg->GetVariableStr(VID_DESCRIPTION);
249 pObject->node.wSNMPVersion = pMsg->GetVariableShort(VID_SNMP_VERSION);
250 pMsg->GetVariableStr(VID_AGENT_VERSION, pObject->node.szAgentVersion, MAX_AGENT_VERSION_LEN);
251 pMsg->GetVariableStr(VID_PLATFORM_NAME, pObject->node.szPlatformName, MAX_PLATFORM_NAME_LEN);
252 break;
253 case OBJECT_SUBNET:
254 pObject->subnet.dwIpNetMask = pMsg->GetVariableLong(VID_IP_NETMASK);
255 pObject->subnet.dwZoneGUID = pMsg->GetVariableLong(VID_ZONE_GUID);
256 break;
257 case OBJECT_CONTAINER:
258 pObject->container.dwCategory = pMsg->GetVariableLong(VID_CATEGORY);
259 pObject->container.pszDescription = pMsg->GetVariableStr(VID_DESCRIPTION);
260 break;
261 case OBJECT_TEMPLATE:
262 pObject->dct.dwVersion = pMsg->GetVariableLong(VID_TEMPLATE_VERSION);
263 pObject->dct.pszDescription = pMsg->GetVariableStr(VID_DESCRIPTION);
264 break;
265 case OBJECT_NETWORKSERVICE:
266 pObject->netsrv.iServiceType = (int)pMsg->GetVariableShort(VID_SERVICE_TYPE);
267 pObject->netsrv.wProto = pMsg->GetVariableShort(VID_IP_PROTO);
268 pObject->netsrv.wPort = pMsg->GetVariableShort(VID_IP_PORT);
269 pObject->netsrv.dwPollerNode = pMsg->GetVariableLong(VID_POLLER_NODE_ID);
270 pObject->netsrv.pszRequest = pMsg->GetVariableStr(VID_SERVICE_REQUEST);
271 pObject->netsrv.pszResponse = pMsg->GetVariableStr(VID_SERVICE_RESPONSE);
272 break;
273 case OBJECT_ZONE:
274 pObject->zone.dwZoneGUID = pMsg->GetVariableLong(VID_ZONE_GUID);
275 pObject->zone.pszDescription = pMsg->GetVariableStr(VID_DESCRIPTION);
276 pObject->zone.wZoneType = pMsg->GetVariableShort(VID_ZONE_TYPE);
277 pObject->zone.dwControllerIpAddr = pMsg->GetVariableLong(VID_CONTROLLER_IP_ADDR);
278 pObject->zone.dwAddrListSize = pMsg->GetVariableLong(VID_ADDR_LIST_SIZE);
279 pObject->zone.pdwAddrList = (DWORD *)malloc(sizeof(DWORD) * pObject->zone.dwAddrListSize);
280 pMsg->GetVariableInt32Array(VID_IP_ADDR_LIST, pObject->zone.dwAddrListSize, pObject->zone.pdwAddrList);
281 break;
282 case OBJECT_VPNCONNECTOR:
283 pObject->vpnc.dwPeerGateway = pMsg->GetVariableLong(VID_PEER_GATEWAY);
284 pObject->vpnc.dwNumLocalNets = pMsg->GetVariableLong(VID_NUM_LOCAL_NETS);
285 pObject->vpnc.pLocalNetList = (IP_NETWORK *)malloc(sizeof(IP_NETWORK) * pObject->vpnc.dwNumLocalNets);
286 for(i = 0, dwId1 = VID_VPN_NETWORK_BASE; i < pObject->vpnc.dwNumLocalNets; i++)
287 {
288 pObject->vpnc.pLocalNetList[i].dwAddr = pMsg->GetVariableLong(dwId1++);
289 pObject->vpnc.pLocalNetList[i].dwMask = pMsg->GetVariableLong(dwId1++);
290 }
291 pObject->vpnc.dwNumRemoteNets = pMsg->GetVariableLong(VID_NUM_REMOTE_NETS);
292 pObject->vpnc.pRemoteNetList = (IP_NETWORK *)malloc(sizeof(IP_NETWORK) * pObject->vpnc.dwNumRemoteNets);
293 for(i = 0; i < pObject->vpnc.dwNumRemoteNets; i++)
294 {
295 pObject->vpnc.pRemoteNetList[i].dwAddr = pMsg->GetVariableLong(dwId1++);
296 pObject->vpnc.pRemoteNetList[i].dwMask = pMsg->GetVariableLong(dwId1++);
297 }
298 break;
299 default:
300 break;
301 }
302
303 return pObject;
304 }
305
306
307 //
308 // Process object information received from server
309 //
310
311 void NXCL_Session::ProcessObjectUpdate(CSCPMessage *pMsg)
312 {
313 NXC_OBJECT *pObject, *pNewObject;
314
315 switch(pMsg->GetCode())
316 {
317 case CMD_OBJECT_LIST_END:
318 if (!(m_dwFlags & NXC_SF_HAS_OBJECT_CACHE))
319 {
320 LockObjectIndex();
321 qsort(m_pIndexById, m_dwNumObjects, sizeof(INDEX), IndexCompare);
322 UnlockObjectIndex();
323 }
324 CompleteSync(RCC_SUCCESS);
325 break;
326 case CMD_OBJECT:
327 DebugPrintf(_T("RECV_OBJECT: ID=%d Name=\"%s\" Class=%d"), pMsg->GetVariableLong(VID_OBJECT_ID),
328 pMsg->GetVariableStr(VID_OBJECT_NAME), pMsg->GetVariableShort(VID_OBJECT_CLASS));
329
330 // Create new object from message and add it to list
331 pNewObject = NewObjectFromMsg(pMsg);
332 if (m_dwFlags & NXC_SF_HAS_OBJECT_CACHE)
333 {
334 // We already have some objects loaded from cache file
335 pObject = FindObjectById(pNewObject->dwId, TRUE);
336 if (pObject == NULL)
337 {
338 AddObject(pNewObject, TRUE);
339 }
340 else
341 {
342 ReplaceObject(pObject, pNewObject);
343 }
344 }
345 else
346 {
347 // No cache file, all objects are new
348 AddObject(pNewObject, FALSE);
349 }
350 break;
351 case CMD_OBJECT_UPDATE:
352 pNewObject = NewObjectFromMsg(pMsg);
353 pObject = FindObjectById(pNewObject->dwId, TRUE);
354 if (pObject == NULL)
355 {
356 AddObject(pNewObject, TRUE);
357 pObject = pNewObject;
358 }
359 else
360 {
361 ReplaceObject(pObject, pNewObject);
362 }
363 CallEventHandler(NXC_EVENT_OBJECT_CHANGED, pObject->dwId, pObject);
364 break;
365 default:
366 break;
367 }
368 }
369
370
371 //
372 // Synchronize objects with the server
373 // This function is NOT REENTRANT
374 //
375
376 DWORD NXCL_Session::SyncObjects(TCHAR *pszCacheFile)
377 {
378 CSCPMessage msg;
379 DWORD dwRetCode, dwRqId;
380
381 dwRqId = CreateRqId();
382 PrepareForSync();
383
384 DestroyAllObjects();
385
386 m_dwFlags &= ~NXC_SF_HAS_OBJECT_CACHE;
387 if (pszCacheFile != NULL)
388 LoadObjectsFromCache(pszCacheFile);
389
390 msg.SetCode(CMD_GET_OBJECTS);
391 msg.SetId(dwRqId);
392 msg.SetVariable(VID_TIMESTAMP, m_dwTimeStamp);
393 SendMsg(&msg);
394
395 dwRetCode = WaitForRCC(dwRqId);
396
397 // If request was successful, wait for object list end or for disconnection
398 if (dwRetCode == RCC_SUCCESS)
399 dwRetCode = WaitForSync(INFINITE);
400 else
401 UnlockSyncOp();
402
403 return dwRetCode;
404 }
405
406
407 //
408 // Wrappers for NXCL_Session::SyncObjects()
409 //
410
411 DWORD LIBNXCL_EXPORTABLE NXCSyncObjects(NXC_SESSION hSession)
412 {
413 return ((NXCL_Session *)hSession)->SyncObjects(NULL);
414 }
415
416 DWORD LIBNXCL_EXPORTABLE NXCSyncObjectsEx(NXC_SESSION hSession, TCHAR *pszCacheFile)
417 {
418 return ((NXCL_Session *)hSession)->SyncObjects(pszCacheFile);
419 }
420
421
422 //
423 // Find object by ID
424 //
425
426 NXC_OBJECT *NXCL_Session::FindObjectById(DWORD dwId, BOOL bLock)
427 {
428 DWORD dwPos;
429 NXC_OBJECT *pObject;
430
431 if (bLock)
432 LockObjectIndex();
433
434 dwPos = SearchIndex(m_pIndexById, m_dwNumObjects, dwId);
435 pObject = (dwPos == INVALID_INDEX) ? NULL : m_pIndexById[dwPos].pObject;
436
437 if (bLock)
438 UnlockObjectIndex();
439
440 return pObject;
441 }
442
443 NXC_OBJECT LIBNXCL_EXPORTABLE *NXCFindObjectById(NXC_SESSION hSession, DWORD dwId)
444 {
445 return ((NXCL_Session *)hSession)->FindObjectById(dwId, TRUE);
446 }
447
448 NXC_OBJECT LIBNXCL_EXPORTABLE *NXCFindObjectByIdNoLock(NXC_SESSION hSession, DWORD dwId)
449 {
450 return ((NXCL_Session *)hSession)->FindObjectById(dwId, FALSE);
451 }
452
453
454 //
455 // Find object by name
456 //
457
458 NXC_OBJECT *NXCL_Session::FindObjectByName(TCHAR *pszName)
459 {
460 NXC_OBJECT *pObject = NULL;
461 DWORD i;
462
463 if (pszName != NULL)
464 if (*pszName != 0)
465 {
466 LockObjectIndex();
467
468 for(i = 0; i < m_dwNumObjects; i++)
469 if (MatchString(pszName, m_pIndexById[i].pObject->szName, FALSE))
470 {
471 pObject = m_pIndexById[i].pObject;
472 break;
473 }
474
475 UnlockObjectIndex();
476 }
477 return pObject;
478 }
479
480 NXC_OBJECT LIBNXCL_EXPORTABLE *NXCFindObjectByName(NXC_SESSION hSession, TCHAR *pszName)
481 {
482 return ((NXCL_Session *)hSession)->FindObjectByName(pszName);
483 }
484
485
486 //
487 // Enumerate all objects
488 //
489
490 void NXCL_Session::EnumerateObjects(BOOL (* pHandler)(NXC_OBJECT *))
491 {
492 DWORD i;
493
494 LockObjectIndex();
495 for(i = 0; i < m_dwNumObjects; i++)
496 if (!pHandler(m_pIndexById[i].pObject))
497 break;
498 UnlockObjectIndex();
499 }
500
501 void LIBNXCL_EXPORTABLE NXCEnumerateObjects(NXC_SESSION hSession, BOOL (* pHandler)(NXC_OBJECT *))
502 {
503 ((NXCL_Session *)hSession)->EnumerateObjects(pHandler);
504 }
505
506
507 //
508 // Get root object
509 //
510
511 NXC_OBJECT *NXCL_Session::GetRootObject(DWORD dwId, DWORD dwIndex)
512 {
513 if (m_dwNumObjects > dwIndex)
514 if (m_pIndexById[dwIndex].dwKey == dwId)
515 return m_pIndexById[dwIndex].pObject;
516 return NULL;
517 }
518
519
520 //
521 // Get topology root ("Entire Network") object
522 //
523
524 NXC_OBJECT LIBNXCL_EXPORTABLE *NXCGetTopologyRootObject(NXC_SESSION hSession)
525 {
526 return ((NXCL_Session *)hSession)->GetRootObject(1, 0);
527 }
528
529
530 //
531 // Get service tree root ("All Services") object
532 //
533
534 NXC_OBJECT LIBNXCL_EXPORTABLE *NXCGetServiceRootObject(NXC_SESSION hSession)
535 {
536 return ((NXCL_Session *)hSession)->GetRootObject(2, 1);
537 }
538
539
540 //
541 // Get template tree root ("Templates") object
542 //
543
544 NXC_OBJECT LIBNXCL_EXPORTABLE *NXCGetTemplateRootObject(NXC_SESSION hSession)
545 {
546 return ((NXCL_Session *)hSession)->GetRootObject(3, 2);
547 }
548
549
550 //
551 // Get pointer to first object on objects' list and entire number of objects
552 //
553
554 void *NXCL_Session::GetObjectIndex(DWORD *pdwNumObjects)
555 {
556 if (pdwNumObjects != NULL)
557 *pdwNumObjects = m_dwNumObjects;
558 return m_pIndexById;
559 }
560
561 void LIBNXCL_EXPORTABLE *NXCGetObjectIndex(NXC_SESSION hSession, DWORD *pdwNumObjects)
562 {
563 return ((NXCL_Session *)hSession)->GetObjectIndex(pdwNumObjects);
564 }
565
566
567 //
568 // Lock object index
569 //
570
571 void LIBNXCL_EXPORTABLE NXCLockObjectIndex(NXC_SESSION hSession)
572 {
573 ((NXCL_Session *)hSession)->LockObjectIndex();
574 }
575
576
577 //
578 // Unlock object index
579 //
580
581 void LIBNXCL_EXPORTABLE NXCUnlockObjectIndex(NXC_SESSION hSession)
582 {
583 ((NXCL_Session *)hSession)->UnlockObjectIndex();
584 }
585
586
587 //
588 // Modify object
589 //
590
591 DWORD LIBNXCL_EXPORTABLE NXCModifyObject(NXC_SESSION hSession, NXC_OBJECT_UPDATE *pUpdate)
592 {
593 CSCPMessage msg;
594 DWORD dwRqId, i, dwId1, dwId2;
595
596 dwRqId = ((NXCL_Session *)hSession)->CreateRqId();
597
598 // Build request message
599 msg.SetCode(CMD_MODIFY_OBJECT);
600 msg.SetId(dwRqId);
601 msg.SetVariable(VID_OBJECT_ID, pUpdate->dwObjectId);
602 if (pUpdate->dwFlags & OBJ_UPDATE_NAME)
603 msg.SetVariable(VID_OBJECT_NAME, pUpdate->pszName);
604 if (pUpdate->dwFlags & OBJ_UPDATE_AGENT_PORT)
605 msg.SetVariable(VID_AGENT_PORT, (WORD)pUpdate->iAgentPort);
606 if (pUpdate->dwFlags & OBJ_UPDATE_AGENT_AUTH)
607 msg.SetVariable(VID_AUTH_METHOD, (WORD)pUpdate->iAuthType);
608 if (pUpdate->dwFlags & OBJ_UPDATE_AGENT_SECRET)
609 msg.SetVariable(VID_SHARED_SECRET, pUpdate->pszSecret);
610 if (pUpdate->dwFlags & OBJ_UPDATE_SNMP_COMMUNITY)
611 msg.SetVariable(VID_COMMUNITY_STRING, pUpdate->pszCommunity);
612 if (pUpdate->dwFlags & OBJ_UPDATE_IMAGE)
613 msg.SetVariable(VID_IMAGE_ID, pUpdate->dwImage);
614 if (pUpdate->dwFlags & OBJ_UPDATE_SNMP_VERSION)
615 msg.SetVariable(VID_SNMP_VERSION, pUpdate->wSNMPVersion);
616 if (pUpdate->dwFlags & OBJ_UPDATE_DESCRIPTION)
617 msg.SetVariable(VID_DESCRIPTION, pUpdate->pszDescription);
618 if (pUpdate->dwFlags & OBJ_UPDATE_CHECK_REQUEST)
619 msg.SetVariable(VID_SERVICE_REQUEST, pUpdate->pszRequest);
620 if (pUpdate->dwFlags & OBJ_UPDATE_CHECK_RESPONSE)
621 msg.SetVariable(VID_SERVICE_RESPONSE, pUpdate->pszResponse);
622 if (pUpdate->dwFlags & OBJ_UPDATE_IP_PROTO)
623 msg.SetVariable(VID_IP_PROTO, pUpdate->wProto);
624 if (pUpdate->dwFlags & OBJ_UPDATE_IP_PORT)
625 msg.SetVariable(VID_IP_PORT, pUpdate->wPort);
626 if (pUpdate->dwFlags & OBJ_UPDATE_SERVICE_TYPE)
627 msg.SetVariable(VID_SERVICE_TYPE, (WORD)pUpdate->iServiceType);
628 if (pUpdate->dwFlags & OBJ_UPDATE_POLLER_NODE)
629 msg.SetVariable(VID_POLLER_NODE_ID, pUpdate->dwPollerNode);
630 if (pUpdate->dwFlags & OBJ_UPDATE_IP_ADDR)
631 msg.SetVariable(VID_IP_ADDRESS, pUpdate->dwIpAddr);
632 if (pUpdate->dwFlags & OBJ_UPDATE_PEER_GATEWAY)
633 msg.SetVariable(VID_PEER_GATEWAY, pUpdate->dwPeerGateway);
634 if (pUpdate->dwFlags & OBJ_UPDATE_STATUS_ALG)
635 {
636 msg.SetVariable(VID_STATUS_CALCULATION_ALG, (WORD)pUpdate->iStatusCalcAlg);
637 msg.SetVariable(VID_STATUS_PROPAGATION_ALG, (WORD)pUpdate->iStatusPropAlg);
638 msg.SetVariable(VID_FIXED_STATUS, (WORD)pUpdate->iFixedStatus);
639 msg.SetVariable(VID_STATUS_SHIFT, (WORD)pUpdate->iStatusShift);
640 msg.SetVariable(VID_STATUS_TRANSLATION_1, (WORD)pUpdate->iStatusTrans[0]);
641 msg.SetVariable(VID_STATUS_TRANSLATION_2, (WORD)pUpdate->iStatusTrans[1]);
642 msg.SetVariable(VID_STATUS_TRANSLATION_3, (WORD)pUpdate->iStatusTrans[2]);
643 msg.SetVariable(VID_STATUS_TRANSLATION_4, (WORD)pUpdate->iStatusTrans[3]);
644 msg.SetVariable(VID_STATUS_SINGLE_THRESHOLD, (WORD)pUpdate->iStatusSingleTh);
645 msg.SetVariable(VID_STATUS_THRESHOLD_1, (WORD)pUpdate->iStatusThresholds[0]);
646 msg.SetVariable(VID_STATUS_THRESHOLD_2, (WORD)pUpdate->iStatusThresholds[1]);
647 msg.SetVariable(VID_STATUS_THRESHOLD_3, (WORD)pUpdate->iStatusThresholds[2]);
648 msg.SetVariable(VID_STATUS_THRESHOLD_4, (WORD)pUpdate->iStatusThresholds[3]);
649 }
650 if (pUpdate->dwFlags & OBJ_UPDATE_NETWORK_LIST)
651 {
652 msg.SetVariable(VID_NUM_LOCAL_NETS, pUpdate->dwNumLocalNets);
653 msg.SetVariable(VID_NUM_REMOTE_NETS, pUpdate->dwNumRemoteNets);
654 for(i = 0, dwId1 = VID_VPN_NETWORK_BASE; i < pUpdate->dwNumLocalNets; i++)
655 {
656 msg.SetVariable(dwId1++, pUpdate->pLocalNetList[i].dwAddr);
657 msg.SetVariable(dwId1++, pUpdate->pLocalNetList[i].dwMask);
658 }
659 for(i = 0; i < pUpdate->dwNumRemoteNets; i++)
660 {
661 msg.SetVariable(dwId1++, pUpdate->pRemoteNetList[i].dwAddr);
662 msg.SetVariable(dwId1++, pUpdate->pRemoteNetList[i].dwMask);
663 }
664 }
665 if (pUpdate->dwFlags & OBJ_UPDATE_ACL)
666 {
667 msg.SetVariable(VID_ACL_SIZE, pUpdate->dwAclSize);
668 msg.SetVariable(VID_INHERIT_RIGHTS, (WORD)pUpdate->bInheritRights);
669 for(i = 0, dwId1 = VID_ACL_USER_BASE, dwId2 = VID_ACL_RIGHTS_BASE;
670 i < pUpdate->dwAclSize; i++, dwId1++, dwId2++)
671 {
672 msg.SetVariable(dwId1, pUpdate->pAccessList[i].dwUserId);
673 msg.SetVariable(dwId2, pUpdate->pAccessList[i].dwAccessRights);
674 }
675 }
676
677 // Send request
678 ((NXCL_Session *)hSession)->SendMsg(&msg);
679
680 // Wait for reply
681 return ((NXCL_Session *)hSession)->WaitForRCC(dwRqId);
682 }
683
684
685 //
686 // Set object's mamagement status
687 //
688
689 DWORD LIBNXCL_EXPORTABLE NXCSetObjectMgmtStatus(NXC_SESSION hSession, DWORD dwObjectId,
690 BOOL bIsManaged)
691 {
692 CSCPMessage msg;
693 DWORD dwRqId;
694
695 dwRqId = ((NXCL_Session *)hSession)->CreateRqId();
696
697 // Build request message
698 msg.SetCode(CMD_SET_OBJECT_MGMT_STATUS);
699 msg.SetId(dwRqId);
700 msg.SetVariable(VID_OBJECT_ID, dwObjectId);
701 msg.SetVariable(VID_MGMT_STATUS, (WORD)bIsManaged);
702
703 // Send request
704 ((NXCL_Session *)hSession)->SendMsg(&msg);
705
706 // Wait for reply
707 return ((NXCL_Session *)hSession)->WaitForRCC(dwRqId);
708 }
709
710
711 //
712 // Create new object
713 //
714
715 DWORD LIBNXCL_EXPORTABLE NXCCreateObject(NXC_SESSION hSession,
716 NXC_OBJECT_CREATE_INFO *pCreateInfo,
717 DWORD *pdwObjectId)
718 {
719 CSCPMessage msg, *pResponse;
720 DWORD dwRqId, dwRetCode;
721
722 dwRqId = ((NXCL_Session *)hSession)->CreateRqId();
723
724 // Build request message
725 msg.SetCode(CMD_CREATE_OBJECT);
726 msg.SetId(dwRqId);
727 msg.SetVariable(VID_PARENT_ID, pCreateInfo->dwParentId);
728 msg.SetVariable(VID_OBJECT_CLASS, (WORD)pCreateInfo->iClass);
729 msg.SetVariable(VID_OBJECT_NAME, pCreateInfo->pszName);
730 switch(pCreateInfo->iClass)
731 {
732 case OBJECT_NODE:
733 msg.SetVariable(VID_IP_ADDRESS, pCreateInfo->cs.node.dwIpAddr);
734 msg.SetVariable(VID_IP_NETMASK, pCreateInfo->cs.node.dwNetMask);
735 break;
736 case OBJECT_CONTAINER:
737 msg.SetVariable(VID_CATEGORY, pCreateInfo->cs.container.dwCategory);
738 msg.SetVariable(VID_DESCRIPTION, pCreateInfo->cs.container.pszDescription);
739 break;
740 case OBJECT_TEMPLATEGROUP:
741 msg.SetVariable(VID_DESCRIPTION, pCreateInfo->cs.templateGroup.pszDescription);
742 break;
743 case OBJECT_NETWORKSERVICE:
744 msg.SetVariable(VID_SERVICE_TYPE, (WORD)pCreateInfo->cs.netsrv.iServiceType);
745 msg.SetVariable(VID_IP_PROTO, pCreateInfo->cs.netsrv.wProto);
746 msg.SetVariable(VID_IP_PORT, pCreateInfo->cs.netsrv.wPort);
747 msg.SetVariable(VID_SERVICE_REQUEST, pCreateInfo->cs.netsrv.pszRequest);
748 msg.SetVariable(VID_SERVICE_RESPONSE, pCreateInfo->cs.netsrv.pszResponse);
749 break;
750 default:
751 break;
752 }
753
754 // Send request
755 ((NXCL_Session *)hSession)->SendMsg(&msg);
756
757 // Wait for response. Creating node object can include polling,
758 // which can take a minute or even more in worst cases
759 pResponse = ((NXCL_Session *)hSession)->WaitForMessage(CMD_REQUEST_COMPLETED, dwRqId, 120000);
760 if (pResponse != NULL)
761 {
762 dwRetCode = pResponse->GetVariableLong(VID_RCC);
763 if (dwRetCode == RCC_SUCCESS)
764 {
765 *pdwObjectId = pResponse->GetVariableLong(VID_OBJECT_ID);
766 }
767 delete pResponse;
768 }
769 else
770 {
771 dwRetCode = RCC_TIMEOUT;
772 }
773
774 return dwRetCode;
775 }
776
777
778 //
779 // Bind/unbind objects
780 //
781
782 static DWORD ChangeObjectBinding(NXCL_Session *pSession, DWORD dwParentObject,
783 DWORD dwChildObject, BOOL bBind, BOOL bRemoveDCI)
784 {
785 CSCPMessage msg;
786 DWORD dwRqId;
787
788 dwRqId = pSession->CreateRqId();
789
790 // Build request message
791 msg.SetCode(bBind ? CMD_BIND_OBJECT : CMD_UNBIND_OBJECT);
792 msg.SetId(dwRqId);
793 msg.SetVariable(VID_PARENT_ID, dwParentObject);
794 msg.SetVariable(VID_CHILD_ID, dwChildObject);
795 if (!bBind)
796 msg.SetVariable(VID_REMOVE_DCI, (WORD)bRemoveDCI);
797
798 // Send request
799 pSession->SendMsg(&msg);
800
801 // Wait for reply
802 return pSession->WaitForRCC(dwRqId);
803 }
804
805
806 //
807 // Bind object
808 //
809
810 DWORD LIBNXCL_EXPORTABLE NXCBindObject(NXC_SESSION hSession, DWORD dwParentObject,
811 DWORD dwChildObject)
812 {
813 return ChangeObjectBinding((NXCL_Session *)hSession, dwParentObject,
814 dwChildObject, TRUE, FALSE);
815 }
816
817
818 //
819 // Unbind object
820 //
821
822 DWORD LIBNXCL_EXPORTABLE NXCUnbindObject(NXC_SESSION hSession, DWORD dwParentObject,
823 DWORD dwChildObject)
824 {
825 return ChangeObjectBinding((NXCL_Session *)hSession, dwParentObject,
826 dwChildObject, FALSE, FALSE);
827 }
828
829
830 //
831 // Remove template from node
832 //
833
834 DWORD LIBNXCL_EXPORTABLE NXCRemoveTemplate(NXC_SESSION hSession, DWORD dwTemplateId,
835 DWORD dwNodeId, BOOL bRemoveDCI)
836 {
837 return ChangeObjectBinding((NXCL_Session *)hSession, dwTemplateId,
838 dwNodeId, FALSE, bRemoveDCI);
839 }
840
841
842 //
843 // Delete object
844 //
845
846 DWORD LIBNXCL_EXPORTABLE NXCDeleteObject(NXC_SESSION hSession, DWORD dwObject)
847 {
848 CSCPMessage msg;
849 DWORD dwRqId;
850
851 dwRqId = ((NXCL_Session *)hSession)->CreateRqId();
852
853 // Build request message
854 msg.SetCode(CMD_DELETE_OBJECT);
855 msg.SetId(dwRqId);
856 msg.SetVariable(VID_OBJECT_ID, dwObject);
857
858 // Send request
859 ((NXCL_Session *)hSession)->SendMsg(&msg);
860
861 // Wait for reply
862 return ((NXCL_Session *)hSession)->WaitForRCC(dwRqId);
863 }
864
865
866 //
867 // Load container categories
868 //
869
870 DWORD LIBNXCL_EXPORTABLE NXCLoadCCList(NXC_SESSION hSession, NXC_CC_LIST **ppList)
871 {
872 CSCPMessage msg, *pResponse;
873 DWORD dwRqId, dwRetCode = RCC_SUCCESS, dwNumCats = 0, dwCatId = 0;
874
875 dwRqId = ((NXCL_Session *)hSession)->CreateRqId();
876
877 msg.SetCode(CMD_GET_CONTAINER_CAT_LIST);
878 msg.SetId(dwRqId);
879 ((NXCL_Session *)hSession)->SendMsg(&msg);
880
881 *ppList = (NXC_CC_LIST *)malloc(sizeof(NXC_CC_LIST));
882 (*ppList)->dwNumElements = 0;
883 (*ppList)->pElements = NULL;
884
885 do
886 {
887 pResponse = ((NXCL_Session *)hSession)->WaitForMessage(CMD_CONTAINER_CAT_DATA, dwRqId);
888 if (pResponse != NULL)
889 {
890 dwCatId = pResponse->GetVariableLong(VID_CATEGORY_ID);
891 if (dwCatId != 0) // 0 is end of list indicator
892 {
893 (*ppList)->pElements = (NXC_CONTAINER_CATEGORY *)realloc((*ppList)->pElements,
894 sizeof(NXC_CONTAINER_CATEGORY) * ((*ppList)->dwNumElements + 1));
895 (*ppList)->pElements[(*ppList)->dwNumElements].dwId = dwCatId;
896 (*ppList)->pElements[(*ppList)->dwNumElements].dwImageId =
897 pResponse->GetVariableLong(VID_IMAGE_ID);
898 pResponse->GetVariableStr(VID_CATEGORY_NAME,
899 (*ppList)->pElements[(*ppList)->dwNumElements].szName, MAX_OBJECT_NAME);
900 (*ppList)->pElements[(*ppList)->dwNumElements].pszDescription =
901 pResponse->GetVariableStr(VID_DESCRIPTION);
902 (*ppList)->dwNumElements++;
903 }
904 delete pResponse;
905 }
906 else
907 {
908 dwRetCode = RCC_TIMEOUT;
909 dwCatId = 0;
910 }
911 }
912 while(dwCatId != 0);
913
914 // Destroy results on failure
915 if (dwRetCode != RCC_SUCCESS)
916 {
917 safe_free((*ppList)->pElements);
918 free(*ppList);
919 *ppList = NULL;
920 }
921
922 return dwRetCode;
923 }
924
925
926 //
927 // Destroy list of container categories
928 //
929
930 void LIBNXCL_EXPORTABLE NXCDestroyCCList(NXC_CC_LIST *pList)
931 {
932 DWORD i;
933
934 if (pList == NULL)
935 return;
936
937 for(i = 0; i < pList->dwNumElements; i++)
938 safe_free(pList->pElements[i].pszDescription);
939 safe_free(pList->pElements);
940 free(pList);
941 }
942
943
944 //
945 // Perform a forced node poll
946 //
947
948 DWORD LIBNXCL_EXPORTABLE NXCPollNode(NXC_SESSION hSession, DWORD dwObjectId, int iPollType,
949 void (* pfCallback)(TCHAR *, void *), void *pArg)
950 {
951 DWORD dwRetCode, dwRqId;
952 CSCPMessage msg, *pResponse;
953 TCHAR *pszMsg;
954
955 dwRqId = ((NXCL_Session *)hSession)->CreateRqId();
956
957 msg.SetCode(CMD_POLL_NODE);
958 msg.SetId(dwRqId);
959 msg.SetVariable(VID_OBJECT_ID, dwObjectId);
960 msg.SetVariable(VID_POLL_TYPE, (WORD)iPollType);
961 ((NXCL_Session *)hSession)->SendMsg(&msg);
962
963 do
964 {
965 // Polls can take a long time, so we wait up to 120 seconds for each message
966 pResponse = ((NXCL_Session *)hSession)->WaitForMessage(CMD_POLLING_INFO, dwRqId, 120000);
967 if (pResponse != NULL)
968 {
969 dwRetCode = pResponse->GetVariableLong(VID_RCC);
970 if ((dwRetCode == RCC_OPERATION_IN_PROGRESS) && (pfCallback != NULL))
971 {
972 pszMsg = pResponse->GetVariableStr(VID_POLLER_MESSAGE);
973 pfCallback(pszMsg, pArg);
974 free(pszMsg);
975 }
976 delete pResponse;
977 }
978 else
979 {
980 dwRetCode = RCC_TIMEOUT;
981 }
982 }
983 while(dwRetCode == RCC_OPERATION_IN_PROGRESS);
984
985 return dwRetCode;
986 }
987
988
989 //
990 // Wake up node by sending magic packet
991 //
992
993 DWORD LIBNXCL_EXPORTABLE NXCWakeUpNode(NXC_SESSION hSession, DWORD dwObjectId)
994 {
995 DWORD dwRqId;
996 CSCPMessage msg;
997
998 dwRqId = ((NXCL_Session *)hSession)->CreateRqId();
999
1000 msg.SetCode(CMD_WAKEUP_NODE);
1001 msg.SetId(dwRqId);
1002 msg.SetVariable(VID_OBJECT_ID, dwObjectId);
1003 ((NXCL_Session *)hSession)->SendMsg(&msg);
1004 return ((NXCL_Session *)hSession)->WaitForRCC(dwRqId);
1005 }
1006
1007
1008 //
1009 // Retrieve list of supported agent parameters
1010 //
1011
1012 DWORD LIBNXCL_EXPORTABLE NXCGetSupportedParameters(NXC_SESSION hSession, DWORD dwNodeId,
1013 DWORD *pdwNumParams,
1014 NXC_AGENT_PARAM **ppParamList)
1015 {
1016 CSCPMessage msg, *pResponse;
1017 DWORD i, dwId, dwRqId, dwRetCode;
1018
1019 dwRqId = ((NXCL_Session *)hSession)->CreateRqId();
1020
1021 *pdwNumParams = 0;
1022 *ppParamList = NULL;
1023
1024 // Build request message
1025 msg.SetCode(CMD_GET_PARAMETER_LIST);
1026 msg.SetId(dwRqId);
1027 msg.SetVariable(VID_OBJECT_ID, dwNodeId);
1028
1029 // Send request
1030 ((NXCL_Session *)hSession)->SendMsg(&msg);
1031
1032 // Wait for response
1033 pResponse = ((NXCL_Session *)hSession)->WaitForMessage(CMD_REQUEST_COMPLETED, dwRqId);
1034 if (pResponse != NULL)
1035 {
1036 dwRetCode = pResponse->GetVariableLong(VID_RCC);
1037 if (dwRetCode == RCC_SUCCESS)
1038 {
1039 *pdwNumParams = pResponse->GetVariableLong(VID_NUM_PARAMETERS);
1040 *ppParamList = (NXC_AGENT_PARAM *)malloc(sizeof(NXC_AGENT_PARAM) * *pdwNumParams);
1041 for(i = 0, dwId = VID_PARAM_LIST_BASE; i < *pdwNumParams; i++)
1042 {
1043 pResponse->GetVariableStr(dwId++, (*ppParamList)[i].szName, MAX_PARAM_NAME);
1044 pResponse->GetVariableStr(dwId++, (*ppParamList)[i].szDescription, MAX_DB_STRING);
1045 (*ppParamList)[i].iDataType = (int)pResponse->GetVariableShort(dwId++);
1046 }
1047 }
1048 delete pResponse;
1049 }
1050 else
1051 {
1052 dwRetCode = RCC_TIMEOUT;
1053 }
1054
1055 return dwRetCode;
1056 }
1057
1058
1059 //
1060 // Check if object has default name formed from IP address
1061 //
1062
1063 static BOOL ObjectHasDefaultName(NXC_OBJECT *pObject)
1064 {
1065 if (pObject->iClass == OBJECT_SUBNET)
1066 {
1067 TCHAR szBuffer[64], szIpAddr[32];
1068 _stprintf(szBuffer, _T("%s/%d"), IpToStr(pObject->dwIpAddr, szIpAddr),
1069 BitsInMask(pObject->subnet.dwIpNetMask));
1070 return !_tcscmp(szBuffer, pObject->szName);
1071 }
1072 else
1073 {
1074 return ((pObject->dwIpAddr != 0) &&
1075 (ntohl(_t_inet_addr(pObject->szName)) == pObject->dwIpAddr));
1076 }
1077 }
1078
1079
1080 //
1081 // Get object name suitable for comparision
1082 //
1083
1084 void LIBNXCL_EXPORTABLE NXCGetComparableObjectName(NXC_SESSION hSession, DWORD dwObjectId, TCHAR *pszName)
1085 {
1086 NXCGetComparableObjectNameEx(((NXCL_Session *)hSession)->FindObjectById(dwObjectId, TRUE), pszName);
1087 }
1088
1089
1090 //
1091 // Get object name suitable for comparision
1092 //
1093
1094 void LIBNXCL_EXPORTABLE NXCGetComparableObjectNameEx(NXC_OBJECT *pObject, TCHAR *pszName)
1095 {
1096 if (pObject != NULL)
1097 {
1098 // If object has an IP address as name, we sort as numbers
1099 // otherwise in alphabetical order
1100 if (ObjectHasDefaultName(pObject))
1101 {
1102 _sntprintf(pszName, MAX_OBJECT_NAME, _T("\x01%03d%03d%03d%03d"),
1103 pObject->dwIpAddr >> 24, (pObject->dwIpAddr >> 16) & 255,
1104 (pObject->dwIpAddr >> 8) & 255, pObject->dwIpAddr & 255);
1105 }
1106 else
1107 {
1108 _tcscpy(pszName, pObject->szName);
1109 }
1110 }
1111 else
1112 {
1113 *pszName = 0;
1114 }
1115 }
1116
1117
1118 //
1119 // Save object's cache to file
1120 //
1121
1122 DWORD LIBNXCL_EXPORTABLE NXCSaveObjectCache(NXC_SESSION hSession, TCHAR *pszFile)
1123 {
1124 FILE *hFile;
1125 OBJECT_CACHE_HEADER hdr;
1126 DWORD i, dwResult, dwNumObjects, dwSize;
1127 INDEX *pList;
1128
1129 hFile = _tfopen(pszFile, _T("wb"));
1130 if (hFile != NULL)
1131 {
1132 ((NXCL_Session *)hSession)->LockObjectIndex();
1133 pList = (INDEX *)((NXCL_Session *)hSession)->GetObjectIndex(&dwNumObjects);
1134
1135 // Write cache file header
1136 hdr.dwMagic = OBJECT_CACHE_MAGIC;
1137 hdr.dwStructSize = sizeof(NXC_OBJECT);
1138 hdr.dwTimeStamp = ((NXCL_Session *)hSession)->GetTimeStamp();
1139 hdr.dwNumObjects = dwNumObjects;
1140 memcpy(hdr.bsServerId, ((NXCL_Session *)hSession)->m_bsServerId, 8);
1141 fwrite(&hdr, 1, sizeof(OBJECT_CACHE_HEADER), hFile);
1142
1143 // Write all objects
1144 for(i = 0; i < dwNumObjects; i++)
1145 {
1146 fwrite(pList[i].pObject, 1, sizeof(NXC_OBJECT), hFile);
1147 fwrite(pList[i].pObject->pdwChildList, 1,
1148 sizeof(DWORD) * pList[i].pObject->dwNumChilds, hFile);
1149 fwrite(pList[i].pObject->pdwParentList, 1,
1150 sizeof(DWORD) * pList[i].pObject->dwNumParents, hFile);
1151 fwrite(pList[i].pObject->pAccessList, 1,
1152 sizeof(NXC_ACL_ENTRY) * pList[i].pObject->dwAclSize, hFile);
1153 switch(pList[i].pObject->iClass)
1154 {
1155 case OBJECT_NODE:
1156 dwSize = _tcslen(pList[i].pObject->node.pszDescription) * sizeof(TCHAR);
1157 fwrite(&dwSize, 1, sizeof(DWORD), hFile);
1158 fwrite(pList[i].pObject->node.pszDescription, 1, dwSize, hFile);
1159 break;
1160 case OBJECT_CONTAINER:
1161 dwSize = _tcslen(pList[i].pObject->container.pszDescription) * sizeof(TCHAR);
1162 fwrite(&dwSize, 1, sizeof(DWORD), hFile);
1163 fwrite(pList[i].pObject->container.pszDescription, 1, dwSize, hFile);
1164 break;
1165 case OBJECT_TEMPLATE:
1166 dwSize = _tcslen(pList[i].pObject->dct.pszDescription) * sizeof(TCHAR);
1167 fwrite(&dwSize, 1, sizeof(DWORD), hFile);
1168 fwrite(pList[i].pObject->dct.pszDescription, 1, dwSize, hFile);
1169 break;
1170 case OBJECT_NETWORKSERVICE:
1171 dwSize = _tcslen(pList[i].pObject->netsrv.pszRequest) * sizeof(TCHAR);
1172 fwrite(&dwSize, 1, sizeof(DWORD), hFile);
1173 fwrite(pList[i].pObject->netsrv.pszRequest, 1, dwSize, hFile);
1174
1175 dwSize = _tcslen(pList[i].pObject->netsrv.pszResponse) * sizeof(TCHAR);
1176 fwrite(&dwSize, 1, sizeof(DWORD), hFile);
1177 fwrite(pList[i].pObject->netsrv.pszResponse, 1, dwSize, hFile);
1178 break;
1179 case OBJECT_ZONE:
1180 dwSize = _tcslen(pList[i].pObject->zone.pszDescription) * sizeof(TCHAR);
1181 fwrite(&dwSize, 1, sizeof(DWORD), hFile);
1182 fwrite(pList[i].pObject->zone.pszDescription, 1, dwSize, hFile);
1183
1184 if (pList[i].pObject->zone.dwAddrListSize > 0)
1185 fwrite(pList[i].pObject->zone.pdwAddrList, sizeof(DWORD),
1186 pList[i].pObject->zone.dwAddrListSize, hFile);
1187 break;
1188 case OBJECT_VPNCONNECTOR:
1189 fwrite(pList[i].pObject->vpnc.pLocalNetList, 1,
1190 pList[i].pObject->vpnc.dwNumLocalNets * sizeof(IP_NETWORK), hFile);
1191 fwrite(pList[i].pObject->vpnc.pRemoteNetList, 1,
1192 pList[i].pObject->vpnc.dwNumRemoteNets * sizeof(IP_NETWORK), hFile);
1193 break;
1194 default:
1195 break;
1196 }
1197 }
1198
1199 ((NXCL_Session *)hSession)->UnlockObjectIndex();
1200 fclose(hFile);
1201 dwResult = RCC_SUCCESS;
1202 }
1203 else
1204 {
1205 dwResult = RCC_IO_ERROR;
1206 }
1207
1208 return dwResult;
1209 }
1210
1211
1212 //
1213 // Load objects from cache file
1214 //
1215
1216 void NXCL_Session::LoadObjectsFromCache(TCHAR *pszFile)
1217 {
1218 FILE *hFile;
1219 OBJECT_CACHE_HEADER hdr;
1220 NXC_OBJECT object;
1221 DWORD i, dwSize;
1222
1223 hFile = _tfopen(pszFile, _T("rb"));
1224 if (hFile != NULL)
1225 {
1226 // Read header
1227 DebugPrintf(_T("Checking cache file %s"), pszFile);
1228 if (fread(&hdr, 1, sizeof(OBJECT_CACHE_HEADER), hFile) == sizeof(OBJECT_CACHE_HEADER))
1229 {
1230 if ((hdr.dwMagic == OBJECT_CACHE_MAGIC) &&
1231 (hdr.dwStructSize == sizeof(NXC_OBJECT)) &&
1232 (!memcmp(hdr.bsServerId, m_bsServerId, 8)))
1233 {
1234 DebugPrintf(_T("Cache file OK, loading objects"));
1235 m_dwTimeStamp = hdr.dwTimeStamp;
1236 for(i = 0; i < hdr.dwNumObjects; i++)
1237 {
1238 if (fread(&object, 1, sizeof(NXC_OBJECT), hFile) == sizeof(NXC_OBJECT))
1239 {
1240 object.pdwChildList = (DWORD *)malloc(sizeof(DWORD) * object.dwNumChilds);
1241 fread(object.pdwChildList, 1, sizeof(DWORD) * object.dwNumChilds, hFile);
1242
1243 object.pdwParentList = (DWORD *)malloc(sizeof(DWORD) * object.dwNumParents);
1244 fread(object.pdwParentList, 1, sizeof(DWORD) * object.dwNumParents, hFile);
1245
1246 object.pAccessList = (NXC_ACL_ENTRY *)malloc(sizeof(NXC_ACL_ENTRY) * object.dwAclSize);
1247 fread(object.pAccessList, 1, sizeof(NXC_ACL_ENTRY) * object.dwAclSize, hFile);
1248
1249 switch(object.iClass)
1250 {
1251 case OBJECT_NODE:
1252 fread(&dwSize, 1, sizeof(DWORD), hFile);
1253 object.node.pszDescription = (TCHAR *)malloc(dwSize + sizeof(TCHAR));
1254 fread(object.node.pszDescription, 1, dwSize, hFile);
1255 object.node.pszDescription[dwSize / sizeof(TCHAR)] = 0;
1256 break;
1257 case OBJECT_CONTAINER:
1258 fread(&dwSize, 1, sizeof(DWORD), hFile);
1259 object.container.pszDescription = (TCHAR *)malloc(dwSize + sizeof(TCHAR));
1260 fread(object.container.pszDescription, 1, dwSize, hFile);
1261 object.container.pszDescription[dwSize / sizeof(TCHAR)] = 0;
1262 break;
1263 case OBJECT_TEMPLATE:
1264 fread(&dwSize, 1, sizeof(DWORD), hFile);
1265 object.dct.pszDescription = (TCHAR *)malloc(dwSize + sizeof(TCHAR));
1266 fread(object.dct.pszDescription, 1, dwSize, hFile);
1267 object.dct.pszDescription[dwSize / sizeof(TCHAR)] = 0;
1268 break;
1269 case OBJECT_NETWORKSERVICE:
1270 fread(&dwSize, 1, sizeof(DWORD), hFile);
1271 object.netsrv.pszRequest = (TCHAR *)malloc(dwSize + sizeof(TCHAR));
1272 fread(object.netsrv.pszRequest, 1, dwSize, hFile);
1273 object.netsrv.pszRequest[dwSize / sizeof(TCHAR)] = 0;
1274
1275 fread(&dwSize, 1, sizeof(DWORD), hFile);
1276 object.netsrv.pszResponse = (TCHAR *)malloc(dwSize + sizeof(TCHAR));
1277 fread(object.netsrv.pszResponse, 1, dwSize, hFile);
1278 object.netsrv.pszResponse[dwSize / sizeof(TCHAR)] = 0;
1279 break;
1280 case OBJECT_ZONE:
1281 fread(&dwSize, 1, sizeof(DWORD), hFile);
1282 object.zone.pszDescription = (TCHAR *)malloc(dwSize + sizeof(TCHAR));
1283 fread(object.zone.pszDescription, 1, dwSize, hFile);
1284 object.zone.pszDescription[dwSize / sizeof(TCHAR)] = 0;
1285
1286 if (object.zone.dwAddrListSize > 0)
1287 {
1288 object.zone.pdwAddrList = (DWORD *)malloc(object.zone.dwAddrListSize * sizeof(DWORD));
1289 fread(object.zone.pdwAddrList, sizeof(DWORD), object.zone.dwAddrListSize, hFile);
1290 }
1291 else
1292 {
1293 object.zone.pdwAddrList = NULL;
1294 }
1295 break;
1296 case OBJECT_VPNCONNECTOR:
1297 dwSize = object.vpnc.dwNumLocalNets * sizeof(IP_NETWORK);
1298 object.vpnc.pLocalNetList = (IP_NETWORK *)malloc(dwSize);
1299 fread(object.vpnc.pLocalNetList, 1, dwSize, hFile);
1300
1301 dwSize = object.vpnc.dwNumRemoteNets * sizeof(IP_NETWORK);
1302 object.vpnc.pRemoteNetList = (IP_NETWORK *)malloc(dwSize);
1303 fread(object.vpnc.pRemoteNetList, 1, dwSize, hFile);
1304 break;
1305 default:
1306 break;
1307 }
1308
1309 AddObject((NXC_OBJECT *)nx_memdup(&object, sizeof(NXC_OBJECT)), FALSE);
1310 }
1311 }
1312 LockObjectIndex();
1313 qsort(m_pIndexById, m_dwNumObjects, sizeof(INDEX), IndexCompare);
1314 UnlockObjectIndex();
1315 m_dwFlags |= NXC_SF_HAS_OBJECT_CACHE;
1316 }
1317 }
1318
1319 fclose(hFile);
1320 }
1321 }
1322
1323
1324 //
1325 // Change node's IP address
1326 //
1327
1328 DWORD LIBNXCL_EXPORTABLE NXCChangeNodeIP(NXC_SESSION hSession, DWORD dwNodeId, DWORD dwIpAddr)
1329 {
1330 DWORD dwRqId;
1331 CSCPMessage msg;
1332
1333 dwRqId = ((NXCL_Session *)hSession)->CreateRqId();
1334
1335 msg.SetCode(CMD_CHANGE_IP_ADDR);
1336 msg.SetId(dwRqId);
1337 msg.SetVariable(VID_OBJECT_ID, dwNodeId);
1338 msg.SetVariable(VID_IP_ADDRESS, dwIpAddr);
1339 ((NXCL_Session *)hSession)->SendMsg(&msg);
1340 return ((NXCL_Session *)hSession)->WaitForRCC(dwRqId, 300000);
1341 }
1342
1343
1344 //
1345 // Read agent's configuration file
1346 //
1347
1348 DWORD LIBNXCL_EXPORTABLE NXCGetAgentConfig(NXC_SESSION hSession, DWORD dwNodeId,
1349 TCHAR **ppszConfig)
1350 {
1351 CSCPMessage msg, *pResponse;
1352 DWORD dwRqId, dwRetCode;
1353
1354 dwRqId = ((NXCL_Session *)hSession)->CreateRqId();
1355
1356 *ppszConfig = NULL;
1357
1358 // Build request message
1359 msg.SetCode(CMD_GET_AGENT_CONFIG);
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, 60000);
1368 if (pResponse != NULL)
1369 {
1370 dwRetCode = pResponse->GetVariableLong(VID_RCC);
1371 if (dwRetCode == RCC_SUCCESS)
1372 {
1373 *ppszConfig = pResponse->GetVariableStr(VID_CONFIG_FILE);
1374 }
1375 delete pResponse;
1376 }
1377 else
1378 {
1379 dwRetCode = RCC_TIMEOUT;
1380 }
1381
1382 return dwRetCode;
1383 }
1384
1385
1386 //
1387 // Update agent's configuration file
1388 //
1389
1390 DWORD LIBNXCL_EXPORTABLE NXCUpdateAgentConfig(NXC_SESSION hSession, DWORD dwNodeId,
1391 TCHAR *pszConfig, BOOL bApply)
1392 {
1393 CSCPMessage msg;
1394 DWORD dwRqId;
1395
1396 dwRqId = ((NXCL_Session *)hSession)->CreateRqId();
1397
1398 // Build request message
1399 msg.SetCode(CMD_UPDATE_AGENT_CONFIG);
1400 msg.SetId(dwRqId);
1401 msg.SetVariable(VID_OBJECT_ID, dwNodeId);
1402 msg.SetVariable(VID_CONFIG_FILE, pszConfig);
1403 msg.SetVariable(VID_APPLY_FLAG, (WORD)bApply);
1404
1405 // Send request
1406 ((NXCL_Session *)hSession)->SendMsg(&msg);
1407
1408 return ((NXCL_Session *)hSession)->WaitForRCC(dwRqId, 60000);
1409 }
1410
1411
1412 //
1413 // Execute action on agent
1414 //
1415
1416 DWORD LIBNXCL_EXPORTABLE NXCExecuteAction(NXC_SESSION hSession, DWORD dwObjectId,
1417 TCHAR *pszAction)
1418 {
1419 DWORD dwRqId;
1420 CSCPMessage msg;
1421
1422 dwRqId = ((NXCL_Session *)hSession)->CreateRqId();
1423
1424 msg.SetCode(CMD_EXECUTE_ACTION);
1425 msg.SetId(dwRqId);
1426 msg.SetVariable(VID_OBJECT_ID, dwObjectId);
1427 msg.SetVariable(VID_ACTION_NAME, pszAction);
1428 ((NXCL_Session *)hSession)->SendMsg(&msg);
1429 return ((NXCL_Session *)hSession)->WaitForRCC(dwRqId);
1430 }