- Version number changed to 0.2.2-dev
[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
35//
36// Receiver thread starter
37//
38
ccdbbb52 39THREAD_RESULT THREAD_CALL AgentConnection::ReceiverThreadStarter(void *pArg)
f77084bb
VK
40{
41 ((AgentConnection *)pArg)->ReceiverThread();
ccdbbb52 42 return THREAD_OK;
f77084bb
VK
43}
44
45
46//
47// Default constructor for AgentConnection - normally shouldn't be used
48//
49
50AgentConnection::AgentConnection()
51{
52 m_dwAddr = inet_addr("127.0.0.1");
53 m_wPort = AGENT_LISTEN_PORT;
54 m_iAuthMethod = AUTH_NONE;
55 m_szSecret[0] = 0;
56 m_hSocket = -1;
57 m_tLastCommandTime = 0;
58 m_dwNumDataLines = 0;
59 m_ppDataLines = NULL;
60 m_pMsgWaitQueue = new MsgWaitQueue;
d1d0b3be 61 m_dwRequestId = 1;
f77084bb 62 m_dwCommandTimeout = 10000; // Default timeout 10 seconds
1c62be36 63 m_bIsConnected = FALSE;
38e832d6 64 m_mutexDataLock = MutexCreate();
ccdbbb52 65 m_hReceiverThread = INVALID_THREAD_HANDLE;
f77084bb
VK
66}
67
68
69//
70// Normal constructor for AgentConnection
71//
72
268774a0 73AgentConnection::AgentConnection(DWORD dwAddr, WORD wPort, int iAuthMethod, TCHAR *pszSecret)
f77084bb
VK
74{
75 m_dwAddr = dwAddr;
76 m_wPort = wPort;
77 m_iAuthMethod = iAuthMethod;
268774a0
VK
78 if (pszSecret != NULL)
79 {
80#ifdef UNICODE
81 WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK | WC_DEFAULTCHAR,
82 pszSecret, -1, m_szSecret, MAX_SECRET_LENGTH, NULL, NULL);
83#else
84 strncpy(m_szSecret, pszSecret, MAX_SECRET_LENGTH);
85#endif
86 }
f77084bb 87 else
268774a0 88 {
f77084bb 89 m_szSecret[0] = 0;
268774a0 90 }
f77084bb
VK
91 m_hSocket = -1;
92 m_tLastCommandTime = 0;
93 m_dwNumDataLines = 0;
94 m_ppDataLines = NULL;
95 m_pMsgWaitQueue = new MsgWaitQueue;
d1d0b3be 96 m_dwRequestId = 1;
f77084bb 97 m_dwCommandTimeout = 10000; // Default timeout 10 seconds
1c62be36 98 m_bIsConnected = FALSE;
38e832d6 99 m_mutexDataLock = MutexCreate();
ccdbbb52 100 m_hReceiverThread = INVALID_THREAD_HANDLE;
f77084bb
VK
101}
102
103
104//
105// Destructor
106//
107
108AgentConnection::~AgentConnection()
109{
1a60d114
VK
110 // Disconnect from peer
111 Disconnect();
38e832d6
VK
112
113 // Wait for receiver thread termination
ccdbbb52 114 ThreadJoin(m_hReceiverThread);
ba8681ba
VK
115 if (m_hSocket != -1)
116 closesocket(m_hSocket);
38e832d6
VK
117
118 Lock();
f77084bb 119 DestroyResultData();
38e832d6
VK
120 Unlock();
121
f77084bb 122 delete m_pMsgWaitQueue;
38e832d6
VK
123
124 MutexDestroy(m_mutexDataLock);
f77084bb
VK
125}
126
127
128//
059f6632
VK
129// Print message. This function is virtual and can be overrided in
130// derived classes. Default implementation will print message to stdout.
f77084bb
VK
131//
132
268774a0 133void AgentConnection::PrintMsg(TCHAR *pszFormat, ...)
f77084bb
VK
134{
135 va_list args;
136
137 va_start(args, pszFormat);
268774a0 138 _vtprintf(pszFormat, args);
f77084bb 139 va_end(args);
268774a0 140 _tprintf(_T("\n"));
f77084bb
VK
141}
142
143
144//
145// Receiver thread
146//
147
148void AgentConnection::ReceiverThread(void)
149{
150 CSCPMessage *pMsg;
151 CSCP_MESSAGE *pRawMsg;
152 CSCP_BUFFER *pMsgBuffer;
153 int iErr;
268774a0 154 TCHAR szBuffer[128];
f77084bb
VK
155
156 // Initialize raw message receiving function
9d72bde1 157 pMsgBuffer = (CSCP_BUFFER *)malloc(sizeof(CSCP_BUFFER));
f77084bb
VK
158 RecvCSCPMessage(0, NULL, pMsgBuffer, 0);
159
160 // Allocate space for raw message
9d72bde1 161 pRawMsg = (CSCP_MESSAGE *)malloc(RECEIVER_BUFFER_SIZE);
f77084bb
VK
162
163 // Message receiving loop
164 while(1)
165 {
166 // Receive raw message
167 if ((iErr = RecvCSCPMessage(m_hSocket, pRawMsg, pMsgBuffer, RECEIVER_BUFFER_SIZE)) <= 0)
168 break;
169
170 // Check if we get too large message
171 if (iErr == 1)
172 {
268774a0 173 PrintMsg(_T("Received too large message %s (%ld bytes)"),
f77084bb
VK
174 CSCPMessageCodeName(ntohs(pRawMsg->wCode), szBuffer),
175 ntohl(pRawMsg->dwSize));
176 continue;
177 }
178
179 // Check that actual received packet size is equal to encoded in packet
180 if ((int)ntohl(pRawMsg->dwSize) != iErr)
181 {
268774a0 182 PrintMsg(_T("RecvMsg: Bad packet length [dwSize=%d ActualSize=%d]"), ntohl(pRawMsg->dwSize), iErr);
f77084bb
VK
183 continue; // Bad packet, wait for next
184 }
185
186 // Create message object from raw message
187 pMsg = new CSCPMessage(pRawMsg);
188 if (pMsg->GetCode() == CMD_TRAP)
189 {
901c96c7 190 OnTrap(pMsg);
f77084bb
VK
191 delete pMsg;
192 }
193 else
194 {
195 m_pMsgWaitQueue->Put(pMsg);
196 }
197 }
198
1c62be36 199 // Close socket and mark connection as disconnected
ba8681ba
VK
200 if (iErr == 0)
201 shutdown(m_hSocket, SHUT_RDWR);
202 closesocket(m_hSocket);
203 m_hSocket = -1;
204 m_bIsConnected = FALSE;
1c62be36 205
9d72bde1
VK
206 free(pRawMsg);
207 free(pMsgBuffer);
f77084bb
VK
208}
209
210
211//
212// Connect to agent
213//
214
215BOOL AgentConnection::Connect(BOOL bVerbose)
216{
217 struct sockaddr_in sa;
268774a0 218 TCHAR szBuffer[256];
f77084bb 219 BOOL bSuccess = FALSE;
d1d0b3be 220 DWORD dwError;
f77084bb 221
1c62be36 222 // Check if already connected
ba8681ba 223 if (m_bIsConnected)
1c62be36
VK
224 return FALSE;
225
ccdbbb52
VK
226 // Wait for receiver thread from previous connection, if any
227 ThreadJoin(m_hReceiverThread);
228 m_hReceiverThread = INVALID_THREAD_HANDLE;
229
ba8681ba
VK
230 // Check if we need to close existing socket
231 if (m_hSocket != -1)
232 closesocket(m_hSocket);
233
f77084bb
VK
234 // Create socket
235 m_hSocket = socket(AF_INET, SOCK_STREAM, 0);
236 if (m_hSocket == -1)
237 {
268774a0 238 PrintMsg(_T("Call to socket() failed"));
f77084bb
VK
239 goto connect_cleanup;
240 }
241
242 // Fill in address structure
243 memset(&sa, 0, sizeof(sa));
244 sa.sin_addr.s_addr = m_dwAddr;
245 sa.sin_family = AF_INET;
246 sa.sin_port = htons(m_wPort);
247
248 // Connect to server
249 if (connect(m_hSocket, (struct sockaddr *)&sa, sizeof(sa)) == -1)
250 {
251 if (bVerbose)
205acaf4 252 PrintMsg(_T("Cannot establish connection with agent %s"), IpToStr(ntohl(m_dwAddr), szBuffer));
f77084bb
VK
253 goto connect_cleanup;
254 }
255
256 // Start receiver thread
ccdbbb52 257 m_hReceiverThread = ThreadCreateEx(ReceiverThreadStarter, 0, this);
f77084bb
VK
258
259 // Authenticate itself to agent
d1d0b3be 260 if ((dwError = Authenticate()) != ERR_SUCCESS)
f77084bb 261 {
205acaf4 262 PrintMsg(_T("Authentication to agent %s failed (%s)"), IpToStr(ntohl(m_dwAddr), szBuffer),
d1d0b3be
VK
263 AgentErrorCodeToText(dwError));
264 goto connect_cleanup;
f77084bb
VK
265 }
266
267 // Test connectivity
d1d0b3be 268 if ((dwError = Nop()) != ERR_SUCCESS)
f77084bb 269 {
205acaf4 270 PrintMsg(_T("Communication with agent %s failed (%s)"), IpToStr(ntohl(m_dwAddr), szBuffer),
d1d0b3be 271 AgentErrorCodeToText(dwError));
f77084bb
VK
272 goto connect_cleanup;
273 }
274
275 bSuccess = TRUE;
276
277connect_cleanup:
278 if (!bSuccess)
279 {
280 if (m_hSocket != -1)
f77084bb 281 shutdown(m_hSocket, 2);
ba8681ba
VK
282 ThreadJoin(m_hReceiverThread);
283 m_hReceiverThread = INVALID_THREAD_HANDLE;
284
285 if (m_hSocket != -1)
f77084bb 286 closesocket(m_hSocket);
f77084bb 287 }
1c62be36 288 m_bIsConnected = bSuccess;
f77084bb
VK
289 return bSuccess;
290}
291
292
293//
294// Disconnect from agent
295//
296
297void AgentConnection::Disconnect(void)
298{
1c62be36 299 Lock();
f77084bb
VK
300 if (m_hSocket != -1)
301 {
ba8681ba 302 shutdown(m_hSocket, SHUT_RDWR);
f77084bb
VK
303 }
304 DestroyResultData();
1c62be36
VK
305 m_bIsConnected = FALSE;
306 Unlock();
f77084bb
VK
307}
308
309
310//
311// Destroy command execuion results data
312//
313
314void AgentConnection::DestroyResultData(void)
315{
316 DWORD i;
317
318 if (m_ppDataLines != NULL)
319 {
320 for(i = 0; i < m_dwNumDataLines; i++)
321 if (m_ppDataLines[i] != NULL)
9d72bde1
VK
322 free(m_ppDataLines[i]);
323 free(m_ppDataLines);
f77084bb
VK
324 m_ppDataLines = NULL;
325 }
326 m_dwNumDataLines = 0;
327}
328
329
330//
331// Get interface list from agent
332//
333
334INTERFACE_LIST *AgentConnection::GetInterfaceList(void)
335{
1c62be36
VK
336 INTERFACE_LIST *pIfList = NULL;
337 DWORD i;
268774a0 338 TCHAR *pChar, *pBuf;
1c62be36 339
268774a0 340 if (GetList(_T("Net.InterfaceList")) == ERR_SUCCESS)
1c62be36 341 {
9d72bde1 342 pIfList = (INTERFACE_LIST *)malloc(sizeof(INTERFACE_LIST));
1c62be36 343 pIfList->iNumEntries = m_dwNumDataLines;
9d72bde1 344 pIfList->pInterfaces = (INTERFACE_INFO *)malloc(sizeof(INTERFACE_INFO) * m_dwNumDataLines);
1c62be36
VK
345 memset(pIfList->pInterfaces, 0, sizeof(INTERFACE_INFO) * m_dwNumDataLines);
346 for(i = 0; i < m_dwNumDataLines; i++)
347 {
348 pBuf = m_ppDataLines[i];
349
350 // Index
268774a0 351 pChar = _tcschr(pBuf, ' ');
1c62be36
VK
352 if (pChar != NULL)
353 {
354 *pChar = 0;
268774a0 355 pIfList->pInterfaces[i].dwIndex = _tcstoul(pBuf, NULL, 10);
1c62be36
VK
356 pBuf = pChar + 1;
357 }
358
359 // Address and mask
268774a0 360 pChar = _tcschr(pBuf, _T(' '));
1c62be36
VK
361 if (pChar != NULL)
362 {
268774a0 363 TCHAR *pSlash;
1c62be36
VK
364
365 *pChar = 0;
268774a0 366 pSlash = _tcschr(pBuf, _T('/'));
1c62be36
VK
367 if (pSlash != NULL)
368 {
369 *pSlash = 0;
370 pSlash++;
371 }
372 else // Just a paranoia protection, should'n happen if agent working correctly
373 {
268774a0 374 pSlash = _T("24");
1c62be36 375 }
205acaf4
VK
376 pIfList->pInterfaces[i].dwIpAddr = ntohl(_t_inet_addr(pBuf));
377 pIfList->pInterfaces[i].dwIpNetMask = ~(0xFFFFFFFF >> _tcstoul(pSlash, NULL, 10));
1c62be36
VK
378 pBuf = pChar + 1;
379 }
380
381 // Interface type
268774a0 382 pChar = _tcschr(pBuf, ' ');
1c62be36
VK
383 if (pChar != NULL)
384 {
385 *pChar = 0;
205acaf4 386 pIfList->pInterfaces[i].dwType = _tcstoul(pBuf, NULL, 10);
1c62be36 387 pBuf = pChar + 1;
b50f1100
VK
388 }
389
390 // MAC address
391 pChar = _tcschr(pBuf, ' ');
392 if (pChar != NULL)
393 {
394 *pChar = 0;
395 StrToBin(pBuf, pIfList->pInterfaces[i].bMacAddr, MAC_ADDR_LENGTH);
396 pBuf = pChar + 1;
1c62be36
VK
397 }
398
399 // Name
268774a0 400 _tcsncpy(pIfList->pInterfaces[i].szName, pBuf, MAX_OBJECT_NAME - 1);
1c62be36
VK
401 }
402
9d72bde1 403 Lock();
1c62be36 404 DestroyResultData();
9d72bde1 405 Unlock();
1c62be36
VK
406 }
407
408 return pIfList;
f77084bb
VK
409}
410
411
412//
413// Get parameter value
414//
415
268774a0 416DWORD AgentConnection::GetParameter(TCHAR *pszParam, DWORD dwBufSize, TCHAR *pszBuffer)
f77084bb
VK
417{
418 CSCPMessage msg, *pResponce;
419 DWORD dwRqId, dwRetCode;
420
1c62be36 421 if (m_bIsConnected)
f77084bb 422 {
1c62be36
VK
423 dwRqId = m_dwRequestId++;
424 msg.SetCode(CMD_GET_PARAMETER);
425 msg.SetId(dwRqId);
426 msg.SetVariable(VID_PARAMETER, pszParam);
427 if (SendMessage(&msg))
f77084bb 428 {
1c62be36
VK
429 pResponce = WaitForMessage(CMD_REQUEST_COMPLETED, dwRqId, m_dwCommandTimeout);
430 if (pResponce != NULL)
431 {
432 dwRetCode = pResponce->GetVariableLong(VID_RCC);
433 if (dwRetCode == ERR_SUCCESS)
434 pResponce->GetVariableStr(VID_VALUE, pszBuffer, dwBufSize);
435 delete pResponce;
436 }
437 else
438 {
439 dwRetCode = ERR_REQUEST_TIMEOUT;
440 }
f77084bb
VK
441 }
442 else
443 {
1c62be36 444 dwRetCode = ERR_CONNECTION_BROKEN;
f77084bb
VK
445 }
446 }
447 else
448 {
1c62be36 449 dwRetCode = ERR_NOT_CONNECTED;
f77084bb
VK
450 }
451
452 return dwRetCode;
453}
454
455
456//
457// Get ARP cache
458//
459
460ARP_CACHE *AgentConnection::GetArpCache(void)
461{
1c62be36 462 ARP_CACHE *pArpCache = NULL;
268774a0 463 TCHAR szByte[4], *pBuf, *pChar;
1c62be36
VK
464 DWORD i, j;
465
268774a0 466 if (GetList(_T("Net.ArpCache")) == ERR_SUCCESS)
1c62be36
VK
467 {
468 // Create empty structure
9d72bde1 469 pArpCache = (ARP_CACHE *)malloc(sizeof(ARP_CACHE));
1c62be36 470 pArpCache->dwNumEntries = m_dwNumDataLines;
9d72bde1 471 pArpCache->pEntries = (ARP_ENTRY *)malloc(sizeof(ARP_ENTRY) * m_dwNumDataLines);
1c62be36
VK
472 memset(pArpCache->pEntries, 0, sizeof(ARP_ENTRY) * m_dwNumDataLines);
473
474 szByte[2] = 0;
475
476 // Parse data lines
477 // Each line has form of XXXXXXXXXXXX a.b.c.d
478 // where XXXXXXXXXXXX is a MAC address (12 hexadecimal digits)
479 // and a.b.c.d is an IP address in decimal dotted notation
480 for(i = 0; i < m_dwNumDataLines; i++)
481 {
482 pBuf = m_ppDataLines[i];
268774a0 483 if (_tcslen(pBuf) < 20) // Invalid line
1c62be36
VK
484 continue;
485
486 // MAC address
487 for(j = 0; j < 6; j++)
488 {
268774a0
VK
489 memcpy(szByte, pBuf, sizeof(TCHAR) * 2);
490 pArpCache->pEntries[i].bMacAddr[j] = (BYTE)_tcstol(szByte, NULL, 16);
1c62be36
VK
491 pBuf+=2;
492 }
493
494 // IP address
495 while(*pBuf == ' ')
496 pBuf++;
268774a0 497 pChar = _tcschr(pBuf, _T(' '));
1c62be36
VK
498 if (pChar != NULL)
499 *pChar = 0;
205acaf4 500 pArpCache->pEntries[i].dwIpAddr = ntohl(_t_inet_addr(pBuf));
1c62be36
VK
501
502 // Interface index
503 if (pChar != NULL)
268774a0 504 pArpCache->pEntries[i].dwIndex = _tcstoul(pChar + 1, NULL, 10);
1c62be36
VK
505 }
506
507 DestroyResultData();
508 }
509 return pArpCache;
f77084bb
VK
510}
511
512
513//
514// Send dummy command to agent (can be used for keepalive)
515//
516
517DWORD AgentConnection::Nop(void)
518{
519 CSCPMessage msg;
520 DWORD dwRqId;
521
522 dwRqId = m_dwRequestId++;
523 msg.SetCode(CMD_KEEPALIVE);
524 msg.SetId(dwRqId);
525 if (SendMessage(&msg))
526 return WaitForRCC(dwRqId, m_dwCommandTimeout);
527 else
528 return ERR_CONNECTION_BROKEN;
529}
530
531
532//
533// Wait for request completion code
534//
535
536DWORD AgentConnection::WaitForRCC(DWORD dwRqId, DWORD dwTimeOut)
537{
538 CSCPMessage *pMsg;
539 DWORD dwRetCode;
540
541 pMsg = m_pMsgWaitQueue->WaitForMessage(CMD_REQUEST_COMPLETED, dwRqId, dwTimeOut);
542 if (pMsg != NULL)
543 {
544 dwRetCode = pMsg->GetVariableLong(VID_RCC);
545 delete pMsg;
546 }
547 else
548 {
549 dwRetCode = ERR_REQUEST_TIMEOUT;
550 }
551 return dwRetCode;
552}
553
554
555//
556// Send message to agent
557//
558
559BOOL AgentConnection::SendMessage(CSCPMessage *pMsg)
560{
561 CSCP_MESSAGE *pRawMsg;
562 BOOL bResult;
563
564 pRawMsg = pMsg->CreateMessage();
1216cc73 565 bResult = (SendEx(m_hSocket, (char *)pRawMsg, ntohl(pRawMsg->dwSize), 0) == (int)ntohl(pRawMsg->dwSize));
9d72bde1 566 free(pRawMsg);
f77084bb
VK
567 return bResult;
568}
901c96c7
VK
569
570
571//
572// Trap handler. Should be overriden in derived classes to implement
573// actual trap processing. Default implementation do nothing.
574//
575
576void AgentConnection::OnTrap(CSCPMessage *pMsg)
577{
578}
579
580
581//
582// Get list of values
583//
584
268774a0 585DWORD AgentConnection::GetList(TCHAR *pszParam)
901c96c7
VK
586{
587 CSCPMessage msg, *pResponce;
588 DWORD i, dwRqId, dwRetCode;
589
1c62be36 590 if (m_bIsConnected)
901c96c7 591 {
1c62be36
VK
592 DestroyResultData();
593 dwRqId = m_dwRequestId++;
594 msg.SetCode(CMD_GET_LIST);
595 msg.SetId(dwRqId);
596 msg.SetVariable(VID_PARAMETER, pszParam);
597 if (SendMessage(&msg))
901c96c7 598 {
1c62be36
VK
599 pResponce = WaitForMessage(CMD_REQUEST_COMPLETED, dwRqId, m_dwCommandTimeout);
600 if (pResponce != NULL)
601 {
602 dwRetCode = pResponce->GetVariableLong(VID_RCC);
603 if (dwRetCode == ERR_SUCCESS)
604 {
605 m_dwNumDataLines = pResponce->GetVariableLong(VID_NUM_STRINGS);
268774a0 606 m_ppDataLines = (TCHAR **)malloc(sizeof(TCHAR *) * m_dwNumDataLines);
1c62be36
VK
607 for(i = 0; i < m_dwNumDataLines; i++)
608 m_ppDataLines[i] = pResponce->GetVariableStr(VID_ENUM_VALUE_BASE + i);
609 }
610 delete pResponce;
611 }
612 else
901c96c7 613 {
1c62be36 614 dwRetCode = ERR_REQUEST_TIMEOUT;
901c96c7 615 }
901c96c7
VK
616 }
617 else
618 {
1c62be36 619 dwRetCode = ERR_CONNECTION_BROKEN;
901c96c7
VK
620 }
621 }
622 else
623 {
1c62be36 624 dwRetCode = ERR_NOT_CONNECTED;
901c96c7
VK
625 }
626
627 return dwRetCode;
628}
d1d0b3be
VK
629
630
631//
632// Authenticate to agent
633//
634
635DWORD AgentConnection::Authenticate(void)
636{
637 CSCPMessage msg;
638 DWORD dwRqId;
639 BYTE hash[32];
268774a0
VK
640#ifdef UNICODE
641 WCHAR szBuffer[MAX_SECRET_LENGTH];
642#endif
d1d0b3be
VK
643
644 if (m_iAuthMethod == AUTH_NONE)
645 return ERR_SUCCESS; // No authentication required
646
647 dwRqId = m_dwRequestId++;
648 msg.SetCode(CMD_AUTHENTICATE);
649 msg.SetId(dwRqId);
650 msg.SetVariable(VID_AUTH_METHOD, (WORD)m_iAuthMethod);
651 switch(m_iAuthMethod)
652 {
653 case AUTH_PLAINTEXT:
268774a0
VK
654#ifdef UNICODE
655 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, m_szSecret, -1, szBuffer, MAX_SECRET_LENGTH);
656 msg.SetVariable(VID_SHARED_SECRET, szBuffer);
657#else
d1d0b3be 658 msg.SetVariable(VID_SHARED_SECRET, m_szSecret);
268774a0 659#endif
d1d0b3be
VK
660 break;
661 case AUTH_MD5_HASH:
662 CalculateMD5Hash((BYTE *)m_szSecret, strlen(m_szSecret), hash);
663 msg.SetVariable(VID_SHARED_SECRET, hash, MD5_DIGEST_SIZE);
664 break;
665 case AUTH_SHA1_HASH:
666 CalculateSHA1Hash((BYTE *)m_szSecret, strlen(m_szSecret), hash);
667 msg.SetVariable(VID_SHARED_SECRET, hash, SHA1_DIGEST_SIZE);
668 break;
669 default:
670 break;
671 }
672 if (SendMessage(&msg))
673 return WaitForRCC(dwRqId, m_dwCommandTimeout);
674 else
675 return ERR_CONNECTION_BROKEN;
676}
3c774461
VK
677
678
679//
680// Execute action on agent
681//
682
268774a0 683DWORD AgentConnection::ExecAction(TCHAR *pszAction, int argc, TCHAR **argv)
3c774461
VK
684{
685 CSCPMessage msg;
686 DWORD dwRqId;
687 int i;
688
1c62be36
VK
689 if (!m_bIsConnected)
690 return ERR_NOT_CONNECTED;
691
3c774461
VK
692 dwRqId = m_dwRequestId++;
693 msg.SetCode(CMD_ACTION);
694 msg.SetId(dwRqId);
695 msg.SetVariable(VID_ACTION_NAME, pszAction);
696 msg.SetVariable(VID_NUM_ARGS, (DWORD)argc);
697 for(i = 0; i < argc; i++)
698 msg.SetVariable(VID_ACTION_ARG_BASE + i, argv[i]);
699
700 if (SendMessage(&msg))
701 return WaitForRCC(dwRqId, m_dwCommandTimeout);
702 else
703 return ERR_CONNECTION_BROKEN;
704}
d096bcdd
VK
705
706
707//
708// Upload file to agent
709//
710
711DWORD AgentConnection::UploadFile(TCHAR *pszFile)
712{
713 DWORD dwRqId, dwResult;
714 CSCPMessage msg;
715 int i;
716
717 if (!m_bIsConnected)
718 return ERR_NOT_CONNECTED;
719
720 dwRqId = m_dwRequestId++;
721
722 msg.SetCode(CMD_TRANSFER_FILE);
723 msg.SetId(dwRqId);
724 for(i = _tcslen(pszFile) - 1;
725 (i >= 0) && (pszFile[i] != '\\') && (pszFile[i] != '/'); i--);
726 msg.SetVariable(VID_FILE_NAME, &pszFile[i + 1]);
727
728 if (SendMessage(&msg))
729 {
730 dwResult = WaitForRCC(dwRqId, m_dwCommandTimeout);
731 }
732 else
733 {
734 dwResult = ERR_CONNECTION_BROKEN;
735 }
736
737 if (dwResult == ERR_SUCCESS)
738 {
739 if (SendFileOverCSCP(m_hSocket, dwRqId, pszFile))
740 dwResult = WaitForRCC(dwRqId, m_dwCommandTimeout);
741 else
742 dwResult = ERR_IO_FAILURE;
743 }
744
745 return dwResult;
746}
e925a5fc
VK
747
748
749//
750// Send upgrade command
751//
752
753DWORD AgentConnection::StartUpgrade(TCHAR *pszPkgName)
754{
755 DWORD dwRqId, dwResult;
756 CSCPMessage msg;
757 int i;
758
759 if (!m_bIsConnected)
760 return ERR_NOT_CONNECTED;
761
762 dwRqId = m_dwRequestId++;
763
764 msg.SetCode(CMD_UPGRADE_AGENT);
765 msg.SetId(dwRqId);
766 for(i = _tcslen(pszPkgName) - 1;
767 (i >= 0) && (pszPkgName[i] != '\\') && (pszPkgName[i] != '/'); i--);
768 msg.SetVariable(VID_FILE_NAME, &pszPkgName[i + 1]);
769
770 if (SendMessage(&msg))
771 {
772 dwResult = WaitForRCC(dwRqId, m_dwCommandTimeout);
773 }
774 else
775 {
776 dwResult = ERR_CONNECTION_BROKEN;
777 }
778
779 return dwResult;
780}
3f0ca036
VK
781
782
783//
784// Check status of network service via agent
785//
786
787DWORD AgentConnection::CheckNetworkService(DWORD *pdwStatus, DWORD dwIpAddr, int iServiceType,
788 WORD wPort, WORD wProto,
789 TCHAR *pszRequest, TCHAR *pszResponce)
790{
791 DWORD dwRqId, dwResult;
792 CSCPMessage msg, *pResponce;
793 static WORD m_wDefaultPort[] = { 7, 22, 110, 25, 21, 80 };
794
795 if (!m_bIsConnected)
796 return ERR_NOT_CONNECTED;
797
798 dwRqId = m_dwRequestId++;
799
800 msg.SetCode(CMD_CHECK_NETWORK_SERVICE);
801 msg.SetId(dwRqId);
802 msg.SetVariable(VID_IP_ADDRESS, dwIpAddr);
803 msg.SetVariable(VID_SERVICE_TYPE, (WORD)iServiceType);
804 msg.SetVariable(VID_IP_PORT,
805 (wPort != 0) ? wPort :
25376fc7 806 m_wDefaultPort[((iServiceType >= NETSRV_CUSTOM) &&
3f0ca036 807 (iServiceType <= NETSRV_HTTP)) ? iServiceType : 0]);
25376fc7 808 msg.SetVariable(VID_IP_PROTO, (wProto != 0) ? wProto : (WORD)IPPROTO_TCP);
3f0ca036
VK
809 msg.SetVariable(VID_SERVICE_REQUEST, pszRequest);
810 msg.SetVariable(VID_SERVICE_RESPONCE, pszResponce);
811
812 if (SendMessage(&msg))
813 {
814 // Wait up to 90 seconds for results
815 pResponce = WaitForMessage(CMD_REQUEST_COMPLETED, dwRqId, 90000);
816 if (pResponce != NULL)
817 {
818 dwResult = pResponce->GetVariableLong(VID_RCC);
819 if (dwResult == ERR_SUCCESS)
820 {
821 *pdwStatus = pResponce->GetVariableLong(VID_SERVICE_STATUS);
822 }
823 delete pResponce;
824 }
825 else
826 {
827 dwResult = ERR_REQUEST_TIMEOUT;
828 }
829 }
830 else
831 {
832 dwResult = ERR_CONNECTION_BROKEN;
833 }
834
835 return dwResult;
836}
125c0e81
VK
837
838
839//
840// Get list of supported parameters from subagent
841//
842
843DWORD AgentConnection::GetSupportedParameters(DWORD *pdwNumParams, NXC_AGENT_PARAM **ppParamList)
844{
845 DWORD i, dwId, dwRqId, dwResult;
846 CSCPMessage msg, *pResponce;
847
848 if (!m_bIsConnected)
849 return ERR_NOT_CONNECTED;
850
851 *pdwNumParams = 0;
852 *ppParamList = NULL;
853
854 dwRqId = m_dwRequestId++;
855
856 msg.SetCode(CMD_GET_PARAMETER_LIST);
857 msg.SetId(dwRqId);
858
859 if (SendMessage(&msg))
860 {
861 // Wait up to 90 seconds for results
862 pResponce = WaitForMessage(CMD_REQUEST_COMPLETED, dwRqId, m_dwCommandTimeout);
863 if (pResponce != NULL)
864 {
865 dwResult = pResponce->GetVariableLong(VID_RCC);
866 if (dwResult == ERR_SUCCESS)
867 {
868 *pdwNumParams = pResponce->GetVariableLong(VID_NUM_PARAMETERS);
869 *ppParamList = (NXC_AGENT_PARAM *)malloc(sizeof(NXC_AGENT_PARAM) * *pdwNumParams);
870 for(i = 0, dwId = VID_PARAM_LIST_BASE; i < *pdwNumParams; i++)
871 {
872 pResponce->GetVariableStr(dwId++, (*ppParamList)[i].szName, MAX_PARAM_NAME);
873 pResponce->GetVariableStr(dwId++, (*ppParamList)[i].szDescription, MAX_DB_STRING);
874 (*ppParamList)[i].iDataType = (int)pResponce->GetVariableShort(dwId++);
875 }
876 }
877 delete pResponce;
878 }
879 else
880 {
881 dwResult = ERR_REQUEST_TIMEOUT;
882 }
883 }
884 else
885 {
886 dwResult = ERR_CONNECTION_BROKEN;
887 }
888
889 return dwResult;
890}