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 ******************************************************************************/
19 const char *progname = "check_mrtg";
20 const char *revision = "$Revision$";
21 const char *copyright = "1999-2001";
22 const char *email = "nagiosplug-devel@lists.sourceforge.net";
24 #include "common.h"
25 #include "utils.h"
27 int process_arguments (int, char **);
28 int validate_arguments (void);
29 void print_help (void);
30 void print_usage (void);
32 char *log_file = NULL;
33 int expire_minutes = 0;
34 int use_average = TRUE;
35 int variable_number = -1;
36 unsigned long value_warning_threshold = 0L;
37 unsigned long value_critical_threshold = 0L;
38 char *value_label;
39 char *units_label;
41 int
42 main (int argc, char **argv)
43 {
44 int result = STATE_OK;
45 FILE *fp;
46 int line;
47 char input_buffer[MAX_INPUT_BUFFER];
48 char *temp_buffer;
49 time_t current_time;
50 char error_message[MAX_INPUT_BUFFER];
51 time_t timestamp = 0L;
52 unsigned long average_value_rate = 0L;
53 unsigned long maximum_value_rate = 0L;
54 unsigned long value_rate = 0L;
56 setlocale (LC_ALL, "");
57 bindtextdomain (PACKAGE, LOCALEDIR);
58 textdomain (PACKAGE);
60 if (process_arguments (argc, argv) != OK)
61 usage (_("Invalid command arguments supplied\n"));
63 /* open the MRTG log file for reading */
64 fp = fopen (log_file, "r");
65 if (fp == NULL) {
66 printf (_("Unable to open MRTG log file\n"));
67 return STATE_UNKNOWN;
68 }
70 line = 0;
71 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, fp)) {
73 line++;
75 /* skip the first line of the log file */
76 if (line == 1)
77 continue;
79 /* break out of read loop if we've passed the number of entries we want to read */
80 if (line > 2)
81 break;
83 /* grab the timestamp */
84 temp_buffer = strtok (input_buffer, " ");
85 timestamp = strtoul (temp_buffer, NULL, 10);
87 /* grab the average value 1 rate */
88 temp_buffer = strtok (NULL, " ");
89 if (variable_number == 1)
90 average_value_rate = strtoul (temp_buffer, NULL, 10);
92 /* grab the average value 2 rate */
93 temp_buffer = strtok (NULL, " ");
94 if (variable_number == 2)
95 average_value_rate = strtoul (temp_buffer, NULL, 10);
97 /* grab the maximum value 1 rate */
98 temp_buffer = strtok (NULL, " ");
99 if (variable_number == 1)
100 maximum_value_rate = strtoul (temp_buffer, NULL, 10);
102 /* grab the maximum value 2 rate */
103 temp_buffer = strtok (NULL, " ");
104 if (variable_number == 2)
105 maximum_value_rate = strtoul (temp_buffer, NULL, 10);
106 }
108 /* close the log file */
109 fclose (fp);
111 /* if we couldn't read enough data, return an unknown error */
112 if (line <= 2) {
113 result = STATE_UNKNOWN;
114 sprintf (error_message, _("Unable to process MRTG log file\n"));
115 }
117 /* make sure the MRTG data isn't too old */
118 if (result == STATE_OK) {
119 time (¤t_time);
120 if (expire_minutes > 0
121 && (current_time - timestamp) > (expire_minutes * 60)) {
122 result = STATE_WARNING;
123 sprintf (error_message, _("MRTG data has expired (%d minutes old)\n"),
124 (int) ((current_time - timestamp) / 60));
125 }
126 }
128 /* else check the incoming/outgoing rates */
129 if (result == STATE_OK) {
131 if (use_average == TRUE)
132 value_rate = average_value_rate;
133 else
134 value_rate = maximum_value_rate;
136 if (value_rate > value_critical_threshold)
137 result = STATE_CRITICAL;
138 else if (value_rate > value_warning_threshold)
139 result = STATE_WARNING;
140 }
142 sprintf (error_message, "%s. %s = %lu %s",
143 (use_average == TRUE) ? _("Ave") : _("Max"), value_label, value_rate,
144 units_label);
145 printf ("%s\n", error_message);
147 return result;
148 }
149 \f
150 /* process command-line arguments */
151 int
152 process_arguments (int argc, char **argv)
153 {
154 int c;
156 int option = 0;
157 static struct option longopts[] = {
158 {"logfile", required_argument, 0, 'F'},
159 {"expires", required_argument, 0, 'e'},
160 {"aggregation", required_argument, 0, 'a'},
161 {"variable", required_argument, 0, 'v'},
162 {"critical", required_argument, 0, 'c'},
163 {"warning", required_argument, 0, 'w'},
164 {"label", required_argument, 0, 'l'},
165 {"units", required_argument, 0, 'u'},
166 {"verbose", no_argument, 0, 'v'},
167 {"version", no_argument, 0, 'V'},
168 {"help", no_argument, 0, 'h'},
169 {0, 0, 0, 0}
170 };
172 if (argc < 2)
173 return ERROR;
175 for (c = 1; c < argc; c++) {
176 if (strcmp ("-to", argv[c]) == 0)
177 strcpy (argv[c], "-t");
178 else if (strcmp ("-wt", argv[c]) == 0)
179 strcpy (argv[c], "-w");
180 else if (strcmp ("-ct", argv[c]) == 0)
181 strcpy (argv[c], "-c");
182 }
184 while (1) {
185 c = getopt_long (argc, argv, "hVF:e:a:v:c:w:l:u:", longopts,
186 &option);
188 if (c == -1 || c == EOF)
189 break;
191 switch (c) {
192 case 'F': /* input file */
193 log_file = optarg;
194 break;
195 case 'e': /* ups name */
196 expire_minutes = atoi (optarg);
197 break;
198 case 'a': /* port */
199 if (!strcmp (optarg, "MAX"))
200 use_average = FALSE;
201 else
202 use_average = TRUE;
203 break;
204 case 'v':
205 variable_number = atoi (optarg);
206 if (variable_number < 1 || variable_number > 2)
207 usage (_("Invalid variable number\n"));
208 break;
209 case 'w': /* critical time threshold */
210 value_warning_threshold = strtoul (optarg, NULL, 10);
211 break;
212 case 'c': /* warning time threshold */
213 value_critical_threshold = strtoul (optarg, NULL, 10);
214 break;
215 case 'l': /* label */
216 value_label = optarg;
217 break;
218 case 'u': /* timeout */
219 units_label = optarg;
220 break;
221 case 'V': /* version */
222 print_revision (progname, revision);
223 exit (STATE_OK);
224 case 'h': /* help */
225 print_help ();
226 exit (STATE_OK);
227 case '?': /* help */
228 usage (_("Invalid argument\n"));
229 }
230 }
232 c = optind;
233 if (log_file == NULL && argc > c) {
234 log_file = argv[c++];
235 }
237 if (expire_minutes <= 0 && argc > c) {
238 if (is_intpos (argv[c]))
239 expire_minutes = atoi (argv[c++]);
240 else
241 die (STATE_UNKNOWN,
242 _("%s is not a valid expiration time\nUse '%s -h' for additional help\n"),
243 argv[c], progname);
244 }
246 if (argc > c && strcmp (argv[c], "MAX") == 0) {
247 use_average = FALSE;
248 c++;
249 }
250 else if (argc > c && strcmp (argv[c], "AVG") == 0) {
251 use_average = TRUE;
252 c++;
253 }
255 if (argc > c && variable_number == -1) {
256 variable_number = atoi (argv[c++]);
257 if (variable_number < 1 || variable_number > 2) {
258 printf ("%s :", argv[c]);
259 usage (_("Invalid variable number\n"));
260 }
261 }
263 if (argc > c && value_warning_threshold == 0) {
264 value_warning_threshold = strtoul (argv[c++], NULL, 10);
265 }
267 if (argc > c && value_critical_threshold == 0) {
268 value_critical_threshold = strtoul (argv[c++], NULL, 10);
269 }
271 if (argc > c && strlen (value_label) == 0) {
272 value_label = argv[c++];
273 }
275 if (argc > c && strlen (units_label) == 0) {
276 units_label = argv[c++];
277 }
279 return validate_arguments ();
280 }
282 int
283 validate_arguments (void)
284 {
285 if (variable_number == -1)
286 usage (_("You must supply the variable number\n"));
288 if (value_label == NULL)
289 value_label = strdup ("");
291 if (units_label == NULL)
292 units_label = strdup ("");
294 return OK;
295 }
301 \f
302 void
303 print_help (void)
304 {
305 print_revision (progname, revision);
307 printf (_("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n"));
308 printf (_(COPYRIGHT), copyright, email);
310 printf(_("\
311 This plugin will check either the average or maximum value of one of the\n\
312 two variables recorded in an MRTG log file.\n"));
314 print_usage ();
316 printf (_(UT_HELP_VRSN));
318 printf (_("\
319 -F, --logfile=FILE\n\
320 The MRTG log file containing the data you want to monitor\n\
321 -e, --expires=MINUTES\n\
322 Minutes before MRTG data is considered to be too old\n\
323 -a, --aggregation=AVG|MAX\n\
324 Should we check average or maximum values?\n\
325 -v, --variable=INTEGER\n\
326 Which variable set should we inspect? (1 or 2)\n\
327 -w, --warning=INTEGER\n\
328 Threshold value for data to result in WARNING status\n\
329 -c, --critical=INTEGER\n\
330 Threshold value for data to result in CRITICAL status\n"));
332 printf (_("\
333 -l, --label=STRING\n\
334 Type label for data (Examples: Conns, \"Processor Load\", In, Out)\n\
335 -u, --units=STRING\n\
336 Option units label for data (Example: Packets/Sec, Errors/Sec, \n\
337 \"Bytes Per Second\", \"%% Utilization\")\n"));
339 printf (_("\
340 If the value exceeds the <vwl> threshold, a WARNING status is returned. If\n\
341 the value exceeds the <vcl> threshold, a CRITICAL status is returned. If\n\
342 the data in the log file is older than <expire_minutes> old, a WARNING\n\
343 status is returned and a warning message is printed.\n\n"));
345 printf(_("This plugin is useful for monitoring MRTG data that does not correspond to\n\
346 bandwidth usage. (Use the check_mrtgtraf plugin for monitoring bandwidth).\n\
347 It can be used to monitor any kind of data that MRTG is monitoring - errors,\n\
348 packets/sec, etc. I use MRTG in conjuction with the Novell NLM that allows\n\
349 me to track processor utilization, user connections, drive space, etc and\n\
350 this plugin works well for monitoring that kind of data as well.\n\n"));
352 printf (_("Notes:\n\
353 - This plugin only monitors one of the two variables stored in the MRTG log\n\
354 file. If you want to monitor both values you will have to define two\n\
355 commands with different values for the <variable> argument. Of course,\n\
356 you can always hack the code to make this plugin work for you...\n\
357 - MRTG stands for the Multi Router Traffic Grapher. It can be downloaded from\n\
358 http://ee-staff.ethz.ch/~oetiker/webtools/mrtg/mrtg.html\n"));
360 printf (_(UT_SUPPORT));
361 }
366 /* original command line:
367 <log_file> <expire_minutes> <AVG|MAX> <variable> <vwl> <vcl> <label> [units] */
369 void
370 print_usage (void)
371 {
372 printf (_("\
373 Usage: %s -F log_file -a <AVG | MAX> -v variable -w warning -c critical\n\
374 [-l label] [-u units] [-e expire_minutes] [-t timeout] [-v]\n"), progname);
375 printf (_(UT_HLP_VRS), progname, progname);
376 }