e26abf75f6471a282e679e353a4d98821686bea3
[public/netxms.git] / src / server / libnxsrv / agent.cpp
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"
25 #include <stdarg.h>
26
27
28 //
29 // Constants
30 //
31
32 #define RECEIVER_BUFFER_SIZE 262144
33
34
35 //
36 // Receiver thread starter
37 //
38
39 THREAD_RESULT THREAD_CALL AgentConnection::ReceiverThreadStarter(void *pArg)
40 {
41 ((AgentConnection *)pArg)->ReceiverThread();
42 return THREAD_OK;
43 }
44
45
46 //
47 // Default constructor for AgentConnection - normally shouldn't be used
48 //
49
50 AgentConnection::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;
61 m_dwRequestId = 1;
62 m_dwCommandTimeout = 10000; // Default timeout 10 seconds
63 m_bIsConnected = FALSE;
64 m_mutexDataLock = MutexCreate();
65 m_hReceiverThread = INVALID_THREAD_HANDLE;
66 }
67
68
69 //
70 // Normal constructor for AgentConnection
71 //
72
73 AgentConnection::AgentConnection(DWORD dwAddr, WORD wPort, int iAuthMethod, TCHAR *pszSecret)
74 {
75 m_dwAddr = dwAddr;
76 m_wPort = wPort;
77 m_iAuthMethod = iAuthMethod;
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 }
87 else
88 {
89 m_szSecret[0] = 0;
90 }
91 m_hSocket = -1;
92 m_tLastCommandTime = 0;
93 m_dwNumDataLines = 0;
94 m_ppDataLines = NULL;
95 m_pMsgWaitQueue = new MsgWaitQueue;
96 m_dwRequestId = 1;
97 m_dwCommandTimeout = 10000; // Default timeout 10 seconds
98 m_bIsConnected = FALSE;
99 m_mutexDataLock = MutexCreate();
100 m_hReceiverThread = INVALID_THREAD_HANDLE;
101 }
102
103
104 //
105 // Destructor
106 //
107
108 AgentConnection::~AgentConnection()
109 {
110 // Disconnect from peer
111 Disconnect();
112
113 // Wait for receiver thread termination
114 ThreadJoin(m_hReceiverThread);
115
116 Lock();
117 DestroyResultData();
118 Unlock();
119
120 delete m_pMsgWaitQueue;
121
122 MutexDestroy(m_mutexDataLock);
123 }
124
125
126 //
127 // Print message. This function is virtual and can be overrided in
128 // derived classes. Default implementation will print message to stdout.
129 //
130
131 void AgentConnection::PrintMsg(TCHAR *pszFormat, ...)
132 {
133 va_list args;
134
135 va_start(args, pszFormat);
136 _vtprintf(pszFormat, args);
137 va_end(args);
138 _tprintf(_T("\n"));
139 }
140
141
142 //
143 // Receiver thread
144 //
145
146 void AgentConnection::ReceiverThread(void)
147 {
148 CSCPMessage *pMsg;
149 CSCP_MESSAGE *pRawMsg;
150 CSCP_BUFFER *pMsgBuffer;
151 int iErr;
152 TCHAR szBuffer[128];
153
154 // Initialize raw message receiving function
155 pMsgBuffer = (CSCP_BUFFER *)malloc(sizeof(CSCP_BUFFER));
156 RecvCSCPMessage(0, NULL, pMsgBuffer, 0);
157
158 // Allocate space for raw message
159 pRawMsg = (CSCP_MESSAGE *)malloc(RECEIVER_BUFFER_SIZE);
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 {
171 PrintMsg(_T("Received too large message %s (%ld bytes)"),
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 {
180 PrintMsg(_T("RecvMsg: Bad packet length [dwSize=%d ActualSize=%d]"), ntohl(pRawMsg->dwSize), iErr);
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 {
188 OnTrap(pMsg);
189 delete pMsg;
190 }
191 else
192 {
193 m_pMsgWaitQueue->Put(pMsg);
194 }
195 }
196
197 // Close socket and mark connection as disconnected
198 Disconnect();
199
200 free(pRawMsg);
201 free(pMsgBuffer);
202 }
203
204
205 //
206 // Connect to agent
207 //
208
209 BOOL AgentConnection::Connect(BOOL bVerbose)
210 {
211 struct sockaddr_in sa;
212 TCHAR szBuffer[256];
213 BOOL bSuccess = FALSE;
214 DWORD dwError;
215
216 // Check if already connected
217 if ((m_bIsConnected) || (m_hSocket != -1))
218 return FALSE;
219
220 // Wait for receiver thread from previous connection, if any
221 ThreadJoin(m_hReceiverThread);
222 m_hReceiverThread = INVALID_THREAD_HANDLE;
223
224 // Create socket
225 m_hSocket = socket(AF_INET, SOCK_STREAM, 0);
226 if (m_hSocket == -1)
227 {
228 PrintMsg(_T("Call to socket() failed"));
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)
242 PrintMsg(_T("Cannot establish connection with agent %s"), IpToStr(ntohl(m_dwAddr), szBuffer));
243 goto connect_cleanup;
244 }
245
246 // Start receiver thread
247 m_hReceiverThread = ThreadCreateEx(ReceiverThreadStarter, 0, this);
248
249 // Authenticate itself to agent
250 if ((dwError = Authenticate()) != ERR_SUCCESS)
251 {
252 PrintMsg(_T("Authentication to agent %s failed (%s)"), IpToStr(ntohl(m_dwAddr), szBuffer),
253 AgentErrorCodeToText(dwError));
254 goto connect_cleanup;
255 }
256
257 // Test connectivity
258 if ((dwError = Nop()) != ERR_SUCCESS)
259 {
260 PrintMsg(_T("Communication with agent %s failed (%s)"), IpToStr(ntohl(m_dwAddr), szBuffer),
261 AgentErrorCodeToText(dwError));
262 goto connect_cleanup;
263 }
264
265 bSuccess = TRUE;
266
267 connect_cleanup:
268 if (!bSuccess)
269 {
270 Lock();
271 if (m_hSocket != -1)
272 {
273 shutdown(m_hSocket, 2);
274 closesocket(m_hSocket);
275 m_hSocket = -1;
276 }
277 Unlock();
278 }
279 m_bIsConnected = bSuccess;
280 return bSuccess;
281 }
282
283
284 //
285 // Disconnect from agent
286 //
287
288 void AgentConnection::Disconnect(void)
289 {
290 Lock();
291 if (m_hSocket != -1)
292 {
293 shutdown(m_hSocket, 2);
294 closesocket(m_hSocket);
295 m_hSocket = -1;
296 }
297 DestroyResultData();
298 m_bIsConnected = FALSE;
299 Unlock();
300 }
301
302
303 //
304 // Destroy command execuion results data
305 //
306
307 void 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)
315 free(m_ppDataLines[i]);
316 free(m_ppDataLines);
317 m_ppDataLines = NULL;
318 }
319 m_dwNumDataLines = 0;
320 }
321
322
323 //
324 // Get interface list from agent
325 //
326
327 INTERFACE_LIST *AgentConnection::GetInterfaceList(void)
328 {
329 INTERFACE_LIST *pIfList = NULL;
330 DWORD i;
331 TCHAR *pChar, *pBuf;
332
333 if (GetList(_T("Net.InterfaceList")) == ERR_SUCCESS)
334 {
335 pIfList = (INTERFACE_LIST *)malloc(sizeof(INTERFACE_LIST));
336 pIfList->iNumEntries = m_dwNumDataLines;
337 pIfList->pInterfaces = (INTERFACE_INFO *)malloc(sizeof(INTERFACE_INFO) * m_dwNumDataLines);
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
344 pChar = _tcschr(pBuf, ' ');
345 if (pChar != NULL)
346 {
347 *pChar = 0;
348 pIfList->pInterfaces[i].dwIndex = _tcstoul(pBuf, NULL, 10);
349 pBuf = pChar + 1;
350 }
351
352 // Address and mask
353 pChar = _tcschr(pBuf, _T(' '));
354 if (pChar != NULL)
355 {
356 TCHAR *pSlash;
357
358 *pChar = 0;
359 pSlash = _tcschr(pBuf, _T('/'));
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 {
367 pSlash = _T("24");
368 }
369 pIfList->pInterfaces[i].dwIpAddr = ntohl(_t_inet_addr(pBuf));
370 pIfList->pInterfaces[i].dwIpNetMask = ~(0xFFFFFFFF >> _tcstoul(pSlash, NULL, 10));
371 pBuf = pChar + 1;
372 }
373
374 // Interface type
375 pChar = _tcschr(pBuf, ' ');
376 if (pChar != NULL)
377 {
378 *pChar = 0;
379 pIfList->pInterfaces[i].dwType = _tcstoul(pBuf, NULL, 10);
380 pBuf = pChar + 1;
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;
390 }
391
392 // Name
393 _tcsncpy(pIfList->pInterfaces[i].szName, pBuf, MAX_OBJECT_NAME - 1);
394 }
395
396 Lock();
397 DestroyResultData();
398 Unlock();
399 }
400
401 return pIfList;
402 }
403
404
405 //
406 // Get parameter value
407 //
408
409 DWORD AgentConnection::GetParameter(TCHAR *pszParam, DWORD dwBufSize, TCHAR *pszBuffer)
410 {
411 CSCPMessage msg, *pResponce;
412 DWORD dwRqId, dwRetCode;
413
414 if (m_bIsConnected)
415 {
416 dwRqId = m_dwRequestId++;
417 msg.SetCode(CMD_GET_PARAMETER);
418 msg.SetId(dwRqId);
419 msg.SetVariable(VID_PARAMETER, pszParam);
420 if (SendMessage(&msg))
421 {
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 }
434 }
435 else
436 {
437 dwRetCode = ERR_CONNECTION_BROKEN;
438 }
439 }
440 else
441 {
442 dwRetCode = ERR_NOT_CONNECTED;
443 }
444
445 return dwRetCode;
446 }
447
448
449 //
450 // Get ARP cache
451 //
452
453 ARP_CACHE *AgentConnection::GetArpCache(void)
454 {
455 ARP_CACHE *pArpCache = NULL;
456 TCHAR szByte[4], *pBuf, *pChar;
457 DWORD i, j;
458
459 if (GetList(_T("Net.ArpCache")) == ERR_SUCCESS)
460 {
461 // Create empty structure
462 pArpCache = (ARP_CACHE *)malloc(sizeof(ARP_CACHE));
463 pArpCache->dwNumEntries = m_dwNumDataLines;
464 pArpCache->pEntries = (ARP_ENTRY *)malloc(sizeof(ARP_ENTRY) * m_dwNumDataLines);
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];
476 if (_tcslen(pBuf) < 20) // Invalid line
477 continue;
478
479 // MAC address
480 for(j = 0; j < 6; j++)
481 {
482 memcpy(szByte, pBuf, sizeof(TCHAR) * 2);
483 pArpCache->pEntries[i].bMacAddr[j] = (BYTE)_tcstol(szByte, NULL, 16);
484 pBuf+=2;
485 }
486
487 // IP address
488 while(*pBuf == ' ')
489 pBuf++;
490 pChar = _tcschr(pBuf, _T(' '));
491 if (pChar != NULL)
492 *pChar = 0;
493 pArpCache->pEntries[i].dwIpAddr = ntohl(_t_inet_addr(pBuf));
494
495 // Interface index
496 if (pChar != NULL)
497 pArpCache->pEntries[i].dwIndex = _tcstoul(pChar + 1, NULL, 10);
498 }
499
500 DestroyResultData();
501 }
502 return pArpCache;
503 }
504
505
506 //
507 // Send dummy command to agent (can be used for keepalive)
508 //
509
510 DWORD 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
529 DWORD 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
552 BOOL 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));
559 free(pRawMsg);
560 return bResult;
561 }
562
563
564 //
565 // Trap handler. Should be overriden in derived classes to implement
566 // actual trap processing. Default implementation do nothing.
567 //
568
569 void AgentConnection::OnTrap(CSCPMessage *pMsg)
570 {
571 }
572
573
574 //
575 // Get list of values
576 //
577
578 DWORD AgentConnection::GetList(TCHAR *pszParam)
579 {
580 CSCPMessage msg, *pResponce;
581 DWORD i, dwRqId, dwRetCode;
582
583 if (m_bIsConnected)
584 {
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))
591 {
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);
599 m_ppDataLines = (TCHAR **)malloc(sizeof(TCHAR *) * m_dwNumDataLines);
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
606 {
607 dwRetCode = ERR_REQUEST_TIMEOUT;
608 }
609 }
610 else
611 {
612 dwRetCode = ERR_CONNECTION_BROKEN;
613 }
614 }
615 else
616 {
617 dwRetCode = ERR_NOT_CONNECTED;
618 }
619
620 return dwRetCode;
621 }
622
623
624 //
625 // Authenticate to agent
626 //
627
628 DWORD AgentConnection::Authenticate(void)
629 {
630 CSCPMessage msg;
631 DWORD dwRqId;
632 BYTE hash[32];
633 #ifdef UNICODE
634 WCHAR szBuffer[MAX_SECRET_LENGTH];
635 #endif
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:
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
651 msg.SetVariable(VID_SHARED_SECRET, m_szSecret);
652 #endif
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 }
670
671
672 //
673 // Execute action on agent
674 //
675
676 DWORD AgentConnection::ExecAction(TCHAR *pszAction, int argc, TCHAR **argv)
677 {
678 CSCPMessage msg;
679 DWORD dwRqId;
680 int i;
681
682 if (!m_bIsConnected)
683 return ERR_NOT_CONNECTED;
684
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 }
698
699
700 //
701 // Upload file to agent
702 //
703
704 DWORD 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 }
740
741
742 //
743 // Send upgrade command
744 //
745
746 DWORD 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 }
774
775
776 //
777 // Check status of network service via agent
778 //
779
780 DWORD 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_PROTO, (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 }
830
831
832 //
833 // Get list of supported parameters from subagent
834 //
835
836 DWORD AgentConnection::GetSupportedParameters(DWORD *pdwNumParams, NXC_AGENT_PARAM **ppParamList)
837 {
838 DWORD i, dwId, dwRqId, dwResult;
839 CSCPMessage msg, *pResponce;
840
841 if (!m_bIsConnected)
842 return ERR_NOT_CONNECTED;
843
844 *pdwNumParams = 0;
845 *ppParamList = NULL;
846
847 dwRqId = m_dwRequestId++;
848
849 msg.SetCode(CMD_GET_PARAMETER_LIST);
850 msg.SetId(dwRqId);
851
852 if (SendMessage(&msg))
853 {
854 // Wait up to 90 seconds for results
855 pResponce = WaitForMessage(CMD_REQUEST_COMPLETED, dwRqId, m_dwCommandTimeout);
856 if (pResponce != NULL)
857 {
858 dwResult = pResponce->GetVariableLong(VID_RCC);
859 if (dwResult == ERR_SUCCESS)
860 {
861 *pdwNumParams = pResponce->GetVariableLong(VID_NUM_PARAMETERS);
862 *ppParamList = (NXC_AGENT_PARAM *)malloc(sizeof(NXC_AGENT_PARAM) * *pdwNumParams);
863 for(i = 0, dwId = VID_PARAM_LIST_BASE; i < *pdwNumParams; i++)
864 {
865 pResponce->GetVariableStr(dwId++, (*ppParamList)[i].szName, MAX_PARAM_NAME);
866 pResponce->GetVariableStr(dwId++, (*ppParamList)[i].szDescription, MAX_DB_STRING);
867 (*ppParamList)[i].iDataType = (int)pResponce->GetVariableShort(dwId++);
868 }
869 }
870 delete pResponce;
871 }
872 else
873 {
874 dwResult = ERR_REQUEST_TIMEOUT;
875 }
876 }
877 else
878 {
879 dwResult = ERR_CONNECTION_BROKEN;
880 }
881
882 return dwResult;
883 }