Implemented object caching on client side
[public/netxms.git] / src / server / core / session.cpp
1 /*
2 ** NetXMS - Network Management System
3 ** Copyright (C) 2003, 2004 Victor Kirhenshtein
4 **
5 ** This program is free software; you can redistribute it and/or modify
6 ** it under the terms of the GNU General Public License as published by
7 ** the Free Software Foundation; either version 2 of the License, or
8 ** (at your option) any later version.
9 **
10 ** This program is distributed in the hope that it will be useful,
11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ** GNU General Public License for more details.
14 **
15 ** You should have received a copy of the GNU General Public License
16 ** along with this program; if not, write to the Free Software
17 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 **
19 ** $module: session.cpp
20 **
21 **/
22
23 #include "nxcore.h"
24
25 #ifndef _WIN32
26 #include <dirent.h>
27 #endif
28
29
30 //
31 // Constants
32 //
33
34 #define TRAP_CREATE 1
35 #define TRAP_UPDATE 2
36 #define TRAP_DELETE 3
37
38 #define RAW_MSG_SIZE 262144
39
40
41 //
42 // Externals
43 //
44
45 void UnregisterSession(DWORD dwIndex);
46
47
48 //
49 // Node poller start data
50 //
51
52 typedef struct
53 {
54 ClientSession *pSession;
55 Node *pNode;
56 int iPollType;
57 DWORD dwRqId;
58 } POLLER_START_DATA;
59
60
61 //
62 // Fill CSCP message with user data
63 //
64
65 static void FillUserInfoMessage(CSCPMessage *pMsg, NMS_USER *pUser)
66 {
67 pMsg->SetVariable(VID_USER_ID, pUser->dwId);
68 pMsg->SetVariable(VID_USER_NAME, pUser->szName);
69 pMsg->SetVariable(VID_USER_FLAGS, pUser->wFlags);
70 pMsg->SetVariable(VID_USER_SYS_RIGHTS, pUser->wSystemRights);
71 pMsg->SetVariable(VID_USER_FULL_NAME, pUser->szFullName);
72 pMsg->SetVariable(VID_USER_DESCRIPTION, pUser->szDescription);
73 }
74
75
76 //
77 // Fill CSCP message with user group data
78 //
79
80 static void FillGroupInfoMessage(CSCPMessage *pMsg, NMS_USER_GROUP *pGroup)
81 {
82 DWORD i, dwId;
83
84 pMsg->SetVariable(VID_USER_ID, pGroup->dwId);
85 pMsg->SetVariable(VID_USER_NAME, pGroup->szName);
86 pMsg->SetVariable(VID_USER_FLAGS, pGroup->wFlags);
87 pMsg->SetVariable(VID_USER_SYS_RIGHTS, pGroup->wSystemRights);
88 pMsg->SetVariable(VID_USER_DESCRIPTION, pGroup->szDescription);
89 pMsg->SetVariable(VID_NUM_MEMBERS, pGroup->dwNumMembers);
90 for(i = 0, dwId = VID_GROUP_MEMBER_BASE; i < pGroup->dwNumMembers; i++, dwId++)
91 pMsg->SetVariable(dwId, pGroup->pMembers[i]);
92 }
93
94
95 //
96 // Client communication read thread starter
97 //
98
99 THREAD_RESULT THREAD_CALL ClientSession::ReadThreadStarter(void *pArg)
100 {
101 ((ClientSession *)pArg)->ReadThread();
102
103 // When ClientSession::ReadThread exits, all other session
104 // threads are already stopped, so we can safely destroy
105 // session object
106 UnregisterSession(((ClientSession *)pArg)->GetIndex());
107 delete (ClientSession *)pArg;
108 return THREAD_OK;
109 }
110
111
112 //
113 // Client communication write thread starter
114 //
115
116 THREAD_RESULT THREAD_CALL ClientSession::WriteThreadStarter(void *pArg)
117 {
118 ((ClientSession *)pArg)->WriteThread();
119 return THREAD_OK;
120 }
121
122
123 //
124 // Received message processing thread starter
125 //
126
127 THREAD_RESULT THREAD_CALL ClientSession::ProcessingThreadStarter(void *pArg)
128 {
129 ((ClientSession *)pArg)->ProcessingThread();
130 return THREAD_OK;
131 }
132
133
134 //
135 // Information update processing thread starter
136 //
137
138 THREAD_RESULT THREAD_CALL ClientSession::UpdateThreadStarter(void *pArg)
139 {
140 ((ClientSession *)pArg)->UpdateThread();
141 return THREAD_OK;
142 }
143
144
145 //
146 // Forced node poll thread starter
147 //
148
149 THREAD_RESULT THREAD_CALL ClientSession::PollerThreadStarter(void *pArg)
150 {
151 ((POLLER_START_DATA *)pArg)->pSession->PollerThread(
152 ((POLLER_START_DATA *)pArg)->pNode,
153 ((POLLER_START_DATA *)pArg)->iPollType,
154 ((POLLER_START_DATA *)pArg)->dwRqId);
155 ((POLLER_START_DATA *)pArg)->pSession->DecRefCount();
156 free(pArg);
157 return THREAD_OK;
158 }
159
160
161 //
162 // Client session class constructor
163 //
164
165 ClientSession::ClientSession(SOCKET hSocket, DWORD dwHostAddr)
166 {
167 m_pSendQueue = new Queue;
168 m_pMessageQueue = new Queue;
169 m_pUpdateQueue = new Queue;
170 m_hSocket = hSocket;
171 m_dwIndex = INVALID_INDEX;
172 m_iState = SESSION_STATE_INIT;
173 m_pMsgBuffer = (CSCP_BUFFER *)malloc(sizeof(CSCP_BUFFER));
174 m_hWriteThread = INVALID_THREAD_HANDLE;
175 m_hProcessingThread = INVALID_THREAD_HANDLE;
176 m_hUpdateThread = INVALID_THREAD_HANDLE;
177 m_mutexSendEvents = MutexCreate();
178 m_mutexSendObjects = MutexCreate();
179 m_mutexSendAlarms = MutexCreate();
180 m_mutexSendActions = MutexCreate();
181 m_mutexPollerInit = MutexCreate();
182 m_dwFlags = 0;
183 m_dwHostAddr = dwHostAddr;
184 strcpy(m_szUserName, "<not logged in>");
185 m_dwUserId = INVALID_INDEX;
186 m_dwOpenDCIListSize = 0;
187 m_pOpenDCIList = NULL;
188 m_ppEPPRuleList = NULL;
189 m_hCurrFile = -1;
190 m_dwFileRqId = 0;
191 m_dwRefCount = 0;
192 }
193
194
195 //
196 // Destructor
197 //
198
199 ClientSession::~ClientSession()
200 {
201 shutdown(m_hSocket, 2);
202 closesocket(m_hSocket);
203 delete m_pSendQueue;
204 delete m_pMessageQueue;
205 delete m_pUpdateQueue;
206 safe_free(m_pMsgBuffer);
207 MutexDestroy(m_mutexSendEvents);
208 MutexDestroy(m_mutexSendObjects);
209 MutexDestroy(m_mutexSendAlarms);
210 MutexDestroy(m_mutexSendActions);
211 MutexDestroy(m_mutexPollerInit);
212 safe_free(m_pOpenDCIList);
213 if (m_ppEPPRuleList != NULL)
214 {
215 DWORD i;
216
217 if (m_dwFlags & CSF_EPP_UPLOAD) // Aborted in the middle of EPP transfer
218 for(i = 0; i < m_dwRecordsUploaded; i++)
219 delete m_ppEPPRuleList[i];
220 free(m_ppEPPRuleList);
221 }
222 }
223
224
225 //
226 // Start all threads
227 //
228
229 void ClientSession::Run(void)
230 {
231 m_hWriteThread = ThreadCreateEx(WriteThreadStarter, 0, this);
232 m_hProcessingThread = ThreadCreateEx(ProcessingThreadStarter, 0, this);
233 m_hUpdateThread = ThreadCreateEx(UpdateThreadStarter, 0, this);
234 ThreadCreate(ReadThreadStarter, 0, this);
235 }
236
237
238 //
239 // Print debug information
240 //
241
242 void ClientSession::DebugPrintf(char *szFormat, ...)
243 {
244 if ((g_dwFlags & AF_STANDALONE) && (g_dwFlags & AF_DEBUG_CSCP))
245 {
246 va_list args;
247
248 printf("*CSCP(%d)* ", m_dwIndex);
249 va_start(args, szFormat);
250 vprintf(szFormat, args);
251 va_end(args);
252 }
253 }
254
255
256 //
257 // ReadThread()
258 //
259
260 void ClientSession::ReadThread(void)
261 {
262 CSCP_MESSAGE *pRawMsg;
263 CSCPMessage *pMsg;
264 TCHAR szBuffer[256];
265 int iErr;
266 DWORD i;
267 NetObj *pObject;
268 WORD wFlags;
269
270 // Initialize raw message receiving function
271 RecvCSCPMessage(0, NULL, m_pMsgBuffer, 0);
272
273 pRawMsg = (CSCP_MESSAGE *)malloc(RAW_MSG_SIZE);
274 while(1)
275 {
276 if ((iErr = RecvCSCPMessage(m_hSocket, pRawMsg, m_pMsgBuffer, RAW_MSG_SIZE)) <= 0)
277 break;
278
279 // Check if message is too large
280 if (iErr == 1)
281 {
282 DebugPrintf("Received message %s is too large (%d bytes)\n",
283 CSCPMessageCodeName(ntohs(pRawMsg->wCode), szBuffer),
284 ntohl(pRawMsg->dwSize));
285 continue;
286 }
287
288 // Check that actual received packet size is equal to encoded in packet
289 if ((int)ntohl(pRawMsg->dwSize) != iErr)
290 {
291 DebugPrintf("Actual message size doesn't match wSize value (%d,%d)\n", iErr, ntohl(pRawMsg->dwSize));
292 continue; // Bad packet, wait for next
293 }
294
295 // Special handling for raw messages
296 wFlags = ntohs(pRawMsg->wFlags);
297 if (wFlags & MF_BINARY)
298 {
299 // Convert message header to host format
300 pRawMsg->dwId = ntohl(pRawMsg->dwId);
301 pRawMsg->wCode = ntohs(pRawMsg->wCode);
302 pRawMsg->dwNumVars = ntohl(pRawMsg->dwNumVars);
303 DebugPrintf("Received raw message %s\n", CSCPMessageCodeName(pRawMsg->wCode, szBuffer));
304
305 if ((pRawMsg->wCode == CMD_FILE_DATA) ||
306 (pRawMsg->wCode == CMD_ABORT_FILE_TRANSFER))
307 {
308 if ((m_hCurrFile != -1) && (m_dwFileRqId == pRawMsg->dwId))
309 {
310 if (pRawMsg->wCode == CMD_FILE_DATA)
311 {
312 if (write(m_hCurrFile, pRawMsg->df, pRawMsg->dwNumVars) == (int)pRawMsg->dwNumVars)
313 {
314 if (wFlags & MF_EOF)
315 {
316 CSCPMessage msg;
317
318 close(m_hCurrFile);
319 m_hCurrFile = -1;
320
321 msg.SetCode(CMD_REQUEST_COMPLETED);
322 msg.SetId(pRawMsg->dwId);
323 msg.SetVariable(VID_RCC, RCC_SUCCESS);
324 SendMessage(&msg);
325
326 OnFileUpload(TRUE);
327 }
328 }
329 else
330 {
331 // I/O error
332 CSCPMessage msg;
333
334 close(m_hCurrFile);
335 m_hCurrFile = -1;
336
337 msg.SetCode(CMD_REQUEST_COMPLETED);
338 msg.SetId(pRawMsg->dwId);
339 msg.SetVariable(VID_RCC, RCC_IO_ERROR);
340 SendMessage(&msg);
341
342 OnFileUpload(FALSE);
343 }
344 }
345 else
346 {
347 // Abort current file transfer because of client's problem
348 close(m_hCurrFile);
349 m_hCurrFile = -1;
350
351 OnFileUpload(FALSE);
352 }
353 }
354 else
355 {
356 DebugPrintf("Out of state message (ID: %d)\n", pRawMsg->dwId);
357 }
358 }
359 }
360 else
361 {
362 // Create message object from raw message
363 pMsg = new CSCPMessage(pRawMsg);
364 m_pMessageQueue->Put(pMsg);
365 }
366 }
367 if (iErr < 0)
368 WriteLog(MSG_SESSION_CLOSED, EVENTLOG_WARNING_TYPE, "e", WSAGetLastError());
369 free(pRawMsg);
370
371 // Notify other threads to exit
372 m_pSendQueue->Clear();
373 m_pSendQueue->Put(INVALID_POINTER_VALUE);
374 m_pMessageQueue->Clear();
375 m_pMessageQueue->Put(INVALID_POINTER_VALUE);
376 m_pUpdateQueue->Clear();
377 m_pUpdateQueue->Put(INVALID_POINTER_VALUE);
378
379 // Wait for other threads to finish
380 ThreadJoin(m_hWriteThread);
381 ThreadJoin(m_hProcessingThread);
382 ThreadJoin(m_hUpdateThread);
383
384 // Abort current file upload operation, if any
385 if (m_hCurrFile != -1)
386 {
387 close(m_hCurrFile);
388 m_hCurrFile = -1;
389 OnFileUpload(FALSE);
390 }
391
392 // Remove all locks created by this session
393 RemoveAllSessionLocks(m_dwIndex);
394 for(i = 0; i < m_dwOpenDCIListSize; i++)
395 {
396 pObject = FindObjectById(m_pOpenDCIList[i]);
397 if (pObject != NULL)
398 if ((pObject->Type() == OBJECT_NODE) ||
399 (pObject->Type() == OBJECT_TEMPLATE))
400 ((Template *)pObject)->UnlockDCIList(m_dwIndex);
401 }
402
403 // Waiting while reference count becomes 0
404 if (m_dwRefCount > 0)
405 {
406 DebugPrintf("Waiting for pending requests...\n");
407 do
408 {
409 ThreadSleep(1);
410 } while(m_dwRefCount > 0);
411 }
412
413 DebugPrintf("Session closed\n");
414 }
415
416
417 //
418 // WriteThread()
419 //
420
421 void ClientSession::WriteThread(void)
422 {
423 CSCP_MESSAGE *pMsg;
424 char szBuffer[128];
425
426 while(1)
427 {
428 pMsg = (CSCP_MESSAGE *)m_pSendQueue->GetOrBlock();
429 if (pMsg == INVALID_POINTER_VALUE) // Session termination indicator
430 break;
431
432 DebugPrintf("Sending message %s\n", CSCPMessageCodeName(ntohs(pMsg->wCode), szBuffer));
433 if (SendEx(m_hSocket, (const char *)pMsg, ntohl(pMsg->dwSize), 0) <= 0)
434 {
435 safe_free(pMsg);
436 closesocket(m_hSocket);
437 break;
438 }
439 safe_free(pMsg);
440 }
441 }
442
443
444 //
445 // Update processing thread
446 //
447
448 void ClientSession::UpdateThread(void)
449 {
450 UPDATE_INFO *pUpdate;
451 CSCPMessage msg;
452
453 while(1)
454 {
455 pUpdate = (UPDATE_INFO *)m_pUpdateQueue->GetOrBlock();
456 if (pUpdate == INVALID_POINTER_VALUE) // Session termination indicator
457 break;
458
459 switch(pUpdate->dwCategory)
460 {
461 case INFO_CAT_EVENT:
462 MutexLock(m_mutexSendEvents, INFINITE);
463 m_pSendQueue->Put(CreateRawCSCPMessage(CMD_EVENT, 0, sizeof(NXC_EVENT), pUpdate->pData, NULL));
464 MutexUnlock(m_mutexSendEvents);
465 free(pUpdate->pData);
466 break;
467 case INFO_CAT_OBJECT_CHANGE:
468 MutexLock(m_mutexSendObjects, INFINITE);
469 msg.SetCode(CMD_OBJECT_UPDATE);
470 msg.SetId(0);
471 ((NetObj *)pUpdate->pData)->CreateMessage(&msg);
472 SendMessage(&msg);
473 MutexUnlock(m_mutexSendObjects);
474 msg.DeleteAllVariables();
475 ((NetObj *)pUpdate->pData)->DecRefCount();
476 break;
477 case INFO_CAT_ALARM:
478 MutexLock(m_mutexSendAlarms, INFINITE);
479 msg.SetCode(CMD_ALARM_UPDATE);
480 msg.SetId(0);
481 msg.SetVariable(VID_NOTIFICATION_CODE, pUpdate->dwCode);
482 FillAlarmInfoMessage(&msg, (NXC_ALARM *)pUpdate->pData);
483 SendMessage(&msg);
484 MutexUnlock(m_mutexSendAlarms);
485 msg.DeleteAllVariables();
486 free(pUpdate->pData);
487 break;
488 case INFO_CAT_ACTION:
489 MutexLock(m_mutexSendActions, INFINITE);
490 msg.SetCode(CMD_ACTION_DB_UPDATE);
491 msg.SetId(0);
492 msg.SetVariable(VID_NOTIFICATION_CODE, pUpdate->dwCode);
493 msg.SetVariable(VID_ACTION_ID, ((NXC_ACTION *)pUpdate->pData)->dwId);
494 if (pUpdate->dwCode != NX_NOTIFY_ACTION_DELETED)
495 FillActionInfoMessage(&msg, (NXC_ACTION *)pUpdate->pData);
496 SendMessage(&msg);
497 MutexUnlock(m_mutexSendActions);
498 msg.DeleteAllVariables();
499 free(pUpdate->pData);
500 break;
501 default:
502 break;
503 }
504
505 free(pUpdate);
506 }
507 }
508
509
510 //
511 // Message processing thread
512 //
513
514 void ClientSession::ProcessingThread(void)
515 {
516 CSCPMessage *pMsg;
517 char szBuffer[128];
518 DWORD i;
519
520 while(1)
521 {
522 pMsg = (CSCPMessage *)m_pMessageQueue->GetOrBlock();
523 if (pMsg == INVALID_POINTER_VALUE) // Session termination indicator
524 break;
525
526 DebugPrintf("Received message %s\n", CSCPMessageCodeName(pMsg->GetCode(), szBuffer));
527 if (!(m_dwFlags & CSF_AUTHENTICATED) &&
528 (pMsg->GetCode() != CMD_LOGIN) && (pMsg->GetCode() != CMD_GET_SERVER_INFO))
529 {
530 delete pMsg;
531 continue;
532 }
533
534 m_wCurrentCmd = pMsg->GetCode();
535 m_iState = SESSION_STATE_PROCESSING;
536 switch(m_wCurrentCmd)
537 {
538 case CMD_LOGIN:
539 Login(pMsg);
540 break;
541 case CMD_GET_SERVER_INFO:
542 SendServerInfo(pMsg->GetId());
543 break;
544 case CMD_GET_OBJECTS:
545 SendAllObjects(pMsg);
546 break;
547 case CMD_GET_EVENTS:
548 SendAllEvents(pMsg->GetId());
549 break;
550 case CMD_GET_CONFIG_VARLIST:
551 SendAllConfigVars();
552 break;
553 case CMD_LOAD_EVENT_DB:
554 SendEventDB(pMsg->GetId());
555 break;
556 case CMD_LOCK_EVENT_DB:
557 LockEventDB(pMsg->GetId());
558 break;
559 case CMD_UNLOCK_EVENT_DB:
560 UnlockEventDB(pMsg->GetId());
561 break;
562 case CMD_SET_EVENT_INFO:
563 SetEventInfo(pMsg);
564 break;
565 case CMD_DELETE_EVENT_TEMPLATE:
566 DeleteEventTemplate(pMsg);
567 break;
568 case CMD_GENERATE_EVENT_CODE:
569 GenerateEventCode(pMsg->GetId());
570 break;
571 case CMD_MODIFY_OBJECT:
572 ModifyObject(pMsg);
573 break;
574 case CMD_SET_OBJECT_MGMT_STATUS:
575 ChangeObjectMgmtStatus(pMsg);
576 break;
577 case CMD_LOAD_USER_DB:
578 SendUserDB(pMsg->GetId());
579 break;
580 case CMD_CREATE_USER:
581 CreateUser(pMsg);
582 break;
583 case CMD_UPDATE_USER:
584 UpdateUser(pMsg);
585 break;
586 case CMD_DELETE_USER:
587 DeleteUser(pMsg);
588 break;
589 case CMD_LOCK_USER_DB:
590 LockUserDB(pMsg->GetId(), TRUE);
591 break;
592 case CMD_UNLOCK_USER_DB:
593 LockUserDB(pMsg->GetId(), FALSE);
594 break;
595 case CMD_SET_PASSWORD:
596 SetPassword(pMsg);
597 break;
598 case CMD_GET_NODE_DCI_LIST:
599 OpenNodeDCIList(pMsg);
600 break;
601 case CMD_UNLOCK_NODE_DCI_LIST:
602 CloseNodeDCIList(pMsg);
603 break;
604 case CMD_CREATE_NEW_DCI:
605 case CMD_MODIFY_NODE_DCI:
606 case CMD_DELETE_NODE_DCI:
607 ModifyNodeDCI(pMsg);
608 break;
609 case CMD_SET_DCI_STATUS:
610 ChangeDCIStatus(pMsg);
611 break;
612 case CMD_COPY_DCI:
613 CopyDCI(pMsg);
614 break;
615 case CMD_APPLY_TEMPLATE:
616 ApplyTemplate(pMsg);
617 break;
618 case CMD_GET_DCI_DATA:
619 GetCollectedData(pMsg);
620 break;
621 case CMD_OPEN_EPP:
622 OpenEPP(pMsg->GetId());
623 break;
624 case CMD_CLOSE_EPP:
625 CloseEPP(pMsg->GetId());
626 break;
627 case CMD_SAVE_EPP:
628 SaveEPP(pMsg);
629 break;
630 case CMD_EPP_RECORD:
631 ProcessEPPRecord(pMsg);
632 break;
633 case CMD_GET_MIB_LIST:
634 SendMIBList(pMsg->GetId());
635 break;
636 case CMD_GET_MIB:
637 SendMIB(pMsg);
638 break;
639 case CMD_CREATE_OBJECT:
640 CreateObject(pMsg);
641 break;
642 case CMD_BIND_OBJECT:
643 ChangeObjectBinding(pMsg, TRUE);
644 break;
645 case CMD_UNBIND_OBJECT:
646 ChangeObjectBinding(pMsg, FALSE);
647 break;
648 case CMD_GET_IMAGE_LIST:
649 SendImageCatalogue(this, pMsg->GetId(), pMsg->GetVariableShort(VID_IMAGE_FORMAT));
650 break;
651 case CMD_LOAD_IMAGE_FILE:
652 SendImageFile(this, pMsg->GetId(), pMsg->GetVariableLong(VID_IMAGE_ID),
653 pMsg->GetVariableShort(VID_IMAGE_FORMAT));
654 break;
655 case CMD_GET_DEFAULT_IMAGE_LIST:
656 SendDefaultImageList(this, pMsg->GetId());
657 break;
658 case CMD_GET_ALL_ALARMS:
659 SendAllAlarms(pMsg->GetId(), pMsg->GetVariableShort(VID_IS_ACK));
660 break;
661 case CMD_GET_ALARM:
662 break;
663 case CMD_ACK_ALARM:
664 AcknowlegeAlarm(pMsg);
665 break;
666 case CMD_DELETE_ALARM:
667 DeleteAlarm(pMsg);
668 break;
669 case CMD_LOCK_ACTION_DB:
670 LockActionDB(pMsg->GetId(), TRUE);
671 break;
672 case CMD_UNLOCK_ACTION_DB:
673 LockActionDB(pMsg->GetId(), FALSE);
674 break;
675 case CMD_CREATE_ACTION:
676 CreateAction(pMsg);
677 break;
678 case CMD_MODIFY_ACTION:
679 UpdateAction(pMsg);
680 break;
681 case CMD_DELETE_ACTION:
682 DeleteAction(pMsg);
683 break;
684 case CMD_LOAD_ACTIONS:
685 SendAllActions(pMsg->GetId());
686 break;
687 case CMD_GET_CONTAINER_CAT_LIST:
688 SendContainerCategories(pMsg->GetId());
689 break;
690 case CMD_DELETE_OBJECT:
691 DeleteObject(pMsg);
692 break;
693 case CMD_POLL_NODE:
694 ForcedNodePoll(pMsg);
695 break;
696 case CMD_TRAP:
697 OnTrap(pMsg);
698 break;
699 case CMD_WAKEUP_NODE:
700 OnWakeUpNode(pMsg);
701 break;
702 case CMD_LOCK_TRAP_CFG:
703 LockTrapCfg(pMsg->GetId(), TRUE);
704 break;
705 case CMD_UNLOCK_TRAP_CFG:
706 LockTrapCfg(pMsg->GetId(), FALSE);
707 break;
708 case CMD_CREATE_TRAP:
709 EditTrap(TRAP_CREATE, pMsg);
710 break;
711 case CMD_MODIFY_TRAP:
712 EditTrap(TRAP_UPDATE, pMsg);
713 break;
714 case CMD_DELETE_TRAP:
715 EditTrap(TRAP_DELETE, pMsg);
716 break;
717 case CMD_LOAD_TRAP_CFG:
718 SendAllTraps(pMsg->GetId());
719 break;
720 case CMD_QUERY_PARAMETER:
721 QueryParameter(pMsg);
722 break;
723 case CMD_LOCK_PACKAGE_DB:
724 LockPackageDB(pMsg->GetId(), TRUE);
725 break;
726 case CMD_UNLOCK_PACKAGE_DB:
727 LockPackageDB(pMsg->GetId(), FALSE);
728 break;
729 case CMD_GET_PACKAGE_LIST:
730 SendAllPackages(pMsg->GetId());
731 break;
732 case CMD_INSTALL_PACKAGE:
733 InstallPackage(pMsg);
734 break;
735 case CMD_REMOVE_PACKAGE:
736 RemovePackage(pMsg);
737 break;
738 case CMD_GET_PARAMETER_LIST:
739 SendParametersList(pMsg);
740 break;
741 case CMD_DEPLOY_PACKAGE:
742 DeployPackage(pMsg);
743 break;
744 case CMD_GET_LAST_VALUES:
745 SendLastValues(pMsg);
746 break;
747 default:
748 // Pass message to loaded modules
749 for(i = 0; i < g_dwNumModules; i++)
750 if (g_pModuleList[i].pfCommandHandler(m_wCurrentCmd, pMsg, this))
751 break; // Message was processed by the module
752 if (i == g_dwNumModules)
753 {
754 CSCPMessage responce;
755
756 responce.SetId(pMsg->GetId());
757 responce.SetCode(CMD_REQUEST_COMPLETED);
758 responce.SetVariable(VID_RCC, RCC_NOT_IMPLEMENTED);
759 SendMessage(&responce);
760 }
761 break;
762 }
763 delete pMsg;
764 m_iState = (m_dwFlags & CSF_AUTHENTICATED) ? SESSION_STATE_IDLE : SESSION_STATE_INIT;
765 }
766 }
767
768
769 //
770 // Process received file
771 //
772
773 void ClientSession::OnFileUpload(BOOL bSuccess)
774 {
775 // Do processing specific to command initiated file upload
776 switch(m_dwUploadCommand)
777 {
778 case CMD_INSTALL_PACKAGE:
779 if (!bSuccess)
780 {
781 TCHAR szQuery[256];
782
783 _sntprintf(szQuery, 256, _T("DELETE FROM agent_pkg WHERE pkg_id=%ld"), m_dwUploadData);
784 DBQuery(g_hCoreDB, szQuery);
785 }
786 break;
787 default:
788 break;
789 }
790
791 // Remove received file in case of failure
792 if (!bSuccess)
793 _tunlink(m_szCurrFileName);
794 }
795
796
797 //
798 // Send server information to client
799 //
800
801 void ClientSession::SendServerInfo(DWORD dwRqId)
802 {
803 CSCPMessage msg;
804
805 // Prepare responce message
806 msg.SetCode(CMD_REQUEST_COMPLETED);
807 msg.SetId(dwRqId);
808
809 // Fill message with server info
810 msg.SetVariable(VID_RCC, RCC_SUCCESS);
811 msg.SetVariable(VID_SERVER_VERSION, NETXMS_VERSION_STRING);
812 msg.SetVariable(VID_SUPPORTED_ENCRYPTION, (DWORD)0);
813
814 // Send responce
815 SendMessage(&msg);
816 }
817
818
819 //
820 // Authenticate client
821 //
822
823 void ClientSession::Login(CSCPMessage *pRequest)
824 {
825 CSCPMessage msg;
826 BYTE szPassword[SHA1_DIGEST_SIZE];
827 char szLogin[MAX_USER_NAME], szBuffer[32];
828
829 // Prepare responce message
830 msg.SetCode(CMD_LOGIN_RESP);
831 msg.SetId(pRequest->GetId());
832
833 if (!(m_dwFlags & CSF_AUTHENTICATED))
834 {
835
836 pRequest->GetVariableStr(VID_LOGIN_NAME, szLogin, MAX_USER_NAME);
837 pRequest->GetVariableBinary(VID_PASSWORD, szPassword, SHA1_DIGEST_SIZE);
838
839 if (AuthenticateUser(szLogin, szPassword, &m_dwUserId, &m_dwSystemAccess))
840 {
841 m_dwFlags |= CSF_AUTHENTICATED;
842 sprintf(m_szUserName, "%s@%s", szLogin, IpToStr(m_dwHostAddr, szBuffer));
843 msg.SetVariable(VID_RCC, RCC_SUCCESS);
844 DebugPrintf("User %s authenticated\n", m_szUserName);
845 }
846 else
847 {
848 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
849 }
850 }
851 else
852 {
853 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
854 }
855
856 // Send responce
857 SendMessage(&msg);
858 }
859
860
861 //
862 // Send event configuration to client
863 //
864
865 void ClientSession::SendEventDB(DWORD dwRqId)
866 {
867 DB_ASYNC_RESULT hResult;
868 CSCPMessage msg;
869 char szBuffer[1024];
870
871 // Prepare responce message
872 msg.SetCode(CMD_REQUEST_COMPLETED);
873 msg.SetId(dwRqId);
874
875 if (!CheckSysAccessRights(SYSTEM_ACCESS_VIEW_EVENT_DB))
876 {
877 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
878 SendMessage(&msg);
879 }
880 else
881 {
882 msg.SetVariable(VID_RCC, RCC_SUCCESS);
883 SendMessage(&msg);
884 msg.DeleteAllVariables();
885
886 // Prepare data message
887 msg.SetCode(CMD_EVENT_DB_RECORD);
888 msg.SetId(dwRqId);
889
890 hResult = DBAsyncSelect(g_hCoreDB, "SELECT event_code,event_name,severity,flags,message,description FROM event_cfg");
891 if (hResult != NULL)
892 {
893 while(DBFetch(hResult))
894 {
895 msg.SetVariable(VID_EVENT_CODE, DBGetFieldAsyncULong(hResult, 0));
896 msg.SetVariable(VID_NAME, DBGetFieldAsync(hResult, 1, szBuffer, 1024));
897 msg.SetVariable(VID_SEVERITY, DBGetFieldAsyncULong(hResult, 2));
898 msg.SetVariable(VID_FLAGS, DBGetFieldAsyncULong(hResult, 3));
899
900 DBGetFieldAsync(hResult, 4, szBuffer, 1024);
901 DecodeSQLString(szBuffer);
902 msg.SetVariable(VID_MESSAGE, szBuffer);
903
904 DBGetFieldAsync(hResult, 5, szBuffer, 1024);
905 DecodeSQLString(szBuffer);
906 msg.SetVariable(VID_DESCRIPTION, szBuffer);
907
908 SendMessage(&msg);
909 msg.DeleteAllVariables();
910 }
911 DBFreeAsyncResult(hResult);
912 }
913
914 // Send end-of-list indicator
915 msg.SetVariable(VID_EVENT_CODE, (DWORD)0);
916 SendMessage(&msg);
917 }
918 }
919
920
921 //
922 // Lock event configuration database
923 //
924
925 void ClientSession::LockEventDB(DWORD dwRqId)
926 {
927 CSCPMessage msg;
928 char szBuffer[1024];
929
930 // Prepare responce message
931 msg.SetCode(CMD_REQUEST_COMPLETED);
932 msg.SetId(dwRqId);
933
934 if (!CheckSysAccessRights(SYSTEM_ACCESS_EDIT_EVENT_DB))
935 {
936 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
937 }
938 else if (!LockComponent(CID_EVENT_DB, m_dwIndex, m_szUserName, NULL, szBuffer))
939 {
940 msg.SetVariable(VID_RCC, RCC_COMPONENT_LOCKED);
941 msg.SetVariable(VID_LOCKED_BY, szBuffer);
942 }
943 else
944 {
945 m_dwFlags |= CSF_EVENT_DB_LOCKED;
946 m_dwFlags &= ~CSF_EVENT_DB_MODIFIED;
947
948 msg.SetVariable(VID_RCC, RCC_SUCCESS);
949 }
950 SendMessage(&msg);
951 }
952
953
954 //
955 // Close event configuration database
956 //
957
958 void ClientSession::UnlockEventDB(DWORD dwRqId)
959 {
960 CSCPMessage msg;
961
962 msg.SetCode(CMD_REQUEST_COMPLETED);
963 msg.SetId(dwRqId);
964
965 if (m_dwFlags & CSF_EVENT_DB_LOCKED)
966 {
967 // Check if event configuration DB has been modified
968 if (m_dwFlags & CSF_EVENT_DB_MODIFIED)
969 {
970 ReloadEvents();
971
972 // Notify clients on event database change
973 EnumerateClientSessions(NotifyClient, (void *)NX_NOTIFY_EVENTDB_CHANGED);
974 }
975 UnlockComponent(CID_EVENT_DB);
976 m_dwFlags &= ~CSF_EVENT_DB_LOCKED;
977 msg.SetVariable(VID_RCC, RCC_SUCCESS);
978 }
979 else
980 {
981 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
982 }
983 SendMessage(&msg);
984 }
985
986
987 //
988 // Update event template
989 //
990
991 void ClientSession::SetEventInfo(CSCPMessage *pRequest)
992 {
993 CSCPMessage msg;
994
995 // Prepare reply message
996 msg.SetCode(CMD_REQUEST_COMPLETED);
997 msg.SetId(pRequest->GetId());
998
999 // Check if we have event configuration database opened
1000 if (!(m_dwFlags & CSF_EVENT_DB_LOCKED))
1001 {
1002 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
1003 }
1004 else
1005 {
1006 // Check access rights
1007 if (CheckSysAccessRights(SYSTEM_ACCESS_EDIT_EVENT_DB))
1008 {
1009 char szQuery[4096], szName[MAX_EVENT_NAME];
1010 DWORD dwEventCode;
1011 BOOL bEventExist = FALSE;
1012 DB_RESULT hResult;
1013
1014 // Check if event with specific code exists
1015 dwEventCode = pRequest->GetVariableLong(VID_EVENT_CODE);
1016 sprintf(szQuery, "SELECT event_code FROM event_cfg WHERE event_code=%ld", dwEventCode);
1017 hResult = DBSelect(g_hCoreDB, szQuery);
1018 if (hResult != NULL)
1019 {
1020 if (DBGetNumRows(hResult) > 0)
1021 bEventExist = TRUE;
1022 DBFreeResult(hResult);
1023 }
1024
1025 // Check that we are not trying to create event below 100000
1026 if (bEventExist || (dwEventCode >= FIRST_USER_EVENT_ID))
1027 {
1028 // Prepare and execute SQL query
1029 pRequest->GetVariableStr(VID_NAME, szName, MAX_EVENT_NAME);
1030 if (IsValidObjectName(szName))
1031 {
1032 char szMessage[MAX_DB_STRING], *pszDescription, *pszEscMsg, *pszEscDescr;
1033
1034 pRequest->GetVariableStr(VID_MESSAGE, szMessage, MAX_DB_STRING);
1035 pszEscMsg = EncodeSQLString(szMessage);
1036
1037 pszDescription = pRequest->GetVariableStr(VID_DESCRIPTION);
1038 pszEscDescr = EncodeSQLString(pszDescription);
1039 safe_free(pszDescription);
1040
1041 if (bEventExist)
1042 {
1043 sprintf(szQuery, "UPDATE event_cfg SET event_name='%s',severity=%ld,flags=%ld,message='%s',description='%s' WHERE event_code=%ld",
1044 szName, pRequest->GetVariableLong(VID_SEVERITY), pRequest->GetVariableLong(VID_FLAGS),
1045 pszEscMsg, pszEscDescr, dwEventCode);
1046 }
1047 else
1048 {
1049 sprintf(szQuery, "INSERT INTO event_cfg (event_code,event_name,severity,flags,"
1050 "message,description) VALUES (%ld,'%s',%ld,%ld,'%s','%s')",
1051 dwEventCode, szName, pRequest->GetVariableLong(VID_SEVERITY),
1052 pRequest->GetVariableLong(VID_FLAGS), pszEscMsg, pszEscDescr);
1053 }
1054
1055 free(pszEscMsg);
1056 free(pszEscDescr);
1057
1058 if (DBQuery(g_hCoreDB, szQuery))
1059 {
1060 msg.SetVariable(VID_RCC, RCC_SUCCESS);
1061 m_dwFlags |= CSF_EVENT_DB_MODIFIED;
1062 }
1063 else
1064 {
1065 msg.SetVariable(VID_RCC, RCC_DB_FAILURE);
1066 }
1067 }
1068 else
1069 {
1070 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_NAME);
1071 }
1072 }
1073 else
1074 {
1075 msg.SetVariable(VID_RCC, RCC_INVALID_EVENT_CODE);
1076 }
1077 }
1078 else
1079 {
1080 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1081 }
1082 }
1083
1084 // Send responce
1085 SendMessage(&msg);
1086 }
1087
1088
1089 //
1090 // Delete event template
1091 //
1092
1093 void ClientSession::DeleteEventTemplate(CSCPMessage *pRequest)
1094 {
1095 CSCPMessage msg;
1096 DWORD dwEventCode;
1097
1098 // Prepare reply message
1099 msg.SetCode(CMD_REQUEST_COMPLETED);
1100 msg.SetId(pRequest->GetId());
1101
1102 // Check if we have event configuration database opened
1103 if (!(m_dwFlags & CSF_EVENT_DB_LOCKED))
1104 {
1105 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
1106 }
1107 else
1108 {
1109 dwEventCode = pRequest->GetVariableLong(VID_EVENT_CODE);
1110
1111 // Check access rights
1112 if (CheckSysAccessRights(SYSTEM_ACCESS_EDIT_EVENT_DB) && (dwEventCode >= FIRST_USER_EVENT_ID))
1113 {
1114 TCHAR szQuery[256];
1115
1116 _stprintf(szQuery, _T("DELETE FROM event_cfg WHERE event_code=%ld"), dwEventCode);
1117 if (DBQuery(g_hCoreDB, szQuery))
1118 {
1119 msg.SetVariable(VID_RCC, RCC_SUCCESS);
1120 m_dwFlags |= CSF_EVENT_DB_LOCKED;
1121 }
1122 else
1123 {
1124 msg.SetVariable(VID_RCC, RCC_DB_FAILURE);
1125 }
1126 }
1127 else
1128 {
1129 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1130 }
1131 }
1132
1133 // Send responce
1134 SendMessage(&msg);
1135 }
1136
1137
1138 //
1139 // Generate ID for new event template
1140 //
1141
1142 void ClientSession::GenerateEventCode(DWORD dwRqId)
1143 {
1144 CSCPMessage msg;
1145
1146 // Prepare reply message
1147 msg.SetCode(CMD_REQUEST_COMPLETED);
1148 msg.SetId(dwRqId);
1149
1150 // Check if we have event configuration database opened
1151 if (!(m_dwFlags & CSF_EVENT_DB_LOCKED))
1152 {
1153 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
1154 }
1155 else
1156 {
1157 // Check access rights
1158 if (CheckSysAccessRights(SYSTEM_ACCESS_EDIT_EVENT_DB))
1159 {
1160 msg.SetVariable(VID_EVENT_CODE, CreateUniqueId(IDG_EVENT));
1161 }
1162 else
1163 {
1164 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1165 }
1166 }
1167
1168 // Send responce
1169 SendMessage(&msg);
1170 }
1171
1172
1173 //
1174 // Send all objects to client
1175 //
1176
1177 void ClientSession::SendAllObjects(CSCPMessage *pRequest)
1178 {
1179 DWORD i, dwTimeStamp;
1180 CSCPMessage msg;
1181
1182 // Send confirmation message
1183 msg.SetCode(CMD_REQUEST_COMPLETED);
1184 msg.SetId(pRequest->GetId());
1185 msg.SetVariable(VID_RCC, RCC_SUCCESS);
1186 SendMessage(&msg);
1187 msg.DeleteAllVariables();
1188
1189 // Get client's last known time stamp
1190 dwTimeStamp = pRequest->GetVariableLong(VID_TIMESTAMP);
1191
1192 MutexLock(m_mutexSendObjects, INFINITE);
1193
1194 // Prepare message
1195 msg.SetCode(CMD_OBJECT);
1196
1197 // Send objects, one per message
1198 RWLockReadLock(g_rwlockIdIndex, INFINITE);
1199 for(i = 0; i < g_dwIdIndexSize; i++)
1200 if ((g_pIndexById[i].pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_READ)) &&
1201 (g_pIndexById[i].pObject->TimeStamp() > dwTimeStamp))
1202 {
1203 g_pIndexById[i].pObject->CreateMessage(&msg);
1204 SendMessage(&msg);
1205 msg.DeleteAllVariables();
1206 }
1207 RWLockUnlock(g_rwlockIdIndex);
1208
1209 // Send end of list notification
1210 msg.SetCode(CMD_OBJECT_LIST_END);
1211 SendMessage(&msg);
1212
1213 MutexUnlock(m_mutexSendObjects);
1214 }
1215
1216
1217 //
1218 // Send all events to client
1219 //
1220
1221 void ClientSession::SendAllEvents(DWORD dwRqId)
1222 {
1223 CSCPMessage msg;
1224 DB_ASYNC_RESULT hResult;
1225 NXC_EVENT event;
1226 #ifndef UNICODE
1227 char szBuffer[MAX_EVENT_MSG_LENGTH];
1228 #endif
1229
1230 // Send confirmation message
1231 msg.SetCode(CMD_REQUEST_COMPLETED);
1232 msg.SetId(dwRqId);
1233 msg.SetVariable(VID_RCC, RCC_SUCCESS);
1234 SendMessage(&msg);
1235 msg.DeleteAllVariables();
1236
1237 MutexLock(m_mutexSendEvents, INFINITE);
1238
1239 // Retrieve events from database
1240 hResult = DBAsyncSelect(g_hCoreDB, "SELECT event_id,event_code,event_timestamp,event_source,"
1241 "event_severity,event_message FROM event_log "
1242 "ORDER BY event_timestamp");
1243 if (hResult != NULL)
1244 {
1245 // Send events, one per message
1246 while(DBFetch(hResult))
1247 {
1248 event.qwEventId = htonq(DBGetFieldAsyncUInt64(hResult, 0));
1249 event.dwEventCode = htonl(DBGetFieldAsyncULong(hResult, 1));
1250 event.dwTimeStamp = htonl(DBGetFieldAsyncULong(hResult, 2));
1251 event.dwSourceId = htonl(DBGetFieldAsyncULong(hResult, 3));
1252 event.dwSeverity = htonl(DBGetFieldAsyncULong(hResult, 4));
1253 #ifdef UNICODE
1254 DBGetFieldAsync(hResult, 5, event.szMessage, MAX_EVENT_MSG_LENGTH);
1255 DecodeSQLString(event.szMessage);
1256 #else
1257 DBGetFieldAsync(hResult, 5, szBuffer, MAX_EVENT_MSG_LENGTH);
1258 DecodeSQLString(szBuffer);
1259 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, szBuffer, -1,
1260 (WCHAR *)event.szMessage, MAX_EVENT_MSG_LENGTH);
1261 ((WCHAR *)event.szMessage)[MAX_EVENT_MSG_LENGTH - 1] = 0;
1262 #endif
1263 SwapWideString((WCHAR *)event.szMessage);
1264 m_pSendQueue->Put(CreateRawCSCPMessage(CMD_EVENT, dwRqId, sizeof(NXC_EVENT), &event, NULL));
1265 }
1266 DBFreeAsyncResult(hResult);
1267 }
1268
1269 // Send end of list notification
1270 msg.SetCode(CMD_EVENT_LIST_END);
1271 SendMessage(&msg);
1272
1273 MutexUnlock(m_mutexSendEvents);
1274 }
1275
1276
1277 //
1278 // Send all configuration variables to client
1279 //
1280
1281 void ClientSession::SendAllConfigVars(void)
1282 {
1283 DWORD i, dwNumRecords;
1284 CSCPMessage msg;
1285 DB_RESULT hResult;
1286
1287 // Check user rights
1288 if ((m_dwUserId != 0) && ((m_dwSystemAccess & SYSTEM_ACCESS_SERVER_CONFIG) == 0))
1289 {
1290 // Access denied
1291 msg.SetCode(CMD_CONFIG_VARLIST_END);
1292 msg.SetVariable(VID_ERROR, (DWORD)1);
1293 SendMessage(&msg);
1294 }
1295 else
1296 {
1297 // Prepare message
1298 msg.SetCode(CMD_CONFIG_VARIABLE);
1299
1300 // Retrieve configuration variables from database
1301 hResult = DBSelect(g_hCoreDB, "SELECT var_name,var_value FROM config WHERE is_visible=1");
1302 if (hResult != NULL)
1303 {
1304 // Send events, one per message
1305 dwNumRecords = DBGetNumRows(hResult);
1306 for(i = 0; i < dwNumRecords; i++)
1307 {
1308 msg.SetVariable(VID_NAME, DBGetField(hResult, i, 0));
1309 msg.SetVariable(VID_VALUE, DBGetField(hResult, i, 1));
1310 SendMessage(&msg);
1311 msg.DeleteAllVariables();
1312 }
1313 DBFreeResult(hResult);
1314 }
1315
1316 // Send end of list notification
1317 msg.SetCode(CMD_CONFIG_VARLIST_END);
1318 msg.SetVariable(VID_ERROR, (DWORD)0);
1319 SendMessage(&msg);
1320 }
1321 }
1322
1323
1324 //
1325 // Close session forcibly
1326 //
1327
1328 void ClientSession::Kill(void)
1329 {
1330 // We shutdown socket connection, which will cause
1331 // read thread to stop, and other threads will follow
1332 shutdown(m_hSocket, 2);
1333 }
1334
1335
1336 //
1337 // Handler for new events
1338 //
1339
1340 void ClientSession::OnNewEvent(Event *pEvent)
1341 {
1342 UPDATE_INFO *pUpdate;
1343
1344 if (IsAuthenticated())
1345 {
1346 pUpdate = (UPDATE_INFO *)malloc(sizeof(UPDATE_INFO));
1347 pUpdate->dwCategory = INFO_CAT_EVENT;
1348 pUpdate->pData = malloc(sizeof(NXC_EVENT));
1349 pEvent->PrepareMessage((NXC_EVENT *)pUpdate->pData);
1350 m_pUpdateQueue->Put(pUpdate);
1351 }
1352 }
1353
1354
1355 //
1356 // Handler for object changes
1357 //
1358
1359 void ClientSession::OnObjectChange(NetObj *pObject)
1360 {
1361 UPDATE_INFO *pUpdate;
1362
1363 if (IsAuthenticated())
1364 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_READ))
1365 {
1366 pUpdate = (UPDATE_INFO *)malloc(sizeof(UPDATE_INFO));
1367 pUpdate->dwCategory = INFO_CAT_OBJECT_CHANGE;
1368 pUpdate->pData = pObject;
1369 pObject->IncRefCount();
1370 m_pUpdateQueue->Put(pUpdate);
1371 }
1372 }
1373
1374
1375 //
1376 // Send notification message to server
1377 //
1378
1379 void ClientSession::Notify(DWORD dwCode, DWORD dwData)
1380 {
1381 CSCPMessage msg;
1382
1383 msg.SetCode(CMD_NOTIFY);
1384 msg.SetVariable(VID_NOTIFICATION_CODE, dwCode);
1385 msg.SetVariable(VID_NOTIFICATION_DATA, dwData);
1386 SendMessage(&msg);
1387 }
1388
1389
1390 //
1391 // Modify object
1392 //
1393
1394 void ClientSession::ModifyObject(CSCPMessage *pRequest)
1395 {
1396 DWORD dwObjectId, dwResult = RCC_SUCCESS;
1397 NetObj *pObject;
1398 CSCPMessage msg;
1399
1400 // Prepare reply message
1401 msg.SetCode(CMD_REQUEST_COMPLETED);
1402 msg.SetId(pRequest->GetId());
1403
1404 dwObjectId = pRequest->GetVariableLong(VID_OBJECT_ID);
1405 pObject = FindObjectById(dwObjectId);
1406 if (pObject != NULL)
1407 {
1408 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_MODIFY))
1409 {
1410 // If user attempts to change object's ACL, check
1411 // if he has OBJECT_ACCESS_CONTROL permission
1412 if (pRequest->IsVariableExist(VID_ACL_SIZE))
1413 if (!pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_CONTROL))
1414 dwResult = RCC_ACCESS_DENIED;
1415
1416 // If allowed, change object and set completion code
1417 if (dwResult != RCC_ACCESS_DENIED)
1418 dwResult = pObject->ModifyFromMessage(pRequest);
1419 msg.SetVariable(VID_RCC, dwResult);
1420 }
1421 else
1422 {
1423 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1424 }
1425 }
1426 else
1427 {
1428 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
1429 }
1430
1431 // Send responce
1432 SendMessage(&msg);
1433 }
1434
1435
1436 //
1437 // Send users database to client
1438 //
1439
1440 void ClientSession::SendUserDB(DWORD dwRqId)
1441 {
1442 CSCPMessage msg;
1443 DWORD i;
1444
1445 // Prepare responce message
1446 msg.SetCode(CMD_REQUEST_COMPLETED);
1447 msg.SetId(dwRqId);
1448 msg.SetVariable(VID_RCC, RCC_SUCCESS);
1449 SendMessage(&msg);
1450
1451 // Send users
1452 msg.SetCode(CMD_USER_DATA);
1453 for(i = 0; i < g_dwNumUsers; i++)
1454 {
1455 FillUserInfoMessage(&msg, &g_pUserList[i]);
1456 SendMessage(&msg);
1457 msg.DeleteAllVariables();
1458 }
1459
1460 // Send groups
1461 msg.SetCode(CMD_GROUP_DATA);
1462 for(i = 0; i < g_dwNumGroups; i++)
1463 {
1464 FillGroupInfoMessage(&msg, &g_pGroupList[i]);
1465 SendMessage(&msg);
1466 msg.DeleteAllVariables();
1467 }
1468
1469 // Send end-of-database notification
1470 msg.SetCode(CMD_USER_DB_EOF);
1471 SendMessage(&msg);
1472 }
1473
1474
1475 //
1476 // Create new user
1477 //
1478
1479 void ClientSession::CreateUser(CSCPMessage *pRequest)
1480 {
1481 CSCPMessage msg;
1482
1483 // Prepare responce message
1484 msg.SetCode(CMD_REQUEST_COMPLETED);
1485 msg.SetId(pRequest->GetId());
1486
1487 // Check user rights
1488 if (!(m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_USERS))
1489 {
1490 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1491 }
1492 else if (!(m_dwFlags & CSF_USER_DB_LOCKED))
1493 {
1494 // User database have to be locked before any
1495 // changes to user database can be made
1496 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
1497 }
1498 else
1499 {
1500 DWORD dwResult, dwUserId;
1501 BOOL bIsGroup;
1502 char szUserName[MAX_USER_NAME];
1503
1504 pRequest->GetVariableStr(VID_USER_NAME, szUserName, MAX_USER_NAME);
1505 if (IsValidObjectName(szUserName))
1506 {
1507 bIsGroup = pRequest->GetVariableShort(VID_IS_GROUP);
1508 dwResult = CreateNewUser(szUserName, bIsGroup, &dwUserId);
1509 msg.SetVariable(VID_RCC, dwResult);
1510 if (dwResult == RCC_SUCCESS)
1511 msg.SetVariable(VID_USER_ID, dwUserId); // Send id of new user to client
1512 }
1513 else
1514 {
1515 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_NAME);
1516 }
1517 }
1518
1519 // Send responce
1520 SendMessage(&msg);
1521 }
1522
1523
1524 //
1525 // Update existing user's data
1526 //
1527
1528 void ClientSession::UpdateUser(CSCPMessage *pRequest)
1529 {
1530 CSCPMessage msg;
1531
1532 // Prepare responce message
1533 msg.SetCode(CMD_REQUEST_COMPLETED);
1534 msg.SetId(pRequest->GetId());
1535
1536 // Check user rights
1537 if (!(m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_USERS))
1538 {
1539 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1540 }
1541 else if (!(m_dwFlags & CSF_USER_DB_LOCKED))
1542 {
1543 // User database have to be locked before any
1544 // changes to user database can be made
1545 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
1546 }
1547 else
1548 {
1549 DWORD dwUserId, dwResult;
1550
1551 dwUserId = pRequest->GetVariableLong(VID_USER_ID);
1552 if (dwUserId & GROUP_FLAG)
1553 {
1554 NMS_USER_GROUP group;
1555 DWORD i, dwId;
1556
1557 group.dwId = dwUserId;
1558 pRequest->GetVariableStr(VID_USER_DESCRIPTION, group.szDescription, MAX_USER_DESCR);
1559 pRequest->GetVariableStr(VID_USER_NAME, group.szName, MAX_USER_NAME);
1560 group.wFlags = pRequest->GetVariableShort(VID_USER_FLAGS);
1561 group.wSystemRights = pRequest->GetVariableShort(VID_USER_SYS_RIGHTS);
1562 group.dwNumMembers = pRequest->GetVariableLong(VID_NUM_MEMBERS);
1563 group.pMembers = (DWORD *)malloc(sizeof(DWORD) * group.dwNumMembers);
1564 for(i = 0, dwId = VID_GROUP_MEMBER_BASE; i < group.dwNumMembers; i++, dwId++)
1565 group.pMembers[i] = pRequest->GetVariableLong(dwId);
1566 dwResult = ModifyGroup(&group);
1567 safe_free(group.pMembers);
1568 }
1569 else
1570 {
1571 NMS_USER user;
1572
1573 user.dwId = dwUserId;
1574 pRequest->GetVariableStr(VID_USER_DESCRIPTION, user.szDescription, MAX_USER_DESCR);
1575 pRequest->GetVariableStr(VID_USER_FULL_NAME, user.szFullName, MAX_USER_FULLNAME);
1576 pRequest->GetVariableStr(VID_USER_NAME, user.szName, MAX_USER_NAME);
1577 user.wFlags = pRequest->GetVariableShort(VID_USER_FLAGS);
1578 user.wSystemRights = pRequest->GetVariableShort(VID_USER_SYS_RIGHTS);
1579 dwResult = ModifyUser(&user);
1580 }
1581 msg.SetVariable(VID_RCC, dwResult);
1582 }
1583
1584 // Send responce
1585 SendMessage(&msg);
1586 }
1587
1588
1589 //
1590 // Delete user
1591 //
1592
1593 void ClientSession::DeleteUser(CSCPMessage *pRequest)
1594 {
1595 CSCPMessage msg;
1596 DWORD dwUserId;
1597
1598 // Prepare responce message
1599 msg.SetCode(CMD_REQUEST_COMPLETED);
1600 msg.SetId(pRequest->GetId());
1601
1602 // Check user rights
1603 if (!(m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_USERS))
1604 {
1605 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1606 }
1607 else if (!(m_dwFlags & CSF_USER_DB_LOCKED))
1608 {
1609 // User database have to be locked before any
1610 // changes to user database can be made
1611 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
1612 }
1613 else
1614 {
1615 // Get Id of user to be deleted
1616 dwUserId = pRequest->GetVariableLong(VID_USER_ID);
1617
1618 if (dwUserId != 0)
1619 {
1620 DWORD dwResult;
1621
1622 dwResult = DeleteUserFromDB(dwUserId);
1623 msg.SetVariable(VID_RCC, dwResult);
1624 }
1625 else
1626 {
1627 // Nobody can delete system administrator account
1628 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1629 }
1630 }
1631
1632 // Send responce
1633 SendMessage(&msg);
1634 }
1635
1636
1637 //
1638 // Lock/unlock user database
1639 //
1640
1641 void ClientSession::LockUserDB(DWORD dwRqId, BOOL bLock)
1642 {
1643 CSCPMessage msg;
1644 char szBuffer[256];
1645
1646 // Prepare responce message
1647 msg.SetCode(CMD_REQUEST_COMPLETED);
1648 msg.SetId(dwRqId);
1649
1650 if (m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_USERS)
1651 {
1652 if (bLock)
1653 {
1654 if (!LockComponent(CID_USER_DB, m_dwIndex, m_szUserName, NULL, szBuffer))
1655 {
1656 msg.SetVariable(VID_RCC, RCC_COMPONENT_LOCKED);
1657 msg.SetVariable(VID_LOCKED_BY, szBuffer);
1658 }
1659 else
1660 {
1661 m_dwFlags |= CSF_USER_DB_LOCKED;
1662 msg.SetVariable(VID_RCC, RCC_SUCCESS);
1663 }
1664 }
1665 else
1666 {
1667 if (m_dwFlags & CSF_USER_DB_LOCKED)
1668 {
1669 UnlockComponent(CID_USER_DB);
1670 m_dwFlags &= ~CSF_USER_DB_LOCKED;
1671 }
1672 msg.SetVariable(VID_RCC, RCC_SUCCESS);
1673 }
1674 }
1675 else
1676 {
1677 // Current user has no rights for user account management
1678 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1679 }
1680
1681 // Send responce
1682 SendMessage(&msg);
1683 }
1684
1685
1686 //
1687 // Notify client on user database update
1688 //
1689
1690 void ClientSession::OnUserDBUpdate(int iCode, DWORD dwUserId, NMS_USER *pUser, NMS_USER_GROUP *pGroup)
1691 {
1692 CSCPMessage msg;
1693
1694 if (IsAuthenticated())
1695 {
1696 msg.SetCode(CMD_USER_DB_UPDATE);
1697 msg.SetId(0);
1698 msg.SetVariable(VID_UPDATE_TYPE, (WORD)iCode);
1699
1700 switch(iCode)
1701 {
1702 case USER_DB_CREATE:
1703 msg.SetVariable(VID_USER_ID, dwUserId);
1704 if (dwUserId & GROUP_FLAG)
1705 msg.SetVariable(VID_USER_NAME, pGroup->szName);
1706 else
1707 msg.SetVariable(VID_USER_NAME, pUser->szName);
1708 break;
1709 case USER_DB_MODIFY:
1710 if (dwUserId & GROUP_FLAG)
1711 FillGroupInfoMessage(&msg, pGroup);
1712 else
1713 FillUserInfoMessage(&msg, pUser);
1714 break;
1715 default:
1716 msg.SetVariable(VID_USER_ID, dwUserId);
1717 break;
1718 }
1719
1720 SendMessage(&msg);
1721 }
1722 }
1723
1724
1725 //
1726 // Change management status for the object
1727 //
1728
1729 void ClientSession::ChangeObjectMgmtStatus(CSCPMessage *pRequest)
1730 {
1731 CSCPMessage msg;
1732 DWORD dwObjectId;
1733 NetObj *pObject;
1734
1735 // Prepare responce message
1736 msg.SetCode(CMD_REQUEST_COMPLETED);
1737 msg.SetId(pRequest->GetId());
1738
1739 // Get object id and check access rights
1740 dwObjectId = pRequest->GetVariableLong(VID_OBJECT_ID);
1741 pObject = FindObjectById(dwObjectId);
1742 if (pObject != NULL)
1743 {
1744 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_MODIFY))
1745 {
1746 BOOL bIsManaged;
1747
1748 bIsManaged = (BOOL)pRequest->GetVariableShort(VID_MGMT_STATUS);
1749 pObject->SetMgmtStatus(bIsManaged);
1750 msg.SetVariable(VID_RCC, RCC_SUCCESS);
1751 }
1752 else
1753 {
1754 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1755 }
1756 }
1757 else
1758 {
1759 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
1760 }
1761
1762 // Send responce
1763 SendMessage(&msg);
1764 }
1765
1766
1767 //
1768 // Set user's password
1769 //
1770
1771 void ClientSession::SetPassword(CSCPMessage *pRequest)
1772 {
1773 CSCPMessage msg;
1774 DWORD dwUserId;
1775
1776 // Prepare responce message
1777 msg.SetCode(CMD_REQUEST_COMPLETED);
1778 msg.SetId(pRequest->GetId());
1779
1780 dwUserId = pRequest->GetVariableLong(VID_USER_ID);
1781
1782 if (((m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_USERS) &&
1783 !((dwUserId == 0) && (m_dwUserId != 0))) || // Only administrator can change password for UID 0
1784 (dwUserId == m_dwUserId)) // User can change password for itself
1785 {
1786 DWORD dwResult;
1787 BYTE szPassword[SHA1_DIGEST_SIZE];
1788
1789 pRequest->GetVariableBinary(VID_PASSWORD, szPassword, SHA1_DIGEST_SIZE);
1790 dwResult = SetUserPassword(dwUserId, szPassword);
1791 msg.SetVariable(VID_RCC, dwResult);
1792 }
1793 else
1794 {
1795 // Current user has no rights to change password for specific user
1796 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1797 }
1798
1799 // Send responce
1800 SendMessage(&msg);
1801 }
1802
1803
1804 //
1805 // Send node's DCIs to client and lock data collection settings
1806 //
1807
1808 void ClientSession::OpenNodeDCIList(CSCPMessage *pRequest)
1809 {
1810 CSCPMessage msg;
1811 DWORD dwObjectId;
1812 NetObj *pObject;
1813 BOOL bSuccess = FALSE;
1814
1815 // Prepare responce message
1816 msg.SetCode(CMD_REQUEST_COMPLETED);
1817 msg.SetId(pRequest->GetId());
1818
1819 // Get node id and check object class and access rights
1820 dwObjectId = pRequest->GetVariableLong(VID_OBJECT_ID);
1821 pObject = FindObjectById(dwObjectId);
1822 if (pObject != NULL)
1823 {
1824 if ((pObject->Type() == OBJECT_NODE) ||
1825 (pObject->Type() == OBJECT_TEMPLATE))
1826 {
1827 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_READ))
1828 {
1829 // Try to lock DCI list
1830 bSuccess = ((Template *)pObject)->LockDCIList(m_dwIndex);
1831 msg.SetVariable(VID_RCC, bSuccess ? RCC_SUCCESS : RCC_COMPONENT_LOCKED);
1832
1833 // Modify list of open nodes DCI lists
1834 if (bSuccess)
1835 {
1836 m_pOpenDCIList = (DWORD *)realloc(m_pOpenDCIList, sizeof(DWORD) * (m_dwOpenDCIListSize + 1));
1837 m_pOpenDCIList[m_dwOpenDCIListSize] = dwObjectId;
1838 m_dwOpenDCIListSize++;
1839 }
1840 }
1841 else
1842 {
1843 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1844 }
1845 }
1846 else
1847 {
1848 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
1849 }
1850 }
1851 else
1852 {
1853 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
1854 }
1855
1856 // Send responce
1857 SendMessage(&msg);
1858
1859 // If DCI list was successfully locked, send it to client
1860 if (bSuccess)
1861 ((Template *)pObject)->SendItemsToClient(this, pRequest->GetId());
1862 }
1863
1864
1865 //
1866 // Unlock node's data collection settings
1867 //
1868
1869 void ClientSession::CloseNodeDCIList(CSCPMessage *pRequest)
1870 {
1871 CSCPMessage msg;
1872 DWORD dwObjectId;
1873 NetObj *pObject;
1874
1875 // Prepare responce message
1876 msg.SetCode(CMD_REQUEST_COMPLETED);
1877 msg.SetId(pRequest->GetId());
1878
1879 // Get node id and check object class and access rights
1880 dwObjectId = pRequest->GetVariableLong(VID_OBJECT_ID);
1881 pObject = FindObjectById(dwObjectId);
1882 if (pObject != NULL)
1883 {
1884 if ((pObject->Type() == OBJECT_NODE) ||
1885 (pObject->Type() == OBJECT_TEMPLATE))
1886 {
1887 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_READ))
1888 {
1889 BOOL bSuccess;
1890
1891 // Try to unlock DCI list
1892 bSuccess = ((Template *)pObject)->UnlockDCIList(m_dwIndex);
1893 msg.SetVariable(VID_RCC, bSuccess ? RCC_SUCCESS : RCC_OUT_OF_STATE_REQUEST);
1894
1895 // Modify list of open nodes DCI lists
1896 if (bSuccess)
1897 {
1898 DWORD i;
1899
1900 for(i = 0; i < m_dwOpenDCIListSize; i++)
1901 if (m_pOpenDCIList[i] == dwObjectId)
1902 {
1903 m_dwOpenDCIListSize--;
1904 memmove(&m_pOpenDCIList[i], &m_pOpenDCIList[i + 1],
1905 sizeof(DWORD) * (m_dwOpenDCIListSize - i));
1906 break;
1907 }
1908 }
1909 }
1910 else
1911 {
1912 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1913 }
1914 }
1915 else
1916 {
1917 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
1918 }
1919 }
1920 else
1921 {
1922 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
1923 }
1924
1925 // Send responce
1926 SendMessage(&msg);
1927 }
1928
1929
1930 //
1931 // Create, modify, or delete data collection item for node
1932 //
1933
1934 void ClientSession::ModifyNodeDCI(CSCPMessage *pRequest)
1935 {
1936 CSCPMessage msg;
1937 DWORD dwObjectId;
1938 NetObj *pObject;
1939
1940 // Prepare responce message
1941 msg.SetCode(CMD_REQUEST_COMPLETED);
1942 msg.SetId(pRequest->GetId());
1943
1944 // Get node id and check object class and access rights
1945 dwObjectId = pRequest->GetVariableLong(VID_OBJECT_ID);
1946 pObject = FindObjectById(dwObjectId);
1947 if (pObject != NULL)
1948 {
1949 if ((pObject->Type() == OBJECT_NODE) ||
1950 (pObject->Type() == OBJECT_TEMPLATE))
1951 {
1952 if (((Template *)pObject)->IsLockedBySession(m_dwIndex))
1953 {
1954 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_MODIFY))
1955 {
1956 DWORD i, dwItemId, dwNumMaps, *pdwMapId, *pdwMapIndex;
1957 DCItem *pItem;
1958 BOOL bSuccess;
1959
1960 switch(pRequest->GetCode())
1961 {
1962 case CMD_CREATE_NEW_DCI:
1963 // Create dummy DCI
1964 pItem = new DCItem(CreateUniqueId(IDG_ITEM), "no name", DS_INTERNAL,
1965 DCI_DT_INT, 60, 30, (Node *)pObject);
1966 pItem->SetStatus(ITEM_STATUS_DISABLED);
1967 if (((Template *)pObject)->AddItem(pItem))
1968 {
1969 msg.SetVariable(VID_RCC, RCC_SUCCESS);
1970 // Return new item id to client
1971 msg.SetVariable(VID_DCI_ID, pItem->Id());
1972 }
1973 else // Unable to add item to node
1974 {
1975 delete pItem;
1976 msg.SetVariable(VID_RCC, RCC_DUPLICATE_DCI);
1977 }
1978 break;
1979 case CMD_MODIFY_NODE_DCI:
1980 dwItemId = pRequest->GetVariableLong(VID_DCI_ID);
1981 bSuccess = ((Template *)pObject)->UpdateItem(dwItemId, pRequest, &dwNumMaps,
1982 &pdwMapIndex, &pdwMapId);
1983 if (bSuccess)
1984 {
1985 msg.SetVariable(VID_RCC, RCC_SUCCESS);
1986
1987 // Send index to id mapping for newly created thresholds to client
1988 msg.SetVariable(VID_DCI_NUM_MAPS, dwNumMaps);
1989 for(i = 0; i < dwNumMaps; i++)
1990 {
1991 pdwMapId[i] = htonl(pdwMapId[i]);
1992 pdwMapIndex[i] = htonl(pdwMapIndex[i]);
1993 }
1994 msg.SetVariable(VID_DCI_MAP_IDS, (BYTE *)pdwMapId, sizeof(DWORD) * dwNumMaps);
1995 msg.SetVariable(VID_DCI_MAP_INDEXES, (BYTE *)pdwMapIndex, sizeof(DWORD) * dwNumMaps);
1996 safe_free(pdwMapId);
1997 safe_free(pdwMapIndex);
1998 }
1999 else
2000 {
2001 msg.SetVariable(VID_RCC, RCC_INVALID_DCI_ID);
2002 }
2003 break;
2004 case CMD_DELETE_NODE_DCI:
2005 dwItemId = pRequest->GetVariableLong(VID_DCI_ID);
2006 bSuccess = ((Template *)pObject)->DeleteItem(dwItemId);
2007 msg.SetVariable(VID_RCC, bSuccess ? RCC_SUCCESS : RCC_INVALID_DCI_ID);
2008 break;
2009 }
2010 if (bSuccess)
2011 ((Template *)pObject)->SetDCIModificationFlag();
2012 }
2013 else // User doesn't have MODIFY rights on object
2014 {
2015 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2016 }
2017 }
2018 else // Nodes DCI list not locked by this session
2019 {
2020 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
2021 }
2022 }
2023 else // Object is not a node
2024 {
2025 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
2026 }
2027 }
2028 else // No object with given ID
2029 {
2030 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
2031 }
2032
2033 // Send responce
2034 SendMessage(&msg);
2035 }
2036
2037
2038 //
2039 // Change status for one or more DCIs
2040 //
2041
2042 void ClientSession::ChangeDCIStatus(CSCPMessage *pRequest)
2043 {
2044 CSCPMessage msg;
2045 NetObj *pObject;
2046
2047 // Prepare responce message
2048 msg.SetCode(CMD_REQUEST_COMPLETED);
2049 msg.SetId(pRequest->GetId());
2050
2051 // Get node id and check object class and access rights
2052 pObject = FindObjectById(pRequest->GetVariableLong(VID_OBJECT_ID));
2053 if (pObject != NULL)
2054 {
2055 if ((pObject->Type() == OBJECT_NODE) ||
2056 (pObject->Type() == OBJECT_TEMPLATE))
2057 {
2058 if (((Template *)pObject)->IsLockedBySession(m_dwIndex))
2059 {
2060 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_MODIFY))
2061 {
2062 DWORD dwNumItems, *pdwItemList;
2063 int iStatus;
2064
2065 iStatus = pRequest->GetVariableShort(VID_DCI_STATUS);
2066 dwNumItems = pRequest->GetVariableLong(VID_NUM_ITEMS);
2067 pdwItemList = (DWORD *)malloc(sizeof(DWORD) * dwNumItems);
2068 pRequest->GetVariableInt32Array(VID_ITEM_LIST, dwNumItems, pdwItemList);
2069 if (((Template *)pObject)->SetItemStatus(dwNumItems, pdwItemList, iStatus))
2070 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2071 else
2072 msg.SetVariable(VID_RCC, RCC_INVALID_DCI_ID);
2073 free(pdwItemList);
2074 }
2075 else // User doesn't have MODIFY rights on object
2076 {
2077 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2078 }
2079 }
2080 else // Nodes DCI list not locked by this session
2081 {
2082 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
2083 }
2084 }
2085 else // Object is not a node
2086 {
2087 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
2088 }
2089 }
2090 else // No object with given ID
2091 {
2092 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
2093 }
2094
2095 // Send responce
2096 SendMessage(&msg);
2097 }
2098
2099
2100 //
2101 // Copy DCI from one node or template to another
2102 //
2103
2104 void ClientSession::CopyDCI(CSCPMessage *pRequest)
2105 {
2106 CSCPMessage msg;
2107 NetObj *pSource, *pDestination;
2108
2109 // Prepare responce message
2110 msg.SetCode(CMD_REQUEST_COMPLETED);
2111 msg.SetId(pRequest->GetId());
2112
2113 // Get source and destination
2114 pSource = FindObjectById(pRequest->GetVariableLong(VID_SOURCE_OBJECT_ID));
2115 pDestination = FindObjectById(pRequest->GetVariableLong(VID_DESTINATION_OBJECT_ID));
2116 if ((pSource != NULL) && (pDestination != NULL))
2117 {
2118 // Check object types
2119 if (((pSource->Type() == OBJECT_NODE) || (pSource->Type() == OBJECT_TEMPLATE)) &&
2120 (pDestination->Type() == OBJECT_NODE))
2121 {
2122 if (((Template *)pSource)->IsLockedBySession(m_dwIndex))
2123 {
2124 // Check access rights
2125 if ((pSource->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_READ)) &&
2126 (pDestination->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_MODIFY)))
2127 {
2128 // Attempt to lock destination's DCI list
2129 if ((pDestination->Id() == pSource->Id()) ||
2130 (((Template *)pDestination)->LockDCIList(m_dwIndex)))
2131 {
2132 DWORD i, *pdwItemList, dwNumItems;
2133 const DCItem *pSrcItem;
2134 DCItem *pDstItem;
2135 int iErrors = 0;
2136
2137 // Get list of items to be copied
2138 dwNumItems = pRequest->GetVariableLong(VID_NUM_ITEMS);
2139 pdwItemList = (DWORD *)malloc(sizeof(DWORD) * dwNumItems);
2140 pRequest->GetVariableInt32Array(VID_ITEM_LIST, dwNumItems, pdwItemList);
2141
2142 // Copy items
2143 for(i = 0; i < dwNumItems; i++)
2144 {
2145 pSrcItem = ((Template *)pSource)->GetItemById(pdwItemList[i]);
2146 if (pSrcItem != NULL)
2147 {
2148 pDstItem = new DCItem(pSrcItem);
2149 pDstItem->ChangeBinding(CreateUniqueId(IDG_ITEM),
2150 (Template *)pDestination);
2151 if (!((Template *)pDestination)->AddItem(pDstItem))
2152 {
2153 delete pDstItem;
2154 iErrors++;
2155 }
2156 }
2157 else
2158 {
2159 iErrors++;
2160 }
2161 }
2162
2163 // Cleanup
2164 free(pdwItemList);
2165 if (pDestination->Id() != pSource->Id())
2166 ((Template *)pDestination)->UnlockDCIList(m_dwIndex);
2167 msg.SetVariable(VID_RCC, (iErrors == 0) ? RCC_SUCCESS : RCC_DCI_COPY_ERRORS);
2168 }
2169 else // Destination's DCI list already locked by someone else
2170 {
2171 msg.SetVariable(VID_RCC, RCC_COMPONENT_LOCKED);
2172 }
2173 }
2174 else // User doesn't have enough rights on object(s)
2175 {
2176 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2177 }
2178 }
2179 else // Source node DCI list not locked by this session
2180 {
2181 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
2182 }
2183 }
2184 else // Object(s) is not a node
2185 {
2186 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
2187 }
2188 }
2189 else // No object(s) with given ID
2190 {
2191 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
2192 }
2193
2194 // Send responce
2195 SendMessage(&msg);
2196 }
2197
2198
2199 //
2200 // Get collected data
2201 //
2202
2203 void ClientSession::GetCollectedData(CSCPMessage *pRequest)
2204 {
2205 CSCPMessage msg;
2206 DWORD dwObjectId;
2207 NetObj *pObject;
2208 BOOL bSuccess = FALSE;
2209 static DWORD m_dwRowSize[] = { 8, 8, 12, 12, 260, 12 };
2210
2211 // Prepare responce message
2212 msg.SetCode(CMD_REQUEST_COMPLETED);
2213 msg.SetId(pRequest->GetId());
2214
2215 // Get node id and check object class and access rights
2216 dwObjectId = pRequest->GetVariableLong(VID_OBJECT_ID);
2217 pObject = FindObjectById(dwObjectId);
2218 if (pObject != NULL)
2219 {
2220 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_READ))
2221 {
2222 DB_ASYNC_RESULT hResult;
2223 DWORD dwItemId, dwMaxRows, dwTimeFrom, dwTimeTo;
2224 DWORD dwAllocatedRows = 100, dwNumRows = 0;
2225 char szQuery[512], szCond[256];
2226 int iPos = 0, iType;
2227 DCI_DATA_HEADER *pData = NULL;
2228 DCI_DATA_ROW *pCurr;
2229
2230 // Get request parameters
2231 dwItemId = pRequest->GetVariableLong(VID_DCI_ID);
2232 dwMaxRows = pRequest->GetVariableLong(VID_MAX_ROWS);
2233 dwTimeFrom = pRequest->GetVariableLong(VID_TIME_FROM);
2234 dwTimeTo = pRequest->GetVariableLong(VID_TIME_TO);
2235
2236 szCond[0] = 0;
2237 if (dwTimeFrom != 0)
2238 {
2239 sprintf(szCond, " AND idata_timestamp>=%d", dwTimeFrom);
2240 iPos = strlen(szCond);
2241 }
2242 if (dwTimeTo != 0)
2243 {
2244 sprintf(&szCond[iPos], " AND idata_timestamp<=%d", dwTimeTo);
2245 }
2246
2247 // Get item's data type to determine actual row size
2248 iType = ((Node *)pObject)->GetItemType(dwItemId);
2249
2250 // Create database-dependent query for fetching N rows
2251 if (dwMaxRows > 0)
2252 {
2253 switch(g_dwDBSyntax)
2254 {
2255 case DB_SYNTAX_MSSQL:
2256 sprintf(szQuery, "SELECT TOP %ld idata_timestamp,idata_value FROM idata_%d WHERE item_id=%d%s ORDER BY idata_timestamp DESC",
2257 dwMaxRows, dwObjectId, dwItemId, szCond);
2258 break;
2259 case DB_SYNTAX_MYSQL:
2260 case DB_SYNTAX_PGSQL:
2261 sprintf(szQuery, "SELECT idata_timestamp,idata_value FROM idata_%d WHERE item_id=%d%s ORDER BY idata_timestamp DESC LIMIT %ld",
2262 dwObjectId, dwItemId, szCond, dwMaxRows);
2263 break;
2264 default:
2265 sprintf(szQuery, "SELECT idata_timestamp,idata_value FROM idata_%d WHERE item_id=%d%s ORDER BY idata_timestamp DESC",
2266 dwObjectId, dwItemId, szCond);
2267 break;
2268 }
2269 }
2270 else
2271 {
2272 sprintf(szQuery, "SELECT idata_timestamp,idata_value FROM idata_%d WHERE item_id=%d%s ORDER BY idata_timestamp DESC",
2273 dwObjectId, dwItemId, szCond);
2274 }
2275 hResult = DBAsyncSelect(g_hCoreDB, szQuery);
2276 if (hResult != NULL)
2277 {
2278 // Send CMD_REQUEST_COMPLETED message
2279 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2280 SendMessage(&msg);
2281
2282 // Allocate initial memory block and prepare data header
2283 pData = (DCI_DATA_HEADER *)malloc(dwAllocatedRows * m_dwRowSize[iType] + sizeof(DCI_DATA_HEADER));
2284 pData->dwDataType = htonl((DWORD)iType);
2285 pData->dwItemId = htonl(dwItemId);
2286
2287 // Fill memory block with records
2288 pCurr = (DCI_DATA_ROW *)(((char *)pData) + sizeof(DCI_DATA_HEADER));
2289 while(DBFetch(hResult))
2290 {
2291 if ((dwMaxRows > 0) && (dwNumRows >= dwMaxRows))
2292 break;
2293
2294 // Extend buffer if we are at the end
2295 if (dwNumRows == dwAllocatedRows)
2296 {
2297 dwAllocatedRows += 50;
2298 pData = (DCI_DATA_HEADER *)realloc(pData,
2299 dwAllocatedRows * m_dwRowSize[iType] + sizeof(DCI_DATA_HEADER));
2300 pCurr = (DCI_DATA_ROW *)(((char *)pData) + sizeof(DCI_DATA_HEADER) + m_dwRowSize[iType] * dwNumRows);
2301 }
2302
2303 dwNumRows++;
2304
2305 pCurr->dwTimeStamp = htonl(DBGetFieldAsyncULong(hResult, 0));
2306 switch(iType)
2307 {
2308 case DCI_DT_INT:
2309 case DCI_DT_UINT:
2310 pCurr->value.dwInteger = htonl(DBGetFieldAsyncULong(hResult, 1));
2311 break;
2312 case DCI_DT_INT64:
2313 case DCI_DT_UINT64:
2314 pCurr->value.qwInt64 = htonq(DBGetFieldAsyncUInt64(hResult, 1));
2315 break;
2316 case DCI_DT_FLOAT:
2317 pCurr->value.dFloat = htond(DBGetFieldAsyncDouble(hResult, 1));
2318 break;
2319 case DCI_DT_STRING:
2320 DBGetFieldAsync(hResult, 1, pCurr->value.szString, MAX_DCI_STRING_VALUE);
2321 break;
2322 }
2323 pCurr = (DCI_DATA_ROW *)(((char *)pCurr) + m_dwRowSize[iType]);
2324 }
2325 DBFreeAsyncResult(hResult);
2326 pData->dwNumRows = htonl(dwNumRows);
2327
2328 // Prepare and send raw message with fetched data
2329 m_pSendQueue->Put(
2330 CreateRawCSCPMessage(CMD_DCI_DATA, pRequest->GetId(),
2331 dwNumRows * m_dwRowSize[iType] + sizeof(DCI_DATA_HEADER),
2332 pData, NULL));
2333 free(pData);
2334 bSuccess = TRUE;
2335 }
2336 else
2337 {
2338 msg.SetVariable(VID_RCC, RCC_DB_FAILURE);
2339 }
2340 }
2341 else
2342 {
2343 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2344 }
2345 }
2346 else // No object with given ID
2347 {
2348 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
2349 }
2350
2351 // Send responce
2352 if (!bSuccess)
2353 SendMessage(&msg);
2354 }
2355
2356
2357 //
2358 // Send latest collected values for all DCIs of given node
2359 //
2360
2361 void ClientSession::SendLastValues(CSCPMessage *pRequest)
2362 {
2363 CSCPMessage msg;
2364 NetObj *pObject;
2365
2366 // Prepare responce message
2367 msg.SetCode(CMD_REQUEST_COMPLETED);
2368 msg.SetId(pRequest->GetId());
2369
2370 // Get node id and check object class and access rights
2371 pObject = FindObjectById(pRequest->GetVariableLong(VID_OBJECT_ID));
2372 if (pObject != NULL)
2373 {
2374 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_READ))
2375 {
2376 if (pObject->Type() == OBJECT_NODE)
2377 {
2378 msg.SetVariable(VID_RCC, ((Node *)pObject)->GetLastValues(&msg));
2379 }
2380 else
2381 {
2382 msg.SetVariable(VID_RCC, RCC_INCOMPATIBLE_OPERATION);
2383 }
2384 }
2385 else
2386 {
2387 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2388 }
2389 }
2390 else // No object with given ID
2391 {
2392 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
2393 }
2394
2395 // Send responce
2396 SendMessage(&msg);
2397 }
2398
2399
2400 //
2401 // Open event processing policy
2402 //
2403
2404 void ClientSession::OpenEPP(DWORD dwRqId)
2405 {
2406 CSCPMessage msg;
2407 char szBuffer[256];
2408 BOOL bSuccess = FALSE;
2409
2410 // Prepare responce message
2411 msg.SetCode(CMD_REQUEST_COMPLETED);
2412 msg.SetId(dwRqId);
2413
2414 if (m_dwSystemAccess & SYSTEM_ACCESS_EPP)
2415 {
2416 if (!LockComponent(CID_EPP, m_dwIndex, m_szUserName, NULL, szBuffer))
2417 {
2418 msg.SetVariable(VID_RCC, RCC_COMPONENT_LOCKED);
2419 msg.SetVariable(VID_LOCKED_BY, szBuffer);
2420 }
2421 else
2422 {
2423 m_dwFlags |= CSF_EPP_LOCKED;
2424 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2425 msg.SetVariable(VID_NUM_RULES, g_pEventPolicy->NumRules());
2426 bSuccess = TRUE;
2427 }
2428 }
2429 else
2430 {
2431 // Current user has no rights for event policy management
2432 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2433 }
2434
2435 // Send responce
2436 SendMessage(&msg);
2437
2438 // Send policy to client
2439 if (bSuccess)
2440 g_pEventPolicy->SendToClient(this, dwRqId);
2441 }
2442
2443
2444 //
2445 // Close event processing policy
2446 //
2447
2448 void ClientSession::CloseEPP(DWORD dwRqId)
2449 {
2450 CSCPMessage msg;
2451
2452 // Prepare responce message
2453 msg.SetCode(CMD_REQUEST_COMPLETED);
2454 msg.SetId(dwRqId);
2455
2456 if (m_dwSystemAccess & SYSTEM_ACCESS_EPP)
2457 {
2458 if (m_dwFlags & CSF_EPP_LOCKED)
2459 {
2460 UnlockComponent(CID_EPP);
2461 m_dwFlags &= ~CSF_EPP_LOCKED;
2462 }
2463 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2464 }
2465 else
2466 {
2467 // Current user has no rights for event policy management
2468 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2469 }
2470
2471 // Send responce
2472 SendMessage(&msg);
2473 }
2474
2475
2476 //
2477 // Save event processing policy
2478 //
2479
2480 void ClientSession::SaveEPP(CSCPMessage *pRequest)
2481 {
2482 CSCPMessage msg;
2483
2484 // Prepare responce message
2485 msg.SetCode(CMD_REQUEST_COMPLETED);
2486 msg.SetId(pRequest->GetId());
2487
2488 if (m_dwSystemAccess & SYSTEM_ACCESS_EPP)
2489 {
2490 if (m_dwFlags & CSF_EPP_LOCKED)
2491 {
2492 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2493 m_dwNumRecordsToUpload = pRequest->GetVariableLong(VID_NUM_RULES);
2494 m_dwRecordsUploaded = 0;
2495 if (m_dwNumRecordsToUpload == 0)
2496 {
2497 g_pEventPolicy->ReplacePolicy(0, NULL);
2498 g_pEventPolicy->SaveToDB();
2499 }
2500 else
2501 {
2502 m_dwFlags |= CSF_EPP_UPLOAD;
2503 m_ppEPPRuleList = (EPRule **)malloc(sizeof(EPRule *) * m_dwNumRecordsToUpload);
2504 memset(m_ppEPPRuleList, 0, sizeof(EPRule *) * m_dwNumRecordsToUpload);
2505 }
2506 DebugPrintf("Accepted EPP upload request for %d rules\n", m_dwNumRecordsToUpload);
2507 }
2508 else
2509 {
2510 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
2511 }
2512 }
2513 else
2514 {
2515 // Current user has no rights for event policy management
2516 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2517 }
2518
2519 // Send responce
2520 SendMessage(&msg);
2521 }
2522
2523
2524 //
2525 // Process EPP rule received from client
2526 //
2527
2528 void ClientSession::ProcessEPPRecord(CSCPMessage *pRequest)
2529 {
2530 if (!(m_dwFlags & CSF_EPP_LOCKED))
2531 {
2532 CSCPMessage msg;
2533
2534 msg.SetCode(CMD_REQUEST_COMPLETED);
2535 msg.SetId(pRequest->GetId());
2536 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
2537 SendMessage(&msg);
2538 }
2539 else
2540 {
2541 if (m_dwRecordsUploaded < m_dwNumRecordsToUpload)
2542 {
2543 m_ppEPPRuleList[m_dwRecordsUploaded] = new EPRule(pRequest);
2544 m_dwRecordsUploaded++;
2545 if (m_dwRecordsUploaded == m_dwNumRecordsToUpload)
2546 {
2547 CSCPMessage msg;
2548
2549 // All records received, replace event policy...
2550 DebugPrintf("Replacing event processing policy with a new one at %p (%d rules)\n",
2551 m_ppEPPRuleList, m_dwNumRecordsToUpload);
2552 g_pEventPolicy->ReplacePolicy(m_dwNumRecordsToUpload, m_ppEPPRuleList);
2553 g_pEventPolicy->SaveToDB();
2554 m_ppEPPRuleList = NULL;
2555
2556 // ... and send final confirmation
2557 msg.SetCode(CMD_REQUEST_COMPLETED);
2558 msg.SetId(pRequest->GetId());
2559 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2560 SendMessage(&msg);
2561
2562 m_dwFlags &= ~CSF_EPP_UPLOAD;
2563 }
2564 }
2565 }
2566 }
2567
2568
2569 //
2570 // Send list of available MIB files to client
2571 //
2572
2573 void ClientSession::SendMIBList(DWORD dwRqId)
2574 {
2575 CSCPMessage msg;
2576 DWORD dwId1, dwId2, dwNumFiles;
2577 DIR *dir;
2578 int iBufPos;
2579 struct dirent *dptr;
2580 char szBuffer[MAX_PATH];
2581 BYTE md5Hash[MD5_DIGEST_SIZE];
2582
2583 // Prepare responce message
2584 msg.SetCode(CMD_MIB_LIST);
2585 msg.SetId(dwRqId);
2586
2587 // Read directory
2588 dwNumFiles = 0;
2589 strcpy(szBuffer, g_szDataDir);
2590 strcat(szBuffer, DDIR_MIBS);
2591 dir = opendir(szBuffer);
2592 if (dir != NULL)
2593 {
2594 strcat(szBuffer, FS_PATH_SEPARATOR);
2595 iBufPos = strlen(szBuffer);
2596 dwId1 = VID_MIB_NAME_BASE;
2597 dwId2 = VID_MIB_HASH_BASE;
2598 while((dptr = readdir(dir)) != NULL)
2599 {
2600 if (dptr->d_name[0] == '.')
2601 continue;
2602
2603 strcpy(&szBuffer[iBufPos], dptr->d_name);
2604 if (CalculateFileMD5Hash(szBuffer, md5Hash))
2605 {
2606 msg.SetVariable(dwId1++, dptr->d_name);
2607 msg.SetVariable(dwId2++, md5Hash, MD5_DIGEST_SIZE);
2608 dwNumFiles++;
2609 }
2610 }
2611 closedir(dir);
2612 }
2613
2614 msg.SetVariable(VID_NUM_MIBS, dwNumFiles);
2615
2616 // Send responce
2617 SendMessage(&msg);
2618 }
2619
2620
2621 //
2622 // Send requested MIB file to client
2623 //
2624
2625 void ClientSession::SendMIB(CSCPMessage *pRequest)
2626 {
2627 CSCPMessage msg;
2628 BYTE *pFile;
2629 DWORD dwFileSize;
2630 char szBuffer[MAX_PATH], szMIB[MAX_PATH];
2631
2632 // Prepare responce message
2633 msg.SetCode(CMD_MIB);
2634 msg.SetId(pRequest->GetId());
2635
2636 // Get name of the requested file
2637 pRequest->GetVariableStr(VID_MIB_NAME, szMIB, MAX_PATH);
2638
2639 // Load file into memory
2640 strcpy(szBuffer, g_szDataDir);
2641 strcat(szBuffer, DDIR_MIBS);
2642 #ifdef _WIN32
2643 strcat(szBuffer, "\\");
2644 #else
2645 strcat(szBuffer, "/");
2646 #endif
2647 strcat(szBuffer, szMIB);
2648 pFile = LoadFile(szBuffer, &dwFileSize);
2649 if (pFile != NULL)
2650 {
2651 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2652 msg.SetVariable(VID_MIB_FILE_SIZE, dwFileSize);
2653 msg.SetVariable(VID_MIB_FILE, pFile, dwFileSize);
2654 free(pFile);
2655 }
2656 else
2657 {
2658 msg.SetVariable(VID_RCC, RCC_SYSTEM_FAILURE);
2659 }
2660
2661 // Send responce
2662 SendMessage(&msg);
2663 }
2664
2665
2666 //
2667 // Create new object
2668 //
2669
2670 void ClientSession::CreateObject(CSCPMessage *pRequest)
2671 {
2672 CSCPMessage msg;
2673 NetObj *pObject, *pParent;
2674 int iClass, iServiceType;
2675 TCHAR *pDescription, szObjectName[MAX_OBJECT_NAME];
2676 TCHAR *pszRequest, *pszResponce;
2677 DWORD dwIpAddr;
2678 WORD wIpProto, wIpPort;
2679 BOOL bParentAlwaysValid = FALSE;
2680
2681 // Prepare responce message
2682 msg.SetCode(CMD_REQUEST_COMPLETED);
2683 msg.SetId(pRequest->GetId());
2684
2685 iClass = pRequest->GetVariableShort(VID_OBJECT_CLASS);
2686
2687 // Find parent object
2688 pParent = FindObjectById(pRequest->GetVariableLong(VID_PARENT_ID));
2689 if (iClass == OBJECT_NODE)
2690 {
2691 dwIpAddr = pRequest->GetVariableLong(VID_IP_ADDRESS);
2692 if ((pParent == NULL) && (dwIpAddr != 0))
2693 {
2694 pParent = FindSubnetForNode(dwIpAddr);
2695 bParentAlwaysValid = TRUE;
2696 }
2697 }
2698 if ((pParent != NULL) || (iClass == OBJECT_NODE))
2699 {
2700 // User should have create access to parent object
2701 if ((pParent != NULL) ?
2702 pParent->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_CREATE) :
2703 g_pEntireNet->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_CREATE))
2704 {
2705 // Parent object should be of valid type
2706 if (bParentAlwaysValid || IsValidParentClass(iClass, (pParent != NULL) ? pParent->Type() : -1))
2707 {
2708 pRequest->GetVariableStr(VID_OBJECT_NAME, szObjectName, MAX_OBJECT_NAME);
2709 if (IsValidObjectName(szObjectName))
2710 {
2711 // Create new object
2712 switch(iClass)
2713 {
2714 case OBJECT_NODE:
2715 pObject = PollNewNode(dwIpAddr, pRequest->GetVariableLong(VID_IP_NETMASK),
2716 DF_DEFAULT, szObjectName);
2717 break;
2718 case OBJECT_CONTAINER:
2719 pDescription = pRequest->GetVariableStr(VID_DESCRIPTION);
2720 pObject = new Container(szObjectName,
2721 pRequest->GetVariableLong(VID_CATEGORY),
2722 pDescription);
2723 safe_free(pDescription);
2724 NetObjInsert(pObject, TRUE);
2725 break;
2726 case OBJECT_TEMPLATEGROUP:
2727 pDescription = pRequest->GetVariableStr(VID_DESCRIPTION);
2728 pObject = new TemplateGroup(szObjectName, pDescription);
2729 safe_free(pDescription);
2730 NetObjInsert(pObject, TRUE);
2731 break;
2732 case OBJECT_TEMPLATE:
2733 pObject = new Template;
2734 pObject->SetName(szObjectName);
2735 NetObjInsert(pObject, TRUE);
2736 break;
2737 case OBJECT_NETWORKSERVICE:
2738 iServiceType = (int)pRequest->GetVariableShort(VID_SERVICE_TYPE);
2739 wIpProto = pRequest->GetVariableShort(VID_IP_PROTO);
2740 wIpPort = pRequest->GetVariableShort(VID_IP_PORT);
2741 pszRequest = pRequest->GetVariableStr(VID_SERVICE_REQUEST);
2742 pszResponce = pRequest->GetVariableStr(VID_SERVICE_RESPONCE);
2743 pObject = new NetworkService(iServiceType, wIpProto, wIpPort,
2744 pszRequest, pszResponce, (Node *)pParent);
2745 pObject->SetName(szObjectName);
2746 NetObjInsert(pObject, TRUE);
2747 break;
2748 }
2749
2750 // If creation was successful do binding
2751 if (pObject != NULL)
2752 {
2753 if (pParent != NULL) // parent can be NULL for nodes
2754 {
2755 pParent->AddChild(pObject);
2756 pObject->AddParent(pParent);
2757 pParent->CalculateCompoundStatus();
2758 }
2759 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2760 msg.SetVariable(VID_OBJECT_ID, pObject->Id());
2761 }
2762 else
2763 {
2764 msg.SetVariable(VID_RCC, RCC_OBJECT_CREATION_FAILED);
2765 }
2766 }
2767 else
2768 {
2769 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_NAME);
2770 }
2771 }
2772 else
2773 {
2774 msg.SetVariable(VID_RCC, RCC_INCOMPATIBLE_OPERATION);
2775 }
2776 }
2777 else
2778 {
2779 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2780 }
2781 }
2782 else
2783 {
2784 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
2785 }
2786
2787 // Send responce
2788 SendMessage(&msg);
2789 }
2790
2791
2792 //
2793 // Bind/unbind object
2794 //
2795
2796 void ClientSession::ChangeObjectBinding(CSCPMessage *pRequest, BOOL bBind)
2797 {
2798 CSCPMessage msg;
2799 NetObj *pParent, *pChild;
2800
2801 // Prepare responce message
2802 msg.SetCode(CMD_REQUEST_COMPLETED);
2803 msg.SetId(pRequest->GetId());
2804
2805 // Get parent and child objects
2806 pParent = FindObjectById(pRequest->GetVariableLong(VID_PARENT_ID));
2807 pChild = FindObjectById(pRequest->GetVariableLong(VID_CHILD_ID));
2808
2809 // Check access rights and change binding
2810 if ((pParent != NULL) && (pChild != NULL))
2811 {
2812 // User should have modify access to both objects
2813 if ((pParent->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_MODIFY)) &&
2814 (pChild->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_MODIFY)))
2815 {
2816 // Parent object should be container or service root
2817 if ((pParent->Type() == OBJECT_CONTAINER) ||
2818 (pParent->Type() == OBJECT_SERVICEROOT))
2819 {
2820 if (bBind)
2821 {
2822 // Prevent loops
2823 if (!pChild->IsChild(pParent->Id()))
2824 {
2825 pParent->AddChild(pChild);
2826 pChild->AddParent(pParent);
2827 pParent->CalculateCompoundStatus();
2828 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2829 }
2830 else
2831 {
2832 msg.SetVariable(VID_RCC, RCC_OBJECT_LOOP);
2833 }
2834 }
2835 else
2836 {
2837 pParent->DeleteChild(pChild);
2838 pChild->DeleteParent(pParent);
2839 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2840 }
2841 }
2842 else
2843 {
2844 msg.SetVariable(VID_RCC, RCC_INCOMPATIBLE_OPERATION);
2845 }
2846 }
2847 else
2848 {
2849 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2850 }
2851 }
2852 else
2853 {
2854 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
2855 }
2856
2857 // Send responce
2858 SendMessage(&msg);
2859 }
2860
2861
2862 //
2863 // Delete object
2864 //
2865
2866 void ClientSession::DeleteObject(CSCPMessage *pRequest)
2867 {
2868 CSCPMessage msg;
2869 NetObj *pObject;
2870
2871 // Prepare responce message
2872 msg.SetCode(CMD_REQUEST_COMPLETED);
2873 msg.SetId(pRequest->GetId());
2874
2875 // Find object to be deleted
2876 pObject = FindObjectById(pRequest->GetVariableLong(VID_OBJECT_ID));
2877 if (pObject != NULL)
2878 {
2879 // Check if it is a built-in object, like "Entire Network"
2880 if (pObject->Id() >= 10)
2881 {
2882 // Check access rights
2883 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_DELETE))
2884 {
2885 pObject->Delete(FALSE);
2886 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2887 }
2888 else
2889 {
2890 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2891 }
2892 }
2893 else
2894 {
2895 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2896 }
2897 }
2898 else
2899 {
2900 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
2901 }
2902
2903 // Send responce
2904 SendMessage(&msg);
2905 }
2906
2907
2908 //
2909 // Process changes in alarms
2910 //
2911
2912 void ClientSession::OnAlarmUpdate(DWORD dwCode, NXC_ALARM *pAlarm)
2913 {
2914 UPDATE_INFO *pUpdate;
2915 NetObj *pObject;
2916
2917 if (IsAuthenticated())
2918 {
2919 pObject = FindObjectById(pAlarm->dwSourceObject);
2920 if (pObject != NULL)
2921 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_READ_ALARMS))
2922 {
2923 pUpdate = (UPDATE_INFO *)malloc(sizeof(UPDATE_INFO));
2924 pUpdate->dwCategory = INFO_CAT_ALARM;
2925 pUpdate->dwCode = dwCode;
2926 pUpdate->pData = nx_memdup(pAlarm, sizeof(NXC_ALARM));
2927 m_pUpdateQueue->Put(pUpdate);
2928 }
2929 }
2930 }
2931
2932
2933 //
2934 // Send all alarms to client
2935 //
2936
2937 void ClientSession::SendAllAlarms(DWORD dwRqId, BOOL bIncludeAck)
2938 {
2939 MutexLock(m_mutexSendAlarms, INFINITE);
2940 g_alarmMgr.SendAlarmsToClient(dwRqId, bIncludeAck, this);
2941 MutexUnlock(m_mutexSendAlarms);
2942 }
2943
2944
2945 //
2946 // Acknowlege alarm
2947 //
2948
2949 void ClientSession::AcknowlegeAlarm(CSCPMessage *pRequest)
2950 {
2951 CSCPMessage msg;
2952 NetObj *pObject;
2953 DWORD dwAlarmId;
2954
2955 // Prepare responce message
2956 msg.SetCode(CMD_REQUEST_COMPLETED);
2957 msg.SetId(pRequest->GetId());
2958
2959 // Get alarm id and it's source object
2960 dwAlarmId = pRequest->GetVariableLong(VID_ALARM_ID);
2961 pObject = g_alarmMgr.GetAlarmSourceObject(dwAlarmId);
2962 if (pObject != NULL)
2963 {
2964 // User should have "acknowlege alarm" right to the object
2965 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_ACK_ALARMS))
2966 {
2967 g_alarmMgr.AckById(dwAlarmId, m_dwUserId);
2968 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2969 }
2970 else
2971 {
2972 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2973 }
2974 }
2975 else
2976 {
2977 // Normally, for existing alarms pObject will not be NULL,
2978 // so we assume that alarm id is invalid
2979 msg.SetVariable(VID_RCC, RCC_INVALID_ALARM_ID);
2980 }
2981
2982 // Send responce
2983 SendMessage(&msg);
2984 }
2985
2986
2987 //
2988 // Delete alarm
2989 //
2990
2991 void ClientSession::DeleteAlarm(CSCPMessage *pRequest)
2992 {
2993 CSCPMessage msg;
2994 NetObj *pObject;
2995 DWORD dwAlarmId;
2996
2997 // Prepare responce message
2998 msg.SetCode(CMD_REQUEST_COMPLETED);
2999 msg.SetId(pRequest->GetId());
3000
3001 // Get alarm id and it's source object
3002 dwAlarmId = pRequest->GetVariableLong(VID_ALARM_ID);
3003 pObject = g_alarmMgr.GetAlarmSourceObject(dwAlarmId);
3004 if (pObject != NULL)
3005 {
3006 // User should have "acknowlege alarm" right to the object
3007 // and system right "delete alarms"
3008 if ((pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_ACK_ALARMS)) &&
3009 (m_dwSystemAccess & SYSTEM_ACCESS_DELETE_ALARMS))
3010 {
3011 g_alarmMgr.DeleteAlarm(dwAlarmId);
3012 msg.SetVariable(VID_RCC, RCC_SUCCESS);
3013 }
3014 else
3015 {
3016 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
3017 }
3018 }
3019 else
3020 {
3021 // Normally, for existing alarms pObject will not be NULL,
3022 // so we assume that alarm id is invalid
3023 msg.SetVariable(VID_RCC, RCC_INVALID_ALARM_ID);
3024 }
3025
3026 // Send responce
3027 SendMessage(&msg);
3028 }
3029
3030
3031 //
3032 // Lock/unlock action configuration database
3033 //
3034
3035 void ClientSession::LockActionDB(DWORD dwRqId, BOOL bLock)
3036 {
3037 CSCPMessage msg;
3038 char szBuffer[256];
3039
3040 // Prepare responce message
3041 msg.SetCode(CMD_REQUEST_COMPLETED);
3042 msg.SetId(dwRqId);
3043
3044 if (m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_ACTIONS)
3045 {
3046 if (bLock)
3047 {
3048 if (!LockComponent(CID_ACTION_DB, m_dwIndex, m_szUserName, NULL, szBuffer))
3049 {
3050 msg.SetVariable(VID_RCC, RCC_COMPONENT_LOCKED);
3051 msg.SetVariable(VID_LOCKED_BY, szBuffer);
3052 }
3053 else
3054 {
3055 m_dwFlags |= CSF_ACTION_DB_LOCKED;
3056 msg.SetVariable(VID_RCC, RCC_SUCCESS);
3057 }
3058 }
3059 else
3060 {
3061 if (m_dwFlags & CSF_ACTION_DB_LOCKED)
3062 {
3063 UnlockComponent(CID_ACTION_DB);
3064 m_dwFlags &= ~CSF_ACTION_DB_LOCKED;
3065 }
3066 msg.SetVariable(VID_RCC, RCC_SUCCESS);
3067 }
3068 }
3069 else
3070 {
3071 // Current user has no rights for action management
3072 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
3073 }
3074
3075 // Send responce
3076 SendMessage(&msg);
3077 }
3078
3079
3080 //
3081 // Create new action
3082 //
3083
3084 void ClientSession::CreateAction(CSCPMessage *pRequest)
3085 {
3086 CSCPMessage msg;
3087
3088 // Prepare responce message
3089 msg.SetCode(CMD_REQUEST_COMPLETED);
3090 msg.SetId(pRequest->GetId());
3091
3092 // Check user rights
3093 if (!(m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_ACTIONS))
3094 {
3095 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
3096 }
3097 else if (!(m_dwFlags & CSF_ACTION_DB_LOCKED))
3098 {
3099 // Action database have to be locked before any
3100 // changes can be made
3101 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
3102 }
3103 else
3104 {
3105 DWORD dwResult, dwActionId;
3106 char szActionName[MAX_USER_NAME];
3107
3108 pRequest->GetVariableStr(VID_ACTION_NAME, szActionName, MAX_OBJECT_NAME);
3109 if (IsValidObjectName(szActionName))
3110 {
3111 dwResult = CreateNewAction(szActionName, &dwActionId);
3112 msg.SetVariable(VID_RCC, dwResult);
3113 if (dwResult == RCC_SUCCESS)
3114 msg.SetVariable(VID_ACTION_ID, dwActionId); // Send id of new action to client
3115 }
3116 else
3117 {
3118 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_NAME);
3119 }
3120 }
3121
3122 // Send responce
3123 SendMessage(&msg);
3124 }
3125
3126
3127 //
3128 // Update existing action's data
3129 //
3130
3131 void ClientSession::UpdateAction(CSCPMessage *pRequest)
3132 {
3133 CSCPMessage msg;
3134
3135 // Prepare responce message
3136 msg.SetCode(CMD_REQUEST_COMPLETED);
3137 msg.SetId(pRequest->GetId());
3138
3139 // Check user rights
3140 if (!(m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_ACTIONS))
3141 {
3142 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
3143 }
3144 else if (!(m_dwFlags & CSF_ACTION_DB_LOCKED))
3145 {
3146 // Action database have to be locked before any
3147 // changes can be made
3148 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
3149 }
3150 else
3151 {
3152 msg.SetVariable(VID_RCC, ModifyActionFromMessage(pRequest));
3153 }
3154
3155 // Send responce
3156 SendMessage(&msg);
3157 }
3158
3159
3160 //
3161 // Delete action
3162 //
3163
3164 void ClientSession::DeleteAction(CSCPMessage *pRequest)
3165 {
3166 CSCPMessage msg;
3167 DWORD dwActionId;
3168
3169 // Prepare responce message
3170 msg.SetCode(CMD_REQUEST_COMPLETED);
3171 msg.SetId(pRequest->GetId());
3172
3173 // Check user rights
3174 if (!(m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_ACTIONS))
3175 {
3176 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
3177 }
3178 else if (!(m_dwFlags & CSF_ACTION_DB_LOCKED))
3179 {
3180 // Action database have to be locked before any
3181 // changes can be made
3182 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
3183 }
3184 else
3185 {
3186 // Get Id of action to be deleted
3187 dwActionId = pRequest->GetVariableLong(VID_ACTION_ID);
3188 if (!g_pEventPolicy->ActionInUse(dwActionId))
3189 {
3190 msg.SetVariable(VID_RCC, DeleteActionFromDB(dwActionId));
3191 }
3192 else
3193 {
3194 msg.SetVariable(VID_RCC, RCC_ACTION_IN_USE);
3195 }
3196 }
3197
3198 // Send responce
3199 SendMessage(&msg);
3200 }
3201
3202
3203 //
3204 // Process changes in actions
3205 //
3206
3207 void ClientSession::OnActionDBUpdate(DWORD dwCode, NXC_ACTION *pAction)
3208 {
3209 UPDATE_INFO *pUpdate;
3210
3211 if (IsAuthenticated())
3212 {
3213 if (m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_ACTIONS)
3214 {
3215 pUpdate = (UPDATE_INFO *)malloc(sizeof(UPDATE_INFO));
3216 pUpdate->dwCategory = INFO_CAT_ACTION;
3217 pUpdate->dwCode = dwCode;
3218 pUpdate->pData = nx_memdup(pAction, sizeof(NXC_ACTION));
3219 m_pUpdateQueue->Put(pUpdate);
3220 }
3221 }
3222 }
3223
3224
3225 //
3226 // Send all actions to client
3227 //
3228
3229 void ClientSession::SendAllActions(DWORD dwRqId)
3230 {
3231 CSCPMessage msg;
3232
3233 // Prepare responce message
3234 msg.SetCode(CMD_REQUEST_COMPLETED);
3235 msg.SetId(dwRqId);
3236
3237 // Check user rights
3238 if ((m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_ACTIONS) ||
3239 (m_dwSystemAccess & SYSTEM_ACCESS_EPP))
3240 {
3241 msg.SetVariable(VID_RCC, RCC_SUCCESS);
3242 SendMessage(&msg);
3243 MutexLock(m_mutexSendActions, INFINITE);
3244 SendActionsToClient(this, dwRqId);
3245 MutexUnlock(m_mutexSendActions);
3246 }
3247 else
3248 {
3249 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
3250 SendMessage(&msg);
3251 }
3252 }
3253
3254
3255 //
3256 // Send list of configured container categories to client
3257 //
3258
3259 void ClientSession::SendContainerCategories(DWORD dwRqId)
3260 {
3261 CSCPMessage msg;
3262 DWORD i;
3263
3264 // Prepare responce message
3265 msg.SetCode(CMD_CONTAINER_CAT_DATA);
3266 msg.SetId(dwRqId);
3267
3268 for(i = 0; i < g_dwNumCategories; i++)
3269 {
3270 msg.SetVariable(VID_CATEGORY_ID, g_pContainerCatList[i].dwCatId);
3271 msg.SetVariable(VID_CATEGORY_NAME, g_pContainerCatList[i].szName);
3272 msg.SetVariable(VID_IMAGE_ID, g_pContainerCatList[i].dwImageId);
3273 msg.SetVariable(VID_DESCRIPTION, g_pContainerCatList[i].pszDescription);
3274 SendMessage(&msg);
3275 msg.DeleteAllVariables();
3276 }
3277
3278 // Send end-of-list indicator
3279 msg.SetVariable(VID_CATEGORY_ID, (DWORD)0);
3280 SendMessage(&msg);
3281 }
3282
3283
3284 //
3285 // Perform a forced node poll
3286 //
3287
3288 void ClientSession::ForcedNodePoll(CSCPMessage *pRequest)
3289 {
3290 CSCPMessage msg;
3291 POLLER_START_DATA *pData;
3292 NetObj *pObject;
3293
3294 pData = (POLLER_START_DATA *)malloc(sizeof(POLLER_START_DATA));
3295 pData->pSession = this;
3296 MutexLock(m_mutexPollerInit, INFINITE);
3297
3298 // Prepare responce message
3299 pData->dwRqId = pRequest->GetId();
3300 msg.SetCode(CMD_POLLING_INFO);
3301 msg.SetId(pData->dwRqId);
3302
3303 // Get polling type
3304 pData->iPollType = pRequest->GetVariableShort(VID_POLL_TYPE);
3305
3306 // Find object to be deleted
3307 pObject = FindObjectById(pRequest->GetVariableLong(VID_OBJECT_ID));
3308 if (pObject != NULL)
3309 {
3310 // We can do polls only for node objects
3311 if ((pObject->Type() == OBJECT_NODE) &&
3312 ((pData->iPollType == POLL_STATUS) || (pData->iPollType == POLL_CONFIGURATION)))
3313 {
3314 // Check access rights
3315 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_MODIFY))
3316 {
3317 ((Node *)pObject)->IncRefCount();
3318 m_dwRefCount++;
3319
3320 pData->pNode = (Node *)pObject;
3321 ThreadCreate(PollerThreadStarter, 0, pData);
3322 msg.SetVariable(VID_RCC, RCC_OPERATION_IN_PROGRESS);
3323 msg.SetVariable(VID_POLLER_MESSAGE, _T("Poll request accepted\r\n"));
3324 }
3325 else
3326 {
3327 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
3328 }
3329 }
3330 else
3331 {
3332 msg.SetVariable(VID_RCC, RCC_INCOMPATIBLE_OPERATION);
3333 }
3334 }
3335 else
3336 {
3337 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
3338 }
3339
3340 // Send responce
3341 SendMessage(&msg);
3342 MutexUnlock(m_mutexPollerInit);
3343 }
3344
3345
3346 //
3347 // Send message fro poller to client
3348 //
3349
3350 void ClientSession::SendPollerMsg(DWORD dwRqId, TCHAR *pszMsg)
3351 {
3352 CSCPMessage msg;
3353
3354 msg.SetCode(CMD_POLLING_INFO);
3355 msg.SetId(dwRqId);
3356 msg.SetVariable(VID_RCC, RCC_OPERATION_IN_PROGRESS);
3357 msg.SetVariable(VID_POLLER_MESSAGE, pszMsg);
3358 SendMessage(&msg);
3359 }
3360
3361
3362 //
3363 // Node poller thread
3364 //
3365
3366 void ClientSession::PollerThread(Node *pNode, int iPollType, DWORD dwRqId)
3367 {
3368 CSCPMessage msg;
3369
3370 // Wait while parent thread finishes initialization
3371 MutexLock(m_mutexPollerInit, INFINITE);
3372 MutexUnlock(m_mutexPollerInit);
3373
3374 switch(iPollType)
3375 {
3376 case POLL_STATUS:
3377 pNode->StatusPoll(this, dwRqId);
3378 break;
3379 case POLL_CONFIGURATION:
3380 pNode->ConfigurationPoll(this, dwRqId);
3381 break;
3382 default:
3383 SendPollerMsg(dwRqId, _T("Invalid poll type requested\r\n"));
3384 break;
3385 }
3386 pNode->DecRefCount();
3387
3388 msg.SetCode(CMD_POLLING_INFO);
3389 msg.SetId(dwRqId);
3390 msg.SetVariable(VID_RCC, RCC_SUCCESS);
3391 SendMessage(&msg);
3392 }
3393
3394
3395 //
3396 // Receive event from user
3397 //
3398
3399 void ClientSession::OnTrap(CSCPMessage *pRequest)
3400 {
3401 CSCPMessage msg;
3402 DWORD dwObjectId, dwEventCode;
3403 int i, iNumArgs;
3404 NetObj *pObject;
3405 TCHAR *pszArgList[32];
3406 TCHAR szFormat[] = "ssssssssssssssssssssssssssssssss";
3407 BOOL bSuccess;
3408
3409 // Prepare responce message
3410 msg.SetCode(CMD_REQUEST_COMPLETED);
3411 msg.SetId(pRequest->GetId());
3412
3413 // Find event's source object
3414 dwObjectId = pRequest->GetVariableLong(VID_OBJECT_ID);
3415 if (dwObjectId != 0)
3416 pObject = FindObjectById(dwObjectId); // Object is specified explicitely
3417 else
3418 pObject = FindNodeByIP(m_dwHostAddr); // Client is the source
3419 if (pObject != NULL)
3420 {
3421 // User should have SEND_EVENTS access right to object
3422 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_SEND_EVENTS))
3423 {
3424 dwEventCode = pRequest->GetVariableLong(VID_EVENT_CODE);
3425 iNumArgs = pRequest->GetVariableShort(VID_NUM_ARGS);
3426 for(i = 0; i < iNumArgs; i++)
3427 pszArgList[i] = pRequest->GetVariableStr(VID_EVENT_ARG_BASE + i);
3428
3429 // Following call is not very good, but I'm too lazy now
3430 // to change PostEvent()
3431 szFormat[iNumArgs] = 0;
3432 bSuccess = PostEvent(dwEventCode, pObject->Id(), (iNumArgs > 0) ? szFormat : NULL,
3433 pszArgList[0], pszArgList[1], pszArgList[2], pszArgList[3],
3434 pszArgList[4], pszArgList[5], pszArgList[6], pszArgList[7],
3435 pszArgList[8], pszArgList[9], pszArgList[10], pszArgList[11],
3436 pszArgList[12], pszArgList[13], pszArgList[14], pszArgList[15],
3437 pszArgList[16], pszArgList[17], pszArgList[18], pszArgList[19],
3438 pszArgList[20], pszArgList[21], pszArgList[22], pszArgList[23],
3439 pszArgList[24], pszArgList[25], pszArgList[26], pszArgList[27],
3440 pszArgList[28], pszArgList[29], pszArgList[30], pszArgList[31]);
3441
3442 // Cleanup
3443 for(i = 0; i < iNumArgs; i++)
3444 free(pszArgList[i]);
3445
3446 msg.SetVariable(VID_RCC, bSuccess ? RCC_SUCCESS : RCC_INVALID_EVENT_CODE);
3447 }
3448 else
3449 {
3450 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
3451 }
3452 }
3453 else
3454 {
3455 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
3456 }
3457
3458 // Send responce
3459 SendMessage(&msg);
3460 }
3461
3462
3463 //
3464 // Wake up node
3465 //
3466
3467 void ClientSession::OnWakeUpNode(CSCPMessage *pRequest)
3468 {
3469 NetObj *pObject;
3470 CSCPMessage msg;
3471
3472 // Prepare responce message
3473 msg.SetCode(CMD_REQUEST_COMPLETED);
3474 msg.SetId(pRequest->GetId());
3475
3476 // Find node or interface object
3477 pObject = FindObjectById(pRequest->GetVariableLong(VID_OBJECT_ID));
3478 if (pObject != NULL)
3479 {
3480 if ((pObject->Type() == OBJECT_NODE) ||
3481 (pObject->Type() == OBJECT_INTERFACE))
3482 {
3483 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_READ))
3484 {
3485 DWORD dwResult;
3486
3487 if (pObject->Type() == OBJECT_NODE)
3488 dwResult = ((Node *)pObject)->WakeUp();
3489 else
3490 dwResult = ((Interface *)pObject)->WakeUp();
3491 msg.SetVariable(VID_RCC, dwResult);
3492 }
3493 else
3494 {
3495 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
3496 }
3497 }
3498 else
3499 {
3500 msg.SetVariable(VID_RCC, RCC_INCOMPATIBLE_OPERATION);
3501 }
3502 }
3503 else
3504 {
3505 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
3506 }
3507
3508 // Send responce
3509 SendMessage(&msg);
3510 }
3511
3512
3513 //
3514 // Query specific parameter from node
3515 //
3516
3517 void ClientSession::QueryParameter(CSCPMessage *pRequest)
3518 {
3519 NetObj *pObject;
3520 CSCPMessage msg;
3521
3522 // Prepare responce message
3523 msg.SetCode(CMD_REQUEST_COMPLETED);
3524 msg.SetId(pRequest->GetId());
3525
3526 // Find node object
3527 pObject = FindObjectById(pRequest->GetVariableLong(VID_OBJECT_ID));
3528 if (pObject != NULL)
3529 {
3530 if (pObject->Type() == OBJECT_NODE)
3531 {
3532 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_READ))
3533 {
3534 DWORD dwResult;
3535 TCHAR szBuffer[256], szName[MAX_PARAM_NAME];
3536
3537 pRequest->GetVariableStr(VID_NAME, szName, MAX_PARAM_NAME);
3538 dwResult = ((Node *)pObject)->GetItemForClient(pRequest->GetVariableShort(VID_DCI_SOURCE_TYPE),
3539 szName, szBuffer, 256);
3540 msg.SetVariable(VID_RCC, dwResult);
3541 if (dwResult == RCC_SUCCESS)
3542 msg.SetVariable(VID_VALUE, szBuffer);
3543 }
3544 else
3545 {
3546 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
3547 }
3548 }
3549 else
3550 {
3551 msg.SetVariable(VID_RCC, RCC_INCOMPATIBLE_OPERATION);
3552 }
3553 }
3554 else
3555 {
3556 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
3557 }
3558
3559 // Send responce
3560 SendMessage(&msg);
3561 }
3562
3563
3564 //
3565 // Edit trap configuration record
3566 //
3567
3568 void ClientSession::EditTrap(int iOperation, CSCPMessage *pRequest)
3569 {
3570 CSCPMessage msg;
3571 DWORD dwTrapId, dwResult;
3572
3573 // Prepare responce message
3574 msg.SetCode(CMD_REQUEST_COMPLETED);
3575 msg.SetId(pRequest->GetId());
3576
3577 // Check access rights
3578 if (m_dwSystemAccess & SYSTEM_ACCESS_CONFIGURE_TRAPS)
3579 {
3580 if (m_dwFlags & CSF_TRAP_CFG_LOCKED)
3581 {
3582 switch(iOperation)
3583 {
3584 case TRAP_CREATE:
3585 dwResult = CreateNewTrap(&dwTrapId);
3586 msg.SetVariable(VID_RCC, dwResult);
3587 if (dwResult == RCC_SUCCESS)
3588 msg.SetVariable(VID_TRAP_ID, dwTrapId); // Send id of new trap to client
3589 break;
3590 case TRAP_UPDATE:
3591 msg.SetVariable(VID_RCC, UpdateTrapFromMsg(pRequest));
3592 break;
3593 case TRAP_DELETE:
3594 dwTrapId = pRequest->GetVariableLong(VID_TRAP_ID);
3595 msg.SetVariable(VID_RCC, DeleteTrap(dwTrapId));
3596 break;
3597 default:
3598 msg.SetVariable(VID_RCC, RCC_SYSTEM_FAILURE);
3599 break;
3600 }
3601 }
3602 else
3603 {
3604 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
3605 }
3606 }
3607 else
3608 {
3609 // Current user has no rights for trap management
3610 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
3611 }
3612
3613 // Send responce
3614 SendMessage(&msg);
3615 }
3616
3617
3618 //
3619 // Lock/unlock trap configuration
3620 //
3621
3622 void ClientSession::LockTrapCfg(DWORD dwRqId, BOOL bLock)
3623 {
3624 CSCPMessage msg;
3625 char szBuffer[256];
3626
3627 // Prepare responce message
3628 msg.SetCode(CMD_REQUEST_COMPLETED);
3629 msg.SetId(dwRqId);
3630
3631 if (m_dwSystemAccess & SYSTEM_ACCESS_CONFIGURE_TRAPS)
3632 {
3633 if (bLock)
3634 {
3635 if (!LockComponent(CID_TRAP_CFG, m_dwIndex, m_szUserName, NULL, szBuffer))
3636 {
3637 msg.SetVariable(VID_RCC, RCC_COMPONENT_LOCKED);
3638 msg.SetVariable(VID_LOCKED_BY, szBuffer);
3639 }
3640 else
3641 {
3642 m_dwFlags |= CSF_TRAP_CFG_LOCKED;
3643 msg.SetVariable(VID_RCC, RCC_SUCCESS);
3644 }
3645 }
3646 else
3647 {
3648 if (m_dwFlags & CSF_TRAP_CFG_LOCKED)
3649 {
3650 UnlockComponent(CID_TRAP_CFG);
3651 m_dwFlags &= ~CSF_TRAP_CFG_LOCKED;
3652 }
3653 msg.SetVariable(VID_RCC, RCC_SUCCESS);
3654 }
3655 }
3656 else
3657 {
3658 // Current user has no rights for trap management
3659 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
3660 }
3661
3662 // Send responce
3663 SendMessage(&msg);
3664 }
3665
3666
3667 //
3668 // Send all trap configuration records to client
3669 //
3670
3671 void ClientSession::SendAllTraps(DWORD dwRqId)
3672 {
3673 CSCPMessage msg;
3674 BOOL bSuccess = FALSE;
3675
3676 // Prepare responce message
3677 msg.SetCode(CMD_REQUEST_COMPLETED);
3678 msg.SetId(dwRqId);
3679
3680 if (m_dwSystemAccess & SYSTEM_ACCESS_CONFIGURE_TRAPS)
3681 {
3682 if (m_dwFlags & CSF_TRAP_CFG_LOCKED)
3683 {
3684 msg.SetVariable(VID_RCC, RCC_SUCCESS);
3685 SendMessage(&msg);
3686 bSuccess = TRUE;
3687 SendTrapsToClient(this, dwRqId);
3688 }
3689 else
3690 {
3691 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
3692 }
3693 }
3694 else
3695 {
3696 // Current user has no rights for trap management
3697 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
3698 }
3699
3700 // Send responce
3701 if (!bSuccess)
3702 SendMessage(&msg);
3703 }
3704
3705
3706 //
3707 // Lock/unlock package database
3708 //
3709
3710 void ClientSession::LockPackageDB(DWORD dwRqId, BOOL bLock)
3711 {
3712 CSCPMessage msg;
3713 char szBuffer[256];
3714
3715 // Prepare responce message
3716 msg.SetCode(CMD_REQUEST_COMPLETED);
3717 msg.SetId(dwRqId);
3718
3719 if (m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_PACKAGES)
3720 {
3721 if (bLock)
3722 {
3723 if (!LockComponent(CID_PACKAGE_DB, m_dwIndex, m_szUserName, NULL, szBuffer))
3724 {
3725 msg.SetVariable(VID_RCC, RCC_COMPONENT_LOCKED);
3726 msg.SetVariable(VID_LOCKED_BY, szBuffer);
3727 }
3728 else
3729 {
3730 m_dwFlags |= CSF_PACKAGE_DB_LOCKED;
3731 msg.SetVariable(VID_RCC, RCC_SUCCESS);
3732 }
3733 }
3734 else
3735 {
3736 if (m_dwFlags & CSF_PACKAGE_DB_LOCKED)
3737 {
3738 UnlockComponent(CID_PACKAGE_DB);
3739 m_dwFlags &= ~CSF_PACKAGE_DB_LOCKED;
3740 }
3741 msg.SetVariable(VID_RCC, RCC_SUCCESS);
3742 }
3743 }
3744 else
3745 {
3746 // Current user has no rights for trap management
3747 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
3748 }
3749
3750 // Send responce
3751 SendMessage(&msg);
3752 }
3753
3754
3755 //
3756 // Send list of all installed packages to client
3757 //
3758
3759 void ClientSession::SendAllPackages(DWORD dwRqId)
3760 {
3761 CSCPMessage msg;
3762 DB_ASYNC_RESULT hResult;
3763 BOOL bSuccess = FALSE;
3764 TCHAR szBuffer[MAX_DB_STRING];
3765
3766 // Prepare responce message
3767 msg.SetCode(CMD_REQUEST_COMPLETED);
3768 msg.SetId(dwRqId);
3769
3770 if (m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_PACKAGES)
3771 {
3772 if (m_dwFlags & CSF_PACKAGE_DB_LOCKED)
3773 {
3774 hResult = DBAsyncSelect(g_hCoreDB, "SELECT pkg_id,version,platform,pkg_file,pkg_name,description FROM agent_pkg");
3775 if (hResult != NULL)
3776 {
3777 msg.SetVariable(VID_RCC, RCC_SUCCESS);
3778 SendMessage(&msg);
3779 bSuccess = TRUE;
3780
3781 msg.SetCode(CMD_PACKAGE_INFO);
3782 msg.DeleteAllVariables();
3783
3784 while(DBFetch(hResult))
3785 {
3786 msg.SetVariable(VID_PACKAGE_ID, DBGetFieldAsyncULong(hResult, 0));
3787 msg.SetVariable(VID_PACKAGE_VERSION, DBGetFieldAsync(hResult, 1, szBuffer, MAX_DB_STRING));
3788 msg.SetVariable(VID_PLATFORM_NAME, DBGetFieldAsync(hResult, 2, szBuffer, MAX_DB_STRING));
3789 msg.SetVariable(VID_FILE_NAME, DBGetFieldAsync(hResult, 3, szBuffer, MAX_DB_STRING));
3790 msg.SetVariable(VID_PACKAGE_NAME, DBGetFieldAsync(hResult, 4, szBuffer, MAX_DB_STRING));
3791 DBGetFieldAsync(hResult, 5, szBuffer, MAX_DB_STRING);
3792 DecodeSQLString(szBuffer);
3793 msg.SetVariable(VID_DESCRIPTION, szBuffer);
3794 SendMessage(&msg);
3795 msg.DeleteAllVariables();
3796 }
3797
3798 msg.SetVariable(VID_PACKAGE_ID, (DWORD)0);
3799 SendMessage(&msg);
3800
3801 DBFreeAsyncResult(hResult);
3802 }
3803 else
3804 {
3805 msg.SetVariable(VID_RCC, RCC_DB_FAILURE);
3806 }
3807 }
3808 else
3809 {
3810 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
3811 }
3812 }
3813 else
3814 {
3815 // Current user has no rights for package management
3816 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
3817 }
3818
3819 // Send responce
3820 if (!bSuccess)
3821 SendMessage(&msg);
3822 }
3823
3824
3825 //
3826 // Install package to server
3827 //
3828
3829 void ClientSession::InstallPackage(CSCPMessage *pRequest)
3830 {
3831 CSCPMessage msg;
3832 TCHAR szPkgName[MAX_PACKAGE_NAME_LEN], szDescription[MAX_DB_STRING];
3833 TCHAR szPkgVersion[MAX_AGENT_VERSION_LEN], szFileName[MAX_DB_STRING];
3834 TCHAR szPlatform[MAX_PLATFORM_NAME_LEN], *pszCleanFileName, *pszEscDescr;
3835 TCHAR szQuery[2048];
3836
3837 // Prepare responce message
3838 msg.SetCode(CMD_REQUEST_COMPLETED);
3839 msg.SetId(pRequest->GetId());
3840
3841 if (m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_PACKAGES)
3842 {
3843 if (m_dwFlags & CSF_PACKAGE_DB_LOCKED)
3844 {
3845 pRequest->GetVariableStr(VID_PACKAGE_NAME, szPkgName, MAX_PACKAGE_NAME_LEN);
3846 pRequest->GetVariableStr(VID_DESCRIPTION, szDescription, MAX_DB_STRING);
3847 pRequest->GetVariableStr(VID_FILE_NAME, szFileName, MAX_DB_STRING);
3848 pRequest->GetVariableStr(VID_PACKAGE_VERSION, szPkgVersion, MAX_AGENT_VERSION_LEN);
3849 pRequest->GetVariableStr(VID_PLATFORM_NAME, szPlatform, MAX_PLATFORM_NAME_LEN);
3850
3851 // Remove possible path specification from file name
3852 pszCleanFileName = GetCleanFileName(szFileName);
3853
3854 if (IsValidObjectName(pszCleanFileName) &&
3855 IsValidObjectName(szPkgName) &&
3856 IsValidObjectName(szPkgVersion) &&
3857 IsValidObjectName(szPlatform))
3858 {
3859 // Check if same package already exist
3860 if (!IsPackageInstalled(szPkgName, szPkgVersion, szPlatform))
3861 {
3862 // Check for duplicate file name
3863 if (!IsPackageFileExist(pszCleanFileName))
3864 {
3865 // Prepare for file receive
3866 if (m_hCurrFile == -1)
3867 {
3868 _tcscpy(m_szCurrFileName, g_szDataDir);
3869 _tcscat(m_szCurrFileName, DDIR_PACKAGES);
3870 _tcscat(m_szCurrFileName, FS_PATH_SEPARATOR);
3871 _tcscat(m_szCurrFileName, pszCleanFileName);
3872 m_hCurrFile = _topen(m_szCurrFileName, O_CREAT | O_TRUNC | O_WRONLY | O_BINARY, S_IRUSR | S_IWUSR);
3873 if (m_hCurrFile != -1)
3874 {
3875 m_dwFileRqId = pRequest->GetId();
3876 m_dwUploadCommand = CMD_INSTALL_PACKAGE;
3877 m_dwUploadData = CreateUniqueId(IDG_PACKAGE);
3878 msg.SetVariable(VID_RCC, RCC_SUCCESS);
3879 msg.SetVariable(VID_PACKAGE_ID, m_dwUploadData);
3880
3881 // Create record in database
3882 pszEscDescr = EncodeSQLString(szDescription);
3883 _sntprintf(szQuery, 2048, _T("INSERT INTO agent_pkg (pkg_id,pkg_name,"
3884 "version,description,platform,pkg_file) "
3885 "VALUES (%ld,'%s','%s','%s','%s','%s')"),
3886 m_dwUploadData, szPkgName, szPkgVersion, pszEscDescr,
3887 szPlatform, pszCleanFileName);
3888 free(pszEscDescr);
3889 DBQuery(g_hCoreDB, szQuery);
3890 }
3891 else
3892 {
3893 msg.SetVariable(VID_RCC, RCC_IO_ERROR);
3894 }
3895 }
3896 else
3897 {
3898 msg.SetVariable(VID_RCC, RCC_RESOURCE_BUSY);
3899 }
3900 }
3901 else
3902 {
3903 msg.SetVariable(VID_RCC, RCC_PACKAGE_FILE_EXIST);
3904 }
3905 }
3906 else
3907 {
3908 msg.SetVariable(VID_RCC, RCC_DUPLICATE_PACKAGE);
3909 }
3910 }
3911 else
3912 {
3913 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_NAME);
3914 }
3915 }
3916 else
3917 {
3918 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
3919 }
3920 }
3921 else
3922 {
3923 // Current user has no rights for package management
3924 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
3925 }
3926
3927 // Send responce
3928 SendMessage(&msg);
3929 }
3930
3931
3932 //
3933 // Remove package from server
3934 //
3935
3936 void ClientSession::RemovePackage(CSCPMessage *pRequest)
3937 {
3938 CSCPMessage msg;
3939 DWORD dwPkgId;
3940
3941 // Prepare responce message
3942 msg.SetCode(CMD_REQUEST_COMPLETED);
3943 msg.SetId(pRequest->GetId());
3944
3945 if (m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_PACKAGES)
3946 {
3947 if (m_dwFlags & CSF_PACKAGE_DB_LOCKED)
3948 {