Initial version of crash dump generator on Windows
[public/netxms.git] / src / server / tools / nxget / nxget.cpp
1 /*
2 ** nxget - command line tool used to retrieve parameters from NetXMS agent
3 ** Copyright (C) 2004, 2005 Victor Kirhenshtein
4 **
5 ** This program is free software; you can redistribute it and/or modify
6 ** it under the terms of the GNU General Public License as published by
7 ** the Free Software Foundation; either version 2 of the License, or
8 ** (at your option) any later version.
9 **
10 ** This program is distributed in the hope that it will be useful,
11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ** GNU General Public License for more details.
14 **
15 ** You should have received a copy of the GNU General Public License
16 ** along with this program; if not, write to the Free Software
17 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 **
19 ** $module: nxget.cpp
20 **
21 **/
22
23 #include <nms_common.h>
24 #include <nms_agent.h>
25 #include <nms_util.h>
26 #include <nxclapi.h>
27 #include <nxsrvapi.h>
28
29 #ifndef _WIN32
30 #include <netdb.h>
31 #endif
32
33
34 //
35 // Constants
36 //
37
38 #define MAX_LINE_SIZE 4096
39
40 #define CMD_GET 0
41 #define CMD_LIST 1
42 #define CMD_CHECK_SERVICE 2
43 #define CMD_GET_PARAMS 3
44 #define CMD_GET_CONFIG 4
45
46
47 //
48 // Static data
49 //
50
51 static int m_iAuthMethod = AUTH_NONE;
52 static BOOL m_bVerbose = TRUE;
53
54
55 //
56 // Get single parameter
57 //
58
59 static int Get(AgentConnection *pConn, char *pszParam, BOOL bShowName)
60 {
61 DWORD dwError;
62 char szBuffer[1024];
63
64 dwError = pConn->GetParameter(pszParam, 1024, szBuffer);
65 if (dwError == ERR_SUCCESS)
66 {
67 if (bShowName)
68 printf("%s = %s\n", pszParam, szBuffer);
69 else
70 printf("%s\n", szBuffer);
71 }
72 else
73 {
74 printf("%d: %s\n", dwError, AgentErrorCodeToText(dwError));
75 }
76 return (dwError == ERR_SUCCESS) ? 0 : 1;
77 }
78
79
80 //
81 // Get list of values for enum parameters
82 //
83
84 static int List(AgentConnection *pConn, char *pszParam)
85 {
86 DWORD i, dwNumLines, dwError;
87
88 dwError = pConn->GetList(pszParam);
89 if (dwError == ERR_SUCCESS)
90 {
91 dwNumLines = pConn->GetNumDataLines();
92 for(i = 0; i < dwNumLines; i++)
93 printf("%s\n", pConn->GetDataLine(i));
94 }
95 else
96 {
97 printf("%d: %s\n", dwError, AgentErrorCodeToText(dwError));
98 }
99 return (dwError == ERR_SUCCESS) ? 0 : 1;
100 }
101
102
103 //
104 // Check network service state
105 //
106
107 static int CheckService(AgentConnection *pConn, int iServiceType, DWORD dwServiceAddr,
108 WORD wProto, WORD wPort, char *pszRequest, char *pszResponse)
109 {
110 DWORD dwStatus, dwError;
111
112 dwError = pConn->CheckNetworkService(&dwStatus, dwServiceAddr, iServiceType, wPort,
113 wProto, pszRequest, pszResponse);
114 if (dwError == ERR_SUCCESS)
115 {
116 printf("Service status: %d\n", dwStatus);
117 }
118 else
119 {
120 printf("%d: %s\n", dwError, AgentErrorCodeToText(dwError));
121 }
122 return (dwError == ERR_SUCCESS) ? 0 : 1;
123 }
124
125
126 //
127 // List supported parameters
128 //
129
130 static int ListParameters(AgentConnection *pConn)
131 {
132 DWORD i, dwNumParams, dwError;
133 NXC_AGENT_PARAM *pParamList;
134 static char *pszDataType[] = { "INT", "UINT", "INT64", "UINT64", "STRING", "FLOAT", "UNKNOWN" };
135
136 dwError = pConn->GetSupportedParameters(&dwNumParams, &pParamList);
137 if (dwError == ERR_SUCCESS)
138 {
139 for(i = 0; i < dwNumParams; i++)
140 {
141 printf("%s %s \"%s\"\n", pParamList[i].szName,
142 pszDataType[(pParamList[i].iDataType < 6) && (pParamList[i].iDataType >= 0) ? pParamList[i].iDataType : 6],
143 pParamList[i].szDescription);
144 }
145 safe_free(pParamList);
146 }
147 else
148 {
149 printf("%d: %s\n", dwError, AgentErrorCodeToText(dwError));
150 }
151 return (dwError == ERR_SUCCESS) ? 0 : 1;
152 }
153
154
155 //
156 // Get configuration file
157 //
158
159 static int GetConfig(AgentConnection *pConn)
160 {
161 DWORD dwError, dwSize;
162 TCHAR *pszFile;
163
164 dwError = pConn->GetConfigFile(&pszFile, &dwSize);
165 if (dwError == ERR_SUCCESS)
166 {
167 TranslateStr(pszFile, "\r\n", "\n");
168 fputs(pszFile, stdout);
169 if (dwSize > 0)
170 {
171 if (pszFile[dwSize - 1] != '\n')
172 fputc('\n', stdout);
173 }
174 else
175 {
176 fputc('\n', stdout);
177 }
178 }
179 else
180 {
181 printf("%d: %s\n", dwError, AgentErrorCodeToText(dwError));
182 }
183 return (dwError == ERR_SUCCESS) ? 0 : 1;
184 }
185
186
187 //
188 // Startup
189 //
190
191 int main(int argc, char *argv[])
192 {
193 char *eptr;
194 BOOL bStart = TRUE, bBatchMode = FALSE, bShowNames = FALSE, bUseProxy = FALSE;
195 int i, ch, iPos, iExitCode = 3, iCommand = CMD_GET, iInterval = 0;
196 int iAuthMethod = AUTH_NONE, iProxyAuth = AUTH_NONE, iServiceType = NETSRV_SSH;
197 #ifdef _WITH_ENCRYPTION
198 int iEncryptionPolicy = ENCRYPTION_ALLOWED;
199 #else
200 int iEncryptionPolicy = ENCRYPTION_DISABLED;
201 #endif
202 WORD wAgentPort = AGENT_LISTEN_PORT, wProxyPort = AGENT_LISTEN_PORT;
203 WORD wServicePort = 0, wServiceProto = 0;
204 DWORD dwTimeout = 3000, dwServiceAddr = 0, dwError, dwAddr, dwProxyAddr;
205 char szSecret[MAX_SECRET_LENGTH] = "", szRequest[MAX_DB_STRING] = "";
206 char szKeyFile[MAX_PATH] = DEFAULT_DATA_DIR DFILE_KEYS, szResponse[MAX_DB_STRING] = "";
207 char szProxy[MAX_OBJECT_NAME] = "", szProxySecret[MAX_SECRET_LENGTH] = "";
208 RSA *pServerKey = NULL;
209
210 InitThreadLibrary();
211 #ifdef _WIN32
212 SetExceptionHandler(SEHDefaultConsoleHandler, NULL);
213 #endif
214
215 // Parse command line
216 opterr = 1;
217 while((ch = getopt(argc, argv, "a:A:bCe:hi:IK:lnO:p:P:qr:R:s:S:t:vw:X:Z:")) != -1)
218 {
219 switch(ch)
220 {
221 case 'h': // Display help and exit
222 printf("Usage: nxget [<options>] <host> [<parameter> [<parameter> ...]]\n"
223 "Valid options are:\n"
224 " -a <auth> : Authentication method. Valid methods are \"none\",\n"
225 " \"plain\", \"md5\" and \"sha1\". Default is \"none\".\n"
226 " -A <auth> : Authentication method for proxy agent.\n"
227 " -b : Batch mode - get all parameters listed on command line.\n"
228 " -C : Get agent's configuration file\n"
229 #ifdef _WITH_ENCRYPTION
230 " -e <policy> : Set encryption policy. Possible values are:\n"
231 " 0 = Encryption disabled;\n"
232 " 1 = Encrypt connection only if agent requires encryption;\n"
233 " 2 = Encrypt connection if agent supports encryption;\n"
234 " 3 = Force encrypted connection;\n"
235 " Default value is 1.\n"
236 #endif
237 " -h : Display help and exit.\n"
238 " -i <seconds> : Get specified parameter(s) continously with given interval.\n"
239 " -I : Get list of supported parameters.\n"
240 #ifdef _WITH_ENCRYPTION
241 " -K <file> : Specify server's key file\n"
242 " (default is " DEFAULT_DATA_DIR DFILE_KEYS ").\n"
243 #endif
244 " -l : Get list of values for enum parameter.\n"
245 " -n : Show parameter's name in result.\n"
246 " -O <port> : Proxy agent's port number. Default is %d.\n"
247 " -p <port> : Agent's port number. Default is %d.\n"
248 " -P <port> : Network service port (to be used wth -S option).\n"
249 " -q : Quiet mode.\n"
250 " -r <string> : Service check request string.\n"
251 " -R <string> : Service check expected response string.\n"
252 " -s <secret> : Shared secret for authentication.\n"
253 " -S <addr> : Check state of network service at given address.\n"
254 " -t <type> : Set type of service to be checked.\n"
255 " -T <proto> : Protocol number to be used for service check.\n"
256 " -v : Display version and exit.\n"
257 " -w <seconds> : Specify command timeout (default is 3 seconds).\n"
258 " -X <addr> : Use proxy agent at given address.\n"
259 " -Z <secret> : Shared secret for proxy agent authentication.\n"
260 "\n", wAgentPort, wAgentPort);
261 bStart = FALSE;
262 break;
263 case 'a': // Auth method
264 case 'A':
265 if (!strcmp(optarg, "none"))
266 i = AUTH_NONE;
267 else if (!strcmp(optarg, "plain"))
268 i = AUTH_PLAINTEXT;
269 else if (!strcmp(optarg, "md5"))
270 i = AUTH_MD5_HASH;
271 else if (!strcmp(optarg, "sha1"))
272 i = AUTH_SHA1_HASH;
273 else
274 {
275 printf("Invalid authentication method \"%s\"\n", optarg);
276 bStart = FALSE;
277 }
278 if (ch == 'a')
279 iAuthMethod = i;
280 else
281 iProxyAuth = i;
282 break;
283 case 'b': // Batch mode
284 bBatchMode = TRUE;
285 break;
286 case 'i': // Interval
287 i = strtol(optarg, &eptr, 0);
288 if ((*eptr != 0) || (i <= 0))
289 {
290 printf("Invalid interval \"%s\"\n", optarg);
291 bStart = FALSE;
292 }
293 else
294 {
295 iInterval = i;
296 }
297 break;
298 case 'I':
299 iCommand = CMD_GET_PARAMS;
300 break;
301 case 'C':
302 iCommand = CMD_GET_CONFIG;
303 break;
304 case 'l':
305 iCommand = CMD_LIST;
306 break;
307 case 'n': // Show names
308 bShowNames = TRUE;
309 break;
310 case 'p': // Agent's port number
311 case 'P': // Port number for service check
312 case 'O': // Proxy agent's port number
313 i = strtol(optarg, &eptr, 0);
314 if ((*eptr != 0) || (i < 0) || (i > 65535))
315 {
316 printf("Invalid port number \"%s\"\n", optarg);
317 bStart = FALSE;
318 }
319 else
320 {
321 if (ch == 'p')
322 wAgentPort = (WORD)i;
323 else if (ch == 'O')
324 wProxyPort = (WORD)i;
325 else
326 wServicePort = (WORD)i;
327 }
328 break;
329 case 'q': // Quiet mode
330 m_bVerbose = FALSE;
331 break;
332 case 'r': // Service check request string
333 nx_strncpy(szRequest, optarg, MAX_DB_STRING);
334 break;
335 case 'R': // Service check response string
336 nx_strncpy(szResponse, optarg, MAX_DB_STRING);
337 break;
338 case 's': // Shared secret
339 nx_strncpy(szSecret, optarg, MAX_SECRET_LENGTH);
340 break;
341 case 'S': // Check service
342 iCommand = CMD_CHECK_SERVICE;
343 dwServiceAddr = ntohl(inet_addr(optarg));
344 if ((dwServiceAddr == INADDR_NONE) || (dwServiceAddr == INADDR_ANY))
345 {
346 printf("Invalid IP address \"%s\"\n", optarg);
347 bStart = FALSE;
348 }
349 break;
350 case 't': // Service type
351 iServiceType = strtol(optarg, &eptr, 0);
352 if (*eptr != 0)
353 {
354 printf("Invalid service type \"%s\"\n", optarg);
355 bStart = FALSE;
356 }
357 break;
358 case 'T': // Protocol number for service check
359 i = strtol(optarg, &eptr, 0);
360 if ((*eptr != 0) || (i < 0) || (i > 65535))
361 {
362 printf("Invalid protocol number \"%s\"\n", optarg);
363 bStart = FALSE;
364 }
365 else
366 {
367 wServiceProto = (WORD)i;
368 }
369 break;
370 case 'v': // Print version and exit
371 printf("NetXMS GET command-line utility Version " NETXMS_VERSION_STRING "\n");
372 bStart = FALSE;
373 break;
374 case 'w': // Command timeout
375 i = strtol(optarg, &eptr, 0);
376 if ((*eptr != 0) || (i < 1) || (i > 120))
377 {
378 printf("Invalid timeout \"%s\"\n", optarg);
379 bStart = FALSE;
380 }
381 else
382 {
383 dwTimeout = (DWORD)i * 1000; // Convert to milliseconds
384 }
385 break;
386 #ifdef _WITH_ENCRYPTION
387 case 'e':
388 iEncryptionPolicy = atoi(optarg);
389 if ((iEncryptionPolicy < 0) ||
390 (iEncryptionPolicy > 3))
391 {
392 printf("Invalid encryption policy %d\n", iEncryptionPolicy);
393 bStart = FALSE;
394 }
395 break;
396 case 'K':
397 nx_strncpy(szKeyFile, optarg, MAX_PATH);
398 break;
399 #else
400 case 'e':
401 case 'K':
402 printf("ERROR: This tool was compiled without encryption support\n");
403 bStart = FALSE;
404 break;
405 #endif
406 case 'X': // Use proxy
407 strncpy(szProxy, optarg, MAX_OBJECT_NAME);
408 bUseProxy = TRUE;
409 break;
410 case 'Z': // Shared secret for proxy agent
411 nx_strncpy(szProxySecret, optarg, MAX_SECRET_LENGTH);
412 break;
413 case '?':
414 bStart = FALSE;
415 break;
416 default:
417 break;
418 }
419 }
420
421 // Check parameter correctness
422 if (bStart)
423 {
424 if (argc - optind < (((iCommand == CMD_CHECK_SERVICE) || (iCommand == CMD_GET_PARAMS) || (iCommand == CMD_GET_CONFIG)) ? 1 : 2))
425 {
426 printf("Required argument(s) missing.\nUse nxget -h to get complete command line syntax.\n");
427 bStart = FALSE;
428 }
429 else if ((iAuthMethod != AUTH_NONE) && (szSecret[0] == 0))
430 {
431 printf("Shared secret not specified or empty\n");
432 bStart = FALSE;
433 }
434
435 // Load server key if requested
436 #ifdef _WITH_ENCRYPTION
437 if ((iEncryptionPolicy != ENCRYPTION_DISABLED) && bStart)
438 {
439 if (InitCryptoLib(0xFFFF))
440 {
441 pServerKey = LoadRSAKeys(szKeyFile);
442 if (pServerKey == NULL)
443 {
444 printf("Error loading RSA keys from \"%s\"\n", szKeyFile);
445 if (iEncryptionPolicy == ENCRYPTION_REQUIRED)
446 bStart = FALSE;
447 }
448 }
449 else
450 {
451 printf("Error initializing cryptografy module\n");
452 if (iEncryptionPolicy == ENCRYPTION_REQUIRED)
453 bStart = FALSE;
454 }
455 }
456 #endif
457
458 // If everything is ok, start communications
459 if (bStart)
460 {
461 // Initialize WinSock
462 #ifdef _WIN32
463 WSADATA wsaData;
464 WSAStartup(2, &wsaData);
465 #endif
466 dwAddr = ResolveHostName(argv[optind]);
467 if (bUseProxy)
468 dwProxyAddr = ResolveHostName(szProxy);
469 if ((dwAddr == INADDR_ANY) || (dwAddr == INADDR_NONE))
470 {
471 fprintf(stderr, "Invalid host name or address \"%s\"\n", argv[optind]);
472 }
473 else if (bUseProxy && ((dwProxyAddr == INADDR_ANY) || (dwProxyAddr == INADDR_NONE)))
474 {
475 fprintf(stderr, "Invalid host name or address \"%s\"\n", szProxy);
476 }
477 else
478 {
479 AgentConnection conn(dwAddr, wAgentPort, iAuthMethod, szSecret);
480
481 conn.SetCommandTimeout(dwTimeout);
482 conn.SetEncryptionPolicy(iEncryptionPolicy);
483 if (bUseProxy)
484 conn.SetProxy(dwProxyAddr, wProxyPort, iProxyAuth, szProxySecret);
485 if (conn.Connect(pServerKey, m_bVerbose, &dwError))
486 {
487 do
488 {
489 switch(iCommand)
490 {
491 case CMD_GET:
492 iPos = optind + 1;
493 do
494 {
495 iExitCode = Get(&conn, argv[iPos++], bShowNames);
496 } while((iExitCode == 0) && (bBatchMode) && (iPos < argc));
497 break;
498 case CMD_LIST:
499 iExitCode = List(&conn, argv[optind + 1]);
500 break;
501 case CMD_CHECK_SERVICE:
502 iExitCode = CheckService(&conn, iServiceType, dwServiceAddr,
503 wServiceProto, wServicePort, szRequest, szResponse);
504 break;
505 case CMD_GET_PARAMS:
506 iExitCode = ListParameters(&conn);
507 break;
508 case CMD_GET_CONFIG:
509 iExitCode = GetConfig(&conn);
510 break;
511 default:
512 break;
513 }
514 ThreadSleep(iInterval);
515 }
516 while(iInterval > 0);
517 conn.Disconnect();
518 }
519 else
520 {
521 printf("%d: %s\n", dwError, AgentErrorCodeToText(dwError));
522 iExitCode = 2;
523 }
524 }
525 }
526 }
527
528 return iExitCode;
529 }