fixed build error; fixed compilation warnings
[public/netxms.git] / src / server / libnxsrv / agent.cpp
CommitLineData
cc022855 1/*
5039dede
AK
2** NetXMS - Network Management System
3** Server Library
0f506caa 4** Copyright (C) 2003-2013 Victor Kirhenshtein
5039dede
AK
5**
6** This program is free software; you can redistribute it and/or modify
0702ed69
VK
7** it under the terms of the GNU Lesser General Public License as published by
8** the Free Software Foundation; either version 3 of the License, or
5039dede
AK
9** (at your option) any later version.
10**
11** This program is distributed in the hope that it will be useful,
12** but WITHOUT ANY WARRANTY; without even the implied warranty of
13** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14** GNU General Public License for more details.
15**
0702ed69 16** You should have received a copy of the GNU Lesser General Public License
5039dede
AK
17** along with this program; if not, write to the Free Software
18** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19**
20** File: agent.cpp
21**
22**/
23
24#include "libnxsrv.h"
25#include <stdarg.h>
26
f00612ba
VK
27#ifdef _WIN32
28#define open _open
29#define close _close
30#define write _write
8c1befb6 31#else
ff198273 32#define _tell(f) lseek(f,0,SEEK_CUR)
f00612ba
VK
33#endif
34
a3050773
VK
35/**
36 * Constants
37 */
8f4f648d 38#define MAX_MSG_SIZE 8388608
5039dede 39
a3050773
VK
40/**
41 * Static data
42 */
5039dede
AK
43#ifdef _WITH_ENCRYPTION
44static int m_iDefaultEncryptionPolicy = ENCRYPTION_ALLOWED;
45#else
46static int m_iDefaultEncryptionPolicy = ENCRYPTION_DISABLED;
47#endif
48
a3050773
VK
49/**
50 * Set default encryption policy for agent communication
51 */
5039dede
AK
52void LIBNXSRV_EXPORTABLE SetAgentDEP(int iPolicy)
53{
54#ifdef _WITH_ENCRYPTION
55 m_iDefaultEncryptionPolicy = iPolicy;
56#endif
57}
58
a3050773
VK
59/**
60 * Receiver thread starter
61 */
62THREAD_RESULT THREAD_CALL AgentConnection::receiverThreadStarter(void *pArg)
5039dede 63{
a3050773 64 ((AgentConnection *)pArg)->receiverThread();
5039dede
AK
65 return THREAD_OK;
66}
67
a3050773
VK
68/**
69 * Constructor for AgentConnection
70 */
69c6604d 71AgentConnection::AgentConnection(UINT32 ipAddr, WORD port, int authMethod, const TCHAR *secret)
5039dede 72{
69c6604d
VK
73 m_dwAddr = ipAddr;
74 m_wPort = port;
75 m_iAuthMethod = authMethod;
76 if (secret != NULL)
5039dede
AK
77 {
78#ifdef UNICODE
69c6604d 79 WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK | WC_DEFAULTCHAR, secret, -1, m_szSecret, MAX_SECRET_LENGTH, NULL, NULL);
08b214c6 80 m_szSecret[MAX_SECRET_LENGTH - 1] = 0;
5039dede 81#else
69c6604d 82 nx_strncpy(m_szSecret, secret, MAX_SECRET_LENGTH);
5039dede
AK
83#endif
84 }
85 else
86 {
87 m_szSecret[0] = 0;
88 }
89 m_hSocket = -1;
90 m_tLastCommandTime = 0;
91 m_dwNumDataLines = 0;
92 m_ppDataLines = NULL;
93 m_pMsgWaitQueue = new MsgWaitQueue;
94 m_dwRequestId = 1;
7c521895 95 m_connectionTimeout = 30000; // 30 seconds
5039dede
AK
96 m_dwCommandTimeout = 10000; // Default timeout 10 seconds
97 m_bIsConnected = FALSE;
98 m_mutexDataLock = MutexCreate();
d3a7cf4c 99 m_mutexSocketWrite = MutexCreate();
5039dede
AK
100 m_hReceiverThread = INVALID_THREAD_HANDLE;
101 m_pCtx = NULL;
102 m_iEncryptionPolicy = m_iDefaultEncryptionPolicy;
103 m_bUseProxy = FALSE;
104 m_dwRecvTimeout = 420000; // 7 minutes
105 m_nProtocolVersion = NXCP_VERSION;
106 m_hCurrFile = -1;
76b4edb5 107 m_deleteFileOnDownloadFailure = true;
bb85e341 108 m_condFileDownload = ConditionCreate(TRUE);
4685a2ad 109 m_fileUploadInProgress = false;
9630fcd1 110 m_sendToClientMessageCallback = NULL;
5039dede
AK
111}
112
a3050773
VK
113/**
114 * Destructor
115 */
5039dede
AK
116AgentConnection::~AgentConnection()
117{
118 // Disconnect from peer
7c521895 119 disconnect();
5039dede
AK
120
121 // Wait for receiver thread termination
122 ThreadJoin(m_hReceiverThread);
cc022855 123
5039dede 124 // Close socket if active
a3050773 125 lock();
5039dede
AK
126 if (m_hSocket != -1)
127 {
128 closesocket(m_hSocket);
129 m_hSocket = -1;
130 }
a3050773 131 unlock();
5039dede 132
a3050773 133 lock();
7c521895 134 destroyResultData();
a3050773 135 unlock();
5039dede
AK
136
137 delete m_pMsgWaitQueue;
98abc9f1
VK
138 if (m_pCtx != NULL)
139 m_pCtx->decRefCount();
5039dede
AK
140
141 if (m_hCurrFile != -1)
9f6d453a 142 {
5039dede 143 close(m_hCurrFile);
f480bdd4 144 onFileDownload(FALSE);
9f6d453a 145 }
5039dede
AK
146
147 MutexDestroy(m_mutexDataLock);
d3a7cf4c 148 MutexDestroy(m_mutexSocketWrite);
bb85e341 149 ConditionDestroy(m_condFileDownload);
5039dede
AK
150}
151
a3050773
VK
152/**
153 * Print message. This method is virtual and can be overrided in
154 * derived classes. Default implementation will print message to stdout.
155 */
af21affe 156void AgentConnection::printMsg(const TCHAR *format, ...)
5039dede
AK
157{
158 va_list args;
159
af21affe
VK
160 va_start(args, format);
161 _vtprintf(format, args);
5039dede
AK
162 va_end(args);
163 _tprintf(_T("\n"));
164}
165
a3050773
VK
166/**
167 * Receiver thread
168 */
169void AgentConnection::receiverThread()
5039dede 170{
967893bb 171 UINT32 msgBufferSize = 1024;
5039dede
AK
172 CSCPMessage *pMsg;
173 CSCP_MESSAGE *pRawMsg;
174 CSCP_BUFFER *pMsgBuffer;
175 BYTE *pDecryptionBuffer = NULL;
4685a2ad 176 int error;
5039dede
AK
177 TCHAR szBuffer[128], szIpAddr[16];
178 SOCKET nSocket;
179
180 // Initialize raw message receiving function
181 pMsgBuffer = (CSCP_BUFFER *)malloc(sizeof(CSCP_BUFFER));
182 RecvNXCPMessage(0, NULL, pMsgBuffer, 0, NULL, NULL, 0);
183
184 // Allocate space for raw message
8f4f648d 185 pRawMsg = (CSCP_MESSAGE *)malloc(msgBufferSize);
5039dede 186#ifdef _WITH_ENCRYPTION
8f4f648d 187 pDecryptionBuffer = (BYTE *)malloc(msgBufferSize);
5039dede
AK
188#endif
189
190 // Message receiving loop
191 while(1)
192 {
8f4f648d
VK
193 // Shrink buffer after receiving large message
194 if (msgBufferSize > 131072)
195 {
196 msgBufferSize = 131072;
197 pRawMsg = (CSCP_MESSAGE *)realloc(pRawMsg, msgBufferSize);
198 if (pDecryptionBuffer != NULL)
199 pDecryptionBuffer = (BYTE *)realloc(pDecryptionBuffer, msgBufferSize);
200 }
201
5039dede 202 // Receive raw message
a3050773 203 lock();
5039dede 204 nSocket = m_hSocket;
a3050773 205 unlock();
8f4f648d
VK
206 if ((error = RecvNXCPMessageEx(nSocket, &pRawMsg, pMsgBuffer, &msgBufferSize,
207 &m_pCtx, (pDecryptionBuffer != NULL) ? &pDecryptionBuffer : NULL,
208 m_dwRecvTimeout, MAX_MSG_SIZE)) <= 0)
5039dede 209 {
a2069340
VK
210 if (WSAGetLastError() != WSAESHUTDOWN)
211 DbgPrintf(6, _T("AgentConnection::ReceiverThread(): RecvNXCPMessage() failed: error=%d, socket_error=%d"), error, WSAGetLastError());
5039dede
AK
212 break;
213 }
214
215 // Check if we get too large message
4685a2ad 216 if (error == 1)
5039dede 217 {
cc022855 218 printMsg(_T("Received too large message %s (%d bytes)"),
5039dede
AK
219 NXCPMessageCodeName(ntohs(pRawMsg->wCode), szBuffer),
220 ntohl(pRawMsg->dwSize));
221 continue;
222 }
223
224 // Check if we are unable to decrypt message
4685a2ad 225 if (error == 2)
5039dede 226 {
a3050773 227 printMsg(_T("Unable to decrypt received message"));
5039dede
AK
228 continue;
229 }
230
231 // Check for timeout
4685a2ad 232 if (error == 3)
5039dede 233 {
4685a2ad
VK
234 if (m_fileUploadInProgress)
235 continue; // Receive timeout may occur when uploading large files via slow links
a3050773 236 printMsg(_T("Timed out waiting for message"));
5039dede
AK
237 break;
238 }
239
240 // Check that actual received packet size is equal to encoded in packet
4685a2ad 241 if ((int)ntohl(pRawMsg->dwSize) != error)
5039dede 242 {
a3050773 243 printMsg(_T("RecvMsg: Bad packet length [dwSize=%d ActualSize=%d]"), ntohl(pRawMsg->dwSize), error);
5039dede
AK
244 continue; // Bad packet, wait for next
245 }
246
247 if (ntohs(pRawMsg->wFlags) & MF_BINARY)
248 {
249 // Convert message header to host format
250 pRawMsg->dwId = ntohl(pRawMsg->dwId);
251 pRawMsg->wCode = ntohs(pRawMsg->wCode);
252 pRawMsg->dwNumVars = ntohl(pRawMsg->dwNumVars);
08b214c6 253 DbgPrintf(6, _T("Received raw message %s from agent at %s"),
7c521895 254 NXCPMessageCodeName(pRawMsg->wCode, szBuffer), IpToStr(getIpAddr(), szIpAddr));
5039dede 255
76b4edb5 256 if ((pRawMsg->wCode == CMD_FILE_DATA) && (pRawMsg->dwId == m_dwDownloadRequestId))
5039dede 257 {
76b4edb5 258 if (m_sendToClientMessageCallback != NULL)
5039dede 259 {
76b4edb5 260 pRawMsg->wCode = ntohs(pRawMsg->wCode);
261 pRawMsg->dwNumVars = ntohl(pRawMsg->dwNumVars);
262 m_sendToClientMessageCallback(pRawMsg, m_downloadProgressCallbackArg);
263
5039dede
AK
264 if (ntohs(pRawMsg->wFlags) & MF_END_OF_FILE)
265 {
f480bdd4 266 onFileDownload(TRUE);
5039dede 267 }
76b4edb5 268 else
269 {
270 if (m_downloadProgressCallback != NULL)
271 {
6be0a20b 272 m_downloadProgressCallback(pRawMsg->dwSize - (NXCP_HEADER_SIZE + 8), m_downloadProgressCallbackArg);
76b4edb5 273 }
274 }
5039dede
AK
275 }
276 else
277 {
76b4edb5 278 if (m_hCurrFile != -1)
279 {
280 if (write(m_hCurrFile, pRawMsg->df, pRawMsg->dwNumVars) == (int)pRawMsg->dwNumVars)
281 {
282 if (ntohs(pRawMsg->wFlags) & MF_END_OF_FILE)
283 {
284 close(m_hCurrFile);
285 m_hCurrFile = -1;
286
287 onFileDownload(TRUE);
288 }
289 else
290 {
291 if (m_downloadProgressCallback != NULL)
292 {
293 m_downloadProgressCallback(_tell(m_hCurrFile), m_downloadProgressCallbackArg);
294 }
295 }
296 }
297 }
298 else
299 {
300 // I/O error
301 close(m_hCurrFile);
302 m_hCurrFile = -1;
cc022855 303
76b4edb5 304 onFileDownload(FALSE);
305 }
9a895fd6 306 }
307 }
308
309 if((pRawMsg->wCode == CMD_ABORT_FILE_TRANSFER) && (pRawMsg->dwId == m_dwDownloadRequestId))
310 {
311 if (m_sendToClientMessageCallback != NULL)
312 {
313 pRawMsg->wCode = ntohs(pRawMsg->wCode);
314 pRawMsg->dwNumVars = ntohl(pRawMsg->dwNumVars);
315 m_sendToClientMessageCallback(pRawMsg, m_downloadProgressCallbackArg);
316
317 onFileDownload(FALSE);
318 }
319 else
320 {
321 //error on agent side
322 close(m_hCurrFile);
323 m_hCurrFile = -1;
324
325 onFileDownload(FALSE);
5039dede
AK
326 }
327 }
328 }
329 else
330 {
331 // Create message object from raw message
332 pMsg = new CSCPMessage(pRawMsg, m_nProtocolVersion);
f480bdd4 333 switch(pMsg->GetCode())
5039dede 334 {
f480bdd4
VK
335 case CMD_TRAP:
336 onTrap(pMsg);
337 delete pMsg;
338 break;
339 case CMD_PUSH_DCI_DATA:
340 onDataPush(pMsg);
341 delete pMsg;
342 break;
90284364 343 case CMD_REQUEST_COMPLETED:
c17f6cbc 344 m_pMsgWaitQueue->put(pMsg);
f480bdd4 345 break;
9fa031cd 346 case CMD_FILE_MONITORING:
347 onFileMonitoringData(pMsg);
348 delete pMsg;
489b117b 349 break;
350 case CMD_SNMP_TRAP:
351 onSnmpTrap(pMsg);
9fa031cd 352 break;
90284364
VK
353 default:
354 if (processCustomMessage(pMsg))
355 delete pMsg;
356 else
c17f6cbc 357 m_pMsgWaitQueue->put(pMsg);
90284364 358 break;
5039dede
AK
359 }
360 }
361 }
362
363 // Close socket and mark connection as disconnected
a3050773 364 lock();
f2665675
VK
365 if (m_hCurrFile != -1)
366 {
367 close(m_hCurrFile);
368 m_hCurrFile = -1;
f480bdd4 369 onFileDownload(FALSE);
f2665675 370 }
cc022855 371
4685a2ad 372 if (error == 0)
5039dede
AK
373 shutdown(m_hSocket, SHUT_RDWR);
374 closesocket(m_hSocket);
375 m_hSocket = -1;
98abc9f1
VK
376 if (m_pCtx != NULL)
377 {
378 m_pCtx->decRefCount();
379 m_pCtx = NULL;
380 }
5039dede 381 m_bIsConnected = FALSE;
a3050773 382 unlock();
5039dede
AK
383
384 free(pRawMsg);
385 free(pMsgBuffer);
386#ifdef _WITH_ENCRYPTION
387 free(pDecryptionBuffer);
388#endif
389}
390
a3050773
VK
391/**
392 * Connect to agent
393 */
967893bb 394BOOL AgentConnection::connect(RSA *pServerKey, BOOL bVerbose, UINT32 *pdwError, UINT32 *pdwSocketError)
5039dede
AK
395{
396 struct sockaddr_in sa;
397 TCHAR szBuffer[256];
398 BOOL bSuccess = FALSE, bForceEncryption = FALSE, bSecondPass = FALSE;
967893bb 399 UINT32 dwError = 0;
5039dede
AK
400
401 if (pdwError != NULL)
402 *pdwError = ERR_INTERNAL_ERROR;
403
c3acd0f6
VK
404 if (pdwSocketError != NULL)
405 *pdwSocketError = 0;
406
5039dede
AK
407 // Check if already connected
408 if (m_bIsConnected)
409 return FALSE;
410
411 // Wait for receiver thread from previous connection, if any
412 ThreadJoin(m_hReceiverThread);
413 m_hReceiverThread = INVALID_THREAD_HANDLE;
414
415 // Check if we need to close existing socket
416 if (m_hSocket != -1)
417 closesocket(m_hSocket);
418
419 // Create socket
420 m_hSocket = socket(AF_INET, SOCK_STREAM, 0);
4c0c75c7 421 if (m_hSocket == INVALID_SOCKET)
5039dede 422 {
a3050773 423 printMsg(_T("Call to socket() failed"));
5039dede
AK
424 goto connect_cleanup;
425 }
426
427 // Fill in address structure
428 memset(&sa, 0, sizeof(sa));
429 sa.sin_family = AF_INET;
430 if (m_bUseProxy)
431 {
432 sa.sin_addr.s_addr = m_dwProxyAddr;
433 sa.sin_port = htons(m_wProxyPort);
434 }
435 else
436 {
437 sa.sin_addr.s_addr = m_dwAddr;
438 sa.sin_port = htons(m_wPort);
439 }
440
441 // Connect to server
7c521895 442 if (ConnectEx(m_hSocket, (struct sockaddr *)&sa, sizeof(sa), m_connectionTimeout) == -1)
5039dede
AK
443 {
444 if (bVerbose)
a3050773 445 printMsg(_T("Cannot establish connection with agent %s"),
5039dede
AK
446 IpToStr(ntohl(m_bUseProxy ? m_dwProxyAddr : m_dwAddr), szBuffer));
447 dwError = ERR_CONNECT_FAILED;
448 goto connect_cleanup;
449 }
450
d3a7cf4c 451 if (!NXCPGetPeerProtocolVersion(m_hSocket, &m_nProtocolVersion, m_mutexSocketWrite))
5039dede
AK
452 {
453 dwError = ERR_INTERNAL_ERROR;
454 goto connect_cleanup;
455 }
456
457 // Start receiver thread
a3050773 458 m_hReceiverThread = ThreadCreateEx(receiverThreadStarter, 0, this);
5039dede
AK
459
460 // Setup encryption
461setup_encryption:
462 if ((m_iEncryptionPolicy == ENCRYPTION_PREFERRED) ||
463 (m_iEncryptionPolicy == ENCRYPTION_REQUIRED) ||
464 (bForceEncryption)) // Agent require encryption
465 {
466 if (pServerKey != NULL)
467 {
7c521895 468 dwError = setupEncryption(pServerKey);
5039dede
AK
469 if ((dwError != ERR_SUCCESS) &&
470 ((m_iEncryptionPolicy == ENCRYPTION_REQUIRED) || bForceEncryption))
471 goto connect_cleanup;
472 }
473 else
474 {
475 if ((m_iEncryptionPolicy == ENCRYPTION_REQUIRED) || bForceEncryption)
476 {
477 dwError = ERR_ENCRYPTION_REQUIRED;
478 goto connect_cleanup;
479 }
480 }
481 }
482
483 // Authenticate itself to agent
7c521895 484 if ((dwError = authenticate(m_bUseProxy && !bSecondPass)) != ERR_SUCCESS)
5039dede
AK
485 {
486 if ((dwError == ERR_ENCRYPTION_REQUIRED) &&
487 (m_iEncryptionPolicy != ENCRYPTION_DISABLED))
488 {
489 bForceEncryption = TRUE;
490 goto setup_encryption;
491 }
a3050773 492 printMsg(_T("Authentication to agent %s failed (%s)"), IpToStr(ntohl(m_dwAddr), szBuffer),
5039dede
AK
493 AgentErrorCodeToText(dwError));
494 goto connect_cleanup;
495 }
496
497 // Test connectivity
45d84f8a 498 if ((dwError = nop()) != ERR_SUCCESS)
5039dede
AK
499 {
500 if ((dwError == ERR_ENCRYPTION_REQUIRED) &&
501 (m_iEncryptionPolicy != ENCRYPTION_DISABLED))
502 {
503 bForceEncryption = TRUE;
504 goto setup_encryption;
505 }
a3050773 506 printMsg(_T("Communication with agent %s failed (%s)"), IpToStr(ntohl(m_dwAddr), szBuffer),
5039dede
AK
507 AgentErrorCodeToText(dwError));
508 goto connect_cleanup;
509 }
510
511 if (m_bUseProxy && !bSecondPass)
512 {
7c521895 513 dwError = setupProxyConnection();
5039dede
AK
514 if (dwError != ERR_SUCCESS)
515 goto connect_cleanup;
a3050773 516 lock();
98abc9f1
VK
517 if (m_pCtx != NULL)
518 {
519 m_pCtx->decRefCount();
520 m_pCtx = NULL;
521 }
a3050773 522 unlock();
5039dede
AK
523 bSecondPass = TRUE;
524 bForceEncryption = FALSE;
525 goto setup_encryption;
526 }
527
528 bSuccess = TRUE;
529 dwError = ERR_SUCCESS;
530
531connect_cleanup:
532 if (!bSuccess)
533 {
c3acd0f6 534 if (pdwSocketError != NULL)
967893bb 535 *pdwSocketError = (UINT32)WSAGetLastError();
c3acd0f6 536
a3050773 537 lock();
5039dede
AK
538 if (m_hSocket != -1)
539 shutdown(m_hSocket, SHUT_RDWR);
a3050773 540 unlock();
5039dede
AK
541 ThreadJoin(m_hReceiverThread);
542 m_hReceiverThread = INVALID_THREAD_HANDLE;
543
a3050773 544 lock();
5039dede
AK
545 if (m_hSocket != -1)
546 {
547 closesocket(m_hSocket);
548 m_hSocket = -1;
549 }
550
98abc9f1
VK
551 if (m_pCtx != NULL)
552 {
553 m_pCtx->decRefCount();
554 m_pCtx = NULL;
555 }
5039dede 556
a3050773 557 unlock();
5039dede
AK
558 }
559 m_bIsConnected = bSuccess;
560 if (pdwError != NULL)
561 *pdwError = dwError;
562 return bSuccess;
563}
564
af21affe
VK
565/**
566 * Disconnect from agent
567 */
7c521895 568void AgentConnection::disconnect()
5039dede 569{
a3050773 570 lock();
f2665675
VK
571 if (m_hCurrFile != -1)
572 {
573 close(m_hCurrFile);
574 m_hCurrFile = -1;
f480bdd4 575 onFileDownload(FALSE);
f2665675 576 }
9fa031cd 577
5039dede
AK
578 if (m_hSocket != -1)
579 {
580 shutdown(m_hSocket, SHUT_RDWR);
581 }
7c521895 582 destroyResultData();
5039dede 583 m_bIsConnected = FALSE;
a3050773 584 unlock();
5039dede
AK
585}
586
af21affe
VK
587/**
588 * Set authentication data
589 */
590void AgentConnection::setAuthData(int method, const TCHAR *secret)
cc022855 591{
af21affe
VK
592 m_iAuthMethod = method;
593#ifdef UNICODE
594 WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK | WC_DEFAULTCHAR, secret, -1, m_szSecret, MAX_SECRET_LENGTH, NULL, NULL);
595 m_szSecret[MAX_SECRET_LENGTH - 1] = 0;
596#else
597 nx_strncpy(m_szSecret, secret, MAX_SECRET_LENGTH);
598#endif
599}
5039dede 600
af21affe
VK
601/**
602 * Destroy command execuion results data
603 */
7c521895 604void AgentConnection::destroyResultData()
5039dede 605{
967893bb 606 UINT32 i;
5039dede
AK
607
608 if (m_ppDataLines != NULL)
609 {
610 for(i = 0; i < m_dwNumDataLines; i++)
611 if (m_ppDataLines[i] != NULL)
612 free(m_ppDataLines[i]);
613 free(m_ppDataLines);
614 m_ppDataLines = NULL;
615 }
616 m_dwNumDataLines = 0;
617}
618
d51f2182
VK
619/**
620 * Get interface list from agent
621 */
98762401 622InterfaceList *AgentConnection::getInterfaceList()
5039dede 623{
98762401 624 InterfaceList *pIfList = NULL;
36e44abe 625 NX_INTERFACE_INFO iface;
967893bb 626 UINT32 i, dwBits;
5039dede
AK
627 TCHAR *pChar, *pBuf;
628
4687826e 629 if (getList(_T("Net.InterfaceList")) == ERR_SUCCESS)
5039dede 630 {
98762401 631 pIfList = new InterfaceList(m_dwNumDataLines);
5039dede
AK
632
633 // Parse result set. Each line should have the following format:
634 // index ip_address/mask_bits iftype mac_address name
635 for(i = 0; i < m_dwNumDataLines; i++)
636 {
637 pBuf = m_ppDataLines[i];
36e44abe 638 memset(&iface, 0, sizeof(NX_INTERFACE_INFO));
5039dede
AK
639
640 // Index
641 pChar = _tcschr(pBuf, ' ');
642 if (pChar != NULL)
643 {
644 *pChar = 0;
98762401 645 iface.dwIndex = _tcstoul(pBuf, NULL, 10);
5039dede
AK
646 pBuf = pChar + 1;
647 }
648
649 // Address and mask
650 pChar = _tcschr(pBuf, _T(' '));
651 if (pChar != NULL)
652 {
653 TCHAR *pSlash;
654 static TCHAR defaultMask[] = _T("24");
655
656 *pChar = 0;
657 pSlash = _tcschr(pBuf, _T('/'));
658 if (pSlash != NULL)
659 {
660 *pSlash = 0;
661 pSlash++;
662 }
663 else // Just a paranoia protection, should'n happen if agent working correctly
664 {
665 pSlash = defaultMask;
666 }
98762401 667 iface.dwIpAddr = ntohl(_t_inet_addr(pBuf));
5039dede 668 dwBits = _tcstoul(pSlash, NULL, 10);
98762401 669 iface.dwIpNetMask = (dwBits == 32) ? 0xFFFFFFFF : (~(0xFFFFFFFF >> dwBits));
5039dede
AK
670 pBuf = pChar + 1;
671 }
672
673 // Interface type
674 pChar = _tcschr(pBuf, ' ');
675 if (pChar != NULL)
676 {
677 *pChar = 0;
98762401 678 iface.dwType = _tcstoul(pBuf, NULL, 10);
5039dede
AK
679 pBuf = pChar + 1;
680 }
681
682 // MAC address
683 pChar = _tcschr(pBuf, ' ');
684 if (pChar != NULL)
685 {
686 *pChar = 0;
98762401 687 StrToBin(pBuf, iface.bMacAddr, MAC_ADDR_LENGTH);
5039dede
AK
688 pBuf = pChar + 1;
689 }
690
478d4ff4
VK
691 // Name (set description to name)
692 nx_strncpy(iface.szName, pBuf, MAX_DB_STRING);
693 nx_strncpy(iface.szDescription, pBuf, MAX_DB_STRING);
98762401
VK
694
695 pIfList->add(&iface);
5039dede
AK
696 }
697
a3050773 698 lock();
7c521895 699 destroyResultData();
a3050773 700 unlock();
5039dede
AK
701 }
702
703 return pIfList;
704}
705
706
489b117b 707/**
708 * Get parameter value
709 */
967893bb 710UINT32 AgentConnection::getParameter(const TCHAR *pszParam, UINT32 dwBufSize, TCHAR *pszBuffer)
5039dede
AK
711{
712 CSCPMessage msg(m_nProtocolVersion), *pResponse;
967893bb 713 UINT32 dwRqId, dwRetCode;
5039dede
AK
714
715 if (m_bIsConnected)
716 {
717 dwRqId = m_dwRequestId++;
718 msg.SetCode(CMD_GET_PARAMETER);
719 msg.SetId(dwRqId);
720 msg.SetVariable(VID_PARAMETER, pszParam);
7c521895 721 if (sendMessage(&msg))
5039dede 722 {
7c521895 723 pResponse = waitForMessage(CMD_REQUEST_COMPLETED, dwRqId, m_dwCommandTimeout);
5039dede
AK
724 if (pResponse != NULL)
725 {
726 dwRetCode = pResponse->GetVariableLong(VID_RCC);
727 if (dwRetCode == ERR_SUCCESS)
728 pResponse->GetVariableStr(VID_VALUE, pszBuffer, dwBufSize);
729 delete pResponse;
730 }
731 else
732 {
733 dwRetCode = ERR_REQUEST_TIMEOUT;
734 }
735 }
736 else
737 {
738 dwRetCode = ERR_CONNECTION_BROKEN;
739 }
740 }
741 else
742 {
743 dwRetCode = ERR_NOT_CONNECTED;
744 }
745
746 return dwRetCode;
747}
748
749
489b117b 750/**
751 * Get ARP cache
752 */
4687826e 753ARP_CACHE *AgentConnection::getArpCache()
5039dede
AK
754{
755 ARP_CACHE *pArpCache = NULL;
756 TCHAR szByte[4], *pBuf, *pChar;
967893bb 757 UINT32 i, j;
5039dede 758
4687826e 759 if (getList(_T("Net.ArpCache")) == ERR_SUCCESS)
5039dede
AK
760 {
761 // Create empty structure
762 pArpCache = (ARP_CACHE *)malloc(sizeof(ARP_CACHE));
763 pArpCache->dwNumEntries = m_dwNumDataLines;
764 pArpCache->pEntries = (ARP_ENTRY *)malloc(sizeof(ARP_ENTRY) * m_dwNumDataLines);
765 memset(pArpCache->pEntries, 0, sizeof(ARP_ENTRY) * m_dwNumDataLines);
766
767 szByte[2] = 0;
768
769 // Parse data lines
770 // Each line has form of XXXXXXXXXXXX a.b.c.d n
771 // where XXXXXXXXXXXX is a MAC address (12 hexadecimal digits)
772 // a.b.c.d is an IP address in decimal dotted notation
773 // n is an interface index
774 for(i = 0; i < m_dwNumDataLines; i++)
775 {
776 pBuf = m_ppDataLines[i];
777 if (_tcslen(pBuf) < 20) // Invalid line
778 continue;
779
780 // MAC address
781 for(j = 0; j < 6; j++)
782 {
783 memcpy(szByte, pBuf, sizeof(TCHAR) * 2);
784 pArpCache->pEntries[i].bMacAddr[j] = (BYTE)_tcstol(szByte, NULL, 16);
785 pBuf+=2;
786 }
787
788 // IP address
789 while(*pBuf == ' ')
790 pBuf++;
791 pChar = _tcschr(pBuf, _T(' '));
792 if (pChar != NULL)
793 *pChar = 0;
794 pArpCache->pEntries[i].dwIpAddr = ntohl(_t_inet_addr(pBuf));
795
796 // Interface index
797 if (pChar != NULL)
798 pArpCache->pEntries[i].dwIndex = _tcstoul(pChar + 1, NULL, 10);
799 }
800
a3050773 801 lock();
7c521895 802 destroyResultData();
a3050773 803 unlock();
5039dede
AK
804 }
805 return pArpCache;
806}
807
808
489b117b 809/**
810 * Send dummy command to agent (can be used for keepalive)
811 */
5039dede 812
967893bb 813UINT32 AgentConnection::nop()
5039dede
AK
814{
815 CSCPMessage msg(m_nProtocolVersion);
967893bb 816 UINT32 dwRqId;
5039dede
AK
817
818 dwRqId = m_dwRequestId++;
819 msg.SetCode(CMD_KEEPALIVE);
820 msg.SetId(dwRqId);
7c521895
VK
821 if (sendMessage(&msg))
822 return waitForRCC(dwRqId, m_dwCommandTimeout);
5039dede
AK
823 else
824 return ERR_CONNECTION_BROKEN;
825}
826
827
489b117b 828/**
829 * Wait for request completion code
830 */
967893bb 831UINT32 AgentConnection::waitForRCC(UINT32 dwRqId, UINT32 dwTimeOut)
5039dede
AK
832{
833 CSCPMessage *pMsg;
967893bb 834 UINT32 dwRetCode;
5039dede 835
c17f6cbc 836 pMsg = m_pMsgWaitQueue->waitForMessage(CMD_REQUEST_COMPLETED, dwRqId, dwTimeOut);
5039dede
AK
837 if (pMsg != NULL)
838 {
839 dwRetCode = pMsg->GetVariableLong(VID_RCC);
840 delete pMsg;
841 }
842 else
843 {
844 dwRetCode = ERR_REQUEST_TIMEOUT;
845 }
846 return dwRetCode;
847}
848
5c44534b
VK
849/**
850 * Send message to agent
851 */
7c521895 852BOOL AgentConnection::sendMessage(CSCPMessage *pMsg)
5039dede 853{
5039dede
AK
854 BOOL bResult;
855
5c44534b 856 CSCP_MESSAGE *pRawMsg = pMsg->createMessage();
98abc9f1
VK
857 NXCPEncryptionContext *pCtx = acquireEncryptionContext();
858 if (pCtx != NULL)
5039dede 859 {
6be0a20b 860 NXCP_ENCRYPTED_MESSAGE *pEnMsg = CSCPEncryptMessage(pCtx, pRawMsg);
5039dede
AK
861 if (pEnMsg != NULL)
862 {
d3a7cf4c 863 bResult = (SendEx(m_hSocket, (char *)pEnMsg, ntohl(pEnMsg->dwSize), 0, m_mutexSocketWrite) == (int)ntohl(pEnMsg->dwSize));
5039dede
AK
864 free(pEnMsg);
865 }
866 else
867 {
868 bResult = FALSE;
869 }
98abc9f1 870 pCtx->decRefCount();
5039dede
AK
871 }
872 else
873 {
d3a7cf4c 874 bResult = (SendEx(m_hSocket, (char *)pRawMsg, ntohl(pRawMsg->dwSize), 0, m_mutexSocketWrite) == (int)ntohl(pRawMsg->dwSize));
5039dede
AK
875 }
876 free(pRawMsg);
877 return bResult;
878}
879
7cf549ad 880/**
881 * Send raw message to agent
882 */
883BOOL AgentConnection::sendRawMessage(CSCP_MESSAGE *pMsg)
884{
885 BOOL bResult;
886
887 CSCP_MESSAGE *pRawMsg = pMsg;
888 NXCPEncryptionContext *pCtx = acquireEncryptionContext();
889 if (pCtx != NULL)
890 {
6be0a20b 891 NXCP_ENCRYPTED_MESSAGE *pEnMsg = CSCPEncryptMessage(pCtx, pRawMsg);
7cf549ad 892 if (pEnMsg != NULL)
893 {
894 bResult = (SendEx(m_hSocket, (char *)pEnMsg, ntohl(pEnMsg->dwSize), 0, m_mutexSocketWrite) == (int)ntohl(pEnMsg->dwSize));
895 free(pEnMsg);
896 }
897 else
898 {
899 bResult = FALSE;
900 }
901 pCtx->decRefCount();
902 }
903 else
904 {
905 bResult = (SendEx(m_hSocket, (char *)pRawMsg, ntohl(pRawMsg->dwSize), 0, m_mutexSocketWrite) == (int)ntohl(pRawMsg->dwSize));
906 }
907 return bResult;
908}
909
d51f2182
VK
910/**
911 * Trap handler. Should be overriden in derived classes to implement
912 * actual trap processing. Default implementation do nothing.
913 */
f480bdd4
VK
914void AgentConnection::onTrap(CSCPMessage *pMsg)
915{
916}
917
d51f2182
VK
918/**
919 * Data push handler. Should be overriden in derived classes to implement
920 * actual data push processing. Default implementation do nothing.
921 */
f480bdd4 922void AgentConnection::onDataPush(CSCPMessage *pMsg)
5039dede
AK
923{
924}
925
9fa031cd 926/**
927 * Monitoring data handler. Should be overriden in derived classes to implement
928 * actual monitoring data processing. Default implementation do nothing.
929 */
930void AgentConnection::onFileMonitoringData(CSCPMessage *pMsg)
931{
932}
933
489b117b 934/**
935 * SNMP trap handler. Should be overriden in derived classes to implement
936 * actual SNMP trap processing. Default implementation do nothing.
937 */
938void AgentConnection::onSnmpTrap(CSCPMessage *pMsg)
939{
940}
941
d51f2182
VK
942/**
943 * Custom message handler
944 * If returns true, message considered as processed and will not be placed in wait queue
945 */
90284364
VK
946bool AgentConnection::processCustomMessage(CSCPMessage *pMsg)
947{
948 return false;
949}
950
d51f2182
VK
951/**
952 * Get list of values
953 */
967893bb 954UINT32 AgentConnection::getList(const TCHAR *pszParam)
5039dede
AK
955{
956 CSCPMessage msg(m_nProtocolVersion), *pResponse;
967893bb 957 UINT32 i, dwRqId, dwRetCode;
5039dede
AK
958
959 if (m_bIsConnected)
960 {
7c521895 961 destroyResultData();
5039dede
AK
962 dwRqId = m_dwRequestId++;
963 msg.SetCode(CMD_GET_LIST);
964 msg.SetId(dwRqId);
965 msg.SetVariable(VID_PARAMETER, pszParam);
7c521895 966 if (sendMessage(&msg))
5039dede 967 {
7c521895 968 pResponse = waitForMessage(CMD_REQUEST_COMPLETED, dwRqId, m_dwCommandTimeout);
5039dede
AK
969 if (pResponse != NULL)
970 {
971 dwRetCode = pResponse->GetVariableLong(VID_RCC);
972 if (dwRetCode == ERR_SUCCESS)
973 {
974 m_dwNumDataLines = pResponse->GetVariableLong(VID_NUM_STRINGS);
975 m_ppDataLines = (TCHAR **)malloc(sizeof(TCHAR *) * m_dwNumDataLines);
976 for(i = 0; i < m_dwNumDataLines; i++)
977 m_ppDataLines[i] = pResponse->GetVariableStr(VID_ENUM_VALUE_BASE + i);
978 }
979 delete pResponse;
980 }
981 else
982 {
983 dwRetCode = ERR_REQUEST_TIMEOUT;
984 }
985 }
986 else
987 {
988 dwRetCode = ERR_CONNECTION_BROKEN;
989 }
990 }
991 else
992 {
993 dwRetCode = ERR_NOT_CONNECTED;
994 }
995
996 return dwRetCode;
997}
998
d51f2182
VK
999/**
1000 * Get table
1001 */
967893bb 1002UINT32 AgentConnection::getTable(const TCHAR *pszParam, Table **table)
4687826e
VK
1003{
1004 CSCPMessage msg(m_nProtocolVersion), *pResponse;
967893bb 1005 UINT32 dwRqId, dwRetCode;
4687826e
VK
1006
1007 *table = NULL;
1008 if (m_bIsConnected)
1009 {
1010 dwRqId = m_dwRequestId++;
1011 msg.SetCode(CMD_GET_TABLE);
1012 msg.SetId(dwRqId);
1013 msg.SetVariable(VID_PARAMETER, pszParam);
1014 if (sendMessage(&msg))
1015 {
1016 pResponse = waitForMessage(CMD_REQUEST_COMPLETED, dwRqId, m_dwCommandTimeout);
1017 if (pResponse != NULL)
1018 {
1019 dwRetCode = pResponse->GetVariableLong(VID_RCC);
1020 if (dwRetCode == ERR_SUCCESS)
1021 {
1022 *table = new Table(pResponse);
1023 }
1024 delete pResponse;
1025 }
1026 else
1027 {
1028 dwRetCode = ERR_REQUEST_TIMEOUT;
1029 }
1030 }
1031 else
1032 {
1033 dwRetCode = ERR_CONNECTION_BROKEN;
1034 }
1035 }
1036 else
1037 {
1038 dwRetCode = ERR_NOT_CONNECTED;
1039 }
1040
1041 return dwRetCode;
1042}
1043
975f38fc
VK
1044/**
1045 * Authenticate to agent
1046 */
967893bb 1047UINT32 AgentConnection::authenticate(BOOL bProxyData)
5039dede
AK
1048{
1049 CSCPMessage msg(m_nProtocolVersion);
967893bb 1050 UINT32 dwRqId;
5039dede
AK
1051 BYTE hash[32];
1052 int iAuthMethod = bProxyData ? m_iProxyAuth : m_iAuthMethod;
08b214c6 1053 const char *pszSecret = bProxyData ? m_szProxySecret : m_szSecret;
5039dede
AK
1054#ifdef UNICODE
1055 WCHAR szBuffer[MAX_SECRET_LENGTH];
1056#endif
1057
1058 if (iAuthMethod == AUTH_NONE)
1059 return ERR_SUCCESS; // No authentication required
1060
1061 dwRqId = m_dwRequestId++;
1062 msg.SetCode(CMD_AUTHENTICATE);
1063 msg.SetId(dwRqId);
1064 msg.SetVariable(VID_AUTH_METHOD, (WORD)iAuthMethod);
1065 switch(iAuthMethod)
1066 {
1067 case AUTH_PLAINTEXT:
1068#ifdef UNICODE
1069 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pszSecret, -1, szBuffer, MAX_SECRET_LENGTH);
1070 msg.SetVariable(VID_SHARED_SECRET, szBuffer);
1071#else
1072 msg.SetVariable(VID_SHARED_SECRET, pszSecret);
1073#endif
1074 break;
1075 case AUTH_MD5_HASH:
1076 CalculateMD5Hash((BYTE *)pszSecret, (int)strlen(pszSecret), hash);
1077 msg.SetVariable(VID_SHARED_SECRET, hash, MD5_DIGEST_SIZE);
1078 break;
1079 case AUTH_SHA1_HASH:
1080 CalculateSHA1Hash((BYTE *)pszSecret, (int)strlen(pszSecret), hash);
1081 msg.SetVariable(VID_SHARED_SECRET, hash, SHA1_DIGEST_SIZE);
1082 break;
1083 default:
1084 break;
1085 }
7c521895
VK
1086 if (sendMessage(&msg))
1087 return waitForRCC(dwRqId, m_dwCommandTimeout);
5039dede
AK
1088 else
1089 return ERR_CONNECTION_BROKEN;
1090}
1091
908d71bd
VK
1092/**
1093 * Execute action on agent
1094 */
1095UINT32 AgentConnection::execAction(const TCHAR *pszAction, int argc, TCHAR **argv,
1096 bool withOutput, void (* outputCallback)(ActionCallbackEvent, const TCHAR *, void *), void *cbData)
5039dede
AK
1097{
1098 CSCPMessage msg(m_nProtocolVersion);
967893bb 1099 UINT32 dwRqId;
5039dede
AK
1100 int i;
1101
1102 if (!m_bIsConnected)
1103 return ERR_NOT_CONNECTED;
1104
1105 dwRqId = m_dwRequestId++;
1106 msg.SetCode(CMD_ACTION);
1107 msg.SetId(dwRqId);
1108 msg.SetVariable(VID_ACTION_NAME, pszAction);
908d71bd 1109 msg.SetVariable(VID_RECEIVE_OUTPUT, (UINT16)(withOutput ? 1 : 0));
967893bb 1110 msg.SetVariable(VID_NUM_ARGS, (UINT32)argc);
5039dede
AK
1111 for(i = 0; i < argc; i++)
1112 msg.SetVariable(VID_ACTION_ARG_BASE + i, argv[i]);
1113
7c521895 1114 if (sendMessage(&msg))
908d71bd
VK
1115 {
1116 if (withOutput)
1117 {
1118 UINT32 rcc = waitForRCC(dwRqId, m_dwCommandTimeout);
1119 if (rcc == ERR_SUCCESS)
1120 {
1121 outputCallback(ACE_CONNECTED, NULL, cbData); // Indicate successful start
1122 bool eos = false;
1123 while(!eos)
1124 {
1125 CSCPMessage *response = waitForMessage(CMD_COMMAND_OUTPUT, dwRqId, m_dwCommandTimeout);
1126 if (response != NULL)
1127 {
1128 eos = response->isEndOfSequence();
1129 if (response->isFieldExist(VID_MESSAGE))
1130 {
1131 TCHAR line[4096];
1132 response->GetVariableStr(VID_MESSAGE, line, 4096);
1133 outputCallback(ACE_DATA, line, cbData);
1134 }
1135 delete response;
1136 }
1137 else
1138 {
1139 return ERR_REQUEST_TIMEOUT;
1140 }
1141 }
1142 outputCallback(ACE_DISCONNECTED, NULL, cbData);
1143 return ERR_SUCCESS;
1144 }
1145 else
1146 {
1147 return rcc;
1148 }
1149 }
1150 else
1151 {
1152 return waitForRCC(dwRqId, m_dwCommandTimeout);
1153 }
1154 }
5039dede 1155 else
908d71bd 1156 {
5039dede 1157 return ERR_CONNECTION_BROKEN;
908d71bd 1158 }
5039dede
AK
1159}
1160
74d2f1ea 1161/**
1162 * Upload file to agent
1163 */
967893bb 1164UINT32 AgentConnection::uploadFile(const TCHAR *localFile, const TCHAR *destinationFile, void (* progressCallback)(INT64, void *), void *cbArg)
5039dede 1165{
967893bb 1166 UINT32 dwRqId, dwResult;
5039dede 1167 CSCPMessage msg(m_nProtocolVersion);
5039dede
AK
1168
1169 if (!m_bIsConnected)
1170 return ERR_NOT_CONNECTED;
1171
1172 dwRqId = m_dwRequestId++;
8581943e 1173 msg.SetId(dwRqId);
5039dede 1174
8581943e
VK
1175 // Use core agent if destination file name is not set and file manager subagent otherwise
1176 if ((destinationFile == NULL) || (*destinationFile == 0))
74d2f1ea 1177 {
1178 msg.SetCode(CMD_TRANSFER_FILE);
8581943e
VK
1179 int i;
1180 for(i = (int)_tcslen(localFile) - 1;
1181 (i >= 0) && (localFile[i] != '\\') && (localFile[i] != '/'); i--);
1182 msg.SetVariable(VID_FILE_NAME, &localFile[i + 1]);
74d2f1ea 1183 }
1184 else
1185 {
1186 msg.SetCode(CMD_FILEMGR_UPLOAD);
74d2f1ea 1187 msg.SetVariable(VID_FILE_NAME, destinationFile);
f0c1d2a4 1188 }
5039dede 1189
7c521895 1190 if (sendMessage(&msg))
5039dede 1191 {
7c521895 1192 dwResult = waitForRCC(dwRqId, m_dwCommandTimeout);
5039dede
AK
1193 }
1194 else
1195 {
1196 dwResult = ERR_CONNECTION_BROKEN;
1197 }
1198
1199 if (dwResult == ERR_SUCCESS)
1200 {
4685a2ad 1201 m_fileUploadInProgress = true;
98abc9f1 1202 NXCPEncryptionContext *ctx = acquireEncryptionContext();
cc022855 1203 if (SendFileOverNXCP(m_hSocket, dwRqId, localFile, ctx, 0, progressCallback, cbArg, m_mutexSocketWrite))
7c521895 1204 dwResult = waitForRCC(dwRqId, m_dwCommandTimeout);
5039dede
AK
1205 else
1206 dwResult = ERR_IO_FAILURE;
4685a2ad 1207 m_fileUploadInProgress = false;
5039dede
AK
1208 }
1209
1210 return dwResult;
1211}
1212
8581943e
VK
1213/**
1214 * Send upgrade command
1215 */
967893bb 1216UINT32 AgentConnection::startUpgrade(const TCHAR *pszPkgName)
5039dede 1217{
967893bb 1218 UINT32 dwRqId, dwResult;
5039dede
AK
1219 CSCPMessage msg(m_nProtocolVersion);
1220 int i;
1221
1222 if (!m_bIsConnected)
1223 return ERR_NOT_CONNECTED;
1224
1225 dwRqId = m_dwRequestId++;
1226
1227 msg.SetCode(CMD_UPGRADE_AGENT);
1228 msg.SetId(dwRqId);
cc022855 1229 for(i = (int)_tcslen(pszPkgName) - 1;
5039dede
AK
1230 (i >= 0) && (pszPkgName[i] != '\\') && (pszPkgName[i] != '/'); i--);
1231 msg.SetVariable(VID_FILE_NAME, &pszPkgName[i + 1]);
1232
7c521895 1233 if (sendMessage(&msg))
5039dede 1234 {
7c521895 1235 dwResult = waitForRCC(dwRqId, m_dwCommandTimeout);
5039dede
AK
1236 }
1237 else
1238 {
1239 dwResult = ERR_CONNECTION_BROKEN;
1240 }
1241
1242 return dwResult;
1243}
1244
a0e181dc
VK
1245/**
1246 * Check status of network service via agent
1247 */
cc022855 1248UINT32 AgentConnection::checkNetworkService(UINT32 *pdwStatus, UINT32 dwIpAddr, int iServiceType,
b8014eee
VK
1249 WORD wPort, WORD wProto, const TCHAR *pszRequest,
1250 const TCHAR *pszResponse, UINT32 *responseTime)
5039dede 1251{
967893bb 1252 UINT32 dwRqId, dwResult;
5039dede 1253 CSCPMessage msg(m_nProtocolVersion), *pResponse;
a0e181dc 1254 static WORD m_wDefaultPort[] = { 7, 22, 110, 25, 21, 80, 443, 23 };
5039dede
AK
1255
1256 if (!m_bIsConnected)
1257 return ERR_NOT_CONNECTED;
1258
1259 dwRqId = m_dwRequestId++;
1260
1261 msg.SetCode(CMD_CHECK_NETWORK_SERVICE);
1262 msg.SetId(dwRqId);
1263 msg.SetVariable(VID_IP_ADDRESS, dwIpAddr);
1264 msg.SetVariable(VID_SERVICE_TYPE, (WORD)iServiceType);
cc022855 1265 msg.SetVariable(VID_IP_PORT,
1266 (wPort != 0) ? wPort :
1267 m_wDefaultPort[((iServiceType >= NETSRV_CUSTOM) &&
a0e181dc 1268 (iServiceType <= NETSRV_TELNET)) ? iServiceType : 0]);
5039dede
AK
1269 msg.SetVariable(VID_IP_PROTO, (wProto != 0) ? wProto : (WORD)IPPROTO_TCP);
1270 msg.SetVariable(VID_SERVICE_REQUEST, pszRequest);
1271 msg.SetVariable(VID_SERVICE_RESPONSE, pszResponse);
1272
7c521895 1273 if (sendMessage(&msg))
5039dede
AK
1274 {
1275 // Wait up to 90 seconds for results
7c521895 1276 pResponse = waitForMessage(CMD_REQUEST_COMPLETED, dwRqId, 90000);
5039dede
AK
1277 if (pResponse != NULL)
1278 {
1279 dwResult = pResponse->GetVariableLong(VID_RCC);
1280 if (dwResult == ERR_SUCCESS)
1281 {
1282 *pdwStatus = pResponse->GetVariableLong(VID_SERVICE_STATUS);
b8014eee
VK
1283 if (responseTime != NULL)
1284 {
1285 *responseTime = pResponse->GetVariableLong(VID_RESPONSE_TIME);
1286 }
5039dede
AK
1287 }
1288 delete pResponse;
1289 }
1290 else
1291 {
1292 dwResult = ERR_REQUEST_TIMEOUT;
1293 }
1294 }
1295 else
1296 {
1297 dwResult = ERR_CONNECTION_BROKEN;
1298 }
1299
1300 return dwResult;
1301}
1302
074498ac 1303/**
86c126f5 1304 * Get list of supported parameters from agent
074498ac 1305 */
967893bb 1306UINT32 AgentConnection::getSupportedParameters(ObjectArray<AgentParameterDefinition> **paramList, ObjectArray<AgentTableDefinition> **tableList)
5039dede 1307{
967893bb 1308 UINT32 dwRqId, dwResult;
5039dede
AK
1309 CSCPMessage msg(m_nProtocolVersion), *pResponse;
1310
cc8ce218
VK
1311 *paramList = NULL;
1312 *tableList = NULL;
5039dede
AK
1313
1314 if (!m_bIsConnected)
1315 return ERR_NOT_CONNECTED;
1316
1317 dwRqId = m_dwRequestId++;
1318
1319 msg.SetCode(CMD_GET_PARAMETER_LIST);
1320 msg.SetId(dwRqId);
1321
7c521895 1322 if (sendMessage(&msg))
5039dede 1323 {
7c521895 1324 pResponse = waitForMessage(CMD_REQUEST_COMPLETED, dwRqId, m_dwCommandTimeout);
5039dede
AK
1325 if (pResponse != NULL)
1326 {
1327 dwResult = pResponse->GetVariableLong(VID_RCC);
cc8ce218 1328 DbgPrintf(6, _T("AgentConnection::getSupportedParameters(): RCC=%d"), dwResult);
5039dede
AK
1329 if (dwResult == ERR_SUCCESS)
1330 {
967893bb 1331 UINT32 count = pResponse->GetVariableLong(VID_NUM_PARAMETERS);
86c126f5 1332 ObjectArray<AgentParameterDefinition> *plist = new ObjectArray<AgentParameterDefinition>(count, 16, true);
967893bb 1333 for(UINT32 i = 0, dwId = VID_PARAM_LIST_BASE; i < count; i++)
5039dede 1334 {
86c126f5
VK
1335 plist->add(new AgentParameterDefinition(pResponse, dwId));
1336 dwId += 3;
5039dede 1337 }
86c126f5 1338 *paramList = plist;
cc8ce218
VK
1339 DbgPrintf(6, _T("AgentConnection::getSupportedParameters(): %d parameters received from agent"), count);
1340
1341 count = pResponse->GetVariableLong(VID_NUM_TABLES);
86c126f5 1342 ObjectArray<AgentTableDefinition> *tlist = new ObjectArray<AgentTableDefinition>(count, 16, true);
967893bb 1343 for(UINT32 i = 0, dwId = VID_TABLE_LIST_BASE; i < count; i++)
cc8ce218 1344 {
86c126f5
VK
1345 tlist->add(new AgentTableDefinition(pResponse, dwId));
1346 dwId += 3;
cc8ce218 1347 }
86c126f5 1348 *tableList = tlist;
cc8ce218
VK
1349 DbgPrintf(6, _T("AgentConnection::getSupportedParameters(): %d tables received from agent"), count);
1350 }
5039dede
AK
1351 delete pResponse;
1352 }
1353 else
1354 {
1355 dwResult = ERR_REQUEST_TIMEOUT;
1356 }
1357 }
1358 else
1359 {
1360 dwResult = ERR_CONNECTION_BROKEN;
1361 }
1362
1363 return dwResult;
1364}
1365
074498ac
VK
1366/**
1367 * Setup encryption
1368 */
967893bb 1369UINT32 AgentConnection::setupEncryption(RSA *pServerKey)
5039dede
AK
1370{
1371#ifdef _WITH_ENCRYPTION
1372 CSCPMessage msg(m_nProtocolVersion), *pResp;
967893bb 1373 UINT32 dwRqId, dwError, dwResult;
5039dede
AK
1374
1375 dwRqId = m_dwRequestId++;
1376
9e9d631e 1377 PrepareKeyRequestMsg(&msg, pServerKey, false);
5039dede 1378 msg.SetId(dwRqId);
7c521895 1379 if (sendMessage(&msg))
5039dede 1380 {
7c521895 1381 pResp = waitForMessage(CMD_SESSION_KEY, dwRqId, m_dwCommandTimeout);
5039dede
AK
1382 if (pResp != NULL)
1383 {
1384 dwResult = SetupEncryptionContext(pResp, &m_pCtx, NULL, pServerKey, m_nProtocolVersion);
1385 switch(dwResult)
1386 {
1387 case RCC_SUCCESS:
1388 dwError = ERR_SUCCESS;
1389 break;
1390 case RCC_NO_CIPHERS:
1391 dwError = ERR_NO_CIPHERS;
1392 break;
1393 case RCC_INVALID_PUBLIC_KEY:
1394 dwError = ERR_INVALID_PUBLIC_KEY;
1395 break;
1396 case RCC_INVALID_SESSION_KEY:
1397 dwError = ERR_INVALID_SESSION_KEY;
1398 break;
1399 default:
1400 dwError = ERR_INTERNAL_ERROR;
1401 break;
1402 }
1403 delete pResp;
1404 }
1405 else
1406 {
1407 dwError = ERR_REQUEST_TIMEOUT;
1408 }
1409 }
1410 else
1411 {
1412 dwError = ERR_CONNECTION_BROKEN;
1413 }
1414
1415 return dwError;
1416#else
1417 return ERR_NOT_IMPLEMENTED;
1418#endif
1419}
1420
5944946e
VK
1421/**
1422 * Get configuration file from agent
1423 */
967893bb 1424UINT32 AgentConnection::getConfigFile(TCHAR **ppszConfig, UINT32 *pdwSize)
5039dede 1425{
967893bb 1426 UINT32 i, dwRqId, dwResult;
5039dede
AK
1427 CSCPMessage msg(m_nProtocolVersion), *pResponse;
1428#ifdef UNICODE
1429 BYTE *pBuffer;
1430#endif
1431
1432 *ppszConfig = NULL;
1433 *pdwSize = 0;
1434
1435 if (!m_bIsConnected)
1436 return ERR_NOT_CONNECTED;
1437
1438 dwRqId = m_dwRequestId++;
1439
1440 msg.SetCode(CMD_GET_AGENT_CONFIG);
1441 msg.SetId(dwRqId);
1442
7c521895 1443 if (sendMessage(&msg))
5039dede 1444 {
7c521895 1445 pResponse = waitForMessage(CMD_REQUEST_COMPLETED, dwRqId, m_dwCommandTimeout);
5039dede
AK
1446 if (pResponse != NULL)
1447 {
1448 dwResult = pResponse->GetVariableLong(VID_RCC);
1449 if (dwResult == ERR_SUCCESS)
1450 {
1451 *pdwSize = pResponse->GetVariableBinary(VID_CONFIG_FILE, NULL, 0);
1452 *ppszConfig = (TCHAR *)malloc((*pdwSize + 1) * sizeof(TCHAR));
1453#ifdef UNICODE
1454 pBuffer = (BYTE *)malloc(*pdwSize + 1);
1455 pResponse->GetVariableBinary(VID_CONFIG_FILE, pBuffer, *pdwSize);
08b214c6 1456 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, (char *)pBuffer, *pdwSize, *ppszConfig, *pdwSize);
5039dede
AK
1457 free(pBuffer);
1458#else
1459 pResponse->GetVariableBinary(VID_CONFIG_FILE, (BYTE *)(*ppszConfig), *pdwSize);
1460#endif
1461 (*ppszConfig)[*pdwSize] = 0;
1462
1463 // We expect text file, so replace all non-printable characters with spaces
1464 for(i = 0; i < *pdwSize; i++)
cc022855 1465 if (((*ppszConfig)[i] < _T(' ')) &&
5039dede
AK
1466 ((*ppszConfig)[i] != _T('\t')) &&
1467 ((*ppszConfig)[i] != _T('\r')) &&
1468 ((*ppszConfig)[i] != _T('\n')))
1469 (*ppszConfig)[i] = _T(' ');
1470 }
1471 delete pResponse;
1472 }
1473 else
1474 {
1475 dwResult = ERR_REQUEST_TIMEOUT;
1476 }
1477 }
1478 else
1479 {
1480 dwResult = ERR_CONNECTION_BROKEN;
1481 }
1482
1483 return dwResult;
1484}
1485
5944946e
VK
1486/**
1487 * Update configuration file on agent
1488 */
967893bb 1489UINT32 AgentConnection::updateConfigFile(const TCHAR *pszConfig)
5039dede 1490{
967893bb 1491 UINT32 dwRqId, dwResult;
5039dede
AK
1492 CSCPMessage msg(m_nProtocolVersion);
1493#ifdef UNICODE
1494 int nChars;
1495 BYTE *pBuffer;
1496#endif
1497
1498 if (!m_bIsConnected)
1499 return ERR_NOT_CONNECTED;
1500
1501 dwRqId = m_dwRequestId++;
1502
1503 msg.SetCode(CMD_UPDATE_AGENT_CONFIG);
1504 msg.SetId(dwRqId);
1505#ifdef UNICODE
465b3f2d 1506 nChars = (int)_tcslen(pszConfig);
5039dede
AK
1507 pBuffer = (BYTE *)malloc(nChars + 1);
1508 WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK | WC_DEFAULTCHAR,
08b214c6 1509 pszConfig, nChars, (char *)pBuffer, nChars + 1, NULL, NULL);
5039dede
AK
1510 msg.SetVariable(VID_CONFIG_FILE, pBuffer, nChars);
1511 free(pBuffer);
1512#else
967893bb 1513 msg.SetVariable(VID_CONFIG_FILE, (BYTE *)pszConfig, (UINT32)strlen(pszConfig));
5039dede
AK
1514#endif
1515
7c521895 1516 if (sendMessage(&msg))
5039dede 1517 {
7c521895 1518 dwResult = waitForRCC(dwRqId, m_dwCommandTimeout);
5039dede
AK
1519 }
1520 else
1521 {
1522 dwResult = ERR_CONNECTION_BROKEN;
1523 }
1524
1525 return dwResult;
1526}
1527
5944946e
VK
1528/**
1529 * Get routing table from agent
1530 */
4687826e 1531ROUTING_TABLE *AgentConnection::getRoutingTable()
5039dede
AK
1532{
1533 ROUTING_TABLE *pRT = NULL;
967893bb 1534 UINT32 i, dwBits;
5039dede
AK
1535 TCHAR *pChar, *pBuf;
1536
4687826e 1537 if (getList(_T("Net.IP.RoutingTable")) == ERR_SUCCESS)
5039dede
AK
1538 {
1539 pRT = (ROUTING_TABLE *)malloc(sizeof(ROUTING_TABLE));
1540 pRT->iNumEntries = m_dwNumDataLines;
1541 pRT->pRoutes = (ROUTE *)malloc(sizeof(ROUTE) * m_dwNumDataLines);
1542 memset(pRT->pRoutes, 0, sizeof(ROUTE) * m_dwNumDataLines);
1543 for(i = 0; i < m_dwNumDataLines; i++)
1544 {
1545 pBuf = m_ppDataLines[i];
1546
1547 // Destination address and mask
1548 pChar = _tcschr(pBuf, _T(' '));
1549 if (pChar != NULL)
1550 {
1551 TCHAR *pSlash;
1552 static TCHAR defaultMask[] = _T("24");
1553
1554 *pChar = 0;
1555 pSlash = _tcschr(pBuf, _T('/'));
1556 if (pSlash != NULL)
1557 {
1558 *pSlash = 0;
1559 pSlash++;
1560 }
1561 else // Just a paranoia protection, should'n happen if agent working correctly
1562 {
1563 pSlash = defaultMask;
1564 }
1565 pRT->pRoutes[i].dwDestAddr = ntohl(_t_inet_addr(pBuf));
1566 dwBits = _tcstoul(pSlash, NULL, 10);
1567 pRT->pRoutes[i].dwDestMask = (dwBits == 32) ? 0xFFFFFFFF : (~(0xFFFFFFFF >> dwBits));
1568 pBuf = pChar + 1;
1569 }
1570
1571 // Next hop address
1572 pChar = _tcschr(pBuf, _T(' '));
1573 if (pChar != NULL)
1574 {
1575 *pChar = 0;
1576 pRT->pRoutes[i].dwNextHop = ntohl(_t_inet_addr(pBuf));
1577 pBuf = pChar + 1;
1578 }
1579
1580 // Interface index
1581 pChar = _tcschr(pBuf, ' ');
1582 if (pChar != NULL)
1583 {
1584 *pChar = 0;
1585 pRT->pRoutes[i].dwIfIndex = _tcstoul(pBuf, NULL, 10);
1586 pBuf = pChar + 1;
1587 }
1588
1589 // Route type
1590 pRT->pRoutes[i].dwRouteType = _tcstoul(pBuf, NULL, 10);
1591 }
1592
a3050773 1593 lock();
7c521895 1594 destroyResultData();
a3050773 1595 unlock();
5039dede
AK
1596 }
1597
1598 return pRT;
1599}
1600
5944946e
VK
1601/**
1602 * Set proxy information
1603 */
967893bb 1604void AgentConnection::setProxy(UINT32 dwAddr, WORD wPort, int iAuthMethod, const TCHAR *pszSecret)
5039dede
AK
1605{
1606 m_dwProxyAddr = dwAddr;
1607 m_wProxyPort = wPort;
1608 m_iProxyAuth = iAuthMethod;
1609 if (pszSecret != NULL)
1610 {
1611#ifdef UNICODE
cc022855 1612 WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK | WC_DEFAULTCHAR,
5039dede
AK
1613 pszSecret, -1, m_szProxySecret, MAX_SECRET_LENGTH, NULL, NULL);
1614#else
1615 nx_strncpy(m_szProxySecret, pszSecret, MAX_SECRET_LENGTH);
1616#endif
1617 }
1618 else
1619 {
1620 m_szProxySecret[0] = 0;
1621 }
1622 m_bUseProxy = TRUE;
1623}
1624
5944946e
VK
1625/**
1626 * Setup proxy connection
1627 */
967893bb 1628UINT32 AgentConnection::setupProxyConnection()
5039dede
AK
1629{
1630 CSCPMessage msg(m_nProtocolVersion);
967893bb 1631 UINT32 dwRqId;
5039dede
AK
1632
1633 dwRqId = m_dwRequestId++;
1634 msg.SetCode(CMD_SETUP_PROXY_CONNECTION);
1635 msg.SetId(dwRqId);
967893bb 1636 msg.SetVariable(VID_IP_ADDRESS, (UINT32)ntohl(m_dwAddr));
5039dede 1637 msg.SetVariable(VID_AGENT_PORT, m_wPort);
7c521895
VK
1638 if (sendMessage(&msg))
1639 return waitForRCC(dwRqId, 60000); // Wait 60 seconds for remote connect
5039dede
AK
1640 else
1641 return ERR_CONNECTION_BROKEN;
1642}
1643
ef8278f0
VK
1644/**
1645 * Enable trap receiving on connection
1646 */
967893bb 1647UINT32 AgentConnection::enableTraps()
5039dede
AK
1648{
1649 CSCPMessage msg(m_nProtocolVersion);
967893bb 1650 UINT32 dwRqId;
5039dede
AK
1651
1652 dwRqId = m_dwRequestId++;
1653 msg.SetCode(CMD_ENABLE_AGENT_TRAPS);
1654 msg.SetId(dwRqId);
7c521895
VK
1655 if (sendMessage(&msg))
1656 return waitForRCC(dwRqId, m_dwCommandTimeout);
5039dede
AK
1657 else
1658 return ERR_CONNECTION_BROKEN;
1659}
1660
5944946e
VK
1661/**
1662 * Take screenshot from remote system
1663 */
9c786c0f 1664UINT32 AgentConnection::takeScreenshot(const TCHAR *sessionName, BYTE **data, size_t *size)
5944946e
VK
1665{
1666 CSCPMessage msg(m_nProtocolVersion);
1667 UINT32 dwRqId;
1668
1669 dwRqId = m_dwRequestId++;
1670 msg.SetCode(CMD_TAKE_SCREENSHOT);
1671 msg.SetId(dwRqId);
9c786c0f 1672 msg.SetVariable(VID_NAME, sessionName);
5944946e
VK
1673 if (sendMessage(&msg))
1674 {
1675 CSCPMessage *response = waitForMessage(CMD_REQUEST_COMPLETED, dwRqId, m_dwCommandTimeout);
1676 if (response != NULL)
1677 {
1678 UINT32 rcc = response->GetVariableLong(VID_RCC);
1679 if (rcc == ERR_SUCCESS)
1680 {
1681 BYTE *p = response->getBinaryFieldPtr(VID_FILE_DATA, size);
1682 if (p != NULL)
1683 {
1684 *data = (BYTE *)malloc(*size);
1685 memcpy(*data, p, *size);
1686 }
1687 else
1688 {
1689 *data = NULL;
1690 }
1691 }
1692 delete response;
1693 return rcc;
1694 }
1695 else
1696 {
1697 return ERR_REQUEST_TIMEOUT;
1698 }
1699 }
1700 else
1701 {
1702 return ERR_CONNECTION_BROKEN;
1703 }
1704}
1705
cc022855 1706/**
1707 * Send custom request to agent
1708 */
76b4edb5 1709CSCPMessage *AgentConnection::customRequest(CSCPMessage *pRequest, const TCHAR *recvFile, bool append, void (*downloadProgressCallback)(size_t, void *),
1710 void (*fileResendCallback)(CSCP_MESSAGE*, void *), void *cbArg)
5039dede 1711{
967893bb 1712 UINT32 dwRqId, rcc;
5039dede
AK
1713 CSCPMessage *msg = NULL;
1714
1715 dwRqId = m_dwRequestId++;
1716 pRequest->SetId(dwRqId);
1717 if (recvFile != NULL)
1718 {
76b4edb5 1719 rcc = prepareFileDownload(recvFile, dwRqId, append, downloadProgressCallback, fileResendCallback,cbArg);
5039dede
AK
1720 if (rcc != ERR_SUCCESS)
1721 {
1722 // Create fake response message
1723 msg = new CSCPMessage;
1724 msg->SetCode(CMD_REQUEST_COMPLETED);
1725 msg->SetId(dwRqId);
1726 msg->SetVariable(VID_RCC, rcc);
1727 }
1728 }
1729
1730 if (msg == NULL)
1731 {
7c521895 1732 if (sendMessage(pRequest))
5039dede 1733 {
7c521895 1734 msg = waitForMessage(CMD_REQUEST_COMPLETED, dwRqId, m_dwCommandTimeout);
5039dede
AK
1735 if ((msg != NULL) && (recvFile != NULL))
1736 {
1737 if (msg->GetVariableLong(VID_RCC) == ERR_SUCCESS)
1738 {
bb85e341 1739 if (ConditionWait(m_condFileDownload, 1800000)) // 30 min timeout
5039dede 1740 {
bb85e341 1741 if (!m_fileDownloadSucceeded)
5039dede
AK
1742 {
1743 msg->SetVariable(VID_RCC, ERR_IO_FAILURE);
901a5a9b 1744 if (m_deleteFileOnDownloadFailure)
08b214c6 1745 _tremove(recvFile);
5039dede
AK
1746 }
1747 }
1748 else
1749 {
1750 msg->SetVariable(VID_RCC, ERR_REQUEST_TIMEOUT);
1751 }
1752 }
1753 else
1754 {
ef8278f0 1755 if (fileResendCallback != NULL)
76b4edb5 1756 {
1757 close(m_hCurrFile);
1758 m_hCurrFile = -1;
1759 _tremove(recvFile);
1760 }
5039dede
AK
1761 }
1762 }
76b4edb5 1763
5039dede
AK
1764 }
1765 }
1766
1767 return msg;
1768}
1769
76b4edb5 1770/**
ef8278f0 1771 * Prepare for file download
76b4edb5 1772 */
76b4edb5 1773UINT32 AgentConnection::prepareFileDownload(const TCHAR *fileName, UINT32 rqId, bool append, void (*downloadProgressCallback)(size_t, void *),
ef8278f0 1774 void (*fileResendCallback)(CSCP_MESSAGE *, void *), void *cbArg)
5039dede 1775{
ef8278f0 1776 if (fileResendCallback == NULL)
76b4edb5 1777 {
1778 if (m_hCurrFile != -1)
1779 return ERR_RESOURCE_BUSY;
5039dede 1780
76b4edb5 1781 nx_strncpy(m_currentFileName, fileName, MAX_PATH);
1782 ConditionReset(m_condFileDownload);
1783 m_hCurrFile = _topen(fileName, (append ? 0 : (O_CREAT | O_TRUNC)) | O_RDWR | O_BINARY, S_IREAD | S_IWRITE);
1784 if (m_hCurrFile == -1)
1785 {
1786 DbgPrintf(4, _T("AgentConnection::PrepareFileDownload(): cannot open file %s (%s); append=%d rqId=%d"),
1787 fileName, _tcserror(errno), append, rqId);
1788 }
1789 else
1790 {
1791 if (append)
1792 lseek(m_hCurrFile, 0, SEEK_END);
1793 }
1794
1795 m_dwDownloadRequestId = rqId;
1796 m_downloadProgressCallback = downloadProgressCallback;
1797 m_downloadProgressCallbackArg = cbArg;
1798
9630fcd1
AK
1799 m_sendToClientMessageCallback = NULL;
1800
76b4edb5 1801 return (m_hCurrFile != -1) ? ERR_SUCCESS : ERR_FILE_OPEN_ERROR;
1802 }
1803 else
1804 {
1805 ConditionReset(m_condFileDownload);
76b4edb5 1806
1807 m_dwDownloadRequestId = rqId;
1808 m_downloadProgressCallback = downloadProgressCallback;
1809 m_downloadProgressCallbackArg = cbArg;
1810
9630fcd1
AK
1811 m_sendToClientMessageCallback = fileResendCallback;
1812
76b4edb5 1813 return ERR_SUCCESS;
1814 }
5039dede
AK
1815}
1816
76b4edb5 1817/**
1818 * File upload completion handler
1819 */
f480bdd4 1820void AgentConnection::onFileDownload(BOOL success)
5039dede 1821{
76b4edb5 1822 if (!success && m_deleteFileOnDownloadFailure)
901a5a9b 1823 _tremove(m_currentFileName);
bb85e341
VK
1824 m_fileDownloadSucceeded = success;
1825 ConditionSet(m_condFileDownload);
5039dede 1826}
1f385e47 1827
ef8278f0
VK
1828/**
1829 * Enable trap receiving on connection
1830 */
967893bb 1831UINT32 AgentConnection::getPolicyInventory(AgentPolicyInfo **info)
1f385e47
VK
1832{
1833 CSCPMessage msg(m_nProtocolVersion);
967893bb 1834 UINT32 dwRqId, rcc;
1f385e47
VK
1835
1836 *info = NULL;
1837 dwRqId = m_dwRequestId++;
1838 msg.SetCode(CMD_GET_POLICY_INVENTORY);
1839 msg.SetId(dwRqId);
1840 if (sendMessage(&msg))
1841 {
1842 CSCPMessage *response = waitForMessage(CMD_REQUEST_COMPLETED, dwRqId, m_dwCommandTimeout);
1843 if (response != NULL)
1844 {
1845 rcc = response->GetVariableLong(VID_RCC);
1846 if (rcc == ERR_SUCCESS)
1847 *info = new AgentPolicyInfo(response);
1848 delete response;
1849 }
1850 else
1851 {
1852 rcc = ERR_REQUEST_TIMEOUT;
1853 }
1854 }
1855 else
1856 {
1857 rcc = ERR_CONNECTION_BROKEN;
1858 }
1859 return rcc;
1860}
1861
ef8278f0
VK
1862/**
1863 * Uninstall policy by GUID
1864 */
967893bb 1865UINT32 AgentConnection::uninstallPolicy(uuid_t guid)
1f385e47 1866{
967893bb 1867 UINT32 rqId, rcc;
1f385e47
VK
1868 CSCPMessage msg(m_nProtocolVersion);
1869
1870 rqId = generateRequestId();
1871 msg.SetId(rqId);
1872 msg.SetCode(CMD_UNINSTALL_AGENT_POLICY);
1873 msg.SetVariable(VID_GUID, guid, UUID_LENGTH);
1874 if (sendMessage(&msg))
1875 {
1876 rcc = waitForRCC(rqId, m_dwCommandTimeout);
1877 }
1878 else
1879 {
1880 rcc = ERR_CONNECTION_BROKEN;
1881 }
1882 return rcc;
1883}
98abc9f1 1884
86c126f5
VK
1885/**
1886 * Acquire encryption context
1887 */
98abc9f1
VK
1888NXCPEncryptionContext *AgentConnection::acquireEncryptionContext()
1889{
a3050773 1890 lock();
98abc9f1
VK
1891 NXCPEncryptionContext *ctx = m_pCtx;
1892 if (ctx != NULL)
1893 ctx->incRefCount();
a3050773 1894 unlock();
98abc9f1
VK
1895 return ctx;
1896}
86c126f5
VK
1897
1898/**
1899 * Create new agent parameter definition from NXCP message
1900 */
967893bb 1901AgentParameterDefinition::AgentParameterDefinition(CSCPMessage *msg, UINT32 baseId)
86c126f5
VK
1902{
1903 m_name = msg->GetVariableStr(baseId);
1904 m_description = msg->GetVariableStr(baseId + 1);
1905 m_dataType = (int)msg->GetVariableShort(baseId + 2);
1906}
1907
1908/**
1909 * Create new agent parameter definition from another definition object
1910 */
1911AgentParameterDefinition::AgentParameterDefinition(AgentParameterDefinition *src)
1912{
1913 m_name = (src->m_name != NULL) ? _tcsdup(src->m_name) : NULL;
1914 m_description = (src->m_description != NULL) ? _tcsdup(src->m_description) : NULL;
1915 m_dataType = src->m_dataType;
1916}
1917
1918/**
1919 * Destructor for agent parameter definition
1920 */
1921AgentParameterDefinition::~AgentParameterDefinition()
1922{
1923 safe_free(m_name);
1924 safe_free(m_description);
1925}
1926
1927/**
1928 * Fill NXCP message
1929 */
967893bb 1930UINT32 AgentParameterDefinition::fillMessage(CSCPMessage *msg, UINT32 baseId)
86c126f5
VK
1931{
1932 msg->SetVariable(baseId, m_name);
1933 msg->SetVariable(baseId + 1, m_description);
1934 msg->SetVariable(baseId + 2, (WORD)m_dataType);
1935 return 3;
1936}
1937
1938/**
1939 * Create new agent table definition from NXCP message
1940 */
967893bb 1941AgentTableDefinition::AgentTableDefinition(CSCPMessage *msg, UINT32 baseId)
86c126f5
VK
1942{
1943 m_name = msg->GetVariableStr(baseId);
1944 m_description = msg->GetVariableStr(baseId + 2);
1945
1946 TCHAR *instanceColumns = msg->GetVariableStr(baseId + 1);
1947 if (instanceColumns != NULL)
1948 {
1949 m_instanceColumns = new StringList(instanceColumns, _T("|"));
1950 free(instanceColumns);
1951 }
1952 else
1953 {
1954 m_instanceColumns = new StringList;
1955 }
1956
1957 m_columns = new ObjectArray<AgentTableColumnDefinition>(16, 16, true);
1958}
1959
1960/**
1961 * Create new agent table definition from another definition object
1962 */
1963AgentTableDefinition::AgentTableDefinition(AgentTableDefinition *src)
1964{
1965 m_name = (src->m_name != NULL) ? _tcsdup(src->m_name) : NULL;
1966 m_description = (src->m_description != NULL) ? _tcsdup(src->m_description) : NULL;
1967 m_instanceColumns = new StringList(src->m_instanceColumns);
1968 m_columns = new ObjectArray<AgentTableColumnDefinition>(16, 16, true);
1969 for(int i = 0; i < src->m_columns->size(); i++)
1970 {
1971 m_columns->add(new AgentTableColumnDefinition(src->m_columns->get(i)));
1972 }
1973}
1974/**
1975 * Destructor for agent table definition
1976 */
1977AgentTableDefinition::~AgentTableDefinition()
1978{
1979 safe_free(m_name);
1980 safe_free(m_description);
1981 delete m_instanceColumns;
1982 delete m_columns;
1983}
1984
1985/**
1986 * Fill NXCP message
1987 */
967893bb 1988UINT32 AgentTableDefinition::fillMessage(CSCPMessage *msg, UINT32 baseId)
86c126f5
VK
1989{
1990 msg->SetVariable(baseId + 1, m_name);
1991 msg->SetVariable(baseId + 2, m_description);
1992
1993 TCHAR *instanceColumns = m_instanceColumns->join(_T("|"));
1994 msg->SetVariable(baseId + 3, instanceColumns);
1995 free(instanceColumns);
1996
967893bb 1997 UINT32 varId = baseId + 4;
86c126f5
VK
1998 for(int i = 0; i < m_columns->size(); i++)
1999 {
2000 msg->SetVariable(varId++, m_columns->get(i)->m_name);
2001 msg->SetVariable(varId++, (WORD)m_columns->get(i)->m_dataType);
2002 }
2003
2004 msg->SetVariable(baseId, varId - baseId);
2005 return varId - baseId;
2006}