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 /* original command line:
28 <log_file> <expire_minutes> <AVG|MAX> <variable> <vwl> <vcl> <label> [units] */
30 void
31 print_usage (void)
32 {
33 printf (_("\
34 Usage: %s -F log_file -a <AVG | MAX> -v variable -w warning -c critical\n\
35 [-l label] [-u units] [-e expire_minutes] [-t timeout] [-v]\n"), progname);
36 printf (_(UT_HLP_VRS), progname, progname);
37 }
39 void
40 print_help (void)
41 {
42 print_revision (progname, revision);
44 printf (_(COPYRIGHT), copyright, email);
46 printf(_("\
47 This plugin will check either the average or maximum value of one of the\n\
48 two variables recorded in an MRTG log file.\n"));
50 print_usage ();
52 printf (_(UT_HELP_VRSN));
54 printf (_("\
55 -F, --logfile=FILE\n\
56 The MRTG log file containing the data you want to monitor\n\
57 -e, --expires=MINUTES\n\
58 Minutes before MRTG data is considered to be too old\n\
59 -a, --aggregation=AVG|MAX\n\
60 Should we check average or maximum values?\n\
61 -v, --variable=INTEGER\n\
62 Which variable set should we inspect? (1 or 2)\n\
63 -w, --warning=INTEGER\n\
64 Threshold value for data to result in WARNING status\n\
65 -c, --critical=INTEGER\n\
66 Threshold value for data to result in CRITICAL status\n"));
68 printf (_("\
69 -l, --label=STRING\n\
70 Type label for data (Examples: Conns, \"Processor Load\", In, Out)\n\
71 -u, --units=STRING\n\
72 Option units label for data (Example: Packets/Sec, Errors/Sec, \n\
73 \"Bytes Per Second\", \"%% Utilization\")\n"));
75 printf (_("\
76 If the value exceeds the <vwl> threshold, a WARNING status is returned. If\n\
77 the value exceeds the <vcl> threshold, a CRITICAL status is returned. If\n\
78 the data in the log file is older than <expire_minutes> old, a WARNING\n\
79 status is returned and a warning message is printed.\n\n"));
81 printf(_("This plugin is useful for monitoring MRTG data that does not correspond to\n\
82 bandwidth usage. (Use the check_mrtgtraf plugin for monitoring bandwidth).\n\
83 It can be used to monitor any kind of data that MRTG is monitoring - errors,\n\
84 packets/sec, etc. I use MRTG in conjuction with the Novell NLM that allows\n\
85 me to track processor utilization, user connections, drive space, etc and\n\
86 this plugin works well for monitoring that kind of data as well.\n\n"));
88 printf (_("Notes:\n\
89 - This plugin only monitors one of the two variables stored in the MRTG log\n\
90 file. If you want to monitor both values you will have to define two\n\
91 commands with different values for the <variable> argument. Of course,\n\
92 you can always hack the code to make this plugin work for you...\n\
93 - MRTG stands for the Multi Router Traffic Grapher. It can be downloaded from\n\
94 http://ee-staff.ethz.ch/~oetiker/webtools/mrtg/mrtg.html\n"));
96 printf (_(UT_SUPPORT));
97 }
99 int process_arguments (int, char **);
100 int validate_arguments (void);
102 char *log_file = NULL;
103 int expire_minutes = 0;
104 int use_average = TRUE;
105 int variable_number = -1;
106 unsigned long value_warning_threshold = 0L;
107 unsigned long value_critical_threshold = 0L;
108 char *value_label = "";
109 char *units_label = "";
111 int
112 main (int argc, char **argv)
113 {
114 int result = STATE_OK;
115 FILE *fp;
116 int line;
117 char input_buffer[MAX_INPUT_BUFFER];
118 char *temp_buffer;
119 time_t current_time;
120 char error_message[MAX_INPUT_BUFFER];
121 time_t timestamp = 0L;
122 unsigned long average_value_rate = 0L;
123 unsigned long maximum_value_rate = 0L;
124 unsigned long value_rate = 0L;
126 if (process_arguments (argc, argv) != OK)
127 usage (_("Invalid command arguments supplied\n"));
129 /* open the MRTG log file for reading */
130 fp = fopen (log_file, "r");
131 if (fp == NULL) {
132 printf (_("Unable to open MRTG log file\n"));
133 return STATE_UNKNOWN;
134 }
136 line = 0;
137 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, fp)) {
139 line++;
141 /* skip the first line of the log file */
142 if (line == 1)
143 continue;
145 /* break out of read loop if we've passed the number of entries we want to read */
146 if (line > 2)
147 break;
149 /* grab the timestamp */
150 temp_buffer = strtok (input_buffer, " ");
151 timestamp = strtoul (temp_buffer, NULL, 10);
153 /* grab the average value 1 rate */
154 temp_buffer = strtok (NULL, " ");
155 if (variable_number == 1)
156 average_value_rate = strtoul (temp_buffer, NULL, 10);
158 /* grab the average value 2 rate */
159 temp_buffer = strtok (NULL, " ");
160 if (variable_number == 2)
161 average_value_rate = strtoul (temp_buffer, NULL, 10);
163 /* grab the maximum value 1 rate */
164 temp_buffer = strtok (NULL, " ");
165 if (variable_number == 1)
166 maximum_value_rate = strtoul (temp_buffer, NULL, 10);
168 /* grab the maximum value 2 rate */
169 temp_buffer = strtok (NULL, " ");
170 if (variable_number == 2)
171 maximum_value_rate = strtoul (temp_buffer, NULL, 10);
172 }
174 /* close the log file */
175 fclose (fp);
177 /* if we couldn't read enough data, return an unknown error */
178 if (line <= 2) {
179 result = STATE_UNKNOWN;
180 sprintf (error_message, _("Unable to process MRTG log file\n"));
181 }
183 /* make sure the MRTG data isn't too old */
184 if (result == STATE_OK) {
185 time (¤t_time);
186 if (expire_minutes > 0
187 && (current_time - timestamp) > (expire_minutes * 60)) {
188 result = STATE_WARNING;
189 sprintf (error_message, _("MRTG data has expired (%d minutes old)\n"),
190 (int) ((current_time - timestamp) / 60));
191 }
192 }
194 /* else check the incoming/outgoing rates */
195 if (result == STATE_OK) {
197 if (use_average == TRUE)
198 value_rate = average_value_rate;
199 else
200 value_rate = maximum_value_rate;
202 if (value_rate > value_critical_threshold)
203 result = STATE_CRITICAL;
204 else if (value_rate > value_warning_threshold)
205 result = STATE_WARNING;
206 }
208 sprintf (error_message, "%s. %s = %lu %s",
209 (use_average == TRUE) ? _("Ave") : _("Max"), value_label, value_rate,
210 units_label);
211 printf ("%s\n", error_message);
213 return result;
214 }
215 \f
216 /* process command-line arguments */
217 int
218 process_arguments (int argc, char **argv)
219 {
220 int c;
222 int option_index = 0;
223 static struct option long_options[] = {
224 {"logfile", required_argument, 0, 'F'},
225 {"expires", required_argument, 0, 'e'},
226 {"aggregation", required_argument, 0, 'a'},
227 {"variable", required_argument, 0, 'v'},
228 {"critical", required_argument, 0, 'c'},
229 {"warning", required_argument, 0, 'w'},
230 {"label", required_argument, 0, 'l'},
231 {"units", required_argument, 0, 'u'},
232 {"verbose", no_argument, 0, 'v'},
233 {"version", no_argument, 0, 'V'},
234 {"help", no_argument, 0, 'h'},
235 {0, 0, 0, 0}
236 };
238 if (argc < 2)
239 return ERROR;
241 for (c = 1; c < argc; c++) {
242 if (strcmp ("-to", argv[c]) == 0)
243 strcpy (argv[c], "-t");
244 else if (strcmp ("-wt", argv[c]) == 0)
245 strcpy (argv[c], "-w");
246 else if (strcmp ("-ct", argv[c]) == 0)
247 strcpy (argv[c], "-c");
248 }
250 while (1) {
251 c = getopt_long (argc, argv, "hVF:e:a:v:c:w:l:u:", long_options,
252 &option_index);
254 if (c == -1 || c == EOF)
255 break;
257 switch (c) {
258 case 'F': /* input file */
259 log_file = optarg;
260 break;
261 case 'e': /* ups name */
262 expire_minutes = atoi (optarg);
263 break;
264 case 'a': /* port */
265 if (!strcmp (optarg, "MAX"))
266 use_average = FALSE;
267 else
268 use_average = TRUE;
269 break;
270 case 'v':
271 variable_number = atoi (optarg);
272 if (variable_number < 1 || variable_number > 2)
273 usage (_("Invalid variable number\n"));
274 break;
275 case 'w': /* critical time threshold */
276 value_warning_threshold = strtoul (optarg, NULL, 10);
277 break;
278 case 'c': /* warning time threshold */
279 value_critical_threshold = strtoul (optarg, NULL, 10);
280 break;
281 case 'l': /* label */
282 value_label = optarg;
283 break;
284 case 'u': /* timeout */
285 units_label = optarg;
286 break;
287 case 'V': /* version */
288 print_revision (progname, revision);
289 exit (STATE_OK);
290 case 'h': /* help */
291 print_help ();
292 exit (STATE_OK);
293 case '?': /* help */
294 usage (_("Invalid argument\n"));
295 }
296 }
298 c = optind;
299 if (log_file == NULL && argc > c) {
300 log_file = argv[c++];
301 }
303 if (expire_minutes <= 0 && argc > c) {
304 if (is_intpos (argv[c]))
305 expire_minutes = atoi (argv[c++]);
306 else
307 terminate (STATE_UNKNOWN,
308 _("%s is not a valid expiration time\nUse '%s -h' for additional help\n"),
309 argv[c], progname);
310 }
312 if (argc > c && strcmp (argv[c], "MAX") == 0) {
313 use_average = FALSE;
314 c++;
315 }
316 else if (argc > c && strcmp (argv[c], "AVG") == 0) {
317 use_average = TRUE;
318 c++;
319 }
321 if (argc > c && variable_number == -1) {
322 variable_number = atoi (argv[c++]);
323 if (variable_number < 1 || variable_number > 2) {
324 printf ("%s :", argv[c]);
325 usage (_("Invalid variable number\n"));
326 }
327 }
329 if (argc > c && value_warning_threshold == 0) {
330 value_warning_threshold = strtoul (argv[c++], NULL, 10);
331 }
333 if (argc > c && value_critical_threshold == 0) {
334 value_critical_threshold = strtoul (argv[c++], NULL, 10);
335 }
337 if (argc > c && strlen (value_label) == 0) {
338 value_label = argv[c++];
339 }
341 if (argc > c && strlen (units_label) == 0) {
342 units_label = argv[c++];
343 }
345 return validate_arguments ();
346 }
348 int
349 validate_arguments (void)
350 {
351 if (variable_number == -1)
352 usage (_("You must supply the variable number\n"));
354 return OK;
355 }