1 /******************************************************************************
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2 of the License, or
6 (at your option) any later version.
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 $Id$
19 ******************************************************************************/
21 const char *progname = "check_mrtg";
22 const char *revision = "$Revision$";
23 const char *copyright = "1999-2004";
24 const char *email = "nagiosplug-devel@lists.sourceforge.net";
26 #include "common.h"
27 #include "utils.h"
29 int process_arguments (int, char **);
30 int validate_arguments (void);
31 void print_help (void);
32 void print_usage (void);
34 char *log_file = NULL;
35 int expire_minutes = 0;
36 int use_average = TRUE;
37 int variable_number = -1;
38 unsigned long value_warning_threshold = 0L;
39 unsigned long value_critical_threshold = 0L;
40 char *label;
41 char *units;
43 int
44 main (int argc, char **argv)
45 {
46 int result = STATE_UNKNOWN;
47 FILE *fp;
48 int line;
49 char input_buffer[MAX_INPUT_BUFFER];
50 char *temp_buffer;
51 time_t current_time;
52 char* message;
53 time_t timestamp = 0L;
54 unsigned long average_value_rate = 0L;
55 unsigned long maximum_value_rate = 0L;
56 unsigned long rate = 0L;
58 setlocale (LC_ALL, "");
59 bindtextdomain (PACKAGE, LOCALEDIR);
60 textdomain (PACKAGE);
62 if (process_arguments (argc, argv) == ERROR)
63 usage4 (_("Could not parse arguments\n"));
65 /* open the MRTG log file for reading */
66 fp = fopen (log_file, "r");
67 if (fp == NULL) {
68 printf (_("Unable to open MRTG log file\n"));
69 return STATE_UNKNOWN;
70 }
72 line = 0;
73 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, fp)) {
75 line++;
77 /* skip the first line of the log file */
78 if (line == 1)
79 continue;
81 /* break out of read loop if we've passed the number of entries we want to read */
82 if (line > 2)
83 break;
85 /* grab the timestamp */
86 temp_buffer = strtok (input_buffer, " ");
87 timestamp = strtoul (temp_buffer, NULL, 10);
89 /* grab the average value 1 rate */
90 temp_buffer = strtok (NULL, " ");
91 if (variable_number == 1)
92 average_value_rate = strtoul (temp_buffer, NULL, 10);
94 /* grab the average value 2 rate */
95 temp_buffer = strtok (NULL, " ");
96 if (variable_number == 2)
97 average_value_rate = strtoul (temp_buffer, NULL, 10);
99 /* grab the maximum value 1 rate */
100 temp_buffer = strtok (NULL, " ");
101 if (variable_number == 1)
102 maximum_value_rate = strtoul (temp_buffer, NULL, 10);
104 /* grab the maximum value 2 rate */
105 temp_buffer = strtok (NULL, " ");
106 if (variable_number == 2)
107 maximum_value_rate = strtoul (temp_buffer, NULL, 10);
108 }
110 /* close the log file */
111 fclose (fp);
113 /* if we couldn't read enough data, return an unknown error */
114 if (line <= 2) {
115 result = STATE_UNKNOWN;
116 asprintf (&message, _("Unable to process MRTG log file\n"));
117 }
119 /* make sure the MRTG data isn't too old */
120 if (result == STATE_OK) {
121 time (¤t_time);
122 if (expire_minutes > 0
123 && (current_time - timestamp) > (expire_minutes * 60)) {
124 result = STATE_WARNING;
125 asprintf (&message, _("MRTG data has expired (%d minutes old)\n"),
126 (int) ((current_time - timestamp) / 60));
127 }
128 }
130 /* else check the incoming/outgoing rates */
131 if (result == STATE_OK) {
132 if (use_average == TRUE)
133 rate = average_value_rate;
134 else
135 rate = maximum_value_rate;
137 if (rate > value_critical_threshold)
138 result = STATE_CRITICAL;
139 else if (rate > value_warning_threshold)
140 result = STATE_WARNING;
142 asprintf (&message, "%s. %s = %lu %s|%s",
143 (use_average == TRUE) ? _("Avg") : _("Max"),
144 label, rate, units,
145 perfdata(label, (long) rate, units,
146 (int) value_warning_threshold, (long) value_warning_threshold,
147 (int) value_critical_threshold, (long) value_critical_threshold,
148 0, 0, 0, 0));
149 }
151 printf ("%s\n", message);
153 return result;
154 }
158 /* process command-line arguments */
159 int
160 process_arguments (int argc, char **argv)
161 {
162 int c;
164 int option = 0;
165 static struct option longopts[] = {
166 {"logfile", required_argument, 0, 'F'},
167 {"expires", required_argument, 0, 'e'},
168 {"aggregation", required_argument, 0, 'a'},
169 {"variable", required_argument, 0, 'v'},
170 {"critical", required_argument, 0, 'c'},
171 {"warning", required_argument, 0, 'w'},
172 {"label", required_argument, 0, 'l'},
173 {"units", required_argument, 0, 'u'},
174 {"verbose", no_argument, 0, 'v'},
175 {"version", no_argument, 0, 'V'},
176 {"help", no_argument, 0, 'h'},
177 {0, 0, 0, 0}
178 };
180 if (argc < 2)
181 return ERROR;
183 for (c = 1; c < argc; c++) {
184 if (strcmp ("-to", argv[c]) == 0)
185 strcpy (argv[c], "-t");
186 else if (strcmp ("-wt", argv[c]) == 0)
187 strcpy (argv[c], "-w");
188 else if (strcmp ("-ct", argv[c]) == 0)
189 strcpy (argv[c], "-c");
190 }
192 while (1) {
193 c = getopt_long (argc, argv, "hVF:e:a:v:c:w:l:u:", longopts,
194 &option);
196 if (c == -1 || c == EOF)
197 break;
199 switch (c) {
200 case 'F': /* input file */
201 log_file = optarg;
202 break;
203 case 'e': /* ups name */
204 expire_minutes = atoi (optarg);
205 break;
206 case 'a': /* port */
207 if (!strcmp (optarg, "MAX"))
208 use_average = FALSE;
209 else
210 use_average = TRUE;
211 break;
212 case 'v':
213 variable_number = atoi (optarg);
214 if (variable_number < 1 || variable_number > 2)
215 usage4 (_("Invalid variable number"));
216 break;
217 case 'w': /* critical time threshold */
218 value_warning_threshold = strtoul (optarg, NULL, 10);
219 break;
220 case 'c': /* warning time threshold */
221 value_critical_threshold = strtoul (optarg, NULL, 10);
222 break;
223 case 'l': /* label */
224 label = optarg;
225 break;
226 case 'u': /* timeout */
227 units = optarg;
228 break;
229 case 'V': /* version */
230 print_revision (progname, revision);
231 exit (STATE_OK);
232 case 'h': /* help */
233 print_help ();
234 exit (STATE_OK);
235 case '?': /* help */
236 printf (_("%s: Unknown argument: %s\n\n"), progname, optarg);
237 print_usage ();
238 exit (STATE_UNKNOWN);
239 }
240 }
242 c = optind;
243 if (log_file == NULL && argc > c) {
244 log_file = argv[c++];
245 }
247 if (expire_minutes <= 0 && argc > c) {
248 if (is_intpos (argv[c]))
249 expire_minutes = atoi (argv[c++]);
250 else
251 die (STATE_UNKNOWN,
252 _("%s is not a valid expiration time\nUse '%s -h' for additional help\n"),
253 argv[c], progname);
254 }
256 if (argc > c && strcmp (argv[c], "MAX") == 0) {
257 use_average = FALSE;
258 c++;
259 }
260 else if (argc > c && strcmp (argv[c], "AVG") == 0) {
261 use_average = TRUE;
262 c++;
263 }
265 if (argc > c && variable_number == -1) {
266 variable_number = atoi (argv[c++]);
267 if (variable_number < 1 || variable_number > 2) {
268 printf ("%s :", argv[c]);
269 usage (_("Invalid variable number\n"));
270 }
271 }
273 if (argc > c && value_warning_threshold == 0) {
274 value_warning_threshold = strtoul (argv[c++], NULL, 10);
275 }
277 if (argc > c && value_critical_threshold == 0) {
278 value_critical_threshold = strtoul (argv[c++], NULL, 10);
279 }
281 if (argc > c && strlen (label) == 0) {
282 label = argv[c++];
283 }
285 if (argc > c && strlen (units) == 0) {
286 units = argv[c++];
287 }
289 return validate_arguments ();
290 }
292 int
293 validate_arguments (void)
294 {
295 if (variable_number == -1)
296 usage4 (_("You must supply the variable number"));
298 if (label == NULL)
299 label = strdup ("value");
301 if (units == NULL)
302 units = strdup ("");
304 return OK;
305 }
309 void
310 print_help (void)
311 {
312 print_revision (progname, revision);
314 printf ("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n");
315 printf (COPYRIGHT, copyright, email);
317 printf(_("\
318 This plugin will check either the average or maximum value of one of the\n\
319 two variables recorded in an MRTG log file.\n\n"));
321 print_usage ();
323 printf (_(UT_HELP_VRSN));
325 printf (_("\
326 -F, --logfile=FILE\n\
327 The MRTG log file containing the data you want to monitor\n\
328 -e, --expires=MINUTES\n\
329 Minutes before MRTG data is considered to be too old\n\
330 -a, --aggregation=AVG|MAX\n\
331 Should we check average or maximum values?\n\
332 -v, --variable=INTEGER\n\
333 Which variable set should we inspect? (1 or 2)\n\
334 -w, --warning=INTEGER\n\
335 Threshold value for data to result in WARNING status\n\
336 -c, --critical=INTEGER\n\
337 Threshold value for data to result in CRITICAL status\n"));
339 printf (_("\
340 -l, --label=STRING\n\
341 Type label for data (Examples: Conns, \"Processor Load\", In, Out)\n\
342 -u, --units=STRING\n\
343 Option units label for data (Example: Packets/Sec, Errors/Sec, \n\
344 \"Bytes Per Second\", \"%% Utilization\")\n"));
346 printf (_("\
347 If the value exceeds the <vwl> threshold, a WARNING status is returned. If\n\
348 the value exceeds the <vcl> threshold, a CRITICAL status is returned. If\n\
349 the data in the log file is older than <expire_minutes> old, a WARNING\n\
350 status is returned and a warning message is printed.\n\n"));
352 printf(_("This plugin is useful for monitoring MRTG data that does not correspond to\n\
353 bandwidth usage. (Use the check_mrtgtraf plugin for monitoring bandwidth).\n\
354 It can be used to monitor any kind of data that MRTG is monitoring - errors,\n\
355 packets/sec, etc. I use MRTG in conjuction with the Novell NLM that allows\n\
356 me to track processor utilization, user connections, drive space, etc and\n\
357 this plugin works well for monitoring that kind of data as well.\n\n"));
359 printf (_("Notes:\n\
360 - This plugin only monitors one of the two variables stored in the MRTG log\n\
361 file. If you want to monitor both values you will have to define two\n\
362 commands with different values for the <variable> argument. Of course,\n\
363 you can always hack the code to make this plugin work for you...\n\
364 - MRTG stands for the Multi Router Traffic Grapher. It can be downloaded from\n\
365 http://ee-staff.ethz.ch/~oetiker/webtools/mrtg/mrtg.html\n"));
367 printf (_(UT_SUPPORT));
368 }
372 /* original command line:
373 <log_file> <expire_minutes> <AVG|MAX> <variable> <vwl> <vcl> <label> [units] */
375 void
376 print_usage (void)
377 {
378 printf ("\
379 Usage: %s -F log_file -a <AVG | MAX> -v variable -w warning -c critical\n\
380 [-l label] [-u units] [-e expire_minutes] [-t timeout]\n\
381 [-v]\n", progname);
382 }