Merge pull request #2045 from RincewindsHat/fix/calloc_argument_order
[monitoring-plugins.git] / plugins / check_mrtg.c
blob632e66fb40bfa88fd8aae08b76b841d385f9d3cb
1 /*****************************************************************************
3 * Monitoring check_mrtg plugin
5 * License: GPL
6 * Copyright (c) 1999-2024 Monitoring Plugins Development Team
8 * Description:
10 * This file contains the check_mrtg plugin
12 * This plugin will check either the average or maximum value of one of the
13 * two variables recorded in an MRTG log file.
16 * This program is free software: you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation, either version 3 of the License, or
19 * (at your option) any later version.
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
26 * You should have received a copy of the GNU General Public License
27 * along with this program. If not, see <http://www.gnu.org/licenses/>.
30 *****************************************************************************/
32 const char *progname = "check_mrtg";
33 const char *copyright = "1999-2024";
34 const char *email = "devel@monitoring-plugins.org";
36 #include "common.h"
37 #include "utils.h"
39 static int process_arguments(int /*argc*/, char ** /*argv*/);
40 static int validate_arguments(void);
41 static void print_help(void);
42 void print_usage(void);
44 static char *log_file = NULL;
45 static int expire_minutes = 0;
46 static bool use_average = true;
47 static int variable_number = -1;
48 static unsigned long value_warning_threshold = 0L;
49 static unsigned long value_critical_threshold = 0L;
50 static char *label;
51 static char *units;
53 int main(int argc, char **argv) {
54 setlocale(LC_ALL, "");
55 bindtextdomain(PACKAGE, LOCALEDIR);
56 textdomain(PACKAGE);
58 /* Parse extra opts if any */
59 argv = np_extra_opts(&argc, argv, progname);
61 if (process_arguments(argc, argv) == ERROR)
62 usage4(_("Could not parse arguments\n"));
64 /* open the MRTG log file for reading */
65 FILE *mtrg_log_file = fopen(log_file, "r");
66 if (mtrg_log_file == NULL) {
67 printf(_("Unable to open MRTG log file\n"));
68 return STATE_UNKNOWN;
71 time_t timestamp = 0L;
72 unsigned long average_value_rate = 0L;
73 unsigned long maximum_value_rate = 0L;
74 char input_buffer[MAX_INPUT_BUFFER];
75 int line = 0;
76 while (fgets(input_buffer, MAX_INPUT_BUFFER - 1, mtrg_log_file)) {
78 line++;
80 /* skip the first line of the log file */
81 if (line == 1)
82 continue;
84 /* break out of read loop if we've passed the number of entries we want to read */
85 if (line > 2)
86 break;
88 /* grab the timestamp */
89 char *temp_buffer = strtok(input_buffer, " ");
90 timestamp = strtoul(temp_buffer, NULL, 10);
92 /* grab the average value 1 rate */
93 temp_buffer = strtok(NULL, " ");
94 if (variable_number == 1)
95 average_value_rate = strtoul(temp_buffer, NULL, 10);
97 /* grab the average value 2 rate */
98 temp_buffer = strtok(NULL, " ");
99 if (variable_number == 2)
100 average_value_rate = strtoul(temp_buffer, NULL, 10);
102 /* grab the maximum value 1 rate */
103 temp_buffer = strtok(NULL, " ");
104 if (variable_number == 1)
105 maximum_value_rate = strtoul(temp_buffer, NULL, 10);
107 /* grab the maximum value 2 rate */
108 temp_buffer = strtok(NULL, " ");
109 if (variable_number == 2)
110 maximum_value_rate = strtoul(temp_buffer, NULL, 10);
113 /* close the log file */
114 fclose(mtrg_log_file);
116 /* if we couldn't read enough data, return an unknown error */
117 if (line <= 2) {
118 printf(_("Unable to process MRTG log file\n"));
119 return STATE_UNKNOWN;
122 /* make sure the MRTG data isn't too old */
123 time_t current_time;
124 time(&current_time);
125 if (expire_minutes > 0 && (current_time - timestamp) > (expire_minutes * 60)) {
126 printf(_("MRTG data has expired (%d minutes old)\n"), (int)((current_time - timestamp) / 60));
127 return STATE_WARNING;
130 unsigned long rate = 0L;
131 /* else check the incoming/outgoing rates */
132 if (use_average)
133 rate = average_value_rate;
134 else
135 rate = maximum_value_rate;
137 int result = STATE_OK;
138 if (rate > value_critical_threshold)
139 result = STATE_CRITICAL;
140 else if (rate > value_warning_threshold)
141 result = STATE_WARNING;
143 printf("%s. %s = %lu %s|%s\n", (use_average) ? _("Avg") : _("Max"), label, rate, units,
144 perfdata(label, (long)rate, units, (int)value_warning_threshold, (long)value_warning_threshold, (int)value_critical_threshold,
145 (long)value_critical_threshold, 0, 0, 0, 0));
147 return result;
150 /* process command-line arguments */
151 int process_arguments(int argc, char **argv) {
152 static struct option longopts[] = {
153 {"logfile", required_argument, 0, 'F'}, {"expires", required_argument, 0, 'e'}, {"aggregation", required_argument, 0, 'a'},
154 {"variable", required_argument, 0, 'v'}, {"critical", required_argument, 0, 'c'}, {"warning", required_argument, 0, 'w'},
155 {"label", required_argument, 0, 'l'}, {"units", required_argument, 0, 'u'}, {"variable", required_argument, 0, 'v'},
156 {"version", no_argument, 0, 'V'}, {"help", no_argument, 0, 'h'}, {0, 0, 0, 0}};
158 if (argc < 2)
159 return ERROR;
161 for (int i = 1; i < argc; i++) {
162 if (strcmp("-to", argv[i]) == 0)
163 strcpy(argv[i], "-t");
164 else if (strcmp("-wt", argv[i]) == 0)
165 strcpy(argv[i], "-w");
166 else if (strcmp("-ct", argv[i]) == 0)
167 strcpy(argv[i], "-c");
170 int option_char;
171 int option = 0;
172 while (1) {
173 option_char = getopt_long(argc, argv, "hVF:e:a:v:c:w:l:u:", longopts, &option);
175 if (option_char == -1 || option_char == EOF)
176 break;
178 switch (option_char) {
179 case 'F': /* input file */
180 log_file = optarg;
181 break;
182 case 'e': /* ups name */
183 expire_minutes = atoi(optarg);
184 break;
185 case 'a': /* port */
186 if (!strcmp(optarg, "MAX"))
187 use_average = false;
188 else
189 use_average = true;
190 break;
191 case 'v':
192 variable_number = atoi(optarg);
193 if (variable_number < 1 || variable_number > 2)
194 usage4(_("Invalid variable number"));
195 break;
196 case 'w': /* critical time threshold */
197 value_warning_threshold = strtoul(optarg, NULL, 10);
198 break;
199 case 'c': /* warning time threshold */
200 value_critical_threshold = strtoul(optarg, NULL, 10);
201 break;
202 case 'l': /* label */
203 label = optarg;
204 break;
205 case 'u': /* timeout */
206 units = optarg;
207 break;
208 case 'V': /* version */
209 print_revision(progname, NP_VERSION);
210 exit(STATE_UNKNOWN);
211 case 'h': /* help */
212 print_help();
213 exit(STATE_UNKNOWN);
214 case '?': /* help */
215 usage5();
219 option_char = optind;
220 if (log_file == NULL && argc > option_char) {
221 log_file = argv[option_char++];
224 if (expire_minutes <= 0 && argc > option_char) {
225 if (is_intpos(argv[option_char]))
226 expire_minutes = atoi(argv[option_char++]);
227 else
228 die(STATE_UNKNOWN, _("%s is not a valid expiration time\nUse '%s -h' for additional help\n"), argv[option_char], progname);
231 if (argc > option_char && strcmp(argv[option_char], "MAX") == 0) {
232 use_average = false;
233 option_char++;
234 } else if (argc > option_char && strcmp(argv[option_char], "AVG") == 0) {
235 use_average = true;
236 option_char++;
239 if (argc > option_char && variable_number == -1) {
240 variable_number = atoi(argv[option_char++]);
241 if (variable_number < 1 || variable_number > 2) {
242 printf("%s :", argv[option_char]);
243 usage(_("Invalid variable number\n"));
247 if (argc > option_char && value_warning_threshold == 0) {
248 value_warning_threshold = strtoul(argv[option_char++], NULL, 10);
251 if (argc > option_char && value_critical_threshold == 0) {
252 value_critical_threshold = strtoul(argv[option_char++], NULL, 10);
255 if (argc > option_char && strlen(label) == 0) {
256 label = argv[option_char++];
259 if (argc > option_char && strlen(units) == 0) {
260 units = argv[option_char++];
263 return validate_arguments();
266 int validate_arguments(void) {
267 if (variable_number == -1)
268 usage4(_("You must supply the variable number"));
270 if (label == NULL)
271 label = strdup("value");
273 if (units == NULL)
274 units = strdup("");
276 return OK;
279 void print_help(void) {
280 print_revision(progname, NP_VERSION);
282 printf("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n");
283 printf(COPYRIGHT, copyright, email);
285 printf("%s\n", _("This plugin will check either the average or maximum value of one of the"));
286 printf("%s\n", _("two variables recorded in an MRTG log file."));
288 printf("\n\n");
290 print_usage();
292 printf(UT_HELP_VRSN);
293 printf(UT_EXTRA_OPTS);
295 printf(" %s\n", "-F, --logfile=FILE");
296 printf(" %s\n", _("The MRTG log file containing the data you want to monitor"));
297 printf(" %s\n", "-e, --expires=MINUTES");
298 printf(" %s\n", _("Minutes before MRTG data is considered to be too old"));
299 printf(" %s\n", "-a, --aggregation=AVG|MAX");
300 printf(" %s\n", _("Should we check average or maximum values?"));
301 printf(" %s\n", "-v, --variable=INTEGER");
302 printf(" %s\n", _("Which variable set should we inspect? (1 or 2)"));
303 printf(" %s\n", "-w, --warning=INTEGER");
304 printf(" %s\n", _("Threshold value for data to result in WARNING status"));
305 printf(" %s\n", "-c, --critical=INTEGER");
306 printf(" %s\n", _("Threshold value for data to result in CRITICAL status"));
307 printf(" %s\n", "-l, --label=STRING");
308 printf(" %s\n", _("Type label for data (Examples: Conns, \"Processor Load\", In, Out)"));
309 printf(" %s\n", "-u, --units=STRING");
310 printf(" %s\n", _("Option units label for data (Example: Packets/Sec, Errors/Sec,"));
311 printf(" %s\n", _("\"Bytes Per Second\", \"%% Utilization\")"));
313 printf("\n");
314 printf(" %s\n", _("If the value exceeds the <vwl> threshold, a WARNING status is returned. If"));
315 printf(" %s\n", _("the value exceeds the <vcl> threshold, a CRITICAL status is returned. If"));
316 printf(" %s\n", _("the data in the log file is older than <expire_minutes> old, a WARNING"));
317 printf(" %s\n", _("status is returned and a warning message is printed."));
319 printf("\n");
320 printf(" %s\n", _("This plugin is useful for monitoring MRTG data that does not correspond to"));
321 printf(" %s\n", _("bandwidth usage. (Use the check_mrtgtraf plugin for monitoring bandwidth)."));
322 printf(" %s\n", _("It can be used to monitor any kind of data that MRTG is monitoring - errors,"));
323 printf(" %s\n", _("packets/sec, etc. I use MRTG in conjunction with the Novell NLM that allows"));
324 printf(" %s\n", _("me to track processor utilization, user connections, drive space, etc and"));
325 printf(" %s\n\n", _("this plugin works well for monitoring that kind of data as well."));
327 printf("%s\n", _("Notes:"));
328 printf(" %s\n", _("- This plugin only monitors one of the two variables stored in the MRTG log"));
329 printf(" %s\n", _("file. If you want to monitor both values you will have to define two"));
330 printf(" %s\n", _("commands with different values for the <variable> argument. Of course,"));
331 printf(" %s\n", _("you can always hack the code to make this plugin work for you..."));
332 printf(" %s\n", _("- MRTG stands for the Multi Router Traffic Grapher. It can be downloaded from"));
333 printf(" %s\n", "http://ee-staff.ethz.ch/~oetiker/webtools/mrtg/mrtg.html");
335 printf(UT_SUPPORT);
338 /* original command line:
339 <log_file> <expire_minutes> <AVG|MAX> <variable> <vwl> <vcl> <label> [units] */
341 void print_usage(void) {
342 printf("%s\n", _("Usage:"));
343 printf("%s -F log_file -a <AVG | MAX> -v variable -w warning -c critical\n", progname);
344 printf("[-l label] [-u units] [-e expire_minutes] [-t timeout] [-v]\n");