1 /*
2 * File: utilities.c
3 * Copyright: (c) 2006 by Peter Gritsch
4 * Email: s4nag@no-where.at
5 *
6 * This file is part of SNMP4Nagios.
7 *
8 * SNMP4Nagios is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or (at
11 * your option) any later version.
12 *
13 * SNMP4Nagios is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with SNMP4Nagios; if not, write to the
20 *
21 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
22 * MA 02110-1301, USA
23 */
24
25 #if HAVE_CONFIG_H
26 #include <config.h>
27 #endif
28
29 #include <errno.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include "globals.h"
34 #include "nagiosif.h"
35 #include "snmpif.h"
36 #include "strutils.h"
37
38
HelpCopyright()39 void HelpCopyright ()
40 {
41 printf ( "%s %s (SNMP4Nagios %s)\n", progName, progVersion, VERSION );
42 printf (
43 "\n"
44 "Copyright (c) 2006 Peter Gritsch\n"
45 "SNMP4Nagios is free software; you can redistribute it and/or modify\n"
46 "it under the terms of the GNU General Public License. See the file\n"
47 "COPYING for more details.\n"
48 "\n"
49 );
50 }
51
HelpUsage()52 void HelpUsage ()
53 {
54 if ( helpIndexP == NULL )
55 printf ( "Usage: %s\n", progName );
56 else printf ( "Usage: %s %s\n", progName, helpIndexP );
57 if ( helpThresP == NULL ) printf ( " [-S] [-T]" );
58 else printf ( " [-S] [-T %s ]", helpThresP );
59 #if(WITH_RRD)
60 if ( supportsPerfLog ) printf ( " [-L] [-P]" );
61 #endif /* WITH_RRD */
62 printf ( " [-V] [-h]\n" );
63 printf ( " [-H HOST] [-A ADDRESS] [-C COMMUNITY|-F COMMFILE]\n" );
64 printf ( " [-v] [-1|-2] [-r RETRIES] [-t TIMEOUT ]\n" );
65 #if(WITH_RRD)
66 if ( supportsPerfLog ) printf ( " [-R RRDDIR] [-G GRAPHDIR]\n" );
67 #endif /* WITH_RRD */
68 }
69
HelpModesStd()70 void HelpModesStd ()
71 {
72 printf (
73 "Modes:\n"
74 "\n"
75 "-S, --scan\n"
76 " Scan the host for services. This disables all other modes.\n"
77 "\n"
78 "-T, --test\n"
79 " Check the service.\n"
80 "\n"
81 );
82 }
83
84 #if(WITH_RRD)
HelpModesPerflog()85 void HelpModesPerflog ()
86 {
87 printf (
88 "-L, --log\n"
89 " Log performance data. If -T is given, then the data is passed\n"
90 " internally from the check otherwise it is read from the\n"
91 " environment.\n"
92 "\n"
93 "-P, --plot\n"
94 " Create plots.\n"
95 "\n"
96 );
97 }
98 #endif /* WITH_RRD */
99
HelpModesOther()100 void HelpModesOther ()
101 {
102 printf (
103 "-V, --version\n"
104 " Print version and exit.\n"
105 "\n"
106 "-h, --help\n"
107 " This help.\n"
108 "\n"
109 );
110 }
111
HelpGeneral()112 void HelpGeneral ()
113 {
114 printf (
115 "General options:\n"
116 "\n"
117 "-H, --host HOSTNAME\n"
118 " Name of the host which should be be checked. This defaults to the\n"
119 " contents of the environment variable $NAGIOS_HOSTNAME and is\n"
120 " needed for logging and plotting.\n"
121 "\n"
122 "-A, --address BYTE.BYTE.BYTE.BYTE\n"
123 " IP Address of the host which should be checkded. This defaults to\n"
124 " the contents of the environment variable $NAGIOS_HOSTADDRESS and\n"
125 " is preferred for setting up SNMP connections.\n"
126 "\n"
127 );
128 printf (
129 "-v, --verbose\n"
130 " Increase verbosity. This can be given several times but there may\n"
131 " simply be nothing more to say. Note also that messages are written\n"
132 " to syslog and that you might need to use three '-v's to see\n"
133 " anything.\n"
134 "\n"
135 );
136 printf (
137 "-N, --nagios-plugins-format\n"
138 " Use the alternative 'Nagios Plugins' performance data format.\n"
139 "\n"
140 );
141 }
142
HelpSNMP()143 void HelpSNMP ()
144 {
145 printf (
146 "SNMP Options:\n"
147 "\n"
148 "-1, --snmp-v1\n"
149 " Use the SNMP protocol version 1.\n"
150 "\n"
151 "-2, --snmp-v2c\n"
152 " Use the SNMP protocol version 2c (default).\n"
153 "\n"
154 "-C, --community STRING\n"
155 " Use the community STRING.\n"
156 "\n"
157 "-F, --community-file FILENAME\n"
158 " Read the SNMP community string from FILENAME.\n"
159 "\n"
160 "-r, --retries INTEGER\n"
161 " Number of times to retry a request. Note that net-snmp uses\n"
162 " increasing timeouts for retries.\n"
163 "\n"
164 "-t, --snmp-timeout INTEGER\n"
165 " Timeout for the first SNMP request in milliseconds.\n"
166 "\n"
167 );
168 printf (
169 "If a community string is provided (-C) then it is used. Else if a\n"
170 "community file is provided, then the community is read from it.\n"
171 "Per default the program tries to read the community string from the\n"
172 "files $HOME/.snmp4nagios/community, <home>/.snmp4nagios/community\n"
173 "(where <home> is read from /etc/passwd) and /etc/snmp4nagios/community.\n"
174 "The first file that can be read is used. If no community is given, then\n"
175 "the program will use the community 'public'.\n"
176 "\n"
177 );
178 }
179
180 #if(WITH_RRD)
HelpOptionsLogPlot()181 void HelpOptionsLogPlot ()
182 {
183 printf (
184 "Logging and plotting options:\n"
185 "\n"
186 "-R, --rrd-directory DIRNAME\n"
187 " RRD archives' base directory. The filename of the archive is build\n"
188 " by appending the hostname, the check's name and -- depending on the\n"
189 " service -- other information to DIRNAME. If this option is not\n"
190 " given, then the compiled in default is used.\n"
191 "\n"
192 );
193 printf (
194 "-G, --graph-directory DIRNAME\n"
195 " PNG plots' base directory. The filename of the plots is build by\n"
196 " appending the hostname, the check's name and -- depending on the\n"
197 " service -- other information to DIRNAME. If this option is not\n"
198 " given, then the compiled in default is used.\n"
199 "\n"
200 );
201 if ( hasAddInfParam )
202 {
203 printf (
204 "-I, --additional-info ADDINF\n"
205 " Additional info used to find the RRD archive and image pathes.\n"
206 "\n"
207 );
208 }
209 }
210 #endif /* WITH_RRD */
211
Version()212 void Version ()
213 {
214 HelpCopyright ();
215 exit ( STATE_OK );
216 }
217
Usage(char * aMsg)218 void Usage ( char* aMsg )
219 {
220 printf ( "Usage error: %s\n", aMsg );
221 HelpUsage ();
222 exit ( STATE_UNKNOWN );
223 }
224
Help()225 void Help ()
226 {
227 HelpCopyright ();
228 printf ( "%s\n", helpPurpose );
229 printf ( "\n" );
230 HelpUsage ();
231 printf ( "\n" );
232 HelpModesStd ();
233 #if(WITH_RRD)
234 if ( supportsPerfLog ) HelpModesPerflog ();
235 #endif /* WITH_RRD */
236 HelpModesOther ();
237 HelpGeneral ();
238 HelpSNMP ();
239 #if(WITH_RRD)
240 if ( supportsPerfLog ) HelpOptionsLogPlot ();
241 #endif /* WITH_RRD */
242 printf ( "Plugin-specific parameters:\n" );
243 printf ( "\n" );
244 HelpSpecificParams ();
245 HelpExplain ();
246 if ( supportsPerfLog ) HelpPerformanceData ();
247 exit ( STATE_OK );
248 }
249
ChkOptModesStd(int argc,char ** argv,int * i)250 int ChkOptModesStd ( int argc, char** argv, int* i )
251 {
252 int ret = TRUE;
253
254 if ( !strcmp ( argv [(*i)], "-S" )
255 || !strcmp ( argv [(*i)], "--scan" ) )
256 {
257 scanServices = TRUE;
258 (*i)++;
259 } else if ( !strcmp ( argv [(*i)], "-T" )
260 || !strcmp ( argv [(*i)], "--test" ) )
261 {
262 checkData = TRUE;
263 (*i)++;
264 } else ret = FALSE;
265 return ( ret );
266 }
267
268 #if(WITH_RRD)
ChkOptModesPerflog(int argc,char ** argv,int * i)269 int ChkOptModesPerflog ( int argc, char** argv, int* i )
270 {
271 int ret = TRUE;
272
273 if ( !strcmp ( argv [(*i)], "-L" )
274 || !strcmp ( argv [(*i)], "--log" ) )
275 {
276 logPerfData = TRUE;
277 (*i)++;
278 } else if ( !strcmp ( argv [(*i)], "-P" )
279 || !strcmp ( argv [(*i)], "--plot" ) )
280 {
281 plotPerfData = TRUE;
282 (*i)++;
283 } else ret = FALSE;
284 return ( ret );
285 }
286 #endif /* WITH_RRD */
287
ChkOptModesOther(int argc,char ** argv,int * i)288 int ChkOptModesOther ( int argc, char** argv, int* i )
289 {
290 int ret = TRUE;
291
292 if ( !strcmp ( argv [(*i)], "-V" )
293 || !strcmp ( argv [(*i)], "--version" ) )
294 {
295 Version ();
296 } else if ( !strcmp ( argv [(*i)], "-h" )
297 || !strcmp ( argv [(*i)], "--help" ) )
298 {
299 Help ();
300 } else ret = FALSE;
301 return ( ret );
302 }
303
ChkOptGeneral(int argc,char ** argv,int * i)304 int ChkOptGeneral ( int argc, char** argv, int* i )
305 {
306 int ret = TRUE;
307
308 if ( !strcmp ( argv [(*i)], "-H" )
309 || !strcmp ( argv [(*i)], "--host" ) )
310 {
311 isHostNameSet = TRUE;
312 (*i)++;
313 if ( (*i) < argc ) hostName = StrDup ( argv [(*i)++] );
314 else Usage ( "Missing 'host' parameter" );
315 } else if ( !strcmp ( argv [(*i)], "-A" )
316 || !strcmp ( argv [(*i)], "--address" ) )
317 {
318 isHostAddrSet = TRUE;
319 (*i)++;
320 if ( (*i) < argc ) hostAddr = StrDup ( argv [(*i)++] );
321 else Usage ( "Missing 'address' parameter" );
322 } else if ( !strcmp ( argv [(*i)], "-v" )
323 || !strcmp ( argv [(*i)], "--verbose" ) )
324 {
325 switch ( loggingLevel )
326 {
327 case LOG_EMERG:
328 case LOG_ALERT:
329 case LOG_CRIT:
330 case LOG_ERR:
331 loggingLevel = LOG_WARNING;
332 break;
333 case LOG_WARNING:
334 loggingLevel = LOG_NOTICE;
335 break;
336 case LOG_NOTICE:
337 loggingLevel = LOG_DEBUG;
338 break;
339 case LOG_INFO:
340 case LOG_DEBUG:
341 break;
342 default:
343 loggingLevel = LOG_ERR;
344 break;
345 }
346 (*i)++;
347 } else if ( !strcmp ( argv [(*i)], "-N" )
348 || !strcmp ( argv [(*i)], "--nagios-plugins-format" ) )
349 {
350 npPerfData = TRUE;
351 (*i)++;
352 } else ret = FALSE;
353 return ( ret );
354 }
355
ChkOptSNMP(int argc,char ** argv,int * i)356 int ChkOptSNMP ( int argc, char** argv, int* i )
357 {
358 int ret = TRUE;
359
360 if ( !strcmp ( argv [(*i)], "-1" )
361 || !strcmp ( argv [(*i)], "--snmp-v1" ) )
362 {
363 snmpVersion = SNMP_VERSION_1;
364 (*i)++;
365 } else if ( !strcmp ( argv [(*i)], "-2" )
366 || !strcmp ( argv [(*i)], "--snmp-v2c" ) )
367 {
368 snmpVersion = SNMP_VERSION_2c;
369 (*i)++;
370 } else if ( !strcmp ( argv [(*i)], "-C" )
371 || !strcmp ( argv [(*i)], "--community" ) )
372 {
373 (*i)++;
374 if ( (*i) < argc ) community = argv [(*i)++];
375 else Usage ( "Missing 'community' parameter" );
376 } else if ( !strcmp ( argv [(*i)], "-F" )
377 || !strcmp ( argv [(*i)], "--community-file" ) )
378 {
379 (*i)++;
380 if ( (*i) < argc ) commFile = argv [(*i)++];
381 else Usage ( "Missing 'community file' parameter" );
382 } else if ( !strcmp ( argv [(*i)], "-r" )
383 || !strcmp ( argv [(*i)], "--retries" ) )
384 {
385 (*i)++;
386 if ( (*i) < argc )
387 {
388 char *tail = argv [(*i)];
389 errno = 0;
390 snmpRetries = strtoul ( argv [(*i)++], &tail, 0 );
391 if ( errno || *tail )
392 Usage ( "Invalid 'retries' parameter" );
393 }
394 else Usage ( "Missing 'retries' parameter" );
395 } else if ( !strcmp ( argv [(*i)], "-t" )
396 || !strcmp ( argv [(*i)], "--snmp-timeout" ) )
397 {
398 (*i)++;
399 if ( (*i) < argc )
400 {
401 char *tail = argv [(*i)];
402 errno = 0;
403 snmpTimeOut = 1000 * strtoul ( argv [(*i)++], &tail, 0 );
404 if ( errno || *tail )
405 Usage ( "Invalid 'SNMP timeout' parameter" );
406 }
407 else Usage ( "Missing 'SNMP timeout' parameter" );
408 } else ret = FALSE;
409 return ( ret );
410 }
411
412 #if(WITH_RRD)
ChkOptLogPlot(int argc,char ** argv,int * i)413 int ChkOptLogPlot ( int argc, char** argv, int* i )
414 {
415 int ret = TRUE;
416
417 if ( !strcmp ( argv [(*i)], "-R" )
418 || !strcmp ( argv [(*i)], "--rrd-directory" ) )
419 {
420 (*i)++;
421 if ( (*i) < argc )
422 {
423 rrdDir = argv [(*i)++];
424 } else
425 {
426 Usage ( "Missing 'rrd-directory' parameter" );
427 }
428 } else if ( !strcmp ( argv [(*i)], "-G" )
429 || !strcmp ( argv [(*i)], "--graph-directory" ) )
430 {
431 (*i)++;
432 if ( (*i) < argc )
433 {
434 pngDir = argv [(*i)++];
435 } else
436 {
437 Usage ( "Missing 'graph-directory' parameter" );
438 }
439 } else ret = FALSE;
440 return ( ret );
441 }
442 #endif /* WITH_RRD */
443
ChkOptAddInf(int argc,char ** argv,int * i)444 int ChkOptAddInf ( int argc, char** argv, int* i )
445 {
446 int ret = TRUE;
447
448 if ( !strcmp ( argv [(*i)], "-I" )
449 || !strcmp ( argv [(*i)], "--additional-info" ) )
450 {
451 (*i)++;
452 if ( (*i) < argc )
453 {
454 addInf = argv [(*i)++];
455 isAddInfSet = TRUE;
456 } else
457 {
458 Usage ( "Missing 'graph-directory' parameter" );
459 }
460 } else ret = FALSE;
461 return ( ret );
462 }
463
ChkOptIndex(int argc,char ** argv,int * i)464 int ChkOptIndex ( int argc, char** argv, int* i )
465 {
466 int ret = TRUE;
467
468 if ( !strcmp ( argv [(*i)], "-i" )
469 || !strcmp ( argv [(*i)], "--index" ) )
470 {
471 isIdxSet = TRUE;
472 (*i)++;
473 if ( (*i) < argc )
474 {
475 char *tail = argv [(*i)];
476
477 errno = 0;
478 idx = strtoul ( argv [(*i)++], &tail, 0 );
479 if ( errno || *tail ) Usage ( "Invalid 'index' parameter" );
480 }
481 else Usage ( "Missing 'index' parameter" );
482 } else ret = FALSE;
483 return ( ret );
484 }
485
ReadArgs(int argc,char ** argv)486 void ReadArgs ( int argc, char** argv )
487 {
488 int i = 0;
489
490 ReadHostName ();
491 ReadHostAddr ();
492 progName = Basename ( argv [i++] );
493 while ( i < argc )
494 {
495 /*
496 * Note the semicolons at the end of the lines. IOW: Do nothing if the
497 * function returns TRUE.
498 */
499 if ( ChkOptModesStd ( argc, argv, &i ) );
500 #if(WITH_RRD)
501 else if ( supportsPerfLog && ChkOptModesPerflog ( argc, argv, &i ) );
502 #endif /* WITH_RRD */
503 else if ( ChkOptModesOther ( argc, argv, &i ) );
504 else if ( ChkOptGeneral ( argc, argv, &i ) );
505 else if ( ChkOptSNMP ( argc, argv, &i ) );
506 #if(WITH_RRD)
507 else if ( supportsPerfLog && ChkOptLogPlot ( argc, argv, &i ) );
508 #endif /* WITH_RRD */
509 else if ( hasAddInfParam && ChkOptAddInf ( argc, argv, &i ) );
510 else if ( hasIndexParam && ChkOptIndex ( argc, argv, &i ) );
511 else if ( ChkOptSpecificParams ( argc, argv, &i ) );
512 else
513 {
514 char msg[512] = "Unknown parameter: ";
515 strncat ( msg, argv [i], 256 );
516 Usage ( msg );
517 }
518 }
519 if ( checkData && hasIndexParam )
520 {
521 if ( !isIdxSet ) Usage ( "Missing 'index' parameters" );
522 }
523 if ( ( checkData
524 #if(WITH_RRD)
525 || logPerfData || plotPerfData
526 #endif /* WITH_RRD */
527 ) && hasAddInfParam )
528 {
529 if ( !isAddInfSet ) Usage ( "Missing 'addInf' parameters" );
530 }
531 #if(WITH_RRD)
532 if ( logPerfData || plotPerfData )
533 {
534 if ( !isHostNameSet ) Usage ( "'Missing 'host name' parameters" );
535 }
536 #endif /* WITH_RRD */
537 if ( !( isHostNameSet || isHostAddrSet ) )
538 {
539 Usage ( "Missing both 'host name' and 'host address' parameters" );
540 }
541 }
542