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