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