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