2 ** NetXMS - Network Management System
3 ** Copyright (C) 2003-2016 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>
41 #define min(a,b) ((a) < (b) ? (a) : (b))
44 // WARNING! this hack works only for d2i_X509(); be carefull when adding new code
48 #if OPENSSL_VERSION_NUMBER >= 0x0090800fL
49 # define OPENSSL_CONST const
51 # define OPENSSL_CONST
61 #define MAX_MSG_SIZE 4194304
66 extern Queue g_nodePollerQueue
;
67 extern Queue g_dataCollectionQueue
;
68 extern Queue g_dciCacheLoaderQueue
;
70 void UnregisterClientSession(int id
);
71 void ResetDiscoveryPoller();
72 NXCPMessage
*ForwardMessageToReportingServer(NXCPMessage
*request
, ClientSession
*session
);
73 void RemovePendingFileTransferRequests(ClientSession
*session
);
74 bool UpdateAddressListFromMessage(NXCPMessage
*msg
);
77 * Node poller start data
81 ClientSession
*pSession
;
88 * Additional processing thread start data
92 ClientSession
*pSession
;
94 } PROCTHREAD_START_DATA
;
103 } LIBRARY_IMAGE_UPDATE_INFO
;
106 * Callback to delete agent connections for loading files in destructor
108 static void DeleteCallback(NetObj
* obj
, void *data
)
110 ((AgentConnection
*)obj
)->decRefCount();
114 * Callback for sending image library update notifications
116 static void ImageLibraryUpdateCallback(ClientSession
*pSession
, void *pArg
)
118 pSession
->onLibraryImageChange((uuid_t
*)pArg
, false);
122 * Callback for sending image library delete notifications
124 static void ImageLibraryDeleteCallback(ClientSession
*pSession
, void *pArg
)
126 pSession
->onLibraryImageChange((uuid_t
*)pArg
, true);
130 * Additional message processing thread starters
132 #define CALL_IN_NEW_THREAD(func, msg) \
134 PROCTHREAD_START_DATA *pData = (PROCTHREAD_START_DATA *)malloc(sizeof(PROCTHREAD_START_DATA)); \
135 pData->pSession = this; \
137 msg = NULL; /* prevent deletion by main processing thread*/ \
138 InterlockedIncrement(&m_refCount); \
139 ThreadPoolExecute(g_mainThreadPool, ThreadStarter_##func, pData); \
142 #define DEFINE_THREAD_STARTER(func) \
143 void ClientSession::ThreadStarter_##func(void *pArg) \
145 ((PROCTHREAD_START_DATA *)pArg)->pSession->debugPrintf(6, _T("Method ") _T(#func) _T(" called on background thread")); \
146 ((PROCTHREAD_START_DATA *)pArg)->pSession->func(((PROCTHREAD_START_DATA *)pArg)->pMsg); \
147 InterlockedDecrement(&((PROCTHREAD_START_DATA *)pArg)->pSession->m_refCount); \
148 delete ((PROCTHREAD_START_DATA *)pArg)->pMsg; \
152 DEFINE_THREAD_STARTER(cancelFileMonitoring
)
153 DEFINE_THREAD_STARTER(clearDCIData
)
154 DEFINE_THREAD_STARTER(createObject
)
155 DEFINE_THREAD_STARTER(executeAction
)
156 DEFINE_THREAD_STARTER(executeScript
)
157 DEFINE_THREAD_STARTER(fileManagerControl
)
158 DEFINE_THREAD_STARTER(findIpAddress
)
159 DEFINE_THREAD_STARTER(findMacAddress
)
160 DEFINE_THREAD_STARTER(findNodeConnection
)
161 DEFINE_THREAD_STARTER(forceDCIPoll
)
162 DEFINE_THREAD_STARTER(forwardToReportingServer
)
163 DEFINE_THREAD_STARTER(getAgentFile
)
164 DEFINE_THREAD_STARTER(getAlarms
)
165 DEFINE_THREAD_STARTER(getAlarmEvents
)
166 DEFINE_THREAD_STARTER(getCollectedData
)
167 DEFINE_THREAD_STARTER(getLocationHistory
)
168 DEFINE_THREAD_STARTER(getNetworkPath
)
169 DEFINE_THREAD_STARTER(getRoutingTable
)
170 DEFINE_THREAD_STARTER(getServerFile
)
171 DEFINE_THREAD_STARTER(getServerLogQueryData
)
172 DEFINE_THREAD_STARTER(getSwitchForwardingDatabase
)
173 DEFINE_THREAD_STARTER(getTableCollectedData
)
174 DEFINE_THREAD_STARTER(importConfiguration
)
175 DEFINE_THREAD_STARTER(openHelpdeskIssue
)
176 DEFINE_THREAD_STARTER(processConsoleCommand
)
177 DEFINE_THREAD_STARTER(queryAgentTable
)
178 DEFINE_THREAD_STARTER(queryL2Topology
)
179 DEFINE_THREAD_STARTER(queryParameter
)
180 DEFINE_THREAD_STARTER(queryServerLog
)
181 DEFINE_THREAD_STARTER(sendEventLog
)
182 DEFINE_THREAD_STARTER(sendMib
)
183 DEFINE_THREAD_STARTER(sendSyslog
)
184 DEFINE_THREAD_STARTER(uploadUserFileToAgent
)
185 DEFINE_THREAD_STARTER(getRepositories
)
186 DEFINE_THREAD_STARTER(addRepository
)
187 DEFINE_THREAD_STARTER(modifyRepository
)
188 DEFINE_THREAD_STARTER(deleteRepository
)
191 * Client communication read thread starter
193 THREAD_RESULT THREAD_CALL
ClientSession::readThreadStarter(void *pArg
)
195 ((ClientSession
*)pArg
)->readThread();
197 // When ClientSession::ReadThread exits, all other session
198 // threads are already stopped, so we can safely destroy
200 UnregisterClientSession(((ClientSession
*)pArg
)->getId());
201 delete (ClientSession
*)pArg
;
206 * Client communication write thread starter
208 THREAD_RESULT THREAD_CALL
ClientSession::writeThreadStarter(void *pArg
)
210 ((ClientSession
*)pArg
)->writeThread();
215 * Received message processing thread starter
217 THREAD_RESULT THREAD_CALL
ClientSession::processingThreadStarter(void *pArg
)
219 ((ClientSession
*)pArg
)->processingThread();
224 * Information update processing thread starter
226 THREAD_RESULT THREAD_CALL
ClientSession::updateThreadStarter(void *pArg
)
228 ((ClientSession
*)pArg
)->updateThread();
233 * Client session class constructor
235 ClientSession::ClientSession(SOCKET hSocket
, struct sockaddr
*addr
)
237 m_pSendQueue
= new Queue
;
238 m_pMessageQueue
= new Queue
;
239 m_pUpdateQueue
= new Queue
;
242 m_state
= SESSION_STATE_INIT
;
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();
257 m_subscriptionLock
= MutexCreate();
258 m_subscriptions
= new StringObjectMap
<UINT32
>(true);
260 m_clientType
= CLIENT_TYPE_DESKTOP
;
261 m_clientAddr
= (struct sockaddr
*)nx_memdup(addr
, (addr
->sa_family
== AF_INET
) ? sizeof(struct sockaddr_in
) : sizeof(struct sockaddr_in6
));
262 if (addr
->sa_family
== AF_INET
)
263 IpToStr(ntohl(((struct sockaddr_in
*)m_clientAddr
)->sin_addr
.s_addr
), m_workstation
);
266 Ip6ToStr(((struct sockaddr_in6
*)m_clientAddr
)->sin6_addr
.s6_addr
, m_workstation
);
268 m_webServerAddress
[0] = 0;
270 _tcscpy(m_sessionName
, _T("<not logged in>"));
271 _tcscpy(m_clientInfo
, _T("n/a"));
272 m_dwUserId
= INVALID_INDEX
;
273 m_dwSystemAccess
= 0;
274 m_dwOpenDCIListSize
= 0;
275 m_pOpenDCIList
= NULL
;
276 m_ppEPPRuleList
= NULL
;
280 m_dwUploadCommand
= 0;
281 m_dwNumRecordsToUpload
= 0;
282 m_dwRecordsUploaded
= 0;
284 m_dwEncryptionRqId
= 0;
285 m_dwEncryptionResult
= 0;
287 m_condEncryptionSetup
= INVALID_CONDITION_HANDLE
;
289 m_loginTime
= time(NULL
);
290 m_musicTypeList
.add(_T("wav"));
291 _tcscpy(m_language
, _T("en"));
297 ClientSession::~ClientSession()
300 closesocket(m_hSocket
);
302 delete m_pMessageQueue
;
303 delete m_pUpdateQueue
;
304 safe_free(m_clientAddr
);
305 MutexDestroy(m_mutexSocketWrite
);
306 MutexDestroy(m_mutexSendEvents
);
307 MutexDestroy(m_mutexSendSyslog
);
308 MutexDestroy(m_mutexSendTrapLog
);
309 MutexDestroy(m_mutexSendObjects
);
310 MutexDestroy(m_mutexSendAlarms
);
311 MutexDestroy(m_mutexSendActions
);
312 MutexDestroy(m_mutexSendAuditLog
);
313 MutexDestroy(m_mutexSendSituations
);
314 MutexDestroy(m_mutexPollerInit
);
315 MutexDestroy(m_subscriptionLock
);
316 delete m_subscriptions
;
317 free(m_pOpenDCIList
);
318 if (m_ppEPPRuleList
!= NULL
)
322 if (m_dwFlags
& CSF_EPP_UPLOAD
) // Aborted in the middle of EPP transfer
323 for(i
= 0; i
< m_dwRecordsUploaded
; i
++)
324 delete m_ppEPPRuleList
[i
];
325 free(m_ppEPPRuleList
);
328 m_pCtx
->decRefCount();
329 if (m_condEncryptionSetup
!= INVALID_CONDITION_HANDLE
)
330 ConditionDestroy(m_condEncryptionSetup
);
332 if (m_console
!= NULL
)
334 delete m_console
->pMsg
;
337 m_musicTypeList
.clear();
338 if (m_agentConn
.size() > 0)
340 m_agentConn
.forEach(&DeleteCallback
, NULL
);
347 void ClientSession::run()
349 m_hWriteThread
= ThreadCreateEx(writeThreadStarter
, 0, this);
350 m_hProcessingThread
= ThreadCreateEx(processingThreadStarter
, 0, this);
351 m_hUpdateThread
= ThreadCreateEx(updateThreadStarter
, 0, this);
352 ThreadCreate(readThreadStarter
, 0, this);
356 * Print debug information
358 void ClientSession::debugPrintf(int level
, const TCHAR
*format
, ...)
360 if (level
<= nxlog_get_debug_level())
365 va_start(args
, format
);
366 _vsntprintf(buffer
, 8192, format
, args
);
368 DbgPrintf(level
, _T("[CLSN-%d] %s"), m_id
, buffer
);
375 void ClientSession::writeAuditLog(const TCHAR
*subsys
, bool success
, UINT32 objectId
, const TCHAR
*format
, ...)
378 va_start(args
, format
);
379 WriteAuditLog2(subsys
, success
, m_dwUserId
, m_workstation
, m_id
, objectId
, format
, args
);
384 * Check channel subscription
386 bool ClientSession::isSubscribedTo(const TCHAR
*channel
) const
388 MutexLock(m_subscriptionLock
);
389 bool subscribed
= m_subscriptions
->contains(channel
);
390 MutexUnlock(m_subscriptionLock
);
397 void ClientSession::readThread()
403 SocketMessageReceiver
receiver(m_hSocket
, 4096, MAX_MSG_SIZE
);
406 MessageReceiverResult result
;
407 NXCPMessage
*msg
= receiver
.readMessage(900000, &result
);
409 // Check for decryption error
410 if (result
== MSGRECV_DECRYPTION_FAILURE
)
412 debugPrintf(4, _T("readThread: Unable to decrypt received message"));
419 if (result
== MSGRECV_CLOSED
)
420 debugPrintf(5, _T("readThread: connection closed"));
422 debugPrintf(5, _T("readThread: message receiving error (%s)"), AbstractMessageReceiver::resultToText(result
));
426 if (nxlog_get_debug_level() >= 8)
428 String msgDump
= NXCPMessage::dump(receiver
.getRawMessageBuffer(), NXCP_VERSION
);
429 debugPrintf(8, _T("Message dump:\n%s"), (const TCHAR
*)msgDump
);
432 // Special handling for raw messages
435 debugPrintf(6, _T("Received raw message %s"), NXCPMessageCodeName(msg
->getCode(), szBuffer
));
437 if ((msg
->getCode() == CMD_FILE_DATA
) ||
438 (msg
->getCode() == CMD_ABORT_FILE_TRANSFER
))
440 if ((m_hCurrFile
!= -1) && (m_dwFileRqId
== msg
->getId()))
442 if (msg
->getCode() == CMD_FILE_DATA
)
444 if (write(m_hCurrFile
, msg
->getBinaryData(), (int)msg
->getBinaryDataSize()) == (int)msg
->getBinaryDataSize())
446 if (msg
->isEndOfFile())
448 debugPrintf(6, _T("Got end of file marker"));
449 NXCPMessage response
;
454 response
.setCode(CMD_REQUEST_COMPLETED
);
455 response
.setId(msg
->getId());
456 response
.setField(VID_RCC
, RCC_SUCCESS
);
457 sendMessage(&response
);
464 debugPrintf(6, _T("I/O error"));
466 NXCPMessage response
;
471 response
.setCode(CMD_REQUEST_COMPLETED
);
472 response
.setId(msg
->getId());
473 response
.setField(VID_RCC
, RCC_IO_ERROR
);
474 sendMessage(&response
);
481 // Abort current file transfer because of client's problem
490 AgentConnection
*conn
= (AgentConnection
*)m_agentConn
.get(msg
->getId());
493 if (msg
->getCode() == CMD_FILE_DATA
)
495 if (conn
->sendMessage(msg
)) //send raw message
497 if (msg
->isEndOfFile())
499 debugPrintf(6, _T("Got end of file marker"));
500 //get response with specific ID if ok< then send ok, else send error
501 m_agentConn
.remove(msg
->getId());
504 NXCPMessage response
;
505 response
.setCode(CMD_REQUEST_COMPLETED
);
506 response
.setId(msg
->getId());
507 response
.setField(VID_RCC
, RCC_SUCCESS
);
508 sendMessage(&response
);
513 debugPrintf(6, _T("Error while sending to agent"));
515 m_agentConn
.remove(msg
->getId());
518 NXCPMessage response
;
519 response
.setCode(CMD_REQUEST_COMPLETED
);
520 response
.setId(msg
->getId());
521 response
.setField(VID_RCC
, RCC_IO_ERROR
); //set result that came from agent
522 sendMessage(&response
);
527 // Resend abort message
528 conn
->sendMessage(msg
);
529 m_agentConn
.remove(msg
->getId());
535 debugPrintf(4, _T("Out of state message (ID: %d)"), msg
->getId());
543 if ((msg
->getCode() == CMD_SESSION_KEY
) && (msg
->getId() == m_dwEncryptionRqId
))
545 debugPrintf(6, _T("Received message %s"), NXCPMessageCodeName(msg
->getCode(), szBuffer
));
546 m_dwEncryptionResult
= SetupEncryptionContext(msg
, &m_pCtx
, NULL
, g_pServerKey
, NXCP_VERSION
);
547 receiver
.setEncryptionContext(m_pCtx
);
548 ConditionSet(m_condEncryptionSetup
);
549 m_dwEncryptionRqId
= 0;
552 else if (msg
->getCode() == CMD_KEEPALIVE
)
554 debugPrintf(6, _T("Received message %s"), NXCPMessageCodeName(msg
->getCode(), szBuffer
));
555 respondToKeepalive(msg
->getId());
560 m_pMessageQueue
->put(msg
);
565 // Mark as terminated (sendMessage calls will not work after that point)
566 m_dwFlags
|= CSF_TERMINATED
;
568 // Finish update thread first
569 m_pUpdateQueue
->put(INVALID_POINTER_VALUE
);
570 ThreadJoin(m_hUpdateThread
);
572 // Notify other threads to exit
573 NXCP_MESSAGE
*rawMsg
;
574 while((rawMsg
= (NXCP_MESSAGE
*)m_pSendQueue
->get()) != NULL
)
576 m_pSendQueue
->put(INVALID_POINTER_VALUE
);
579 while((msg
= (NXCPMessage
*)m_pMessageQueue
->get()) != NULL
)
581 m_pMessageQueue
->put(INVALID_POINTER_VALUE
);
583 // Wait for other threads to finish
584 ThreadJoin(m_hWriteThread
);
585 ThreadJoin(m_hProcessingThread
);
587 // Abort current file upload operation, if any
588 if (m_hCurrFile
!= -1)
595 // remove all pending file transfers from reporting server
596 RemovePendingFileTransferRequests(this);
598 // Remove all locks created by this session
599 RemoveAllSessionLocks(m_id
);
600 for(i
= 0; i
< m_dwOpenDCIListSize
; i
++)
602 object
= FindObjectById(m_pOpenDCIList
[i
]);
604 if (object
->isDataCollectionTarget() || (object
->getObjectClass() == OBJECT_TEMPLATE
))
605 ((Template
*)object
)->unlockDCIList(m_id
);
608 // Waiting while reference count becomes 0
611 debugPrintf(3, _T("Waiting for pending requests..."));
615 } while(m_refCount
> 0);
618 if (m_dwFlags
& CSF_AUTHENTICATED
)
620 CALL_ALL_MODULES(pfClientSessionClose
, (this));
621 WriteAuditLog(AUDIT_SECURITY
, TRUE
, m_dwUserId
, m_workstation
, m_id
, 0, _T("User logged out (client: %s)"), m_clientInfo
);
623 debugPrintf(3, _T("Session closed"));
627 * Network write thread
629 void ClientSession::writeThread()
633 NXCP_MESSAGE
*rawMsg
= (NXCP_MESSAGE
*)m_pSendQueue
->getOrBlock();
634 if (rawMsg
== INVALID_POINTER_VALUE
) // Session termination indicator
637 sendRawMessage(rawMsg
);
643 * Update processing thread
645 void ClientSession::updateThread()
647 UPDATE_INFO
*pUpdate
;
652 pUpdate
= (UPDATE_INFO
*)m_pUpdateQueue
->getOrBlock();
653 if (pUpdate
== INVALID_POINTER_VALUE
) // Session termination indicator
656 switch(pUpdate
->dwCategory
)
659 MutexLock(m_mutexSendEvents
);
660 sendMessage((NXCPMessage
*)pUpdate
->pData
);
661 MutexUnlock(m_mutexSendEvents
);
662 delete (NXCPMessage
*)pUpdate
->pData
;
664 case INFO_CAT_SYSLOG_MSG
:
665 MutexLock(m_mutexSendSyslog
);
666 msg
.setCode(CMD_SYSLOG_RECORDS
);
667 CreateMessageFromSyslogMsg(&msg
, (NX_SYSLOG_RECORD
*)pUpdate
->pData
);
669 MutexUnlock(m_mutexSendSyslog
);
670 free(pUpdate
->pData
);
672 case INFO_CAT_SNMP_TRAP
:
673 MutexLock(m_mutexSendTrapLog
);
674 sendMessage((NXCPMessage
*)pUpdate
->pData
);
675 MutexUnlock(m_mutexSendTrapLog
);
676 delete (NXCPMessage
*)pUpdate
->pData
;
678 case INFO_CAT_AUDIT_RECORD
:
679 MutexLock(m_mutexSendAuditLog
);
680 sendMessage((NXCPMessage
*)pUpdate
->pData
);
681 MutexUnlock(m_mutexSendAuditLog
);
682 delete (NXCPMessage
*)pUpdate
->pData
;
684 case INFO_CAT_OBJECT_CHANGE
:
685 MutexLock(m_mutexSendObjects
);
686 msg
.setCode(CMD_OBJECT_UPDATE
);
687 if (!((NetObj
*)pUpdate
->pData
)->isDeleted())
689 ((NetObj
*)pUpdate
->pData
)->fillMessage(&msg
);
690 if (m_dwFlags
& CSF_SYNC_OBJECT_COMMENTS
)
691 ((NetObj
*)pUpdate
->pData
)->commentsToMessage(&msg
);
695 msg
.setField(VID_OBJECT_ID
, ((NetObj
*)pUpdate
->pData
)->getId());
696 msg
.setField(VID_IS_DELETED
, (WORD
)1);
699 MutexUnlock(m_mutexSendObjects
);
700 msg
.deleteAllFields();
701 ((NetObj
*)pUpdate
->pData
)->decRefCount();
704 MutexLock(m_mutexSendAlarms
);
705 msg
.setCode(CMD_ALARM_UPDATE
);
706 msg
.setField(VID_NOTIFICATION_CODE
, pUpdate
->dwCode
);
707 ((Alarm
*)pUpdate
->pData
)->fillMessage(&msg
);
709 MutexUnlock(m_mutexSendAlarms
);
710 msg
.deleteAllFields();
711 delete (Alarm
*)pUpdate
->pData
;
713 case INFO_CAT_ACTION
:
714 MutexLock(m_mutexSendActions
);
715 msg
.setCode(CMD_ACTION_DB_UPDATE
);
716 msg
.setField(VID_NOTIFICATION_CODE
, pUpdate
->dwCode
);
717 msg
.setField(VID_ACTION_ID
, ((NXC_ACTION
*)pUpdate
->pData
)->dwId
);
718 if (pUpdate
->dwCode
!= NX_NOTIFY_ACTION_DELETED
)
719 FillActionInfoMessage(&msg
, (NXC_ACTION
*)pUpdate
->pData
);
721 MutexUnlock(m_mutexSendActions
);
722 msg
.deleteAllFields();
723 free(pUpdate
->pData
);
725 case INFO_CAT_SITUATION
:
726 MutexLock(m_mutexSendSituations
);
727 sendMessage((NXCPMessage
*)pUpdate
->pData
);
728 MutexUnlock(m_mutexSendSituations
);
729 delete (NXCPMessage
*)pUpdate
->pData
;
731 case INFO_CAT_LIBRARY_IMAGE
:
733 LIBRARY_IMAGE_UPDATE_INFO
*info
= (LIBRARY_IMAGE_UPDATE_INFO
*)pUpdate
->pData
;
734 msg
.setCode(CMD_IMAGE_LIBRARY_UPDATE
);
735 msg
.setField(VID_GUID
, (BYTE
*)info
->guid
, UUID_LENGTH
);
738 msg
.setField(VID_FLAGS
, (UINT32
)1);
742 msg
.setField(VID_FLAGS
, (UINT32
)0);
745 msg
.deleteAllFields();
759 * Message processing thread
761 void ClientSession::processingThread()
770 pMsg
= (NXCPMessage
*)m_pMessageQueue
->getOrBlock();
771 if (pMsg
== INVALID_POINTER_VALUE
) // Session termination indicator
774 m_wCurrentCmd
= pMsg
->getCode();
775 debugPrintf(6, _T("Received message %s"), NXCPMessageCodeName(m_wCurrentCmd
, szBuffer
));
776 if (!(m_dwFlags
& CSF_AUTHENTICATED
) &&
777 (m_wCurrentCmd
!= CMD_LOGIN
) &&
778 (m_wCurrentCmd
!= CMD_GET_SERVER_INFO
) &&
779 (m_wCurrentCmd
!= CMD_REQUEST_ENCRYPTION
) &&
780 (m_wCurrentCmd
!= CMD_GET_MY_CONFIG
) &&
781 (m_wCurrentCmd
!= CMD_REGISTER_AGENT
))
787 m_state
= SESSION_STATE_PROCESSING
;
788 switch(m_wCurrentCmd
)
793 case CMD_GET_SERVER_INFO
:
794 sendServerInfo(pMsg
->getId());
796 case CMD_GET_MY_CONFIG
:
797 sendConfigForAgent(pMsg
);
799 case CMD_GET_OBJECTS
:
800 sendAllObjects(pMsg
);
802 case CMD_GET_SELECTED_OBJECTS
:
803 sendSelectedObjects(pMsg
);
806 CALL_IN_NEW_THREAD(sendEventLog
, pMsg
);
808 case CMD_GET_CONFIG_VARLIST
:
809 getConfigurationVariables(pMsg
->getId());
811 case CMD_GET_PUBLIC_CONFIG_VAR
:
812 getPublicConfigurationVariable(pMsg
);
814 case CMD_SET_CONFIG_VARIABLE
:
815 setConfigurationVariable(pMsg
);
817 case CMD_DELETE_CONFIG_VARIABLE
:
818 deleteConfigurationVariable(pMsg
);
820 case CMD_CONFIG_GET_CLOB
:
823 case CMD_CONFIG_SET_CLOB
:
826 case CMD_LOAD_EVENT_DB
:
827 sendEventDB(pMsg
->getId());
829 case CMD_SET_EVENT_INFO
:
830 modifyEventTemplate(pMsg
);
832 case CMD_DELETE_EVENT_TEMPLATE
:
833 deleteEventTemplate(pMsg
);
835 case CMD_GENERATE_EVENT_CODE
:
836 generateEventCode(pMsg
->getId());
838 case CMD_MODIFY_OBJECT
:
841 case CMD_SET_OBJECT_MGMT_STATUS
:
842 changeObjectMgmtStatus(pMsg
);
844 case CMD_ENTER_MAINT_MODE
:
845 enterMaintenanceMode(pMsg
);
847 case CMD_LEAVE_MAINT_MODE
:
848 leaveMaintenanceMode(pMsg
);
850 case CMD_LOAD_USER_DB
:
851 sendUserDB(pMsg
->getId());
853 case CMD_CREATE_USER
:
856 case CMD_UPDATE_USER
:
859 case CMD_DETACH_LDAP_USER
:
860 detachLdapUser(pMsg
);
862 case CMD_DELETE_USER
:
865 case CMD_LOCK_USER_DB
:
866 lockUserDB(pMsg
->getId(), TRUE
);
868 case CMD_UNLOCK_USER_DB
:
869 lockUserDB(pMsg
->getId(), FALSE
);
871 case CMD_SET_PASSWORD
:
874 case CMD_VALIDATE_PASSWORD
:
875 validatePassword(pMsg
);
877 case CMD_GET_NODE_DCI_LIST
:
878 openNodeDCIList(pMsg
);
880 case CMD_UNLOCK_NODE_DCI_LIST
:
881 closeNodeDCIList(pMsg
);
883 case CMD_CREATE_NEW_DCI
:
884 case CMD_MODIFY_NODE_DCI
:
885 case CMD_DELETE_NODE_DCI
:
888 case CMD_SET_DCI_STATUS
:
889 changeDCIStatus(pMsg
);
894 case CMD_APPLY_TEMPLATE
:
897 case CMD_GET_DCI_DATA
:
898 CALL_IN_NEW_THREAD(getCollectedData
, pMsg
);
900 case CMD_GET_TABLE_DCI_DATA
:
901 CALL_IN_NEW_THREAD(getTableCollectedData
, pMsg
);
903 case CMD_CLEAR_DCI_DATA
:
904 CALL_IN_NEW_THREAD(clearDCIData
, pMsg
);
906 case CMD_FORCE_DCI_POLL
:
907 CALL_IN_NEW_THREAD(forceDCIPoll
, pMsg
);
913 closeEPP(pMsg
->getId());
919 processEPPRecord(pMsg
);
921 case CMD_GET_MIB_TIMESTAMP
:
922 sendMIBTimestamp(pMsg
->getId());
925 CALL_IN_NEW_THREAD(sendMib
, pMsg
);
927 case CMD_CREATE_OBJECT
:
928 CALL_IN_NEW_THREAD(createObject
, pMsg
);
930 case CMD_BIND_OBJECT
:
931 changeObjectBinding(pMsg
, TRUE
);
933 case CMD_UNBIND_OBJECT
:
934 changeObjectBinding(pMsg
, FALSE
);
936 case CMD_ADD_CLUSTER_NODE
:
937 addClusterNode(pMsg
);
939 case CMD_GET_ALL_ALARMS
:
940 CALL_IN_NEW_THREAD(getAlarms
, pMsg
);
942 case CMD_GET_ALARM_COMMENTS
:
943 getAlarmComments(pMsg
);
945 case CMD_SET_ALARM_STATUS_FLOW
:
946 updateAlarmStatusFlow(pMsg
);
948 case CMD_UPDATE_ALARM_COMMENT
:
949 updateAlarmComment(pMsg
);
951 case CMD_DELETE_ALARM_COMMENT
:
952 deleteAlarmComment(pMsg
);
957 case CMD_GET_ALARM_EVENTS
:
958 CALL_IN_NEW_THREAD(getAlarmEvents
, pMsg
);
961 acknowledgeAlarm(pMsg
);
963 case CMD_RESOLVE_ALARM
:
964 resolveAlarm(pMsg
, false);
966 case CMD_TERMINATE_ALARM
:
967 resolveAlarm(pMsg
, true);
969 case CMD_DELETE_ALARM
:
972 case CMD_OPEN_HELPDESK_ISSUE
:
973 CALL_IN_NEW_THREAD(openHelpdeskIssue
, pMsg
);
975 case CMD_GET_HELPDESK_URL
:
976 getHelpdeskUrl(pMsg
);
978 case CMD_UNLINK_HELPDESK_ISSUE
:
979 unlinkHelpdeskIssue(pMsg
);
981 case CMD_CREATE_ACTION
:
984 case CMD_MODIFY_ACTION
:
987 case CMD_DELETE_ACTION
:
990 case CMD_LOAD_ACTIONS
:
991 sendAllActions(pMsg
->getId());
993 case CMD_DELETE_OBJECT
:
997 forcedNodePoll(pMsg
);
1002 case CMD_WAKEUP_NODE
:
1005 case CMD_CREATE_TRAP
:
1006 editTrap(TRAP_CREATE
, pMsg
);
1008 case CMD_MODIFY_TRAP
:
1009 editTrap(TRAP_UPDATE
, pMsg
);
1011 case CMD_DELETE_TRAP
:
1012 editTrap(TRAP_DELETE
, pMsg
);
1014 case CMD_LOAD_TRAP_CFG
:
1015 sendAllTraps(pMsg
->getId());
1017 case CMD_GET_TRAP_CFG_RO
:
1018 sendAllTraps2(pMsg
->getId());
1020 case CMD_QUERY_PARAMETER
:
1021 CALL_IN_NEW_THREAD(queryParameter
, pMsg
);
1023 case CMD_QUERY_TABLE
:
1024 CALL_IN_NEW_THREAD(queryAgentTable
, pMsg
);
1026 case CMD_LOCK_PACKAGE_DB
:
1027 LockPackageDB(pMsg
->getId(), TRUE
);
1029 case CMD_UNLOCK_PACKAGE_DB
:
1030 LockPackageDB(pMsg
->getId(), FALSE
);
1032 case CMD_GET_PACKAGE_LIST
:
1033 SendAllPackages(pMsg
->getId());
1035 case CMD_INSTALL_PACKAGE
:
1036 InstallPackage(pMsg
);
1038 case CMD_REMOVE_PACKAGE
:
1039 RemovePackage(pMsg
);
1041 case CMD_GET_PARAMETER_LIST
:
1042 getParametersList(pMsg
);
1044 case CMD_DEPLOY_PACKAGE
:
1045 DeployPackage(pMsg
);
1047 case CMD_GET_LAST_VALUES
:
1048 getLastValues(pMsg
);
1050 case CMD_GET_DCI_VALUES
:
1051 getLastValuesByDciId(pMsg
);
1053 case CMD_GET_TABLE_LAST_VALUES
:
1054 getTableLastValues(pMsg
);
1056 case CMD_GET_THRESHOLD_SUMMARY
:
1057 getThresholdSummary(pMsg
);
1059 case CMD_GET_USER_VARIABLE
:
1060 getUserVariable(pMsg
);
1062 case CMD_SET_USER_VARIABLE
:
1063 setUserVariable(pMsg
);
1065 case CMD_DELETE_USER_VARIABLE
:
1066 deleteUserVariable(pMsg
);
1068 case CMD_ENUM_USER_VARIABLES
:
1069 enumUserVariables(pMsg
);
1071 case CMD_COPY_USER_VARIABLE
:
1072 copyUserVariable(pMsg
);
1074 case CMD_CHANGE_ZONE
:
1075 changeObjectZone(pMsg
);
1077 case CMD_REQUEST_ENCRYPTION
:
1078 setupEncryption(pMsg
);
1080 case CMD_GET_AGENT_CONFIG
:
1081 getAgentConfig(pMsg
);
1083 case CMD_UPDATE_AGENT_CONFIG
:
1084 updateAgentConfig(pMsg
);
1086 case CMD_EXECUTE_ACTION
:
1087 CALL_IN_NEW_THREAD(executeAction
, pMsg
);
1089 case CMD_GET_OBJECT_TOOLS
:
1090 getObjectTools(pMsg
->getId());
1092 case CMD_EXEC_TABLE_TOOL
:
1093 execTableTool(pMsg
);
1095 case CMD_GET_OBJECT_TOOL_DETAILS
:
1096 getObjectToolDetails(pMsg
);
1098 case CMD_UPDATE_OBJECT_TOOL
:
1099 updateObjectTool(pMsg
);
1101 case CMD_DELETE_OBJECT_TOOL
:
1102 deleteObjectTool(pMsg
);
1104 case CMD_CHANGE_OBJECT_TOOL_STATUS
:
1105 changeObjectToolStatus(pMsg
);
1107 case CMD_GENERATE_OBJECT_TOOL_ID
:
1108 generateObjectToolId(pMsg
->getId());
1110 case CMD_CHANGE_SUBSCRIPTION
:
1111 changeSubscription(pMsg
);
1113 case CMD_GET_SYSLOG
:
1114 CALL_IN_NEW_THREAD(sendSyslog
, pMsg
);
1116 case CMD_GET_SERVER_STATS
:
1117 sendServerStats(pMsg
->getId());
1119 case CMD_GET_SCRIPT_LIST
:
1120 sendScriptList(pMsg
->getId());
1122 case CMD_GET_SCRIPT
:
1125 case CMD_UPDATE_SCRIPT
:
1128 case CMD_RENAME_SCRIPT
:
1131 case CMD_DELETE_SCRIPT
:
1134 case CMD_GET_SESSION_LIST
:
1135 SendSessionList(pMsg
->getId());
1137 case CMD_KILL_SESSION
:
1140 case CMD_GET_TRAP_LOG
:
1143 case CMD_START_SNMP_WALK
:
1144 StartSnmpWalk(pMsg
);
1146 case CMD_RESOLVE_DCI_NAMES
:
1147 resolveDCINames(pMsg
);
1149 case CMD_GET_DCI_INFO
:
1152 case CMD_GET_DCI_THRESHOLDS
:
1153 sendDCIThresholds(pMsg
);
1155 case CMD_GET_DCI_EVENTS_LIST
:
1156 getDCIEventList(pMsg
);
1158 case CMD_GET_DCI_SCRIPT_LIST
:
1159 getDCIScriptList(pMsg
);
1161 case CMD_GET_PERFTAB_DCI_LIST
:
1162 sendPerfTabDCIList(pMsg
);
1164 case CMD_PUSH_DCI_DATA
:
1167 case CMD_GET_AGENT_CFG_LIST
:
1168 sendAgentCfgList(pMsg
->getId());
1170 case CMD_OPEN_AGENT_CONFIG
:
1171 OpenAgentConfig(pMsg
);
1173 case CMD_SAVE_AGENT_CONFIG
:
1174 SaveAgentConfig(pMsg
);
1176 case CMD_DELETE_AGENT_CONFIG
:
1177 DeleteAgentConfig(pMsg
);
1179 case CMD_SWAP_AGENT_CONFIGS
:
1180 SwapAgentConfigs(pMsg
);
1182 case CMD_GET_OBJECT_COMMENTS
:
1183 SendObjectComments(pMsg
);
1185 case CMD_UPDATE_OBJECT_COMMENTS
:
1186 updateObjectComments(pMsg
);
1188 case CMD_GET_ADDR_LIST
:
1191 case CMD_SET_ADDR_LIST
:
1194 case CMD_RESET_COMPONENT
:
1195 resetComponent(pMsg
);
1197 case CMD_EXPORT_CONFIGURATION
:
1198 exportConfiguration(pMsg
);
1200 case CMD_IMPORT_CONFIGURATION
:
1201 CALL_IN_NEW_THREAD(importConfiguration
, pMsg
);
1203 case CMD_GET_GRAPH_LIST
:
1204 sendGraphList(pMsg
);
1206 case CMD_SAVE_GRAPH
:
1209 case CMD_DELETE_GRAPH
:
1212 case CMD_ADD_CA_CERTIFICATE
:
1213 addCACertificate(pMsg
);
1215 case CMD_DELETE_CERTIFICATE
:
1216 deleteCertificate(pMsg
);
1218 case CMD_UPDATE_CERT_COMMENTS
:
1219 updateCertificateComments(pMsg
);
1221 case CMD_GET_CERT_LIST
:
1222 getCertificateList(pMsg
->getId());
1224 case CMD_QUERY_L2_TOPOLOGY
:
1225 CALL_IN_NEW_THREAD(queryL2Topology
, pMsg
);
1230 case CMD_GET_COMMUNITY_LIST
:
1231 SendCommunityList(pMsg
->getId());
1233 case CMD_UPDATE_COMMUNITY_LIST
:
1234 UpdateCommunityList(pMsg
);
1236 case CMD_GET_USM_CREDENTIALS
:
1237 sendUsmCredentials(pMsg
->getId());
1239 case CMD_UPDATE_USM_CREDENTIALS
:
1240 updateUsmCredentials(pMsg
);
1242 case CMD_GET_SITUATION_LIST
:
1243 getSituationList(pMsg
->getId());
1245 case CMD_CREATE_SITUATION
:
1246 createSituation(pMsg
);
1248 case CMD_UPDATE_SITUATION
:
1249 updateSituation(pMsg
);
1251 case CMD_DELETE_SITUATION
:
1252 deleteSituation(pMsg
);
1254 case CMD_DEL_SITUATION_INSTANCE
:
1255 deleteSituationInstance(pMsg
);
1257 case CMD_REGISTER_AGENT
:
1258 registerAgent(pMsg
);
1260 case CMD_GET_SERVER_FILE
:
1261 CALL_IN_NEW_THREAD(getServerFile
, pMsg
);
1263 case CMD_GET_AGENT_FILE
:
1264 CALL_IN_NEW_THREAD(getAgentFile
, pMsg
);
1266 case CMD_CANCEL_FILE_MONITORING
:
1267 CALL_IN_NEW_THREAD(cancelFileMonitoring
, pMsg
);
1269 case CMD_TEST_DCI_TRANSFORMATION
:
1270 testDCITransformation(pMsg
);
1272 case CMD_EXECUTE_SCRIPT
:
1273 CALL_IN_NEW_THREAD(executeScript
, pMsg
);
1275 case CMD_GET_JOB_LIST
:
1276 sendJobList(pMsg
->getId());
1278 case CMD_CANCEL_JOB
:
1284 case CMD_UNHOLD_JOB
:
1287 case CMD_DEPLOY_AGENT_POLICY
:
1288 deployAgentPolicy(pMsg
, false);
1290 case CMD_UNINSTALL_AGENT_POLICY
:
1291 deployAgentPolicy(pMsg
, true);
1293 case CMD_GET_CURRENT_USER_ATTR
:
1294 getUserCustomAttribute(pMsg
);
1296 case CMD_SET_CURRENT_USER_ATTR
:
1297 setUserCustomAttribute(pMsg
);
1299 case CMD_OPEN_SERVER_LOG
:
1300 openServerLog(pMsg
);
1302 case CMD_CLOSE_SERVER_LOG
:
1303 closeServerLog(pMsg
);
1306 CALL_IN_NEW_THREAD(queryServerLog
, pMsg
);
1308 case CMD_GET_LOG_DATA
:
1309 CALL_IN_NEW_THREAD(getServerLogQueryData
, pMsg
);
1311 case CMD_FIND_NODE_CONNECTION
:
1312 CALL_IN_NEW_THREAD(findNodeConnection
, pMsg
);
1314 case CMD_FIND_MAC_LOCATION
:
1315 CALL_IN_NEW_THREAD(findMacAddress
, pMsg
);
1317 case CMD_FIND_IP_LOCATION
:
1318 CALL_IN_NEW_THREAD(findIpAddress
, pMsg
);
1321 sendLibraryImage(pMsg
);
1323 case CMD_CREATE_IMAGE
:
1324 updateLibraryImage(pMsg
);
1326 case CMD_DELETE_IMAGE
:
1327 deleteLibraryImage(pMsg
);
1329 case CMD_MODIFY_IMAGE
:
1330 updateLibraryImage(pMsg
);
1332 case CMD_LIST_IMAGES
:
1333 listLibraryImages(pMsg
);
1335 case CMD_EXECUTE_SERVER_COMMAND
:
1336 executeServerCommand(pMsg
);
1338 case CMD_LIST_SERVER_FILES
:
1339 listServerFileStore(pMsg
);
1341 case CMD_UPLOAD_FILE_TO_AGENT
:
1342 uploadFileToAgent(pMsg
);
1344 case CMD_UPLOAD_FILE
:
1347 case CMD_DELETE_FILE
:
1350 case CMD_OPEN_CONSOLE
:
1351 openConsole(pMsg
->getId());
1353 case CMD_CLOSE_CONSOLE
:
1354 closeConsole(pMsg
->getId());
1356 case CMD_ADM_REQUEST
:
1357 CALL_IN_NEW_THREAD(processConsoleCommand
, pMsg
);
1362 case CMD_GET_NETWORK_PATH
:
1363 CALL_IN_NEW_THREAD(getNetworkPath
, pMsg
);
1365 case CMD_GET_NODE_COMPONENTS
:
1366 getNodeComponents(pMsg
);
1368 case CMD_GET_NODE_SOFTWARE
:
1369 getNodeSoftware(pMsg
);
1371 case CMD_GET_WINPERF_OBJECTS
:
1372 getWinPerfObjects(pMsg
);
1374 case CMD_LIST_MAPPING_TABLES
:
1375 listMappingTables(pMsg
);
1377 case CMD_GET_MAPPING_TABLE
:
1378 getMappingTable(pMsg
);
1380 case CMD_UPDATE_MAPPING_TABLE
:
1381 updateMappingTable(pMsg
);
1383 case CMD_DELETE_MAPPING_TABLE
:
1384 deleteMappingTable(pMsg
);
1386 case CMD_GET_WIRELESS_STATIONS
:
1387 getWirelessStations(pMsg
);
1389 case CMD_GET_SUMMARY_TABLES
:
1390 getSummaryTables(pMsg
->getId());
1392 case CMD_GET_SUMMARY_TABLE_DETAILS
:
1393 getSummaryTableDetails(pMsg
);
1395 case CMD_MODIFY_SUMMARY_TABLE
:
1396 modifySummaryTable(pMsg
);
1398 case CMD_DELETE_SUMMARY_TABLE
:
1399 deleteSummaryTable(pMsg
);
1401 case CMD_QUERY_SUMMARY_TABLE
:
1402 querySummaryTable(pMsg
);
1404 case CMD_QUERY_ADHOC_SUMMARY_TABLE
:
1405 queryAdHocSummaryTable(pMsg
);
1407 case CMD_GET_SUBNET_ADDRESS_MAP
:
1408 getSubnetAddressMap(pMsg
);
1410 case CMD_GET_EFFECTIVE_RIGHTS
:
1411 getEffectiveRights(pMsg
);
1413 case CMD_GET_FOLDER_CONTENT
:
1414 case CMD_FILEMGR_DELETE_FILE
:
1415 case CMD_FILEMGR_RENAME_FILE
:
1416 case CMD_FILEMGR_MOVE_FILE
:
1417 case CMD_FILEMGR_CREATE_FOLDER
:
1418 CALL_IN_NEW_THREAD(fileManagerControl
, pMsg
);
1420 case CMD_FILEMGR_UPLOAD
:
1421 CALL_IN_NEW_THREAD(uploadUserFileToAgent
, pMsg
);
1423 case CMD_GET_SWITCH_FDB
:
1424 CALL_IN_NEW_THREAD(getSwitchForwardingDatabase
, pMsg
);
1426 case CMD_GET_ROUTING_TABLE
:
1427 CALL_IN_NEW_THREAD(getRoutingTable
, pMsg
);
1429 case CMD_GET_LOC_HISTORY
:
1430 CALL_IN_NEW_THREAD(getLocationHistory
, pMsg
);
1432 case CMD_TAKE_SCREENSHOT
:
1433 getScreenshot(pMsg
);
1435 case CMD_COMPILE_SCRIPT
:
1436 compileScript(pMsg
);
1438 case CMD_CLEAN_AGENT_DCI_CONF
:
1439 cleanAgentDciConfiguration(pMsg
);
1441 case CMD_RESYNC_AGENT_DCI_CONF
:
1442 resyncAgentDciConfiguration(pMsg
);
1444 case CMD_LIST_SCHEDULE_CALLBACKS
:
1445 getSchedulerTaskHandlers(pMsg
);
1447 case CMD_LIST_SCHEDULES
:
1448 getScheduledTasks(pMsg
);
1450 case CMD_ADD_SCHEDULE
:
1451 addScheduledTask(pMsg
);
1453 case CMD_UPDATE_SCHEDULE
:
1454 updateScheduledTask(pMsg
);
1456 case CMD_REMOVE_SCHEDULE
:
1457 removeScheduledTask(pMsg
);
1459 case CMD_GET_REPOSITORIES
:
1460 CALL_IN_NEW_THREAD(getRepositories
, pMsg
);
1462 case CMD_ADD_REPOSITORY
:
1463 CALL_IN_NEW_THREAD(addRepository
, pMsg
);
1465 case CMD_MODIFY_REPOSITORY
:
1466 CALL_IN_NEW_THREAD(modifyRepository
, pMsg
);
1468 case CMD_DELETE_REPOSITORY
:
1469 CALL_IN_NEW_THREAD(deleteRepository
, pMsg
);
1472 case CMD_ZMQ_SUBSCRIBE_EVENT
:
1473 zmqManageSubscription(pMsg
, zmq::EVENT
, true);
1475 case CMD_ZMQ_UNSUBSCRIBE_EVENT
:
1476 zmqManageSubscription(pMsg
, zmq::EVENT
, false);
1478 case CMD_ZMQ_SUBSCRIBE_DATA
:
1479 zmqManageSubscription(pMsg
, zmq::DATA
, true);
1481 case CMD_ZMQ_UNSUBSCRIBE_DATA
:
1482 zmqManageSubscription(pMsg
, zmq::DATA
, false);
1484 case CMD_ZMQ_LIST_EVENT_SUBSCRIPTIONS
:
1485 zmqListSubscriptions(pMsg
, zmq::EVENT
);
1487 case CMD_ZMQ_LIST_DATA_SUBSCRIPTIONS
:
1488 zmqListSubscriptions(pMsg
, zmq::DATA
);
1492 if ((m_wCurrentCmd
>> 8) == 0x11)
1494 // Reporting Server range (0x1100 - 0x11FF)
1495 CALL_IN_NEW_THREAD(forwardToReportingServer
, pMsg
);
1499 // Pass message to loaded modules
1500 for(i
= 0; i
< g_dwNumModules
; i
++)
1502 if (g_pModuleList
[i
].pfClientCommandHandler
!= NULL
)
1504 status
= g_pModuleList
[i
].pfClientCommandHandler(m_wCurrentCmd
, pMsg
, this);
1505 if (status
!= NXMOD_COMMAND_IGNORED
)
1507 if (status
== NXMOD_COMMAND_ACCEPTED_ASYNC
)
1509 pMsg
= NULL
; // Prevent deletion
1510 InterlockedIncrement(&m_refCount
);
1512 break; // Message was processed by the module
1516 if (i
== g_dwNumModules
)
1518 NXCPMessage response
;
1520 response
.setId(pMsg
->getId());
1521 response
.setCode(CMD_REQUEST_COMPLETED
);
1522 response
.setField(VID_RCC
, RCC_NOT_IMPLEMENTED
);
1523 sendMessage(&response
);
1528 m_state
= (m_dwFlags
& CSF_AUTHENTICATED
) ? SESSION_STATE_IDLE
: SESSION_STATE_INIT
;
1533 * Respond to client's keepalive message
1535 void ClientSession::respondToKeepalive(UINT32 dwRqId
)
1539 msg
.setCode(CMD_REQUEST_COMPLETED
);
1541 msg
.setField(VID_RCC
, RCC_SUCCESS
);
1546 * Process received file
1548 void ClientSession::onFileUpload(BOOL bSuccess
)
1550 // Do processing specific to command initiated file upload
1551 switch(m_dwUploadCommand
)
1553 case CMD_INSTALL_PACKAGE
:
1556 DB_HANDLE hdb
= DBConnectionPoolAcquireConnection();
1558 _sntprintf(szQuery
, 256, _T("DELETE FROM agent_pkg WHERE pkg_id=%d"), m_dwUploadData
);
1559 DBQuery(hdb
, szQuery
);
1560 DBConnectionPoolReleaseConnection(hdb
);
1563 case CMD_MODIFY_IMAGE
:
1564 EnumerateClientSessions(ImageLibraryUpdateCallback
, (void *)&m_uploadImageGuid
);
1570 // Remove received file in case of failure
1572 _tunlink(m_szCurrFileName
);
1576 * Send message to client
1578 bool ClientSession::sendMessage(NXCPMessage
*msg
)
1583 if (msg
->getCode() != CMD_ADM_MESSAGE
)
1586 debugPrintf(6, _T("Sending message %s"), NXCPMessageCodeName(msg
->getCode(), buffer
));
1589 NXCP_MESSAGE
*rawMsg
= msg
->createMessage();
1590 if ((nxlog_get_debug_level() >= 8) && (msg
->getCode() != CMD_ADM_MESSAGE
))
1592 String msgDump
= NXCPMessage::dump(rawMsg
, NXCP_VERSION
);
1593 debugPrintf(8, _T("Message dump:\n%s"), (const TCHAR
*)msgDump
);
1599 NXCP_ENCRYPTED_MESSAGE
*enMsg
= m_pCtx
->encryptMessage(rawMsg
);
1602 result
= (SendEx(m_hSocket
, (char *)enMsg
, ntohl(enMsg
->size
), 0, m_mutexSocketWrite
) == (int)ntohl(enMsg
->size
));
1612 result
= (SendEx(m_hSocket
, (const char *)rawMsg
, ntohl(rawMsg
->size
), 0, m_mutexSocketWrite
) == (int)ntohl(rawMsg
->size
));
1618 closesocket(m_hSocket
);
1625 * Send raw message to client
1627 void ClientSession::sendRawMessage(NXCP_MESSAGE
*msg
)
1632 UINT16 code
= htons(msg
->code
);
1633 if (code
!= CMD_ADM_MESSAGE
)
1636 debugPrintf(6, _T("Sending message %s"), NXCPMessageCodeName(ntohs(msg
->code
), buffer
));
1639 if ((code
!= CMD_ADM_MESSAGE
) && (nxlog_get_debug_level() >= 8))
1641 String msgDump
= NXCPMessage::dump(msg
, NXCP_VERSION
);
1642 debugPrintf(8, _T("Message dump:\n%s"), (const TCHAR
*)msgDump
);
1648 NXCP_ENCRYPTED_MESSAGE
*enMsg
= m_pCtx
->encryptMessage(msg
);
1651 result
= (SendEx(m_hSocket
, (char *)enMsg
, ntohl(enMsg
->size
), 0, m_mutexSocketWrite
) == (int)ntohl(enMsg
->size
));
1661 result
= (SendEx(m_hSocket
, (const char *)msg
, ntohl(msg
->size
), 0, m_mutexSocketWrite
) == (int)ntohl(msg
->size
));
1666 closesocket(m_hSocket
);
1672 * Send file to client
1674 BOOL
ClientSession::sendFile(const TCHAR
*file
, UINT32 dwRqId
, long ofset
)
1676 return !isTerminated() ? SendFileOverNXCP(m_hSocket
, dwRqId
, file
, m_pCtx
, ofset
, NULL
, NULL
, m_mutexSocketWrite
) : FALSE
;
1680 * Send server information to client
1682 void ClientSession::sendServerInfo(UINT32 dwRqId
)
1684 static UINT32 protocolVersions
[] = {
1685 CLIENT_PROTOCOL_VERSION_BASE
,
1686 CLIENT_PROTOCOL_VERSION_ALARMS
,
1687 CLIENT_PROTOCOL_VERSION_PUSH
,
1688 CLIENT_PROTOCOL_VERSION_TRAP
,
1689 CLIENT_PROTOCOL_VERSION_MOBILE
,
1690 CLIENT_PROTOCOL_VERSION_FULL
1693 TCHAR szBuffer
[MAX_CONFIG_VALUE
];
1696 // Prepare response message
1697 msg
.setCode(CMD_REQUEST_COMPLETED
);
1700 // Generate challenge for certificate authentication
1701 #ifdef _WITH_ENCRYPTION
1702 RAND_bytes(m_challenge
, CLIENT_CHALLENGE_SIZE
);
1704 memset(m_challenge
, 0, CLIENT_CHALLENGE_SIZE
);
1707 // Fill message with server info
1708 msg
.setField(VID_RCC
, RCC_SUCCESS
);
1709 msg
.setField(VID_SERVER_VERSION
, NETXMS_VERSION_STRING
);
1710 msg
.setField(VID_SERVER_ID
, g_serverId
);
1711 msg
.setField(VID_SUPPORTED_ENCRYPTION
, (UINT32
)0);
1712 msg
.setField(VID_PROTOCOL_VERSION
, (UINT32
)CLIENT_PROTOCOL_VERSION_BASE
);
1713 msg
.setFieldFromInt32Array(VID_PROTOCOL_VERSION_EX
, sizeof(protocolVersions
) / sizeof(UINT32
), protocolVersions
);
1714 msg
.setField(VID_CHALLENGE
, m_challenge
, CLIENT_CHALLENGE_SIZE
);
1715 msg
.setField(VID_TIMESTAMP
, (UINT32
)time(NULL
));
1718 TIME_ZONE_INFORMATION tz
;
1719 WCHAR wst
[4], wdt
[8], *curr
;
1722 DWORD tzType
= GetTimeZoneInformation(&tz
);
1724 // Create 3 letter abbreviation for standard name
1725 for(i
= 0, curr
= tz
.StandardName
; (*curr
!= 0) && (i
< 3); curr
++)
1726 if (iswupper(*curr
))
1732 // Create abbreviation for DST name
1733 for(i
= 0, curr
= tz
.DaylightName
; (*curr
!= 0) && (i
< 7); curr
++)
1734 if (iswupper(*curr
))
1743 case TIME_ZONE_ID_STANDARD
:
1744 effectiveBias
= tz
.Bias
+ tz
.StandardBias
;
1746 case TIME_ZONE_ID_DAYLIGHT
:
1747 effectiveBias
= tz
.Bias
+ tz
.DaylightBias
;
1749 case TIME_ZONE_ID_UNKNOWN
:
1750 effectiveBias
= tz
.Bias
;
1754 debugPrintf(4, _T("GetTimeZoneInformation() call failed"));
1759 swprintf(szBuffer
, 1024, L
"%s%c%02d%s", wst
, (effectiveBias
> 0) ? '-' : '+',
1760 abs(effectiveBias
) / 60, (tz
.DaylightBias
!= 0) ? wdt
: L
"");
1762 sprintf(szBuffer
, "%S%c%02d%S", wst
, (effectiveBias
> 0) ? '-' : '+',
1763 abs(effectiveBias
) / 60, (tz
.DaylightBias
!= 0) ? wdt
: L
"");
1766 #elif HAVE_TM_GMTOFF /* not Windows but have tm_gmtoff */
1768 time_t t
= time(NULL
);
1770 #if HAVE_LOCALTIME_R
1772 struct tm
*loc
= localtime_r(&t
, &tmbuff
);
1774 struct tm
*loc
= localtime(&t
);
1776 gmtOffset
= loc
->tm_gmtoff
/ 3600;
1778 swprintf(szBuffer
, 1024, L
"%hs%hc%02d%hs", tzname
[0], (gmtOffset
>= 0) ? '+' : '-',
1779 abs(gmtOffset
), (tzname
[1] != NULL
) ? tzname
[1] : "");
1781 sprintf(szBuffer
, "%s%c%02d%s", tzname
[0], (gmtOffset
>= 0) ? '+' : '-',
1782 abs(gmtOffset
), (tzname
[1] != NULL
) ? tzname
[1] : "");
1785 #else /* not Windows and no tm_gmtoff */
1787 time_t t
= time(NULL
);
1790 struct tm
*gmt
= gmtime_r(&t
, &tmbuff
);
1792 struct tm
*gmt
= gmtime(&t
);
1795 int gmtOffset
= (int)((t
- mktime(gmt
)) / 3600);
1797 swprintf(szBuffer
, 1024, L
"%hs%hc%02d%hs", tzname
[0], (gmtOffset
>= 0) ? '+' : '-',
1798 abs(gmtOffset
), (tzname
[1] != NULL
) ? tzname
[1] : "");
1800 sprintf(szBuffer
, "%s%c%02d%s", tzname
[0], (gmtOffset
>= 0) ? '+' : '-',
1801 abs(gmtOffset
), (tzname
[1] != NULL
) ? tzname
[1] : "");
1806 msg
.setField(VID_TIMEZONE
, szBuffer
);
1807 debugPrintf(2, _T("Server time zone: %s"), szBuffer
);
1809 ConfigReadStr(_T("TileServerURL"), szBuffer
, MAX_CONFIG_VALUE
, _T("http://tile.openstreetmap.org/"));
1810 msg
.setField(VID_TILE_SERVER_URL
, szBuffer
);
1812 ConfigReadStr(_T("DefaultConsoleDateFormat"), szBuffer
, MAX_CONFIG_VALUE
, _T("dd.MM.yyyy"));
1813 msg
.setField(VID_DATE_FORMAT
, szBuffer
);
1815 ConfigReadStr(_T("DefaultConsoleTimeFormat"), szBuffer
, MAX_CONFIG_VALUE
, _T("HH:mm:ss"));
1816 msg
.setField(VID_TIME_FORMAT
, szBuffer
);
1818 ConfigReadStr(_T("DefaultConsoleShortTimeFormat"), szBuffer
, MAX_CONFIG_VALUE
, _T("HH:mm"));
1819 msg
.setField(VID_SHORT_TIME_FORMAT
, szBuffer
);
1826 * Authenticate client
1828 void ClientSession::login(NXCPMessage
*pRequest
)
1831 TCHAR szLogin
[MAX_USER_NAME
], szPassword
[1024];
1833 bool changePasswd
= false, intruderLockout
= false;
1835 #ifdef _WITH_ENCRYPTION
1839 // Prepare response message
1840 msg
.setCode(CMD_LOGIN_RESP
);
1841 msg
.setId(pRequest
->getId());
1843 // Get client info string
1844 if (pRequest
->isFieldExist(VID_CLIENT_INFO
))
1846 TCHAR szClientInfo
[32], szOSInfo
[32], szLibVersion
[16];
1848 pRequest
->getFieldAsString(VID_CLIENT_INFO
, szClientInfo
, 32);
1849 pRequest
->getFieldAsString(VID_OS_INFO
, szOSInfo
, 32);
1850 pRequest
->getFieldAsString(VID_LIBNXCL_VERSION
, szLibVersion
, 16);
1851 _sntprintf(m_clientInfo
, 96, _T("%s (%s; libnxcl %s)"), szClientInfo
, szOSInfo
, szLibVersion
);
1854 m_clientType
= pRequest
->getFieldAsUInt16(VID_CLIENT_TYPE
);
1855 if ((m_clientType
< 0) || (m_clientType
> CLIENT_TYPE_APPLICATION
))
1856 m_clientType
= CLIENT_TYPE_DESKTOP
;
1858 if (m_clientType
== CLIENT_TYPE_WEB
)
1860 _tcscpy(m_webServerAddress
, m_workstation
);
1861 if (pRequest
->isFieldExist(VID_CLIENT_ADDRESS
))
1863 pRequest
->getFieldAsString(VID_CLIENT_ADDRESS
, m_workstation
, 256);
1864 debugPrintf(5, _T("Real web client address is %s"), m_workstation
);
1868 if (pRequest
->isFieldExist(VID_LANGUAGE
))
1870 pRequest
->getFieldAsString(VID_LANGUAGE
, m_language
, 8);
1873 if (!(m_dwFlags
& CSF_AUTHENTICATED
))
1875 bool closeOtherSessions
= false;
1876 pRequest
->getFieldAsString(VID_LOGIN_NAME
, szLogin
, MAX_USER_NAME
);
1877 nAuthType
= (int)pRequest
->getFieldAsUInt16(VID_AUTH_TYPE
);
1878 debugPrintf(6, _T("authentication type %d"), nAuthType
);
1881 case NETXMS_AUTH_TYPE_PASSWORD
:
1883 pRequest
->getFieldAsString(VID_PASSWORD
, szPassword
, 256);
1885 pRequest
->getFieldAsUtf8String(VID_PASSWORD
, szPassword
, 1024);
1887 dwResult
= AuthenticateUser(szLogin
, szPassword
, 0, NULL
, NULL
, &m_dwUserId
,
1888 &m_dwSystemAccess
, &changePasswd
, &intruderLockout
,
1889 &closeOtherSessions
, false);
1891 case NETXMS_AUTH_TYPE_CERTIFICATE
:
1892 #ifdef _WITH_ENCRYPTION
1893 pCert
= CertificateFromLoginMessage(pRequest
);
1896 BYTE signature
[256];
1899 dwSigLen
= pRequest
->getFieldAsBinary(VID_SIGNATURE
, signature
, 256);
1900 dwResult
= AuthenticateUser(szLogin
, (TCHAR
*)signature
, dwSigLen
, pCert
,
1901 m_challenge
, &m_dwUserId
, &m_dwSystemAccess
,
1902 &changePasswd
, &intruderLockout
,
1903 &closeOtherSessions
, false);
1908 dwResult
= RCC_BAD_CERTIFICATE
;
1911 dwResult
= RCC_NOT_IMPLEMENTED
;
1914 case NETXMS_AUTH_TYPE_SSO_TICKET
:
1916 pRequest
->getFieldAsMBString(VID_PASSWORD
, ticket
, 1024);
1917 if (CASAuthenticate(ticket
, szLogin
))
1919 debugPrintf(5, _T("SSO ticket %hs is valid, login name %s"), ticket
, szLogin
);
1920 dwResult
= AuthenticateUser(szLogin
, NULL
, 0, NULL
, NULL
, &m_dwUserId
,
1921 &m_dwSystemAccess
, &changePasswd
, &intruderLockout
,
1922 &closeOtherSessions
, true);
1926 debugPrintf(5, _T("SSO ticket %hs is invalid"), ticket
);
1927 dwResult
= RCC_ACCESS_DENIED
;
1931 dwResult
= RCC_UNSUPPORTED_AUTH_TYPE
;
1935 // Additional validation by loaded modules
1936 if (dwResult
== RCC_SUCCESS
)
1938 for(UINT32 i
= 0; i
< g_dwNumModules
; i
++)
1940 if (g_pModuleList
[i
].pfAdditionalLoginCheck
!= NULL
)
1942 dwResult
= g_pModuleList
[i
].pfAdditionalLoginCheck(m_dwUserId
, pRequest
);
1943 if (dwResult
!= RCC_SUCCESS
)
1945 debugPrintf(4, _T("Login blocked by module %s (rcc=%d)"), g_pModuleList
[i
].szName
, dwResult
);
1952 if (dwResult
== RCC_SUCCESS
)
1954 m_dwFlags
|= CSF_AUTHENTICATED
;
1955 nx_strncpy(m_loginName
, szLogin
, MAX_USER_NAME
);
1956 _sntprintf(m_sessionName
, MAX_SESSION_NAME
, _T("%s@%s"), szLogin
, m_workstation
);
1957 m_loginTime
= time(NULL
);
1958 msg
.setField(VID_RCC
, RCC_SUCCESS
);
1959 msg
.setField(VID_USER_SYS_RIGHTS
, m_dwSystemAccess
);
1960 msg
.setField(VID_USER_ID
, m_dwUserId
);
1961 msg
.setField(VID_SESSION_ID
, (UINT32
)m_id
);
1962 msg
.setField(VID_CHANGE_PASSWD_FLAG
, (WORD
)changePasswd
);
1963 msg
.setField(VID_DBCONN_STATUS
, (UINT16
)((g_flags
& AF_DB_CONNECTION_LOST
) ? 0 : 1));
1964 msg
.setField(VID_ZONING_ENABLED
, (UINT16
)((g_flags
& AF_ENABLE_ZONING
) ? 1 : 0));
1965 msg
.setField(VID_POLLING_INTERVAL
, (INT32
)DCObject::m_defaultPollingInterval
);
1966 msg
.setField(VID_RETENTION_TIME
, (INT32
)DCObject::m_defaultRetentionTime
);
1967 msg
.setField(VID_ALARM_STATUS_FLOW_STATE
, (UINT16
)ConfigReadInt(_T("StrictAlarmStatusFlow"), 0));
1968 msg
.setField(VID_TIMED_ALARM_ACK_ENABLED
, (UINT16
)ConfigReadInt(_T("EnableTimedAlarmAck"), 0));
1969 msg
.setField(VID_VIEW_REFRESH_INTERVAL
, (UINT16
)ConfigReadInt(_T("MinViewRefreshInterval"), 200));
1970 msg
.setField(VID_HELPDESK_LINK_ACTIVE
, (UINT16
)((g_flags
& AF_HELPDESK_LINK_ACTIVE
) ? 1 : 0));
1971 msg
.setField(VID_ALARM_LIST_DISP_LIMIT
, ConfigReadULong(_T("AlarmListDisplayLimit"), 4096));
1972 msg
.setField(VID_SERVERCMD_TIMEOUT
, ConfigReadULong(_T("ServerCommandOutputTimeout"), 60));
1973 debugPrintf(3, _T("User %s authenticated (language=%s clientInfo=\"%s\")"), m_sessionName
, m_language
, m_clientInfo
);
1974 WriteAuditLog(AUDIT_SECURITY
, TRUE
, m_dwUserId
, m_workstation
, m_id
, 0,
1975 _T("User \"%s\" logged in (language: %s; client info: %s)"), szLogin
, m_language
, m_clientInfo
);
1977 if (closeOtherSessions
)
1979 debugPrintf(5, _T("Closing other sessions for user %s"), m_loginName
);
1980 CloseOtherSessions(m_dwUserId
, m_id
);
1985 msg
.setField(VID_RCC
, dwResult
);
1986 WriteAuditLog(AUDIT_SECURITY
, FALSE
, m_dwUserId
, m_workstation
, m_id
, 0,
1987 _T("User \"%s\" login failed with error code %d (client info: %s)"),
1988 szLogin
, dwResult
, m_clientInfo
);
1989 if (intruderLockout
)
1991 WriteAuditLog(AUDIT_SECURITY
, FALSE
, m_dwUserId
, m_workstation
, m_id
, 0,
1992 _T("User account \"%s\" temporary disabled due to excess count of failed authentication attempts"), szLogin
);
1998 msg
.setField(VID_RCC
, RCC_OUT_OF_STATE_REQUEST
);
2006 * Send event configuration to client
2008 void ClientSession::sendEventDB(UINT32 dwRqId
)
2011 TCHAR szBuffer
[4096];
2013 // Prepare response message
2014 msg
.setCode(CMD_REQUEST_COMPLETED
);
2017 if (checkSysAccessRights(SYSTEM_ACCESS_VIEW_EVENT_DB
) || checkSysAccessRights(SYSTEM_ACCESS_EDIT_EVENT_DB
) || checkSysAccessRights(SYSTEM_ACCESS_EPP
))
2019 if (!(g_flags
& AF_DB_CONNECTION_LOST
))
2021 msg
.setField(VID_RCC
, RCC_SUCCESS
);
2023 msg
.deleteAllFields();
2025 // Prepare data message
2026 msg
.setCode(CMD_EVENT_DB_RECORD
);
2029 DB_HANDLE hdb
= DBConnectionPoolAcquireConnection();
2030 DB_UNBUFFERED_RESULT hResult
= DBSelectUnbuffered(hdb
, _T("SELECT event_code,event_name,severity,flags,message,description FROM event_cfg"));
2031 if (hResult
!= NULL
)
2033 while(DBFetch(hResult
))
2035 msg
.setField(VID_EVENT_CODE
, DBGetFieldULong(hResult
, 0));
2036 msg
.setField(VID_NAME
, DBGetField(hResult
, 1, szBuffer
, 1024));
2037 msg
.setField(VID_SEVERITY
, DBGetFieldULong(hResult
, 2));
2038 msg
.setField(VID_FLAGS
, DBGetFieldULong(hResult
, 3));
2040 DBGetField(hResult
, 4, szBuffer
, 4096);
2041 msg
.setField(VID_MESSAGE
, szBuffer
);
2043 DBGetField(hResult
, 5, szBuffer
, 4096);
2044 msg
.setField(VID_DESCRIPTION
, szBuffer
);
2047 msg
.deleteAllFields();
2049 DBFreeResult(hResult
);
2051 DBConnectionPoolReleaseConnection(hdb
);
2053 // End-of-list indicator
2054 msg
.setField(VID_EVENT_CODE
, (UINT32
)0);
2055 msg
.setEndOfSequence();
2059 msg
.setField(VID_RCC
, RCC_DB_CONNECTION_LOST
);
2064 msg
.setField(VID_RCC
, RCC_ACCESS_DENIED
);
2070 * Callback for sending event configuration change notifications
2072 static void SendEventDBChangeNotification(ClientSession
*session
, void *arg
)
2074 if (session
->isAuthenticated() &&
2075 (session
->checkSysAccessRights(SYSTEM_ACCESS_VIEW_EVENT_DB
) ||
2076 session
->checkSysAccessRights(SYSTEM_ACCESS_EDIT_EVENT_DB
) ||
2077 session
->checkSysAccessRights(SYSTEM_ACCESS_EPP
)))
2078 session
->postMessage((NXCPMessage
*)arg
);
2082 * Update event template
2084 void ClientSession::modifyEventTemplate(NXCPMessage
*pRequest
)
2088 // Prepare reply message
2089 msg
.setCode(CMD_REQUEST_COMPLETED
);
2090 msg
.setId(pRequest
->getId());
2092 // Check access rights
2093 if (checkSysAccessRights(SYSTEM_ACCESS_EDIT_EVENT_DB
))
2095 DB_HANDLE hdb
= DBConnectionPoolAcquireConnection();
2097 // Check if event with specific code exists
2098 UINT32 dwEventCode
= pRequest
->getFieldAsUInt32(VID_EVENT_CODE
);
2099 bool bEventExist
= IsDatabaseRecordExist(hdb
, _T("event_cfg"), _T("event_code"), dwEventCode
);
2101 // Check that we are not trying to create event below 100000
2102 if (bEventExist
|| (dwEventCode
>= FIRST_USER_EVENT_ID
))
2104 // Prepare and execute SQL query
2105 TCHAR name
[MAX_EVENT_NAME
];
2106 pRequest
->getFieldAsString(VID_NAME
, name
, MAX_EVENT_NAME
);
2107 if (IsValidObjectName(name
, TRUE
))
2112 hStmt
= DBPrepare(hdb
, _T("UPDATE event_cfg SET event_name=?,severity=?,flags=?,message=?,description=? WHERE event_code=?"));
2116 hStmt
= DBPrepare(hdb
, _T("INSERT INTO event_cfg (event_name,severity,flags,message,description,event_code,guid) VALUES (?,?,?,?,?,?,?)"));
2121 DBBind(hStmt
, 1, DB_SQLTYPE_VARCHAR
, name
, DB_BIND_STATIC
);
2122 DBBind(hStmt
, 2, DB_SQLTYPE_INTEGER
, pRequest
->getFieldAsInt32(VID_SEVERITY
));
2123 DBBind(hStmt
, 3, DB_SQLTYPE_INTEGER
, pRequest
->getFieldAsInt32(VID_FLAGS
));
2124 DBBind(hStmt
, 4, DB_SQLTYPE_VARCHAR
, pRequest
->getFieldAsString(VID_MESSAGE
), DB_BIND_DYNAMIC
, MAX_EVENT_MSG_LENGTH
- 1);
2125 DBBind(hStmt
, 5, DB_SQLTYPE_TEXT
, pRequest
->getFieldAsString(VID_DESCRIPTION
), DB_BIND_DYNAMIC
);
2126 DBBind(hStmt
, 6, DB_SQLTYPE_INTEGER
, dwEventCode
);
2129 DBBind(hStmt
, 7, DB_SQLTYPE_VARCHAR
, uuid::generate());
2132 if (DBExecute(hStmt
))
2134 msg
.setField(VID_RCC
, RCC_SUCCESS
);
2137 NXCPMessage
nmsg(pRequest
);
2138 nmsg
.setCode(CMD_EVENT_DB_UPDATE
);
2139 nmsg
.setField(VID_NOTIFICATION_CODE
, (WORD
)NX_NOTIFY_ETMPL_CHANGED
);
2140 EnumerateClientSessions(SendEventDBChangeNotification
, &nmsg
);
2144 msg
.setField(VID_RCC
, RCC_DB_FAILURE
);
2146 DBFreeStatement(hStmt
);
2150 msg
.setField(VID_RCC
, RCC_DB_FAILURE
);
2155 msg
.setField(VID_RCC
, RCC_INVALID_OBJECT_NAME
);
2160 msg
.setField(VID_RCC
, RCC_INVALID_EVENT_CODE
);
2162 DBConnectionPoolReleaseConnection(hdb
);
2166 msg
.setField(VID_RCC
, RCC_ACCESS_DENIED
);
2174 * Delete event template
2176 void ClientSession::deleteEventTemplate(NXCPMessage
*pRequest
)
2181 // Prepare reply message
2182 msg
.setCode(CMD_REQUEST_COMPLETED
);
2183 msg
.setId(pRequest
->getId());
2185 dwEventCode
= pRequest
->getFieldAsUInt32(VID_EVENT_CODE
);
2187 // Check access rights
2188 if (checkSysAccessRights(SYSTEM_ACCESS_EDIT_EVENT_DB
) && (dwEventCode
>= FIRST_USER_EVENT_ID
))
2190 DB_HANDLE hdb
= DBConnectionPoolAcquireConnection();
2192 _sntprintf(szQuery
, 256, _T("DELETE FROM event_cfg WHERE event_code=%d"), dwEventCode
);
2193 if (DBQuery(hdb
, szQuery
))
2195 DeleteEventTemplateFromList(dwEventCode
);
2198 nmsg
.setCode(CMD_EVENT_DB_UPDATE
);
2199 nmsg
.setField(VID_NOTIFICATION_CODE
, (WORD
)NX_NOTIFY_ETMPL_DELETED
);
2200 nmsg
.setField(VID_EVENT_CODE
, dwEventCode
);
2201 EnumerateClientSessions(SendEventDBChangeNotification
, &nmsg
);
2203 msg
.setField(VID_RCC
, RCC_SUCCESS
);
2205 WriteAuditLog(AUDIT_SYSCFG
, TRUE
, m_dwUserId
, m_workstation
, m_id
, 0, _T("Event template %d deleted"), dwEventCode
);
2209 msg
.setField(VID_RCC
, RCC_DB_FAILURE
);
2211 DBConnectionPoolReleaseConnection(hdb
);
2215 msg
.setField(VID_RCC
, RCC_ACCESS_DENIED
);
2223 * Generate event code for new event template
2225 void ClientSession::generateEventCode(UINT32 dwRqId
)
2229 // Prepare reply message
2230 msg
.setCode(CMD_REQUEST_COMPLETED
);
2233 // Check access rights
2234 if (checkSysAccessRights(SYSTEM_ACCESS_EDIT_EVENT_DB
))
2236 msg
.setField(VID_EVENT_CODE
, CreateUniqueId(IDG_EVENT
));
2240 msg
.setField(VID_RCC
, RCC_ACCESS_DENIED
);
2248 * Data for session object filter
2250 struct SessionObjectFilterData
2252 ClientSession
*session
;
2253 time_t baseTimeStamp
;
2257 * Object filter for ClientSession::sendAllObjects
2259 static bool SessionObjectFilter(NetObj
*object
, void *data
)
2261 return !object
->isHidden() && !object
->isSystem() && !object
->isDeleted() &&
2262 (object
->getTimeStamp() >= ((SessionObjectFilterData
*)data
)->baseTimeStamp
) &&
2263 object
->checkAccessRights(((SessionObjectFilterData
*)data
)->session
->getUserId(), OBJECT_ACCESS_READ
);
2267 * Send all objects to client
2269 void ClientSession::sendAllObjects(NXCPMessage
*pRequest
)
2273 // Send confirmation message
2274 msg
.setCode(CMD_REQUEST_COMPLETED
);
2275 msg
.setId(pRequest
->getId());
2276 msg
.setField(VID_RCC
, RCC_SUCCESS
);
2278 msg
.deleteAllFields();
2280 // Change "sync comments" flag
2281 if (pRequest
->getFieldAsUInt16(VID_SYNC_COMMENTS
))
2282 m_dwFlags
|= CSF_SYNC_OBJECT_COMMENTS
;
2284 m_dwFlags
&= ~CSF_SYNC_OBJECT_COMMENTS
;
2287 msg
.setCode(CMD_OBJECT
);
2289 // Send objects, one per message
2290 SessionObjectFilterData data
;
2291 data
.session
= this;
2292 data
.baseTimeStamp
= pRequest
->getFieldAsTime(VID_TIMESTAMP
);
2293 ObjectArray
<NetObj
> *objects
= g_idxObjectById
.getObjects(true, SessionObjectFilter
, &data
);
2294 MutexLock(m_mutexSendObjects
);
2295 for(int i
= 0; i
< objects
->size(); i
++)
2297 NetObj
*object
= objects
->get(i
);
2298 object
->fillMessage(&msg
);
2299 if (m_dwFlags
& CSF_SYNC_OBJECT_COMMENTS
)
2300 object
->commentsToMessage(&msg
);
2301 if (!object
->checkAccessRights(m_dwUserId
, OBJECT_ACCESS_MODIFY
))
2304 msg
.setField(VID_SHARED_SECRET
, _T("********"));
2305 msg
.setField(VID_SNMP_AUTH_PASSWORD
, _T("********"));
2306 msg
.setField(VID_SNMP_PRIV_PASSWORD
, _T("********"));
2309 msg
.deleteAllFields();
2310 object
->decRefCount();
2314 // Send end of list notification
2315 msg
.setCode(CMD_OBJECT_LIST_END
);
2318 MutexUnlock(m_mutexSendObjects
);
2322 * Send selected objects to client
2324 void ClientSession::sendSelectedObjects(NXCPMessage
*pRequest
)
2328 // Send confirmation message
2329 msg
.setCode(CMD_REQUEST_COMPLETED
);
2330 msg
.setId(pRequest
->getId());
2331 msg
.setField(VID_RCC
, RCC_SUCCESS
);
2333 msg
.deleteAllFields();
2335 // Change "sync comments" flag
2336 if (pRequest
->getFieldAsBoolean(VID_SYNC_COMMENTS
))
2337 m_dwFlags
|= CSF_SYNC_OBJECT_COMMENTS
;
2339 m_dwFlags
&= ~CSF_SYNC_OBJECT_COMMENTS
;
2341 UINT32 dwTimeStamp
= pRequest
->getFieldAsUInt32(VID_TIMESTAMP
);
2342 UINT32 numObjects
= pRequest
->getFieldAsUInt32(VID_NUM_OBJECTS
);
2343 UINT32
*objects
= (UINT32
*)malloc(sizeof(UINT32
) * numObjects
);
2344 pRequest
->getFieldAsInt32Array(VID_OBJECT_LIST
, numObjects
, objects
);
2345 UINT32 options
= pRequest
->getFieldAsUInt16(VID_FLAGS
);
2347 MutexLock(m_mutexSendObjects
);
2350 msg
.setCode((options
& OBJECT_SYNC_SEND_UPDATES
) ? CMD_OBJECT_UPDATE
: CMD_OBJECT
);
2352 // Send objects, one per message
2353 for(UINT32 i
= 0; i
< numObjects
; i
++)
2355 NetObj
*object
= FindObjectById(objects
[i
]);
2356 if ((object
!= NULL
) &&
2357 object
->checkAccessRights(m_dwUserId
, OBJECT_ACCESS_READ
) &&
2358 (object
->getTimeStamp() >= dwTimeStamp
) &&
2359 !object
->isHidden() && !object
->isSystem())
2361 object
->fillMessage(&msg
);
2362 if (m_dwFlags
& CSF_SYNC_OBJECT_COMMENTS
)
2363 object
->commentsToMessage(&msg
);
2364 if (!object
->checkAccessRights(m_dwUserId
, OBJECT_ACCESS_MODIFY
))
2367 msg
.setField(VID_SHARED_SECRET
, _T("********"));
2368 msg
.setField(VID_SNMP_AUTH_PASSWORD
, _T("********"));
2369 msg
.setField(VID_SNMP_PRIV_PASSWORD
, _T("********"));
2372 msg
.deleteAllFields();
2376 MutexUnlock(m_mutexSendObjects
);
2379 if (options
& OBJECT_SYNC_DUAL_CONFIRM
)
2381 msg
.setCode(CMD_REQUEST_COMPLETED
);
2382 msg
.setField(VID_RCC
, RCC_SUCCESS
);
2388 * Send event log records to client
2390 void ClientSession::sendEventLog(NXCPMessage
*pRequest
)
2393 DB_RESULT hTempResult
;
2394 UINT32 dwRqId
, dwMaxRecords
, dwNumRows
, dwId
;
2395 TCHAR szQuery
[1024], szBuffer
[1024];
2398 dwRqId
= pRequest
->getId();
2399 dwMaxRecords
= pRequest
->getFieldAsUInt32(VID_MAX_RECORDS
);
2400 wRecOrder
= ((g_dbSyntax
== DB_SYNTAX_MSSQL
) || (g_dbSyntax
== DB_SYNTAX_ORACLE
)) ? RECORD_ORDER_REVERSED
: RECORD_ORDER_NORMAL
;
2402 // Prepare confirmation message
2403 msg
.setCode(CMD_REQUEST_COMPLETED
);
2406 MutexLock(m_mutexSendEvents
);
2407 DB_HANDLE hdb
= DBConnectionPoolAcquireConnection();
2409 // Retrieve events from database
2412 case DB_SYNTAX_MYSQL
:
2413 case DB_SYNTAX_PGSQL
:
2414 case DB_SYNTAX_SQLITE
:
2416 hTempResult
= DBSelect(hdb
, _T("SELECT count(*) FROM event_log"));
2417 if (hTempResult
!= NULL
)
2419 if (DBGetNumRows(hTempResult
) > 0)
2421 dwNumRows
= DBGetFieldULong(hTempResult
, 0, 0);
2423 DBFreeResult(hTempResult
);
2425 _sntprintf(szQuery
, 1024,
2426 _T("SELECT event_id,event_code,event_timestamp,event_source,")
2427 _T("event_severity,event_message,user_tag FROM event_log ")
2428 _T("ORDER BY event_id LIMIT %u OFFSET %u"),
2429 dwMaxRecords
, dwNumRows
- min(dwNumRows
, dwMaxRecords
));
2431 case DB_SYNTAX_MSSQL
:
2432 _sntprintf(szQuery
, 1024,
2433 _T("SELECT TOP %u event_id,event_code,event_timestamp,event_source,")
2434 _T("event_severity,event_message,user_tag FROM event_log ")
2435 _T("ORDER BY event_id DESC"), dwMaxRecords
);
2437 case DB_SYNTAX_ORACLE
:
2438 _sntprintf(szQuery
, 1024,
2439 _T("SELECT event_id,event_code,event_timestamp,event_source,")
2440 _T("event_severity,event_message,user_tag FROM event_log ")
2441 _T("WHERE ROWNUM <= %u ORDER BY event_id DESC"), dwMaxRecords
);
2444 _sntprintf(szQuery
, 1024,
2445 _T("SELECT event_id,event_code,event_timestamp,event_source,")
2446 _T("event_severity,event_message,user_tag FROM event_log ")
2447 _T("ORDER BY event_id DESC FETCH FIRST %u ROWS ONLY"), dwMaxRecords
);
2453 DB_UNBUFFERED_RESULT hResult
= DBSelectUnbuffered(hdb
, szQuery
);
2454 if (hResult
!= NULL
)
2456 msg
.setField(VID_RCC
, RCC_SUCCESS
);
2458 msg
.deleteAllFields();
2459 msg
.setCode(CMD_EVENTLOG_RECORDS
);
2461 for(dwId
= VID_EVENTLOG_MSG_BASE
, dwNumRows
= 0; DBFetch(hResult
); dwNumRows
++)
2463 if (dwNumRows
== 10)
2465 msg
.setField(VID_NUM_RECORDS
, dwNumRows
);
2466 msg
.setField(VID_RECORDS_ORDER
, wRecOrder
);
2468 msg
.deleteAllFields();
2470 dwId
= VID_EVENTLOG_MSG_BASE
;
2472 msg
.setField(dwId
++, DBGetFieldUInt64(hResult
, 0));
2473 msg
.setField(dwId
++, DBGetFieldULong(hResult
, 1));
2474 msg
.setField(dwId
++, DBGetFieldULong(hResult
, 2));
2475 msg
.setField(dwId
++, DBGetFieldULong(hResult
, 3));
2476 msg
.setField(dwId
++, (WORD
)DBGetFieldLong(hResult
, 4));
2477 DBGetField(hResult
, 5, szBuffer
, 1024);
2478 msg
.setField(dwId
++, szBuffer
);
2479 DBGetField(hResult
, 6, szBuffer
, 1024);
2480 msg
.setField(dwId
++, szBuffer
);
2481 msg
.setField(dwId
++, (UINT32
)0); // Do not send parameters
2483 DBFreeResult(hResult
);
2485 // Send remaining records with End-Of-Sequence notification
2486 msg
.setField(VID_NUM_RECORDS
, dwNumRows
);
2487 msg
.setField(VID_RECORDS_ORDER
, wRecOrder
);
2488 msg
.setEndOfSequence();
2493 msg
.setField(VID_RCC
, RCC_DB_FAILURE
);
2497 DBConnectionPoolReleaseConnection(hdb
);
2498 MutexUnlock(m_mutexSendEvents
);
2502 * Send all configuration variables to client
2504 void ClientSession::getConfigurationVariables(UINT32 dwRqId
)
2506 UINT32 i
, dwId
, dwNumRecords
;
2508 TCHAR szBuffer
[MAX_CONFIG_VALUE
];
2511 msg
.setCode(CMD_REQUEST_COMPLETED
);
2514 // Check user rights
2515 if ((m_dwUserId
== 0) || (m_dwSystemAccess
& SYSTEM_ACCESS_SERVER_CONFIG
))
2517 DB_HANDLE hdb
= DBConnectionPoolAcquireConnection();
2519 // Retrieve configuration variables from database
2520 DB_RESULT hResult
= DBSelect(hdb
, _T("SELECT var_name,var_value,need_server_restart FROM config WHERE is_visible=1"));
2521 if (hResult
!= NULL
)
2523 // Send events, one per message
2524 dwNumRecords
= DBGetNumRows(hResult
);
2525 msg
.setField(VID_NUM_VARIABLES
, dwNumRecords
);
2526 for(i
= 0, dwId
= VID_VARLIST_BASE
; i
< dwNumRecords
; i
++)
2528 msg
.setField(dwId
++, DBGetField(hResult
, i
, 0, szBuffer
, MAX_DB_STRING
));
2529 DBGetField(hResult
, i
, 1, szBuffer
, MAX_CONFIG_VALUE
);
2530 DecodeSQLString(szBuffer
);
2531 msg
.setField(dwId
++, szBuffer
);
2532 msg
.setField(dwId
++, (WORD
)DBGetFieldLong(hResult
, i
, 2));
2534 DBFreeResult(hResult
);
2536 DBConnectionPoolReleaseConnection(hdb
);
2537 msg
.setField(VID_RCC
, RCC_SUCCESS
);
2541 msg
.setField(VID_RCC
, RCC_ACCESS_DENIED
);
2549 * Get public configuration variable by name
2551 void ClientSession::getPublicConfigurationVariable(NXCPMessage
*request
)
2554 msg
.setCode(CMD_REQUEST_COMPLETED
);
2555 msg
.setId(request
->getId());
2557 DB_HANDLE hdb
= DBConnectionPoolAcquireConnection();
2559 DB_STATEMENT hStmt
= DBPrepare(hdb
, _T("SELECT var_value FROM config WHERE var_name=? AND is_public='Y'"));
2563 request
->getFieldAsString(VID_NAME
, name
, 64);
2564 DBBind(hStmt
, 1, DB_SQLTYPE_VARCHAR
, name
, DB_BIND_STATIC
);
2566 DB_RESULT hResult
= DBSelectPrepared(hStmt
);
2567 if (hResult
!= NULL
)
2569 if (DBGetNumRows(hResult
) > 0)
2571 TCHAR value
[MAX_CONFIG_VALUE
];
2572 msg
.setField(VID_VALUE
, DBGetField(hResult
, 0, 0, value
, MAX_CONFIG_VALUE
));
2573 msg
.setField(VID_RCC
, RCC_SUCCESS
);
2577 msg
.setField(VID_RCC
, RCC_UNKNOWN_CONFIG_VARIABLE
);
2579 DBFreeResult(hResult
);
2583 msg
.setField(VID_RCC
, RCC_DB_FAILURE
);
2585 DBFreeStatement(hStmt
);
2589 msg
.setField(VID_RCC
, RCC_DB_FAILURE
);
2596 * Set configuration variable's value
2598 void ClientSession::setConfigurationVariable(NXCPMessage
*pRequest
)
2601 TCHAR szName
[MAX_OBJECT_NAME
], szValue
[MAX_CONFIG_VALUE
];
2603 // Prepare response message
2604 msg
.setCode(CMD_REQUEST_COMPLETED
);
2605 msg
.setId(pRequest
->getId());
2607 // Check user rights
2608 if ((m_dwUserId
== 0) || (m_dwSystemAccess
& SYSTEM_ACCESS_SERVER_CONFIG
))
2610 pRequest
->getFieldAsString(VID_NAME
, szName
, MAX_OBJECT_NAME
);
2611 pRequest
->getFieldAsString(VID_VALUE
, szValue
, MAX_CONFIG_VALUE
);
2612 if (ConfigWriteStr(szName
, szValue
, true))
2614 msg
.setField(VID_RCC
, RCC_SUCCESS
);
2615 WriteAuditLog(AUDIT_SYSCFG
, TRUE
, m_dwUserId
, m_workstation
, m_id
, 0,
2616 _T("Server configuration variable \"%s\" set to \"%s\""), szName
, szValue
);
2620 msg
.setField(VID_RCC
, RCC_DB_FAILURE
);
2625 msg
.setField(VID_RCC
, RCC_ACCESS_DENIED
);
2633 * Delete configuration variable
2635 void ClientSession::deleteConfigurationVariable(NXCPMessage
*pRequest
)
2639 // Prepare response message
2640 msg
.setCode(CMD_REQUEST_COMPLETED
);
2641 msg
.setId(pRequest
->getId());
2643 // Check user rights
2644 if ((m_dwUserId
== 0) || (m_dwSystemAccess
& SYSTEM_ACCESS_SERVER_CONFIG
))
2646 TCHAR name
[MAX_OBJECT_NAME
];
2647 pRequest
->getFieldAsString(VID_NAME
, name
, MAX_OBJECT_NAME
);
2648 if (ConfigDelete(name
))
2650 msg
.setField(VID_RCC
, RCC_SUCCESS
);
2651 WriteAuditLog(AUDIT_SYSCFG
, TRUE
, m_dwUserId
, m_workstation
, m_id
, 0, _T("Server configuration variable \"%s\" deleted"), name
);
2655 msg
.setField(VID_RCC
, RCC_DB_FAILURE
);
2660 msg
.setField(VID_RCC
, RCC_ACCESS_DENIED
);
2668 * Set configuration clob
2670 void ClientSession::setConfigCLOB(NXCPMessage
*pRequest
)
2673 TCHAR name
[MAX_OBJECT_NAME
], *value
;
2675 msg
.setId(pRequest
->getId());
2676 msg
.setCode(CMD_REQUEST_COMPLETED
);
2678 if (m_dwSystemAccess
& SYSTEM_ACCESS_SERVER_CONFIG
)
2680 pRequest
->getFieldAsString(VID_NAME
, name
, MAX_OBJECT_NAME
);
2681 value
= pRequest
->getFieldAsString(VID_VALUE
);
2684 if (ConfigWriteCLOB(name
, value
, TRUE
))
2686 msg
.setField(VID_RCC
, RCC_SUCCESS
);
2687 WriteAuditLog(AUDIT_SYSCFG
, TRUE
, m_dwUserId
, m_workstation
, m_id
, 0,
2688 _T("Server configuration variable \"%s\" set to \"%s\""), name
, value
);
2693 msg
.setField(VID_RCC
, RCC_DB_FAILURE
);
2698 msg
.setField(VID_RCC
, RCC_INVALID_REQUEST
);
2703 msg
.setField(VID_RCC
, RCC_ACCESS_DENIED
);
2710 * Get value of configuration clob
2712 void ClientSession::getConfigCLOB(NXCPMessage
*pRequest
)
2715 TCHAR name
[MAX_OBJECT_NAME
], *value
;
2717 msg
.setId(pRequest
->getId());
2718 msg
.setCode(CMD_REQUEST_COMPLETED
);
2720 if (m_dwSystemAccess
& SYSTEM_ACCESS_SERVER_CONFIG
)
2722 pRequest
->getFieldAsString(VID_NAME
, name
, MAX_OBJECT_NAME
);
2723 value
= ConfigReadCLOB(name
, NULL
);
2726 msg
.setField(VID_VALUE
, value
);
2727 msg
.setField(VID_RCC
, RCC_SUCCESS
);
2732 msg
.setField(VID_RCC
, RCC_UNKNOWN_VARIABLE
);
2737 msg
.setField(VID_RCC
, RCC_ACCESS_DENIED
);
2746 void ClientSession::kill()
2748 notify(NX_NOTIFY_SESSION_KILLED
);
2750 // We shutdown socket connection, which will cause
2751 // read thread to stop, and other threads will follow
2752 shutdown(m_hSocket
, 2);
2756 * Handler for new events
2758 void ClientSession::onNewEvent(Event
*pEvent
)
2760 UPDATE_INFO
*pUpdate
;
2762 if (isAuthenticated() && isSubscribedTo(NXC_CHANNEL_EVENTS
) && (m_dwSystemAccess
& SYSTEM_ACCESS_VIEW_EVENT_LOG
))
2764 NetObj
*object
= FindObjectById(pEvent
->getSourceId());
2765 //If can't find object - just send to all events, if object found send to thous who have rights
2766 if (object
== NULL
|| object
->checkAccessRights(m_dwUserId
, OBJECT_ACCESS_READ
))
2768 pUpdate
= (UPDATE_INFO
*)malloc(sizeof(UPDATE_INFO
));
2769 pUpdate
->dwCategory
= INFO_CAT_EVENT
;
2770 msg
= new NXCPMessage
;
2771 msg
->setCode(CMD_EVENTLOG_RECORDS
);
2772 pEvent
->prepareMessage(msg
);
2773 pUpdate
->pData
= msg
;
2774 m_pUpdateQueue
->put(pUpdate
);
2780 * Handler for object changes
2782 void ClientSession::onObjectChange(NetObj
*object
)
2784 UPDATE_INFO
*pUpdate
;
2786 if (isAuthenticated() && isSubscribedTo(NXC_CHANNEL_OBJECTS
))
2787 if (object
->isDeleted() || object
->checkAccessRights(m_dwUserId
, OBJECT_ACCESS_READ
))
2789 pUpdate
= (UPDATE_INFO
*)malloc(sizeof(UPDATE_INFO
));
2790 pUpdate
->dwCategory
= INFO_CAT_OBJECT_CHANGE
;
2791 pUpdate
->pData
= object
;
2792 object
->incRefCount();
2793 m_pUpdateQueue
->put(pUpdate
);
2798 * Send notification message to server
2800 void ClientSession::notify(UINT32 dwCode
, UINT32 dwData
)
2804 msg
.setCode(CMD_NOTIFY
);
2805 msg
.setField(VID_NOTIFICATION_CODE
, dwCode
);
2806 msg
.setField(VID_NOTIFICATION_DATA
, dwData
);
2810 static void SetNodesConflictString(NXCPMessage
*msg
, UINT32 zoneId
, InetAddress ipAddr
)
2812 if(ipAddr
.isValid())
2816 Node
*sameNode
= FindNodeByIP(zoneId
, ipAddr
);
2817 Subnet
*sameSubnet
= FindSubnetByIP(zoneId
, ipAddr
);
2818 if(sameNode
!= NULL
)
2820 _sntprintf(value
, 512, _T("%s"), sameNode
->getName());
2822 else if (sameSubnet
!= NULL
)
2824 _sntprintf(value
, 512, _T("%s"), sameSubnet
->getName());
2828 _tcscpy(value
, _T(""));
2830 msg
->setField(VID_VALUE
, value
);
2837 void ClientSession::modifyObject(NXCPMessage
*pRequest
)
2839 UINT32 dwObjectId
, dwResult
= RCC_SUCCESS
;
2843 // Prepare reply message
2844 msg
.setCode(CMD_REQUEST_COMPLETED
);
2845 msg
.setId(pRequest
->getId());
2847 dwObjectId
= pRequest
->getFieldAsUInt32(VID_OBJECT_ID
);
2848 object
= FindObjectById(dwObjectId
);
2851 if (object
->checkAccessRights(m_dwUserId
, OBJECT_ACCESS_MODIFY
))
2853 // If user attempts to change object's ACL, check
2854 // if he has OBJECT_ACCESS_ACL permission
2855 if (pRequest
->isFieldExist(VID_ACL_SIZE
))
2856 if (!object
->checkAccessRights(m_dwUserId
, OBJECT_ACCESS_ACL
))
2857 dwResult
= RCC_ACCESS_DENIED
;
2859 // If user attempts to rename object, check object's name
2860 if (pRequest
->isFieldExist(VID_OBJECT_NAME
))
2863 pRequest
->getFieldAsString(VID_OBJECT_NAME
, name
, 256);
2864 if (!IsValidObjectName(name
, TRUE
))
2865 dwResult
= RCC_INVALID_OBJECT_NAME
;
2868 // If allowed, change object and set completion code
2869 if (dwResult
== RCC_SUCCESS
)
2871 dwResult
= object
->modifyFromMessage(pRequest
);
2872 if (dwResult
== RCC_SUCCESS
)
2874 object
->postModify();
2876 else if (dwResult
== RCC_ALREADY_EXIST
)
2878 //Add information about conflicting nodes
2881 if (pRequest
->isFieldExist(VID_IP_ADDRESS
))
2883 ipAddr
= pRequest
->getFieldAsInetAddress(VID_IP_ADDRESS
);
2884 } else if (pRequest
->isFieldExist(VID_PRIMARY_NAME
))
2886 TCHAR primaryName
[MAX_DNS_NAME
];
2887 pRequest
->getFieldAsString(VID_PRIMARY_NAME
, primaryName
, MAX_DNS_NAME
);
2888 ipAddr
= InetAddress::resolveHostName(primaryName
);
2890 SetNodesConflictString(&msg
, ((Node
*)object
)->getZoneId(), ipAddr
);
2893 msg
.setField(VID_RCC
, dwResult
);
2895 if (dwResult
== RCC_SUCCESS
)
2897 WriteAuditLog(AUDIT_OBJECTS
, TRUE
, m_dwUserId
, m_workstation
, m_id
, dwObjectId
,
2898 _T("Object %s modified from client"), object
->getName());
2902 WriteAuditLog(AUDIT_OBJECTS
, FALSE
, m_dwUserId
, m_workstation
, m_id
, dwObjectId
,
2903 _T("Failed to modify object from client - error %d"), dwResult
);
2908 msg
.setField(VID_RCC
, RCC_ACCESS_DENIED
);
2909 WriteAuditLog(AUDIT_OBJECTS
, FALSE
, m_dwUserId
, m_workstation
, m_id
, dwObjectId
,
2910 _T("Failed to modify object from client - access denied"), dwResult
);
2915 msg
.setField(VID_RCC
, RCC_INVALID_OBJECT_ID
);
2923 * Send users database to client
2925 void ClientSession::sendUserDB(UINT32 dwRqId
)
2928 msg
.setCode(CMD_REQUEST_COMPLETED
);
2930 msg
.setField(VID_RCC
, RCC_SUCCESS
);
2932 msg
.deleteAllFields();
2934 // Send user database
2935 Iterator
<UserDatabaseObject
> *users
= OpenUserDatabase();
2936 while(users
->hasNext())
2938 UserDatabaseObject
*object
= users
->next();
2939 msg
.setCode(object
->isGroup() ? CMD_GROUP_DATA
: CMD_USER_DATA
);
2940 object
->fillMessage(&msg
);
2942 msg
.deleteAllFields();
2944 CloseUserDatabase(users
);
2946 // Send end-of-database notification
2947 msg
.setCode(CMD_USER_DB_EOF
);
2954 void ClientSession::createUser(NXCPMessage
*pRequest
)
2958 // Prepare response message
2959 msg
.setCode(CMD_REQUEST_COMPLETED
);
2960 msg
.setId(pRequest
->getId());
2962 // Check user rights
2963 if (!(m_dwSystemAccess
& SYSTEM_ACCESS_MANAGE_USERS
))
2965 msg
.setField(VID_RCC
, RCC_ACCESS_DENIED
);
2967 else if (!(m_dwFlags
& CSF_USER_DB_LOCKED
))
2969 // User database have to be locked before any
2970 // changes to user database can be made
2971 msg
.setField(VID_RCC
, RCC_OUT_OF_STATE_REQUEST
);
2975 UINT32 dwResult
, dwUserId
;
2976 TCHAR szUserName
[MAX_USER_NAME
];
2978 pRequest
->getFieldAsString(VID_USER_NAME
, szUserName
, MAX_USER_NAME
);
2979 if (IsValidObjectName(szUserName
))
2981 bool isGroup
= pRequest
->getFieldAsBoolean(VID_IS_GROUP
);
2982 dwResult
= CreateNewUser(szUserName
, isGroup
, &dwUserId
);
2983 msg
.setField(VID_RCC
, dwResult
);
2984 if (dwResult
== RCC_SUCCESS
)
2986 msg
.setField(VID_USER_ID
, dwUserId
); // Send id of new user to client
2987 WriteAuditLog(AUDIT_SECURITY
, TRUE
, m_dwUserId
, m_workstation
, m_id
, dwUserId
, _T("%s %s created"), isGroup
? _T("Group") : _T("User"), szUserName
);
2992 msg
.setField(VID_RCC
, RCC_INVALID_OBJECT_NAME
);
3001 * Update existing user's data
3003 void ClientSession::updateUser(NXCPMessage
*pRequest
)
3007 // Prepare response message
3008 msg
.setCode(CMD_REQUEST_COMPLETED
);
3009 msg
.setId(pRequest
->getId());
3011 // Check user rights
3012 if (!(m_dwSystemAccess
& SYSTEM_ACCESS_MANAGE_USERS
))
3014 msg
.setField(VID_RCC
, RCC_ACCESS_DENIED
);
3016 else if (!(m_dwFlags
& CSF_USER_DB_LOCKED
))
3018 // User database have to be locked before any
3019 // changes to user database can be made
3020 msg
.setField(VID_RCC
, RCC_OUT_OF_STATE_REQUEST
);
3024 UINT32 result
= ModifyUserDatabaseObject(pRequest
);
3025 if (result
== RCC_SUCCESS
)
3027 TCHAR name
[MAX_DB_STRING
];
3028 UINT32 id
= pRequest
->getFieldAsUInt32(VID_USER_ID
);
3029 ResolveUserId(id
, name
, MAX_DB_STRING
);
3030 WriteAuditLog(AUDIT_SECURITY
, TRUE
, m_dwUserId
, m_workstation
, m_id
, id
,
3031 _T("%s %s modified"), (id
& GROUP_FLAG
) ? _T("Group") : _T("User"), name
);
3033 msg
.setField(VID_RCC
, result
);
3043 void ClientSession::detachLdapUser(NXCPMessage
*pRequest
)
3047 // Prepare response message
3048 msg
.setCode(CMD_REQUEST_COMPLETED
);
3049 msg
.setId(pRequest
->getId());
3050 UINT32 id
= pRequest
->getFieldAsUInt32(VID_USER_ID
);
3052 // Check user rights
3053 if (!(m_dwSystemAccess
& SYSTEM_ACCESS_MANAGE_USERS
))
3055 msg
.setField(VID_RCC
, RCC_ACCESS_DENIED
);
3057 else if (!(m_dwFlags
& CSF_USER_DB_LOCKED
))
3059 // User database have to be locked before any
3060 // changes to user database can be made
3061 msg
.setField(VID_RCC
, RCC_OUT_OF_STATE_REQUEST
);
3065 UINT32 result
= DetachLdapUser(id
);
3066 if (result
== RCC_SUCCESS
)
3068 TCHAR name
[MAX_DB_STRING
];
3069 ResolveUserId(id
, name
, MAX_DB_STRING
);
3070 WriteAuditLog(AUDIT_SECURITY
, TRUE
, m_dwUserId
, m_workstation
, m_id
, id
,
3071 _T("%s %s modified"), (id
& GROUP_FLAG
) ? _T("Group") : _T("User"), name
);
3073 msg
.setField(VID_RCC
, result
);
3083 void ClientSession::deleteUser(NXCPMessage
*pRequest
)
3088 // Prepare response message
3089 msg
.setCode(CMD_REQUEST_COMPLETED
);
3090 msg
.setId(pRequest
->getId());
3092 // Check user rights
3093 if (!(m_dwSystemAccess
& SYSTEM_ACCESS_MANAGE_USERS
))
3095 msg
.setField(VID_RCC
, RCC_ACCESS_DENIED
);
3097 else if (!(m_dwFlags
& CSF_USER_DB_LOCKED
))
3099 // User database have to be locked before any
3100 // changes to user database can be made
3101 msg
.setField(VID_RCC
, RCC_OUT_OF_STATE_REQUEST
);
3105 // Get Id of user to be deleted
3106 dwUserId
= pRequest
->getFieldAsUInt32(VID_USER_ID
);
3108 if ((dwUserId
!= 0) && (dwUserId
!= GROUP_EVERYONE
))
3110 if (!IsLoggedIn(dwUserId
))
3112 TCHAR name
[MAX_DB_STRING
];
3113 ResolveUserId(dwUserId
, name
, MAX_DB_STRING
);
3114 UINT32 rcc
= DeleteUserDatabaseObject(dwUserId
);
3115 msg
.setField(VID_RCC
, rcc
);
3116 if(rcc
== RCC_SUCCESS
)
3118 WriteAuditLog(AUDIT_SECURITY
, TRUE
, m_dwUserId
, m_workstation
, m_id
, dwUserId
,
3119 _T("%s %s [%d] deleted"), (dwUserId
& GROUP_FLAG
) ? _T("Group") : _T("User"), name
, dwUserId
);
3124 // logger in users cannot be deleted
3125 msg
.setField(VID_RCC
, RCC_USER_LOGGED_IN
);
3130 // System administrator account and everyone group cannot be deleted
3131 msg
.setField(VID_RCC
, RCC_ACCESS_DENIED
);
3140 * Lock/unlock user database
3142 void ClientSession::lockUserDB(UINT32 dwRqId
, BOOL bLock
)
3145 TCHAR szBuffer
[256];
3147 // Prepare response message
3148 msg
.setCode(CMD_REQUEST_COMPLETED
);
3151 if (m_dwSystemAccess
& SYSTEM_ACCESS_MANAGE_USERS
)
3155 if (!LockComponent(CID_USER_DB
, m_id
, m_sessionName
, NULL
, szBuffer
))
3157 msg
.setField(VID_RCC
, RCC_COMPONENT_LOCKED
);
3158 msg
.setField(VID_LOCKED_BY
, szBuffer
);
3162 m_dwFlags
|= CSF_USER_DB_LOCKED
;
3163 msg
.setField(VID_RCC
, RCC_SUCCESS
);
3168 if (m_dwFlags
& CSF_USER_DB_LOCKED
)
3170 UnlockComponent(CID_USER_DB
);
3171 m_dwFlags
&= ~CSF_USER_DB_LOCKED
;
3173 msg
.setField(VID_RCC
, RCC_SUCCESS
);
3178 // Current user has no rights for user account management
3179 msg
.setField(VID_RCC
, RCC_ACCESS_DENIED
);
3187 * Change management status for the object
3189 void ClientSession::changeObjectMgmtStatus(NXCPMessage
*pRequest
)
3195 // Prepare response message
3196 msg
.setCode(CMD_REQUEST_COMPLETED
);
3197 msg
.setId(pRequest
->getId());
3199 // Get object id and check access rights
3200 dwObjectId
= pRequest
->getFieldAsUInt32(VID_OBJECT_ID
);
3201 object
= FindObjectById(dwObjectId
);
3204 if (object
->checkAccessRights(m_dwUserId
, OBJECT_ACCESS_MODIFY
))
3206 if ((object
->getObjectClass() != OBJECT_TEMPLATE
) &&
3207 (object
->getObjectClass() != OBJECT_TEMPLATEGROUP
) &&
3208 (object
->getObjectClass() != OBJECT_TEMPLATEROOT
))
3210 BOOL bIsManaged
= (BOOL
)pRequest
->getFieldAsUInt16(VID_MGMT_STATUS
);
3211 object
->setMgmtStatus(bIsManaged
);
3212 msg
.setField(VID_RCC
, RCC_SUCCESS
);
3213 WriteAuditLog(AUDIT_OBJECTS
, TRUE
, m_dwUserId
, m_workstation
, m_id
, object
->getId(),
3214 _T("Object %s set to %s state"), object
->getName(), bIsManaged
? _T("managed") : _T("unmanaged"));
3218 msg
.setField(VID_RCC
, RCC_INCOMPATIBLE_OPERATION
);
3223 msg
.setField(VID_RCC
, RCC_ACCESS_DENIED
);
3228 msg
.setField(VID_RCC
, RCC_INVALID_OBJECT_ID
);
3236 * Enter maintenance mode for object
3238 void ClientSession::enterMaintenanceMode(NXCPMessage
*request
)
3241 msg
.setCode(CMD_REQUEST_COMPLETED
);
3242 msg
.setId(request
->getId());
3244 // Get object id and check access rights
3245 NetObj
*object
= FindObjectById(request
->getFieldAsUInt32(VID_OBJECT_ID
));
3248 if (object
->checkAccessRights(m_dwUserId
, OBJECT_ACCESS_MODIFY
))
3250 if ((object
->getObjectClass() == OBJECT_CONTAINER
) ||
3251 (object
->getObjectClass() == OBJECT_CLUSTER
) ||
3252 (object
->getObjectClass() == OBJECT_NODE
) ||
3253 (object
->getObjectClass() == OBJECT_MOBILEDEVICE
) ||
3254 (object
->getObjectClass() == OBJECT_ACCESSPOINT
) ||
3255 (object
->getObjectClass() == OBJECT_CHASSIS
) ||
3256 (object
->getObjectClass() == OBJECT_ZONE
) ||
3257 (object
->getObjectClass() == OBJECT_SUBNET
) ||
3258 (object
->getObjectClass() == OBJECT_NETWORK
) ||
3259 (object
->getObjectClass() == OBJECT_SERVICEROOT
))
3261 object
->enterMaintenanceMode();
3262 msg
.setField(VID_RCC
, RCC_SUCCESS
);
3263 WriteAuditLog(AUDIT_OBJECTS
, TRUE
, m_dwUserId
, m_workstation
, m_id
, object
->getId(),
3264 _T("Requested maintenance mode enter for object %s [%d]"), object
->getName(), object
->getId());
3268 msg
.setField(VID_RCC
, RCC_INCOMPATIBLE_OPERATION
);
3273 msg
.setField(VID_RCC
, RCC_ACCESS_DENIED
);
3274 WriteAuditLog(AUDIT_OBJECTS
, FALSE
, m_dwUserId
, m_workstation
, m_id
, object
->getId(),
3275 _T("Access denied on maintenance mode enter request for object %s [%d]"), object
->getName(), object
->getId());
3280 msg
.setField(VID_RCC
, RCC_INVALID_OBJECT_ID
);
3287 * Leave maintenance mode for object
3289 void ClientSession::leaveMaintenanceMode(NXCPMessage
*request
)
3292 msg
.setCode(CMD_REQUEST_COMPLETED
);
3293 msg
.setId(request
->getId());
3295 // Get object id and check access rights
3296 NetObj
*object
= FindObjectById(request
->getFieldAsUInt32(VID_OBJECT_ID
));
3299 if (object
->checkAccessRights(m_dwUserId
, OBJECT_ACCESS_MODIFY
))
3301 if ((object
->getObjectClass() == OBJECT_CONTAINER
) ||
3302 (object
->getObjectClass() == OBJECT_CLUSTER
) ||
3303 (object
->getObjectClass() == OBJECT_NODE
) ||
3304 (object
->getObjectClass() == OBJECT_MOBILEDEVICE
) ||
3305 (object
->getObjectClass() == OBJECT_ACCESSPOINT
) ||
3306 (object
->getObjectClass() == OBJECT_CHASSIS
) ||
3307 (object
->getObjectClass() == OBJECT_ZONE
) ||
3308 (object
->getObjectClass() == OBJECT_SUBNET
) ||
3309 (object
->getObjectClass() == OBJECT_NETWORK
) ||
3310 (object
->getObjectClass() == OBJECT_SERVICEROOT
))
3312 object
->leaveMaintenanceMode();
3313 msg
.setField(VID_RCC
, RCC_SUCCESS
);
3314 WriteAuditLog(AUDIT_OBJECTS
, TRUE
, m_dwUserId
, m_workstation
, m_id
, object
->getId(),
3315 _T("Requested maintenance mode exit for object %s [%d]"), object
->getName(), object
->getId());
3319 msg
.setField(VID_RCC
, RCC_INCOMPATIBLE_OPERATION
);
3324 msg
.setField(VID_RCC
, RCC_ACCESS_DENIED
);
3325 WriteAuditLog(AUDIT_OBJECTS
, FALSE
, m_dwUserId
, m_workstation
, m_id
, object
->getId(),
3326 _T("Access denied on maintenance mode exit request for object %s [%d]"), object
->getName(), object
->getId());
3331 msg
.setField(VID_RCC
, RCC_INVALID_OBJECT_ID
);
3338 * Validate password for currently logged in user
3340 void ClientSession::validatePassword(NXCPMessage
*request
)
3343 msg
.setCode(CMD_REQUEST_COMPLETED
);
3344 msg
.setId(request
->getId());
3347 TCHAR password
[256];
3348 request
->getFieldAsString(VID_PASSWORD
, password
, 256);
3351 request
->getFieldAsUtf8String(VID_PASSWORD
, password
, 256);
3354 bool isValid
= false;
3355 msg
.setField(VID_RCC
, ValidateUserPassword(m_dwUserId
, m_loginName
, password
, &isValid
));
3356 msg
.setField(VID_PASSWORD_IS_VALID
, (INT16
)(isValid
? 1 : 0));
3362 * Set user's password
3364 void ClientSession::setPassword(NXCPMessage
*request
)
3369 // Prepare response message
3370 msg
.setCode(CMD_REQUEST_COMPLETED
);
3371 msg
.setId(request
->getId());
3373 dwUserId
= request
->getFieldAsUInt32(VID_USER_ID
);
3375 if (((m_dwSystemAccess
& SYSTEM_ACCESS_MANAGE_USERS
) &&
3376 !((dwUserId
== 0) && (m_dwUserId
!= 0))) || // Only administrator can change password for UID 0
3377 (dwUserId
== m_dwUserId
)) // User can change password for itself
3380 TCHAR newPassword
[1024], oldPassword
[1024];
3383 request
->getFieldAsString(VID_PASSWORD
, newPassword
, 256);
3384 if (request
->isFieldExist(VID_OLD_PASSWORD
))
3385 request
->getFieldAsString(VID_OLD_PASSWORD
, oldPassword
, 256);
3387 request
->getFieldAsUtf8String(VID_PASSWORD
, newPassword
, 1024);
3388 if (request
->isFieldExist(VID_OLD_PASSWORD
))
3389 request
->getFieldAsUtf8String(VID_OLD_PASSWORD
, oldPassword
, 1024);
3393 dwResult
= SetUserPassword(dwUserId
, newPassword
, oldPassword
, dwUserId
== m_dwUserId
);
3394 msg
.setField(VID_RCC
, dwResult
);
3396 if (dwResult
== RCC_SUCCESS
)
3398 TCHAR userName
[MAX_DB_STRING
];
3399 ResolveUserId(dwUserId
, userName
, MAX_DB_STRING
);
3400 WriteAuditLog(AUDIT_SECURITY
, TRUE
, m_dwUserId
, m_workstation
, m_id
, 0, _T("Changed password for user %s"), userName
);
3405 // Current user has no rights to change password for specific user
3406 msg
.setField(VID_RCC
, RCC_ACCESS_DENIED
);
3414 * Send node's DCIs to client and lock data collection settings
3416 void ClientSession::openNodeDCIList(NXCPMessage
*request
)
3421 BOOL bSuccess
= FALSE
;
3422 TCHAR szLockInfo
[MAX_SESSION_NAME
];
3424 // Prepare response message
3425 msg
.setCode(CMD_REQUEST_COMPLETED
);
3426 msg
.setId(request
->getId());
3428 // Get node id and check object class and access rights
3429 dwObjectId
= request
->getFieldAsUInt32(VID_OBJECT_ID
);
3430 object
= FindObjectById(dwObjectId
);
3433 if (object
->isDataCollectionTarget() || (object
->getObjectClass() == OBJECT_TEMPLATE
))
3435 if (object
->checkAccessRights(m_dwUserId
, OBJECT_ACCESS_READ
))
3437 // Try to lock DCI list
3438 if (((Template
*)object
)->lockDCIList(m_id
, m_sessionName
, szLockInfo
))
3441 msg
.setField(VID_RCC
, RCC_SUCCESS
);
3443 // modify list of open nodes DCI lists
3444 m_pOpenDCIList
= (UINT32
*)realloc(m_pOpenDCIList
, sizeof(UINT32
) * (m_dwOpenDCIListSize
+ 1));
3445 m_pOpenDCIList
[m_dwOpenDCIListSize
] = dwObjectId
;
3446 m_dwOpenDCIListSize
++;
3450 msg
.setField(VID_RCC
, RCC_COMPONENT_LOCKED
);
3451 msg
.setField(VID_LOCKED_BY
, szLockInfo
);
3456 msg
.setField(VID_RCC
, RCC_ACCESS_DENIED
);
3461 msg
.setField(VID_RCC
, RCC_INVALID_OBJECT_ID
);
3466 msg
.setField(VID_RCC
, RCC_INVALID_OBJECT_ID
);
3472 // If DCI list was successfully locked, send it to client
3474 ((Template
*)object
)->sendItemsToClient(this, request
->getId());
3478 * Unlock node's data collection settings
3480 void ClientSession::closeNodeDCIList(NXCPMessage
*request
)
3486 // Prepare response message
3487 msg
.setCode(CMD_REQUEST_COMPLETED
);
3488 msg
.setId(request
->getId());
3490 // Get node id and check object class and access rights
3491 dwObjectId
= request
->getFieldAsUInt32(VID_OBJECT_ID
);
3492 object
= FindObjectById(dwObjectId
);
3495 if (object
->isDataCollectionTarget() || (object
->getObjectClass() == OBJECT_TEMPLATE
))
3497 if (object
->checkAccessRights(m_dwUserId
, OBJECT_ACCESS_READ
))
3501 // Try to unlock DCI list
3502 bSuccess
= ((Template
*)object
)->unlockDCIList(m_id
);
3503 msg
.setField(VID_RCC
, bSuccess
? RCC_SUCCESS
: RCC_OUT_OF_STATE_REQUEST
);
3505 // modify list of open nodes DCI lists
3510 for(i
= 0; i
< m_dwOpenDCIListSize
; i
++)
3511 if (m_pOpenDCIList
[i
] == dwObjectId
)
3513 m_dwOpenDCIListSize
--;
3514 memmove(&m_pOpenDCIList
[i
], &m_pOpenDCIList
[i
+ 1], sizeof(UINT32
) * (m_dwOpenDCIListSize
- i
));
3521 msg
.setField(VID_RCC
, RCC_ACCESS_DENIED
);
3526 msg
.setField(VID_RCC
, RCC_INVALID_OBJECT_ID
);
3531 msg
.setField(VID_RCC
, RCC_INVALID_OBJECT_ID
);
3539 * Create, modify, or delete data collection item for node
3541 void ClientSession::modifyNodeDCI(NXCPMessage
*request
)
3547 // Prepare response message
3548 msg
.setCode(CMD_REQUEST_COMPLETED
);
3549 msg
.setId(request
->getId());
3551 // Get node id and check object class and access rights
3552 dwObjectId
= request
->getFieldAsUInt32(VID_OBJECT_ID
);
3553 object
= FindObjectById(dwObjectId
);
3556 if (object
->isDataCollectionTarget() || (object
->getObjectClass() == OBJECT_TEMPLATE
))
3558 if (((Template
*)object
)->isLockedBySession(m_id
))
3560 if (object
->checkAccessRights(m_dwUserId
, OBJECT_ACCESS_MODIFY
))
3562 UINT32 i
, dwItemId
, dwNumMaps
, *pdwMapId
, *pdwMapIndex
;
3564 BOOL bSuccess
= FALSE
;
3566 int dcObjectType
= (int)request
->getFieldAsUInt16(VID_DCOBJECT_TYPE
);
3567 switch(request
->getCode())
3569 case CMD_CREATE_NEW_DCI
:
3571 switch(dcObjectType
)
3574 dcObject
= new DCItem(CreateUniqueId(IDG_ITEM
), _T("no name"), DS_INTERNAL
, DCI_DT_INT
,
3575 ConfigReadInt(_T("DefaultDCIPollingInterval"), 60),
3576 ConfigReadInt(_T("DefaultDCIRetentionTime"), 30), (Node
*)object
);
3578 case DCO_TYPE_TABLE
:
3579 dcObject
= new DCTable(CreateUniqueId(IDG_ITEM
), _T("no name"), DS_INTERNAL
,
3580 ConfigReadInt(_T("DefaultDCIPollingInterval"), 60),
3581 ConfigReadInt(_T("DefaultDCIRetentionTime"), 30), (Node
*)object
);
3587 if (dcObject
!= NULL
)
3589 dcObject
->setStatus(ITEM_STATUS_DISABLED
, false);
3590 if ((bSuccess
= ((Template
*)object
)->addDCObject(dcObject
)))
3592 msg
.setField(VID_RCC
, RCC_SUCCESS
);
3593 // Return new item id to client
3594 msg
.setField(VID_DCI_ID
, dcObject
->getId());
3596 else // Unable to add item to node
3599 msg
.setField(VID_RCC
, RCC_DUPLICATE_DCI
);
3604 msg
.setField(VID_RCC
, RCC_INVALID_ARGUMENT
);
3607 case CMD_MODIFY_NODE_DCI
:
3608 dwItemId
= request
->getFieldAsUInt32(VID_DCI_ID
);
3609 bSuccess
= ((Template
*)object
)->updateDCObject(dwItemId
, request
, &dwNumMaps
, &pdwMapIndex
, &pdwMapId
);
3612 msg
.setField(VID_RCC
, RCC_SUCCESS
);
3614 // Send index to id mapping for newly created thresholds to client
3615 if (dcObjectType
== DCO_TYPE_ITEM
)
3617 msg
.setField(VID_DCI_NUM_MAPS
, dwNumMaps
);
3618 for(i
= 0; i
< dwNumMaps
; i
++)
3620 pdwMapId
[i
] = htonl(pdwMapId
[i
]);
3621 pdwMapIndex
[i
] = htonl(pdwMapIndex
[i
]);
3623 msg
.setField(VID_DCI_MAP_IDS
, (BYTE
*)pdwMapId
, sizeof(UINT32
) * dwNumMaps
);
3624 msg
.setField(VID_DCI_MAP_INDEXES
, (BYTE
*)pdwMapIndex
, sizeof(UINT32
) * dwNumMaps
);
3625 safe_free(pdwMapId
);
3626 safe_free(pdwMapIndex
);
3631 msg
.setField(VID_RCC
, RCC_INVALID_DCI_ID
);
3634 case CMD_DELETE_NODE_DCI
:
3635 dwItemId
= request
->getFieldAsUInt32(VID_DCI_ID
);
3636 bSuccess
= ((Template
*)object
)->deleteDCObject(dwItemId
, true);
3637 msg
.setField(VID_RCC
, bSuccess
? RCC_SUCCESS
: RCC_INVALID_DCI_ID
);
3641 ((Template
*)object
)->setDCIModificationFlag();
3643 else // User doesn't have MODIFY rights on object
3645 msg
.setField(VID_RCC
, RCC_ACCESS_DENIED
);
3648 else // Nodes DCI list not locked by this session
3650 msg
.setField(VID_RCC
, RCC_OUT_OF_STATE_REQUEST
);
3653 else // Object is not a node
3655 msg
.setField(VID_RCC
, RCC_INVALID_OBJECT_ID
);
3658 else // No object with given ID
3660 msg
.setField(VID_RCC
, RCC_INVALID_OBJECT_ID
);
3668 * Change status for one or more DCIs
3670 void ClientSession::changeDCIStatus(NXCPMessage
*request
)
3675 // Prepare response message
3676 msg
.setCode(CMD_REQUEST_COMPLETED
);
3677 msg
.setId(request
->getId());
3679 // Get node id and check object class and access rights
3680 object
= FindObjectById(request
->getFieldAsUInt32(VID_OBJECT_ID
));
3683 if (object
->isDataCollectionTarget() || (object
->getObjectClass() == OBJECT_TEMPLATE
))
3685 if (((Template
*)object
)->isLockedBySession(m_id
))
3687 if (object
->checkAccessRights(m_dwUserId
, OBJECT_ACCESS_MODIFY
))
3689 UINT32 dwNumItems
, *pdwItemList
;
3692 iStatus
= request
->getFieldAsUInt16(VID_DCI_STATUS
);
3693 dwNumItems
= request
->getFieldAsUInt32(VID_NUM_ITEMS
);
3694 pdwItemList
= (UINT32
*)malloc(sizeof(UINT32
) * dwNumItems
);
3695 request
->getFieldAsInt32Array(VID_ITEM_LIST
, dwNumItems
, pdwItemList
);
3696 if (((Template
*)object
)->setItemStatus(dwNumItems
, pdwItemList
, iStatus
))
3697 msg
.setField(VID_RCC
, RCC_SUCCESS
);