imported svn:keywords properties
[public/netxms.git] / src / server / libnxsrv / agent.cpp
CommitLineData
8e76f8aa 1/* $Id$ */
f77084bb
VK
2/*
3** NetXMS - Network Management System
4** Server Library
f1e6a179 5** Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Victor Kirhenshtein
f77084bb
VK
6**
7** This program is free software; you can redistribute it and/or modify
8** it under the terms of the GNU General Public License as published by
9** the Free Software Foundation; either version 2 of the License, or
10** (at your option) any later version.
11**
12** This program is distributed in the hope that it will be useful,
13** but WITHOUT ANY WARRANTY; without even the implied warranty of
14** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15** GNU General Public License for more details.
16**
17** You should have received a copy of the GNU General Public License
18** along with this program; if not, write to the Free Software
19** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20**
439c93c0 21** File: agent.cpp
f77084bb
VK
22**
23**/
24
25#include "libnxsrv.h"
1ba9a162 26#include <stdarg.h>
f77084bb
VK
27
28
29//
30// Constants
31//
32
33#define RECEIVER_BUFFER_SIZE 262144
34
35
f9a4ab9a
VK
36//
37// Static data
38//
39
40#ifdef _WITH_ENCRYPTION
41static int m_iDefaultEncryptionPolicy = ENCRYPTION_ALLOWED;
42#else
43static int m_iDefaultEncryptionPolicy = ENCRYPTION_DISABLED;
44#endif
45
46
47//
48// Set default encryption policy for agent communication
49//
50
51void LIBNXSRV_EXPORTABLE SetAgentDEP(int iPolicy)
52{
53#ifdef _WITH_ENCRYPTION
54 m_iDefaultEncryptionPolicy = iPolicy;
55#endif
56}
57
58
f77084bb
VK
59//
60// Receiver thread starter
61//
62
ccdbbb52 63THREAD_RESULT THREAD_CALL AgentConnection::ReceiverThreadStarter(void *pArg)
f77084bb
VK
64{
65 ((AgentConnection *)pArg)->ReceiverThread();
ccdbbb52 66 return THREAD_OK;
f77084bb
VK
67}
68
69
70//
71// Default constructor for AgentConnection - normally shouldn't be used
72//
73
74AgentConnection::AgentConnection()
75{
76 m_dwAddr = inet_addr("127.0.0.1");
77 m_wPort = AGENT_LISTEN_PORT;
78 m_iAuthMethod = AUTH_NONE;
79 m_szSecret[0] = 0;
80 m_hSocket = -1;
81 m_tLastCommandTime = 0;
82 m_dwNumDataLines = 0;
83 m_ppDataLines = NULL;
84 m_pMsgWaitQueue = new MsgWaitQueue;
d1d0b3be 85 m_dwRequestId = 1;
f77084bb 86 m_dwCommandTimeout = 10000; // Default timeout 10 seconds
1c62be36 87 m_bIsConnected = FALSE;
38e832d6 88 m_mutexDataLock = MutexCreate();
ccdbbb52 89 m_hReceiverThread = INVALID_THREAD_HANDLE;
e44ac467 90 m_pCtx = NULL;
f9a4ab9a 91 m_iEncryptionPolicy = m_iDefaultEncryptionPolicy;
f1448d17 92 m_bUseProxy = FALSE;
08043edf 93 m_dwRecvTimeout = 420000; // 7 minutes
4bd3d6c5 94 m_nProtocolVersion = NXCP_VERSION;
f77084bb
VK
95}
96
97
98//
99// Normal constructor for AgentConnection
100//
101
f1448d17 102AgentConnection::AgentConnection(DWORD dwAddr, WORD wPort,
76154a95 103 int iAuthMethod, const TCHAR *pszSecret)
f77084bb
VK
104{
105 m_dwAddr = dwAddr;
106 m_wPort = wPort;
107 m_iAuthMethod = iAuthMethod;
268774a0
VK
108 if (pszSecret != NULL)
109 {
110#ifdef UNICODE
111 WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK | WC_DEFAULTCHAR,
112 pszSecret, -1, m_szSecret, MAX_SECRET_LENGTH, NULL, NULL);
113#else
c81979bc 114 nx_strncpy(m_szSecret, pszSecret, MAX_SECRET_LENGTH);
268774a0
VK
115#endif
116 }
f77084bb 117 else
268774a0 118 {
f77084bb 119 m_szSecret[0] = 0;
268774a0 120 }
f77084bb
VK
121 m_hSocket = -1;
122 m_tLastCommandTime = 0;
123 m_dwNumDataLines = 0;
124 m_ppDataLines = NULL;
125 m_pMsgWaitQueue = new MsgWaitQueue;
d1d0b3be 126 m_dwRequestId = 1;
f77084bb 127 m_dwCommandTimeout = 10000; // Default timeout 10 seconds
1c62be36 128 m_bIsConnected = FALSE;
38e832d6 129 m_mutexDataLock = MutexCreate();
ccdbbb52 130 m_hReceiverThread = INVALID_THREAD_HANDLE;
e44ac467 131 m_pCtx = NULL;
f9a4ab9a 132 m_iEncryptionPolicy = m_iDefaultEncryptionPolicy;
f1448d17 133 m_bUseProxy = FALSE;
08043edf 134 m_dwRecvTimeout = 420000; // 7 minutes
4bd3d6c5 135 m_nProtocolVersion = NXCP_VERSION;
f77084bb
VK
136}
137
138
139//
140// Destructor
141//
142
143AgentConnection::~AgentConnection()
144{
1a60d114
VK
145 // Disconnect from peer
146 Disconnect();
38e832d6 147
5a8fcfbb
VK
148 // Close socket if active
149 Lock();
ba8681ba 150 if (m_hSocket != -1)
5a8fcfbb 151 {
ba8681ba 152 closesocket(m_hSocket);
5a8fcfbb
VK
153 m_hSocket = -1;
154 }
155 Unlock();
156
157 // Wait for receiver thread termination
158 ThreadJoin(m_hReceiverThread);
38e832d6
VK
159
160 Lock();
f77084bb 161 DestroyResultData();
38e832d6
VK
162 Unlock();
163
f77084bb 164 delete m_pMsgWaitQueue;
e44ac467 165 DestroyEncryptionContext(m_pCtx);
38e832d6
VK
166
167 MutexDestroy(m_mutexDataLock);
f77084bb
VK
168}
169
170
171//
059f6632
VK
172// Print message. This function is virtual and can be overrided in
173// derived classes. Default implementation will print message to stdout.
f77084bb
VK
174//
175
76154a95 176void AgentConnection::PrintMsg(const TCHAR *pszFormat, ...)
f77084bb
VK
177{
178 va_list args;
179
180 va_start(args, pszFormat);
268774a0 181 _vtprintf(pszFormat, args);
f77084bb 182 va_end(args);
268774a0 183 _tprintf(_T("\n"));
f77084bb
VK
184}
185
186
187//
188// Receiver thread
189//
190
191void AgentConnection::ReceiverThread(void)
192{
193 CSCPMessage *pMsg;
194 CSCP_MESSAGE *pRawMsg;
195 CSCP_BUFFER *pMsgBuffer;
e44ac467 196 BYTE *pDecryptionBuffer = NULL;
f77084bb 197 int iErr;
268774a0 198 TCHAR szBuffer[128];
f1e6a179 199 SOCKET nSocket;
f77084bb
VK
200
201 // Initialize raw message receiving function
9d72bde1 202 pMsgBuffer = (CSCP_BUFFER *)malloc(sizeof(CSCP_BUFFER));
4bd3d6c5 203 RecvNXCPMessage(0, NULL, pMsgBuffer, 0, NULL, NULL, 0);
f77084bb
VK
204
205 // Allocate space for raw message
9d72bde1 206 pRawMsg = (CSCP_MESSAGE *)malloc(RECEIVER_BUFFER_SIZE);
e44ac467
VK
207#ifdef _WITH_ENCRYPTION
208 pDecryptionBuffer = (BYTE *)malloc(RECEIVER_BUFFER_SIZE);
209#endif
f77084bb
VK
210
211 // Message receiving loop
212 while(1)
213 {
214 // Receive raw message
f1e6a179
VK
215 Lock();
216 nSocket = m_hSocket;
217 Unlock();
218 if ((iErr = RecvNXCPMessage(nSocket, pRawMsg, pMsgBuffer, RECEIVER_BUFFER_SIZE,
08043edf 219 &m_pCtx, pDecryptionBuffer, m_dwRecvTimeout)) <= 0)
5a8fcfbb 220 {
f77084bb 221 break;
5a8fcfbb 222 }
f77084bb
VK
223
224 // Check if we get too large message
225 if (iErr == 1)
226 {
0212dc5a 227 PrintMsg(_T("Received too large message %s (%d bytes)"),
4bd3d6c5 228 NXCPMessageCodeName(ntohs(pRawMsg->wCode), szBuffer),
f77084bb
VK
229 ntohl(pRawMsg->dwSize));
230 continue;
231 }
232
e44ac467
VK
233 // Check if we are unable to decrypt message
234 if (iErr == 2)
235 {
236 PrintMsg(_T("Unable to decrypt received message"));
237 continue;
238 }
239
08043edf
VK
240 // Check for timeout
241 if (iErr == 3)
242 {
243 PrintMsg(_T("Timed out waiting for message"));
244 break;
245 }
246
f77084bb
VK
247 // Check that actual received packet size is equal to encoded in packet
248 if ((int)ntohl(pRawMsg->dwSize) != iErr)
249 {
268774a0 250 PrintMsg(_T("RecvMsg: Bad packet length [dwSize=%d ActualSize=%d]"), ntohl(pRawMsg->dwSize), iErr);
f77084bb
VK
251 continue; // Bad packet, wait for next
252 }
253
254 // Create message object from raw message
4bd3d6c5 255 pMsg = new CSCPMessage(pRawMsg, m_nProtocolVersion);
f77084bb
VK
256 if (pMsg->GetCode() == CMD_TRAP)
257 {
901c96c7 258 OnTrap(pMsg);
f77084bb
VK
259 delete pMsg;
260 }
261 else
262 {
263 m_pMsgWaitQueue->Put(pMsg);
264 }
265 }
266
1c62be36 267 // Close socket and mark connection as disconnected
0a0bd13b 268 Lock();
ba8681ba
VK
269 if (iErr == 0)
270 shutdown(m_hSocket, SHUT_RDWR);
271 closesocket(m_hSocket);
272 m_hSocket = -1;
e44ac467
VK
273 DestroyEncryptionContext(m_pCtx);
274 m_pCtx = NULL;
ba8681ba 275 m_bIsConnected = FALSE;
966f3ac2 276 Unlock();
1c62be36 277
9d72bde1
VK
278 free(pRawMsg);
279 free(pMsgBuffer);
3332c970
VK
280#ifdef _WITH_ENCRYPTION
281 free(pDecryptionBuffer);
282#endif
f77084bb
VK
283}
284
285
286//
287// Connect to agent
288//
289
1ba3c17a 290BOOL AgentConnection::Connect(RSA *pServerKey, BOOL bVerbose, DWORD *pdwError)
f77084bb
VK
291{
292 struct sockaddr_in sa;
268774a0 293 TCHAR szBuffer[256];
f1448d17 294 BOOL bSuccess = FALSE, bForceEncryption = FALSE, bSecondPass = FALSE;
f9a4ab9a 295 DWORD dwError = 0;
f77084bb 296
1ba3c17a
VK
297 if (pdwError != NULL)
298 *pdwError = ERR_INTERNAL_ERROR;
299
1c62be36 300 // Check if already connected
ba8681ba 301 if (m_bIsConnected)
1c62be36
VK
302 return FALSE;
303
ccdbbb52
VK
304 // Wait for receiver thread from previous connection, if any
305 ThreadJoin(m_hReceiverThread);
306 m_hReceiverThread = INVALID_THREAD_HANDLE;
307
ba8681ba
VK
308 // Check if we need to close existing socket
309 if (m_hSocket != -1)
310 closesocket(m_hSocket);
311
f77084bb
VK
312 // Create socket
313 m_hSocket = socket(AF_INET, SOCK_STREAM, 0);
314 if (m_hSocket == -1)
315 {
268774a0 316 PrintMsg(_T("Call to socket() failed"));
f77084bb
VK
317 goto connect_cleanup;
318 }
319
320 // Fill in address structure
321 memset(&sa, 0, sizeof(sa));
f77084bb 322 sa.sin_family = AF_INET;
f1448d17
VK
323 if (m_bUseProxy)
324 {
325 sa.sin_addr.s_addr = m_dwProxyAddr;
326 sa.sin_port = htons(m_wProxyPort);
327 }
328 else
329 {
330 sa.sin_addr.s_addr = m_dwAddr;
331 sa.sin_port = htons(m_wPort);
332 }
f77084bb
VK
333
334 // Connect to server
335 if (connect(m_hSocket, (struct sockaddr *)&sa, sizeof(sa)) == -1)
336 {
337 if (bVerbose)
f1448d17
VK
338 PrintMsg(_T("Cannot establish connection with agent %s"),
339 IpToStr(ntohl(m_bUseProxy ? m_dwProxyAddr : m_dwAddr), szBuffer));
1ba3c17a 340 dwError = ERR_CONNECT_FAILED;
f77084bb
VK
341 goto connect_cleanup;
342 }
343
4bd3d6c5
VK
344 if (!NXCPGetPeerProtocolVersion(m_hSocket, &m_nProtocolVersion))
345 {
346 dwError = ERR_INTERNAL_ERROR;
347 goto connect_cleanup;
348 }
349
f77084bb 350 // Start receiver thread
ccdbbb52 351 m_hReceiverThread = ThreadCreateEx(ReceiverThreadStarter, 0, this);
f77084bb 352
e44ac467 353 // Setup encryption
f9a4ab9a
VK
354setup_encryption:
355 if ((m_iEncryptionPolicy == ENCRYPTION_PREFERRED) ||
356 (m_iEncryptionPolicy == ENCRYPTION_REQUIRED) ||
357 (bForceEncryption)) // Agent require encryption
e44ac467 358 {
f9a4ab9a
VK
359 if (pServerKey != NULL)
360 {
361 dwError = SetupEncryption(pServerKey);
362 if ((dwError != ERR_SUCCESS) &&
363 ((m_iEncryptionPolicy == ENCRYPTION_REQUIRED) || bForceEncryption))
364 goto connect_cleanup;
365 }
366 else
367 {
368 if ((m_iEncryptionPolicy == ENCRYPTION_REQUIRED) || bForceEncryption)
369 {
370 dwError = ERR_ENCRYPTION_REQUIRED;
371 goto connect_cleanup;
372 }
373 }
e44ac467
VK
374 }
375
f77084bb 376 // Authenticate itself to agent
f1448d17 377 if ((dwError = Authenticate(m_bUseProxy && !bSecondPass)) != ERR_SUCCESS)
f77084bb 378 {
f9a4ab9a
VK
379 if ((dwError == ERR_ENCRYPTION_REQUIRED) &&
380 (m_iEncryptionPolicy != ENCRYPTION_DISABLED))
381 {
382 bForceEncryption = TRUE;
383 goto setup_encryption;
384 }
205acaf4 385 PrintMsg(_T("Authentication to agent %s failed (%s)"), IpToStr(ntohl(m_dwAddr), szBuffer),
d1d0b3be
VK
386 AgentErrorCodeToText(dwError));
387 goto connect_cleanup;
f77084bb
VK
388 }
389
390 // Test connectivity
d1d0b3be 391 if ((dwError = Nop()) != ERR_SUCCESS)
f77084bb 392 {
f9a4ab9a
VK
393 if ((dwError == ERR_ENCRYPTION_REQUIRED) &&
394 (m_iEncryptionPolicy != ENCRYPTION_DISABLED))
395 {
396 bForceEncryption = TRUE;
397 goto setup_encryption;
398 }
205acaf4 399 PrintMsg(_T("Communication with agent %s failed (%s)"), IpToStr(ntohl(m_dwAddr), szBuffer),
d1d0b3be 400 AgentErrorCodeToText(dwError));
f77084bb
VK
401 goto connect_cleanup;
402 }
403
f1448d17
VK
404 if (m_bUseProxy && !bSecondPass)
405 {
406 dwError = SetupProxyConnection();
407 if (dwError != ERR_SUCCESS)
408 goto connect_cleanup;
409 DestroyEncryptionContext(m_pCtx);
410 m_pCtx = NULL;
411 bSecondPass = TRUE;
412 bForceEncryption = FALSE;
413 goto setup_encryption;
414 }
415
f77084bb 416 bSuccess = TRUE;
1ba3c17a 417 dwError = ERR_SUCCESS;
f77084bb
VK
418
419connect_cleanup:
420 if (!bSuccess)
421 {
0a0bd13b 422 Lock();
f77084bb 423 if (m_hSocket != -1)
56684b7a 424 shutdown(m_hSocket, SHUT_RDWR);
0a0bd13b 425 Unlock();
ba8681ba
VK
426 ThreadJoin(m_hReceiverThread);
427 m_hReceiverThread = INVALID_THREAD_HANDLE;
428
0a0bd13b 429 Lock();
ba8681ba 430 if (m_hSocket != -1)
0a0bd13b 431 {
f77084bb 432 closesocket(m_hSocket);
0a0bd13b
VK
433 m_hSocket = -1;
434 }
e44ac467
VK
435
436 DestroyEncryptionContext(m_pCtx);
437 m_pCtx = NULL;
966f3ac2
VK
438
439 Unlock();
f77084bb 440 }
1c62be36 441 m_bIsConnected = bSuccess;
1ba3c17a
VK
442 if (pdwError != NULL)
443 *pdwError = dwError;
f77084bb
VK
444 return bSuccess;
445}
446
447
448//
449// Disconnect from agent
450//
451
452void AgentConnection::Disconnect(void)
453{
1c62be36 454 Lock();
f77084bb
VK
455 if (m_hSocket != -1)
456 {
ba8681ba 457 shutdown(m_hSocket, SHUT_RDWR);
f77084bb
VK
458 }
459 DestroyResultData();
1c62be36
VK
460 m_bIsConnected = FALSE;
461 Unlock();
f77084bb
VK
462}
463
464
465//
466// Destroy command execuion results data
467//
468
469void AgentConnection::DestroyResultData(void)
470{
471 DWORD i;
472
473 if (m_ppDataLines != NULL)
474 {
475 for(i = 0; i < m_dwNumDataLines; i++)
476 if (m_ppDataLines[i] != NULL)
9d72bde1
VK
477 free(m_ppDataLines[i]);
478 free(m_ppDataLines);
f77084bb
VK
479 m_ppDataLines = NULL;
480 }
481 m_dwNumDataLines = 0;
482}
483
484
485//
486// Get interface list from agent
487//
488
489INTERFACE_LIST *AgentConnection::GetInterfaceList(void)
490{
1c62be36 491 INTERFACE_LIST *pIfList = NULL;
66485623 492 DWORD i, dwBits;
268774a0 493 TCHAR *pChar, *pBuf;
1c62be36 494
268774a0 495 if (GetList(_T("Net.InterfaceList")) == ERR_SUCCESS)
1c62be36 496 {
9d72bde1 497 pIfList = (INTERFACE_LIST *)malloc(sizeof(INTERFACE_LIST));
1c62be36 498 pIfList->iNumEntries = m_dwNumDataLines;
9d72bde1 499 pIfList->pInterfaces = (INTERFACE_INFO *)malloc(sizeof(INTERFACE_INFO) * m_dwNumDataLines);
1c62be36 500 memset(pIfList->pInterfaces, 0, sizeof(INTERFACE_INFO) * m_dwNumDataLines);
16adae38
VK
501
502 // Parse result set. Each line should have the following format:
503 // index ip_address/mask_bits iftype mac_address name
1c62be36
VK
504 for(i = 0; i < m_dwNumDataLines; i++)
505 {
506 pBuf = m_ppDataLines[i];
507
508 // Index
268774a0 509 pChar = _tcschr(pBuf, ' ');
1c62be36
VK
510 if (pChar != NULL)
511 {
512 *pChar = 0;
268774a0 513 pIfList->pInterfaces[i].dwIndex = _tcstoul(pBuf, NULL, 10);
1c62be36
VK
514 pBuf = pChar + 1;
515 }
516
517 // Address and mask
268774a0 518 pChar = _tcschr(pBuf, _T(' '));
1c62be36
VK
519 if (pChar != NULL)
520 {
268774a0 521 TCHAR *pSlash;
76154a95 522 static TCHAR defaultMask[] = _T("24");
1c62be36
VK
523
524 *pChar = 0;
268774a0 525 pSlash = _tcschr(pBuf, _T('/'));
1c62be36
VK
526 if (pSlash != NULL)
527 {
528 *pSlash = 0;
529 pSlash++;
530 }
531 else // Just a paranoia protection, should'n happen if agent working correctly
532 {
76154a95 533 pSlash = defaultMask;
1c62be36 534 }
205acaf4 535 pIfList->pInterfaces[i].dwIpAddr = ntohl(_t_inet_addr(pBuf));
66485623
VK
536 dwBits = _tcstoul(pSlash, NULL, 10);
537 pIfList->pInterfaces[i].dwIpNetMask = (dwBits == 32) ? 0xFFFFFFFF : (~(0xFFFFFFFF >> dwBits));
1c62be36
VK
538 pBuf = pChar + 1;
539 }
540
541 // Interface type
268774a0 542 pChar = _tcschr(pBuf, ' ');
1c62be36
VK
543 if (pChar != NULL)
544 {
545 *pChar = 0;
205acaf4 546 pIfList->pInterfaces[i].dwType = _tcstoul(pBuf, NULL, 10);
1c62be36 547 pBuf = pChar + 1;
b50f1100
VK
548 }
549
550 // MAC address
551 pChar = _tcschr(pBuf, ' ');
552 if (pChar != NULL)
553 {
554 *pChar = 0;
555 StrToBin(pBuf, pIfList->pInterfaces[i].bMacAddr, MAC_ADDR_LENGTH);
556 pBuf = pChar + 1;
1c62be36
VK
557 }
558
559 // Name
c81979bc 560 nx_strncpy(pIfList->pInterfaces[i].szName, pBuf, MAX_OBJECT_NAME - 1);
1c62be36
VK
561 }
562
9d72bde1 563 Lock();
1c62be36 564 DestroyResultData();
9d72bde1 565 Unlock();
1c62be36
VK
566 }
567
568 return pIfList;
f77084bb
VK
569}
570
571
572//
573// Get parameter value
574//
575
76154a95 576DWORD AgentConnection::GetParameter(const TCHAR *pszParam, DWORD dwBufSize, TCHAR *pszBuffer)
f77084bb 577{
4bd3d6c5 578 CSCPMessage msg(m_nProtocolVersion), *pResponse;
f77084bb
VK
579 DWORD dwRqId, dwRetCode;
580
1c62be36 581 if (m_bIsConnected)
f77084bb 582 {
1c62be36
VK
583 dwRqId = m_dwRequestId++;
584 msg.SetCode(CMD_GET_PARAMETER);
585 msg.SetId(dwRqId);
586 msg.SetVariable(VID_PARAMETER, pszParam);
587 if (SendMessage(&msg))
f77084bb 588 {
1a17feb0
VK
589 pResponse = WaitForMessage(CMD_REQUEST_COMPLETED, dwRqId, m_dwCommandTimeout);
590 if (pResponse != NULL)
1c62be36 591 {
1a17feb0 592 dwRetCode = pResponse->GetVariableLong(VID_RCC);
1c62be36 593 if (dwRetCode == ERR_SUCCESS)
1a17feb0
VK
594 pResponse->GetVariableStr(VID_VALUE, pszBuffer, dwBufSize);
595 delete pResponse;
1c62be36
VK
596 }
597 else
598 {
599 dwRetCode = ERR_REQUEST_TIMEOUT;
600 }
f77084bb
VK
601 }
602 else
603 {
1c62be36 604 dwRetCode = ERR_CONNECTION_BROKEN;
f77084bb
VK
605 }
606 }
607 else
608 {
1c62be36 609 dwRetCode = ERR_NOT_CONNECTED;
f77084bb
VK
610 }
611
612 return dwRetCode;
613}
614
615
616//
617// Get ARP cache
618//
619
620ARP_CACHE *AgentConnection::GetArpCache(void)
621{
1c62be36 622 ARP_CACHE *pArpCache = NULL;
268774a0 623 TCHAR szByte[4], *pBuf, *pChar;
1c62be36
VK
624 DWORD i, j;
625
268774a0 626 if (GetList(_T("Net.ArpCache")) == ERR_SUCCESS)
1c62be36
VK
627 {
628 // Create empty structure
9d72bde1 629 pArpCache = (ARP_CACHE *)malloc(sizeof(ARP_CACHE));
1c62be36 630 pArpCache->dwNumEntries = m_dwNumDataLines;
9d72bde1 631 pArpCache->pEntries = (ARP_ENTRY *)malloc(sizeof(ARP_ENTRY) * m_dwNumDataLines);
1c62be36
VK
632 memset(pArpCache->pEntries, 0, sizeof(ARP_ENTRY) * m_dwNumDataLines);
633
634 szByte[2] = 0;
635
636 // Parse data lines
0e33e56e 637 // Each line has form of XXXXXXXXXXXX a.b.c.d n
1c62be36 638 // where XXXXXXXXXXXX is a MAC address (12 hexadecimal digits)
0e33e56e
VK
639 // a.b.c.d is an IP address in decimal dotted notation
640 // n is an interface index
1c62be36
VK
641 for(i = 0; i < m_dwNumDataLines; i++)
642 {
643 pBuf = m_ppDataLines[i];
268774a0 644 if (_tcslen(pBuf) < 20) // Invalid line
1c62be36
VK
645 continue;
646
647 // MAC address
648 for(j = 0; j < 6; j++)
649 {
268774a0
VK
650 memcpy(szByte, pBuf, sizeof(TCHAR) * 2);
651 pArpCache->pEntries[i].bMacAddr[j] = (BYTE)_tcstol(szByte, NULL, 16);
1c62be36
VK
652 pBuf+=2;
653 }
654
655 // IP address
656 while(*pBuf == ' ')
657 pBuf++;
268774a0 658 pChar = _tcschr(pBuf, _T(' '));
1c62be36
VK
659 if (pChar != NULL)
660 *pChar = 0;
205acaf4 661 pArpCache->pEntries[i].dwIpAddr = ntohl(_t_inet_addr(pBuf));
1c62be36
VK
662
663 // Interface index
664 if (pChar != NULL)
268774a0 665 pArpCache->pEntries[i].dwIndex = _tcstoul(pChar + 1, NULL, 10);
1c62be36
VK
666 }
667
8be7d446 668 Lock();
1c62be36 669 DestroyResultData();
8be7d446 670 Unlock();
1c62be36
VK
671 }
672 return pArpCache;
f77084bb
VK
673}
674
675
676//
677// Send dummy command to agent (can be used for keepalive)
678//
679
680DWORD AgentConnection::Nop(void)
681{
4bd3d6c5 682 CSCPMessage msg(m_nProtocolVersion);
f77084bb
VK
683 DWORD dwRqId;
684
685 dwRqId = m_dwRequestId++;
686 msg.SetCode(CMD_KEEPALIVE);
687 msg.SetId(dwRqId);
688 if (SendMessage(&msg))
689 return WaitForRCC(dwRqId, m_dwCommandTimeout);
690 else
691 return ERR_CONNECTION_BROKEN;
692}
693
694
695//
696// Wait for request completion code
697//
698
699DWORD AgentConnection::WaitForRCC(DWORD dwRqId, DWORD dwTimeOut)
700{
701 CSCPMessage *pMsg;
702 DWORD dwRetCode;
703
704 pMsg = m_pMsgWaitQueue->WaitForMessage(CMD_REQUEST_COMPLETED, dwRqId, dwTimeOut);
705 if (pMsg != NULL)
706 {
707 dwRetCode = pMsg->GetVariableLong(VID_RCC);
708 delete pMsg;
709 }
710 else
711 {
712 dwRetCode = ERR_REQUEST_TIMEOUT;
713 }
714 return dwRetCode;
715}
716
717
718//
719// Send message to agent
720//
721
722BOOL AgentConnection::SendMessage(CSCPMessage *pMsg)
723{
724 CSCP_MESSAGE *pRawMsg;
e44ac467 725 CSCP_ENCRYPTED_MESSAGE *pEnMsg;
f77084bb
VK
726 BOOL bResult;
727
728 pRawMsg = pMsg->CreateMessage();
e44ac467
VK
729 if (m_pCtx != NULL)
730 {
731 pEnMsg = CSCPEncryptMessage(m_pCtx, pRawMsg);
732 if (pEnMsg != NULL)
733 {
734 bResult = (SendEx(m_hSocket, (char *)pEnMsg, ntohl(pEnMsg->dwSize), 0) == (int)ntohl(pEnMsg->dwSize));
735 free(pEnMsg);
736 }
737 else
738 {
739 bResult = FALSE;
740 }
741 }
742 else
743 {
744 bResult = (SendEx(m_hSocket, (char *)pRawMsg, ntohl(pRawMsg->dwSize), 0) == (int)ntohl(pRawMsg->dwSize));
745 }
9d72bde1 746 free(pRawMsg);
f77084bb
VK
747 return bResult;
748}
901c96c7
VK
749
750
751//
752// Trap handler. Should be overriden in derived classes to implement
753// actual trap processing. Default implementation do nothing.
754//
755
756void AgentConnection::OnTrap(CSCPMessage *pMsg)
757{
758}
759
760
761//
762// Get list of values
763//
764
76154a95 765DWORD AgentConnection::GetList(const TCHAR *pszParam)
901c96c7 766{
4bd3d6c5 767 CSCPMessage msg(m_nProtocolVersion), *pResponse;
901c96c7
VK
768 DWORD i, dwRqId, dwRetCode;
769
1c62be36 770 if (m_bIsConnected)
901c96c7 771 {
1c62be36
VK
772 DestroyResultData();
773 dwRqId = m_dwRequestId++;
774 msg.SetCode(CMD_GET_LIST);
775 msg.SetId(dwRqId);
776 msg.SetVariable(VID_PARAMETER, pszParam);
777 if (SendMessage(&msg))
901c96c7 778 {
1a17feb0
VK
779 pResponse = WaitForMessage(CMD_REQUEST_COMPLETED, dwRqId, m_dwCommandTimeout);
780 if (pResponse != NULL)
1c62be36 781 {
1a17feb0 782 dwRetCode = pResponse->GetVariableLong(VID_RCC);
1c62be36
VK
783 if (dwRetCode == ERR_SUCCESS)
784 {
1a17feb0 785 m_dwNumDataLines = pResponse->GetVariableLong(VID_NUM_STRINGS);
268774a0 786 m_ppDataLines = (TCHAR **)malloc(sizeof(TCHAR *) * m_dwNumDataLines);
1c62be36 787 for(i = 0; i < m_dwNumDataLines; i++)
1a17feb0 788 m_ppDataLines[i] = pResponse->GetVariableStr(VID_ENUM_VALUE_BASE + i);
1c62be36 789 }
1a17feb0 790 delete pResponse;
1c62be36
VK
791 }
792 else
901c96c7 793 {
1c62be36 794 dwRetCode = ERR_REQUEST_TIMEOUT;
901c96c7 795 }
901c96c7
VK
796 }
797 else
798 {
1c62be36 799 dwRetCode = ERR_CONNECTION_BROKEN;
901c96c7
VK
800 }
801 }
802 else
803 {
1c62be36 804 dwRetCode = ERR_NOT_CONNECTED;
901c96c7
VK
805 }
806
807 return dwRetCode;
808}
d1d0b3be
VK
809
810
811//
812// Authenticate to agent
813//
814
f1448d17 815DWORD AgentConnection::Authenticate(BOOL bProxyData)
d1d0b3be 816{
4bd3d6c5 817 CSCPMessage msg(m_nProtocolVersion);
d1d0b3be
VK
818 DWORD dwRqId;
819 BYTE hash[32];
f1448d17
VK
820 int iAuthMethod = bProxyData ? m_iProxyAuth : m_iAuthMethod;
821 char *pszSecret = bProxyData ? m_szProxySecret : m_szSecret;
268774a0
VK
822#ifdef UNICODE
823 WCHAR szBuffer[MAX_SECRET_LENGTH];
824#endif
d1d0b3be 825
f1448d17 826 if (iAuthMethod == AUTH_NONE)
d1d0b3be
VK
827 return ERR_SUCCESS; // No authentication required
828
829 dwRqId = m_dwRequestId++;
830 msg.SetCode(CMD_AUTHENTICATE);
831 msg.SetId(dwRqId);
f1448d17
VK
832 msg.SetVariable(VID_AUTH_METHOD, (WORD)iAuthMethod);
833 switch(iAuthMethod)
d1d0b3be
VK
834 {
835 case AUTH_PLAINTEXT:
268774a0 836#ifdef UNICODE
f1448d17 837 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pszSecret, -1, szBuffer, MAX_SECRET_LENGTH);
268774a0
VK
838 msg.SetVariable(VID_SHARED_SECRET, szBuffer);
839#else
f1448d17 840 msg.SetVariable(VID_SHARED_SECRET, pszSecret);
268774a0 841#endif
d1d0b3be
VK
842 break;
843 case AUTH_MD5_HASH:
f2d3bd5f 844 CalculateMD5Hash((BYTE *)pszSecret, (int)strlen(pszSecret), hash);
d1d0b3be
VK
845 msg.SetVariable(VID_SHARED_SECRET, hash, MD5_DIGEST_SIZE);
846 break;
847 case AUTH_SHA1_HASH:
f2d3bd5f 848 CalculateSHA1Hash((BYTE *)pszSecret, (int)strlen(pszSecret), hash);
d1d0b3be
VK
849 msg.SetVariable(VID_SHARED_SECRET, hash, SHA1_DIGEST_SIZE);
850 break;
851 default:
852 break;
853 }
854 if (SendMessage(&msg))
855 return WaitForRCC(dwRqId, m_dwCommandTimeout);
856 else
857 return ERR_CONNECTION_BROKEN;
858}
3c774461
VK
859
860
861//
862// Execute action on agent
863//
864
a765d97c 865DWORD AgentConnection::ExecAction(const TCHAR *pszAction, int argc, TCHAR **argv)
3c774461 866{
4bd3d6c5 867 CSCPMessage msg(m_nProtocolVersion);
3c774461
VK
868 DWORD dwRqId;
869 int i;
870
1c62be36
VK
871 if (!m_bIsConnected)
872 return ERR_NOT_CONNECTED;
873
3c774461
VK
874 dwRqId = m_dwRequestId++;
875 msg.SetCode(CMD_ACTION);
876 msg.SetId(dwRqId);
877 msg.SetVariable(VID_ACTION_NAME, pszAction);
878 msg.SetVariable(VID_NUM_ARGS, (DWORD)argc);
879 for(i = 0; i < argc; i++)
880 msg.SetVariable(VID_ACTION_ARG_BASE + i, argv[i]);
881
882 if (SendMessage(&msg))
883 return WaitForRCC(dwRqId, m_dwCommandTimeout);
884 else
885 return ERR_CONNECTION_BROKEN;
886}
d096bcdd
VK
887
888
889//
890// Upload file to agent
891//
892
a765d97c 893DWORD AgentConnection::UploadFile(const TCHAR *pszFile)
d096bcdd
VK
894{
895 DWORD dwRqId, dwResult;
4bd3d6c5 896 CSCPMessage msg(m_nProtocolVersion);
d096bcdd
VK
897 int i;
898
899 if (!m_bIsConnected)
900 return ERR_NOT_CONNECTED;
901
902 dwRqId = m_dwRequestId++;
903
904 msg.SetCode(CMD_TRANSFER_FILE);
905 msg.SetId(dwRqId);
f2d3bd5f 906 for(i = (int)_tcslen(pszFile) - 1;
d096bcdd
VK
907 (i >= 0) && (pszFile[i] != '\\') && (pszFile[i] != '/'); i--);
908 msg.SetVariable(VID_FILE_NAME, &pszFile[i + 1]);
909
910 if (SendMessage(&msg))
911 {
912 dwResult = WaitForRCC(dwRqId, m_dwCommandTimeout);
913 }
914 else
915 {
916 dwResult = ERR_CONNECTION_BROKEN;
917 }
918
919 if (dwResult == ERR_SUCCESS)
920 {
4bd3d6c5 921 if (SendFileOverNXCP(m_hSocket, dwRqId, pszFile, m_pCtx))
d096bcdd
VK
922 dwResult = WaitForRCC(dwRqId, m_dwCommandTimeout);
923 else
924 dwResult = ERR_IO_FAILURE;
925 }
926
927 return dwResult;
928}
e925a5fc
VK
929
930
931//
932// Send upgrade command
933//
934
a765d97c 935DWORD AgentConnection::StartUpgrade(const TCHAR *pszPkgName)
e925a5fc
VK
936{
937 DWORD dwRqId, dwResult;
4bd3d6c5 938 CSCPMessage msg(m_nProtocolVersion);
e925a5fc
VK
939 int i;
940
941 if (!m_bIsConnected)
942 return ERR_NOT_CONNECTED;
943
944 dwRqId = m_dwRequestId++;
945
946 msg.SetCode(CMD_UPGRADE_AGENT);
947 msg.SetId(dwRqId);
f2d3bd5f 948 for(i = (int)_tcslen(pszPkgName) - 1;
e925a5fc
VK
949 (i >= 0) && (pszPkgName[i] != '\\') && (pszPkgName[i] != '/'); i--);
950 msg.SetVariable(VID_FILE_NAME, &pszPkgName[i + 1]);
951
952 if (SendMessage(&msg))
953 {
954 dwResult = WaitForRCC(dwRqId, m_dwCommandTimeout);
955 }
956 else
957 {
958 dwResult = ERR_CONNECTION_BROKEN;
959 }
960
961 return dwResult;
962}
3f0ca036
VK
963
964
965//
966// Check status of network service via agent
967//
968
969DWORD AgentConnection::CheckNetworkService(DWORD *pdwStatus, DWORD dwIpAddr, int iServiceType,
970 WORD wPort, WORD wProto,
a765d97c 971 const TCHAR *pszRequest, const TCHAR *pszResponse)
3f0ca036
VK
972{
973 DWORD dwRqId, dwResult;
4bd3d6c5 974 CSCPMessage msg(m_nProtocolVersion), *pResponse;
3f0ca036
VK
975 static WORD m_wDefaultPort[] = { 7, 22, 110, 25, 21, 80 };
976
977 if (!m_bIsConnected)
978 return ERR_NOT_CONNECTED;
979
980 dwRqId = m_dwRequestId++;
981
982 msg.SetCode(CMD_CHECK_NETWORK_SERVICE);
983 msg.SetId(dwRqId);
984 msg.SetVariable(VID_IP_ADDRESS, dwIpAddr);
985 msg.SetVariable(VID_SERVICE_TYPE, (WORD)iServiceType);
986 msg.SetVariable(VID_IP_PORT,
987 (wPort != 0) ? wPort :
25376fc7 988 m_wDefaultPort[((iServiceType >= NETSRV_CUSTOM) &&
3f0ca036 989 (iServiceType <= NETSRV_HTTP)) ? iServiceType : 0]);
25376fc7 990 msg.SetVariable(VID_IP_PROTO, (wProto != 0) ? wProto : (WORD)IPPROTO_TCP);
3f0ca036 991 msg.SetVariable(VID_SERVICE_REQUEST, pszRequest);
1a17feb0 992 msg.SetVariable(VID_SERVICE_RESPONSE, pszResponse);
3f0ca036
VK
993
994 if (SendMessage(&msg))
995 {
996 // Wait up to 90 seconds for results
1a17feb0
VK
997 pResponse = WaitForMessage(CMD_REQUEST_COMPLETED, dwRqId, 90000);
998 if (pResponse != NULL)
3f0ca036 999 {
1a17feb0 1000 dwResult = pResponse->GetVariableLong(VID_RCC);
3f0ca036
VK
1001 if (dwResult == ERR_SUCCESS)
1002 {
1a17feb0 1003 *pdwStatus = pResponse->GetVariableLong(VID_SERVICE_STATUS);
3f0ca036 1004 }
1a17feb0 1005 delete pResponse;
3f0ca036
VK
1006 }
1007 else
1008 {
1009 dwResult = ERR_REQUEST_TIMEOUT;
1010 }
1011 }
1012 else
1013 {
1014 dwResult = ERR_CONNECTION_BROKEN;
1015 }
1016
1017 return dwResult;
1018}
125c0e81
VK
1019
1020
1021//
1022// Get list of supported parameters from subagent
1023//
1024
1025DWORD AgentConnection::GetSupportedParameters(DWORD *pdwNumParams, NXC_AGENT_PARAM **ppParamList)
1026{
1027 DWORD i, dwId, dwRqId, dwResult;
4bd3d6c5 1028 CSCPMessage msg(m_nProtocolVersion), *pResponse;
125c0e81 1029
125c0e81
VK
1030 *pdwNumParams = 0;
1031 *ppParamList = NULL;
1032
cb27dff1
VK
1033 if (!m_bIsConnected)
1034 return ERR_NOT_CONNECTED;
1035
125c0e81
VK
1036 dwRqId = m_dwRequestId++;
1037
1038 msg.SetCode(CMD_GET_PARAMETER_LIST);
1039 msg.SetId(dwRqId);
1040
1041 if (SendMessage(&msg))
1042 {
1a17feb0
VK
1043 pResponse = WaitForMessage(CMD_REQUEST_COMPLETED, dwRqId, m_dwCommandTimeout);
1044 if (pResponse != NULL)
125c0e81 1045 {
1a17feb0 1046 dwResult = pResponse->GetVariableLong(VID_RCC);
125c0e81
VK
1047 if (dwResult == ERR_SUCCESS)
1048 {
1a17feb0 1049 *pdwNumParams = pResponse->GetVariableLong(VID_NUM_PARAMETERS);
125c0e81
VK
1050 *ppParamList = (NXC_AGENT_PARAM *)malloc(sizeof(NXC_AGENT_PARAM) * *pdwNumParams);
1051 for(i = 0, dwId = VID_PARAM_LIST_BASE; i < *pdwNumParams; i++)
1052 {
1a17feb0
VK
1053 pResponse->GetVariableStr(dwId++, (*ppParamList)[i].szName, MAX_PARAM_NAME);
1054 pResponse->GetVariableStr(dwId++, (*ppParamList)[i].szDescription, MAX_DB_STRING);
1055 (*ppParamList)[i].iDataType = (int)pResponse->GetVariableShort(dwId++);
125c0e81
VK
1056 }
1057 }
1a17feb0 1058 delete pResponse;
125c0e81
VK
1059 }
1060 else
1061 {
1062 dwResult = ERR_REQUEST_TIMEOUT;
1063 }
1064 }
1065 else
1066 {
1067 dwResult = ERR_CONNECTION_BROKEN;
1068 }
1069
1070 return dwResult;
1071}
e44ac467
VK
1072
1073
1074//
1075// Setup encryption
1076//
1077
1078DWORD AgentConnection::SetupEncryption(RSA *pServerKey)
1079{
1080#ifdef _WITH_ENCRYPTION
4bd3d6c5 1081 CSCPMessage msg(m_nProtocolVersion), *pResp;
e44ac467
VK
1082 DWORD dwRqId, dwError, dwResult;
1083
1084 dwRqId = m_dwRequestId++;
1085
1086 PrepareKeyRequestMsg(&msg, pServerKey);
1087 msg.SetId(dwRqId);
1088 if (SendMessage(&msg))
1089 {
1090 pResp = WaitForMessage(CMD_SESSION_KEY, dwRqId, m_dwCommandTimeout);
1091 if (pResp != NULL)
1092 {
4bd3d6c5 1093 dwResult = SetupEncryptionContext(pResp, &m_pCtx, NULL, pServerKey, m_nProtocolVersion);
e44ac467
VK
1094 switch(dwResult)
1095 {
1096 case RCC_SUCCESS:
1097 dwError = ERR_SUCCESS;
1098 break;
1099 case RCC_NO_CIPHERS:
1100 dwError = ERR_NO_CIPHERS;
1101 break;
1102 case RCC_INVALID_PUBLIC_KEY:
1103 dwError = ERR_INVALID_PUBLIC_KEY;
1104 break;
1105 case RCC_INVALID_SESSION_KEY:
1106 dwError = ERR_INVALID_SESSION_KEY;
1107 break;
1108 default:
1109 dwError = ERR_INTERNAL_ERROR;
1110 break;
1111 }
cb1b586e 1112 delete pResp;
e44ac467
VK
1113 }
1114 else
1115 {
1116 dwError = ERR_REQUEST_TIMEOUT;
1117 }
1118 }
1119 else
1120 {
1121 dwError = ERR_CONNECTION_BROKEN;
1122 }
1123
1124 return dwError;
1125#else
1126 return ERR_NOT_IMPLEMENTED;
1127#endif
1128}
cb27dff1
VK
1129
1130
1131//
1132// Get configuration file from agent
1133//
1134
1135DWORD AgentConnection::GetConfigFile(TCHAR **ppszConfig, DWORD *pdwSize)
1136{
1137 DWORD i, dwRqId, dwResult;
4bd3d6c5 1138 CSCPMessage msg(m_nProtocolVersion), *pResponse;
cb27dff1
VK
1139#ifdef UNICODE
1140 BYTE *pBuffer;
1141#endif
1142
1143 *ppszConfig = NULL;
1144 *pdwSize = 0;
1145
1146 if (!m_bIsConnected)
1147 return ERR_NOT_CONNECTED;
1148
1149 dwRqId = m_dwRequestId++;
1150
1151 msg.SetCode(CMD_GET_AGENT_CONFIG);
1152 msg.SetId(dwRqId);
1153
1154 if (SendMessage(&msg))
1155 {
1a17feb0
VK
1156 pResponse = WaitForMessage(CMD_REQUEST_COMPLETED, dwRqId, m_dwCommandTimeout);
1157 if (pResponse != NULL)
cb27dff1 1158 {
1a17feb0 1159 dwResult = pResponse->GetVariableLong(VID_RCC);
cb27dff1
VK
1160 if (dwResult == ERR_SUCCESS)
1161 {
1a17feb0 1162 *pdwSize = pResponse->GetVariableBinary(VID_CONFIG_FILE, NULL, 0);
cb27dff1
VK
1163 *ppszConfig = (TCHAR *)malloc((*pdwSize + 1) * sizeof(TCHAR));
1164#ifdef UNICODE
1165 pBuffer = (BYTE *)malloc(*pdwSize + 1);
1a17feb0 1166 pResponse->GetVariableBinary(VID_CONFIG_FILE, pBuffer, *pdwSize);
cb27dff1
VK
1167 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pBuffer, *pdwSize, *ppszConfig, *pdwSize);
1168 free(pBuffer);
1169#else
1a17feb0 1170 pResponse->GetVariableBinary(VID_CONFIG_FILE, (BYTE *)(*ppszConfig), *pdwSize);
cb27dff1
VK
1171#endif
1172 (*ppszConfig)[*pdwSize] = 0;
1173
1174 // We expect text file, so replace all non-printable characters with spaces
1175 for(i = 0; i < *pdwSize; i++)
1176 if (((*ppszConfig)[i] < _T(' ')) &&
1177 ((*ppszConfig)[i] != _T('\t')) &&
1178 ((*ppszConfig)[i] != _T('\r')) &&
1179 ((*ppszConfig)[i] != _T('\n')))
1180 (*ppszConfig)[i] = _T(' ');
1181 }
1a17feb0 1182 delete pResponse;
cb27dff1
VK
1183 }
1184 else
1185 {
1186 dwResult = ERR_REQUEST_TIMEOUT;
1187 }
1188 }
3c2c7839
VK
1189 else
1190 {
1191 dwResult = ERR_CONNECTION_BROKEN;
1192 }
1193
1194 return dwResult;
1195}
1196
1197
1198//
1199// Get configuration file from agent
1200//
1201
a765d97c 1202DWORD AgentConnection::UpdateConfigFile(const TCHAR *pszConfig)
3c2c7839
VK
1203{
1204 DWORD dwRqId, dwResult;
4bd3d6c5 1205 CSCPMessage msg(m_nProtocolVersion);
3c2c7839
VK
1206#ifdef UNICODE
1207 int nChars;
1208 BYTE *pBuffer;
1209#endif
1210
1211 if (!m_bIsConnected)
1212 return ERR_NOT_CONNECTED;
1213
1214 dwRqId = m_dwRequestId++;
1215
1216 msg.SetCode(CMD_UPDATE_AGENT_CONFIG);
1217 msg.SetId(dwRqId);
1218#ifdef UNICODE
1219 nChars = _tcslen(pszConfig);
1220 pBuffer = (BYTE *)malloc(nChars + 1);
1221 WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK | WC_DEFAULTCHAR,
1222 pszConfig, nChars, pBuffer, nChars + 1, NULL, NULL);
1223 msg.SetVariable(VID_CONFIG_FILE, pBuffer, nChars);
1224 free(pBuffer);
1225#else
f2d3bd5f 1226 msg.SetVariable(VID_CONFIG_FILE, (BYTE *)pszConfig, (DWORD)strlen(pszConfig));
3c2c7839
VK
1227#endif
1228
1229 if (SendMessage(&msg))
1230 {
1231 dwResult = WaitForRCC(dwRqId, m_dwCommandTimeout);
1232 }
cb27dff1
VK
1233 else
1234 {
1235 dwResult = ERR_CONNECTION_BROKEN;
1236 }
1237
1238 return dwResult;
1239}
6a4f307b
VK
1240
1241
1242//
1243// Get routing table from agent
1244//
1245
1246ROUTING_TABLE *AgentConnection::GetRoutingTable(void)
1247{
1248 ROUTING_TABLE *pRT = NULL;
66485623 1249 DWORD i, dwBits;
6a4f307b
VK
1250 TCHAR *pChar, *pBuf;
1251
1252 if (GetList(_T("Net.IP.RoutingTable")) == ERR_SUCCESS)
1253 {
1254 pRT = (ROUTING_TABLE *)malloc(sizeof(ROUTING_TABLE));
1255 pRT->iNumEntries = m_dwNumDataLines;
1256 pRT->pRoutes = (ROUTE *)malloc(sizeof(ROUTE) * m_dwNumDataLines);
1257 memset(pRT->pRoutes, 0, sizeof(ROUTE) * m_dwNumDataLines);
1258 for(i = 0; i < m_dwNumDataLines; i++)
1259 {
1260 pBuf = m_ppDataLines[i];
1261
1262 // Destination address and mask
1263 pChar = _tcschr(pBuf, _T(' '));
1264 if (pChar != NULL)
1265 {
1266 TCHAR *pSlash;
76154a95 1267 static TCHAR defaultMask[] = _T("24");
6a4f307b
VK
1268
1269 *pChar = 0;
1270 pSlash = _tcschr(pBuf, _T('/'));
1271 if (pSlash != NULL)
1272 {
1273 *pSlash = 0;
1274 pSlash++;
1275 }
1276 else // Just a paranoia protection, should'n happen if agent working correctly
1277 {
76154a95 1278 pSlash = defaultMask;
6a4f307b
VK
1279 }
1280 pRT->pRoutes[i].dwDestAddr = ntohl(_t_inet_addr(pBuf));
66485623
VK
1281 dwBits = _tcstoul(pSlash, NULL, 10);
1282 pRT->pRoutes[i].dwDestMask = (dwBits == 32) ? 0xFFFFFFFF : (~(0xFFFFFFFF >> dwBits));
6a4f307b
VK
1283 pBuf = pChar + 1;
1284 }
1285
1286 // Next hop address
1287 pChar = _tcschr(pBuf, _T(' '));
1288 if (pChar != NULL)
1289 {
1290 *pChar = 0;
1291 pRT->pRoutes[i].dwNextHop = ntohl(_t_inet_addr(pBuf));
1292 pBuf = pChar + 1;
1293 }
1294
1295 // Interface index
1296 pChar = _tcschr(pBuf, ' ');
1297 if (pChar != NULL)
1298 {
1299 *pChar = 0;
1300 pRT->pRoutes[i].dwIfIndex = _tcstoul(pBuf, NULL, 10);
1301 pBuf = pChar + 1;
1302 }
1303
1304 // Route type
1305 pRT->pRoutes[i].dwRouteType = _tcstoul(pBuf, NULL, 10);
1306 }
1307
1308 Lock();
1309 DestroyResultData();
1310 Unlock();
1311 }
1312
1313 return pRT;
1314}
f1448d17
VK
1315
1316
1317//
1318// Set proxy information
1319//
1320
a765d97c 1321void AgentConnection::SetProxy(DWORD dwAddr, WORD wPort, int iAuthMethod, const TCHAR *pszSecret)
f1448d17
VK
1322{
1323 m_dwProxyAddr = dwAddr;
1324 m_wProxyPort = wPort;
1325 m_iProxyAuth = iAuthMethod;
1326 if (pszSecret != NULL)
1327 {
1328#ifdef UNICODE
1329 WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK | WC_DEFAULTCHAR,
1330 pszSecret, -1, m_szProxySecret, MAX_SECRET_LENGTH, NULL, NULL);
1331#else
1332 nx_strncpy(m_szProxySecret, pszSecret, MAX_SECRET_LENGTH);
1333#endif
1334 }
1335 else
1336 {
1337 m_szProxySecret[0] = 0;
1338 }
1339 m_bUseProxy = TRUE;
1340}
1341
1342
1343//
1344// Setup proxy connection
1345//
1346
1347DWORD AgentConnection::SetupProxyConnection(void)
1348{
4bd3d6c5 1349 CSCPMessage msg(m_nProtocolVersion);
f1448d17
VK
1350 DWORD dwRqId;
1351
1352 dwRqId = m_dwRequestId++;
1353 msg.SetCode(CMD_SETUP_PROXY_CONNECTION);
1354 msg.SetId(dwRqId);
9a85ddb7 1355 msg.SetVariable(VID_IP_ADDRESS, (DWORD)ntohl(m_dwAddr));
f1448d17
VK
1356 msg.SetVariable(VID_AGENT_PORT, m_wPort);
1357 if (SendMessage(&msg))
1358 return WaitForRCC(dwRqId, 60000); // Wait 60 seconds for remote connect
1359 else
1360 return ERR_CONNECTION_BROKEN;
1361}
15c8cf46
VK
1362
1363
1364//
1365// Enable trap receiving on connection
1366//
1367
1368DWORD AgentConnection::EnableTraps(void)
1369{
1370 CSCPMessage msg(m_nProtocolVersion);
1371 DWORD dwRqId;
1372
1373 dwRqId = m_dwRequestId++;
1374 msg.SetCode(CMD_ENABLE_AGENT_TRAPS);
1375 msg.SetId(dwRqId);
1376 if (SendMessage(&msg))
1377 return WaitForRCC(dwRqId, m_dwCommandTimeout);
1378 else
1379 return ERR_CONNECTION_BROKEN;
1380}
439c93c0
VK
1381
1382
1383//
1384// Send custom request to agent
1385//
1386
1387CSCPMessage *AgentConnection::CustomRequest(CSCPMessage *pRequest)
1388{
1389 DWORD dwRqId;
1390
1391 dwRqId = m_dwRequestId++;
1392 pRequest->SetId(dwRqId);
1393 if (SendMessage(pRequest))
1394 return WaitForMessage(CMD_REQUEST_COMPLETED, dwRqId, m_dwCommandTimeout);
1395 else
1396 return NULL;
1397}