version updated
[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 {
272 m_downloadProgressCallback(pRawMsg->dwSize - (CSCP_HEADER_SIZE + 8), m_downloadProgressCallbackArg);
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;
349 break;
90284364
VK
350 default:
351 if (processCustomMessage(pMsg))
352 delete pMsg;
353 else
c17f6cbc 354 m_pMsgWaitQueue->put(pMsg);
90284364 355 break;
5039dede
AK
356 }
357 }
358 }
359
360 // Close socket and mark connection as disconnected
a3050773 361 lock();
f2665675
VK
362 if (m_hCurrFile != -1)
363 {
364 close(m_hCurrFile);
365 m_hCurrFile = -1;
f480bdd4 366 onFileDownload(FALSE);
f2665675 367 }
cc022855 368
4685a2ad 369 if (error == 0)
5039dede
AK
370 shutdown(m_hSocket, SHUT_RDWR);
371 closesocket(m_hSocket);
372 m_hSocket = -1;
98abc9f1
VK
373 if (m_pCtx != NULL)
374 {
375 m_pCtx->decRefCount();
376 m_pCtx = NULL;
377 }
5039dede 378 m_bIsConnected = FALSE;
a3050773 379 unlock();
5039dede
AK
380
381 free(pRawMsg);
382 free(pMsgBuffer);
383#ifdef _WITH_ENCRYPTION
384 free(pDecryptionBuffer);
385#endif
386}
387
a3050773
VK
388/**
389 * Connect to agent
390 */
967893bb 391BOOL AgentConnection::connect(RSA *pServerKey, BOOL bVerbose, UINT32 *pdwError, UINT32 *pdwSocketError)
5039dede
AK
392{
393 struct sockaddr_in sa;
394 TCHAR szBuffer[256];
395 BOOL bSuccess = FALSE, bForceEncryption = FALSE, bSecondPass = FALSE;
967893bb 396 UINT32 dwError = 0;
5039dede
AK
397
398 if (pdwError != NULL)
399 *pdwError = ERR_INTERNAL_ERROR;
400
c3acd0f6
VK
401 if (pdwSocketError != NULL)
402 *pdwSocketError = 0;
403
5039dede
AK
404 // Check if already connected
405 if (m_bIsConnected)
406 return FALSE;
407
408 // Wait for receiver thread from previous connection, if any
409 ThreadJoin(m_hReceiverThread);
410 m_hReceiverThread = INVALID_THREAD_HANDLE;
411
412 // Check if we need to close existing socket
413 if (m_hSocket != -1)
414 closesocket(m_hSocket);
415
416 // Create socket
417 m_hSocket = socket(AF_INET, SOCK_STREAM, 0);
4c0c75c7 418 if (m_hSocket == INVALID_SOCKET)
5039dede 419 {
a3050773 420 printMsg(_T("Call to socket() failed"));
5039dede
AK
421 goto connect_cleanup;
422 }
423
424 // Fill in address structure
425 memset(&sa, 0, sizeof(sa));
426 sa.sin_family = AF_INET;
427 if (m_bUseProxy)
428 {
429 sa.sin_addr.s_addr = m_dwProxyAddr;
430 sa.sin_port = htons(m_wProxyPort);
431 }
432 else
433 {
434 sa.sin_addr.s_addr = m_dwAddr;
435 sa.sin_port = htons(m_wPort);
436 }
437
438 // Connect to server
7c521895 439 if (ConnectEx(m_hSocket, (struct sockaddr *)&sa, sizeof(sa), m_connectionTimeout) == -1)
5039dede
AK
440 {
441 if (bVerbose)
a3050773 442 printMsg(_T("Cannot establish connection with agent %s"),
5039dede
AK
443 IpToStr(ntohl(m_bUseProxy ? m_dwProxyAddr : m_dwAddr), szBuffer));
444 dwError = ERR_CONNECT_FAILED;
445 goto connect_cleanup;
446 }
447
d3a7cf4c 448 if (!NXCPGetPeerProtocolVersion(m_hSocket, &m_nProtocolVersion, m_mutexSocketWrite))
5039dede
AK
449 {
450 dwError = ERR_INTERNAL_ERROR;
451 goto connect_cleanup;
452 }
453
454 // Start receiver thread
a3050773 455 m_hReceiverThread = ThreadCreateEx(receiverThreadStarter, 0, this);
5039dede
AK
456
457 // Setup encryption
458setup_encryption:
459 if ((m_iEncryptionPolicy == ENCRYPTION_PREFERRED) ||
460 (m_iEncryptionPolicy == ENCRYPTION_REQUIRED) ||
461 (bForceEncryption)) // Agent require encryption
462 {
463 if (pServerKey != NULL)
464 {
7c521895 465 dwError = setupEncryption(pServerKey);
5039dede
AK
466 if ((dwError != ERR_SUCCESS) &&
467 ((m_iEncryptionPolicy == ENCRYPTION_REQUIRED) || bForceEncryption))
468 goto connect_cleanup;
469 }
470 else
471 {
472 if ((m_iEncryptionPolicy == ENCRYPTION_REQUIRED) || bForceEncryption)
473 {
474 dwError = ERR_ENCRYPTION_REQUIRED;
475 goto connect_cleanup;
476 }
477 }
478 }
479
480 // Authenticate itself to agent
7c521895 481 if ((dwError = authenticate(m_bUseProxy && !bSecondPass)) != ERR_SUCCESS)
5039dede
AK
482 {
483 if ((dwError == ERR_ENCRYPTION_REQUIRED) &&
484 (m_iEncryptionPolicy != ENCRYPTION_DISABLED))
485 {
486 bForceEncryption = TRUE;
487 goto setup_encryption;
488 }
a3050773 489 printMsg(_T("Authentication to agent %s failed (%s)"), IpToStr(ntohl(m_dwAddr), szBuffer),
5039dede
AK
490 AgentErrorCodeToText(dwError));
491 goto connect_cleanup;
492 }
493
494 // Test connectivity
45d84f8a 495 if ((dwError = nop()) != ERR_SUCCESS)
5039dede
AK
496 {
497 if ((dwError == ERR_ENCRYPTION_REQUIRED) &&
498 (m_iEncryptionPolicy != ENCRYPTION_DISABLED))
499 {
500 bForceEncryption = TRUE;
501 goto setup_encryption;
502 }
a3050773 503 printMsg(_T("Communication with agent %s failed (%s)"), IpToStr(ntohl(m_dwAddr), szBuffer),
5039dede
AK
504 AgentErrorCodeToText(dwError));
505 goto connect_cleanup;
506 }
507
508 if (m_bUseProxy && !bSecondPass)
509 {
7c521895 510 dwError = setupProxyConnection();
5039dede
AK
511 if (dwError != ERR_SUCCESS)
512 goto connect_cleanup;
a3050773 513 lock();
98abc9f1
VK
514 if (m_pCtx != NULL)
515 {
516 m_pCtx->decRefCount();
517 m_pCtx = NULL;
518 }
a3050773 519 unlock();
5039dede
AK
520 bSecondPass = TRUE;
521 bForceEncryption = FALSE;
522 goto setup_encryption;
523 }
524
525 bSuccess = TRUE;
526 dwError = ERR_SUCCESS;
527
528connect_cleanup:
529 if (!bSuccess)
530 {
c3acd0f6 531 if (pdwSocketError != NULL)
967893bb 532 *pdwSocketError = (UINT32)WSAGetLastError();
c3acd0f6 533
a3050773 534 lock();
5039dede
AK
535 if (m_hSocket != -1)
536 shutdown(m_hSocket, SHUT_RDWR);
a3050773 537 unlock();
5039dede
AK
538 ThreadJoin(m_hReceiverThread);
539 m_hReceiverThread = INVALID_THREAD_HANDLE;
540
a3050773 541 lock();
5039dede
AK
542 if (m_hSocket != -1)
543 {
544 closesocket(m_hSocket);
545 m_hSocket = -1;
546 }
547
98abc9f1
VK
548 if (m_pCtx != NULL)
549 {
550 m_pCtx->decRefCount();
551 m_pCtx = NULL;
552 }
5039dede 553
a3050773 554 unlock();
5039dede
AK
555 }
556 m_bIsConnected = bSuccess;
557 if (pdwError != NULL)
558 *pdwError = dwError;
559 return bSuccess;
560}
561
af21affe
VK
562/**
563 * Disconnect from agent
564 */
7c521895 565void AgentConnection::disconnect()
5039dede 566{
a3050773 567 lock();
f2665675
VK
568 if (m_hCurrFile != -1)
569 {
570 close(m_hCurrFile);
571 m_hCurrFile = -1;
f480bdd4 572 onFileDownload(FALSE);
f2665675 573 }
9fa031cd 574
5039dede
AK
575 if (m_hSocket != -1)
576 {
577 shutdown(m_hSocket, SHUT_RDWR);
578 }
7c521895 579 destroyResultData();
5039dede 580 m_bIsConnected = FALSE;
a3050773 581 unlock();
5039dede
AK
582}
583
af21affe
VK
584/**
585 * Set authentication data
586 */
587void AgentConnection::setAuthData(int method, const TCHAR *secret)
cc022855 588{
af21affe
VK
589 m_iAuthMethod = method;
590#ifdef UNICODE
591 WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK | WC_DEFAULTCHAR, secret, -1, m_szSecret, MAX_SECRET_LENGTH, NULL, NULL);
592 m_szSecret[MAX_SECRET_LENGTH - 1] = 0;
593#else
594 nx_strncpy(m_szSecret, secret, MAX_SECRET_LENGTH);
595#endif
596}
5039dede 597
af21affe
VK
598/**
599 * Destroy command execuion results data
600 */
7c521895 601void AgentConnection::destroyResultData()
5039dede 602{
967893bb 603 UINT32 i;
5039dede
AK
604
605 if (m_ppDataLines != NULL)
606 {
607 for(i = 0; i < m_dwNumDataLines; i++)
608 if (m_ppDataLines[i] != NULL)
609 free(m_ppDataLines[i]);
610 free(m_ppDataLines);
611 m_ppDataLines = NULL;
612 }
613 m_dwNumDataLines = 0;
614}
615
d51f2182
VK
616/**
617 * Get interface list from agent
618 */
98762401 619InterfaceList *AgentConnection::getInterfaceList()
5039dede 620{
98762401 621 InterfaceList *pIfList = NULL;
36e44abe 622 NX_INTERFACE_INFO iface;
967893bb 623 UINT32 i, dwBits;
5039dede
AK
624 TCHAR *pChar, *pBuf;
625
4687826e 626 if (getList(_T("Net.InterfaceList")) == ERR_SUCCESS)
5039dede 627 {
98762401 628 pIfList = new InterfaceList(m_dwNumDataLines);
5039dede
AK
629
630 // Parse result set. Each line should have the following format:
631 // index ip_address/mask_bits iftype mac_address name
632 for(i = 0; i < m_dwNumDataLines; i++)
633 {
634 pBuf = m_ppDataLines[i];
36e44abe 635 memset(&iface, 0, sizeof(NX_INTERFACE_INFO));
5039dede
AK
636
637 // Index
638 pChar = _tcschr(pBuf, ' ');
639 if (pChar != NULL)
640 {
641 *pChar = 0;
98762401 642 iface.dwIndex = _tcstoul(pBuf, NULL, 10);
5039dede
AK
643 pBuf = pChar + 1;
644 }
645
646 // Address and mask
647 pChar = _tcschr(pBuf, _T(' '));
648 if (pChar != NULL)
649 {
650 TCHAR *pSlash;
651 static TCHAR defaultMask[] = _T("24");
652
653 *pChar = 0;
654 pSlash = _tcschr(pBuf, _T('/'));
655 if (pSlash != NULL)
656 {
657 *pSlash = 0;
658 pSlash++;
659 }
660 else // Just a paranoia protection, should'n happen if agent working correctly
661 {
662 pSlash = defaultMask;
663 }
98762401 664 iface.dwIpAddr = ntohl(_t_inet_addr(pBuf));
5039dede 665 dwBits = _tcstoul(pSlash, NULL, 10);
98762401 666 iface.dwIpNetMask = (dwBits == 32) ? 0xFFFFFFFF : (~(0xFFFFFFFF >> dwBits));
5039dede
AK
667 pBuf = pChar + 1;
668 }
669
670 // Interface type
671 pChar = _tcschr(pBuf, ' ');
672 if (pChar != NULL)
673 {
674 *pChar = 0;
98762401 675 iface.dwType = _tcstoul(pBuf, NULL, 10);
5039dede
AK
676 pBuf = pChar + 1;
677 }
678
679 // MAC address
680 pChar = _tcschr(pBuf, ' ');
681 if (pChar != NULL)
682 {
683 *pChar = 0;
98762401 684 StrToBin(pBuf, iface.bMacAddr, MAC_ADDR_LENGTH);
5039dede
AK
685 pBuf = pChar + 1;
686 }
687
478d4ff4
VK
688 // Name (set description to name)
689 nx_strncpy(iface.szName, pBuf, MAX_DB_STRING);
690 nx_strncpy(iface.szDescription, pBuf, MAX_DB_STRING);
98762401
VK
691
692 pIfList->add(&iface);
5039dede
AK
693 }
694
a3050773 695 lock();
7c521895 696 destroyResultData();
a3050773 697 unlock();
5039dede
AK
698 }
699
700 return pIfList;
701}
702
703
704//
705// Get parameter value
706//
707
967893bb 708UINT32 AgentConnection::getParameter(const TCHAR *pszParam, UINT32 dwBufSize, TCHAR *pszBuffer)
5039dede
AK
709{
710 CSCPMessage msg(m_nProtocolVersion), *pResponse;
967893bb 711 UINT32 dwRqId, dwRetCode;
5039dede
AK
712
713 if (m_bIsConnected)
714 {
715 dwRqId = m_dwRequestId++;
716 msg.SetCode(CMD_GET_PARAMETER);
717 msg.SetId(dwRqId);
718 msg.SetVariable(VID_PARAMETER, pszParam);
7c521895 719 if (sendMessage(&msg))
5039dede 720 {
7c521895 721 pResponse = waitForMessage(CMD_REQUEST_COMPLETED, dwRqId, m_dwCommandTimeout);
5039dede
AK
722 if (pResponse != NULL)
723 {
724 dwRetCode = pResponse->GetVariableLong(VID_RCC);
725 if (dwRetCode == ERR_SUCCESS)
726 pResponse->GetVariableStr(VID_VALUE, pszBuffer, dwBufSize);
727 delete pResponse;
728 }
729 else
730 {
731 dwRetCode = ERR_REQUEST_TIMEOUT;
732 }
733 }
734 else
735 {
736 dwRetCode = ERR_CONNECTION_BROKEN;
737 }
738 }
739 else
740 {
741 dwRetCode = ERR_NOT_CONNECTED;
742 }
743
744 return dwRetCode;
745}
746
747
748//
749// Get ARP cache
750//
751
4687826e 752ARP_CACHE *AgentConnection::getArpCache()
5039dede
AK
753{
754 ARP_CACHE *pArpCache = NULL;
755 TCHAR szByte[4], *pBuf, *pChar;
967893bb 756 UINT32 i, j;
5039dede 757
4687826e 758 if (getList(_T("Net.ArpCache")) == ERR_SUCCESS)
5039dede
AK
759 {
760 // Create empty structure
761 pArpCache = (ARP_CACHE *)malloc(sizeof(ARP_CACHE));
762 pArpCache->dwNumEntries = m_dwNumDataLines;
763 pArpCache->pEntries = (ARP_ENTRY *)malloc(sizeof(ARP_ENTRY) * m_dwNumDataLines);
764 memset(pArpCache->pEntries, 0, sizeof(ARP_ENTRY) * m_dwNumDataLines);
765
766 szByte[2] = 0;
767
768 // Parse data lines
769 // Each line has form of XXXXXXXXXXXX a.b.c.d n
770 // where XXXXXXXXXXXX is a MAC address (12 hexadecimal digits)
771 // a.b.c.d is an IP address in decimal dotted notation
772 // n is an interface index
773 for(i = 0; i < m_dwNumDataLines; i++)
774 {
775 pBuf = m_ppDataLines[i];
776 if (_tcslen(pBuf) < 20) // Invalid line
777 continue;
778
779 // MAC address
780 for(j = 0; j < 6; j++)
781 {
782 memcpy(szByte, pBuf, sizeof(TCHAR) * 2);
783 pArpCache->pEntries[i].bMacAddr[j] = (BYTE)_tcstol(szByte, NULL, 16);
784 pBuf+=2;
785 }
786
787 // IP address
788 while(*pBuf == ' ')
789 pBuf++;
790 pChar = _tcschr(pBuf, _T(' '));
791 if (pChar != NULL)
792 *pChar = 0;
793 pArpCache->pEntries[i].dwIpAddr = ntohl(_t_inet_addr(pBuf));
794
795 // Interface index
796 if (pChar != NULL)
797 pArpCache->pEntries[i].dwIndex = _tcstoul(pChar + 1, NULL, 10);
798 }
799
a3050773 800 lock();
7c521895 801 destroyResultData();
a3050773 802 unlock();
5039dede
AK
803 }
804 return pArpCache;
805}
806
807
808//
809// Send dummy command to agent (can be used for keepalive)
810//
811
967893bb 812UINT32 AgentConnection::nop()
5039dede
AK
813{
814 CSCPMessage msg(m_nProtocolVersion);
967893bb 815 UINT32 dwRqId;
5039dede
AK
816
817 dwRqId = m_dwRequestId++;
818 msg.SetCode(CMD_KEEPALIVE);
819 msg.SetId(dwRqId);
7c521895
VK
820 if (sendMessage(&msg))
821 return waitForRCC(dwRqId, m_dwCommandTimeout);
5039dede
AK
822 else
823 return ERR_CONNECTION_BROKEN;
824}
825
826
827//
828// Wait for request completion code
829//
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 {
98abc9f1 860 CSCP_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 {
891 CSCP_ENCRYPTED_MESSAGE *pEnMsg = CSCPEncryptMessage(pCtx, pRawMsg);
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
d51f2182
VK
934/**
935 * Custom message handler
936 * If returns true, message considered as processed and will not be placed in wait queue
937 */
90284364
VK
938bool AgentConnection::processCustomMessage(CSCPMessage *pMsg)
939{
940 return false;
941}
942
d51f2182
VK
943/**
944 * Get list of values
945 */
967893bb 946UINT32 AgentConnection::getList(const TCHAR *pszParam)
5039dede
AK
947{
948 CSCPMessage msg(m_nProtocolVersion), *pResponse;
967893bb 949 UINT32 i, dwRqId, dwRetCode;
5039dede
AK
950
951 if (m_bIsConnected)
952 {
7c521895 953 destroyResultData();
5039dede
AK
954 dwRqId = m_dwRequestId++;
955 msg.SetCode(CMD_GET_LIST);
956 msg.SetId(dwRqId);
957 msg.SetVariable(VID_PARAMETER, pszParam);
7c521895 958 if (sendMessage(&msg))
5039dede 959 {
7c521895 960 pResponse = waitForMessage(CMD_REQUEST_COMPLETED, dwRqId, m_dwCommandTimeout);
5039dede
AK
961 if (pResponse != NULL)
962 {
963 dwRetCode = pResponse->GetVariableLong(VID_RCC);
964 if (dwRetCode == ERR_SUCCESS)
965 {
966 m_dwNumDataLines = pResponse->GetVariableLong(VID_NUM_STRINGS);
967 m_ppDataLines = (TCHAR **)malloc(sizeof(TCHAR *) * m_dwNumDataLines);
968 for(i = 0; i < m_dwNumDataLines; i++)
969 m_ppDataLines[i] = pResponse->GetVariableStr(VID_ENUM_VALUE_BASE + i);
970 }
971 delete pResponse;
972 }
973 else
974 {
975 dwRetCode = ERR_REQUEST_TIMEOUT;
976 }
977 }
978 else
979 {
980 dwRetCode = ERR_CONNECTION_BROKEN;
981 }
982 }
983 else
984 {
985 dwRetCode = ERR_NOT_CONNECTED;
986 }
987
988 return dwRetCode;
989}
990
d51f2182
VK
991/**
992 * Get table
993 */
967893bb 994UINT32 AgentConnection::getTable(const TCHAR *pszParam, Table **table)
4687826e
VK
995{
996 CSCPMessage msg(m_nProtocolVersion), *pResponse;
967893bb 997 UINT32 dwRqId, dwRetCode;
4687826e
VK
998
999 *table = NULL;
1000 if (m_bIsConnected)
1001 {
1002 dwRqId = m_dwRequestId++;
1003 msg.SetCode(CMD_GET_TABLE);
1004 msg.SetId(dwRqId);
1005 msg.SetVariable(VID_PARAMETER, pszParam);
1006 if (sendMessage(&msg))
1007 {
1008 pResponse = waitForMessage(CMD_REQUEST_COMPLETED, dwRqId, m_dwCommandTimeout);
1009 if (pResponse != NULL)
1010 {
1011 dwRetCode = pResponse->GetVariableLong(VID_RCC);
1012 if (dwRetCode == ERR_SUCCESS)
1013 {
1014 *table = new Table(pResponse);
1015 }
1016 delete pResponse;
1017 }
1018 else
1019 {
1020 dwRetCode = ERR_REQUEST_TIMEOUT;
1021 }
1022 }
1023 else
1024 {
1025 dwRetCode = ERR_CONNECTION_BROKEN;
1026 }
1027 }
1028 else
1029 {
1030 dwRetCode = ERR_NOT_CONNECTED;
1031 }
1032
1033 return dwRetCode;
1034}
1035
975f38fc
VK
1036/**
1037 * Authenticate to agent
1038 */
967893bb 1039UINT32 AgentConnection::authenticate(BOOL bProxyData)
5039dede
AK
1040{
1041 CSCPMessage msg(m_nProtocolVersion);
967893bb 1042 UINT32 dwRqId;
5039dede
AK
1043 BYTE hash[32];
1044 int iAuthMethod = bProxyData ? m_iProxyAuth : m_iAuthMethod;
08b214c6 1045 const char *pszSecret = bProxyData ? m_szProxySecret : m_szSecret;
5039dede
AK
1046#ifdef UNICODE
1047 WCHAR szBuffer[MAX_SECRET_LENGTH];
1048#endif
1049
1050 if (iAuthMethod == AUTH_NONE)
1051 return ERR_SUCCESS; // No authentication required
1052
1053 dwRqId = m_dwRequestId++;
1054 msg.SetCode(CMD_AUTHENTICATE);
1055 msg.SetId(dwRqId);
1056 msg.SetVariable(VID_AUTH_METHOD, (WORD)iAuthMethod);
1057 switch(iAuthMethod)
1058 {
1059 case AUTH_PLAINTEXT:
1060#ifdef UNICODE
1061 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pszSecret, -1, szBuffer, MAX_SECRET_LENGTH);
1062 msg.SetVariable(VID_SHARED_SECRET, szBuffer);
1063#else
1064 msg.SetVariable(VID_SHARED_SECRET, pszSecret);
1065#endif
1066 break;
1067 case AUTH_MD5_HASH:
1068 CalculateMD5Hash((BYTE *)pszSecret, (int)strlen(pszSecret), hash);
1069 msg.SetVariable(VID_SHARED_SECRET, hash, MD5_DIGEST_SIZE);
1070 break;
1071 case AUTH_SHA1_HASH:
1072 CalculateSHA1Hash((BYTE *)pszSecret, (int)strlen(pszSecret), hash);
1073 msg.SetVariable(VID_SHARED_SECRET, hash, SHA1_DIGEST_SIZE);
1074 break;
1075 default:
1076 break;
1077 }
7c521895
VK
1078 if (sendMessage(&msg))
1079 return waitForRCC(dwRqId, m_dwCommandTimeout);
5039dede
AK
1080 else
1081 return ERR_CONNECTION_BROKEN;
1082}
1083
908d71bd
VK
1084/**
1085 * Execute action on agent
1086 */
1087UINT32 AgentConnection::execAction(const TCHAR *pszAction, int argc, TCHAR **argv,
1088 bool withOutput, void (* outputCallback)(ActionCallbackEvent, const TCHAR *, void *), void *cbData)
5039dede
AK
1089{
1090 CSCPMessage msg(m_nProtocolVersion);
967893bb 1091 UINT32 dwRqId;
5039dede
AK
1092 int i;
1093
1094 if (!m_bIsConnected)
1095 return ERR_NOT_CONNECTED;
1096
1097 dwRqId = m_dwRequestId++;
1098 msg.SetCode(CMD_ACTION);
1099 msg.SetId(dwRqId);
1100 msg.SetVariable(VID_ACTION_NAME, pszAction);
908d71bd 1101 msg.SetVariable(VID_RECEIVE_OUTPUT, (UINT16)(withOutput ? 1 : 0));
967893bb 1102 msg.SetVariable(VID_NUM_ARGS, (UINT32)argc);
5039dede
AK
1103 for(i = 0; i < argc; i++)
1104 msg.SetVariable(VID_ACTION_ARG_BASE + i, argv[i]);
1105
7c521895 1106 if (sendMessage(&msg))
908d71bd
VK
1107 {
1108 if (withOutput)
1109 {
1110 UINT32 rcc = waitForRCC(dwRqId, m_dwCommandTimeout);
1111 if (rcc == ERR_SUCCESS)
1112 {
1113 outputCallback(ACE_CONNECTED, NULL, cbData); // Indicate successful start
1114 bool eos = false;
1115 while(!eos)
1116 {
1117 CSCPMessage *response = waitForMessage(CMD_COMMAND_OUTPUT, dwRqId, m_dwCommandTimeout);
1118 if (response != NULL)
1119 {
1120 eos = response->isEndOfSequence();
1121 if (response->isFieldExist(VID_MESSAGE))
1122 {
1123 TCHAR line[4096];
1124 response->GetVariableStr(VID_MESSAGE, line, 4096);
1125 outputCallback(ACE_DATA, line, cbData);
1126 }
1127 delete response;
1128 }
1129 else
1130 {
1131 return ERR_REQUEST_TIMEOUT;
1132 }
1133 }
1134 outputCallback(ACE_DISCONNECTED, NULL, cbData);
1135 return ERR_SUCCESS;
1136 }
1137 else
1138 {
1139 return rcc;
1140 }
1141 }
1142 else
1143 {
1144 return waitForRCC(dwRqId, m_dwCommandTimeout);
1145 }
1146 }
5039dede 1147 else
908d71bd 1148 {
5039dede 1149 return ERR_CONNECTION_BROKEN;
908d71bd 1150 }
5039dede
AK
1151}
1152
74d2f1ea 1153/**
1154 * Upload file to agent
1155 */
967893bb 1156UINT32 AgentConnection::uploadFile(const TCHAR *localFile, const TCHAR *destinationFile, void (* progressCallback)(INT64, void *), void *cbArg)
5039dede 1157{
967893bb 1158 UINT32 dwRqId, dwResult;
5039dede 1159 CSCPMessage msg(m_nProtocolVersion);
5039dede
AK
1160
1161 if (!m_bIsConnected)
1162 return ERR_NOT_CONNECTED;
1163
1164 dwRqId = m_dwRequestId++;
8581943e 1165 msg.SetId(dwRqId);
5039dede 1166
8581943e
VK
1167 // Use core agent if destination file name is not set and file manager subagent otherwise
1168 if ((destinationFile == NULL) || (*destinationFile == 0))
74d2f1ea 1169 {
1170 msg.SetCode(CMD_TRANSFER_FILE);
8581943e
VK
1171 int i;
1172 for(i = (int)_tcslen(localFile) - 1;
1173 (i >= 0) && (localFile[i] != '\\') && (localFile[i] != '/'); i--);
1174 msg.SetVariable(VID_FILE_NAME, &localFile[i + 1]);
74d2f1ea 1175 }
1176 else
1177 {
1178 msg.SetCode(CMD_FILEMGR_UPLOAD);
74d2f1ea 1179 msg.SetVariable(VID_FILE_NAME, destinationFile);
f0c1d2a4 1180 }
5039dede 1181
7c521895 1182 if (sendMessage(&msg))
5039dede 1183 {
7c521895 1184 dwResult = waitForRCC(dwRqId, m_dwCommandTimeout);
5039dede
AK
1185 }
1186 else
1187 {
1188 dwResult = ERR_CONNECTION_BROKEN;
1189 }
1190
1191 if (dwResult == ERR_SUCCESS)
1192 {
4685a2ad 1193 m_fileUploadInProgress = true;
98abc9f1 1194 NXCPEncryptionContext *ctx = acquireEncryptionContext();
cc022855 1195 if (SendFileOverNXCP(m_hSocket, dwRqId, localFile, ctx, 0, progressCallback, cbArg, m_mutexSocketWrite))
7c521895 1196 dwResult = waitForRCC(dwRqId, m_dwCommandTimeout);
5039dede
AK
1197 else
1198 dwResult = ERR_IO_FAILURE;
4685a2ad 1199 m_fileUploadInProgress = false;
5039dede
AK
1200 }
1201
1202 return dwResult;
1203}
1204
8581943e
VK
1205/**
1206 * Send upgrade command
1207 */
967893bb 1208UINT32 AgentConnection::startUpgrade(const TCHAR *pszPkgName)
5039dede 1209{
967893bb 1210 UINT32 dwRqId, dwResult;
5039dede
AK
1211 CSCPMessage msg(m_nProtocolVersion);
1212 int i;
1213
1214 if (!m_bIsConnected)
1215 return ERR_NOT_CONNECTED;
1216
1217 dwRqId = m_dwRequestId++;
1218
1219 msg.SetCode(CMD_UPGRADE_AGENT);
1220 msg.SetId(dwRqId);
cc022855 1221 for(i = (int)_tcslen(pszPkgName) - 1;
5039dede
AK
1222 (i >= 0) && (pszPkgName[i] != '\\') && (pszPkgName[i] != '/'); i--);
1223 msg.SetVariable(VID_FILE_NAME, &pszPkgName[i + 1]);
1224
7c521895 1225 if (sendMessage(&msg))
5039dede 1226 {
7c521895 1227 dwResult = waitForRCC(dwRqId, m_dwCommandTimeout);
5039dede
AK
1228 }
1229 else
1230 {
1231 dwResult = ERR_CONNECTION_BROKEN;
1232 }
1233
1234 return dwResult;
1235}
1236
a0e181dc
VK
1237/**
1238 * Check status of network service via agent
1239 */
cc022855 1240UINT32 AgentConnection::checkNetworkService(UINT32 *pdwStatus, UINT32 dwIpAddr, int iServiceType,
b8014eee
VK
1241 WORD wPort, WORD wProto, const TCHAR *pszRequest,
1242 const TCHAR *pszResponse, UINT32 *responseTime)
5039dede 1243{
967893bb 1244 UINT32 dwRqId, dwResult;
5039dede 1245 CSCPMessage msg(m_nProtocolVersion), *pResponse;
a0e181dc 1246 static WORD m_wDefaultPort[] = { 7, 22, 110, 25, 21, 80, 443, 23 };
5039dede
AK
1247
1248 if (!m_bIsConnected)
1249 return ERR_NOT_CONNECTED;
1250
1251 dwRqId = m_dwRequestId++;
1252
1253 msg.SetCode(CMD_CHECK_NETWORK_SERVICE);
1254 msg.SetId(dwRqId);
1255 msg.SetVariable(VID_IP_ADDRESS, dwIpAddr);
1256 msg.SetVariable(VID_SERVICE_TYPE, (WORD)iServiceType);
cc022855 1257 msg.SetVariable(VID_IP_PORT,
1258 (wPort != 0) ? wPort :
1259 m_wDefaultPort[((iServiceType >= NETSRV_CUSTOM) &&
a0e181dc 1260 (iServiceType <= NETSRV_TELNET)) ? iServiceType : 0]);
5039dede
AK
1261 msg.SetVariable(VID_IP_PROTO, (wProto != 0) ? wProto : (WORD)IPPROTO_TCP);
1262 msg.SetVariable(VID_SERVICE_REQUEST, pszRequest);
1263 msg.SetVariable(VID_SERVICE_RESPONSE, pszResponse);
1264
7c521895 1265 if (sendMessage(&msg))
5039dede
AK
1266 {
1267 // Wait up to 90 seconds for results
7c521895 1268 pResponse = waitForMessage(CMD_REQUEST_COMPLETED, dwRqId, 90000);
5039dede
AK
1269 if (pResponse != NULL)
1270 {
1271 dwResult = pResponse->GetVariableLong(VID_RCC);
1272 if (dwResult == ERR_SUCCESS)
1273 {
1274 *pdwStatus = pResponse->GetVariableLong(VID_SERVICE_STATUS);
b8014eee
VK
1275 if (responseTime != NULL)
1276 {
1277 *responseTime = pResponse->GetVariableLong(VID_RESPONSE_TIME);
1278 }
5039dede
AK
1279 }
1280 delete pResponse;
1281 }
1282 else
1283 {
1284 dwResult = ERR_REQUEST_TIMEOUT;
1285 }
1286 }
1287 else
1288 {
1289 dwResult = ERR_CONNECTION_BROKEN;
1290 }
1291
1292 return dwResult;
1293}
1294
074498ac 1295/**
86c126f5 1296 * Get list of supported parameters from agent
074498ac 1297 */
967893bb 1298UINT32 AgentConnection::getSupportedParameters(ObjectArray<AgentParameterDefinition> **paramList, ObjectArray<AgentTableDefinition> **tableList)
5039dede 1299{
967893bb 1300 UINT32 dwRqId, dwResult;
5039dede
AK
1301 CSCPMessage msg(m_nProtocolVersion), *pResponse;
1302
cc8ce218
VK
1303 *paramList = NULL;
1304 *tableList = NULL;
5039dede
AK
1305
1306 if (!m_bIsConnected)
1307 return ERR_NOT_CONNECTED;
1308
1309 dwRqId = m_dwRequestId++;
1310
1311 msg.SetCode(CMD_GET_PARAMETER_LIST);
1312 msg.SetId(dwRqId);
1313
7c521895 1314 if (sendMessage(&msg))
5039dede 1315 {
7c521895 1316 pResponse = waitForMessage(CMD_REQUEST_COMPLETED, dwRqId, m_dwCommandTimeout);
5039dede
AK
1317 if (pResponse != NULL)
1318 {
1319 dwResult = pResponse->GetVariableLong(VID_RCC);
cc8ce218 1320 DbgPrintf(6, _T("AgentConnection::getSupportedParameters(): RCC=%d"), dwResult);
5039dede
AK
1321 if (dwResult == ERR_SUCCESS)
1322 {
967893bb 1323 UINT32 count = pResponse->GetVariableLong(VID_NUM_PARAMETERS);
86c126f5 1324 ObjectArray<AgentParameterDefinition> *plist = new ObjectArray<AgentParameterDefinition>(count, 16, true);
967893bb 1325 for(UINT32 i = 0, dwId = VID_PARAM_LIST_BASE; i < count; i++)
5039dede 1326 {
86c126f5
VK
1327 plist->add(new AgentParameterDefinition(pResponse, dwId));
1328 dwId += 3;
5039dede 1329 }
86c126f5 1330 *paramList = plist;
cc8ce218
VK
1331 DbgPrintf(6, _T("AgentConnection::getSupportedParameters(): %d parameters received from agent"), count);
1332
1333 count = pResponse->GetVariableLong(VID_NUM_TABLES);
86c126f5 1334 ObjectArray<AgentTableDefinition> *tlist = new ObjectArray<AgentTableDefinition>(count, 16, true);
967893bb 1335 for(UINT32 i = 0, dwId = VID_TABLE_LIST_BASE; i < count; i++)
cc8ce218 1336 {
86c126f5
VK
1337 tlist->add(new AgentTableDefinition(pResponse, dwId));
1338 dwId += 3;
cc8ce218 1339 }
86c126f5 1340 *tableList = tlist;
cc8ce218
VK
1341 DbgPrintf(6, _T("AgentConnection::getSupportedParameters(): %d tables received from agent"), count);
1342 }
5039dede
AK
1343 delete pResponse;
1344 }
1345 else
1346 {
1347 dwResult = ERR_REQUEST_TIMEOUT;
1348 }
1349 }
1350 else
1351 {
1352 dwResult = ERR_CONNECTION_BROKEN;
1353 }
1354
1355 return dwResult;
1356}
1357
074498ac
VK
1358/**
1359 * Setup encryption
1360 */
967893bb 1361UINT32 AgentConnection::setupEncryption(RSA *pServerKey)
5039dede
AK
1362{
1363#ifdef _WITH_ENCRYPTION
1364 CSCPMessage msg(m_nProtocolVersion), *pResp;
967893bb 1365 UINT32 dwRqId, dwError, dwResult;
5039dede
AK
1366
1367 dwRqId = m_dwRequestId++;
1368
9e9d631e 1369 PrepareKeyRequestMsg(&msg, pServerKey, false);
5039dede 1370 msg.SetId(dwRqId);
7c521895 1371 if (sendMessage(&msg))
5039dede 1372 {
7c521895 1373 pResp = waitForMessage(CMD_SESSION_KEY, dwRqId, m_dwCommandTimeout);
5039dede
AK
1374 if (pResp != NULL)
1375 {
1376 dwResult = SetupEncryptionContext(pResp, &m_pCtx, NULL, pServerKey, m_nProtocolVersion);
1377 switch(dwResult)
1378 {
1379 case RCC_SUCCESS:
1380 dwError = ERR_SUCCESS;
1381 break;
1382 case RCC_NO_CIPHERS:
1383 dwError = ERR_NO_CIPHERS;
1384 break;
1385 case RCC_INVALID_PUBLIC_KEY:
1386 dwError = ERR_INVALID_PUBLIC_KEY;
1387 break;
1388 case RCC_INVALID_SESSION_KEY:
1389 dwError = ERR_INVALID_SESSION_KEY;
1390 break;
1391 default:
1392 dwError = ERR_INTERNAL_ERROR;
1393 break;
1394 }
1395 delete pResp;
1396 }
1397 else
1398 {
1399 dwError = ERR_REQUEST_TIMEOUT;
1400 }
1401 }
1402 else
1403 {
1404 dwError = ERR_CONNECTION_BROKEN;
1405 }
1406
1407 return dwError;
1408#else
1409 return ERR_NOT_IMPLEMENTED;
1410#endif
1411}
1412
5944946e
VK
1413/**
1414 * Get configuration file from agent
1415 */
967893bb 1416UINT32 AgentConnection::getConfigFile(TCHAR **ppszConfig, UINT32 *pdwSize)
5039dede 1417{
967893bb 1418 UINT32 i, dwRqId, dwResult;
5039dede
AK
1419 CSCPMessage msg(m_nProtocolVersion), *pResponse;
1420#ifdef UNICODE
1421 BYTE *pBuffer;
1422#endif
1423
1424 *ppszConfig = NULL;
1425 *pdwSize = 0;
1426
1427 if (!m_bIsConnected)
1428 return ERR_NOT_CONNECTED;
1429
1430 dwRqId = m_dwRequestId++;
1431
1432 msg.SetCode(CMD_GET_AGENT_CONFIG);
1433 msg.SetId(dwRqId);
1434
7c521895 1435 if (sendMessage(&msg))
5039dede 1436 {
7c521895 1437 pResponse = waitForMessage(CMD_REQUEST_COMPLETED, dwRqId, m_dwCommandTimeout);
5039dede
AK
1438 if (pResponse != NULL)
1439 {
1440 dwResult = pResponse->GetVariableLong(VID_RCC);
1441 if (dwResult == ERR_SUCCESS)
1442 {
1443 *pdwSize = pResponse->GetVariableBinary(VID_CONFIG_FILE, NULL, 0);
1444 *ppszConfig = (TCHAR *)malloc((*pdwSize + 1) * sizeof(TCHAR));
1445#ifdef UNICODE
1446 pBuffer = (BYTE *)malloc(*pdwSize + 1);
1447 pResponse->GetVariableBinary(VID_CONFIG_FILE, pBuffer, *pdwSize);
08b214c6 1448 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, (char *)pBuffer, *pdwSize, *ppszConfig, *pdwSize);
5039dede
AK
1449 free(pBuffer);
1450#else
1451 pResponse->GetVariableBinary(VID_CONFIG_FILE, (BYTE *)(*ppszConfig), *pdwSize);
1452#endif
1453 (*ppszConfig)[*pdwSize] = 0;
1454
1455 // We expect text file, so replace all non-printable characters with spaces
1456 for(i = 0; i < *pdwSize; i++)
cc022855 1457 if (((*ppszConfig)[i] < _T(' ')) &&
5039dede
AK
1458 ((*ppszConfig)[i] != _T('\t')) &&
1459 ((*ppszConfig)[i] != _T('\r')) &&
1460 ((*ppszConfig)[i] != _T('\n')))
1461 (*ppszConfig)[i] = _T(' ');
1462 }
1463 delete pResponse;
1464 }
1465 else
1466 {
1467 dwResult = ERR_REQUEST_TIMEOUT;
1468 }
1469 }
1470 else
1471 {
1472 dwResult = ERR_CONNECTION_BROKEN;
1473 }
1474
1475 return dwResult;
1476}
1477
5944946e
VK
1478/**
1479 * Update configuration file on agent
1480 */
967893bb 1481UINT32 AgentConnection::updateConfigFile(const TCHAR *pszConfig)
5039dede 1482{
967893bb 1483 UINT32 dwRqId, dwResult;
5039dede
AK
1484 CSCPMessage msg(m_nProtocolVersion);
1485#ifdef UNICODE
1486 int nChars;
1487 BYTE *pBuffer;
1488#endif
1489
1490 if (!m_bIsConnected)
1491 return ERR_NOT_CONNECTED;
1492
1493 dwRqId = m_dwRequestId++;
1494
1495 msg.SetCode(CMD_UPDATE_AGENT_CONFIG);
1496 msg.SetId(dwRqId);
1497#ifdef UNICODE
465b3f2d 1498 nChars = (int)_tcslen(pszConfig);
5039dede
AK
1499 pBuffer = (BYTE *)malloc(nChars + 1);
1500 WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK | WC_DEFAULTCHAR,
08b214c6 1501 pszConfig, nChars, (char *)pBuffer, nChars + 1, NULL, NULL);
5039dede
AK
1502 msg.SetVariable(VID_CONFIG_FILE, pBuffer, nChars);
1503 free(pBuffer);
1504#else
967893bb 1505 msg.SetVariable(VID_CONFIG_FILE, (BYTE *)pszConfig, (UINT32)strlen(pszConfig));
5039dede
AK
1506#endif
1507
7c521895 1508 if (sendMessage(&msg))
5039dede 1509 {
7c521895 1510 dwResult = waitForRCC(dwRqId, m_dwCommandTimeout);
5039dede
AK
1511 }
1512 else
1513 {
1514 dwResult = ERR_CONNECTION_BROKEN;
1515 }
1516
1517 return dwResult;
1518}
1519
5944946e
VK
1520/**
1521 * Get routing table from agent
1522 */
4687826e 1523ROUTING_TABLE *AgentConnection::getRoutingTable()
5039dede
AK
1524{
1525 ROUTING_TABLE *pRT = NULL;
967893bb 1526 UINT32 i, dwBits;
5039dede
AK
1527 TCHAR *pChar, *pBuf;
1528
4687826e 1529 if (getList(_T("Net.IP.RoutingTable")) == ERR_SUCCESS)
5039dede
AK
1530 {
1531 pRT = (ROUTING_TABLE *)malloc(sizeof(ROUTING_TABLE));
1532 pRT->iNumEntries = m_dwNumDataLines;
1533 pRT->pRoutes = (ROUTE *)malloc(sizeof(ROUTE) * m_dwNumDataLines);
1534 memset(pRT->pRoutes, 0, sizeof(ROUTE) * m_dwNumDataLines);
1535 for(i = 0; i < m_dwNumDataLines; i++)
1536 {
1537 pBuf = m_ppDataLines[i];
1538
1539 // Destination address and mask
1540 pChar = _tcschr(pBuf, _T(' '));
1541 if (pChar != NULL)
1542 {
1543 TCHAR *pSlash;
1544 static TCHAR defaultMask[] = _T("24");
1545
1546 *pChar = 0;
1547 pSlash = _tcschr(pBuf, _T('/'));
1548 if (pSlash != NULL)
1549 {
1550 *pSlash = 0;
1551 pSlash++;
1552 }
1553 else // Just a paranoia protection, should'n happen if agent working correctly
1554 {
1555 pSlash = defaultMask;
1556 }
1557 pRT->pRoutes[i].dwDestAddr = ntohl(_t_inet_addr(pBuf));
1558 dwBits = _tcstoul(pSlash, NULL, 10);
1559 pRT->pRoutes[i].dwDestMask = (dwBits == 32) ? 0xFFFFFFFF : (~(0xFFFFFFFF >> dwBits));
1560 pBuf = pChar + 1;
1561 }
1562
1563 // Next hop address
1564 pChar = _tcschr(pBuf, _T(' '));
1565 if (pChar != NULL)
1566 {
1567 *pChar = 0;
1568 pRT->pRoutes[i].dwNextHop = ntohl(_t_inet_addr(pBuf));
1569 pBuf = pChar + 1;
1570 }
1571
1572 // Interface index
1573 pChar = _tcschr(pBuf, ' ');
1574 if (pChar != NULL)
1575 {
1576 *pChar = 0;
1577 pRT->pRoutes[i].dwIfIndex = _tcstoul(pBuf, NULL, 10);
1578 pBuf = pChar + 1;
1579 }
1580
1581 // Route type
1582 pRT->pRoutes[i].dwRouteType = _tcstoul(pBuf, NULL, 10);
1583 }
1584
a3050773 1585 lock();
7c521895 1586 destroyResultData();
a3050773 1587 unlock();
5039dede
AK
1588 }
1589
1590 return pRT;
1591}
1592
5944946e
VK
1593/**
1594 * Set proxy information
1595 */
967893bb 1596void AgentConnection::setProxy(UINT32 dwAddr, WORD wPort, int iAuthMethod, const TCHAR *pszSecret)
5039dede
AK
1597{
1598 m_dwProxyAddr = dwAddr;
1599 m_wProxyPort = wPort;
1600 m_iProxyAuth = iAuthMethod;
1601 if (pszSecret != NULL)
1602 {
1603#ifdef UNICODE
cc022855 1604 WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK | WC_DEFAULTCHAR,
5039dede
AK
1605 pszSecret, -1, m_szProxySecret, MAX_SECRET_LENGTH, NULL, NULL);
1606#else
1607 nx_strncpy(m_szProxySecret, pszSecret, MAX_SECRET_LENGTH);
1608#endif
1609 }
1610 else
1611 {
1612 m_szProxySecret[0] = 0;
1613 }
1614 m_bUseProxy = TRUE;
1615}
1616
5944946e
VK
1617/**
1618 * Setup proxy connection
1619 */
967893bb 1620UINT32 AgentConnection::setupProxyConnection()
5039dede
AK
1621{
1622 CSCPMessage msg(m_nProtocolVersion);
967893bb 1623 UINT32 dwRqId;
5039dede
AK
1624
1625 dwRqId = m_dwRequestId++;
1626 msg.SetCode(CMD_SETUP_PROXY_CONNECTION);
1627 msg.SetId(dwRqId);
967893bb 1628 msg.SetVariable(VID_IP_ADDRESS, (UINT32)ntohl(m_dwAddr));
5039dede 1629 msg.SetVariable(VID_AGENT_PORT, m_wPort);
7c521895
VK
1630 if (sendMessage(&msg))
1631 return waitForRCC(dwRqId, 60000); // Wait 60 seconds for remote connect
5039dede
AK
1632 else
1633 return ERR_CONNECTION_BROKEN;
1634}
1635
ef8278f0
VK
1636/**
1637 * Enable trap receiving on connection
1638 */
967893bb 1639UINT32 AgentConnection::enableTraps()
5039dede
AK
1640{
1641 CSCPMessage msg(m_nProtocolVersion);
967893bb 1642 UINT32 dwRqId;
5039dede
AK
1643
1644 dwRqId = m_dwRequestId++;
1645 msg.SetCode(CMD_ENABLE_AGENT_TRAPS);
1646 msg.SetId(dwRqId);
7c521895
VK
1647 if (sendMessage(&msg))
1648 return waitForRCC(dwRqId, m_dwCommandTimeout);
5039dede
AK
1649 else
1650 return ERR_CONNECTION_BROKEN;
1651}
1652
5944946e
VK
1653/**
1654 * Take screenshot from remote system
1655 */
9c786c0f 1656UINT32 AgentConnection::takeScreenshot(const TCHAR *sessionName, BYTE **data, size_t *size)
5944946e
VK
1657{
1658 CSCPMessage msg(m_nProtocolVersion);
1659 UINT32 dwRqId;
1660
1661 dwRqId = m_dwRequestId++;
1662 msg.SetCode(CMD_TAKE_SCREENSHOT);
1663 msg.SetId(dwRqId);
9c786c0f 1664 msg.SetVariable(VID_NAME, sessionName);
5944946e
VK
1665 if (sendMessage(&msg))
1666 {
1667 CSCPMessage *response = waitForMessage(CMD_REQUEST_COMPLETED, dwRqId, m_dwCommandTimeout);
1668 if (response != NULL)
1669 {
1670 UINT32 rcc = response->GetVariableLong(VID_RCC);
1671 if (rcc == ERR_SUCCESS)
1672 {
1673 BYTE *p = response->getBinaryFieldPtr(VID_FILE_DATA, size);
1674 if (p != NULL)
1675 {
1676 *data = (BYTE *)malloc(*size);
1677 memcpy(*data, p, *size);
1678 }
1679 else
1680 {
1681 *data = NULL;
1682 }
1683 }
1684 delete response;
1685 return rcc;
1686 }
1687 else
1688 {
1689 return ERR_REQUEST_TIMEOUT;
1690 }
1691 }
1692 else
1693 {
1694 return ERR_CONNECTION_BROKEN;
1695 }
1696}
1697
cc022855 1698/**
1699 * Send custom request to agent
1700 */
76b4edb5 1701CSCPMessage *AgentConnection::customRequest(CSCPMessage *pRequest, const TCHAR *recvFile, bool append, void (*downloadProgressCallback)(size_t, void *),
1702 void (*fileResendCallback)(CSCP_MESSAGE*, void *), void *cbArg)
5039dede 1703{
967893bb 1704 UINT32 dwRqId, rcc;
5039dede
AK
1705 CSCPMessage *msg = NULL;
1706
1707 dwRqId = m_dwRequestId++;
1708 pRequest->SetId(dwRqId);
1709 if (recvFile != NULL)
1710 {
76b4edb5 1711 rcc = prepareFileDownload(recvFile, dwRqId, append, downloadProgressCallback, fileResendCallback,cbArg);
5039dede
AK
1712 if (rcc != ERR_SUCCESS)
1713 {
1714 // Create fake response message
1715 msg = new CSCPMessage;
1716 msg->SetCode(CMD_REQUEST_COMPLETED);
1717 msg->SetId(dwRqId);
1718 msg->SetVariable(VID_RCC, rcc);
1719 }
1720 }
1721
1722 if (msg == NULL)
1723 {
7c521895 1724 if (sendMessage(pRequest))
5039dede 1725 {
7c521895 1726 msg = waitForMessage(CMD_REQUEST_COMPLETED, dwRqId, m_dwCommandTimeout);
5039dede
AK
1727 if ((msg != NULL) && (recvFile != NULL))
1728 {
1729 if (msg->GetVariableLong(VID_RCC) == ERR_SUCCESS)
1730 {
bb85e341 1731 if (ConditionWait(m_condFileDownload, 1800000)) // 30 min timeout
5039dede 1732 {
bb85e341 1733 if (!m_fileDownloadSucceeded)
5039dede
AK
1734 {
1735 msg->SetVariable(VID_RCC, ERR_IO_FAILURE);
901a5a9b 1736 if (m_deleteFileOnDownloadFailure)
08b214c6 1737 _tremove(recvFile);
5039dede
AK
1738 }
1739 }
1740 else
1741 {
1742 msg->SetVariable(VID_RCC, ERR_REQUEST_TIMEOUT);
1743 }
1744 }
1745 else
1746 {
ef8278f0 1747 if (fileResendCallback != NULL)
76b4edb5 1748 {
1749 close(m_hCurrFile);
1750 m_hCurrFile = -1;
1751 _tremove(recvFile);
1752 }
5039dede
AK
1753 }
1754 }
76b4edb5 1755
5039dede
AK
1756 }
1757 }
1758
1759 return msg;
1760}
1761
76b4edb5 1762/**
ef8278f0 1763 * Prepare for file download
76b4edb5 1764 */
76b4edb5 1765UINT32 AgentConnection::prepareFileDownload(const TCHAR *fileName, UINT32 rqId, bool append, void (*downloadProgressCallback)(size_t, void *),
ef8278f0 1766 void (*fileResendCallback)(CSCP_MESSAGE *, void *), void *cbArg)
5039dede 1767{
ef8278f0 1768 if (fileResendCallback == NULL)
76b4edb5 1769 {
1770 if (m_hCurrFile != -1)
1771 return ERR_RESOURCE_BUSY;
5039dede 1772
76b4edb5 1773 nx_strncpy(m_currentFileName, fileName, MAX_PATH);
1774 ConditionReset(m_condFileDownload);
1775 m_hCurrFile = _topen(fileName, (append ? 0 : (O_CREAT | O_TRUNC)) | O_RDWR | O_BINARY, S_IREAD | S_IWRITE);
1776 if (m_hCurrFile == -1)
1777 {
1778 DbgPrintf(4, _T("AgentConnection::PrepareFileDownload(): cannot open file %s (%s); append=%d rqId=%d"),
1779 fileName, _tcserror(errno), append, rqId);
1780 }
1781 else
1782 {
1783 if (append)
1784 lseek(m_hCurrFile, 0, SEEK_END);
1785 }
1786
1787 m_dwDownloadRequestId = rqId;
1788 m_downloadProgressCallback = downloadProgressCallback;
1789 m_downloadProgressCallbackArg = cbArg;
1790
9630fcd1
AK
1791 m_sendToClientMessageCallback = NULL;
1792
76b4edb5 1793 return (m_hCurrFile != -1) ? ERR_SUCCESS : ERR_FILE_OPEN_ERROR;
1794 }
1795 else
1796 {
1797 ConditionReset(m_condFileDownload);
76b4edb5 1798
1799 m_dwDownloadRequestId = rqId;
1800 m_downloadProgressCallback = downloadProgressCallback;
1801 m_downloadProgressCallbackArg = cbArg;
1802
9630fcd1
AK
1803 m_sendToClientMessageCallback = fileResendCallback;
1804
76b4edb5 1805 return ERR_SUCCESS;
1806 }
5039dede
AK
1807}
1808
76b4edb5 1809/**
1810 * File upload completion handler
1811 */
f480bdd4 1812void AgentConnection::onFileDownload(BOOL success)
5039dede 1813{
76b4edb5 1814 if (!success && m_deleteFileOnDownloadFailure)
901a5a9b 1815 _tremove(m_currentFileName);
bb85e341
VK
1816 m_fileDownloadSucceeded = success;
1817 ConditionSet(m_condFileDownload);
5039dede 1818}
1f385e47 1819
ef8278f0
VK
1820/**
1821 * Enable trap receiving on connection
1822 */
967893bb 1823UINT32 AgentConnection::getPolicyInventory(AgentPolicyInfo **info)
1f385e47
VK
1824{
1825 CSCPMessage msg(m_nProtocolVersion);
967893bb 1826 UINT32 dwRqId, rcc;
1f385e47
VK
1827
1828 *info = NULL;
1829 dwRqId = m_dwRequestId++;
1830 msg.SetCode(CMD_GET_POLICY_INVENTORY);
1831 msg.SetId(dwRqId);
1832 if (sendMessage(&msg))
1833 {
1834 CSCPMessage *response = waitForMessage(CMD_REQUEST_COMPLETED, dwRqId, m_dwCommandTimeout);
1835 if (response != NULL)
1836 {
1837 rcc = response->GetVariableLong(VID_RCC);
1838 if (rcc == ERR_SUCCESS)
1839 *info = new AgentPolicyInfo(response);
1840 delete response;
1841 }
1842 else
1843 {
1844 rcc = ERR_REQUEST_TIMEOUT;
1845 }
1846 }
1847 else
1848 {
1849 rcc = ERR_CONNECTION_BROKEN;
1850 }
1851 return rcc;
1852}
1853
ef8278f0
VK
1854/**
1855 * Uninstall policy by GUID
1856 */
967893bb 1857UINT32 AgentConnection::uninstallPolicy(uuid_t guid)
1f385e47 1858{
967893bb 1859 UINT32 rqId, rcc;
1f385e47
VK
1860 CSCPMessage msg(m_nProtocolVersion);
1861
1862 rqId = generateRequestId();
1863 msg.SetId(rqId);
1864 msg.SetCode(CMD_UNINSTALL_AGENT_POLICY);
1865 msg.SetVariable(VID_GUID, guid, UUID_LENGTH);
1866 if (sendMessage(&msg))
1867 {
1868 rcc = waitForRCC(rqId, m_dwCommandTimeout);
1869 }
1870 else
1871 {
1872 rcc = ERR_CONNECTION_BROKEN;
1873 }
1874 return rcc;
1875}
98abc9f1 1876
86c126f5
VK
1877/**
1878 * Acquire encryption context
1879 */
98abc9f1
VK
1880NXCPEncryptionContext *AgentConnection::acquireEncryptionContext()
1881{
a3050773 1882 lock();
98abc9f1
VK
1883 NXCPEncryptionContext *ctx = m_pCtx;
1884 if (ctx != NULL)
1885 ctx->incRefCount();
a3050773 1886 unlock();
98abc9f1
VK
1887 return ctx;
1888}
86c126f5
VK
1889
1890/**
1891 * Create new agent parameter definition from NXCP message
1892 */
967893bb 1893AgentParameterDefinition::AgentParameterDefinition(CSCPMessage *msg, UINT32 baseId)
86c126f5
VK
1894{
1895 m_name = msg->GetVariableStr(baseId);
1896 m_description = msg->GetVariableStr(baseId + 1);
1897 m_dataType = (int)msg->GetVariableShort(baseId + 2);
1898}
1899
1900/**
1901 * Create new agent parameter definition from another definition object
1902 */
1903AgentParameterDefinition::AgentParameterDefinition(AgentParameterDefinition *src)
1904{
1905 m_name = (src->m_name != NULL) ? _tcsdup(src->m_name) : NULL;
1906 m_description = (src->m_description != NULL) ? _tcsdup(src->m_description) : NULL;
1907 m_dataType = src->m_dataType;
1908}
1909
1910/**
1911 * Destructor for agent parameter definition
1912 */
1913AgentParameterDefinition::~AgentParameterDefinition()
1914{
1915 safe_free(m_name);
1916 safe_free(m_description);
1917}
1918
1919/**
1920 * Fill NXCP message
1921 */
967893bb 1922UINT32 AgentParameterDefinition::fillMessage(CSCPMessage *msg, UINT32 baseId)
86c126f5
VK
1923{
1924 msg->SetVariable(baseId, m_name);
1925 msg->SetVariable(baseId + 1, m_description);
1926 msg->SetVariable(baseId + 2, (WORD)m_dataType);
1927 return 3;
1928}
1929
1930/**
1931 * Create new agent table definition from NXCP message
1932 */
967893bb 1933AgentTableDefinition::AgentTableDefinition(CSCPMessage *msg, UINT32 baseId)
86c126f5
VK
1934{
1935 m_name = msg->GetVariableStr(baseId);
1936 m_description = msg->GetVariableStr(baseId + 2);
1937
1938 TCHAR *instanceColumns = msg->GetVariableStr(baseId + 1);
1939 if (instanceColumns != NULL)
1940 {
1941 m_instanceColumns = new StringList(instanceColumns, _T("|"));
1942 free(instanceColumns);
1943 }
1944 else
1945 {
1946 m_instanceColumns = new StringList;
1947 }
1948
1949 m_columns = new ObjectArray<AgentTableColumnDefinition>(16, 16, true);
1950}
1951
1952/**
1953 * Create new agent table definition from another definition object
1954 */
1955AgentTableDefinition::AgentTableDefinition(AgentTableDefinition *src)
1956{
1957 m_name = (src->m_name != NULL) ? _tcsdup(src->m_name) : NULL;
1958 m_description = (src->m_description != NULL) ? _tcsdup(src->m_description) : NULL;
1959 m_instanceColumns = new StringList(src->m_instanceColumns);
1960 m_columns = new ObjectArray<AgentTableColumnDefinition>(16, 16, true);
1961 for(int i = 0; i < src->m_columns->size(); i++)
1962 {
1963 m_columns->add(new AgentTableColumnDefinition(src->m_columns->get(i)));
1964 }
1965}
1966/**
1967 * Destructor for agent table definition
1968 */
1969AgentTableDefinition::~AgentTableDefinition()
1970{
1971 safe_free(m_name);
1972 safe_free(m_description);
1973 delete m_instanceColumns;
1974 delete m_columns;
1975}
1976
1977/**
1978 * Fill NXCP message
1979 */
967893bb 1980UINT32 AgentTableDefinition::fillMessage(CSCPMessage *msg, UINT32 baseId)
86c126f5
VK
1981{
1982 msg->SetVariable(baseId + 1, m_name);
1983 msg->SetVariable(baseId + 2, m_description);
1984
1985 TCHAR *instanceColumns = m_instanceColumns->join(_T("|"));
1986 msg->SetVariable(baseId + 3, instanceColumns);
1987 free(instanceColumns);
1988
967893bb 1989 UINT32 varId = baseId + 4;
86c126f5
VK
1990 for(int i = 0; i < m_columns->size(); i++)
1991 {
1992 msg->SetVariable(varId++, m_columns->get(i)->m_name);
1993 msg->SetVariable(varId++, (WORD)m_columns->get(i)->m_dataType);
1994 }
1995
1996 msg->SetVariable(baseId, varId - baseId);
1997 return varId - baseId;
1998}