2 ** NetXMS - Network Management System
3 ** Copyright (C) 2003-2014 Raden Solutions
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.
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.
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.
24 #include <netxms_mt.h>
35 #define min(a,b) ((a) < (b) ? (a) : (b))
39 #define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
42 // WARNING! this hack works only for d2i_X509(); be carefull when adding new code
46 #if OPENSSL_VERSION_NUMBER >= 0x0090800fL
47 # define OPENSSL_CONST const
49 # define OPENSSL_CONST
59 #define MAX_MSG_SIZE 4194304
64 extern Queue g_statusPollQueue
;
65 extern Queue g_configPollQueue
;
66 extern Queue g_routePollQueue
;
67 extern Queue g_discoveryPollQueue
;
68 extern Queue g_nodePollerQueue
;
69 extern Queue g_conditionPollerQueue
;
70 extern Queue
*g_pItemQueue
;
72 void UnregisterClientSession(UINT32 dwIndex
);
73 void ResetDiscoveryPoller();
74 CSCPMessage
*ForwardMessageToReportingServer(CSCPMessage
*request
, ClientSession
*session
);
75 void RemovePendingFileTransferRequests(ClientSession
*session
);
78 * Node poller start data
82 ClientSession
*pSession
;
89 * Additional processing thread start data
93 ClientSession
*pSession
;
95 } PROCTHREAD_START_DATA
;
98 * Object tool acl entry
113 } LIBRARY_IMAGE_UPDATE_INFO
;
116 * Callback to delete agent connections for loading files in distructor
118 static void DeleteCallback(NetObj
* obj
, void *data
)
120 delete (AgentConnection
*)obj
;
124 * Additional message processing thread starters
126 #define CALL_IN_NEW_THREAD(func, msg) \
128 PROCTHREAD_START_DATA *pData = (PROCTHREAD_START_DATA *)malloc(sizeof(PROCTHREAD_START_DATA)); \
129 pData->pSession = this; \
131 msg = NULL; /* prevent deletion by main processing thread*/ \
133 ThreadCreate(ThreadStarter_##func, 0, pData); \
136 #define DEFINE_THREAD_STARTER(func) \
137 THREAD_RESULT THREAD_CALL ClientSession::ThreadStarter_##func(void *pArg) \
139 ((PROCTHREAD_START_DATA *)pArg)->pSession->func(((PROCTHREAD_START_DATA *)pArg)->pMsg); \
140 ((PROCTHREAD_START_DATA *)pArg)->pSession->m_dwRefCount--; \
141 delete ((PROCTHREAD_START_DATA *)pArg)->pMsg; \
146 DEFINE_THREAD_STARTER(getCollectedData
)
147 DEFINE_THREAD_STARTER(getTableCollectedData
)
148 DEFINE_THREAD_STARTER(clearDCIData
)
149 DEFINE_THREAD_STARTER(queryL2Topology
)
150 DEFINE_THREAD_STARTER(sendEventLog
)
151 DEFINE_THREAD_STARTER(sendSyslog
)
152 DEFINE_THREAD_STARTER(createObject
)
153 DEFINE_THREAD_STARTER(getServerFile
)
154 DEFINE_THREAD_STARTER(getAgentFile
)
155 DEFINE_THREAD_STARTER(cancelFileMonitoring
)
156 DEFINE_THREAD_STARTER(queryServerLog
)
157 DEFINE_THREAD_STARTER(getServerLogQueryData
)
158 DEFINE_THREAD_STARTER(executeAction
)
159 DEFINE_THREAD_STARTER(findNodeConnection
)
160 DEFINE_THREAD_STARTER(findMacAddress
)
161 DEFINE_THREAD_STARTER(findIpAddress
)
162 DEFINE_THREAD_STARTER(processConsoleCommand
)
163 DEFINE_THREAD_STARTER(sendMib
)
164 DEFINE_THREAD_STARTER(getNetworkPath
)
165 DEFINE_THREAD_STARTER(queryParameter
)
166 DEFINE_THREAD_STARTER(queryAgentTable
)
167 DEFINE_THREAD_STARTER(getAlarmEvents
)
168 DEFINE_THREAD_STARTER(openHelpdeskIssue
)
169 DEFINE_THREAD_STARTER(forwardToReportingServer
)
170 DEFINE_THREAD_STARTER(fileManagerControl
)
171 DEFINE_THREAD_STARTER(uploadUserFileToAgent
)
172 DEFINE_THREAD_STARTER(getSwitchForwardingDatabase
)
173 DEFINE_THREAD_STARTER(getRoutingTable
)
176 * Client communication read thread starter
178 THREAD_RESULT THREAD_CALL
ClientSession::readThreadStarter(void *pArg
)
180 ((ClientSession
*)pArg
)->readThread();
182 // When ClientSession::ReadThread exits, all other session
183 // threads are already stopped, so we can safely destroy
185 UnregisterClientSession(((ClientSession
*)pArg
)->getIndex());
186 delete (ClientSession
*)pArg
;
191 * Client communication write thread starter
193 THREAD_RESULT THREAD_CALL
ClientSession::writeThreadStarter(void *pArg
)
195 ((ClientSession
*)pArg
)->writeThread();
200 * Received message processing thread starter
202 THREAD_RESULT THREAD_CALL
ClientSession::processingThreadStarter(void *pArg
)
204 ((ClientSession
*)pArg
)->processingThread();
209 * Information update processing thread starter
211 THREAD_RESULT THREAD_CALL
ClientSession::updateThreadStarter(void *pArg
)
213 ((ClientSession
*)pArg
)->updateThread();
218 * Forced node poll thread starter
220 THREAD_RESULT THREAD_CALL
ClientSession::pollerThreadStarter(void *pArg
)
222 ((POLLER_START_DATA
*)pArg
)->pSession
->pollerThread(
223 ((POLLER_START_DATA
*)pArg
)->pNode
,
224 ((POLLER_START_DATA
*)pArg
)->iPollType
,
225 ((POLLER_START_DATA
*)pArg
)->dwRqId
);
226 ((POLLER_START_DATA
*)pArg
)->pSession
->decRefCount();
232 * Client session class constructor
234 ClientSession::ClientSession(SOCKET hSocket
, struct sockaddr
*addr
)
236 m_pSendQueue
= new Queue
;
237 m_pMessageQueue
= new Queue
;
238 m_pUpdateQueue
= new Queue
;
240 m_dwIndex
= INVALID_INDEX
;
241 m_iState
= SESSION_STATE_INIT
;
242 m_pMsgBuffer
= (CSCP_BUFFER
*)malloc(sizeof(CSCP_BUFFER
));
244 m_hWriteThread
= INVALID_THREAD_HANDLE
;
245 m_hProcessingThread
= INVALID_THREAD_HANDLE
;
246 m_hUpdateThread
= INVALID_THREAD_HANDLE
;
247 m_mutexSocketWrite
= MutexCreate();
248 m_mutexSendEvents
= MutexCreate();
249 m_mutexSendSyslog
= MutexCreate();
250 m_mutexSendTrapLog
= MutexCreate();
251 m_mutexSendObjects
= MutexCreate();
252 m_mutexSendAlarms
= MutexCreate();
253 m_mutexSendActions
= MutexCreate();
254 m_mutexSendAuditLog
= MutexCreate();
255 m_mutexSendSituations
= MutexCreate();
256 m_mutexPollerInit
= MutexCreate();
258 m_clientType
= CLIENT_TYPE_DESKTOP
;
259 m_clientAddr
= (struct sockaddr
*)nx_memdup(addr
, (addr
->sa_family
== AF_INET
) ? sizeof(struct sockaddr_in
) : sizeof(struct sockaddr_in6
));
260 if (addr
->sa_family
== AF_INET
)
261 IpToStr(ntohl(((struct sockaddr_in
*)m_clientAddr
)->sin_addr
.s_addr
), m_workstation
);
264 Ip6ToStr(((struct sockaddr_in6
*)m_clientAddr
)->sin6_addr
.s6_addr
, m_workstation
);
266 m_webServerAddress
[0] = 0;
267 _tcscpy(m_szUserName
, _T("<not logged in>"));
268 _tcscpy(m_szClientInfo
, _T("n/a"));
269 m_dwUserId
= INVALID_INDEX
;
270 m_dwOpenDCIListSize
= 0;
271 m_pOpenDCIList
= NULL
;
272 m_ppEPPRuleList
= NULL
;
276 m_dwEncryptionRqId
= 0;
277 m_condEncryptionSetup
= INVALID_CONDITION_HANDLE
;
278 m_dwActiveChannels
= 0;
280 m_loginTime
= time(NULL
);
281 m_musicTypeList
.add(_T("wav"));
287 ClientSession::~ClientSession()
290 closesocket(m_hSocket
);
292 delete m_pMessageQueue
;
293 delete m_pUpdateQueue
;
294 safe_free(m_pMsgBuffer
);
295 safe_free(m_clientAddr
);
296 MutexDestroy(m_mutexSocketWrite
);
297 MutexDestroy(m_mutexSendEvents
);
298 MutexDestroy(m_mutexSendSyslog
);
299 MutexDestroy(m_mutexSendTrapLog
);
300 MutexDestroy(m_mutexSendObjects
);
301 MutexDestroy(m_mutexSendAlarms
);
302 MutexDestroy(m_mutexSendActions
);
303 MutexDestroy(m_mutexSendAuditLog
);
304 MutexDestroy(m_mutexSendSituations
);
305 MutexDestroy(m_mutexPollerInit
);
306 safe_free(m_pOpenDCIList
);
307 if (m_ppEPPRuleList
!= NULL
)
311 if (m_dwFlags
& CSF_EPP_UPLOAD
) // Aborted in the middle of EPP transfer
312 for(i
= 0; i
< m_dwRecordsUploaded
; i
++)
313 delete m_ppEPPRuleList
[i
];
314 free(m_ppEPPRuleList
);
317 m_pCtx
->decRefCount();
318 if (m_condEncryptionSetup
!= INVALID_CONDITION_HANDLE
)
319 ConditionDestroy(m_condEncryptionSetup
);
321 if (m_console
!= NULL
)
323 delete m_console
->pMsg
;
326 m_musicTypeList
.clear();
327 if(m_agentConn
.getSize() > 0)
329 m_agentConn
.forEach(&DeleteCallback
, NULL
);
336 void ClientSession::run()
338 m_hWriteThread
= ThreadCreateEx(writeThreadStarter
, 0, this);
339 m_hProcessingThread
= ThreadCreateEx(processingThreadStarter
, 0, this);
340 m_hUpdateThread
= ThreadCreateEx(updateThreadStarter
, 0, this);
341 ThreadCreate(readThreadStarter
, 0, this);
345 * Print debug information
347 void ClientSession::debugPrintf(int level
, const TCHAR
*format
, ...)
349 if (level
<= (int)g_debugLevel
)
354 va_start(args
, format
);
355 _vsntprintf(buffer
, 4096, format
, args
);
357 DbgPrintf(level
, _T("[CLSN-%d] %s"), m_dwIndex
, buffer
);
364 void ClientSession::readThread()
366 UINT32 msgBufferSize
= 1024;
367 CSCP_MESSAGE
*pRawMsg
;
369 BYTE
*pDecryptionBuffer
= NULL
;
376 // Initialize raw message receiving function
377 RecvNXCPMessage(0, NULL
, m_pMsgBuffer
, 0, NULL
, NULL
, 0);
379 pRawMsg
= (CSCP_MESSAGE
*)malloc(msgBufferSize
);
380 #ifdef _WITH_ENCRYPTION
381 pDecryptionBuffer
= (BYTE
*)malloc(msgBufferSize
);
385 // Shrink buffer after receiving large message
386 if (msgBufferSize
> 131072)
388 msgBufferSize
= 131072;
389 pRawMsg
= (CSCP_MESSAGE
*)realloc(pRawMsg
, msgBufferSize
);
390 if (pDecryptionBuffer
!= NULL
)
391 pDecryptionBuffer
= (BYTE
*)realloc(pDecryptionBuffer
, msgBufferSize
);
394 if ((iErr
= RecvNXCPMessageEx(m_hSocket
, &pRawMsg
, m_pMsgBuffer
, &msgBufferSize
,
395 &m_pCtx
, (pDecryptionBuffer
!= NULL
) ? &pDecryptionBuffer
: NULL
,
396 900000, MAX_MSG_SIZE
)) <= 0) // timeout 15 minutes
398 debugPrintf(5, _T("RecvNXCPMessageEx failed (%d)"), iErr
);
405 debugPrintf(5, _T("RecvNXCPMessageEx: receive timeout"));
409 // Check if message is too large
412 debugPrintf(4, _T("Received message %s is too large (%d bytes)"),
413 NXCPMessageCodeName(ntohs(pRawMsg
->wCode
), szBuffer
),
414 ntohl(pRawMsg
->dwSize
));
418 // Check for decryption error
421 debugPrintf(4, _T("Unable to decrypt received message"));
425 // Check that actual received packet size is equal to encoded in packet
426 if ((int)ntohl(pRawMsg
->dwSize
) != iErr
)
428 debugPrintf(4, _T("Actual message size doesn't match wSize value (%d,%d)"), iErr
, ntohl(pRawMsg
->dwSize
));
429 continue; // Bad packet, wait for next
432 if (g_debugLevel
>= 8)
434 String msgDump
= CSCPMessage::dump(pRawMsg
, NXCP_VERSION
);
435 debugPrintf(8, _T("Message dump:\n%s"), (const TCHAR
*)msgDump
);
438 // Special handling for raw messages
439 wFlags
= ntohs(pRawMsg
->wFlags
);
440 if (wFlags
& MF_BINARY
)
442 // Convert message header to host format
443 UINT32 id
= ntohl(pRawMsg
->dwId
);
444 UINT16 code
= ntohs(pRawMsg
->wCode
);
445 UINT32 numVars
= ntohl(pRawMsg
->dwNumVars
);
446 debugPrintf(6, _T("Received raw message %s"), NXCPMessageCodeName(code
, szBuffer
));
448 if ((code
== CMD_FILE_DATA
) ||
449 (code
== CMD_ABORT_FILE_TRANSFER
))
451 if ((m_hCurrFile
!= -1) && (m_dwFileRqId
== id
))
453 if (code
== CMD_FILE_DATA
)
455 if (write(m_hCurrFile
, pRawMsg
->df
, numVars
) == (int)numVars
)
457 if (wFlags
& MF_END_OF_FILE
)
459 debugPrintf(6, _T("Got end of file marker"));
465 msg
.SetCode(CMD_REQUEST_COMPLETED
);
467 msg
.SetVariable(VID_RCC
, RCC_SUCCESS
);
475 debugPrintf(6, _T("I/O error"));
482 msg
.SetCode(CMD_REQUEST_COMPLETED
);
484 msg
.SetVariable(VID_RCC
, RCC_IO_ERROR
);
492 // Abort current file transfer because of client's problem
501 AgentConnection
*conn
= (AgentConnection
*)m_agentConn
.get(id
);
504 if (code
== CMD_FILE_DATA
)
507 if (conn
->sendRawMessage(pRawMsg
))//send raw message
509 if (wFlags
& MF_END_OF_FILE
)
511 debugPrintf(6, _T("Got end of file marker"));
512 //get response with specific ID if ok< then send ok, else send error
513 m_agentConn
.remove(id
);
517 msg
.SetCode(CMD_REQUEST_COMPLETED
);
519 msg
.SetVariable(VID_RCC
, RCC_SUCCESS
);
525 debugPrintf(6, _T("Error while sending to agent"));
528 m_agentConn
.remove(id
);
531 msg
.SetCode(CMD_REQUEST_COMPLETED
);
533 msg
.SetVariable(VID_RCC
, RCC_IO_ERROR
); //set result that came from agent
539 // Resend abort message
540 conn
->sendRawMessage(pRawMsg
);
541 m_agentConn
.remove(id
);
547 debugPrintf(4, _T("Out of state message (ID: %d)"), id
);
554 // Create message object from raw message
555 pMsg
= new CSCPMessage(pRawMsg
);
556 if ((pMsg
->GetCode() == CMD_SESSION_KEY
) && (pMsg
->GetId() == m_dwEncryptionRqId
))
558 debugPrintf(6, _T("Received message %s"), NXCPMessageCodeName(pMsg
->GetCode(), szBuffer
));
559 m_dwEncryptionResult
= SetupEncryptionContext(pMsg
, &m_pCtx
, NULL
, g_pServerKey
, NXCP_VERSION
);
560 ConditionSet(m_condEncryptionSetup
);
561 m_dwEncryptionRqId
= 0;
564 else if (pMsg
->GetCode() == CMD_KEEPALIVE
)
566 debugPrintf(6, _T("Received message %s"), NXCPMessageCodeName(pMsg
->GetCode(), szBuffer
));
567 respondToKeepalive(pMsg
->GetId());
572 m_pMessageQueue
->Put(pMsg
);
577 nxlog_write(MSG_SESSION_CLOSED
, EVENTLOG_WARNING_TYPE
, "e", WSAGetLastError());
579 #ifdef _WITH_ENCRYPTION
580 free(pDecryptionBuffer
);
583 // Finish update thread first
584 m_pUpdateQueue
->Put(INVALID_POINTER_VALUE
);
585 ThreadJoin(m_hUpdateThread
);
587 // Notify other threads to exit
588 while((pRawMsg
= (CSCP_MESSAGE
*)m_pSendQueue
->Get()) != NULL
)
590 m_pSendQueue
->Put(INVALID_POINTER_VALUE
);
591 while((pMsg
= (CSCPMessage
*)m_pMessageQueue
->Get()) != NULL
)
593 m_pMessageQueue
->Put(INVALID_POINTER_VALUE
);
595 // Wait for other threads to finish
596 ThreadJoin(m_hWriteThread
);
597 ThreadJoin(m_hProcessingThread
);
599 // Abort current file upload operation, if any
600 if (m_hCurrFile
!= -1)
607 // remove all pending file transfers from reporting server
608 RemovePendingFileTransferRequests(this);
610 // Remove all locks created by this session
611 RemoveAllSessionLocks(m_dwIndex
);
612 for(i
= 0; i
< m_dwOpenDCIListSize
; i
++)
614 object
= FindObjectById(m_pOpenDCIList
[i
]);
616 if ((object
->Type() == OBJECT_NODE
) ||
617 (object
->Type() == OBJECT_CLUSTER
) ||
618 (object
->Type() == OBJECT_TEMPLATE
))
619 ((Template
*)object
)->unlockDCIList(m_dwIndex
);
622 // Waiting while reference count becomes 0
623 if (m_dwRefCount
> 0)
625 debugPrintf(3, _T("Waiting for pending requests..."));
629 } while(m_dwRefCount
> 0);
632 if (m_dwFlags
& CSF_AUTHENTICATED
)
634 CALL_ALL_MODULES(pfClientSessionClose
, (this));
635 WriteAuditLog(AUDIT_SECURITY
, TRUE
, m_dwUserId
, m_workstation
, 0, _T("User logged out (client: %s)"), m_szClientInfo
);
637 debugPrintf(3, _T("Session closed"));
641 * Network write thread
643 void ClientSession::writeThread()
645 CSCP_MESSAGE
*pRawMsg
;
646 CSCP_ENCRYPTED_MESSAGE
*pEnMsg
;
652 pRawMsg
= (CSCP_MESSAGE
*)m_pSendQueue
->GetOrBlock();
653 if (pRawMsg
== INVALID_POINTER_VALUE
) // Session termination indicator
656 if (ntohs(pRawMsg
->wCode
) != CMD_ADM_MESSAGE
)
657 debugPrintf(6, _T("Sending message %s"), NXCPMessageCodeName(ntohs(pRawMsg
->wCode
), szBuffer
));
661 pEnMsg
= CSCPEncryptMessage(m_pCtx
, pRawMsg
);
664 bResult
= (SendEx(m_hSocket
, (char *)pEnMsg
, ntohl(pEnMsg
->dwSize
), 0, m_mutexSocketWrite
) == (int)ntohl(pEnMsg
->dwSize
));
674 bResult
= (SendEx(m_hSocket
, (const char *)pRawMsg
, ntohl(pRawMsg
->dwSize
), 0, m_mutexSocketWrite
) == (int)ntohl(pRawMsg
->dwSize
));
680 closesocket(m_hSocket
);
688 * Update processing thread
690 void ClientSession::updateThread()
692 UPDATE_INFO
*pUpdate
;
697 pUpdate
= (UPDATE_INFO
*)m_pUpdateQueue
->GetOrBlock();
698 if (pUpdate
== INVALID_POINTER_VALUE
) // Session termination indicator
701 switch(pUpdate
->dwCategory
)
704 MutexLock(m_mutexSendEvents
);
705 sendMessage((CSCPMessage
*)pUpdate
->pData
);
706 MutexUnlock(m_mutexSendEvents
);
707 delete (CSCPMessage
*)pUpdate
->pData
;
709 case INFO_CAT_SYSLOG_MSG
:
710 MutexLock(m_mutexSendSyslog
);
711 msg
.SetCode(CMD_SYSLOG_RECORDS
);
712 CreateMessageFromSyslogMsg(&msg
, (NX_SYSLOG_RECORD
*)pUpdate
->pData
);
714 MutexUnlock(m_mutexSendSyslog
);
715 free(pUpdate
->pData
);
717 case INFO_CAT_SNMP_TRAP
:
718 MutexLock(m_mutexSendTrapLog
);
719 sendMessage((CSCPMessage
*)pUpdate
->pData
);
720 MutexUnlock(m_mutexSendTrapLog
);
721 delete (CSCPMessage
*)pUpdate
->pData
;
723 case INFO_CAT_AUDIT_RECORD
:
724 MutexLock(m_mutexSendAuditLog
);
725 sendMessage((CSCPMessage
*)pUpdate
->pData
);
726 MutexUnlock(m_mutexSendAuditLog
);
727 delete (CSCPMessage
*)pUpdate
->pData
;
729 case INFO_CAT_OBJECT_CHANGE
:
730 MutexLock(m_mutexSendObjects
);
731 msg
.SetCode(CMD_OBJECT_UPDATE
);
732 if (!((NetObj
*)pUpdate
->pData
)->isDeleted())
734 ((NetObj
*)pUpdate
->pData
)->CreateMessage(&msg
);
735 if (m_dwFlags
& CSF_SYNC_OBJECT_COMMENTS
)
736 ((NetObj
*)pUpdate
->pData
)->commentsToMessage(&msg
);
740 msg
.SetVariable(VID_OBJECT_ID
, ((NetObj
*)pUpdate
->pData
)->Id());
741 msg
.SetVariable(VID_IS_DELETED
, (WORD
)1);
744 MutexUnlock(m_mutexSendObjects
);
745 msg
.deleteAllVariables();
746 ((NetObj
*)pUpdate
->pData
)->decRefCount();
749 MutexLock(m_mutexSendAlarms
);
750 msg
.SetCode(CMD_ALARM_UPDATE
);
751 msg
.SetVariable(VID_NOTIFICATION_CODE
, pUpdate
->dwCode
);
752 FillAlarmInfoMessage(&msg
, (NXC_ALARM
*)pUpdate
->pData
);
754 MutexUnlock(m_mutexSendAlarms
);
755 msg
.deleteAllVariables();
756 free(pUpdate
->pData
);
758 case INFO_CAT_ACTION
:
759 MutexLock(m_mutexSendActions
);
760 msg
.SetCode(CMD_ACTION_DB_UPDATE
);
761 msg
.SetVariable(VID_NOTIFICATION_CODE
, pUpdate
->dwCode
);
762 msg
.SetVariable(VID_ACTION_ID
, ((NXC_ACTION
*)pUpdate
->pData
)->dwId
);
763 if (pUpdate
->dwCode
!= NX_NOTIFY_ACTION_DELETED
)
764 FillActionInfoMessage(&msg
, (NXC_ACTION
*)pUpdate
->pData
);
766 MutexUnlock(m_mutexSendActions
);
767 msg
.deleteAllVariables();
768 free(pUpdate
->pData
);
770 case INFO_CAT_SITUATION
:
771 MutexLock(m_mutexSendSituations
);
772 sendMessage((CSCPMessage
*)pUpdate
->pData
);
773 MutexUnlock(m_mutexSendSituations
);
774 delete (CSCPMessage
*)pUpdate
->pData
;
776 case INFO_CAT_LIBRARY_IMAGE
:
778 LIBRARY_IMAGE_UPDATE_INFO
*info
= (LIBRARY_IMAGE_UPDATE_INFO
*)pUpdate
->pData
;
779 msg
.SetCode(CMD_IMAGE_LIBRARY_UPDATE
);
780 msg
.SetVariable(VID_GUID
, (BYTE
*)info
->guid
, UUID_LENGTH
);
783 msg
.SetVariable(VID_FLAGS
, (UINT32
)1);
787 msg
.SetVariable(VID_FLAGS
, (UINT32
)0);
790 msg
.deleteAllVariables();
804 * Message processing thread
806 void ClientSession::processingThread()
815 pMsg
= (CSCPMessage
*)m_pMessageQueue
->GetOrBlock();
816 if (pMsg
== INVALID_POINTER_VALUE
) // Session termination indicator
819 m_wCurrentCmd
= pMsg
->GetCode();
820 debugPrintf(6, _T("Received message %s"), NXCPMessageCodeName(m_wCurrentCmd
, szBuffer
));
821 if (!(m_dwFlags
& CSF_AUTHENTICATED
) &&
822 (m_wCurrentCmd
!= CMD_LOGIN
) &&
823 (m_wCurrentCmd
!= CMD_GET_SERVER_INFO
) &&
824 (m_wCurrentCmd
!= CMD_REQUEST_ENCRYPTION
) &&
825 (m_wCurrentCmd
!= CMD_GET_MY_CONFIG
) &&
826 (m_wCurrentCmd
!= CMD_REGISTER_AGENT
))
832 m_iState
= SESSION_STATE_PROCESSING
;
833 switch(m_wCurrentCmd
)
838 case CMD_GET_SERVER_INFO
:
839 sendServerInfo(pMsg
->GetId());
841 case CMD_GET_MY_CONFIG
:
842 sendConfigForAgent(pMsg
);
844 case CMD_GET_OBJECTS
:
845 sendAllObjects(pMsg
);
847 case CMD_GET_SELECTED_OBJECTS
:
848 sendSelectedObjects(pMsg
);
851 CALL_IN_NEW_THREAD(sendEventLog
, pMsg
);
853 case CMD_GET_CONFIG_VARLIST
:
854 sendAllConfigVars(pMsg
->GetId());
856 case CMD_SET_CONFIG_VARIABLE
:
857 setConfigVariable(pMsg
);
859 case CMD_DELETE_CONFIG_VARIABLE
:
860 deleteConfigVariable(pMsg
);
862 case CMD_CONFIG_GET_CLOB
:
865 case CMD_CONFIG_SET_CLOB
:
868 case CMD_LOAD_EVENT_DB
:
869 sendEventDB(pMsg
->GetId());
871 case CMD_SET_EVENT_INFO
:
872 modifyEventTemplate(pMsg
);
874 case CMD_DELETE_EVENT_TEMPLATE
:
875 deleteEventTemplate(pMsg
);
877 case CMD_GENERATE_EVENT_CODE
:
878 generateEventCode(pMsg
->GetId());
880 case CMD_MODIFY_OBJECT
:
883 case CMD_SET_OBJECT_MGMT_STATUS
:
884 changeObjectMgmtStatus(pMsg
);
886 case CMD_LOAD_USER_DB
:
887 sendUserDB(pMsg
->GetId());
889 case CMD_CREATE_USER
:
892 case CMD_UPDATE_USER
:
895 case CMD_DELETE_USER
:
898 case CMD_LOCK_USER_DB
:
899 lockUserDB(pMsg
->GetId(), TRUE
);
901 case CMD_UNLOCK_USER_DB
:
902 lockUserDB(pMsg
->GetId(), FALSE
);
904 case CMD_SET_PASSWORD
:
907 case CMD_GET_NODE_DCI_LIST
:
908 openNodeDCIList(pMsg
);
910 case CMD_UNLOCK_NODE_DCI_LIST
:
911 closeNodeDCIList(pMsg
);
913 case CMD_CREATE_NEW_DCI
:
914 case CMD_MODIFY_NODE_DCI
:
915 case CMD_DELETE_NODE_DCI
:
918 case CMD_SET_DCI_STATUS
:
919 changeDCIStatus(pMsg
);
924 case CMD_APPLY_TEMPLATE
:
927 case CMD_GET_DCI_DATA
:
928 CALL_IN_NEW_THREAD(getCollectedData
, pMsg
);
930 case CMD_GET_TABLE_DCI_DATA
:
931 CALL_IN_NEW_THREAD(getTableCollectedData
, pMsg
);
933 case CMD_CLEAR_DCI_DATA
:
934 CALL_IN_NEW_THREAD(clearDCIData
, pMsg
);
940 closeEPP(pMsg
->GetId());
946 processEPPRecord(pMsg
);
948 case CMD_GET_MIB_TIMESTAMP
:
949 sendMIBTimestamp(pMsg
->GetId());
952 CALL_IN_NEW_THREAD(sendMib
, pMsg
);
954 case CMD_CREATE_OBJECT
:
955 CALL_IN_NEW_THREAD(createObject
, pMsg
);
957 case CMD_BIND_OBJECT
:
958 changeObjectBinding(pMsg
, TRUE
);
960 case CMD_UNBIND_OBJECT
:
961 changeObjectBinding(pMsg
, FALSE
);
963 case CMD_ADD_CLUSTER_NODE
:
964 addClusterNode(pMsg
);
966 case CMD_GET_ALL_ALARMS
:
967 sendAllAlarms(pMsg
->GetId());
969 case CMD_GET_ALARM_COMMENTS
:
970 getAlarmComments(pMsg
);
972 case CMD_SET_ALARM_STATUS_FLOW
:
973 updateAlarmStatusFlow(pMsg
);
975 case CMD_UPDATE_ALARM_COMMENT
:
976 updateAlarmComment(pMsg
);
978 case CMD_DELETE_ALARM_COMMENT
:
979 deleteAlarmComment(pMsg
);
984 case CMD_GET_ALARM_EVENTS
:
985 CALL_IN_NEW_THREAD(getAlarmEvents
, pMsg
);
988 acknowledgeAlarm(pMsg
);
990 case CMD_RESOLVE_ALARM
:
991 resolveAlarm(pMsg
, false);
993 case CMD_TERMINATE_ALARM
:
994 resolveAlarm(pMsg
, true);
996 case CMD_DELETE_ALARM
:
999 case CMD_OPEN_HELPDESK_ISSUE
:
1000 CALL_IN_NEW_THREAD(openHelpdeskIssue
, pMsg
);
1002 case CMD_GET_HELPDESK_URL
:
1003 getHelpdeskUrl(pMsg
);
1005 case CMD_UNLINK_HELPDESK_ISSUE
:
1006 unlinkHelpdeskIssue(pMsg
);
1008 case CMD_CREATE_ACTION
:
1011 case CMD_MODIFY_ACTION
:
1014 case CMD_DELETE_ACTION
:
1017 case CMD_LOAD_ACTIONS
:
1018 sendAllActions(pMsg
->GetId());
1020 case CMD_GET_CONTAINER_CAT_LIST
:
1021 SendContainerCategories(pMsg
->GetId());
1023 case CMD_DELETE_OBJECT
:
1027 forcedNodePoll(pMsg
);
1032 case CMD_WAKEUP_NODE
:
1035 case CMD_CREATE_TRAP
:
1036 editTrap(TRAP_CREATE
, pMsg
);
1038 case CMD_MODIFY_TRAP
:
1039 editTrap(TRAP_UPDATE
, pMsg
);
1041 case CMD_DELETE_TRAP
:
1042 editTrap(TRAP_DELETE
, pMsg
);
1044 case CMD_LOAD_TRAP_CFG
:
1045 sendAllTraps(pMsg
->GetId());
1047 case CMD_GET_TRAP_CFG_RO
:
1048 sendAllTraps2(pMsg
->GetId());
1050 case CMD_QUERY_PARAMETER
:
1051 CALL_IN_NEW_THREAD(queryParameter
, pMsg
);
1053 case CMD_QUERY_TABLE
:
1054 CALL_IN_NEW_THREAD(queryAgentTable
, pMsg
);
1056 case CMD_LOCK_PACKAGE_DB
:
1057 LockPackageDB(pMsg
->GetId(), TRUE
);
1059 case CMD_UNLOCK_PACKAGE_DB
:
1060 LockPackageDB(pMsg
->GetId(), FALSE
);
1062 case CMD_GET_PACKAGE_LIST
:
1063 SendAllPackages(pMsg
->GetId());
1065 case CMD_INSTALL_PACKAGE
:
1066 InstallPackage(pMsg
);
1068 case CMD_REMOVE_PACKAGE
:
1069 RemovePackage(pMsg
);
1071 case CMD_GET_PARAMETER_LIST
:
1072 getParametersList(pMsg
);
1074 case CMD_DEPLOY_PACKAGE
:
1075 DeployPackage(pMsg
);
1077 case CMD_GET_LAST_VALUES
:
1078 getLastValues(pMsg
);
1080 case CMD_GET_DCI_VALUES
:
1081 getLastValuesByDciId(pMsg
);
1083 case CMD_GET_TABLE_LAST_VALUES
:
1084 getTableLastValues(pMsg
);
1086 case CMD_GET_THRESHOLD_SUMMARY
:
1087 getThresholdSummary(pMsg
);
1089 case CMD_GET_USER_VARIABLE
:
1090 getUserVariable(pMsg
);
1092 case CMD_SET_USER_VARIABLE
:
1093 setUserVariable(pMsg
);
1095 case CMD_DELETE_USER_VARIABLE
:
1096 deleteUserVariable(pMsg
);
1098 case CMD_ENUM_USER_VARIABLES
:
1099 enumUserVariables(pMsg
);
1101 case CMD_COPY_USER_VARIABLE
:
1102 copyUserVariable(pMsg
);
1104 case CMD_CHANGE_ZONE
:
1105 changeObjectZone(pMsg
);
1107 case CMD_REQUEST_ENCRYPTION
:
1108 setupEncryption(pMsg
);
1110 case CMD_GET_AGENT_CONFIG
:
1111 getAgentConfig(pMsg
);
1113 case CMD_UPDATE_AGENT_CONFIG
:
1114 updateAgentConfig(pMsg
);
1116 case CMD_EXECUTE_ACTION
:
1117 CALL_IN_NEW_THREAD(executeAction
, pMsg
);
1119 case CMD_GET_OBJECT_TOOLS
:
1120 sendObjectTools(pMsg
->GetId());
1122 case CMD_EXEC_TABLE_TOOL
:
1123 execTableTool(pMsg
);
1125 case CMD_GET_OBJECT_TOOL_DETAILS
:
1126 sendObjectToolDetails(pMsg
);
1128 case CMD_UPDATE_OBJECT_TOOL
:
1129 updateObjectTool(pMsg
);
1131 case CMD_DELETE_OBJECT_TOOL
:
1132 deleteObjectTool(pMsg
);
1134 case CMD_CHANGE_OBJECT_TOOL_STATUS
:
1135 changeObjectToolStatus(pMsg
);
1137 case CMD_GENERATE_OBJECT_TOOL_ID
:
1138 generateObjectToolId(pMsg
->GetId());
1140 case CMD_CHANGE_SUBSCRIPTION
:
1141 changeSubscription(pMsg
);
1143 case CMD_GET_SYSLOG
:
1144 CALL_IN_NEW_THREAD(sendSyslog
, pMsg
);
1146 case CMD_GET_SERVER_STATS
:
1147 sendServerStats(pMsg
->GetId());
1149 case CMD_GET_SCRIPT_LIST
:
1150 sendScriptList(pMsg
->GetId());
1152 case CMD_GET_SCRIPT
:
1155 case CMD_UPDATE_SCRIPT
:
1158 case CMD_RENAME_SCRIPT
:
1161 case CMD_DELETE_SCRIPT
:
1164 case CMD_GET_SESSION_LIST
:
1165 SendSessionList(pMsg
->GetId());
1167 case CMD_KILL_SESSION
:
1170 case CMD_GET_TRAP_LOG
:
1173 case CMD_START_SNMP_WALK
:
1174 StartSnmpWalk(pMsg
);
1176 case CMD_RESOLVE_DCI_NAMES
:
1177 resolveDCINames(pMsg
);
1179 case CMD_GET_DCI_INFO
:
1182 case CMD_GET_DCI_THRESHOLDS
:
1183 sendDCIThresholds(pMsg
);
1185 case CMD_GET_DCI_EVENTS_LIST
:
1186 sendDCIEventList(pMsg
);
1188 case CMD_GET_PERFTAB_DCI_LIST
:
1189 sendPerfTabDCIList(pMsg
);
1191 case CMD_PUSH_DCI_DATA
:
1194 case CMD_GET_AGENT_CFG_LIST
:
1195 sendAgentCfgList(pMsg
->GetId());
1197 case CMD_OPEN_AGENT_CONFIG
:
1198 OpenAgentConfig(pMsg
);
1200 case CMD_SAVE_AGENT_CONFIG
:
1201 SaveAgentConfig(pMsg
);
1203 case CMD_DELETE_AGENT_CONFIG
:
1204 DeleteAgentConfig(pMsg
);
1206 case CMD_SWAP_AGENT_CONFIGS
:
1207 SwapAgentConfigs(pMsg
);
1209 case CMD_GET_OBJECT_COMMENTS
:
1210 SendObjectComments(pMsg
);
1212 case CMD_UPDATE_OBJECT_COMMENTS
:
1213 updateObjectComments(pMsg
);
1215 case CMD_GET_ADDR_LIST
:
1218 case CMD_SET_ADDR_LIST
:
1221 case CMD_RESET_COMPONENT
:
1222 resetComponent(pMsg
);
1224 case CMD_EXPORT_CONFIGURATION
:
1225 exportConfiguration(pMsg
);
1227 case CMD_IMPORT_CONFIGURATION
:
1228 importConfiguration(pMsg
);
1230 case CMD_GET_GRAPH_LIST
:
1231 sendGraphList(pMsg
->GetId());
1233 case CMD_SAVE_GRAPH
:
1236 case CMD_DELETE_GRAPH
:
1239 case CMD_ADD_CA_CERTIFICATE
:
1240 AddCACertificate(pMsg
);
1242 case CMD_DELETE_CERTIFICATE
:
1243 DeleteCertificate(pMsg
);
1245 case CMD_UPDATE_CERT_COMMENTS
:
1246 UpdateCertificateComments(pMsg
);
1248 case CMD_GET_CERT_LIST
:
1249 getCertificateList(pMsg
->GetId());
1251 case CMD_QUERY_L2_TOPOLOGY
:
1252 CALL_IN_NEW_THREAD(queryL2Topology
, pMsg
);
1257 case CMD_GET_COMMUNITY_LIST
:
1258 SendCommunityList(pMsg
->GetId());
1260 case CMD_UPDATE_COMMUNITY_LIST
:
1261 UpdateCommunityList(pMsg
);
1263 case CMD_GET_USM_CREDENTIALS
:
1264 sendUsmCredentials(pMsg
->GetId());
1266 case CMD_UPDATE_USM_CREDENTIALS
:
1267 updateUsmCredentials(pMsg
);
1269 case CMD_GET_SITUATION_LIST
:
1270 getSituationList(pMsg
->GetId());
1272 case CMD_CREATE_SITUATION
:
1273 createSituation(pMsg
);
1275 case CMD_UPDATE_SITUATION
:
1276 updateSituation(pMsg
);
1278 case CMD_DELETE_SITUATION
:
1279 deleteSituation(pMsg
);
1281 case CMD_DEL_SITUATION_INSTANCE
:
1282 deleteSituationInstance(pMsg
);
1284 case CMD_REGISTER_AGENT
:
1285 registerAgent(pMsg
);
1287 case CMD_GET_SERVER_FILE
:
1288 CALL_IN_NEW_THREAD(getServerFile
, pMsg
);
1290 case CMD_GET_AGENT_FILE
:
1291 CALL_IN_NEW_THREAD(getAgentFile
, pMsg
);
1293 case CMD_CANCEL_FILE_MONITORING
:
1294 CALL_IN_NEW_THREAD(cancelFileMonitoring
, pMsg
);
1296 case CMD_TEST_DCI_TRANSFORMATION
:
1297 testDCITransformation(pMsg
);
1299 case CMD_GET_JOB_LIST
:
1300 sendJobList(pMsg
->GetId());
1302 case CMD_CANCEL_JOB
:
1308 case CMD_UNHOLD_JOB
:
1311 case CMD_DEPLOY_AGENT_POLICY
:
1312 deployAgentPolicy(pMsg
, false);
1314 case CMD_UNINSTALL_AGENT_POLICY
:
1315 deployAgentPolicy(pMsg
, true);
1317 case CMD_GET_CURRENT_USER_ATTR
:
1318 getUserCustomAttribute(pMsg
);
1320 case CMD_SET_CURRENT_USER_ATTR
:
1321 setUserCustomAttribute(pMsg
);
1323 case CMD_OPEN_SERVER_LOG
:
1324 openServerLog(pMsg
);
1326 case CMD_CLOSE_SERVER_LOG
:
1327 closeServerLog(pMsg
);
1330 CALL_IN_NEW_THREAD(queryServerLog
, pMsg
);
1332 case CMD_GET_LOG_DATA
:
1333 CALL_IN_NEW_THREAD(getServerLogQueryData
, pMsg
);
1335 case CMD_FIND_NODE_CONNECTION
:
1336 CALL_IN_NEW_THREAD(findNodeConnection
, pMsg
);
1338 case CMD_FIND_MAC_LOCATION
:
1339 CALL_IN_NEW_THREAD(findMacAddress
, pMsg
);
1341 case CMD_FIND_IP_LOCATION
:
1342 CALL_IN_NEW_THREAD(findIpAddress
, pMsg
);
1345 sendLibraryImage(pMsg
);
1347 case CMD_CREATE_IMAGE
:
1348 updateLibraryImage(pMsg
);
1350 case CMD_DELETE_IMAGE
:
1351 deleteLibraryImage(pMsg
);
1353 case CMD_MODIFY_IMAGE
:
1354 updateLibraryImage(pMsg
);
1356 case CMD_LIST_IMAGES
:
1357 listLibraryImages(pMsg
);
1359 case CMD_EXECUTE_SERVER_COMMAND
:
1360 executeServerCommand(pMsg
);
1362 case CMD_LIST_SERVER_FILES
:
1363 listServerFileStore(pMsg
);
1365 case CMD_UPLOAD_FILE_TO_AGENT
:
1366 uploadFileToAgent(pMsg
);
1368 case CMD_UPLOAD_FILE
:
1371 case CMD_DELETE_FILE
:
1374 case CMD_OPEN_CONSOLE
:
1375 openConsole(pMsg
->GetId());
1377 case CMD_CLOSE_CONSOLE
:
1378 closeConsole(pMsg
->GetId());
1380 case CMD_ADM_REQUEST
:
1381 CALL_IN_NEW_THREAD(processConsoleCommand
, pMsg
);
1386 case CMD_GET_NETWORK_PATH
:
1387 CALL_IN_NEW_THREAD(getNetworkPath
, pMsg
);
1389 case CMD_GET_NODE_COMPONENTS
:
1390 getNodeComponents(pMsg
);
1392 case CMD_GET_NODE_SOFTWARE
:
1393 getNodeSoftware(pMsg
);
1395 case CMD_GET_WINPERF_OBJECTS
:
1396 getWinPerfObjects(pMsg
);
1398 case CMD_LIST_MAPPING_TABLES
:
1399 listMappingTables(pMsg
);
1401 case CMD_GET_MAPPING_TABLE
:
1402 getMappingTable(pMsg
);
1404 case CMD_UPDATE_MAPPING_TABLE
:
1405 updateMappingTable(pMsg
);
1407 case CMD_DELETE_MAPPING_TABLE
:
1408 deleteMappingTable(pMsg
);
1410 case CMD_GET_WIRELESS_STATIONS
:
1411 getWirelessStations(pMsg
);
1413 case CMD_GET_SUMMARY_TABLES
:
1414 getSummaryTables(pMsg
->GetId());
1416 case CMD_GET_SUMMARY_TABLE_DETAILS
:
1417 getSummaryTableDetails(pMsg
);
1419 case CMD_MODIFY_SUMMARY_TABLE
:
1420 modifySummaryTable(pMsg
);
1422 case CMD_DELETE_SUMMARY_TABLE
:
1423 deleteSummaryTable(pMsg
);
1425 case CMD_QUERY_SUMMARY_TABLE
:
1426 querySummaryTable(pMsg
);
1428 case CMD_GET_SUBNET_ADDRESS_MAP
:
1429 getSubnetAddressMap(pMsg
);
1431 case CMD_GET_EFFECTIVE_RIGHTS
:
1432 getEffectiveRights(pMsg
);
1434 case CMD_GET_FOLDER_CONTENT
:
1435 case CMD_FILEMGR_DELETE_FILE
:
1436 case CMD_FILEMGR_RENAME_FILE
:
1437 case CMD_FILEMGR_MOVE_FILE
:
1438 CALL_IN_NEW_THREAD(fileManagerControl
, pMsg
);
1440 case CMD_FILEMGR_UPLOAD
:
1441 CALL_IN_NEW_THREAD(uploadUserFileToAgent
, pMsg
);
1443 case CMD_GET_SWITCH_FDB
:
1444 CALL_IN_NEW_THREAD(getSwitchForwardingDatabase
, pMsg
);
1446 case CMD_GET_ROUTING_TABLE
:
1447 CALL_IN_NEW_THREAD(getRoutingTable
, pMsg
);
1450 if ((m_wCurrentCmd
>> 8) == 0x11)
1452 // Reporting Server range (0x1100 - 0x11FF)
1453 CALL_IN_NEW_THREAD(forwardToReportingServer
, pMsg
);
1457 // Pass message to loaded modules
1458 for(i
= 0; i
< g_dwNumModules
; i
++)
1460 if (g_pModuleList
[i
].pfClientCommandHandler
!= NULL
)
1462 status
= g_pModuleList
[i
].pfClientCommandHandler(m_wCurrentCmd
, pMsg
, this);
1463 if (status
!= NXMOD_COMMAND_IGNORED
)
1465 if (status
== NXMOD_COMMAND_ACCEPTED_ASYNC
)
1467 pMsg
= NULL
; // Prevent deletion
1470 break; // Message was processed by the module
1474 if (i
== g_dwNumModules
)
1476 CSCPMessage response
;
1478 response
.SetId(pMsg
->GetId());
1479 response
.SetCode(CMD_REQUEST_COMPLETED
);
1480 response
.SetVariable(VID_RCC
, RCC_NOT_IMPLEMENTED
);
1481 sendMessage(&response
);
1486 m_iState
= (m_dwFlags
& CSF_AUTHENTICATED
) ? SESSION_STATE_IDLE
: SESSION_STATE_INIT
;
1491 * Respond to client's keepalive message
1493 void ClientSession::respondToKeepalive(UINT32 dwRqId
)
1497 msg
.SetCode(CMD_REQUEST_COMPLETED
);
1499 msg
.SetVariable(VID_RCC
, RCC_SUCCESS
);
1504 * Process received file
1506 static void SendLibraryImageUpdate(ClientSession
*pSession
, void *pArg
);
1507 void ClientSession::onFileUpload(BOOL bSuccess
)
1509 // Do processing specific to command initiated file upload
1510 switch(m_dwUploadCommand
)
1512 case CMD_INSTALL_PACKAGE
:
1517 _sntprintf(szQuery
, 256, _T("DELETE FROM agent_pkg WHERE pkg_id=%d"), m_dwUploadData
);
1518 DBQuery(g_hCoreDB
, szQuery
);
1521 case CMD_MODIFY_IMAGE
:
1522 EnumerateClientSessions(SendLibraryImageUpdate
, (void *)&m_uploadImageGuid
);
1528 // Remove received file in case of failure
1530 _tunlink(m_szCurrFileName
);
1534 * Send message to client
1536 void ClientSession::sendMessage(CSCPMessage
*msg
)
1538 TCHAR szBuffer
[128];
1541 if (msg
->GetCode() != CMD_ADM_MESSAGE
)
1542 debugPrintf(6, _T("Sending message %s"), NXCPMessageCodeName(msg
->GetCode(), szBuffer
));
1544 CSCP_MESSAGE
*pRawMsg
= msg
->createMessage();
1545 if ((g_debugLevel
>= 8) && (msg
->GetCode() != CMD_ADM_MESSAGE
))
1547 String msgDump
= CSCPMessage::dump(pRawMsg
, NXCP_VERSION
);
1548 debugPrintf(8, _T("Message dump:\n%s"), (const TCHAR
*)msgDump
);
1552 CSCP_ENCRYPTED_MESSAGE
*pEnMsg
= CSCPEncryptMessage(m_pCtx
, pRawMsg
);
1555 bResult
= (SendEx(m_hSocket
, (char *)pEnMsg
, ntohl(pEnMsg
->dwSize
), 0, m_mutexSocketWrite
) == (int)ntohl(pEnMsg
->dwSize
));
1565 bResult
= (SendEx(m_hSocket
, (const char *)pRawMsg
, ntohl(pRawMsg
->dwSize
), 0, m_mutexSocketWrite
) == (int)ntohl(pRawMsg
->dwSize
));
1571 closesocket(m_hSocket
);
1577 * Send raw message to client
1579 void ClientSession::sendRawMessage(CSCP_MESSAGE
*msg
)
1581 TCHAR szBuffer
[128];
1584 debugPrintf(6, _T("Sending raw message %s"), NXCPMessageCodeName(ntohs(msg
->wCode
), szBuffer
));
1587 CSCP_ENCRYPTED_MESSAGE
*pEnMsg
= CSCPEncryptMessage(m_pCtx
, msg
);
1590 bResult
= (SendEx(m_hSocket
, (char *)pEnMsg
, ntohl(pEnMsg
->dwSize
), 0, m_mutexSocketWrite
) == (int)ntohl(pEnMsg
->dwSize
));
1600 bResult
= (SendEx(m_hSocket
, (const char *)msg
, ntohl(msg
->dwSize
), 0, m_mutexSocketWrite
) == (int)ntohl(msg
->dwSize
));
1605 closesocket(m_hSocket
);
1611 * Send file to client
1613 BOOL
ClientSession::sendFile(const TCHAR
*file
, UINT32 dwRqId
, long ofset
)
1615 return SendFileOverNXCP(m_hSocket
, dwRqId
, file
, m_pCtx
, ofset
, NULL
, NULL
, m_mutexSocketWrite
);
1619 * Send server information to client
1621 void ClientSession::sendServerInfo(UINT32 dwRqId
)
1624 TCHAR szBuffer
[1024];
1627 // Prepare response message
1628 msg
.SetCode(CMD_REQUEST_COMPLETED
);
1631 // Generate challenge for certificate authentication
1632 #ifdef _WITH_ENCRYPTION
1633 RAND_bytes(m_challenge
, CLIENT_CHALLENGE_SIZE
);
1635 memset(m_challenge
, 0, CLIENT_CHALLENGE_SIZE
);
1638 // Fill message with server info
1639 msg
.SetVariable(VID_RCC
, RCC_SUCCESS
);
1640 msg
.SetVariable(VID_SERVER_VERSION
, NETXMS_VERSION_STRING
);
1641 msg
.SetVariable(VID_SERVER_ID
, (BYTE
*)&g_qwServerId
, sizeof(QWORD
));
1642 msg
.SetVariable(VID_SUPPORTED_ENCRYPTION
, (UINT32
)0);
1643 msg
.SetVariable(VID_PROTOCOL_VERSION
, (UINT32
)CLIENT_PROTOCOL_VERSION
);
1644 msg
.SetVariable(VID_CHALLENGE
, m_challenge
, CLIENT_CHALLENGE_SIZE
);
1645 msg
.SetVariable(VID_TIMESTAMP
, (UINT32
)time(NULL
));
1648 TIME_ZONE_INFORMATION tz
;
1649 WCHAR wst
[4], wdt
[8], *curr
;
1652 DWORD tzType
= GetTimeZoneInformation(&tz
);
1654 // Create 3 letter abbreviation for standard name
1655 for(i
= 0, curr
= tz
.StandardName
; (*curr
!= 0) && (i
< 3); curr
++)
1656 if (iswupper(*curr
))
1662 // Create abbreviation for DST name
1663 for(i
= 0, curr
= tz
.DaylightName
; (*curr
!= 0) && (i
< 7); curr
++)
1664 if (iswupper(*curr
))
1673 case TIME_ZONE_ID_STANDARD
:
1674 effectiveBias
= tz
.Bias
+ tz
.StandardBias
;
1676 case TIME_ZONE_ID_DAYLIGHT
:
1677 effectiveBias
= tz
.Bias
+ tz
.DaylightBias
;
1679 case TIME_ZONE_ID_UNKNOWN
:
1680 effectiveBias
= tz
.Bias
;
1684 debugPrintf(4, _T("GetTimeZoneInformation() call failed"));
1689 swprintf(szBuffer
, 1024, L
"%s%c%02d%s", wst
, (effectiveBias
> 0) ? '-' : '+',
1690 abs(effectiveBias
) / 60, (tz
.DaylightBias
!= 0) ? wdt
: L
"");
1692 sprintf(szBuffer
, "%S%c%02d%S", wst
, (effectiveBias
> 0) ? '-' : '+',
1693 abs(effectiveBias
) / 60, (tz
.DaylightBias
!= 0) ? wdt
: L
"");
1696 #elif HAVE_TM_GMTOFF /* not Windows but have tm_gmtoff */
1698 time_t t
= time(NULL
);
1700 #if HAVE_LOCALTIME_R
1702 struct tm
*loc
= localtime_r(&t
, &tmbuff
);
1704 struct tm
*loc
= localtime(&t
);
1706 gmtOffset
= loc
->tm_gmtoff
/ 3600;
1708 swprintf(szBuffer
, 1024, L
"%hs%hc%02d%hs", tzname
[0], (gmtOffset
>= 0) ? '+' : '-',
1709 abs(gmtOffset
), (tzname
[1] != NULL
) ? tzname
[1] : "");
1711 sprintf(szBuffer
, "%s%c%02d%s", tzname
[0], (gmtOffset
>= 0) ? '+' : '-',
1712 abs(gmtOffset
), (tzname
[1] != NULL
) ? tzname
[1] : "");
1715 #else /* not Windows and no tm_gmtoff */
1717 time_t t
= time(NULL
);
1720 struct tm
*gmt
= gmtime_r(&t
, &tmbuff
);
1722 struct tm
*gmt
= gmtime(&t
);
1725 int gmtOffset
= (int)((t
- mktime(gmt
)) / 3600);
1727 swprintf(szBuffer
, 1024, L
"%hs%hc%02d%hs", tzname
[0], (gmtOffset
>= 0) ? '+' : '-',
1728 abs(gmtOffset
), (tzname
[1] != NULL
) ? tzname
[1] : "");
1730 sprintf(szBuffer
, "%s%c%02d%s", tzname
[0], (gmtOffset
>= 0) ? '+' : '-',
1731 abs(gmtOffset
), (tzname
[1] != NULL
) ? tzname
[1] : "");
1736 msg
.SetVariable(VID_TIMEZONE
, szBuffer
);
1737 debugPrintf(2, _T("Server time zone: %s"), szBuffer
);
1739 ConfigReadStr(_T("TileServerURL"), szBuffer
, 1024, _T("http://tile.openstreetmap.org/"));
1740 msg
.SetVariable(VID_TILE_SERVER_URL
, szBuffer
);
1742 ConfigReadStr(_T("DefaultConsoleDateFormat"), szBuffer
, 1024, _T("dd.MM.yyyy"));
1743 msg
.SetVariable(VID_DATE_FORMAT
, szBuffer
);
1745 ConfigReadStr(_T("DefaultConsoleTimeFormat"), szBuffer
, 1024, _T("HH:mm:ss"));
1746 msg
.SetVariable(VID_TIME_FORMAT
, szBuffer
);
1748 ConfigReadStr(_T("DefaultConsoleShortTimeFormat"), szBuffer
, 1024, _T("HH:mm"));
1749 msg
.SetVariable(VID_SHORT_TIME_FORMAT
, szBuffer
);
1756 * Authenticate client
1758 void ClientSession::login(CSCPMessage
*pRequest
)
1761 TCHAR szLogin
[MAX_USER_NAME
], szPassword
[1024];
1763 bool changePasswd
= false, intruderLockout
= false;
1765 #ifdef _WITH_ENCRYPTION
1769 // Prepare response message
1770 msg
.SetCode(CMD_LOGIN_RESP
);
1771 msg
.SetId(pRequest
->GetId());
1773 // Get client info string
1774 if (pRequest
->isFieldExist(VID_CLIENT_INFO
))
1776 TCHAR szClientInfo
[32], szOSInfo
[32], szLibVersion
[16];
1778 pRequest
->GetVariableStr(VID_CLIENT_INFO
, szClientInfo
, 32);
1779 pRequest
->GetVariableStr(VID_OS_INFO
, szOSInfo
, 32);
1780 pRequest
->GetVariableStr(VID_LIBNXCL_VERSION
, szLibVersion
, 16);
1781 _sntprintf(m_szClientInfo
, 96, _T("%s (%s; libnxcl %s)"),
1782 szClientInfo
, szOSInfo
, szLibVersion
);
1785 m_clientType
= pRequest
->GetVariableShort(VID_CLIENT_TYPE
);
1786 if ((m_clientType
< 0) || (m_clientType
> CLIENT_TYPE_APPLICATION
))
1787 m_clientType
= CLIENT_TYPE_DESKTOP
;
1789 if (m_clientType
== CLIENT_TYPE_WEB
)
1791 _tcscpy(m_webServerAddress
, m_workstation
);
1792 if (pRequest
->isFieldExist(VID_CLIENT_ADDRESS
))
1794 pRequest
->GetVariableStr(VID_CLIENT_ADDRESS
, m_workstation
, 256);
1795 debugPrintf(5, _T("Real web client address is %s"), m_workstation
);
1799 if (!(m_dwFlags
& CSF_AUTHENTICATED
))
1801 pRequest
->GetVariableStr(VID_LOGIN_NAME
, szLogin
, MAX_USER_NAME
);
1802 nAuthType
= (int)pRequest
->GetVariableShort(VID_AUTH_TYPE
);
1803 debugPrintf(6, _T("authentication type %d"), nAuthType
);
1806 case NETXMS_AUTH_TYPE_PASSWORD
:
1808 pRequest
->GetVariableStr(VID_PASSWORD
, szPassword
, 256);
1810 pRequest
->GetVariableStrUTF8(VID_PASSWORD
, szPassword
, 1024);
1812 dwResult
= AuthenticateUser(szLogin
, szPassword
, 0, NULL
, NULL
, &m_dwUserId
,
1813 &m_dwSystemAccess
, &changePasswd
, &intruderLockout
, false);
1815 case NETXMS_AUTH_TYPE_CERTIFICATE
:
1816 #ifdef _WITH_ENCRYPTION
1817 pCert
= CertificateFromLoginMessage(pRequest
);
1820 BYTE signature
[256];
1823 dwSigLen
= pRequest
->GetVariableBinary(VID_SIGNATURE
, signature
, 256);
1824 dwResult
= AuthenticateUser(szLogin
, (TCHAR
*)signature
, dwSigLen
, pCert
,
1825 m_challenge
, &m_dwUserId
, &m_dwSystemAccess
,
1826 &changePasswd
, &intruderLockout
, false);
1831 dwResult
= RCC_BAD_CERTIFICATE
;
1834 dwResult
= RCC_NOT_IMPLEMENTED
;
1837 case NETXMS_AUTH_TYPE_SSO_TICKET
:
1839 pRequest
->GetVariableStrA(VID_PASSWORD
, ticket
, 1024);
1840 if (CASAuthenticate(ticket
, szLogin
))
1842 debugPrintf(5, _T("SSO ticket %hs is valid, login name %s"), ticket
, szLogin
);
1843 dwResult
= AuthenticateUser(szLogin
, NULL
, 0, NULL
, NULL
, &m_dwUserId
,
1844 &m_dwSystemAccess
, &changePasswd
, &intruderLockout
, true);
1848 debugPrintf(5, _T("SSO ticket %hs is invalid"), ticket
);
1849 dwResult
= RCC_ACCESS_DENIED
;
1853 dwResult
= RCC_UNSUPPORTED_AUTH_TYPE
;
1857 // Additional validation by loaded modules
1858 if (dwResult
== RCC_SUCCESS
)
1860 for(UINT32 i
= 0; i
< g_dwNumModules
; i
++)
1862 if (g_pModuleList
[i
].pfAdditionalLoginCheck
!= NULL
)
1864 dwResult
= g_pModuleList
[i
].pfAdditionalLoginCheck(m_dwUserId
, pRequest
);
1865 if (dwResult
!= RCC_SUCCESS
)
1867 debugPrintf(4, _T("Login blocked by module %s (rcc=%d)"), g_pModuleList
[i
].szName
, dwResult
);
1874 if (dwResult
== RCC_SUCCESS
)
1876 m_dwFlags
|= CSF_AUTHENTICATED
;
1877 _sntprintf(m_szUserName
, MAX_SESSION_NAME
, _T("%s@%s"), szLogin
, m_workstation
);
1878 m_loginTime
= time(NULL
);
1879 msg
.SetVariable(VID_RCC
, RCC_SUCCESS
);
1880 msg
.SetVariable(VID_USER_SYS_RIGHTS
, m_dwSystemAccess
);
1881 msg
.SetVariable(VID_USER_ID
, m_dwUserId
);
1882 msg
.SetVariable(VID_SESSION_ID
, m_dwIndex
);
1883 msg
.SetVariable(VID_CHANGE_PASSWD_FLAG
, (WORD
)changePasswd
);
1884 msg
.SetVariable(VID_DBCONN_STATUS
, (UINT16
)((g_flags
& AF_DB_CONNECTION_LOST
) ? 0 : 1));
1885 msg
.SetVariable(VID_ZONING_ENABLED
, (UINT16
)((g_flags
& AF_ENABLE_ZONING
) ? 1 : 0));
1886 msg
.SetVariable(VID_POLLING_INTERVAL
, ConfigReadULong(_T("DefaultDCIPollingInterval"), 60));
1887 msg
.SetVariable(VID_RETENTION_TIME
, ConfigReadULong(_T("DefaultDCIRetentionTime"), 30));
1888 msg
.SetVariable(VID_ALARM_STATUS_FLOW_STATE
, (UINT16
)ConfigReadInt(_T("StrictAlarmStatusFlow"), 0));
1889 msg
.SetVariable(VID_TIMED_ALARM_ACK_ENABLED
, (UINT16
)ConfigReadInt(_T("EnableTimedAlarmAck"), 0));
1890 msg
.SetVariable(VID_VIEW_REFRESH_INTERVAL
, (UINT16
)ConfigReadInt(_T("MinViewRefreshInterval"), 200));
1891 msg
.SetVariable(VID_HELPDESK_LINK_ACTIVE
, (UINT16
)((g_flags
& AF_HELPDESK_LINK_ACTIVE
) ? 1 : 0));
1892 msg
.SetVariable(VID_ALARM_LIST_DISP_LIMIT
, ConfigReadULong(_T("AlarmListDisplayLimit"), 4096));
1893 debugPrintf(3, _T("User %s authenticated"), m_szUserName
);
1894 WriteAuditLog(AUDIT_SECURITY
, TRUE
, m_dwUserId
, m_workstation
, 0,
1895 _T("User \"%s\" logged in (client info: %s)"), szLogin
, m_szClientInfo
);
1899 msg
.SetVariable(VID_RCC
, dwResult
);
1900 WriteAuditLog(AUDIT_SECURITY
, FALSE
, m_dwUserId
, m_workstation
, 0,
1901 _T("User \"%s\" login failed with error code %d (client info: %s)"),
1902 szLogin
, dwResult
, m_szClientInfo
);
1903 if (intruderLockout
)
1905 WriteAuditLog(AUDIT_SECURITY
, FALSE
, m_dwUserId
, m_workstation
, 0,
1906 _T("User account \"%s\" temporary disabled due to excess count of failed authentication attempts"), szLogin
);
1912 msg
.SetVariable(VID_RCC
, RCC_OUT_OF_STATE_REQUEST
);
1920 * Send event configuration to client
1922 void ClientSession::sendEventDB(UINT32 dwRqId
)
1924 DB_ASYNC_RESULT hResult
;
1926 TCHAR szBuffer
[4096];
1928 // Prepare response message
1929 msg
.SetCode(CMD_REQUEST_COMPLETED
);
1932 if (checkSysAccessRights(SYSTEM_ACCESS_VIEW_EVENT_DB
) || checkSysAccessRights(SYSTEM_ACCESS_EDIT_EVENT_DB
) || checkSysAccessRights(SYSTEM_ACCESS_EPP
))
1934 if (!(g_flags
& AF_DB_CONNECTION_LOST
))
1936 msg
.SetVariable(VID_RCC
, RCC_SUCCESS
);
1938 msg
.deleteAllVariables();
1940 // Prepare data message
1941 msg
.SetCode(CMD_EVENT_DB_RECORD
);
1944 DB_HANDLE hdb
= DBConnectionPoolAcquireConnection();
1945 hResult
= DBAsyncSelect(hdb
, _T("SELECT event_code,event_name,severity,flags,message,description FROM event_cfg"));
1946 if (hResult
!= NULL
)
1948 while(DBFetch(hResult
))
1950 msg
.SetVariable(VID_EVENT_CODE
, DBGetFieldAsyncULong(hResult
, 0));
1951 msg
.SetVariable(VID_NAME
, DBGetFieldAsync(hResult
, 1, szBuffer
, 1024));
1952 msg
.SetVariable(VID_SEVERITY
, DBGetFieldAsyncULong(hResult
, 2));
1953 msg
.SetVariable(VID_FLAGS
, DBGetFieldAsyncULong(hResult
, 3));
1955 DBGetFieldAsync(hResult
, 4, szBuffer
, 4096);
1956 msg
.SetVariable(VID_MESSAGE
, szBuffer
);
1958 DBGetFieldAsync(hResult
, 5, szBuffer
, 4096);
1959 msg
.SetVariable(VID_DESCRIPTION
, szBuffer
);
1962 msg
.deleteAllVariables();
1964 DBFreeAsyncResult(hResult
);
1966 DBConnectionPoolReleaseConnection(hdb
);
1968 // End-of-list indicator
1969 msg
.SetVariable(VID_EVENT_CODE
, (UINT32
)0);
1970 msg
.setEndOfSequence();
1974 msg
.SetVariable(VID_RCC
, RCC_DB_CONNECTION_LOST
);
1979 msg
.SetVariable(VID_RCC
, RCC_ACCESS_DENIED
);
1985 * Callback for sending event configuration change notifications
1987 static void SendEventDBChangeNotification(ClientSession
*session
, void *arg
)
1989 if (session
->isAuthenticated() &&
1990 (session
->checkSysAccessRights(SYSTEM_ACCESS_VIEW_EVENT_DB
) ||
1991 session
->checkSysAccessRights(SYSTEM_ACCESS_EDIT_EVENT_DB
) ||
1992 session
->checkSysAccessRights(SYSTEM_ACCESS_EPP
)))
1993 session
->postMessage((CSCPMessage
*)arg
);
1997 * Update event template
1999 void ClientSession::modifyEventTemplate(CSCPMessage
*pRequest
)
2003 // Prepare reply message
2004 msg
.SetCode(CMD_REQUEST_COMPLETED
);
2005 msg
.SetId(pRequest
->GetId());
2007 // Check access rights
2008 if (checkSysAccessRights(SYSTEM_ACCESS_EDIT_EVENT_DB
))
2010 TCHAR szQuery
[8192], szName
[MAX_EVENT_NAME
];
2012 DB_HANDLE hdb
= DBConnectionPoolAcquireConnection();
2014 // Check if event with specific code exists
2015 UINT32 dwEventCode
= pRequest
->GetVariableLong(VID_EVENT_CODE
);
2016 bool bEventExist
= IsDatabaseRecordExist(hdb
, _T("event_cfg"), _T("event_code"), dwEventCode
);
2018 // Check that we are not trying to create event below 100000
2019 if (bEventExist
|| (dwEventCode
>= FIRST_USER_EVENT_ID
))
2021 // Prepare and execute SQL query
2022 pRequest
->GetVariableStr(VID_NAME
, szName
, MAX_EVENT_NAME
);
2023 if (IsValidObjectName(szName
))
2025 TCHAR szMessage
[MAX_EVENT_MSG_LENGTH
], *pszDescription
;
2027 pRequest
->GetVariableStr(VID_MESSAGE
, szMessage
, MAX_EVENT_MSG_LENGTH
);
2028 pszDescription
= pRequest
->GetVariableStr(VID_DESCRIPTION
);
2032 _sntprintf(szQuery
, sizeof(szQuery
) / sizeof(TCHAR
), _T("UPDATE event_cfg SET event_name='%s',severity=%d,flags=%d,message=%s,description=%s WHERE event_code=%d"),
2033 szName
, pRequest
->GetVariableLong(VID_SEVERITY
), pRequest
->GetVariableLong(VID_FLAGS
),
2034 (const TCHAR
*)DBPrepareString(g_hCoreDB
, szMessage
),
2035 (const TCHAR
*)DBPrepareString(g_hCoreDB
, pszDescription
), dwEventCode
);
2039 _sntprintf(szQuery
, sizeof(szQuery
) / sizeof(TCHAR
), _T("INSERT INTO event_cfg (event_code,event_name,severity,flags,")
2040 _T("message,description) VALUES (%d,'%s',%d,%d,%s,%s)"),
2041 dwEventCode
, szName
, pRequest
->GetVariableLong(VID_SEVERITY
),
2042 pRequest
->GetVariableLong(VID_FLAGS
), (const TCHAR
*)DBPrepareString(g_hCoreDB
, szMessage
),
2043 (const TCHAR
*)DBPrepareString(g_hCoreDB
, pszDescription
));
2046 safe_free(pszDescription
);
2048 if (DBQuery(hdb
, szQuery
))
2050 msg
.SetVariable(VID_RCC
, RCC_SUCCESS
);
2052 NotifyClientSessions(NX_NOTIFY_EVENTDB_CHANGED
, 0);
2054 CSCPMessage
nmsg(pRequest
);
2055 nmsg
.SetCode(CMD_EVENT_DB_UPDATE
);
2056 nmsg
.SetVariable(VID_NOTIFICATION_CODE
, (WORD
)NX_NOTIFY_ETMPL_CHANGED
);
2057 EnumerateClientSessions(SendEventDBChangeNotification
, &nmsg
);
2061 msg
.SetVariable(VID_RCC
, RCC_DB_FAILURE
);
2066 msg
.SetVariable(VID_RCC
, RCC_INVALID_OBJECT_NAME
);
2071 msg
.SetVariable(VID_RCC
, RCC_INVALID_EVENT_CODE
);
2073 DBConnectionPoolReleaseConnection(hdb
);
2077 msg
.SetVariable(VID_RCC
, RCC_ACCESS_DENIED
);
2085 * Delete event template
2087 void ClientSession::deleteEventTemplate(CSCPMessage
*pRequest
)
2092 // Prepare reply message
2093 msg
.SetCode(CMD_REQUEST_COMPLETED
);
2094 msg
.SetId(pRequest
->GetId());
2096 dwEventCode
= pRequest
->GetVariableLong(VID_EVENT_CODE
);
2098 // Check access rights
2099 if (checkSysAccessRights(SYSTEM_ACCESS_EDIT_EVENT_DB
) && (dwEventCode
>= FIRST_USER_EVENT_ID
))
2103 _sntprintf(szQuery
, 256, _T("DELETE FROM event_cfg WHERE event_code=%d"), dwEventCode
);
2104 if (DBQuery(g_hCoreDB
, szQuery
))
2106 DeleteEventTemplateFromList(dwEventCode
);
2107 NotifyClientSessions(NX_NOTIFY_EVENTDB_CHANGED
, 0);
2110 nmsg
.SetCode(CMD_EVENT_DB_UPDATE
);
2111 nmsg
.SetVariable(VID_NOTIFICATION_CODE
, (WORD
)NX_NOTIFY_ETMPL_DELETED
);
2112 nmsg
.SetVariable(VID_EVENT_CODE
, dwEventCode
);
2113 EnumerateClientSessions(SendEventDBChangeNotification
, &nmsg
);
2115 msg
.SetVariable(VID_RCC
, RCC_SUCCESS
);
2117 WriteAuditLog(AUDIT_SYSCFG
, TRUE
, m_dwUserId
, m_workstation
, 0,
2118 _T("Event template %d deleted"), dwEventCode
);
2122 msg
.SetVariable(VID_RCC
, RCC_DB_FAILURE
);
2127 msg
.SetVariable(VID_RCC
, RCC_ACCESS_DENIED
);
2135 * Generate event code for new event template
2137 void ClientSession::generateEventCode(UINT32 dwRqId
)
2141 // Prepare reply message
2142 msg
.SetCode(CMD_REQUEST_COMPLETED
);
2145 // Check access rights
2146 if (checkSysAccessRights(SYSTEM_ACCESS_EDIT_EVENT_DB
))
2148 msg
.SetVariable(VID_EVENT_CODE
, CreateUniqueId(IDG_EVENT
));
2152 msg
.SetVariable(VID_RCC
, RCC_ACCESS_DENIED
);
2160 * Send all objects to client
2162 void ClientSession::sendAllObjects(CSCPMessage
*pRequest
)
2166 // Send confirmation message
2167 msg
.SetCode(CMD_REQUEST_COMPLETED
);
2168 msg
.SetId(pRequest
->GetId());
2169 msg
.SetVariable(VID_RCC
, RCC_SUCCESS
);
2171 msg
.deleteAllVariables();
2173 // Change "sync comments" flag
2174 if (pRequest
->GetVariableShort(VID_SYNC_COMMENTS
))
2175 m_dwFlags
|= CSF_SYNC_OBJECT_COMMENTS
;
2177 m_dwFlags
&= ~CSF_SYNC_OBJECT_COMMENTS
;
2179 // Get client's last known time stamp
2180 UINT32 dwTimeStamp
= pRequest
->GetVariableLong(VID_TIMESTAMP
);
2183 msg
.SetCode(CMD_OBJECT
);
2185 // Send objects, one per message
2186 ObjectArray
<NetObj
> *objects
= g_idxObjectById
.getObjects(true);
2187 MutexLock(m_mutexSendObjects
);
2188 for(int i
= 0; i
< objects
->size(); i
++)
2190 NetObj
*object
= objects
->get(i
);
2191 if (object
->checkAccessRights(m_dwUserId
, OBJECT_ACCESS_READ
) &&
2192 (object
->getTimeStamp() >= dwTimeStamp
) &&
2193 !object
->isHidden() && !object
->isSystem())
2195 object
->CreateMessage(&msg
);
2196 if (m_dwFlags
& CSF_SYNC_OBJECT_COMMENTS
)
2197 object
->commentsToMessage(&msg
);
2198 if (!object
->checkAccessRights(m_dwUserId
, OBJECT_ACCESS_MODIFY
))
2201 msg
.SetVariable(VID_SHARED_SECRET
, _T("********"));
2202 msg
.SetVariable(VID_SNMP_AUTH_PASSWORD
, _T("********"));
2203 msg
.SetVariable(VID_SNMP_PRIV_PASSWORD
, _T("********"));
2206 msg
.deleteAllVariables();
2208 object
->decRefCount();
2212 // Send end of list notification
2213 msg
.SetCode(CMD_OBJECT_LIST_END
);
2216 MutexUnlock(m_mutexSendObjects
);
2220 * Send selected objects to client
2222 void ClientSession::sendSelectedObjects(CSCPMessage
*pRequest
)
2226 // Send confirmation message
2227 msg
.SetCode(CMD_REQUEST_COMPLETED
);
2228 msg
.SetId(pRequest
->GetId());
2229 msg
.SetVariable(VID_RCC
, RCC_SUCCESS
);
2231 msg
.deleteAllVariables();
2233 // Change "sync comments" flag
2234 if (pRequest
->GetVariableShort(VID_SYNC_COMMENTS
))
2235 m_dwFlags
|= CSF_SYNC_OBJECT_COMMENTS
;
2237 m_dwFlags
&= ~CSF_SYNC_OBJECT_COMMENTS
;
2239 UINT32 dwTimeStamp
= pRequest
->GetVariableLong(VID_TIMESTAMP
);
2240 UINT32 numObjects
= pRequest
->GetVariableLong(VID_NUM_OBJECTS
);
2241 UINT32
*objects
= (UINT32
*)malloc(sizeof(UINT32
) * numObjects
);
2242 pRequest
->getFieldAsInt32Array(VID_OBJECT_LIST
, numObjects
, objects
);
2243 UINT32 options
= pRequest
->GetVariableShort(VID_FLAGS
);
2245 MutexLock(m_mutexSendObjects
);
2248 msg
.SetCode((options
& OBJECT_SYNC_SEND_UPDATES
) ? CMD_OBJECT_UPDATE
: CMD_OBJECT
);
2250 // Send objects, one per message
2251 for(UINT32 i
= 0; i
< numObjects
; i
++)
2253 NetObj
*object
= FindObjectById(objects
[i
]);
2254 if ((object
!= NULL
) &&
2255 object
->checkAccessRights(m_dwUserId
, OBJECT_ACCESS_READ
) &&
2256 (object
->getTimeStamp() >= dwTimeStamp
) &&
2257 !object
->isHidden() && !object
->isSystem())
2259 object
->CreateMessage(&msg
);
2260 if (m_dwFlags
& CSF_SYNC_OBJECT_COMMENTS
)
2261 object
->commentsToMessage(&msg
);
2262 if (!object
->checkAccessRights(m_dwUserId
, OBJECT_ACCESS_MODIFY
))
2265 msg
.SetVariable(VID_SHARED_SECRET
, _T("********"));
2266 msg
.SetVariable(VID_SNMP_AUTH_PASSWORD
, _T("********"));
2267 msg
.SetVariable(VID_SNMP_PRIV_PASSWORD
, _T("********"));
2270 msg
.deleteAllVariables();
2274 MutexUnlock(m_mutexSendObjects
);
2277 if (options
& OBJECT_SYNC_DUAL_CONFIRM
)
2279 msg
.SetCode(CMD_REQUEST_COMPLETED
);
2280 msg
.SetVariable(VID_RCC
, RCC_SUCCESS
);
2286 * Send event log records to client
2288 void ClientSession::sendEventLog(CSCPMessage
*pRequest
)
2291 DB_ASYNC_RESULT hResult
= NULL
;
2292 DB_RESULT hTempResult
;
2293 UINT32 dwRqId
, dwMaxRecords
, dwNumRows
, dwId
;
2294 TCHAR szQuery
[1024], szBuffer
[1024];
2297 dwRqId
= pRequest
->GetId();
2298 dwMaxRecords
= pRequest
->GetVariableLong(VID_MAX_RECORDS
);
2299 wRecOrder
= ((g_nDBSyntax
== DB_SYNTAX_MSSQL
) || (g_nDBSyntax
== DB_SYNTAX_ORACLE
)) ? RECORD_ORDER_REVERSED
: RECORD_ORDER_NORMAL
;
2301 // Prepare confirmation message
2302 msg
.SetCode(CMD_REQUEST_COMPLETED
);
2305 MutexLock(m_mutexSendEvents
);
2306 DB_HANDLE hdb
= DBConnectionPoolAcquireConnection();
2308 // Retrieve events from database
2311 case DB_SYNTAX_MYSQL
:
2312 case DB_SYNTAX_PGSQL
:
2313 case DB_SYNTAX_SQLITE
:
2315 hTempResult
= DBSelect(hdb
, _T("SELECT count(*) FROM event_log"));
2316 if (hTempResult
!= NULL
)
2318 if (DBGetNumRows(hTempResult
) > 0)
2320 dwNumRows
= DBGetFieldULong(hTempResult
, 0, 0);
2322 DBFreeResult(hTempResult
);
2324 _sntprintf(szQuery
, 1024,
2325 _T("SELECT event_id,event_code,event_timestamp,event_source,")
2326 _T("event_severity,event_message,user_tag FROM event_log ")
2327 _T("ORDER BY event_id LIMIT %u OFFSET %u"),
2328 dwMaxRecords
, dwNumRows
- min(dwNumRows
, dwMaxRecords
));
2330 case DB_SYNTAX_MSSQL
:
2331 _sntprintf(szQuery
, 1024,
2332 _T("SELECT TOP %u event_id,event_code,event_timestamp,event_source,")
2333 _T("event_severity,event_message,user_tag FROM event_log ")
2334 _T("ORDER BY event_id DESC"), dwMaxRecords
);
2336 case DB_SYNTAX_ORACLE
:
2337 _sntprintf(szQuery
, 1024,
2338 _T("SELECT event_id,event_code,event_timestamp,event_source,")
2339 _T("event_severity,event_message,user_tag FROM event_log ")
2340 _T("WHERE ROWNUM <= %u ORDER BY event_id DESC"), dwMaxRecords
);
2343 _sntprintf(szQuery
, 1024,
2344 _T("SELECT event_id,event_code,event_timestamp,event_source,")
2345 _T("event_severity,event_message,user_tag FROM event_log ")
2346 _T("ORDER BY event_id DESC FETCH FIRST %u ROWS ONLY"), dwMaxRecords
);
2352 hResult
= DBAsyncSelect(hdb
, szQuery
);
2353 if (hResult
!= NULL
)
2355 msg
.SetVariable(VID_RCC
, RCC_SUCCESS
);
2357 msg
.deleteAllVariables();
2358 msg
.SetCode(CMD_EVENTLOG_RECORDS
);
2360 for(dwId
= VID_EVENTLOG_MSG_BASE
, dwNumRows
= 0; DBFetch(hResult
); dwNumRows
++)
2362 if (dwNumRows
== 10)
2364 msg
.SetVariable(VID_NUM_RECORDS
, dwNumRows
);
2365 msg
.SetVariable(VID_RECORDS_ORDER
, wRecOrder
);
2367 msg
.deleteAllVariables();
2369 dwId
= VID_EVENTLOG_MSG_BASE
;
2371 msg
.SetVariable(dwId
++, DBGetFieldAsyncUInt64(hResult
, 0));
2372 msg
.SetVariable(dwId
++, DBGetFieldAsyncULong(hResult
, 1));
2373 msg
.SetVariable(dwId
++, DBGetFieldAsyncULong(hResult
, 2));
2374 msg
.SetVariable(dwId
++, DBGetFieldAsyncULong(hResult
, 3));
2375 msg
.SetVariable(dwId
++, (WORD
)DBGetFieldAsyncLong(hResult
, 4));
2376 DBGetFieldAsync(hResult
, 5, szBuffer
, 1024);
2377 msg
.SetVariable(dwId
++, szBuffer
);
2378 DBGetFieldAsync(hResult
, 6, szBuffer
, 1024);
2379 msg
.SetVariable(dwId
++, szBuffer
);
2380 msg
.SetVariable(dwId
++, (UINT32
)0); // Do not send parameters
2382 DBFreeAsyncResult(hResult
);
2384 // Send remaining records with End-Of-Sequence notification
2385 msg
.SetVariable(VID_NUM_RECORDS
, dwNumRows
);
2386 msg
.SetVariable(VID_RECORDS_ORDER
, wRecOrder
);
2387 msg
.setEndOfSequence();
2392 msg
.SetVariable(VID_RCC
, RCC_DB_FAILURE
);
2396 DBConnectionPoolReleaseConnection(hdb
);
2397 MutexUnlock(m_mutexSendEvents
);
2401 * Send all configuration variables to client
2403 void ClientSession::sendAllConfigVars(UINT32 dwRqId
)
2405 UINT32 i
, dwId
, dwNumRecords
;
2408 TCHAR szBuffer
[MAX_DB_STRING
];
2411 msg
.SetCode(CMD_REQUEST_COMPLETED
);
2414 // Check user rights
2415 if ((m_dwUserId
== 0) || (m_dwSystemAccess
& SYSTEM_ACCESS_SERVER_CONFIG
))
2417 // Retrieve configuration variables from database
2418 hResult
= DBSelect(g_hCoreDB
, _T("SELECT var_name,var_value,need_server_restart FROM config WHERE is_visible=1"));
2419 if (hResult
!= NULL
)
2421 // Send events, one per message
2422 dwNumRecords
= DBGetNumRows(hResult
);
2423 msg
.SetVariable(VID_NUM_VARIABLES
, dwNumRecords
);
2424 for(i
= 0, dwId
= VID_VARLIST_BASE
; i
< dwNumRecords
; i
++)
2426 msg
.SetVariable(dwId
++, DBGetField(hResult
, i
, 0, szBuffer
, MAX_DB_STRING
));
2427 DBGetField(hResult
, i
, 1, szBuffer
, MAX_DB_STRING
);
2428 DecodeSQLString(szBuffer
);
2429 msg
.SetVariable(dwId
++, szBuffer
);
2430 msg
.SetVariable(dwId
++, (WORD
)DBGetFieldLong(hResult
, i
, 2));
2432 DBFreeResult(hResult
);
2434 msg
.SetVariable(VID_RCC
, RCC_SUCCESS
);
2438 msg
.SetVariable(VID_RCC
, RCC_ACCESS_DENIED
);
2446 * Set configuration variable's value
2448 void ClientSession::setConfigVariable(CSCPMessage
*pRequest
)
2451 TCHAR szName
[MAX_OBJECT_NAME
], szValue
[MAX_DB_STRING
];
2453 // Prepare response message
2454 msg
.SetCode(CMD_REQUEST_COMPLETED
);
2455 msg
.SetId(pRequest
->GetId());
2457 // Check user rights
2458 if ((m_dwUserId
== 0) || (m_dwSystemAccess
& SYSTEM_ACCESS_SERVER_CONFIG
))
2460 pRequest
->GetVariableStr(VID_NAME
, szName
, MAX_OBJECT_NAME
);
2461 pRequest
->GetVariableStr(VID_VALUE
, szValue
, MAX_DB_STRING
);
2462 if (ConfigWriteStr(szName
, szValue
, TRUE
))
2464 msg
.SetVariable(VID_RCC
, RCC_SUCCESS
);
2465 WriteAuditLog(AUDIT_SYSCFG
, TRUE
, m_dwUserId
, m_workstation
, 0,
2466 _T("Server configuration variable \"%s\" set to \"%s\""), szName
, szValue
);
2470 msg
.SetVariable(VID_RCC
, RCC_DB_FAILURE
);
2475 msg
.SetVariable(VID_RCC
, RCC_ACCESS_DENIED
);
2483 * Delete configuration variable
2485 void ClientSession::deleteConfigVariable(CSCPMessage
*pRequest
)
2489 // Prepare response message
2490 msg
.SetCode(CMD_REQUEST_COMPLETED
);
2491 msg
.SetId(pRequest
->GetId());
2493 // Check user rights
2494 if ((m_dwUserId
== 0) || (m_dwSystemAccess
& SYSTEM_ACCESS_SERVER_CONFIG
))
2496 TCHAR name
[MAX_OBJECT_NAME
];
2497 pRequest
->GetVariableStr(VID_NAME
, name
, MAX_OBJECT_NAME
);
2498 if (ConfigDelete(name
))
2500 msg
.SetVariable(VID_RCC
, RCC_SUCCESS
);
2501 WriteAuditLog(AUDIT_SYSCFG
, TRUE
, m_dwUserId
, m_workstation
, 0, _T("Server configuration variable \"%s\" deleted"), name
);
2505 msg
.SetVariable(VID_RCC
, RCC_DB_FAILURE
);
2510 msg
.SetVariable(VID_RCC
, RCC_ACCESS_DENIED
);
2518 * Set configuration clob
2520 void ClientSession::setConfigCLOB(CSCPMessage
*pRequest
)
2523 TCHAR name
[MAX_OBJECT_NAME
], *value
;
2525 msg
.SetId(pRequest
->GetId());
2526 msg
.SetCode(CMD_REQUEST_COMPLETED
);
2528 if (m_dwSystemAccess
& SYSTEM_ACCESS_SERVER_CONFIG
)
2530 pRequest
->GetVariableStr(VID_NAME
, name
, MAX_OBJECT_NAME
);
2531 value
= pRequest
->GetVariableStr(VID_VALUE
);
2534 if (ConfigWriteCLOB(name
, value
, TRUE
))
2536 msg
.SetVariable(VID_RCC
, RCC_SUCCESS
);
2537 WriteAuditLog(AUDIT_SYSCFG
, TRUE
, m_dwUserId
, m_workstation
, 0,
2538 _T("Server configuration variable \"%s\" set to \"%s\""), name
, value
);
2543 msg
.SetVariable(VID_RCC
, RCC_DB_FAILURE
);
2548 msg
.SetVariable(VID_RCC
, RCC_INVALID_REQUEST
);
2553 msg
.SetVariable(VID_RCC
, RCC_ACCESS_DENIED
);
2560 * Get value of configuration clob
2562 void ClientSession::getConfigCLOB(CSCPMessage
*pRequest
)
2565 TCHAR name
[MAX_OBJECT_NAME
], *value
;
2567 msg
.SetId(pRequest
->GetId());
2568 msg
.SetCode(CMD_REQUEST_COMPLETED
);
2570 if (m_dwSystemAccess
& SYSTEM_ACCESS_SERVER_CONFIG
)
2572 pRequest
->GetVariableStr(VID_NAME
, name
, MAX_OBJECT_NAME
);
2573 value
= ConfigReadCLOB(name
, NULL
);
2576 msg
.SetVariable(VID_VALUE
, value
);
2577 msg
.SetVariable(VID_RCC
, RCC_SUCCESS
);
2582 msg
.SetVariable(VID_RCC
, RCC_UNKNOWN_VARIABLE
);
2587 msg
.SetVariable(VID_RCC
, RCC_ACCESS_DENIED
);
2596 void ClientSession::kill()
2598 // We shutdown socket connection, which will cause
2599 // read thread to stop, and other threads will follow
2600 shutdown(m_hSocket
, 2);
2604 * Handler for new events
2606 void ClientSession::onNewEvent(Event
*pEvent
)
2608 UPDATE_INFO
*pUpdate
;
2611 if (isAuthenticated() && (m_dwActiveChannels
& NXC_CHANNEL_EVENTS
))
2613 pUpdate
= (UPDATE_INFO
*)malloc(sizeof(UPDATE_INFO
));
2614 pUpdate
->dwCategory
= INFO_CAT_EVENT
;
2615 msg
= new CSCPMessage
;
2616 msg
->SetCode(CMD_EVENTLOG_RECORDS
);
2617 pEvent
->prepareMessage(msg
);
2618 pUpdate
->pData
= msg
;
2619 m_pUpdateQueue
->Put(pUpdate
);
2624 * Handler for object changes
2626 void ClientSession::onObjectChange(NetObj
*object
)
2628 UPDATE_INFO
*pUpdate
;
2630 if (isAuthenticated() && (m_dwActiveChannels
& NXC_CHANNEL_OBJECTS
))
2631 if (object
->isDeleted() || object
->checkAccessRights(m_dwUserId
, OBJECT_ACCESS_READ
))
2633 pUpdate
= (UPDATE_INFO
*)malloc(sizeof(UPDATE_INFO
));
2634 pUpdate
->dwCategory
= INFO_CAT_OBJECT_CHANGE
;
2635 pUpdate
->pData
= object
;
2636 object
->incRefCount();
2637 m_pUpdateQueue
->Put(pUpdate
);
2642 * Send notification message to server
2644 void ClientSession::notify(UINT32 dwCode
, UINT32 dwData
)
2648 msg
.SetCode(CMD_NOTIFY
);
2649 msg
.SetVariable(VID_NOTIFICATION_CODE
, dwCode
);
2650 msg
.SetVariable(VID_NOTIFICATION_DATA
, dwData
);
2657 void ClientSession::modifyObject(CSCPMessage
*pRequest
)
2659 UINT32 dwObjectId
, dwResult
= RCC_SUCCESS
;
2663 // Prepare reply message
2664 msg
.SetCode(CMD_REQUEST_COMPLETED
);
2665 msg
.SetId(pRequest
->GetId());
2667 dwObjectId
= pRequest
->GetVariableLong(VID_OBJECT_ID
);
2668 object
= FindObjectById(dwObjectId
);
2671 if (object
->checkAccessRights(m_dwUserId
, OBJECT_ACCESS_MODIFY
))
2673 // If user attempts to change object's ACL, check
2674 // if he has OBJECT_ACCESS_ACL permission
2675 if (pRequest
->isFieldExist(VID_ACL_SIZE
))
2676 if (!object
->checkAccessRights(m_dwUserId
, OBJECT_ACCESS_ACL
))
2677 dwResult
= RCC_ACCESS_DENIED
;
2679 // If user attempts to rename object, check object's name
2680 if (pRequest
->isFieldExist(VID_OBJECT_NAME
))
2683 pRequest
->GetVariableStr(VID_OBJECT_NAME
, name
, 256);
2684 if (!IsValidObjectName(name
, TRUE
))
2685 dwResult
= RCC_INVALID_OBJECT_NAME
;
2688 // If allowed, change object and set completion code
2689 if (dwResult
== RCC_SUCCESS
)
2691 dwResult
= object
->ModifyFromMessage(pRequest
);
2692 if (dwResult
== RCC_SUCCESS
)
2694 object
->postModify();
2697 msg
.SetVariable(VID_RCC
, dwResult
);
2699 if (dwResult
== RCC_SUCCESS
)
2701 WriteAuditLog(AUDIT_OBJECTS
, TRUE
, m_dwUserId
, m_workstation
, dwObjectId
,
2702 _T("Object %s modified from client"), object
->Name());
2706 WriteAuditLog(AUDIT_OBJECTS
, FALSE
, m_dwUserId
, m_workstation
, dwObjectId
,
2707 _T("Failed to modify object from client - error %d"), dwResult
);
2712 msg
.SetVariable(VID_RCC
, RCC_ACCESS_DENIED
);
2713 WriteAuditLog(AUDIT_OBJECTS
, FALSE
, m_dwUserId
, m_workstation
, dwObjectId
,
2714 _T("Failed to modify object from client - access denied"), dwResult
);
2719 msg
.SetVariable(VID_RCC
, RCC_INVALID_OBJECT_ID
);
2727 * Send users database to client
2729 void ClientSession::sendUserDB(UINT32 dwRqId
)
2732 UserDatabaseObject
**users
;
2735 // Prepare response message
2736 msg
.SetCode(CMD_REQUEST_COMPLETED
);
2738 msg
.SetVariable(VID_RCC
, RCC_SUCCESS
);
2740 msg
.deleteAllVariables();
2742 // Send user database
2743 users
= OpenUserDatabase(&userCount
);
2744 for(i
= 0; i
< userCount
; i
++)
2746 msg
.SetCode((users
[i
]->getId() & GROUP_FLAG
) ? CMD_GROUP_DATA
: CMD_USER_DATA
);
2747 users
[i
]->fillMessage(&msg
);
2749 msg
.deleteAllVariables();
2751 CloseUserDatabase();
2753 // Send end-of-database notification
2754 msg
.SetCode(CMD_USER_DB_EOF
);
2761 void ClientSession::createUser(CSCPMessage
*pRequest
)
2765 // Prepare response message
2766 msg
.SetCode(CMD_REQUEST_COMPLETED
);
2767 msg
.SetId(pRequest
->GetId());
2769 // Check user rights
2770 if (!(m_dwSystemAccess
& SYSTEM_ACCESS_MANAGE_USERS
))
2772 msg
.SetVariable(VID_RCC
, RCC_ACCESS_DENIED
);
2774 else if (!(m_dwFlags
& CSF_USER_DB_LOCKED
))
2776 // User database have to be locked before any
2777 // changes to user database can be made
2778 msg
.SetVariable(VID_RCC
, RCC_OUT_OF_STATE_REQUEST
);
2782 UINT32 dwResult
, dwUserId
;
2784 TCHAR szUserName
[MAX_USER_NAME
];
2786 pRequest
->GetVariableStr(VID_USER_NAME
, szUserName
, MAX_USER_NAME
);
2787 if (IsValidObjectName(szUserName
))
2789 bIsGroup
= pRequest
->GetVariableShort(VID_IS_GROUP
);
2790 dwResult
= CreateNewUser(szUserName
, bIsGroup
, &dwUserId
);
2791 msg
.SetVariable(VID_RCC
, dwResult
);
2792 if (dwResult
== RCC_SUCCESS
)
2794 msg
.SetVariable(VID_USER_ID
, dwUserId
); // Send id of new user to client
2795 WriteAuditLog(AUDIT_SECURITY
, TRUE
, m_dwUserId
, m_workstation
, dwUserId
, _T("%s %s created"), bIsGroup
? _T("Group") : _T("User"), szUserName
);
2800 msg
.SetVariable(VID_RCC
, RCC_INVALID_OBJECT_NAME
);
2809 * Update existing user's data
2811 void ClientSession::updateUser(CSCPMessage
*pRequest
)
2815 // Prepare response message
2816 msg
.SetCode(CMD_REQUEST_COMPLETED
);
2817 msg
.SetId(pRequest
->GetId());
2819 // Check user rights
2820 if (!(m_dwSystemAccess
& SYSTEM_ACCESS_MANAGE_USERS
))
2822 msg
.SetVariable(VID_RCC
, RCC_ACCESS_DENIED
);
2824 else if (!(m_dwFlags
& CSF_USER_DB_LOCKED
))
2826 // User database have to be locked before any
2827 // changes to user database can be made
2828 msg
.SetVariable(VID_RCC
, RCC_OUT_OF_STATE_REQUEST
);
2832 UINT32 result
= ModifyUserDatabaseObject(pRequest
);
2833 if (result
== RCC_SUCCESS
)
2835 TCHAR name
[MAX_DB_STRING
];
2836 UINT32 id
= pRequest
->GetVariableLong(VID_USER_ID
);
2837 ResolveUserId(id
, name
, MAX_DB_STRING
);
2838 WriteAuditLog(AUDIT_SECURITY
, TRUE
, m_dwUserId
, m_workstation
, id
,
2839 _T("%s %s modified"), (id
& GROUP_FLAG
) ? _T("Group") : _T("User"), name
);
2841 msg
.SetVariable(VID_RCC
, result
);
2851 void ClientSession::deleteUser(CSCPMessage
*pRequest
)
2856 // Prepare response message
2857 msg
.SetCode(CMD_REQUEST_COMPLETED
);
2858 msg
.SetId(pRequest
->GetId());
2860 // Check user rights
2861 if (!(m_dwSystemAccess
& SYSTEM_ACCESS_MANAGE_USERS
))
2863 msg
.SetVariable(VID_RCC
, RCC_ACCESS_DENIED
);
2865 else if (!(m_dwFlags
& CSF_USER_DB_LOCKED
))
2867 // User database have to be locked before any
2868 // changes to user database can be made
2869 msg
.SetVariable(VID_RCC
, RCC_OUT_OF_STATE_REQUEST
);
2873 // Get Id of user to be deleted
2874 dwUserId
= pRequest
->GetVariableLong(VID_USER_ID
);
2876 if ((dwUserId
!= 0) && (dwUserId
!= GROUP_EVERYONE
))
2878 if (!IsLoggedIn(dwUserId
))
2880 TCHAR name
[MAX_DB_STRING
];
2881 ResolveUserId(dwUserId
, name
, MAX_DB_STRING
);
2882 UINT32 rcc
= DeleteUserDatabaseObject(dwUserId
);
2883 msg
.SetVariable(VID_RCC
, rcc
);
2884 if(rcc
== RCC_SUCCESS
)
2886 WriteAuditLog(AUDIT_SECURITY
, TRUE
, m_dwUserId
, m_workstation
, dwUserId
,
2887 _T("%s %s [%d] deleted"), (dwUserId
& GROUP_FLAG
) ? _T("Group") : _T("User"), name
, dwUserId
);
2892 // logger in users cannot be deleted
2893 msg
.SetVariable(VID_RCC
, RCC_USER_LOGGED_IN
);
2898 // System administrator account and everyone group cannot be deleted
2899 msg
.SetVariable(VID_RCC
, RCC_ACCESS_DENIED
);
2908 * Lock/unlock user database
2910 void ClientSession::lockUserDB(UINT32 dwRqId
, BOOL bLock
)
2913 TCHAR szBuffer
[256];
2915 // Prepare response message
2916 msg
.SetCode(CMD_REQUEST_COMPLETED
);
2919 if (m_dwSystemAccess
& SYSTEM_ACCESS_MANAGE_USERS
)
2923 if (!LockComponent(CID_USER_DB
, m_dwIndex
, m_szUserName
, NULL
, szBuffer
))
2925 msg
.SetVariable(VID_RCC
, RCC_COMPONENT_LOCKED
);
2926 msg
.SetVariable(VID_LOCKED_BY
, szBuffer
);
2930 m_dwFlags
|= CSF_USER_DB_LOCKED
;
2931 msg
.SetVariable(VID_RCC
, RCC_SUCCESS
);
2936 if (m_dwFlags
& CSF_USER_DB_LOCKED
)
2938 UnlockComponent(CID_USER_DB
);
2939 m_dwFlags
&= ~CSF_USER_DB_LOCKED
;
2941 msg
.SetVariable(VID_RCC
, RCC_SUCCESS
);
2946 // Current user has no rights for user account management
2947 msg
.SetVariable(VID_RCC
, RCC_ACCESS_DENIED
);
2955 * Notify client on user database update
2957 void ClientSession::onUserDBUpdate(int code
, UINT32 id
, UserDatabaseObject
*object
)
2961 if (isAuthenticated())
2963 msg
.SetCode(CMD_USER_DB_UPDATE
);
2965 msg
.SetVariable(VID_UPDATE_TYPE
, (WORD
)code
);
2969 case USER_DB_CREATE
:
2970 case USER_DB_MODIFY
:
2971 object
->fillMessage(&msg
);
2974 msg
.SetVariable(VID_USER_ID
, id
);
2983 * Change management status for the object
2985 void ClientSession::changeObjectMgmtStatus(CSCPMessage
*pRequest
)
2991 // Prepare response message
2992 msg
.SetCode(CMD_REQUEST_COMPLETED
);
2993 msg
.SetId(pRequest
->GetId());
2995 // Get object id and check access rights
2996 dwObjectId
= pRequest
->GetVariableLong(VID_OBJECT_ID
);
2997 object
= FindObjectById(dwObjectId
);
3000 if (object
->checkAccessRights(m_dwUserId
, OBJECT_ACCESS_MODIFY
))
3002 if ((object
->Type() != OBJECT_TEMPLATE
) &&
3003 (object
->Type() != OBJECT_TEMPLATEGROUP
) &&
3004 (object
->Type() != OBJECT_TEMPLATEROOT
))
3006 BOOL bIsManaged
= (BOOL
)pRequest
->GetVariableShort(VID_MGMT_STATUS
);
3007 object
->setMgmtStatus(bIsManaged
);
3008 msg
.SetVariable(VID_RCC
, RCC_SUCCESS
);
3009 WriteAuditLog(AUDIT_OBJECTS
, TRUE
, m_dwUserId
, m_workstation
, object
->Id(),
3010 _T("Object %s set to %s state"), object
->Name(), bIsManaged
? _T("managed") : _T("unmanaged"));
3014 msg
.SetVariable(VID_RCC
, RCC_INCOMPATIBLE_OPERATION
);
3019 msg
.SetVariable(VID_RCC
, RCC_ACCESS_DENIED
);
3024 msg
.SetVariable(VID_RCC
, RCC_INVALID_OBJECT_ID
);
3032 * Set user's password
3034 void ClientSession::setPassword(CSCPMessage
*pRequest
)
3039 // Prepare response message
3040 msg
.SetCode(CMD_REQUEST_COMPLETED
);
3041 msg
.SetId(pRequest
->GetId());
3043 dwUserId
= pRequest
->GetVariableLong(VID_USER_ID
);
3045 if (((m_dwSystemAccess
& SYSTEM_ACCESS_MANAGE_USERS
) &&
3046 !((dwUserId
== 0) && (m_dwUserId
!= 0))) || // Only administrator can change password for UID 0
3047 (dwUserId
== m_dwUserId
)) // User can change password for itself
3050 TCHAR newPassword
[1024], oldPassword
[1024];
3053 pRequest
->GetVariableStr(VID_PASSWORD
, newPassword
, 256);
3054 if (pRequest
->isFieldExist(VID_OLD_PASSWORD
))
3055 pRequest
->GetVariableStr(VID_OLD_PASSWORD
, oldPassword
, 256);
3057 pRequest
->GetVariableStrUTF8(VID_PASSWORD
, newPassword
, 1024);
3058 if (pRequest
->isFieldExist(VID_OLD_PASSWORD
))
3059 pRequest
->GetVariableStrUTF8(VID_OLD_PASSWORD
, oldPassword
, 1024);
3063 dwResult
= SetUserPassword(dwUserId
, newPassword
, oldPassword
, dwUserId
== m_dwUserId
);
3064 msg
.SetVariable(VID_RCC
, dwResult
);
3066 if (dwResult
== RCC_SUCCESS
)
3068 TCHAR userName
[MAX_DB_STRING
];
3069 ResolveUserId(dwUserId
, userName
, MAX_DB_STRING
);
3070 WriteAuditLog(AUDIT_SECURITY
, TRUE
, m_dwUserId
, m_workstation
, 0, _T("Changed password for user %s"), userName
);
3075 // Current user has no rights to change password for specific user
3076 msg
.SetVariable(VID_RCC
, RCC_ACCESS_DENIED
);
3084 * Send node's DCIs to client and lock data collection settings
3086 void ClientSession::openNodeDCIList(CSCPMessage
*pRequest
)
3091 BOOL bSuccess
= FALSE
;
3092 TCHAR szLockInfo
[MAX_SESSION_NAME
];
3094 // Prepare response message
3095 msg
.SetCode(CMD_REQUEST_COMPLETED
);
3096 msg
.SetId(pRequest
->GetId());
3098 // Get node id and check object class and access rights
3099 dwObjectId
= pRequest
->GetVariableLong(VID_OBJECT_ID
);
3100 object
= FindObjectById(dwObjectId
);
3103 if ((object
->Type() == OBJECT_NODE
) ||
3104 (object
->Type() == OBJECT_CLUSTER
) ||
3105 (object
->Type() == OBJECT_MOBILEDEVICE
) ||
3106 (object
->Type() == OBJECT_TEMPLATE
))
3108 if (object
->checkAccessRights(m_dwUserId
, OBJECT_ACCESS_READ
))
3110 // Try to lock DCI list
3111 if (((Template
*)object
)->lockDCIList(m_dwIndex
, m_szUserName
, szLockInfo
))
3114 msg
.SetVariable(VID_RCC
, RCC_SUCCESS
);
3116 // Modify list of open nodes DCI lists
3117 m_pOpenDCIList
= (UINT32
*)realloc(m_pOpenDCIList
, sizeof(UINT32
) * (m_dwOpenDCIListSize
+ 1));
3118 m_pOpenDCIList
[m_dwOpenDCIListSize
] = dwObjectId
;
3119 m_dwOpenDCIListSize
++;
3123 msg
.SetVariable(VID_RCC
, RCC_COMPONENT_LOCKED
);
3124 msg
.SetVariable(VID_LOCKED_BY
, szLockInfo
);
3129 msg
.SetVariable(VID_RCC
, RCC_ACCESS_DENIED
);
3134 msg
.SetVariable(VID_RCC
, RCC_INVALID_OBJECT_ID
);
3139 msg
.SetVariable(VID_RCC
, RCC_INVALID_OBJECT_ID
);
3145 // If DCI list was successfully locked, send it to client
3147 ((Template
*)object
)->sendItemsToClient(this, pRequest
->GetId());
3151 * Unlock node's data collection settings
3153 void ClientSession::closeNodeDCIList(CSCPMessage
*pRequest
)
3159 // Prepare response message
3160 msg
.SetCode(CMD_REQUEST_COMPLETED
);
3161 msg
.SetId(pRequest
->GetId());
3163 // Get node id and check object class and access rights
3164 dwObjectId
= pRequest
->GetVariableLong(VID_OBJECT_ID
);
3165 object
= FindObjectById(dwObjectId
);
3168 if ((object
->Type() == OBJECT_NODE
) ||
3169 (object
->Type() == OBJECT_CLUSTER
) ||
3170 (object
->Type() == OBJECT_MOBILEDEVICE
) ||
3171 (object
->Type() == OBJECT_TEMPLATE
))
3173 if (object
->checkAccessRights(m_dwUserId
, OBJECT_ACCESS_READ
))
3177 // Try to unlock DCI list
3178 bSuccess
= ((Template
*)object
)->unlockDCIList(m_dwIndex
);
3179 msg
.SetVariable(VID_RCC
, bSuccess
? RCC_SUCCESS
: RCC_OUT_OF_STATE_REQUEST
);
3181 // Modify list of open nodes DCI lists
3186 for(i
= 0; i
< m_dwOpenDCIListSize
; i
++)
3187 if (m_pOpenDCIList
[i
] == dwObjectId
)
3189 m_dwOpenDCIListSize
--;
3190 memmove(&m_pOpenDCIList
[i
], &m_pOpenDCIList
[i
+ 1], sizeof(UINT32
) * (m_dwOpenDCIListSize
- i
));
3195 // Queue template update
3196 if ((object
->Type() == OBJECT_TEMPLATE
) || (object
->Type() == OBJECT_CLUSTER
))
3197 ((Template
*)object
)->queueUpdate();
3201 msg
.SetVariable(VID_RCC
, RCC_ACCESS_DENIED
);
3206 msg
.SetVariable(VID_RCC
, RCC_INVALID_OBJECT_ID
);
3211 msg
.SetVariable(VID_RCC
, RCC_INVALID_OBJECT_ID
);
3219 * Create, modify, or delete data collection item for node
3221 void ClientSession::modifyNodeDCI(CSCPMessage
*pRequest
)
3227 // Prepare response message
3228 msg
.SetCode(CMD_REQUEST_COMPLETED
);
3229 msg
.SetId(pRequest
->GetId());
3231 // Get node id and check object class and access rights
3232 dwObjectId
= pRequest
->GetVariableLong(VID_OBJECT_ID
);
3233 object
= FindObjectById(dwObjectId
);
3236 if ((object
->Type() == OBJECT_NODE
) ||
3237 (object
->Type() == OBJECT_CLUSTER
) ||
3238 (object
->Type() == OBJECT_MOBILEDEVICE
) ||
3239 (object
->Type() == OBJECT_TEMPLATE
))
3241 if (((Template
*)object
)->isLockedBySession(m_dwIndex
))
3243 if (object
->checkAccessRights(m_dwUserId
, OBJECT_ACCESS_MODIFY
))
3245 UINT32 i
, dwItemId
, dwNumMaps
, *pdwMapId
, *pdwMapIndex
;
3247 BOOL bSuccess
= FALSE
;
3249 int dcObjectType
= (int)pRequest
->GetVariableShort(VID_DCOBJECT_TYPE
);
3250 switch(pRequest
->GetCode())
3252 case CMD_CREATE_NEW_DCI
:
3254 switch(dcObjectType
)
3257 dcObject
= new DCItem(CreateUniqueId(IDG_ITEM
), _T("no name"), DS_INTERNAL
, DCI_DT_INT
,
3258 ConfigReadInt(_T("DefaultDCIPollingInterval"), 60),
3259 ConfigReadInt(_T("DefaultDCIRetentionTime"), 30), (Node
*)object
);
3261 case DCO_TYPE_TABLE
:
3262 dcObject
= new DCTable(CreateUniqueId(IDG_ITEM
), _T("no name"), DS_INTERNAL
,
3263 ConfigReadInt(_T("DefaultDCIPollingInterval"), 60),
3264 ConfigReadInt(_T("DefaultDCIRetentionTime"), 30), (Node
*)object
);
3270 if (dcObject
!= NULL
)
3272 dcObject
->setStatus(ITEM_STATUS_DISABLED
, false);
3273 if ((bSuccess
= ((Template
*)object
)->addDCObject(dcObject
)))
3275 msg
.SetVariable(VID_RCC
, RCC_SUCCESS
);
3276 // Return new item id to client
3277 msg
.SetVariable(VID_DCI_ID
, dcObject
->getId());
3279 else // Unable to add item to node
3282 msg
.SetVariable(VID_RCC
, RCC_DUPLICATE_DCI
);
3287 msg
.SetVariable(VID_RCC
, RCC_INVALID_ARGUMENT
);
3290 case CMD_MODIFY_NODE_DCI
:
3291 dwItemId
= pRequest
->GetVariableLong(VID_DCI_ID
);
3292 bSuccess
= ((Template
*)object
)->updateDCObject(dwItemId
, pRequest
, &dwNumMaps
, &pdwMapIndex
, &pdwMapId
);
3295 msg
.SetVariable(VID_RCC
, RCC_SUCCESS
);
3297 // Send index to id mapping for newly created thresholds to client
3298 if (dcObjectType
== DCO_TYPE_ITEM
)
3300 msg
.SetVariable(VID_DCI_NUM_MAPS
, dwNumMaps
);
3301 for(i
= 0; i
< dwNumMaps
; i
++)
3303 pdwMapId
[i
] = htonl(pdwMapId
[i
]);
3304 pdwMapIndex
[i
] = htonl(pdwMapIndex
[i
]);
3306 msg
.SetVariable(VID_DCI_MAP_IDS
, (BYTE
*)pdwMapId
, sizeof(UINT32
) * dwNumMaps
);
3307 msg
.SetVariable(VID_DCI_MAP_INDEXES
, (BYTE
*)pdwMapIndex
, sizeof(UINT32
) * dwNumMaps
);
3308 safe_free(pdwMapId
);
3309 safe_free(pdwMapIndex
);
3314 msg
.SetVariable(VID_RCC
, RCC_INVALID_DCI_ID
);
3317 case CMD_DELETE_NODE_DCI
:
3318 dwItemId
= pRequest
->GetVariableLong(VID_DCI_ID
);
3319 bSuccess
= ((Template
*)object
)->deleteDCObject(dwItemId
, true);
3320 msg
.SetVariable(VID_RCC
, bSuccess
? RCC_SUCCESS
: RCC_INVALID_DCI_ID
);
3324 ((Template
*)object
)->setDCIModificationFlag();
3326 else // User doesn't have MODIFY rights on object
3328 msg
.SetVariable(VID_RCC
, RCC_ACCESS_DENIED
);
3331 else // Nodes DCI list not locked by this session
3333 msg
.SetVariable(VID_RCC
, RCC_OUT_OF_STATE_REQUEST
);
3336 else // Object is not a node
3338 msg
.SetVariable(VID_RCC
, RCC_INVALID_OBJECT_ID
);
3341 else // No object with given ID
3343 msg
.SetVariable(VID_RCC
, RCC_INVALID_OBJECT_ID
);
3351 * Change status for one or more DCIs
3353 void ClientSession::changeDCIStatus(CSCPMessage
*pRequest
)
3358 // Prepare response message
3359 msg
.SetCode(CMD_REQUEST_COMPLETED
);
3360 msg
.SetId(pRequest
->GetId());
3362 // Get node id and check object class and access rights
3363 object
= FindObjectById(pRequest
->GetVariableLong(VID_OBJECT_ID
));
3366 if ((object
->Type() == OBJECT_NODE
) ||
3367 (object
->Type() == OBJECT_CLUSTER
) ||
3368 (object
->Type() == OBJECT_MOBILEDEVICE
) ||
3369 (object
->Type() == OBJECT_TEMPLATE
))
3371 if (((Template
*)object
)->isLockedBySession(m_dwIndex
))
3373 if (object
->checkAccessRights(m_dwUserId
, OBJECT_ACCESS_MODIFY
))
3375 UINT32 dwNumItems
, *pdwItemList
;
3378 iStatus
= pRequest
->GetVariableShort(VID_DCI_STATUS
);
3379 dwNumItems
= pRequest
->GetVariableLong(VID_NUM_ITEMS
);
3380 pdwItemList
= (UINT32
*)malloc(sizeof(UINT32
) * dwNumItems
);
3381 pRequest
->getFieldAsInt32Array(VID_ITEM_LIST
, dwNumItems
, pdwItemList
);
3382 if (((Template
*)object
)->setItemStatus(dwNumItems
, pdwItemList
, iStatus
))
3383 msg
.SetVariable(VID_RCC
, RCC_SUCCESS
);
3385 msg
.SetVariable(VID_RCC
, RCC_INVALID_DCI_ID
);
3388 else // User doesn't have MODIFY rights on object
3390 msg
.SetVariable(VID_RCC
, RCC_ACCESS_DENIED
);
3393 else // Nodes DCI list not locked by this session
3395 msg
.SetVariable(VID_RCC
, RCC_OUT_OF_STATE_REQUEST
);
3398 else // Object is not a node
3400 msg
.SetVariable(VID_RCC
, RCC_INCOMPATIBLE_OPERATION
);
3403 else // No object with given ID
3405 msg
.SetVariable(VID_RCC
, RCC_INVALID_OBJECT_ID
);
3413 * Clear all collected data for DCI
3415 void ClientSession::clearDCIData(CSCPMessage
*pRequest
)
3421 // Prepare response message
3422 msg
.SetCode(CMD_REQUEST_COMPLETED
);
3423 msg
.SetId(pRequest
->GetId());
3425 // Get node id and check object class and access rights
3426 object
= FindObjectById(pRequest
->GetVariableLong(VID_OBJECT_ID
));
3429 if ((object
->Type() == OBJECT_NODE
) || (object
->Type() == OBJECT_MOBILEDEVICE
) || (object
->Type() == OBJECT_CLUSTER
))
3431 if (object
->checkAccessRights(m_dwUserId
, OBJECT_ACCESS_DELETE
))
3433 dwItemId
= pRequest
->GetVariableLong(VID_DCI_ID
);
3434 debugPrintf(4, _T("ClearDCIData: request for DCI %d at node %d"), dwItemId
, object
->Id());
3435 DCObject
*dci
= ((Template
*)object
)->getDCObjectById(dwItemId
);
3438 msg
.SetVariable(VID_RCC
, dci
->deleteAllData() ? RCC_SUCCESS
: RCC_DB_FAILURE
);
3439 debugPrintf(4, _T("ClearDCIData: DCI %d at node %d"), dwItemId
, object
->Id());
3443 msg
.SetVariable(VID_RCC
, RCC_INVALID_DCI_ID
);
3444 debugPrintf(4, _T("ClearDCIData: DCI %d at node %d not found"), dwItemId
, object
->Id());
3447 else // User doesn't have DELETE rights on object
3449 msg
.SetVariable(VID_RCC
, RCC_ACCESS_DENIED
);
3452 else // Object is not a node
3454 msg
.SetVariable(VID_RCC
, RCC_INCOMPATIBLE_OPERATION
);
3457 else // No object with given ID
3459 msg
.SetVariable(VID_RCC
, RCC_INVALID_OBJECT_ID
);
3467 * Copy or move DCI from one node or template to another
3469 void ClientSession::copyDCI(CSCPMessage
*pRequest
)
3472 NetObj
*pSource
, *pDestination
;
3473 TCHAR szLockInfo
[MAX_SESSION_NAME
];
3476 // Prepare response message
3477 msg
.SetCode(CMD_REQUEST_COMPLETED
);
3478 msg
.SetId(pRequest
->GetId());
3480 // Get source and destination
3481 pSource
= FindObjectById(pRequest
->GetVariableLong(VID_SOURCE_OBJECT_ID
));
3482 pDestination
= FindObjectById(pRequest
->GetVariableLong(VID_DESTINATION_OBJECT_ID
));
3483 if ((pSource
!= NULL
) && (pDestination
!= NULL
))
3485 // Check object types
3486 if (((pSource
->Type() == OBJECT_NODE
) || (pSource
->Type() == OBJECT_MOBILEDEVICE
) || (pSource
->Type() == OBJECT_TEMPLATE
) || (pSource
->Type() == OBJECT_CLUSTER
)) &&
3487 ((pDestination
->Type() == OBJECT_NODE
) || (pDestination
->Type() == OBJECT_MOBILEDEVICE
) || (pDestination
->Type() == OBJECT_TEMPLATE
) || (pDestination
->Type() == OBJECT_CLUSTER
)))
3489 if (((Template
*)pSource
)->isLockedBySession(m_dwIndex
))
3491 bMove
= pRequest
->GetVariableShort(VID_MOVE_FLAG
);
3492 // Check access rights
3493 if ((pSource
->checkAccessRights(m_dwUserId
, bMove
? (OBJECT_ACCESS_READ
| OBJECT_ACCESS_MODIFY
) : OBJECT_ACCESS_READ
)) &&
3494 (pDestination
->checkAccessRights(m_dwUserId
, OBJECT_ACCESS_MODIFY
)))
3496 // Attempt to lock destination's DCI list
3497 if ((pDestination
->Id() == pSource
->Id()) ||
3498 (((Template
*)pDestination
)->lockDCIList(m_dwIndex
, m_szUserName
, szLockInfo
)))
3500 UINT32 i
, *pdwItemList
, dwNumItems
;
3501 const DCObject
*pSrcItem
;
3505 // Get list of items to be copied/moved
3506 dwNumItems
= pRequest
->GetVariableLong(VID_NUM_ITEMS
);
3507 pdwItemList
= (UINT32
*)malloc(sizeof(UINT32
) * dwNumItems
);
3508 pRequest
->getFieldAsInt32Array(VID_ITEM_LIST
, dwNumItems
, pdwItemList
);
3511 for(i
= 0; i
< dwNumItems
; i
++)
3513 pSrcItem
= ((Template
*)pSource
)->getDCObjectById(pdwItemList
[i
]);
3514 if (pSrcItem
!= NULL
)
3516 switch(pSrcItem
->getType())
3519 pDstItem
= new DCItem((DCItem
*)pSrcItem
);
3521 case DCO_TYPE_TABLE
:
3522 pDstItem
= new DCTable((DCTable
*)pSrcItem
);
3528 if (pDstItem
!= NULL
)
3530 pDstItem
->setTemplateId(0, 0);
3531 pDstItem
->changeBinding(CreateUniqueId(IDG_ITEM
),
3532 (Template
*)pDestination
, FALSE
);
3533 if (((Template
*)pDestination
)->addDCObject(pDstItem
))
3537 // Delete original item
3538 if (!((Template
*)pSource
)->deleteDCObject(pdwItemList
[i
], TRUE
))
3552 DbgPrintf(2, _T("INTERNAL ERROR: ClientSession::CopyDCI(): unknown DCO type %d"), pSrcItem
->getType());
3564 if (pDestination
->Id() != pSource
->Id())
3565 ((Template
*)pDestination
)->unlockDCIList(m_dwIndex
);
3566 msg
.SetVariable(VID_RCC
, (iErrors
== 0) ? RCC_SUCCESS
: RCC_DCI_COPY_ERRORS
);
3568 // Queue template update
3569 if (pDestination
->Type() == OBJECT_TEMPLATE
)
3570 ((Template
*)pDestination
)->queueUpdate();
3572 else // Destination's DCI list already locked by someone else
3574 msg
.SetVariable(VID_RCC
, RCC_COMPONENT_LOCKED
);
3575 msg
.SetVariable(VID_LOCKED_BY
, szLockInfo
);
3578 else // User doesn't have enough rights on object(s)
3580 msg
.SetVariable(VID_RCC
, RCC_ACCESS_DENIED
);
3583 else // Source node DCI list not locked by this session
3585 msg
.SetVariable(VID_RCC
, RCC_OUT_OF_STATE_REQUEST
);
3588 else // Object(s) is not a node
3590 msg
.SetVariable(VID_RCC
, RCC_INVALID_OBJECT_ID
);
3593 else // No object(s) with given ID
3595 msg
.SetVariable(VID_RCC
, RCC_INVALID_OBJECT_ID
);
3603 * Send list of thresholds for DCI
3605 void ClientSession::sendDCIThresholds(CSCPMessage
*request
)
3610 // Prepare response message
3611 msg
.SetCode(CMD_REQUEST_COMPLETED
);
3612 msg
.SetId(request
->GetId());
3614 // Get node id and check object class and access rights
3615 object
= FindObjectById(request
->GetVariableLong(VID_OBJECT_ID
));
3618 if (object
->checkAccessRights(m_dwUserId
, OBJECT_ACCESS_READ
))
3620 if ((object
->Type() == OBJECT_NODE
) || (object
->Type() == OBJECT_MOBILEDEVICE
) || (object
->Type() == OBJECT_CLUSTER
))
3622 DCObject
*dci
= ((Template
*)object
)->getDCObjectById(request
->GetVariableLong(VID_DCI_ID
));
3623 if ((dci
!= NULL
) && (dci
->getType() == DCO_TYPE_ITEM
))
3625 ((DCItem
*)dci
)->fillMessageWithThresholds(&msg
);
3626 msg
.SetVariable(VID_RCC
, RCC_SUCCESS
);
3630 msg
.SetVariable(VID_RCC
, RCC_INVALID_DCI_ID
);
3635 msg
.SetVariable(VID_RCC
, RCC_INCOMPATIBLE_OPERATION
);
3640 msg
.SetVariable(VID_RCC
, RCC_ACCESS_DENIED
);
3643 else // No object with given ID
3645 msg
.SetVariable(VID_RCC
, RCC_INVALID_OBJECT_ID
);
3653 * Prepare statement for reading data from idata table
3655 static DB_STATEMENT
PrepareIDataSelect(DB_HANDLE hdb
, UINT32 nodeId
, UINT32 maxRows
, const TCHAR
*condition
)
3661 case DB_SYNTAX_MSSQL
:
3662 _sntprintf(query
, 512, _T("SELECT TOP %d idata_timestamp,idata_value FROM idata_%d WHERE item_id=?%s ORDER BY idata_timestamp DESC"),
3663 (int)maxRows
, (int)nodeId
, condition
);
3665 case DB_SYNTAX_ORACLE
:
3666 _sntprintf(query
, 512, _T("SELECT * FROM (SELECT idata_timestamp,idata_value FROM idata_%d WHERE item_id=?%s ORDER BY idata_timestamp DESC) WHERE ROWNUM<=%d"),
3667 (int)nodeId
, condition
, (int)maxRows
);
3669 case DB_SYNTAX_MYSQL
:
3670 case DB_SYNTAX_PGSQL
:
3671 case DB_SYNTAX_SQLITE
:
3672 _sntprintf(query
, 512, _T("SELECT idata_timestamp,idata_value FROM idata_%d WHERE item_id=?%s ORDER BY idata_timestamp DESC LIMIT %d"),
3673 (int)nodeId
, condition
, (int)maxRows
);
3676 _sntprintf(query
, 512, _T("SELECT idata_timestamp,idata_value FROM idata_%d WHERE item_id=?%s ORDER BY idata_timestamp DESC FETCH FIRST %d ROWS ONLY"),
3677 (int)nodeId
, condition
, (int)maxRows
);
3680 DbgPrintf(1, _T(">>> INTERNAL ERROR: unsupported database in PrepareIDataSelect"));
3681 return NULL
; // Unsupported database
3683 return DBPrepare(hdb
, query
);
3687 * Prepare statement for reading data from tda