summaryrefslogtreecommitdiffstats
path: root/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'plugins')
-rw-r--r--plugins/check_apt.c4
-rw-r--r--plugins/check_by_ssh.c528
-rw-r--r--plugins/check_cluster.c255
-rw-r--r--plugins/check_curl.c4550
-rw-r--r--plugins/check_dbi.c827
-rw-r--r--plugins/check_dig.c650
-rw-r--r--plugins/check_disk.c2066
-rw-r--r--plugins/check_dns.c1101
-rw-r--r--plugins/check_dummy.c195
-rw-r--r--plugins/check_fping.c921
-rw-r--r--plugins/check_game.c567
-rw-r--r--plugins/check_hpjd.c419
-rw-r--r--plugins/check_http.c25
-rw-r--r--plugins/check_ide_smart.c496
-rw-r--r--plugins/check_ldap.c4
-rw-r--r--plugins/check_load.c26
-rw-r--r--plugins/check_mrtg.c456
-rw-r--r--plugins/check_mrtgtraf.c457
-rw-r--r--plugins/check_mysql.c12
-rw-r--r--plugins/check_mysql_query.c396
-rw-r--r--plugins/check_nagios.c306
-rw-r--r--plugins/check_nt.c943
-rw-r--r--plugins/check_ntp.c4
-rw-r--r--plugins/check_ntp_peer.c636
-rw-r--r--plugins/check_ntp_time.c628
-rw-r--r--plugins/check_nwstat.c2114
-rw-r--r--plugins/check_overcr.c397
-rw-r--r--plugins/check_pgsql.c629
-rw-r--r--plugins/check_ping.c603
-rw-r--r--plugins/check_procs.c4
-rw-r--r--plugins/check_radius.c4
-rw-r--r--plugins/check_real.c484
-rw-r--r--plugins/check_smtp.c4
-rw-r--r--plugins/check_snmp.c1397
-rw-r--r--plugins/check_ssh.c476
-rw-r--r--plugins/check_swap.c191
-rw-r--r--plugins/check_swap.d/check_swap.h7
-rw-r--r--plugins/check_swap.d/swap.c151
-rw-r--r--plugins/check_tcp.c598
-rw-r--r--plugins/check_time.c431
-rw-r--r--plugins/check_ups.c991
-rw-r--r--plugins/check_users.c291
-rw-r--r--plugins/negate.c296
-rw-r--r--plugins/netutils.c236
-rw-r--r--plugins/picohttpparser/picohttpparser.c1101
-rw-r--r--plugins/popen.c283
-rw-r--r--plugins/runcmd.c254
-rw-r--r--plugins/sslutils.c228
-rw-r--r--plugins/t/check_curl.t4
-rw-r--r--plugins/t/check_disk.t10
-rw-r--r--plugins/t/check_http.t4
-rw-r--r--plugins/t/check_ssh.t122
-rw-r--r--plugins/t/check_swap.t14
-rwxr-xr-xplugins/tests/check_curl.t14
-rwxr-xr-xplugins/tests/check_http.t12
-rw-r--r--plugins/urlize.c195
-rw-r--r--plugins/utils.c532
-rw-r--r--plugins/utils.h1
58 files changed, 13652 insertions, 14898 deletions
diff --git a/plugins/check_apt.c b/plugins/check_apt.c
index 5c0f6e28..5e4021b5 100644
--- a/plugins/check_apt.c
+++ b/plugins/check_apt.c
@@ -3,7 +3,7 @@
3* Monitoring check_apt plugin 3* Monitoring check_apt plugin
4* 4*
5* License: GPL 5* License: GPL
6* Copyright (c) 2006-2008 Monitoring Plugins Development Team 6* Copyright (c) 2006-2024 Monitoring Plugins Development Team
7* 7*
8* Original author: Sean Finney 8* Original author: Sean Finney
9* 9*
@@ -30,7 +30,7 @@
30*****************************************************************************/ 30*****************************************************************************/
31 31
32const char *progname = "check_apt"; 32const char *progname = "check_apt";
33const char *copyright = "2006-2008"; 33const char *copyright = "2006-2024";
34const char *email = "devel@monitoring-plugins.org"; 34const char *email = "devel@monitoring-plugins.org";
35 35
36#include "common.h" 36#include "common.h"
diff --git a/plugins/check_by_ssh.c b/plugins/check_by_ssh.c
index 2a23b397..905b2393 100644
--- a/plugins/check_by_ssh.c
+++ b/plugins/check_by_ssh.c
@@ -1,33 +1,33 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring check_by_ssh plugin 3 * Monitoring check_by_ssh plugin
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 2000-2008 Monitoring Plugins Development Team 6 * Copyright (c) 2000-2024 Monitoring Plugins Development Team
7* 7 *
8* Description: 8 * Description:
9* 9 *
10* This file contains the check_by_ssh plugin 10 * This file contains the check_by_ssh plugin
11* 11 *
12* 12 *
13* This program is free software: you can redistribute it and/or modify 13 * This program is free software: you can redistribute it and/or modify
14* it under the terms of the GNU General Public License as published by 14 * it under the terms of the GNU General Public License as published by
15* the Free Software Foundation, either version 3 of the License, or 15 * the Free Software Foundation, either version 3 of the License, or
16* (at your option) any later version. 16 * (at your option) any later version.
17* 17 *
18* This program is distributed in the hope that it will be useful, 18 * This program is distributed in the hope that it will be useful,
19* but WITHOUT ANY WARRANTY; without even the implied warranty of 19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21* GNU General Public License for more details. 21 * GNU General Public License for more details.
22* 22 *
23* You should have received a copy of the GNU General Public License 23 * You should have received a copy of the GNU General Public License
24* along with this program. If not, see <http://www.gnu.org/licenses/>. 24 * along with this program. If not, see <http://www.gnu.org/licenses/>.
25* 25 *
26* 26 *
27*****************************************************************************/ 27 *****************************************************************************/
28 28
29const char *progname = "check_by_ssh"; 29const char *progname = "check_by_ssh";
30const char *copyright = "2000-2008"; 30const char *copyright = "2000-2024";
31const char *email = "devel@monitoring-plugins.org"; 31const char *email = "devel@monitoring-plugins.org";
32 32
33#include "common.h" 33#include "common.h"
@@ -36,82 +36,80 @@ const char *email = "devel@monitoring-plugins.org";
36#include "utils_cmd.h" 36#include "utils_cmd.h"
37 37
38#ifndef NP_MAXARGS 38#ifndef NP_MAXARGS
39#define NP_MAXARGS 1024 39# define NP_MAXARGS 1024
40#endif 40#endif
41 41
42int process_arguments (int, char **); 42static int process_arguments(int /*argc*/, char ** /*argv*/);
43int validate_arguments (void); 43static int validate_arguments(void);
44void comm_append (const char *); 44static void comm_append(const char * /*str*/);
45void print_help (void); 45static void print_help(void);
46void print_usage (void); 46void print_usage(void);
47 47
48unsigned int commands = 0; 48static unsigned int commands = 0;
49unsigned int services = 0; 49static unsigned int services = 0;
50int skip_stdout = 0; 50static int skip_stdout = 0;
51int skip_stderr = 0; 51static int skip_stderr = 0;
52int warn_on_stderr = 0; 52static int warn_on_stderr = 0;
53bool unknown_timeout = false; 53static bool unknown_timeout = false;
54char *remotecmd = NULL; 54static char *remotecmd = NULL;
55char **commargv = NULL; 55static char **commargv = NULL;
56int commargc = 0; 56static int commargc = 0;
57char *hostname = NULL; 57static char *hostname = NULL;
58char *outputfile = NULL; 58static char *outputfile = NULL;
59char *host_shortname = NULL; 59static char *host_shortname = NULL;
60char **service; 60static char **service;
61bool passive = false; 61static bool passive = false;
62bool verbose = false; 62static bool verbose = false;
63 63
64int 64int main(int argc, char **argv) {
65main (int argc, char **argv)
66{
67 65
68 char *status_text; 66 char *status_text;
69 int cresult; 67 int cresult;
70 int result = STATE_UNKNOWN; 68 int result = STATE_UNKNOWN;
71 time_t local_time; 69 time_t local_time;
72 FILE *fp = NULL; 70 FILE *file_pointer = NULL;
73 output chld_out, chld_err; 71 output chld_out;
72 output chld_err;
74 73
75 remotecmd = ""; 74 remotecmd = "";
76 comm_append(SSH_COMMAND); 75 comm_append(SSH_COMMAND);
77 76
78 setlocale (LC_ALL, ""); 77 setlocale(LC_ALL, "");
79 bindtextdomain (PACKAGE, LOCALEDIR); 78 bindtextdomain(PACKAGE, LOCALEDIR);
80 textdomain (PACKAGE); 79 textdomain(PACKAGE);
81 80
82 /* Parse extra opts if any */ 81 /* Parse extra opts if any */
83 argv=np_extra_opts (&argc, argv, progname); 82 argv = np_extra_opts(&argc, argv, progname);
84 83
85 /* process arguments */ 84 /* process arguments */
86 if (process_arguments (argc, argv) == ERROR) 85 if (process_arguments(argc, argv) == ERROR)
87 usage_va(_("Could not parse arguments")); 86 usage_va(_("Could not parse arguments"));
88 87
89 /* Set signal handling and alarm timeout */ 88 /* Set signal handling and alarm timeout */
90 if (signal (SIGALRM, timeout_alarm_handler) == SIG_ERR) { 89 if (signal(SIGALRM, timeout_alarm_handler) == SIG_ERR) {
91 usage_va(_("Cannot catch SIGALRM")); 90 usage_va(_("Cannot catch SIGALRM"));
92 } 91 }
93 alarm (timeout_interval); 92 alarm(timeout_interval);
94 93
95 /* run the command */ 94 /* run the command */
96 if (verbose) { 95 if (verbose) {
97 printf ("Command: %s\n", commargv[0]); 96 printf("Command: %s\n", commargv[0]);
98 for (int i = 1; i < commargc; i++) 97 for (int i = 1; i < commargc; i++)
99 printf ("Argument %i: %s\n", i, commargv[i]); 98 printf("Argument %i: %s\n", i, commargv[i]);
100 } 99 }
101 100
102 result = cmd_run_array (commargv, &chld_out, &chld_err, 0); 101 result = cmd_run_array(commargv, &chld_out, &chld_err, 0);
103 102
104 /* SSH returns 255 if connection attempt fails; include the first line of error output */ 103 /* SSH returns 255 if connection attempt fails; include the first line of error output */
105 if (result == 255 && unknown_timeout) { 104 if (result == 255 && unknown_timeout) {
106 printf (_("SSH connection failed: %s\n"), 105 printf(_("SSH connection failed: %s\n"), chld_err.lines > 0 ? chld_err.line[0] : "(no error output)");
107 chld_err.lines > 0 ? chld_err.line[0] : "(no error output)");
108 return STATE_UNKNOWN; 106 return STATE_UNKNOWN;
109 } 107 }
110 108
111 if (verbose) { 109 if (verbose) {
112 for(size_t i = 0; i < chld_out.lines; i++) 110 for (size_t i = 0; i < chld_out.lines; i++)
113 printf("stdout: %s\n", chld_out.line[i]); 111 printf("stdout: %s\n", chld_out.line[i]);
114 for(size_t i = 0; i < chld_err.lines; i++) 112 for (size_t i = 0; i < chld_err.lines; i++)
115 printf("stderr: %s\n", chld_err.line[i]); 113 printf("stderr: %s\n", chld_err.line[i]);
116 } 114 }
117 115
@@ -121,155 +119,144 @@ main (int argc, char **argv)
121 skip_stderr = chld_err.lines; 119 skip_stderr = chld_err.lines;
122 120
123 /* UNKNOWN or worse if (non-skipped) output found on stderr */ 121 /* UNKNOWN or worse if (non-skipped) output found on stderr */
124 if(chld_err.lines > (size_t)skip_stderr) { 122 if (chld_err.lines > (size_t)skip_stderr) {
125 printf (_("Remote command execution failed: %s\n"), 123 printf(_("Remote command execution failed: %s\n"), chld_err.line[skip_stderr]);
126 chld_err.line[skip_stderr]); 124 if (warn_on_stderr)
127 if ( warn_on_stderr )
128 return max_state_alt(result, STATE_WARNING); 125 return max_state_alt(result, STATE_WARNING);
129 else 126 return max_state_alt(result, STATE_UNKNOWN);
130 return max_state_alt(result, STATE_UNKNOWN);
131 } 127 }
132 128
133 /* this is simple if we're not supposed to be passive. 129 /* this is simple if we're not supposed to be passive.
134 * Wrap up quickly and keep the tricks below */ 130 * Wrap up quickly and keep the tricks below */
135 if(!passive) { 131 if (!passive) {
136 if (chld_out.lines > (size_t)skip_stdout) 132 if (chld_out.lines > (size_t)skip_stdout)
137 for (size_t i = skip_stdout; i < chld_out.lines; i++) 133 for (size_t i = skip_stdout; i < chld_out.lines; i++)
138 puts (chld_out.line[i]); 134 puts(chld_out.line[i]);
139 else 135 else
140 printf (_("%s - check_by_ssh: Remote command '%s' returned status %d\n"), 136 printf(_("%s - check_by_ssh: Remote command '%s' returned status %d\n"), state_text(result), remotecmd, result);
141 state_text(result), remotecmd, result); 137 return result; /* return error status from remote command */
142 return result; /* return error status from remote command */
143 } 138 }
144 139
145
146 /* 140 /*
147 * Passive mode 141 * Passive mode
148 */ 142 */
149 143
150 /* process output */ 144 /* process output */
151 if (!(fp = fopen (outputfile, "a"))) { 145 if (!(file_pointer = fopen(outputfile, "a"))) {
152 printf (_("SSH WARNING: could not open %s\n"), outputfile); 146 printf(_("SSH WARNING: could not open %s\n"), outputfile);
153 exit (STATE_UNKNOWN); 147 exit(STATE_UNKNOWN);
154 } 148 }
155 149
156 local_time = time (NULL); 150 local_time = time(NULL);
157 commands = 0; 151 commands = 0;
158 for(size_t i = skip_stdout; i < chld_out.lines; i++) { 152 for (size_t i = skip_stdout; i < chld_out.lines; i++) {
159 status_text = chld_out.line[i++]; 153 status_text = chld_out.line[i++];
160 if (i == chld_out.lines || strstr (chld_out.line[i], "STATUS CODE: ") == NULL) 154 if (i == chld_out.lines || strstr(chld_out.line[i], "STATUS CODE: ") == NULL)
161 die (STATE_UNKNOWN, _("%s: Error parsing output\n"), progname); 155 die(STATE_UNKNOWN, _("%s: Error parsing output\n"), progname);
162 156
163 if (service[commands] && status_text 157 if (service[commands] && status_text && sscanf(chld_out.line[i], "STATUS CODE: %d", &cresult) == 1) {
164 && sscanf (chld_out.line[i], "STATUS CODE: %d", &cresult) == 1) 158 fprintf(file_pointer, "[%d] PROCESS_SERVICE_CHECK_RESULT;%s;%s;%d;%s\n", (int)local_time, host_shortname, service[commands++],
165 { 159 cresult, status_text);
166 fprintf (fp, "[%d] PROCESS_SERVICE_CHECK_RESULT;%s;%s;%d;%s\n",
167 (int) local_time, host_shortname, service[commands++],
168 cresult, status_text);
169 } 160 }
170 } 161 }
171 162
172 /* Multiple commands and passive checking should always return OK */ 163 /* Multiple commands and passive checking should always return OK */
173 return result; 164 return result;
174} 165}
175 166
176/* process command-line arguments */ 167/* process command-line arguments */
177int 168int process_arguments(int argc, char **argv) {
178process_arguments (int argc, char **argv)
179{
180 int c; 169 int c;
181 char *p1, *p2; 170 char *p1;
171 char *p2;
182 172
183 int option = 0; 173 int option = 0;
184 static struct option longopts[] = { 174 static struct option longopts[] = {{"version", no_argument, 0, 'V'},
185 {"version", no_argument, 0, 'V'}, 175 {"help", no_argument, 0, 'h'},
186 {"help", no_argument, 0, 'h'}, 176 {"verbose", no_argument, 0, 'v'},
187 {"verbose", no_argument, 0, 'v'}, 177 {"fork", no_argument, 0, 'f'},
188 {"fork", no_argument, 0, 'f'}, 178 {"timeout", required_argument, 0, 't'},
189 {"timeout", required_argument, 0, 't'}, 179 {"unknown-timeout", no_argument, 0, 'U'},
190 {"unknown-timeout", no_argument, 0, 'U'}, 180 {"host", required_argument, 0, 'H'}, /* backward compatibility */
191 {"host", required_argument, 0, 'H'}, /* backward compatibility */ 181 {"hostname", required_argument, 0, 'H'},
192 {"hostname", required_argument, 0, 'H'}, 182 {"port", required_argument, 0, 'p'},
193 {"port", required_argument,0,'p'}, 183 {"output", required_argument, 0, 'O'},
194 {"output", required_argument, 0, 'O'}, 184 {"name", required_argument, 0, 'n'},
195 {"name", required_argument, 0, 'n'}, 185 {"services", required_argument, 0, 's'},
196 {"services", required_argument, 0, 's'}, 186 {"identity", required_argument, 0, 'i'},
197 {"identity", required_argument, 0, 'i'}, 187 {"user", required_argument, 0, 'u'},
198 {"user", required_argument, 0, 'u'}, 188 {"logname", required_argument, 0, 'l'},
199 {"logname", required_argument, 0, 'l'}, 189 {"command", required_argument, 0, 'C'},
200 {"command", required_argument, 0, 'C'}, 190 {"skip", optional_argument, 0, 'S'}, /* backwards compatibility */
201 {"skip", optional_argument, 0, 'S'}, /* backwards compatibility */ 191 {"skip-stdout", optional_argument, 0, 'S'},
202 {"skip-stdout", optional_argument, 0, 'S'}, 192 {"skip-stderr", optional_argument, 0, 'E'},
203 {"skip-stderr", optional_argument, 0, 'E'}, 193 {"warn-on-stderr", no_argument, 0, 'W'},
204 {"warn-on-stderr", no_argument, 0, 'W'}, 194 {"proto1", no_argument, 0, '1'},
205 {"proto1", no_argument, 0, '1'}, 195 {"proto2", no_argument, 0, '2'},
206 {"proto2", no_argument, 0, '2'}, 196 {"use-ipv4", no_argument, 0, '4'},
207 {"use-ipv4", no_argument, 0, '4'}, 197 {"use-ipv6", no_argument, 0, '6'},
208 {"use-ipv6", no_argument, 0, '6'}, 198 {"ssh-option", required_argument, 0, 'o'},
209 {"ssh-option", required_argument, 0, 'o'}, 199 {"quiet", no_argument, 0, 'q'},
210 {"quiet", no_argument, 0, 'q'}, 200 {"configfile", optional_argument, 0, 'F'},
211 {"configfile", optional_argument, 0, 'F'}, 201 {0, 0, 0, 0}};
212 {0, 0, 0, 0}
213 };
214 202
215 if (argc < 2) 203 if (argc < 2)
216 return ERROR; 204 return ERROR;
217 205
218 for (c = 1; c < argc; c++) 206 for (c = 1; c < argc; c++)
219 if (strcmp ("-to", argv[c]) == 0) 207 if (strcmp("-to", argv[c]) == 0)
220 strcpy (argv[c], "-t"); 208 strcpy(argv[c], "-t");
221 209
222 while (1) { 210 while (1) {
223 c = getopt_long (argc, argv, "Vvh1246fqt:UH:O:p:i:u:l:C:S::E::n:s:o:F:", longopts, 211 c = getopt_long(argc, argv, "Vvh1246fqt:UH:O:p:i:u:l:C:S::E::n:s:o:F:", longopts, &option);
224 &option);
225 212
226 if (c == -1 || c == EOF) 213 if (c == -1 || c == EOF)
227 break; 214 break;
228 215
229 switch (c) { 216 switch (c) {
230 case 'V': /* version */ 217 case 'V': /* version */
231 print_revision (progname, NP_VERSION); 218 print_revision(progname, NP_VERSION);
232 exit (STATE_UNKNOWN); 219 exit(STATE_UNKNOWN);
233 case 'h': /* help */ 220 case 'h': /* help */
234 print_help (); 221 print_help();
235 exit (STATE_UNKNOWN); 222 exit(STATE_UNKNOWN);
236 case 'v': /* help */ 223 case 'v': /* help */
237 verbose = true; 224 verbose = true;
238 break; 225 break;
239 case 't': /* timeout period */ 226 case 't': /* timeout period */
240 if (!is_integer (optarg)) 227 if (!is_integer(optarg))
241 usage_va(_("Timeout interval must be a positive integer")); 228 usage_va(_("Timeout interval must be a positive integer"));
242 else 229 else
243 timeout_interval = atoi (optarg); 230 timeout_interval = atoi(optarg);
244 break; 231 break;
245 case 'U': 232 case 'U':
246 unknown_timeout = true; 233 unknown_timeout = true;
247 break; 234 break;
248 case 'H': /* host */ 235 case 'H': /* host */
249 hostname = optarg; 236 hostname = optarg;
250 break; 237 break;
251 case 'p': /* port number */ 238 case 'p': /* port number */
252 if (!is_integer (optarg)) 239 if (!is_integer(optarg))
253 usage_va(_("Port must be a positive integer")); 240 usage_va(_("Port must be a positive integer"));
254 comm_append("-p"); 241 comm_append("-p");
255 comm_append(optarg); 242 comm_append(optarg);
256 break; 243 break;
257 case 'O': /* output file */ 244 case 'O': /* output file */
258 outputfile = optarg; 245 outputfile = optarg;
259 passive = true; 246 passive = true;
260 break; 247 break;
261 case 's': /* description of service to check */ 248 case 's': /* description of service to check */
262 p1 = optarg; 249 p1 = optarg;
263 service = realloc (service, (++services) * sizeof(char *)); 250 service = realloc(service, (++services) * sizeof(char *));
264 while ((p2 = index (p1, ':'))) { 251 while ((p2 = index(p1, ':'))) {
265 *p2 = '\0'; 252 *p2 = '\0';
266 service[services - 1] = p1; 253 service[services - 1] = p1;
267 service = realloc (service, (++services) * sizeof(char *)); 254 service = realloc(service, (++services) * sizeof(char *));
268 p1 = p2 + 1; 255 p1 = p2 + 1;
269 } 256 }
270 service[services - 1] = p1; 257 service[services - 1] = p1;
271 break; 258 break;
272 case 'n': /* short name of host in the monitoring configuration */ 259 case 'n': /* short name of host in the monitoring configuration */
273 host_shortname = optarg; 260 host_shortname = optarg;
274 break; 261 break;
275 262
@@ -277,67 +264,67 @@ process_arguments (int argc, char **argv)
277 comm_append("-l"); 264 comm_append("-l");
278 comm_append(optarg); 265 comm_append(optarg);
279 break; 266 break;
280 case 'l': /* login name */ 267 case 'l': /* login name */
281 comm_append("-l"); 268 comm_append("-l");
282 comm_append(optarg); 269 comm_append(optarg);
283 break; 270 break;
284 case 'i': /* identity */ 271 case 'i': /* identity */
285 comm_append("-i"); 272 comm_append("-i");
286 comm_append(optarg); 273 comm_append(optarg);
287 break; 274 break;
288 275
289 case '1': /* Pass these switches directly to ssh */ 276 case '1': /* Pass these switches directly to ssh */
290 comm_append("-1"); 277 comm_append("-1");
291 break; 278 break;
292 case '2': /* 1 to force version 1, 2 to force version 2 */ 279 case '2': /* 1 to force version 1, 2 to force version 2 */
293 comm_append("-2"); 280 comm_append("-2");
294 break; 281 break;
295 case '4': /* -4 for IPv4 */ 282 case '4': /* -4 for IPv4 */
296 comm_append("-4"); 283 comm_append("-4");
297 break; 284 break;
298 case '6': /* -6 for IPv6 */ 285 case '6': /* -6 for IPv6 */
299 comm_append("-6"); 286 comm_append("-6");
300 break; 287 break;
301 case 'f': /* fork to background */ 288 case 'f': /* fork to background */
302 comm_append("-f"); 289 comm_append("-f");
303 break; 290 break;
304 case 'C': /* Command for remote machine */ 291 case 'C': /* Command for remote machine */
305 commands++; 292 commands++;
306 if (commands > 1) 293 if (commands > 1)
307 xasprintf (&remotecmd, "%s;echo STATUS CODE: $?;", remotecmd); 294 xasprintf(&remotecmd, "%s;echo STATUS CODE: $?;", remotecmd);
308 xasprintf (&remotecmd, "%s%s", remotecmd, optarg); 295 xasprintf(&remotecmd, "%s%s", remotecmd, optarg);
309 break; 296 break;
310 case 'S': /* skip n (or all) lines on stdout */ 297 case 'S': /* skip n (or all) lines on stdout */
311 if (optarg == NULL) 298 if (optarg == NULL)
312 skip_stdout = -1; /* skip all output on stdout */ 299 skip_stdout = -1; /* skip all output on stdout */
313 else if (!is_integer (optarg)) 300 else if (!is_integer(optarg))
314 usage_va(_("skip-stdout argument must be an integer")); 301 usage_va(_("skip-stdout argument must be an integer"));
315 else 302 else
316 skip_stdout = atoi (optarg); 303 skip_stdout = atoi(optarg);
317 break; 304 break;
318 case 'E': /* skip n (or all) lines on stderr */ 305 case 'E': /* skip n (or all) lines on stderr */
319 if (optarg == NULL) 306 if (optarg == NULL)
320 skip_stderr = -1; /* skip all output on stderr */ 307 skip_stderr = -1; /* skip all output on stderr */
321 else if (!is_integer (optarg)) 308 else if (!is_integer(optarg))
322 usage_va(_("skip-stderr argument must be an integer")); 309 usage_va(_("skip-stderr argument must be an integer"));
323 else 310 else
324 skip_stderr = atoi (optarg); 311 skip_stderr = atoi(optarg);
325 break; 312 break;
326 case 'W': /* exit with warning if there is an output on stderr */ 313 case 'W': /* exit with warning if there is an output on stderr */
327 warn_on_stderr = 1; 314 warn_on_stderr = 1;
328 break; 315 break;
329 case 'o': /* Extra options for the ssh command */ 316 case 'o': /* Extra options for the ssh command */
330 comm_append("-o"); 317 comm_append("-o");
331 comm_append(optarg); 318 comm_append(optarg);
332 break; 319 break;
333 case 'q': /* Tell the ssh command to be quiet */ 320 case 'q': /* Tell the ssh command to be quiet */
334 comm_append("-q"); 321 comm_append("-q");
335 break; 322 break;
336 case 'F': /* ssh configfile */ 323 case 'F': /* ssh configfile */
337 comm_append("-F"); 324 comm_append("-F");
338 comm_append(optarg); 325 comm_append(optarg);
339 break; 326 break;
340 default: /* help */ 327 default: /* help */
341 usage5(); 328 usage5();
342 } 329 }
343 } 330 }
@@ -345,7 +332,7 @@ process_arguments (int argc, char **argv)
345 c = optind; 332 c = optind;
346 if (hostname == NULL) { 333 if (hostname == NULL) {
347 if (c <= argc) { 334 if (c <= argc) {
348 die (STATE_UNKNOWN, _("%s: You must provide a host name\n"), progname); 335 die(STATE_UNKNOWN, _("%s: You must provide a host name\n"), progname);
349 } 336 }
350 hostname = argv[c++]; 337 hostname = argv[c++];
351 } 338 }
@@ -353,143 +340,130 @@ process_arguments (int argc, char **argv)
353 if (strlen(remotecmd) == 0) { 340 if (strlen(remotecmd) == 0) {
354 for (; c < argc; c++) 341 for (; c < argc; c++)
355 if (strlen(remotecmd) > 0) 342 if (strlen(remotecmd) > 0)
356 xasprintf (&remotecmd, "%s %s", remotecmd, argv[c]); 343 xasprintf(&remotecmd, "%s %s", remotecmd, argv[c]);
357 else 344 else
358 xasprintf (&remotecmd, "%s", argv[c]); 345 xasprintf(&remotecmd, "%s", argv[c]);
359 } 346 }
360 347
361 if (commands > 1 || passive) 348 if (commands > 1 || passive)
362 xasprintf (&remotecmd, "%s;echo STATUS CODE: $?;", remotecmd); 349 xasprintf(&remotecmd, "%s;echo STATUS CODE: $?;", remotecmd);
363 350
364 if (remotecmd == NULL || strlen (remotecmd) <= 1) 351 if (remotecmd == NULL || strlen(remotecmd) <= 1)
365 usage_va(_("No remotecmd")); 352 usage_va(_("No remotecmd"));
366 353
367 comm_append(hostname); 354 comm_append(hostname);
368 comm_append(remotecmd); 355 comm_append(remotecmd);
369 356
370 return validate_arguments (); 357 return validate_arguments();
371} 358}
372 359
373 360void comm_append(const char *str) {
374void
375comm_append (const char *str)
376{
377 361
378 if (++commargc > NP_MAXARGS) 362 if (++commargc > NP_MAXARGS)
379 die(STATE_UNKNOWN, _("%s: Argument limit of %d exceeded\n"), progname, NP_MAXARGS); 363 die(STATE_UNKNOWN, _("%s: Argument limit of %d exceeded\n"), progname, NP_MAXARGS);
380 364
381 if ((commargv = (char **)realloc(commargv, (commargc+1) * sizeof(char *))) == NULL) 365 if ((commargv = (char **)realloc(commargv, (commargc + 1) * sizeof(char *))) == NULL)
382 die(STATE_UNKNOWN, _("Can not (re)allocate 'commargv' buffer\n")); 366 die(STATE_UNKNOWN, _("Can not (re)allocate 'commargv' buffer\n"));
383 367
384 commargv[commargc-1] = strdup(str); 368 commargv[commargc - 1] = strdup(str);
385 commargv[commargc] = NULL; 369 commargv[commargc] = NULL;
386
387} 370}
388 371
389int 372int validate_arguments(void) {
390validate_arguments (void)
391{
392 if (remotecmd == NULL || hostname == NULL) 373 if (remotecmd == NULL || hostname == NULL)
393 return ERROR; 374 return ERROR;
394 375
395 if (passive && commands != services) 376 if (passive && commands != services)
396 die (STATE_UNKNOWN, _("%s: In passive mode, you must provide a service name for each command.\n"), progname); 377 die(STATE_UNKNOWN, _("%s: In passive mode, you must provide a service name for each command.\n"), progname);
397 378
398 if (passive && host_shortname == NULL) 379 if (passive && host_shortname == NULL)
399 die (STATE_UNKNOWN, _("%s: In passive mode, you must provide the host short name from the monitoring configs.\n"), progname); 380 die(STATE_UNKNOWN, _("%s: In passive mode, you must provide the host short name from the monitoring configs.\n"), progname);
400 381
401 return OK; 382 return OK;
402} 383}
403 384
404 385void print_help(void) {
405void 386 print_revision(progname, NP_VERSION);
406print_help (void) 387
407{ 388 printf("Copyright (c) 1999 Karl DeBisschop <kdebisschop@users.sourceforge.net>\n");
408 print_revision (progname, NP_VERSION); 389 printf(COPYRIGHT, copyright, email);
409 390
410 printf ("Copyright (c) 1999 Karl DeBisschop <kdebisschop@users.sourceforge.net>\n"); 391 printf(_("This plugin uses SSH to execute commands on a remote host"));
411 printf (COPYRIGHT, copyright, email); 392
412 393 printf("\n\n");
413 printf (_("This plugin uses SSH to execute commands on a remote host")); 394
414 395 print_usage();
415 printf ("\n\n"); 396
416 397 printf(UT_HELP_VRSN);
417 print_usage (); 398
418 399 printf(UT_EXTRA_OPTS);
419 printf (UT_HELP_VRSN); 400
420 401 printf(UT_HOST_PORT, 'p', "none");
421 printf (UT_EXTRA_OPTS); 402
422 403 printf(UT_IPv46);
423 printf (UT_HOST_PORT, 'p', "none"); 404
424 405 printf(" %s\n", "-1, --proto1");
425 printf (UT_IPv46); 406 printf(" %s\n", _("tell ssh to use Protocol 1 [optional]"));
426 407 printf(" %s\n", "-2, --proto2");
427 printf (" %s\n", "-1, --proto1"); 408 printf(" %s\n", _("tell ssh to use Protocol 2 [optional]"));
428 printf (" %s\n", _("tell ssh to use Protocol 1 [optional]")); 409 printf(" %s\n", "-S, --skip-stdout[=n]");
429 printf (" %s\n", "-2, --proto2"); 410 printf(" %s\n", _("Ignore all or (if specified) first n lines on STDOUT [optional]"));
430 printf (" %s\n", _("tell ssh to use Protocol 2 [optional]")); 411 printf(" %s\n", "-E, --skip-stderr[=n]");
431 printf (" %s\n", "-S, --skip-stdout[=n]"); 412 printf(" %s\n", _("Ignore all or (if specified) first n lines on STDERR [optional]"));
432 printf (" %s\n", _("Ignore all or (if specified) first n lines on STDOUT [optional]")); 413 printf(" %s\n", "-W, --warn-on-stderr]");
433 printf (" %s\n", "-E, --skip-stderr[=n]"); 414 printf(" %s\n", _("Exit with an warning, if there is an output on STDERR"));
434 printf (" %s\n", _("Ignore all or (if specified) first n lines on STDERR [optional]")); 415 printf(" %s\n", "-f");
435 printf (" %s\n", "-W, --warn-on-stderr]"); 416 printf(" %s\n", _("tells ssh to fork rather than create a tty [optional]. This will always return OK if ssh is executed"));
436 printf (" %s\n", _("Exit with an warning, if there is an output on STDERR")); 417 printf(" %s\n", "-C, --command='COMMAND STRING'");
437 printf (" %s\n", "-f"); 418 printf(" %s\n", _("command to execute on the remote machine"));
438 printf (" %s\n", _("tells ssh to fork rather than create a tty [optional]. This will always return OK if ssh is executed")); 419 printf(" %s\n", "-l, --logname=USERNAME");
439 printf (" %s\n","-C, --command='COMMAND STRING'"); 420 printf(" %s\n", _("SSH user name on remote host [optional]"));
440 printf (" %s\n", _("command to execute on the remote machine")); 421 printf(" %s\n", "-i, --identity=KEYFILE");
441 printf (" %s\n","-l, --logname=USERNAME"); 422 printf(" %s\n", _("identity of an authorized key [optional]"));
442 printf (" %s\n", _("SSH user name on remote host [optional]")); 423 printf(" %s\n", "-O, --output=FILE");
443 printf (" %s\n","-i, --identity=KEYFILE"); 424 printf(" %s\n", _("external command file for monitoring [optional]"));
444 printf (" %s\n", _("identity of an authorized key [optional]")); 425 printf(" %s\n", "-s, --services=LIST");
445 printf (" %s\n","-O, --output=FILE"); 426 printf(" %s\n", _("list of monitoring service names, separated by ':' [optional]"));
446 printf (" %s\n", _("external command file for monitoring [optional]")); 427 printf(" %s\n", "-n, --name=NAME");
447 printf (" %s\n","-s, --services=LIST"); 428 printf(" %s\n", _("short name of host in the monitoring configuration [optional]"));
448 printf (" %s\n", _("list of monitoring service names, separated by ':' [optional]")); 429 printf(" %s\n", "-o, --ssh-option=OPTION");
449 printf (" %s\n","-n, --name=NAME"); 430 printf(" %s\n", _("Call ssh with '-o OPTION' (may be used multiple times) [optional]"));
450 printf (" %s\n", _("short name of host in the monitoring configuration [optional]")); 431 printf(" %s\n", "-F, --configfile");
451 printf (" %s\n","-o, --ssh-option=OPTION"); 432 printf(" %s\n", _("Tell ssh to use this configfile [optional]"));
452 printf (" %s\n", _("Call ssh with '-o OPTION' (may be used multiple times) [optional]")); 433 printf(" %s\n", "-q, --quiet");
453 printf (" %s\n","-F, --configfile"); 434 printf(" %s\n", _("Tell ssh to suppress warning and diagnostic messages [optional]"));
454 printf (" %s\n", _("Tell ssh to use this configfile [optional]")); 435 printf(UT_WARN_CRIT);
455 printf (" %s\n","-q, --quiet"); 436 printf(UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
456 printf (" %s\n", _("Tell ssh to suppress warning and diagnostic messages [optional]")); 437 printf(" %s\n", "-U, --unknown-timeout");
457 printf (UT_WARN_CRIT); 438 printf(" %s\n", _("Make connection problems return UNKNOWN instead of CRITICAL"));
458 printf (UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); 439 printf(UT_VERBOSE);
459 printf (" %s\n","-U, --unknown-timeout"); 440 printf("\n");
460 printf (" %s\n", _("Make connection problems return UNKNOWN instead of CRITICAL")); 441 printf(" %s\n", _("The most common mode of use is to refer to a local identity file with"));
461 printf (UT_VERBOSE); 442 printf(" %s\n", _("the '-i' option. In this mode, the identity pair should have a null"));
443 printf(" %s\n", _("passphrase and the public key should be listed in the authorized_keys"));
444 printf(" %s\n", _("file of the remote host. Usually the key will be restricted to running"));
445 printf(" %s\n", _("only one command on the remote server. If the remote SSH server tracks"));
446 printf(" %s\n", _("invocation arguments, the one remote program may be an agent that can"));
447 printf(" %s\n", _("execute additional commands as proxy"));
448 printf("\n");
449 printf(" %s\n", _("To use passive mode, provide multiple '-C' options, and provide"));
450 printf(" %s\n", _("all of -O, -s, and -n options (servicelist order must match '-C'options)"));
462 printf("\n"); 451 printf("\n");
463 printf (" %s\n", _("The most common mode of use is to refer to a local identity file with")); 452 printf("%s\n", _("Examples:"));
464 printf (" %s\n", _("the '-i' option. In this mode, the identity pair should have a null")); 453 printf(" %s\n", "$ check_by_ssh -H localhost -n lh -s c1:c2:c3 -C uptime -C uptime -C uptime -O /tmp/foo");
465 printf (" %s\n", _("passphrase and the public key should be listed in the authorized_keys")); 454 printf(" %s\n", "$ cat /tmp/foo");
466 printf (" %s\n", _("file of the remote host. Usually the key will be restricted to running")); 455 printf(" %s\n", "[1080933700] PROCESS_SERVICE_CHECK_RESULT;flint;c1;0; up 2 days");
467 printf (" %s\n", _("only one command on the remote server. If the remote SSH server tracks")); 456 printf(" %s\n", "[1080933700] PROCESS_SERVICE_CHECK_RESULT;flint;c2;0; up 2 days");
468 printf (" %s\n", _("invocation arguments, the one remote program may be an agent that can")); 457 printf(" %s\n", "[1080933700] PROCESS_SERVICE_CHECK_RESULT;flint;c3;0; up 2 days");
469 printf (" %s\n", _("execute additional commands as proxy"));
470 printf("\n");
471 printf (" %s\n", _("To use passive mode, provide multiple '-C' options, and provide"));
472 printf (" %s\n", _("all of -O, -s, and -n options (servicelist order must match '-C'options)"));
473 printf ("\n");
474 printf ("%s\n", _("Examples:"));
475 printf (" %s\n", "$ check_by_ssh -H localhost -n lh -s c1:c2:c3 -C uptime -C uptime -C uptime -O /tmp/foo");
476 printf (" %s\n", "$ cat /tmp/foo");
477 printf (" %s\n", "[1080933700] PROCESS_SERVICE_CHECK_RESULT;flint;c1;0; up 2 days");
478 printf (" %s\n", "[1080933700] PROCESS_SERVICE_CHECK_RESULT;flint;c2;0; up 2 days");
479 printf (" %s\n", "[1080933700] PROCESS_SERVICE_CHECK_RESULT;flint;c3;0; up 2 days");
480 458
481 printf(UT_SUPPORT); 459 printf(UT_SUPPORT);
482} 460}
483 461
484 462void print_usage(void) {
485 463 printf("%s\n", _("Usage:"));
486void 464 printf(" %s -H <host> -C <command> [-fqvU] [-1|-2] [-4|-6]\n"
487print_usage (void) 465 " [-S [lines]] [-E [lines]] [-W] [-t timeout] [-i identity]\n"
488{ 466 " [-l user] [-n name] [-s servicelist] [-O outputfile]\n"
489 printf ("%s\n", _("Usage:")); 467 " [-p port] [-o ssh-option] [-F configfile]\n",
490 printf (" %s -H <host> -C <command> [-fqvU] [-1|-2] [-4|-6]\n" 468 progname);
491 " [-S [lines]] [-E [lines]] [-W] [-t timeout] [-i identity]\n"
492 " [-l user] [-n name] [-s servicelist] [-O outputfile]\n"
493 " [-p port] [-o ssh-option] [-F configfile]\n",
494 progname);
495} 469}
diff --git a/plugins/check_cluster.c b/plugins/check_cluster.c
index e1ede9f7..b40c38c7 100644
--- a/plugins/check_cluster.c
+++ b/plugins/check_cluster.c
@@ -1,92 +1,92 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* check_cluster.c - Host and Service Cluster Plugin for Monitoring 3 * check_cluster.c - Host and Service Cluster Plugin for Monitoring
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 2000-2004 Ethan Galstad (nagios@nagios.org) 6 * Copyright (c) 2000-2004 Ethan Galstad (nagios@nagios.org)
7* Copyright (c) 2007 Monitoring Plugins Development Team 7 * Copyright (c) 2007-2024 Monitoring Plugins Development Team
8* 8 *
9* This program is free software: you can redistribute it and/or modify 9 * This program is free software: you can redistribute it and/or modify
10* it under the terms of the GNU General Public License as published by 10 * it under the terms of the GNU General Public License as published by
11* the Free Software Foundation, either version 3 of the License, or 11 * the Free Software Foundation, either version 3 of the License, or
12* (at your option) any later version. 12 * (at your option) any later version.
13* 13 *
14* This program is distributed in the hope that it will be useful, 14 * This program is distributed in the hope that it will be useful,
15* but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17* GNU General Public License for more details. 17 * GNU General Public License for more details.
18* 18 *
19* You should have received a copy of the GNU General Public License 19 * You should have received a copy of the GNU General Public License
20* along with this program. If not, see <http://www.gnu.org/licenses/>. 20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21* 21 *
22* 22 *
23*****************************************************************************/ 23 *****************************************************************************/
24 24
25const char *progname = "check_cluster"; 25const char *progname = "check_cluster";
26const char *copyright = "2000-2007"; 26const char *copyright = "2000-2024";
27const char *email = "devel@monitoring-plugins.org"; 27const char *email = "devel@monitoring-plugins.org";
28 28
29#include "common.h" 29#include "common.h"
30#include "utils.h" 30#include "utils.h"
31#include "utils_base.h" 31#include "utils_base.h"
32 32
33#define CHECK_SERVICES 1 33enum {
34#define CHECK_HOSTS 2 34 CHECK_SERVICES = 1,
35 CHECK_HOSTS = 2
36};
35 37
36void print_help (void); 38static void print_help(void);
37void print_usage (void); 39void print_usage(void);
38 40
39int total_services_ok=0; 41static int total_services_ok = 0;
40int total_services_warning=0; 42static int total_services_warning = 0;
41int total_services_unknown=0; 43static int total_services_unknown = 0;
42int total_services_critical=0; 44static int total_services_critical = 0;
43 45
44int total_hosts_up=0; 46static int total_hosts_up = 0;
45int total_hosts_down=0; 47static int total_hosts_down = 0;
46int total_hosts_unreachable=0; 48static int total_hosts_unreachable = 0;
47 49
48char *warn_threshold; 50static char *warn_threshold;
49char *crit_threshold; 51static char *crit_threshold;
50 52
51int check_type=CHECK_SERVICES; 53static int check_type = CHECK_SERVICES;
52 54
53char *data_vals=NULL; 55static char *data_vals = NULL;
54char *label=NULL; 56static char *label = NULL;
55 57
56int verbose=0; 58static int verbose = 0;
57 59
58int process_arguments(int,char **); 60static int process_arguments(int /*argc*/, char ** /*argv*/);
59 61
60 62int main(int argc, char **argv) {
61
62int main(int argc, char **argv){
63 char *ptr; 63 char *ptr;
64 int data_val; 64 int data_val;
65 int return_code=STATE_OK; 65 int return_code = STATE_OK;
66 thresholds *thresholds = NULL; 66 thresholds *thresholds = NULL;
67 67
68 setlocale (LC_ALL, ""); 68 setlocale(LC_ALL, "");
69 bindtextdomain (PACKAGE, LOCALEDIR); 69 bindtextdomain(PACKAGE, LOCALEDIR);
70 textdomain (PACKAGE); 70 textdomain(PACKAGE);
71 71
72 /* Parse extra opts if any */ 72 /* Parse extra opts if any */
73 argv=np_extra_opts(&argc, argv, progname); 73 argv = np_extra_opts(&argc, argv, progname);
74 74
75 if(process_arguments(argc,argv)==ERROR) 75 if (process_arguments(argc, argv) == ERROR)
76 usage(_("Could not parse arguments")); 76 usage(_("Could not parse arguments"));
77 77
78 /* Initialize the thresholds */ 78 /* Initialize the thresholds */
79 set_thresholds(&thresholds, warn_threshold, crit_threshold); 79 set_thresholds(&thresholds, warn_threshold, crit_threshold);
80 if(verbose) 80 if (verbose)
81 print_thresholds("check_cluster", thresholds); 81 print_thresholds("check_cluster", thresholds);
82 82
83 /* check the data values */ 83 /* check the data values */
84 for(ptr=strtok(data_vals,",");ptr!=NULL;ptr=strtok(NULL,",")){ 84 for (ptr = strtok(data_vals, ","); ptr != NULL; ptr = strtok(NULL, ",")) {
85 85
86 data_val=atoi(ptr); 86 data_val = atoi(ptr);
87 87
88 if(check_type==CHECK_SERVICES){ 88 if (check_type == CHECK_SERVICES) {
89 switch(data_val){ 89 switch (data_val) {
90 case 0: 90 case 0:
91 total_services_ok++; 91 total_services_ok++;
92 break; 92 break;
@@ -101,10 +101,9 @@ int main(int argc, char **argv){
101 break; 101 break;
102 default: 102 default:
103 break; 103 break;
104 } 104 }
105 } 105 } else {
106 else{ 106 switch (data_val) {
107 switch(data_val){
108 case 0: 107 case 0:
109 total_hosts_up++; 108 total_hosts_up++;
110 break; 109 break;
@@ -116,67 +115,54 @@ int main(int argc, char **argv){
116 break; 115 break;
117 default: 116 default:
118 break; 117 break;
119 } 118 }
120 } 119 }
121 } 120 }
122
123 121
124 /* return the status of the cluster */ 122 /* return the status of the cluster */
125 if(check_type==CHECK_SERVICES){ 123 if (check_type == CHECK_SERVICES) {
126 return_code=get_status(total_services_warning+total_services_unknown+total_services_critical, thresholds); 124 return_code = get_status(total_services_warning + total_services_unknown + total_services_critical, thresholds);
127 printf("CLUSTER %s: %s: %d ok, %d warning, %d unknown, %d critical\n", 125 printf("CLUSTER %s: %s: %d ok, %d warning, %d unknown, %d critical\n", state_text(return_code),
128 state_text(return_code), (label==NULL)?"Service cluster":label, 126 (label == NULL) ? "Service cluster" : label, total_services_ok, total_services_warning, total_services_unknown,
129 total_services_ok,total_services_warning, 127 total_services_critical);
130 total_services_unknown,total_services_critical); 128 } else {
131 } 129 return_code = get_status(total_hosts_down + total_hosts_unreachable, thresholds);
132 else{ 130 printf("CLUSTER %s: %s: %d up, %d down, %d unreachable\n", state_text(return_code), (label == NULL) ? "Host cluster" : label,
133 return_code=get_status(total_hosts_down+total_hosts_unreachable, thresholds); 131 total_hosts_up, total_hosts_down, total_hosts_unreachable);
134 printf("CLUSTER %s: %s: %d up, %d down, %d unreachable\n",
135 state_text(return_code), (label==NULL)?"Host cluster":label,
136 total_hosts_up,total_hosts_down,total_hosts_unreachable);
137 } 132 }
138 133
139 return return_code; 134 return return_code;
140} 135}
141 136
142 137int process_arguments(int argc, char **argv) {
143
144int process_arguments(int argc, char **argv){
145 int c; 138 int c;
146 char *ptr; 139 char *ptr;
147 int option=0; 140 int option = 0;
148 static struct option longopts[]={ 141 static struct option longopts[] = {{"data", required_argument, 0, 'd'}, {"warning", required_argument, 0, 'w'},
149 {"data", required_argument,0,'d'}, 142 {"critical", required_argument, 0, 'c'}, {"label", required_argument, 0, 'l'},
150 {"warning", required_argument,0,'w'}, 143 {"host", no_argument, 0, 'h'}, {"service", no_argument, 0, 's'},
151 {"critical", required_argument,0,'c'}, 144 {"verbose", no_argument, 0, 'v'}, {"version", no_argument, 0, 'V'},
152 {"label", required_argument,0,'l'}, 145 {"help", no_argument, 0, 'H'}, {0, 0, 0, 0}};
153 {"host", no_argument, 0,'h'},
154 {"service", no_argument, 0,'s'},
155 {"verbose", no_argument, 0,'v'},
156 {"version", no_argument, 0,'V'},
157 {"help", no_argument, 0,'H'},
158 {0,0,0,0}
159 };
160 146
161 /* no options were supplied */ 147 /* no options were supplied */
162 if(argc<2) 148 if (argc < 2)
163 return ERROR; 149 return ERROR;
164 150
165 while(1){ 151 while (1) {
166 152
167 c=getopt_long(argc,argv,"hHsvVw:c:d:l:",longopts,&option); 153 c = getopt_long(argc, argv, "hHsvVw:c:d:l:", longopts, &option);
168 154
169 if(c==-1 || c==EOF || c==1) 155 if (c == -1 || c == EOF || c == 1)
170 break; 156 break;
171 157
172 switch(c){ 158 switch (c) {
173 159
174 case 'h': /* host cluster */ 160 case 'h': /* host cluster */
175 check_type=CHECK_HOSTS; 161 check_type = CHECK_HOSTS;
176 break; 162 break;
177 163
178 case 's': /* service cluster */ 164 case 's': /* service cluster */
179 check_type=CHECK_SERVICES; 165 check_type = CHECK_SERVICES;
180 break; 166 break;
181 167
182 case 'w': /* warning threshold */ 168 case 'w': /* warning threshold */
@@ -188,20 +174,20 @@ int process_arguments(int argc, char **argv){
188 break; 174 break;
189 175
190 case 'd': /* data values */ 176 case 'd': /* data values */
191 data_vals=(char *)strdup(optarg); 177 data_vals = (char *)strdup(optarg);
192 /* validate data */ 178 /* validate data */
193 for (ptr=data_vals;ptr!=NULL;ptr+=2){ 179 for (ptr = data_vals; ptr != NULL; ptr += 2) {
194 if (ptr[0]<'0' || ptr[0]>'3') 180 if (ptr[0] < '0' || ptr[0] > '3')
195 return ERROR; 181 return ERROR;
196 if (ptr[1]=='\0') 182 if (ptr[1] == '\0')
197 break; 183 break;
198 if (ptr[1]!=',') 184 if (ptr[1] != ',')
199 return ERROR; 185 return ERROR;
200 } 186 }
201 break; 187 break;
202 188
203 case 'l': /* text label */ 189 case 'l': /* text label */
204 label=(char *)strdup(optarg); 190 label = (char *)strdup(optarg);
205 break; 191 break;
206 192
207 case 'v': /* verbose */ 193 case 'v': /* verbose */
@@ -209,8 +195,8 @@ int process_arguments(int argc, char **argv){
209 break; 195 break;
210 196
211 case 'V': /* version */ 197 case 'V': /* version */
212 print_revision (progname, NP_VERSION); 198 print_revision(progname, NP_VERSION);
213 exit (STATE_UNKNOWN); 199 exit(STATE_UNKNOWN);
214 break; 200 break;
215 201
216 case 'H': /* help */ 202 case 'H': /* help */
@@ -221,20 +207,18 @@ int process_arguments(int argc, char **argv){
221 default: 207 default:
222 return ERROR; 208 return ERROR;
223 break; 209 break;
224 } 210 }
225 } 211 }
226 212
227 if(data_vals==NULL) 213 if (data_vals == NULL)
228 return ERROR; 214 return ERROR;
229 215
230 return OK; 216 return OK;
231} 217}
232 218
233void 219void print_help(void) {
234print_help(void)
235{
236 print_revision(progname, NP_VERSION); 220 print_revision(progname, NP_VERSION);
237 printf ("Copyright (c) 2000-2004 Ethan Galstad (nagios@nagios.org)\n"); 221 printf("Copyright (c) 2000-2004 Ethan Galstad (nagios@nagios.org)\n");
238 printf(COPYRIGHT, copyright, email); 222 printf(COPYRIGHT, copyright, email);
239 223
240 printf(_("Host/Service Cluster Plugin for Monitoring")); 224 printf(_("Host/Service Cluster Plugin for Monitoring"));
@@ -245,21 +229,21 @@ print_help(void)
245 printf("\n"); 229 printf("\n");
246 printf("%s\n", _("Options:")); 230 printf("%s\n", _("Options:"));
247 printf(UT_EXTRA_OPTS); 231 printf(UT_EXTRA_OPTS);
248 printf (" %s\n", "-s, --service"); 232 printf(" %s\n", "-s, --service");
249 printf (" %s\n", _("Check service cluster status")); 233 printf(" %s\n", _("Check service cluster status"));
250 printf (" %s\n", "-h, --host"); 234 printf(" %s\n", "-h, --host");
251 printf (" %s\n", _("Check host cluster status")); 235 printf(" %s\n", _("Check host cluster status"));
252 printf (" %s\n", "-l, --label=STRING"); 236 printf(" %s\n", "-l, --label=STRING");
253 printf (" %s\n", _("Optional prepended text output (i.e. \"Host cluster\")")); 237 printf(" %s\n", _("Optional prepended text output (i.e. \"Host cluster\")"));
254 printf (" %s\n", "-w, --warning=THRESHOLD"); 238 printf(" %s\n", "-w, --warning=THRESHOLD");
255 printf (" %s\n", _("Specifies the range of hosts or services in cluster that must be in a")); 239 printf(" %s\n", _("Specifies the range of hosts or services in cluster that must be in a"));
256 printf (" %s\n", _("non-OK state in order to return a WARNING status level")); 240 printf(" %s\n", _("non-OK state in order to return a WARNING status level"));
257 printf (" %s\n", "-c, --critical=THRESHOLD"); 241 printf(" %s\n", "-c, --critical=THRESHOLD");
258 printf (" %s\n", _("Specifies the range of hosts or services in cluster that must be in a")); 242 printf(" %s\n", _("Specifies the range of hosts or services in cluster that must be in a"));
259 printf (" %s\n", _("non-OK state in order to return a CRITICAL status level")); 243 printf(" %s\n", _("non-OK state in order to return a CRITICAL status level"));
260 printf (" %s\n", "-d, --data=LIST"); 244 printf(" %s\n", "-d, --data=LIST");
261 printf (" %s\n", _("The status codes of the hosts or services in the cluster, separated by")); 245 printf(" %s\n", _("The status codes of the hosts or services in the cluster, separated by"));
262 printf (" %s\n", _("commas")); 246 printf(" %s\n", _("commas"));
263 247
264 printf(UT_VERBOSE); 248 printf(UT_VERBOSE);
265 249
@@ -267,23 +251,18 @@ print_help(void)
267 printf("%s\n", _("Notes:")); 251 printf("%s\n", _("Notes:"));
268 printf(UT_THRESHOLDS_NOTES); 252 printf(UT_THRESHOLDS_NOTES);
269 253
270 printf ("\n"); 254 printf("\n");
271 printf ("%s\n", _("Examples:")); 255 printf("%s\n", _("Examples:"));
272 printf (" %s\n", "check_cluster -s -d 2,0,2,0 -c @3:"); 256 printf(" %s\n", "check_cluster -s -d 2,0,2,0 -c @3:");
273 printf (" %s\n", _("Will alert critical if there are 3 or more service data points in a non-OK") ); 257 printf(" %s\n", _("Will alert critical if there are 3 or more service data points in a non-OK"));
274 printf (" %s\n", _("state.") ); 258 printf(" %s\n", _("state."));
275 259
276 printf(UT_SUPPORT); 260 printf(UT_SUPPORT);
277} 261}
278 262
279 263void print_usage(void) {
280void
281print_usage(void)
282{
283 264
284 printf("%s\n", _("Usage:")); 265 printf("%s\n", _("Usage:"));
285 printf(" %s (-s | -h) -d val1[,val2,...,valn] [-l label]\n", progname); 266 printf(" %s (-s | -h) -d val1[,val2,...,valn] [-l label]\n", progname);
286 printf("[-w threshold] [-c threshold] [-v] [--help]\n"); 267 printf("[-w threshold] [-c threshold] [-v] [--help]\n");
287
288} 268}
289
diff --git a/plugins/check_curl.c b/plugins/check_curl.c
index 8f9a21d2..1d27da28 100644
--- a/plugins/check_curl.c
+++ b/plugins/check_curl.c
@@ -1,40 +1,40 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring check_curl plugin 3 * Monitoring check_curl plugin
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 1999-2019 Monitoring Plugins Development Team 6 * Copyright (c) 1999-2024 Monitoring Plugins Development Team
7* 7 *
8* Description: 8 * Description:
9* 9 *
10* This file contains the check_curl plugin 10 * This file contains the check_curl plugin
11* 11 *
12* This plugin tests the HTTP service on the specified host. It can test 12 * This plugin tests the HTTP service on the specified host. It can test
13* normal (http) and secure (https) servers, follow redirects, search for 13 * normal (http) and secure (https) servers, follow redirects, search for
14* strings and regular expressions, check connection times, and report on 14 * strings and regular expressions, check connection times, and report on
15* certificate expiration times. 15 * certificate expiration times.
16* 16 *
17* This plugin uses functions from the curl library, see 17 * This plugin uses functions from the curl library, see
18* http://curl.haxx.se 18 * http://curl.haxx.se
19* 19 *
20* This program is free software: you can redistribute it and/or modify 20 * This program is free software: you can redistribute it and/or modify
21* it under the terms of the GNU General Public License as published by 21 * it under the terms of the GNU General Public License as published by
22* the Free Software Foundation, either version 3 of the License, or 22 * the Free Software Foundation, either version 3 of the License, or
23* (at your option) any later version. 23 * (at your option) any later version.
24* 24 *
25* This program is distributed in the hope that it will be useful, 25 * This program is distributed in the hope that it will be useful,
26* but WITHOUT ANY WARRANTY; without even the implied warranty of 26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28* GNU General Public License for more details. 28 * GNU General Public License for more details.
29* 29 *
30* You should have received a copy of the GNU General Public License 30 * You should have received a copy of the GNU General Public License
31* along with this program. If not, see <http://www.gnu.org/licenses/>. 31 * along with this program. If not, see <http://www.gnu.org/licenses/>.
32* 32 *
33* 33 *
34*****************************************************************************/ 34 *****************************************************************************/
35const char *progname = "check_curl"; 35const char *progname = "check_curl";
36 36
37const char *copyright = "2006-2019"; 37const char *copyright = "2006-2024";
38const char *email = "devel@monitoring-plugins.org"; 38const char *email = "devel@monitoring-plugins.org";
39 39
40#include <stdbool.h> 40#include <stdbool.h>
@@ -44,7 +44,7 @@ const char *email = "devel@monitoring-plugins.org";
44#include "utils.h" 44#include "utils.h"
45 45
46#ifndef LIBCURL_PROTOCOL_HTTP 46#ifndef LIBCURL_PROTOCOL_HTTP
47#error libcurl compiled without HTTP support, compiling check_curl plugin does not makes a lot of sense 47# error libcurl compiled without HTTP support, compiling check_curl plugin does not makes a lot of sense
48#endif 48#endif
49 49
50#include "curl/curl.h" 50#include "curl/curl.h"
@@ -58,7 +58,7 @@ const char *email = "devel@monitoring-plugins.org";
58#include <netinet/in.h> 58#include <netinet/in.h>
59 59
60#if defined(HAVE_SSL) && defined(USE_OPENSSL) 60#if defined(HAVE_SSL) && defined(USE_OPENSSL)
61#include <openssl/opensslv.h> 61# include <openssl/opensslv.h>
62#endif 62#endif
63 63
64#include <netdb.h> 64#include <netdb.h>
@@ -66,1084 +66,1049 @@ const char *email = "devel@monitoring-plugins.org";
66#define MAKE_LIBCURL_VERSION(major, minor, patch) ((major)*0x10000 + (minor)*0x100 + (patch)) 66#define MAKE_LIBCURL_VERSION(major, minor, patch) ((major)*0x10000 + (minor)*0x100 + (patch))
67 67
68#define DEFAULT_BUFFER_SIZE 2048 68#define DEFAULT_BUFFER_SIZE 2048
69#define DEFAULT_SERVER_URL "/" 69#define DEFAULT_SERVER_URL "/"
70#define HTTP_EXPECT "HTTP/" 70#define HTTP_EXPECT "HTTP/"
71#define INET_ADDR_MAX_SIZE INET6_ADDRSTRLEN 71#define INET_ADDR_MAX_SIZE INET6_ADDRSTRLEN
72enum { 72enum {
73 MAX_IPV4_HOSTLENGTH = 255, 73 MAX_IPV4_HOSTLENGTH = 255,
74 HTTP_PORT = 80, 74 HTTP_PORT = 80,
75 HTTPS_PORT = 443, 75 HTTPS_PORT = 443,
76 MAX_PORT = 65535, 76 MAX_PORT = 65535,
77 DEFAULT_MAX_REDIRS = 15 77 DEFAULT_MAX_REDIRS = 15
78}; 78};
79 79
80enum { 80enum {
81 STICKY_NONE = 0, 81 STICKY_NONE = 0,
82 STICKY_HOST = 1, 82 STICKY_HOST = 1,
83 STICKY_PORT = 2 83 STICKY_PORT = 2
84}; 84};
85 85
86enum { 86enum {
87 FOLLOW_HTTP_CURL = 0, 87 FOLLOW_HTTP_CURL = 0,
88 FOLLOW_LIBCURL = 1 88 FOLLOW_LIBCURL = 1
89}; 89};
90 90
91/* for buffers for header and body */ 91/* for buffers for header and body */
92typedef struct { 92typedef struct {
93 char *buf; 93 char *buf;
94 size_t buflen; 94 size_t buflen;
95 size_t bufsize; 95 size_t bufsize;
96} curlhelp_write_curlbuf; 96} curlhelp_write_curlbuf;
97 97
98/* for buffering the data sent in PUT */ 98/* for buffering the data sent in PUT */
99typedef struct { 99typedef struct {
100 char *buf; 100 char *buf;
101 size_t buflen; 101 size_t buflen;
102 off_t pos; 102 off_t pos;
103} curlhelp_read_curlbuf; 103} curlhelp_read_curlbuf;
104 104
105/* for parsing the HTTP status line */ 105/* for parsing the HTTP status line */
106typedef struct { 106typedef struct {
107 int http_major; /* major version of the protocol, always 1 (HTTP/0.9 107 int http_major; /* major version of the protocol, always 1 (HTTP/0.9
108 * never reached the big internet most likely) */ 108 * never reached the big internet most likely) */
109 int http_minor; /* minor version of the protocol, usually 0 or 1 */ 109 int http_minor; /* minor version of the protocol, usually 0 or 1 */
110 int http_code; /* HTTP return code as in RFC 2145 */ 110 int http_code; /* HTTP return code as in RFC 2145 */
111 int http_subcode; /* Microsoft IIS extension, HTTP subcodes, see 111 int http_subcode; /* Microsoft IIS extension, HTTP subcodes, see
112 * http://support.microsoft.com/kb/318380/en-us */ 112 * http://support.microsoft.com/kb/318380/en-us */
113 const char *msg; /* the human readable message */ 113 const char *msg; /* the human readable message */
114 char *first_line; /* a copy of the first line */ 114 char *first_line; /* a copy of the first line */
115} curlhelp_statusline; 115} curlhelp_statusline;
116 116
117/* to know the underlying SSL library used by libcurl */ 117/* to know the underlying SSL library used by libcurl */
118typedef enum curlhelp_ssl_library { 118typedef enum curlhelp_ssl_library {
119 CURLHELP_SSL_LIBRARY_UNKNOWN, 119 CURLHELP_SSL_LIBRARY_UNKNOWN,
120 CURLHELP_SSL_LIBRARY_OPENSSL, 120 CURLHELP_SSL_LIBRARY_OPENSSL,
121 CURLHELP_SSL_LIBRARY_LIBRESSL, 121 CURLHELP_SSL_LIBRARY_LIBRESSL,
122 CURLHELP_SSL_LIBRARY_GNUTLS, 122 CURLHELP_SSL_LIBRARY_GNUTLS,
123 CURLHELP_SSL_LIBRARY_NSS 123 CURLHELP_SSL_LIBRARY_NSS
124} curlhelp_ssl_library; 124} curlhelp_ssl_library;
125 125
126enum { 126enum {
127 REGS = 2, 127 REGS = 2,
128 MAX_RE_SIZE = 1024 128 MAX_RE_SIZE = 1024
129}; 129};
130#include "regex.h" 130#include "regex.h"
131regex_t preg; 131static regex_t preg;
132regmatch_t pmatch[REGS]; 132static regmatch_t pmatch[REGS];
133char regexp[MAX_RE_SIZE]; 133static char regexp[MAX_RE_SIZE];
134int cflags = REG_NOSUB | REG_EXTENDED | REG_NEWLINE; 134static int cflags = REG_NOSUB | REG_EXTENDED | REG_NEWLINE;
135int errcode; 135static int errcode;
136bool invert_regex = false; 136static bool invert_regex = false;
137 137static int state_regex = STATE_CRITICAL;
138char *server_address = NULL; 138
139char *host_name = NULL; 139static char *server_address = NULL;
140char *server_url = 0; 140static char *host_name = NULL;
141char server_ip[DEFAULT_BUFFER_SIZE]; 141static char *server_url = 0;
142struct curl_slist *server_ips = NULL; 142static struct curl_slist *server_ips = NULL;
143bool specify_port = false; 143static bool specify_port = false;
144unsigned short server_port = HTTP_PORT; 144static unsigned short server_port = HTTP_PORT;
145unsigned short virtual_port = 0; 145static unsigned short virtual_port = 0;
146int host_name_length; 146static int host_name_length;
147char output_header_search[30] = ""; 147static char output_header_search[30] = "";
148char output_string_search[30] = ""; 148static char output_string_search[30] = "";
149char *warning_thresholds = NULL; 149static char *warning_thresholds = NULL;
150char *critical_thresholds = NULL; 150static char *critical_thresholds = NULL;
151int days_till_exp_warn, days_till_exp_crit; 151static int days_till_exp_warn, days_till_exp_crit;
152thresholds *thlds; 152static thresholds *thlds;
153char user_agent[DEFAULT_BUFFER_SIZE]; 153static char user_agent[DEFAULT_BUFFER_SIZE];
154int verbose = 0; 154static int verbose = 0;
155bool show_extended_perfdata = false; 155static bool show_extended_perfdata = false;
156bool show_body = false; 156static bool show_body = false;
157int min_page_len = 0; 157static int min_page_len = 0;
158int max_page_len = 0; 158static int max_page_len = 0;
159int redir_depth = 0; 159static int redir_depth = 0;
160int max_depth = DEFAULT_MAX_REDIRS; 160static int max_depth = DEFAULT_MAX_REDIRS;
161char *http_method = NULL; 161static char *http_method = NULL;
162char *http_post_data = NULL; 162static char *http_post_data = NULL;
163char *http_content_type = NULL; 163static char *http_content_type = NULL;
164CURL *curl; 164static CURL *curl;
165bool curl_global_initialized = false; 165static bool curl_global_initialized = false;
166bool curl_easy_initialized = false; 166static bool curl_easy_initialized = false;
167struct curl_slist *header_list = NULL; 167static struct curl_slist *header_list = NULL;
168bool body_buf_initialized = false; 168static bool body_buf_initialized = false;
169curlhelp_write_curlbuf body_buf; 169static curlhelp_write_curlbuf body_buf;
170bool header_buf_initialized = false; 170static bool header_buf_initialized = false;
171curlhelp_write_curlbuf header_buf; 171static curlhelp_write_curlbuf header_buf;
172bool status_line_initialized = false; 172static bool status_line_initialized = false;
173curlhelp_statusline status_line; 173static curlhelp_statusline status_line;
174bool put_buf_initialized = false; 174static bool put_buf_initialized = false;
175curlhelp_read_curlbuf put_buf; 175static curlhelp_read_curlbuf put_buf;
176char http_header[DEFAULT_BUFFER_SIZE]; 176static char http_header[DEFAULT_BUFFER_SIZE];
177long code; 177static long code;
178long socket_timeout = DEFAULT_SOCKET_TIMEOUT; 178static long socket_timeout = DEFAULT_SOCKET_TIMEOUT;
179double total_time; 179static double total_time;
180double time_connect; 180static double time_connect;
181double time_appconnect; 181static double time_appconnect;
182double time_headers; 182static double time_headers;
183double time_firstbyte; 183static double time_firstbyte;
184char errbuf[MAX_INPUT_BUFFER]; 184static char errbuf[MAX_INPUT_BUFFER];
185CURLcode res; 185static CURLcode res;
186char url[DEFAULT_BUFFER_SIZE]; 186static char url[DEFAULT_BUFFER_SIZE];
187char msg[DEFAULT_BUFFER_SIZE]; 187static char msg[DEFAULT_BUFFER_SIZE];
188char perfstring[DEFAULT_BUFFER_SIZE]; 188static char perfstring[DEFAULT_BUFFER_SIZE];
189char header_expect[MAX_INPUT_BUFFER] = ""; 189static char header_expect[MAX_INPUT_BUFFER] = "";
190char string_expect[MAX_INPUT_BUFFER] = ""; 190static char string_expect[MAX_INPUT_BUFFER] = "";
191char server_expect[MAX_INPUT_BUFFER] = HTTP_EXPECT; 191static char server_expect[MAX_INPUT_BUFFER] = HTTP_EXPECT;
192int server_expect_yn = 0; 192static int server_expect_yn = 0;
193char user_auth[MAX_INPUT_BUFFER] = ""; 193static char user_auth[MAX_INPUT_BUFFER] = "";
194char proxy_auth[MAX_INPUT_BUFFER] = ""; 194static char proxy_auth[MAX_INPUT_BUFFER] = "";
195char **http_opt_headers; 195static char **http_opt_headers;
196int http_opt_headers_count = 0; 196static int http_opt_headers_count = 0;
197bool display_html = false; 197static bool display_html = false;
198int onredirect = STATE_OK; 198static int onredirect = STATE_OK;
199int followmethod = FOLLOW_HTTP_CURL; 199static int followmethod = FOLLOW_HTTP_CURL;
200int followsticky = STICKY_NONE; 200static int followsticky = STICKY_NONE;
201bool use_ssl = false; 201static bool use_ssl = false;
202bool use_sni = true; 202static bool check_cert = false;
203bool check_cert = false; 203static bool continue_after_check_cert = false;
204bool continue_after_check_cert = false;
205typedef union { 204typedef union {
206 struct curl_slist* to_info; 205 struct curl_slist *to_info;
207 struct curl_certinfo* to_certinfo; 206 struct curl_certinfo *to_certinfo;
208} cert_ptr_union; 207} cert_ptr_union;
209cert_ptr_union cert_ptr; 208static cert_ptr_union cert_ptr;
210int ssl_version = CURL_SSLVERSION_DEFAULT; 209static int ssl_version = CURL_SSLVERSION_DEFAULT;
211char *client_cert = NULL; 210static char *client_cert = NULL;
212char *client_privkey = NULL; 211static char *client_privkey = NULL;
213char *ca_cert = NULL; 212static char *ca_cert = NULL;
214bool verify_peer_and_host = false; 213static bool verify_peer_and_host = false;
215bool is_openssl_callback = false; 214static bool is_openssl_callback = false;
215static bool add_sslctx_verify_fun = false;
216#if defined(HAVE_SSL) && defined(USE_OPENSSL) 216#if defined(HAVE_SSL) && defined(USE_OPENSSL)
217X509 *cert = NULL; 217static X509 *cert = NULL;
218#endif /* defined(HAVE_SSL) && defined(USE_OPENSSL) */ 218#endif /* defined(HAVE_SSL) && defined(USE_OPENSSL) */
219bool no_body = false; 219static bool no_body = false;
220int maximum_age = -1; 220static int maximum_age = -1;
221int address_family = AF_UNSPEC; 221static int address_family = AF_UNSPEC;
222curlhelp_ssl_library ssl_library = CURLHELP_SSL_LIBRARY_UNKNOWN; 222static curlhelp_ssl_library ssl_library = CURLHELP_SSL_LIBRARY_UNKNOWN;
223int curl_http_version = CURL_HTTP_VERSION_NONE; 223static int curl_http_version = CURL_HTTP_VERSION_NONE;
224bool automatic_decompression = false; 224static bool automatic_decompression = false;
225char *cookie_jar_file = NULL; 225static char *cookie_jar_file = NULL;
226 226static bool haproxy_protocol = false;
227bool process_arguments (int, char**); 227
228void handle_curl_option_return_code (CURLcode res, const char* option); 228static bool process_arguments(int /*argc*/, char ** /*argv*/);
229int check_http (void); 229static void handle_curl_option_return_code(CURLcode res, const char *option);
230void redir (curlhelp_write_curlbuf*); 230static int check_http(void);
231char *perfd_time (double microsec); 231static void redir(curlhelp_write_curlbuf * /*header_buf*/);
232char *perfd_time_connect (double microsec); 232static char *perfd_time(double elapsed_time);
233char *perfd_time_ssl (double microsec); 233static char *perfd_time_connect(double elapsed_time_connect);
234char *perfd_time_firstbyte (double microsec); 234static char *perfd_time_ssl(double elapsed_time_ssl);
235char *perfd_time_headers (double microsec); 235static char *perfd_time_firstbyte(double elapsed_time_firstbyte);
236char *perfd_time_transfer (double microsec); 236static char *perfd_time_headers(double elapsed_time_headers);
237char *perfd_size (int page_len); 237static char *perfd_time_transfer(double elapsed_time_transfer);
238void print_help (void); 238static char *perfd_size(int page_len);
239void print_usage (void); 239static void print_help(void);
240void print_curl_version (void); 240void print_usage(void);
241int curlhelp_initwritebuffer (curlhelp_write_curlbuf*); 241static void print_curl_version(void);
242size_t curlhelp_buffer_write_callback(void*, size_t , size_t , void*); 242static int curlhelp_initwritebuffer(curlhelp_write_curlbuf * /*buf*/);
243void curlhelp_freewritebuffer (curlhelp_write_curlbuf*); 243static size_t curlhelp_buffer_write_callback(void * /*buffer*/, size_t /*size*/, size_t /*nmemb*/, void * /*stream*/);
244int curlhelp_initreadbuffer (curlhelp_read_curlbuf *, const char *, size_t); 244static void curlhelp_freewritebuffer(curlhelp_write_curlbuf * /*buf*/);
245size_t curlhelp_buffer_read_callback(void *, size_t , size_t , void *); 245static int curlhelp_initreadbuffer(curlhelp_read_curlbuf * /*buf*/, const char * /*data*/, size_t /*datalen*/);
246void curlhelp_freereadbuffer (curlhelp_read_curlbuf *); 246static size_t curlhelp_buffer_read_callback(void * /*buffer*/, size_t /*size*/, size_t /*nmemb*/, void * /*stream*/);
247curlhelp_ssl_library curlhelp_get_ssl_library (); 247static void curlhelp_freereadbuffer(curlhelp_read_curlbuf * /*buf*/);
248const char* curlhelp_get_ssl_library_string (curlhelp_ssl_library); 248static curlhelp_ssl_library curlhelp_get_ssl_library(void);
249int net_noopenssl_check_certificate (cert_ptr_union*, int, int); 249static const char *curlhelp_get_ssl_library_string(curlhelp_ssl_library /*ssl_library*/);
250 250int net_noopenssl_check_certificate(cert_ptr_union *, int, int);
251int curlhelp_parse_statusline (const char*, curlhelp_statusline *); 251
252void curlhelp_free_statusline (curlhelp_statusline *); 252static int curlhelp_parse_statusline(const char * /*buf*/, curlhelp_statusline * /*status_line*/);
253char *get_header_value (const struct phr_header* headers, const size_t nof_headers, const char* header); 253static void curlhelp_free_statusline(curlhelp_statusline * /*status_line*/);
254int check_document_dates (const curlhelp_write_curlbuf *, char (*msg)[DEFAULT_BUFFER_SIZE]); 254static char *get_header_value(const struct phr_header *headers, size_t nof_headers, const char *header);
255int get_content_length (const curlhelp_write_curlbuf* header_buf, const curlhelp_write_curlbuf* body_buf); 255static int check_document_dates(const curlhelp_write_curlbuf * /*header_buf*/, char (*msg)[DEFAULT_BUFFER_SIZE]);
256static int get_content_length(const curlhelp_write_curlbuf *header_buf, const curlhelp_write_curlbuf *body_buf);
256 257
257#if defined(HAVE_SSL) && defined(USE_OPENSSL) 258#if defined(HAVE_SSL) && defined(USE_OPENSSL)
258int np_net_ssl_check_certificate(X509 *certificate, int days_till_exp_warn, int days_till_exp_crit); 259int np_net_ssl_check_certificate(X509 *certificate, int days_till_exp_warn, int days_till_exp_crit);
259#endif /* defined(HAVE_SSL) && defined(USE_OPENSSL) */ 260#endif /* defined(HAVE_SSL) && defined(USE_OPENSSL) */
260 261
261void remove_newlines (char *); 262static void test_file(char * /*path*/);
262void test_file (char *);
263 263
264int 264int main(int argc, char **argv) {
265main (int argc, char **argv) 265 int result = STATE_UNKNOWN;
266{
267 int result = STATE_UNKNOWN;
268 266
269 setlocale (LC_ALL, ""); 267 setlocale(LC_ALL, "");
270 bindtextdomain (PACKAGE, LOCALEDIR); 268 bindtextdomain(PACKAGE, LOCALEDIR);
271 textdomain (PACKAGE); 269 textdomain(PACKAGE);
272 270
273 /* Parse extra opts if any */ 271 /* Parse extra opts if any */
274 argv = np_extra_opts (&argc, argv, progname); 272 argv = np_extra_opts(&argc, argv, progname);
275 273
276 /* set defaults */ 274 /* set defaults */
277 snprintf( user_agent, DEFAULT_BUFFER_SIZE, "%s/v%s (monitoring-plugins %s, %s)", 275 snprintf(user_agent, DEFAULT_BUFFER_SIZE, "%s/v%s (monitoring-plugins %s, %s)", progname, NP_VERSION, VERSION, curl_version());
278 progname, NP_VERSION, VERSION, curl_version());
279 276
280 /* parse arguments */ 277 /* parse arguments */
281 if (process_arguments (argc, argv) == false) 278 if (process_arguments(argc, argv) == false)
282 usage4 (_("Could not parse arguments")); 279 usage4(_("Could not parse arguments"));
283 280
284 if (display_html) 281 if (display_html)
285 printf ("<A HREF=\"%s://%s:%d%s\" target=\"_blank\">", 282 printf("<A HREF=\"%s://%s:%d%s\" target=\"_blank\">", use_ssl ? "https" : "http", host_name ? host_name : server_address,
286 use_ssl ? "https" : "http", 283 virtual_port ? virtual_port : server_port, server_url);
287 host_name ? host_name : server_address,
288 virtual_port ? virtual_port : server_port,
289 server_url);
290 284
291 result = check_http (); 285 result = check_http();
292 return result; 286 return result;
293} 287}
294 288
295#ifdef HAVE_SSL 289#ifdef HAVE_SSL
296#ifdef USE_OPENSSL 290# ifdef USE_OPENSSL
297 291
298int verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx) 292int verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx) {
299{ 293 (void)preverify_ok;
300 (void) preverify_ok; 294 /* TODO: we get all certificates of the chain, so which ones
301 /* TODO: we get all certificates of the chain, so which ones 295 * should we test?
302 * should we test? 296 * TODO: is the last certificate always the server certificate?
303 * TODO: is the last certificate always the server certificate? 297 */
304 */ 298 cert = X509_STORE_CTX_get_current_cert(x509_ctx);
305 cert = X509_STORE_CTX_get_current_cert(x509_ctx); 299# if OPENSSL_VERSION_NUMBER >= 0x10100000L
306#if OPENSSL_VERSION_NUMBER >= 0x10100000L 300 X509_up_ref(cert);
307 X509_up_ref(cert); 301# endif
308#endif 302 if (verbose >= 2) {
309 if (verbose>=2) { 303 puts("* SSL verify callback with certificate:");
310 puts("* SSL verify callback with certificate:"); 304 X509_NAME *subject;
311 X509_NAME *subject, *issuer; 305 X509_NAME *issuer;
312 printf("* issuer:\n"); 306 printf("* issuer:\n");
313 issuer = X509_get_issuer_name( cert ); 307 issuer = X509_get_issuer_name(cert);
314 X509_NAME_print_ex_fp(stdout, issuer, 5, XN_FLAG_MULTILINE); 308 X509_NAME_print_ex_fp(stdout, issuer, 5, XN_FLAG_MULTILINE);
315 printf("* curl verify_callback:\n* subject:\n"); 309 printf("* curl verify_callback:\n* subject:\n");
316 subject = X509_get_subject_name( cert ); 310 subject = X509_get_subject_name(cert);
317 X509_NAME_print_ex_fp(stdout, subject, 5, XN_FLAG_MULTILINE); 311 X509_NAME_print_ex_fp(stdout, subject, 5, XN_FLAG_MULTILINE);
318 puts(""); 312 puts("");
319 } 313 }
320 return 1; 314 return 1;
321} 315}
322 316
323CURLcode sslctxfun(CURL *curl, SSL_CTX *sslctx, void *parm) 317CURLcode sslctxfun(CURL *curl, SSL_CTX *sslctx, void *parm) {
324{ 318 (void)curl; // ignore unused parameter
325 (void) curl; // ignore unused parameter 319 (void)parm; // ignore unused parameter
326 (void) parm; // ignore unused parameter 320 if (add_sslctx_verify_fun) {
327 SSL_CTX_set_verify(sslctx, SSL_VERIFY_PEER, verify_callback); 321 SSL_CTX_set_verify(sslctx, SSL_VERIFY_PEER, verify_callback);
322 }
328 323
329 return CURLE_OK; 324 // workaround for issue:
325 // OpenSSL SSL_read: error:0A000126:SSL routines::unexpected eof while reading, errno 0
326 // see discussion https://github.com/openssl/openssl/discussions/22690
327# ifdef SSL_OP_IGNORE_UNEXPECTED_EOF
328 SSL_CTX_set_options(sslctx, SSL_OP_IGNORE_UNEXPECTED_EOF);
329# endif
330
331 return CURLE_OK;
330} 332}
331 333
332#endif /* USE_OPENSSL */ 334# endif /* USE_OPENSSL */
333#endif /* HAVE_SSL */ 335#endif /* HAVE_SSL */
334 336
335/* returns a string "HTTP/1.x" or "HTTP/2" */ 337/* returns a string "HTTP/1.x" or "HTTP/2" */
336static char *string_statuscode (int major, int minor) 338static char *string_statuscode(int major, int minor) {
337{ 339 static char buf[10];
338 static char buf[10]; 340
339 341 switch (major) {
340 switch (major) { 342 case 1:
341 case 1: 343 snprintf(buf, sizeof(buf), "HTTP/%d.%d", major, minor);
342 snprintf (buf, sizeof (buf), "HTTP/%d.%d", major, minor); 344 break;
343 break; 345 case 2:
344 case 2: 346 case 3:
345 case 3: 347 snprintf(buf, sizeof(buf), "HTTP/%d", major);
346 snprintf (buf, sizeof (buf), "HTTP/%d", major); 348 break;
347 break; 349 default:
348 default: 350 /* assuming here HTTP/N with N>=4 */
349 /* assuming here HTTP/N with N>=4 */ 351 snprintf(buf, sizeof(buf), "HTTP/%d", major);
350 snprintf (buf, sizeof (buf), "HTTP/%d", major); 352 break;
351 break; 353 }
352 } 354
353 355 return buf;
354 return buf;
355} 356}
356 357
357/* Checks if the server 'reply' is one of the expected 'statuscodes' */ 358/* Checks if the server 'reply' is one of the expected 'statuscodes' */
358static int 359static int expected_statuscode(const char *reply, const char *statuscodes) {
359expected_statuscode (const char *reply, const char *statuscodes) 360 char *expected;
360{ 361 char *code;
361 char *expected, *code; 362 int result = 0;
362 int result = 0; 363
363 364 if ((expected = strdup(statuscodes)) == NULL)
364 if ((expected = strdup (statuscodes)) == NULL) 365 die(STATE_UNKNOWN, _("HTTP UNKNOWN - Memory allocation error\n"));
365 die (STATE_UNKNOWN, _("HTTP UNKNOWN - Memory allocation error\n")); 366
366 367 for (code = strtok(expected, ","); code != NULL; code = strtok(NULL, ","))
367 for (code = strtok (expected, ","); code != NULL; code = strtok (NULL, ",")) 368 if (strstr(reply, code) != NULL) {
368 if (strstr (reply, code) != NULL) { 369 result = 1;
369 result = 1; 370 break;
370 break; 371 }
371 } 372
372 373 free(expected);
373 free (expected); 374 return result;
374 return result;
375} 375}
376 376
377void 377void handle_curl_option_return_code(CURLcode res, const char *option) {
378handle_curl_option_return_code (CURLcode res, const char* option) 378 if (res != CURLE_OK) {
379{ 379 snprintf(msg, DEFAULT_BUFFER_SIZE, _("Error while setting cURL option '%s': cURL returned %d - %s"), option, res,
380 if (res != CURLE_OK) { 380 curl_easy_strerror(res));
381 snprintf (msg, 381 die(STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg);
382 DEFAULT_BUFFER_SIZE, 382 }
383 _("Error while setting cURL option '%s': cURL returned %d - %s"),
384 option,
385 res,
386 curl_easy_strerror(res));
387 die (STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg);
388 }
389} 383}
390 384
391int 385int lookup_host(const char *host, char *buf, size_t buflen) {
392lookup_host (const char *host, char *buf, size_t buflen) 386 struct addrinfo hints, *res, *result;
393{ 387 char addrstr[100];
394 struct addrinfo hints, *res, *result; 388 size_t addrstr_len;
395 char addrstr[100]; 389 int errcode;
396 size_t addrstr_len; 390 void *ptr = {0};
397 int errcode; 391 size_t buflen_remaining = buflen - 1;
398 void *ptr = { 0 }; 392
399 size_t buflen_remaining = buflen - 1; 393 memset(&hints, 0, sizeof(hints));
400 394 hints.ai_family = address_family;
401 memset (&hints, 0, sizeof (hints)); 395 hints.ai_socktype = SOCK_STREAM;
402 hints.ai_family = address_family; 396 hints.ai_flags |= AI_CANONNAME;
403 hints.ai_socktype = SOCK_STREAM; 397
404 hints.ai_flags |= AI_CANONNAME; 398 errcode = getaddrinfo(host, NULL, &hints, &result);
405 399 if (errcode != 0)
406 errcode = getaddrinfo (host, NULL, &hints, &result); 400 return errcode;
407 if (errcode != 0) 401
408 return errcode; 402 strcpy(buf, "");
409 403 res = result;
410 strcpy(buf, ""); 404
411 res = result; 405 while (res) {
412 406 switch (res->ai_family) {
413 while (res) { 407 case AF_INET:
414 switch (res->ai_family) { 408 ptr = &((struct sockaddr_in *)res->ai_addr)->sin_addr;
415 case AF_INET: 409 break;
416 ptr = &((struct sockaddr_in *) res->ai_addr)->sin_addr; 410 case AF_INET6:
417 break; 411 ptr = &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr;
418 case AF_INET6: 412 break;
419 ptr = &((struct sockaddr_in6 *) res->ai_addr)->sin6_addr; 413 }
420 break; 414
421 } 415 inet_ntop(res->ai_family, ptr, addrstr, 100);
422 416 if (verbose >= 1) {
423 inet_ntop (res->ai_family, ptr, addrstr, 100); 417 printf("* getaddrinfo IPv%d address: %s\n", res->ai_family == PF_INET6 ? 6 : 4, addrstr);
424 if (verbose >= 1) { 418 }
425 printf ("* getaddrinfo IPv%d address: %s\n", 419
426 res->ai_family == PF_INET6 ? 6 : 4, addrstr); 420 // Append all IPs to buf as a comma-separated string
427 } 421 addrstr_len = strlen(addrstr);
428 422 if (buflen_remaining > addrstr_len + 1) {
429 // Append all IPs to buf as a comma-separated string 423 if (buf[0] != '\0') {
430 addrstr_len = strlen(addrstr); 424 strncat(buf, ",", buflen_remaining);
431 if (buflen_remaining > addrstr_len + 1) { 425 buflen_remaining -= 1;
432 if (buf[0] != '\0') { 426 }
433 strncat(buf, ",", buflen_remaining); 427 strncat(buf, addrstr, buflen_remaining);
434 buflen_remaining -= 1; 428 buflen_remaining -= addrstr_len;
435 } 429 }
436 strncat(buf, addrstr, buflen_remaining); 430
437 buflen_remaining -= addrstr_len; 431 res = res->ai_next;
438 } 432 }
439 433
440 res = res->ai_next; 434 freeaddrinfo(result);
441 } 435
442 436 return 0;
443 freeaddrinfo(result);
444
445 return 0;
446} 437}
447 438
448static void 439static void cleanup(void) {
449cleanup (void) 440 if (status_line_initialized)
450{ 441 curlhelp_free_statusline(&status_line);
451 if (status_line_initialized) curlhelp_free_statusline(&status_line); 442 status_line_initialized = false;
452 status_line_initialized = false; 443 if (curl_easy_initialized)
453 if (curl_easy_initialized) curl_easy_cleanup (curl); 444 curl_easy_cleanup(curl);
454 curl_easy_initialized = false; 445 curl_easy_initialized = false;
455 if (curl_global_initialized) curl_global_cleanup (); 446 if (curl_global_initialized)
456 curl_global_initialized = false; 447 curl_global_cleanup();
457 if (body_buf_initialized) curlhelp_freewritebuffer (&body_buf); 448 curl_global_initialized = false;
458 body_buf_initialized = false; 449 if (body_buf_initialized)
459 if (header_buf_initialized) curlhelp_freewritebuffer (&header_buf); 450 curlhelp_freewritebuffer(&body_buf);
460 header_buf_initialized = false; 451 body_buf_initialized = false;
461 if (put_buf_initialized) curlhelp_freereadbuffer (&put_buf); 452 if (header_buf_initialized)
462 put_buf_initialized = false; 453 curlhelp_freewritebuffer(&header_buf);
454 header_buf_initialized = false;
455 if (put_buf_initialized)
456 curlhelp_freereadbuffer(&put_buf);
457 put_buf_initialized = false;
463} 458}
464 459
465int 460int check_http(void) {
466check_http (void) 461 int result = STATE_OK;
467{ 462 int result_ssl = STATE_OK;
468 int result = STATE_OK; 463 int page_len = 0;
469 int page_len = 0; 464 int i;
470 int i; 465 char *force_host_header = NULL;
471 char *force_host_header = NULL; 466 struct curl_slist *host = NULL;
472 struct curl_slist *host = NULL; 467 char addrstr[DEFAULT_BUFFER_SIZE / 2];
473 char addrstr[DEFAULT_BUFFER_SIZE/2]; 468 char dnscache[DEFAULT_BUFFER_SIZE];
474 char dnscache[DEFAULT_BUFFER_SIZE]; 469
475 470 /* initialize curl */
476 /* initialize curl */ 471 if (curl_global_init(CURL_GLOBAL_DEFAULT) != CURLE_OK)
477 if (curl_global_init (CURL_GLOBAL_DEFAULT) != CURLE_OK) 472 die(STATE_UNKNOWN, "HTTP UNKNOWN - curl_global_init failed\n");
478 die (STATE_UNKNOWN, "HTTP UNKNOWN - curl_global_init failed\n"); 473 curl_global_initialized = true;
479 curl_global_initialized = true; 474
480 475 if ((curl = curl_easy_init()) == NULL) {
481 if ((curl = curl_easy_init()) == NULL) { 476 die(STATE_UNKNOWN, "HTTP UNKNOWN - curl_easy_init failed\n");
482 die (STATE_UNKNOWN, "HTTP UNKNOWN - curl_easy_init failed\n"); 477 }
483 } 478 curl_easy_initialized = true;
484 curl_easy_initialized = true; 479
485 480 /* register cleanup function to shut down libcurl properly */
486 /* register cleanup function to shut down libcurl properly */ 481 atexit(cleanup);
487 atexit (cleanup); 482
488 483 if (verbose >= 1)
489 if (verbose >= 1) 484 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_VERBOSE, 1), "CURLOPT_VERBOSE");
490 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_VERBOSE, 1), "CURLOPT_VERBOSE"); 485
491 486 /* print everything on stdout like check_http would do */
492 /* print everything on stdout like check_http would do */ 487 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_STDERR, stdout), "CURLOPT_STDERR");
493 handle_curl_option_return_code (curl_easy_setopt(curl, CURLOPT_STDERR, stdout), "CURLOPT_STDERR"); 488
494 489 if (automatic_decompression)
495 if (automatic_decompression)
496#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 21, 6) 490#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 21, 6)
497 handle_curl_option_return_code (curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, ""), "CURLOPT_ACCEPT_ENCODING"); 491 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, ""), "CURLOPT_ACCEPT_ENCODING");
498#else 492#else
499 handle_curl_option_return_code (curl_easy_setopt(curl, CURLOPT_ENCODING, ""), "CURLOPT_ENCODING"); 493 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_ENCODING, ""), "CURLOPT_ENCODING");
500#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 21, 6) */ 494#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 21, 6) */
501 495
502 /* initialize buffer for body of the answer */ 496 /* initialize buffer for body of the answer */
503 if (curlhelp_initwritebuffer(&body_buf) < 0) 497 if (curlhelp_initwritebuffer(&body_buf) < 0)
504 die (STATE_UNKNOWN, "HTTP CRITICAL - out of memory allocating buffer for body\n"); 498 die(STATE_UNKNOWN, "HTTP CRITICAL - out of memory allocating buffer for body\n");
505 body_buf_initialized = true; 499 body_buf_initialized = true;
506 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, (curl_write_callback)curlhelp_buffer_write_callback), "CURLOPT_WRITEFUNCTION"); 500 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, (curl_write_callback)curlhelp_buffer_write_callback),
507 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_WRITEDATA, (void *)&body_buf), "CURLOPT_WRITEDATA"); 501 "CURLOPT_WRITEFUNCTION");
508 502 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&body_buf), "CURLOPT_WRITEDATA");
509 /* initialize buffer for header of the answer */ 503
510 if (curlhelp_initwritebuffer( &header_buf ) < 0) 504 /* initialize buffer for header of the answer */
511 die (STATE_UNKNOWN, "HTTP CRITICAL - out of memory allocating buffer for header\n" ); 505 if (curlhelp_initwritebuffer(&header_buf) < 0)
512 header_buf_initialized = true; 506 die(STATE_UNKNOWN, "HTTP CRITICAL - out of memory allocating buffer for header\n");
513 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_HEADERFUNCTION, (curl_write_callback)curlhelp_buffer_write_callback), "CURLOPT_HEADERFUNCTION"); 507 header_buf_initialized = true;
514 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_WRITEHEADER, (void *)&header_buf), "CURLOPT_WRITEHEADER"); 508 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, (curl_write_callback)curlhelp_buffer_write_callback),
515 509 "CURLOPT_HEADERFUNCTION");
516 /* set the error buffer */ 510 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_WRITEHEADER, (void *)&header_buf), "CURLOPT_WRITEHEADER");
517 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_ERRORBUFFER, errbuf), "CURLOPT_ERRORBUFFER"); 511
518 512 /* set the error buffer */
519 /* set timeouts */ 513 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errbuf), "CURLOPT_ERRORBUFFER");
520 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_CONNECTTIMEOUT, socket_timeout), "CURLOPT_CONNECTTIMEOUT"); 514
521 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_TIMEOUT, socket_timeout), "CURLOPT_TIMEOUT"); 515 /* set timeouts */
522 516 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, socket_timeout), "CURLOPT_CONNECTTIMEOUT");
523 // fill dns resolve cache to make curl connect to the given server_address instead of the host_name, only required for ssl, because we use the host_name later on to make SNI happy 517 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_TIMEOUT, socket_timeout), "CURLOPT_TIMEOUT");
524 if(use_ssl && host_name != NULL) { 518
525 if ( (res=lookup_host (server_address, addrstr, DEFAULT_BUFFER_SIZE/2)) != 0) { 519 /* enable haproxy protocol */
526 snprintf (msg, 520 if (haproxy_protocol) {
527 DEFAULT_BUFFER_SIZE, 521 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_HAPROXYPROTOCOL, 1L), "CURLOPT_HAPROXYPROTOCOL");
528 _("Unable to lookup IP address for '%s': getaddrinfo returned %d - %s"), 522 }
529 server_address, 523
530 res, 524 // fill dns resolve cache to make curl connect to the given server_address instead of the host_name, only required for ssl, because we
531 gai_strerror (res)); 525 // use the host_name later on to make SNI happy
532 die (STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg); 526 if (use_ssl && host_name != NULL) {
533 } 527 if ((res = lookup_host(server_address, addrstr, DEFAULT_BUFFER_SIZE / 2)) != 0) {
534 snprintf (dnscache, DEFAULT_BUFFER_SIZE, "%s:%d:%s", host_name, server_port, addrstr); 528 snprintf(msg, DEFAULT_BUFFER_SIZE, _("Unable to lookup IP address for '%s': getaddrinfo returned %d - %d"), server_address, res,
535 host = curl_slist_append(NULL, dnscache); 529 gai_strerror(res));
536 curl_easy_setopt(curl, CURLOPT_RESOLVE, host); 530 die(STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg);
537 if (verbose>=1) 531 }
538 printf ("* curl CURLOPT_RESOLVE: %s\n", dnscache); 532 snprintf(dnscache, DEFAULT_BUFFER_SIZE, "%s:%d:%s", host_name, server_port, addrstr);
539 } 533 host = curl_slist_append(NULL, dnscache);
540 534 curl_easy_setopt(curl, CURLOPT_RESOLVE, host);
541 // If server_address is an IPv6 address it must be surround by square brackets 535 if (verbose >= 1)
542 struct in6_addr tmp_in_addr; 536 printf("* curl CURLOPT_RESOLVE: %s\n", dnscache);
543 if (inet_pton(AF_INET6, server_address, &tmp_in_addr) == 1) { 537 }
544 char *new_server_address = malloc(strlen(server_address) + 3); 538
545 if (new_server_address == NULL) { 539 // If server_address is an IPv6 address it must be surround by square brackets
546 die(STATE_UNKNOWN, "HTTP UNKNOWN - Unable to allocate memory\n"); 540 struct in6_addr tmp_in_addr;
547 } 541 if (inet_pton(AF_INET6, server_address, &tmp_in_addr) == 1) {
548 snprintf(new_server_address, strlen(server_address)+3, "[%s]", server_address); 542 char *new_server_address = malloc(strlen(server_address) + 3);
549 free(server_address); 543 if (new_server_address == NULL) {
550 server_address = new_server_address; 544 die(STATE_UNKNOWN, "HTTP UNKNOWN - Unable to allocate memory\n");
551 } 545 }
552 546 snprintf(new_server_address, strlen(server_address) + 3, "[%s]", server_address);
553 /* compose URL: use the address we want to connect to, set Host: header later */ 547 free(server_address);
554 snprintf (url, DEFAULT_BUFFER_SIZE, "%s://%s:%d%s", 548 server_address = new_server_address;
555 use_ssl ? "https" : "http", 549 }
556 ( use_ssl & ( host_name != NULL ) ) ? host_name : server_address, 550
557 server_port, 551 /* compose URL: use the address we want to connect to, set Host: header later */
558 server_url 552 snprintf(url, DEFAULT_BUFFER_SIZE, "%s://%s:%d%s", use_ssl ? "https" : "http",
559 ); 553 (use_ssl & (host_name != NULL)) ? host_name : server_address, server_port, server_url);
560 554
561 if (verbose>=1) 555 if (verbose >= 1)
562 printf ("* curl CURLOPT_URL: %s\n", url); 556 printf("* curl CURLOPT_URL: %s\n", url);
563 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_URL, url), "CURLOPT_URL"); 557 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_URL, url), "CURLOPT_URL");
564 558
565 /* extract proxy information for legacy proxy https requests */ 559 /* extract proxy information for legacy proxy https requests */
566 if (!strcmp(http_method, "CONNECT") || strstr(server_url, "http") == server_url) { 560 if (!strcmp(http_method, "CONNECT") || strstr(server_url, "http") == server_url) {
567 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_PROXY, server_address), "CURLOPT_PROXY"); 561 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_PROXY, server_address), "CURLOPT_PROXY");
568 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_PROXYPORT, (long)server_port), "CURLOPT_PROXYPORT"); 562 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_PROXYPORT, (long)server_port), "CURLOPT_PROXYPORT");
569 if (verbose>=2) 563 if (verbose >= 2)
570 printf ("* curl CURLOPT_PROXY: %s:%d\n", server_address, server_port); 564 printf("* curl CURLOPT_PROXY: %s:%d\n", server_address, server_port);
571 http_method = "GET"; 565 http_method = "GET";
572 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_URL, server_url), "CURLOPT_URL"); 566 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_URL, server_url), "CURLOPT_URL");
573 } 567 }
574 568
575 /* disable body for HEAD request */ 569 /* disable body for HEAD request */
576 if (http_method && !strcmp (http_method, "HEAD" )) { 570 if (http_method && !strcmp(http_method, "HEAD")) {
577 no_body = true; 571 no_body = true;
578 } 572 }
579 573
580 /* set HTTP protocol version */ 574 /* set HTTP protocol version */
581 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_HTTP_VERSION, curl_http_version), "CURLOPT_HTTP_VERSION"); 575 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, curl_http_version), "CURLOPT_HTTP_VERSION");
582 576
583 /* set HTTP method */ 577 /* set HTTP method */
584 if (http_method) { 578 if (http_method) {
585 if (!strcmp(http_method, "POST")) 579 if (!strcmp(http_method, "POST"))
586 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_POST, 1), "CURLOPT_POST"); 580 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_POST, 1), "CURLOPT_POST");
587 else if (!strcmp(http_method, "PUT")) 581 else if (!strcmp(http_method, "PUT"))
588 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_UPLOAD, 1), "CURLOPT_UPLOAD"); 582 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_UPLOAD, 1), "CURLOPT_UPLOAD");
589 else 583 else
590 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_CUSTOMREQUEST, http_method), "CURLOPT_CUSTOMREQUEST"); 584 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, http_method), "CURLOPT_CUSTOMREQUEST");
591 } 585 }
592 586
593 /* check if Host header is explicitly set in options */ 587 /* check if Host header is explicitly set in options */
594 if (http_opt_headers_count) { 588 if (http_opt_headers_count) {
595 for (i = 0; i < http_opt_headers_count ; i++) { 589 for (i = 0; i < http_opt_headers_count; i++) {
596 if (strncmp(http_opt_headers[i], "Host:", 5) == 0) { 590 if (strncmp(http_opt_headers[i], "Host:", 5) == 0) {
597 force_host_header = http_opt_headers[i]; 591 force_host_header = http_opt_headers[i];
598 } 592 }
599 } 593 }
600 } 594 }
601 595
602 /* set hostname (virtual hosts), not needed if CURLOPT_CONNECT_TO is used, but left in anyway */ 596 /* set hostname (virtual hosts), not needed if CURLOPT_CONNECT_TO is used, but left in anyway */
603 if(host_name != NULL && force_host_header == NULL) { 597 if (host_name != NULL && force_host_header == NULL) {
604 if((virtual_port != HTTP_PORT && !use_ssl) || (virtual_port != HTTPS_PORT && use_ssl)) { 598 if ((virtual_port != HTTP_PORT && !use_ssl) || (virtual_port != HTTPS_PORT && use_ssl)) {
605 snprintf(http_header, DEFAULT_BUFFER_SIZE, "Host: %s:%d", host_name, virtual_port); 599 snprintf(http_header, DEFAULT_BUFFER_SIZE, "Host: %s:%d", host_name, virtual_port);
606 } else { 600 } else {
607 snprintf(http_header, DEFAULT_BUFFER_SIZE, "Host: %s", host_name); 601 snprintf(http_header, DEFAULT_BUFFER_SIZE, "Host: %s", host_name);
608 } 602 }
609 header_list = curl_slist_append (header_list, http_header); 603 header_list = curl_slist_append(header_list, http_header);
610 } 604 }
611 605
612 /* always close connection, be nice to servers */ 606 /* always close connection, be nice to servers */
613 snprintf (http_header, DEFAULT_BUFFER_SIZE, "Connection: close"); 607 snprintf(http_header, DEFAULT_BUFFER_SIZE, "Connection: close");
614 header_list = curl_slist_append (header_list, http_header); 608 header_list = curl_slist_append(header_list, http_header);
615 609
616 /* attach additional headers supplied by the user */ 610 /* attach additional headers supplied by the user */
617 /* optionally send any other header tag */ 611 /* optionally send any other header tag */
618 if (http_opt_headers_count) { 612 if (http_opt_headers_count) {
619 for (i = 0; i < http_opt_headers_count ; i++) { 613 for (i = 0; i < http_opt_headers_count; i++) {
620 header_list = curl_slist_append (header_list, http_opt_headers[i]); 614 header_list = curl_slist_append(header_list, http_opt_headers[i]);
621 } 615 }
622 /* This cannot be free'd here because a redirection will then try to access this and segfault */ 616 /* This cannot be free'd here because a redirection will then try to access this and segfault */
623 /* Covered in a testcase in tests/check_http.t */ 617 /* Covered in a testcase in tests/check_http.t */
624 /* free(http_opt_headers); */ 618 /* free(http_opt_headers); */
625 } 619 }
626 620
627 /* set HTTP headers */ 621 /* set HTTP headers */
628 handle_curl_option_return_code (curl_easy_setopt( curl, CURLOPT_HTTPHEADER, header_list ), "CURLOPT_HTTPHEADER"); 622 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header_list), "CURLOPT_HTTPHEADER");
629 623
630#ifdef LIBCURL_FEATURE_SSL 624#ifdef LIBCURL_FEATURE_SSL
631 625
632 /* set SSL version, warn about insecure or unsupported versions */ 626 /* set SSL version, warn about insecure or unsupported versions */
633 if (use_ssl) { 627 if (use_ssl) {
634 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_SSLVERSION, ssl_version), "CURLOPT_SSLVERSION"); 628 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_SSLVERSION, ssl_version), "CURLOPT_SSLVERSION");
635 } 629 }
636 630
637 /* client certificate and key to present to server (SSL) */ 631 /* client certificate and key to present to server (SSL) */
638 if (client_cert) 632 if (client_cert)
639 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_SSLCERT, client_cert), "CURLOPT_SSLCERT"); 633 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_SSLCERT, client_cert), "CURLOPT_SSLCERT");
640 if (client_privkey) 634 if (client_privkey)
641 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_SSLKEY, client_privkey), "CURLOPT_SSLKEY"); 635 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_SSLKEY, client_privkey), "CURLOPT_SSLKEY");
642 if (ca_cert) { 636 if (ca_cert) {
643 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_CAINFO, ca_cert), "CURLOPT_CAINFO"); 637 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_CAINFO, ca_cert), "CURLOPT_CAINFO");
644 } 638 }
645 if (ca_cert || verify_peer_and_host) { 639 if (ca_cert || verify_peer_and_host) {
646 /* per default if we have a CA verify both the peer and the 640 /* per default if we have a CA verify both the peer and the
647 * hostname in the certificate, can be switched off later */ 641 * hostname in the certificate, can be switched off later */
648 handle_curl_option_return_code (curl_easy_setopt( curl, CURLOPT_SSL_VERIFYPEER, 1), "CURLOPT_SSL_VERIFYPEER"); 642 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1), "CURLOPT_SSL_VERIFYPEER");
649 handle_curl_option_return_code (curl_easy_setopt( curl, CURLOPT_SSL_VERIFYHOST, 2), "CURLOPT_SSL_VERIFYHOST"); 643 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2), "CURLOPT_SSL_VERIFYHOST");
650 } else { 644 } else {
651 /* backward-compatible behaviour, be tolerant in checks 645 /* backward-compatible behaviour, be tolerant in checks
652 * TODO: depending on more options have aspects we want 646 * TODO: depending on more options have aspects we want
653 * to be less tolerant about ssl verfications 647 * to be less tolerant about ssl verfications
654 */ 648 */
655 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_SSL_VERIFYPEER, 0), "CURLOPT_SSL_VERIFYPEER"); 649 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0), "CURLOPT_SSL_VERIFYPEER");
656 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_SSL_VERIFYHOST, 0), "CURLOPT_SSL_VERIFYHOST"); 650 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0), "CURLOPT_SSL_VERIFYHOST");
657 } 651 }
658 652
659 /* detect SSL library used by libcurl */ 653 /* detect SSL library used by libcurl */
660 ssl_library = curlhelp_get_ssl_library (); 654 ssl_library = curlhelp_get_ssl_library();
661 655
662 /* try hard to get a stack of certificates to verify against */ 656 /* try hard to get a stack of certificates to verify against */
663 if (check_cert) { 657 if (check_cert) {
664#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 19, 1) 658# if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 19, 1)
665 /* inform curl to report back certificates */ 659 /* inform curl to report back certificates */
666 switch (ssl_library) { 660 switch (ssl_library) {
667 case CURLHELP_SSL_LIBRARY_OPENSSL: 661 case CURLHELP_SSL_LIBRARY_OPENSSL:
668 case CURLHELP_SSL_LIBRARY_LIBRESSL: 662 case CURLHELP_SSL_LIBRARY_LIBRESSL:
669 /* set callback to extract certificate with OpenSSL context function (works with 663 /* set callback to extract certificate with OpenSSL context function (works with
670 * OpenSSL-style libraries only!) */ 664 * OpenSSL-style libraries only!) */
671#ifdef USE_OPENSSL 665# ifdef USE_OPENSSL
672 /* libcurl and monitoring plugins built with OpenSSL, good */ 666 /* libcurl and monitoring plugins built with OpenSSL, good */
673 handle_curl_option_return_code (curl_easy_setopt(curl, CURLOPT_SSL_CTX_FUNCTION, sslctxfun), "CURLOPT_SSL_CTX_FUNCTION"); 667 add_sslctx_verify_fun = true;
674 is_openssl_callback = true; 668 is_openssl_callback = true;
675#else /* USE_OPENSSL */ 669# endif /* USE_OPENSSL */
676#endif /* USE_OPENSSL */ 670 /* libcurl is built with OpenSSL, monitoring plugins, so falling
677 /* libcurl is built with OpenSSL, monitoring plugins, so falling 671 * back to manually extracting certificate information */
678 * back to manually extracting certificate information */ 672 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_CERTINFO, 1L), "CURLOPT_CERTINFO");
679 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_CERTINFO, 1L), "CURLOPT_CERTINFO"); 673 break;
680 break; 674
681 675 case CURLHELP_SSL_LIBRARY_NSS:
682 case CURLHELP_SSL_LIBRARY_NSS: 676# if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0)
683#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) 677 /* NSS: support for CERTINFO is implemented since 7.34.0 */
684 /* NSS: support for CERTINFO is implemented since 7.34.0 */ 678 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_CERTINFO, 1L), "CURLOPT_CERTINFO");
685 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_CERTINFO, 1L), "CURLOPT_CERTINFO"); 679# else /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) */
686#else /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) */ 680 die(STATE_CRITICAL, "HTTP CRITICAL - Cannot retrieve certificates (libcurl linked with SSL library '%s' is too old)\n",
687 die (STATE_CRITICAL, "HTTP CRITICAL - Cannot retrieve certificates (libcurl linked with SSL library '%s' is too old)\n", curlhelp_get_ssl_library_string (ssl_library)); 681 curlhelp_get_ssl_library_string(ssl_library));
688#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) */ 682# endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) */
689 break; 683 break;
690 684
691 case CURLHELP_SSL_LIBRARY_GNUTLS: 685 case CURLHELP_SSL_LIBRARY_GNUTLS:
692#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 42, 0) 686# if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 42, 0)
693 /* GnuTLS: support for CERTINFO is implemented since 7.42.0 */ 687 /* GnuTLS: support for CERTINFO is implemented since 7.42.0 */
694 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_CERTINFO, 1L), "CURLOPT_CERTINFO"); 688 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_CERTINFO, 1L), "CURLOPT_CERTINFO");
695#else /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 42, 0) */ 689# else /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 42, 0) */
696 die (STATE_CRITICAL, "HTTP CRITICAL - Cannot retrieve certificates (libcurl linked with SSL library '%s' is too old)\n", curlhelp_get_ssl_library_string (ssl_library)); 690 die(STATE_CRITICAL, "HTTP CRITICAL - Cannot retrieve certificates (libcurl linked with SSL library '%s' is too old)\n",
697#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 42, 0) */ 691 curlhelp_get_ssl_library_string(ssl_library));
698 break; 692# endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 42, 0) */
699 693 break;
700 case CURLHELP_SSL_LIBRARY_UNKNOWN: 694
701 default: 695 case CURLHELP_SSL_LIBRARY_UNKNOWN:
702 die (STATE_CRITICAL, "HTTP CRITICAL - Cannot retrieve certificates (unknown SSL library '%s', must implement first)\n", curlhelp_get_ssl_library_string (ssl_library)); 696 default:
703 break; 697 die(STATE_CRITICAL, "HTTP CRITICAL - Cannot retrieve certificates (unknown SSL library '%s', must implement first)\n",
704 } 698 curlhelp_get_ssl_library_string(ssl_library));
705#else /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 19, 1) */ 699 break;
706 /* old libcurl, our only hope is OpenSSL, otherwise we are out of luck */ 700 }
707 if (ssl_library == CURLHELP_SSL_LIBRARY_OPENSSL || ssl_library == CURLHELP_SSL_LIBRARY_LIBRESSL) 701# else /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 19, 1) */
708 handle_curl_option_return_code (curl_easy_setopt(curl, CURLOPT_SSL_CTX_FUNCTION, sslctxfun), "CURLOPT_SSL_CTX_FUNCTION"); 702 /* old libcurl, our only hope is OpenSSL, otherwise we are out of luck */
709 else 703 if (ssl_library == CURLHELP_SSL_LIBRARY_OPENSSL || ssl_library == CURLHELP_SSL_LIBRARY_LIBRESSL)
710 die (STATE_CRITICAL, "HTTP CRITICAL - Cannot retrieve certificates (no CURLOPT_SSL_CTX_FUNCTION, no OpenSSL library or libcurl too old and has no CURLOPT_CERTINFO)\n"); 704 add_sslctx_verify_fun = true;
711#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 19, 1) */ 705 else
712 } 706 die(STATE_CRITICAL, "HTTP CRITICAL - Cannot retrieve certificates (no CURLOPT_SSL_CTX_FUNCTION, no OpenSSL library or libcurl "
707 "too old and has no CURLOPT_CERTINFO)\n");
708# endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 19, 1) */
709 }
710
711# if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 10, 6) /* required for CURLOPT_SSL_CTX_FUNCTION */
712 // ssl ctx function is not available with all ssl backends
713 if (curl_easy_setopt(curl, CURLOPT_SSL_CTX_FUNCTION, NULL) != CURLE_UNKNOWN_OPTION)
714 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_SSL_CTX_FUNCTION, sslctxfun), "CURLOPT_SSL_CTX_FUNCTION");
715# endif
713 716
714#endif /* LIBCURL_FEATURE_SSL */ 717#endif /* LIBCURL_FEATURE_SSL */
715 718
716 /* set default or user-given user agent identification */ 719 /* set default or user-given user agent identification */
717 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_USERAGENT, user_agent), "CURLOPT_USERAGENT"); 720 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_USERAGENT, user_agent), "CURLOPT_USERAGENT");
718 721
719 /* proxy-authentication */ 722 /* proxy-authentication */
720 if (strcmp(proxy_auth, "")) 723 if (strcmp(proxy_auth, ""))
721 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_PROXYUSERPWD, proxy_auth), "CURLOPT_PROXYUSERPWD"); 724 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD, proxy_auth), "CURLOPT_PROXYUSERPWD");
722 725
723 /* authentication */ 726 /* authentication */
724 if (strcmp(user_auth, "")) 727 if (strcmp(user_auth, ""))
725 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_USERPWD, user_auth), "CURLOPT_USERPWD"); 728 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_USERPWD, user_auth), "CURLOPT_USERPWD");
726 729
727 /* TODO: parameter auth method, bitfield of following methods: 730 /* TODO: parameter auth method, bitfield of following methods:
728 * CURLAUTH_BASIC (default) 731 * CURLAUTH_BASIC (default)
729 * CURLAUTH_DIGEST 732 * CURLAUTH_DIGEST
730 * CURLAUTH_DIGEST_IE 733 * CURLAUTH_DIGEST_IE
731 * CURLAUTH_NEGOTIATE 734 * CURLAUTH_NEGOTIATE
732 * CURLAUTH_NTLM 735 * CURLAUTH_NTLM
733 * CURLAUTH_NTLM_WB 736 * CURLAUTH_NTLM_WB
734 * 737 *
735 * convenience tokens for typical sets of methods: 738 * convenience tokens for typical sets of methods:
736 * CURLAUTH_ANYSAFE: most secure, without BASIC 739 * CURLAUTH_ANYSAFE: most secure, without BASIC
737 * or CURLAUTH_ANY: most secure, even BASIC if necessary 740 * or CURLAUTH_ANY: most secure, even BASIC if necessary
738 * 741 *
739 * handle_curl_option_return_code (curl_easy_setopt( curl, CURLOPT_HTTPAUTH, (long)CURLAUTH_DIGEST ), "CURLOPT_HTTPAUTH"); 742 * handle_curl_option_return_code (curl_easy_setopt( curl, CURLOPT_HTTPAUTH, (long)CURLAUTH_DIGEST ), "CURLOPT_HTTPAUTH");
740 */ 743 */
741 744
742 /* handle redirections */ 745 /* handle redirections */
743 if (onredirect == STATE_DEPENDENT) { 746 if (onredirect == STATE_DEPENDENT) {
744 if( followmethod == FOLLOW_LIBCURL ) { 747 if (followmethod == FOLLOW_LIBCURL) {
745 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_FOLLOWLOCATION, 1), "CURLOPT_FOLLOWLOCATION"); 748 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1), "CURLOPT_FOLLOWLOCATION");
746 749
747 /* default -1 is infinite, not good, could lead to zombie plugins! 750 /* default -1 is infinite, not good, could lead to zombie plugins!
748 Setting it to one bigger than maximal limit to handle errors nicely below 751 Setting it to one bigger than maximal limit to handle errors nicely below
749 */ 752 */
750 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_MAXREDIRS, max_depth+1), "CURLOPT_MAXREDIRS"); 753 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_MAXREDIRS, max_depth + 1), "CURLOPT_MAXREDIRS");
751 754
752 /* for now allow only http and https (we are a http(s) check plugin in the end) */ 755 /* for now allow only http and https (we are a http(s) check plugin in the end) */
753#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 85, 0) 756#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 85, 0)
754 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_REDIR_PROTOCOLS_STR, "http,https"), "CURLOPT_REDIR_PROTOCOLS_STR"); 757 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_REDIR_PROTOCOLS_STR, "http,https"),
758 "CURLOPT_REDIR_PROTOCOLS_STR");
755#elif LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 19, 4) 759#elif LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 19, 4)
756 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS), "CURLOPT_REDIRECT_PROTOCOLS"); 760 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS),
761 "CURLOPT_REDIRECT_PROTOCOLS");
757#endif 762#endif
758 763
759 /* TODO: handle the following aspects of redirection, make them 764 /* TODO: handle the following aspects of redirection, make them
760 * command line options too later: 765 * command line options too later:
761 CURLOPT_POSTREDIR: method switch 766 CURLOPT_POSTREDIR: method switch
762 CURLINFO_REDIRECT_URL: custom redirect option 767 CURLINFO_REDIRECT_URL: custom redirect option
763 CURLOPT_REDIRECT_PROTOCOLS: allow people to step outside safe protocols 768 CURLOPT_REDIRECT_PROTOCOLS: allow people to step outside safe protocols
764 CURLINFO_REDIRECT_COUNT: get the number of redirects, print it, maybe a range option here is nice like for expected page size? 769 CURLINFO_REDIRECT_COUNT: get the number of redirects, print it, maybe a range option here is nice like for expected page size?
765 */ 770 */
766 } else { 771 } else {
767 /* old style redirection is handled below */ 772 /* old style redirection is handled below */
768 } 773 }
769 } 774 }
770 775
771 /* no-body */ 776 /* no-body */
772 if (no_body) 777 if (no_body)
773 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_NOBODY, 1), "CURLOPT_NOBODY"); 778 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_NOBODY, 1), "CURLOPT_NOBODY");
774 779
775 /* IPv4 or IPv6 forced DNS resolution */ 780 /* IPv4 or IPv6 forced DNS resolution */
776 if (address_family == AF_UNSPEC) 781 if (address_family == AF_UNSPEC)
777 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_WHATEVER), "CURLOPT_IPRESOLVE(CURL_IPRESOLVE_WHATEVER)"); 782 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_WHATEVER),
778 else if (address_family == AF_INET) 783 "CURLOPT_IPRESOLVE(CURL_IPRESOLVE_WHATEVER)");
779 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4), "CURLOPT_IPRESOLVE(CURL_IPRESOLVE_V4)"); 784 else if (address_family == AF_INET)
780#if defined (USE_IPV6) && defined (LIBCURL_FEATURE_IPV6) 785 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4),
781 else if (address_family == AF_INET6) 786 "CURLOPT_IPRESOLVE(CURL_IPRESOLVE_V4)");
782 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V6), "CURLOPT_IPRESOLVE(CURL_IPRESOLVE_V6)"); 787#if defined(USE_IPV6) && defined(LIBCURL_FEATURE_IPV6)
788 else if (address_family == AF_INET6)
789 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V6),
790 "CURLOPT_IPRESOLVE(CURL_IPRESOLVE_V6)");
783#endif 791#endif
784 792
785 /* either send http POST data (any data, not only POST)*/ 793 /* either send http POST data (any data, not only POST)*/
786 if (!strcmp(http_method, "POST") ||!strcmp(http_method, "PUT")) { 794 if (!strcmp(http_method, "POST") || !strcmp(http_method, "PUT")) {
787 /* set content of payload for POST and PUT */ 795 /* set content of payload for POST and PUT */
788 if (http_content_type) { 796 if (http_content_type) {
789 snprintf (http_header, DEFAULT_BUFFER_SIZE, "Content-Type: %s", http_content_type); 797 snprintf(http_header, DEFAULT_BUFFER_SIZE, "Content-Type: %s", http_content_type);
790 header_list = curl_slist_append (header_list, http_header); 798 header_list = curl_slist_append(header_list, http_header);
791 } 799 }
792 /* NULL indicates "HTTP Continue" in libcurl, provide an empty string 800 /* NULL indicates "HTTP Continue" in libcurl, provide an empty string
793 * in case of no POST/PUT data */ 801 * in case of no POST/PUT data */
794 if (!http_post_data) 802 if (!http_post_data)
795 http_post_data = ""; 803 http_post_data = "";
796 if (!strcmp(http_method, "POST")) { 804 if (!strcmp(http_method, "POST")) {
797 /* POST method, set payload with CURLOPT_POSTFIELDS */ 805 /* POST method, set payload with CURLOPT_POSTFIELDS */
798 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_POSTFIELDS, http_post_data), "CURLOPT_POSTFIELDS"); 806 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_POSTFIELDS, http_post_data), "CURLOPT_POSTFIELDS");
799 } else if (!strcmp(http_method, "PUT")) { 807 } else if (!strcmp(http_method, "PUT")) {
800 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_READFUNCTION, (curl_read_callback)curlhelp_buffer_read_callback), "CURLOPT_READFUNCTION"); 808 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_READFUNCTION, (curl_read_callback)curlhelp_buffer_read_callback),
801 if (curlhelp_initreadbuffer (&put_buf, http_post_data, strlen (http_post_data)) < 0) 809 "CURLOPT_READFUNCTION");
802 die (STATE_UNKNOWN, "HTTP CRITICAL - out of memory allocating read buffer for PUT\n"); 810 if (curlhelp_initreadbuffer(&put_buf, http_post_data, strlen(http_post_data)) < 0)
803 put_buf_initialized = true; 811 die(STATE_UNKNOWN, "HTTP CRITICAL - out of memory allocating read buffer for PUT\n");
804 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_READDATA, (void *)&put_buf), "CURLOPT_READDATA"); 812 put_buf_initialized = true;
805 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_INFILESIZE, (curl_off_t)strlen (http_post_data)), "CURLOPT_INFILESIZE"); 813 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_READDATA, (void *)&put_buf), "CURLOPT_READDATA");
806 } 814 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_INFILESIZE, (curl_off_t)strlen(http_post_data)),
807 } 815 "CURLOPT_INFILESIZE");
808 816 }
809 /* cookie handling */ 817 }
810 if (cookie_jar_file != NULL) { 818
811 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_COOKIEJAR, cookie_jar_file), "CURLOPT_COOKIEJAR"); 819 /* cookie handling */
812 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_COOKIEFILE, cookie_jar_file), "CURLOPT_COOKIEFILE"); 820 if (cookie_jar_file != NULL) {
813 } 821 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_COOKIEJAR, cookie_jar_file), "CURLOPT_COOKIEJAR");
814 822 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_COOKIEFILE, cookie_jar_file), "CURLOPT_COOKIEFILE");
815 /* do the request */ 823 }
816 res = curl_easy_perform(curl); 824
817 825 /* do the request */
818 if (verbose>=2 && http_post_data) 826 res = curl_easy_perform(curl);
819 printf ("**** REQUEST CONTENT ****\n%s\n", http_post_data); 827
820 828 if (verbose >= 2 && http_post_data)
821 /* free header and server IP resolve lists, we don't need it anymore */ 829 printf("**** REQUEST CONTENT ****\n%s\n", http_post_data);
822 curl_slist_free_all (header_list); header_list = NULL; 830
823 curl_slist_free_all (server_ips); server_ips = NULL; 831 /* free header and server IP resolve lists, we don't need it anymore */
824 if (host) { 832 curl_slist_free_all(header_list);
825 curl_slist_free_all (host); host = NULL; 833 header_list = NULL;
826 } 834 curl_slist_free_all(server_ips);
827 835 server_ips = NULL;
828 /* Curl errors, result in critical Nagios state */ 836 if (host) {
829 if (res != CURLE_OK) { 837 curl_slist_free_all(host);
830 snprintf (msg, 838 host = NULL;
831 DEFAULT_BUFFER_SIZE, 839 }
832 _("Invalid HTTP response received from host on port %d: cURL returned %d - %s"), 840
833 server_port, 841 /* Curl errors, result in critical Nagios state */
834 res, 842 if (res != CURLE_OK) {
835 errbuf[0] ? errbuf : curl_easy_strerror(res)); 843 snprintf(msg, DEFAULT_BUFFER_SIZE, _("Invalid HTTP response received from host on port %d: cURL returned %d - %s"), server_port,
836 die (STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg); 844 res, errbuf[0] ? errbuf : curl_easy_strerror(res));
837 } 845 die(STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg);
838 846 }
839 /* certificate checks */ 847
848 /* certificate checks */
840#ifdef LIBCURL_FEATURE_SSL 849#ifdef LIBCURL_FEATURE_SSL
841 if (use_ssl) { 850 if (use_ssl) {
842 if (check_cert) { 851 if (check_cert) {
843 if (is_openssl_callback) { 852 if (is_openssl_callback) {
844#ifdef USE_OPENSSL 853# ifdef USE_OPENSSL
845 /* check certificate with OpenSSL functions, curl has been built against OpenSSL 854 /* check certificate with OpenSSL functions, curl has been built against OpenSSL
846 * and we actually have OpenSSL in the monitoring tools 855 * and we actually have OpenSSL in the monitoring tools
847 */ 856 */
848 result = np_net_ssl_check_certificate(cert, days_till_exp_warn, days_till_exp_crit); 857 result_ssl = np_net_ssl_check_certificate(cert, days_till_exp_warn, days_till_exp_crit);
849 if (!continue_after_check_cert) { 858 if (!continue_after_check_cert) {
850 return result; 859 return result_ssl;
851 } 860 }
852#else /* USE_OPENSSL */ 861# else /* USE_OPENSSL */
853 die (STATE_CRITICAL, "HTTP CRITICAL - Cannot retrieve certificates - OpenSSL callback used and not linked against OpenSSL\n"); 862 die(STATE_CRITICAL,
854#endif /* USE_OPENSSL */ 863 "HTTP CRITICAL - Cannot retrieve certificates - OpenSSL callback used and not linked against OpenSSL\n");
855 } else { 864# endif /* USE_OPENSSL */
856 int i; 865 } else {
857 struct curl_slist *slist; 866 int i;
858 867 struct curl_slist *slist;
859 cert_ptr.to_info = NULL; 868
860 res = curl_easy_getinfo (curl, CURLINFO_CERTINFO, &cert_ptr.to_info); 869 cert_ptr.to_info = NULL;
861 if (!res && cert_ptr.to_info) { 870 res = curl_easy_getinfo(curl, CURLINFO_CERTINFO, &cert_ptr.to_info);
862#ifdef USE_OPENSSL 871 if (!res && cert_ptr.to_info) {
863 /* We have no OpenSSL in libcurl, but we can use OpenSSL for X509 cert parsing 872# ifdef USE_OPENSSL
864 * We only check the first certificate and assume it's the one of the server 873 /* We have no OpenSSL in libcurl, but we can use OpenSSL for X509 cert parsing
865 */ 874 * We only check the first certificate and assume it's the one of the server
866 const char* raw_cert = NULL; 875 */
867 for (i = 0; i < cert_ptr.to_certinfo->num_of_certs; i++) { 876 const char *raw_cert = NULL;
868 for (slist = cert_ptr.to_certinfo->certinfo[i]; slist; slist = slist->next) { 877 for (i = 0; i < cert_ptr.to_certinfo->num_of_certs; i++) {
869 if (verbose >= 2) 878 for (slist = cert_ptr.to_certinfo->certinfo[i]; slist; slist = slist->next) {
870 printf ("%d ** %s\n", i, slist->data); 879 if (verbose >= 2)
871 if (strncmp (slist->data, "Cert:", 5) == 0) { 880 printf("%d ** %s\n", i, slist->data);
872 raw_cert = &slist->data[5]; 881 if (strncmp(slist->data, "Cert:", 5) == 0) {
873 goto GOT_FIRST_CERT; 882 raw_cert = &slist->data[5];
874 } 883 goto GOT_FIRST_CERT;
875 } 884 }
876 } 885 }
877GOT_FIRST_CERT: 886 }
878 if (!raw_cert) { 887 GOT_FIRST_CERT:
879 snprintf (msg, 888 if (!raw_cert) {
880 DEFAULT_BUFFER_SIZE, 889 snprintf(msg, DEFAULT_BUFFER_SIZE,
881 _("Cannot retrieve certificates from CERTINFO information - certificate data was empty")); 890 _("Cannot retrieve certificates from CERTINFO information - certificate data was empty"));
882 die (STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg); 891 die(STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg);
883 } 892 }
884 BIO* cert_BIO = BIO_new (BIO_s_mem()); 893 BIO *cert_BIO = BIO_new(BIO_s_mem());
885 BIO_write (cert_BIO, raw_cert, strlen(raw_cert)); 894 BIO_write(cert_BIO, raw_cert, strlen(raw_cert));
886 cert = PEM_read_bio_X509 (cert_BIO, NULL, NULL, NULL); 895 cert = PEM_read_bio_X509(cert_BIO, NULL, NULL, NULL);
887 if (!cert) { 896 if (!cert) {
888 snprintf (msg, 897 snprintf(msg, DEFAULT_BUFFER_SIZE, _("Cannot read certificate from CERTINFO information - BIO error"));
889 DEFAULT_BUFFER_SIZE, 898 die(STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg);
890 _("Cannot read certificate from CERTINFO information - BIO error")); 899 }
891 die (STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg); 900 BIO_free(cert_BIO);
892 } 901 result_ssl = np_net_ssl_check_certificate(cert, days_till_exp_warn, days_till_exp_crit);
893 BIO_free (cert_BIO); 902 if (!continue_after_check_cert) {
894 result = np_net_ssl_check_certificate(cert, days_till_exp_warn, days_till_exp_crit); 903 return result_ssl;
895 if (!continue_after_check_cert) { 904 }
896 return result; 905# else /* USE_OPENSSL */
897 } 906 /* We assume we don't have OpenSSL and np_net_ssl_check_certificate at our disposal,
898#else /* USE_OPENSSL */ 907 * so we use the libcurl CURLINFO data
899 /* We assume we don't have OpenSSL and np_net_ssl_check_certificate at our disposal, 908 */
900 * so we use the libcurl CURLINFO data 909 result_ssl = net_noopenssl_check_certificate(&cert_ptr, days_till_exp_warn, days_till_exp_crit);
901 */ 910 if (!continue_after_check_cert) {
902 result = net_noopenssl_check_certificate(&cert_ptr, days_till_exp_warn, days_till_exp_crit); 911 return result_ssl;
903 if (!continue_after_check_cert) { 912 }
904 return result; 913# endif /* USE_OPENSSL */
905 } 914 } else {
906#endif /* USE_OPENSSL */ 915 snprintf(msg, DEFAULT_BUFFER_SIZE, _("Cannot retrieve certificates - cURL returned %d - %s"), res,
907 } else { 916 curl_easy_strerror(res));
908 snprintf (msg, 917 die(STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg);
909 DEFAULT_BUFFER_SIZE, 918 }
910 _("Cannot retrieve certificates - cURL returned %d - %s"), 919 }
911 res, 920 }
912 curl_easy_strerror(res)); 921 }
913 die (STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg);
914 }
915 }
916 }
917 }
918#endif /* LIBCURL_FEATURE_SSL */ 922#endif /* LIBCURL_FEATURE_SSL */
919 923
920 /* we got the data and we executed the request in a given time, so we can append 924 /* we got the data and we executed the request in a given time, so we can append
921 * performance data to the answer always 925 * performance data to the answer always
922 */ 926 */
923 handle_curl_option_return_code (curl_easy_getinfo (curl, CURLINFO_TOTAL_TIME, &total_time), "CURLINFO_TOTAL_TIME"); 927 handle_curl_option_return_code(curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME, &total_time), "CURLINFO_TOTAL_TIME");
924 page_len = get_content_length(&header_buf, &body_buf); 928 page_len = get_content_length(&header_buf, &body_buf);
925 if(show_extended_perfdata) { 929 if (show_extended_perfdata) {
926 handle_curl_option_return_code (curl_easy_getinfo(curl, CURLINFO_CONNECT_TIME, &time_connect), "CURLINFO_CONNECT_TIME"); 930 handle_curl_option_return_code(curl_easy_getinfo(curl, CURLINFO_CONNECT_TIME, &time_connect), "CURLINFO_CONNECT_TIME");
927 handle_curl_option_return_code (curl_easy_getinfo(curl, CURLINFO_APPCONNECT_TIME, &time_appconnect), "CURLINFO_APPCONNECT_TIME"); 931 handle_curl_option_return_code(curl_easy_getinfo(curl, CURLINFO_APPCONNECT_TIME, &time_appconnect), "CURLINFO_APPCONNECT_TIME");
928 handle_curl_option_return_code (curl_easy_getinfo(curl, CURLINFO_PRETRANSFER_TIME, &time_headers), "CURLINFO_PRETRANSFER_TIME"); 932 handle_curl_option_return_code(curl_easy_getinfo(curl, CURLINFO_PRETRANSFER_TIME, &time_headers), "CURLINFO_PRETRANSFER_TIME");
929 handle_curl_option_return_code (curl_easy_getinfo(curl, CURLINFO_STARTTRANSFER_TIME, &time_firstbyte), "CURLINFO_STARTTRANSFER_TIME"); 933 handle_curl_option_return_code(curl_easy_getinfo(curl, CURLINFO_STARTTRANSFER_TIME, &time_firstbyte),
930 snprintf(perfstring, DEFAULT_BUFFER_SIZE, "%s %s %s %s %s %s %s", 934 "CURLINFO_STARTTRANSFER_TIME");
931 perfd_time(total_time), 935 snprintf(perfstring, DEFAULT_BUFFER_SIZE, "%s %s %s %s %s %s %s", perfd_time(total_time), perfd_size(page_len),
932 perfd_size(page_len), 936 perfd_time_connect(time_connect), use_ssl ? perfd_time_ssl(time_appconnect - time_connect) : "",
933 perfd_time_connect(time_connect), 937 perfd_time_headers(time_headers - time_appconnect), perfd_time_firstbyte(time_firstbyte - time_headers),
934 use_ssl ? perfd_time_ssl (time_appconnect-time_connect) : "", 938 perfd_time_transfer(total_time - time_firstbyte));
935 perfd_time_headers(time_headers - time_appconnect), 939 } else {
936 perfd_time_firstbyte(time_firstbyte - time_headers), 940 snprintf(perfstring, DEFAULT_BUFFER_SIZE, "%s %s", perfd_time(total_time), perfd_size(page_len));
937 perfd_time_transfer(total_time-time_firstbyte) 941 }
938 );
939 } else {
940 snprintf(perfstring, DEFAULT_BUFFER_SIZE, "%s %s",
941 perfd_time(total_time),
942 perfd_size(page_len)
943 );
944 }
945
946 /* return a CRITICAL status if we couldn't read any data */
947 if (strlen(header_buf.buf) == 0 && strlen(body_buf.buf) == 0)
948 die (STATE_CRITICAL, _("HTTP CRITICAL - No header received from host\n"));
949
950 /* get status line of answer, check sanity of HTTP code */
951 if (curlhelp_parse_statusline (header_buf.buf, &status_line) < 0) {
952 snprintf (msg,
953 DEFAULT_BUFFER_SIZE,
954 "Unparsable status line in %.3g seconds response time|%s\n",
955 total_time,
956 perfstring);
957 /* we cannot know the major/minor version here for sure as we cannot parse the first line */
958 die (STATE_CRITICAL, "HTTP CRITICAL HTTP/x.x %ld unknown - %s", code, msg);
959 }
960 status_line_initialized = true;
961
962 /* get result code from cURL */
963 handle_curl_option_return_code (curl_easy_getinfo (curl, CURLINFO_RESPONSE_CODE, &code), "CURLINFO_RESPONSE_CODE");
964 if (verbose>=2)
965 printf ("* curl CURLINFO_RESPONSE_CODE is %ld\n", code);
966
967 /* print status line, header, body if verbose */
968 if (verbose >= 2) {
969 printf ("**** HEADER ****\n%s\n**** CONTENT ****\n%s\n", header_buf.buf,
970 (no_body ? " [[ skipped ]]" : body_buf.buf));
971 }
972
973 /* make sure the status line matches the response we are looking for */
974 if (!expected_statuscode(status_line.first_line, server_expect)) {
975 if (server_port == HTTP_PORT)
976 snprintf(msg,
977 DEFAULT_BUFFER_SIZE,
978 _("Invalid HTTP response received from host: %s\n"),
979 status_line.first_line);
980 else
981 snprintf(msg,
982 DEFAULT_BUFFER_SIZE,
983 _("Invalid HTTP response received from host on port %d: %s\n"),
984 server_port,
985 status_line.first_line);
986 die (STATE_CRITICAL, "HTTP CRITICAL - %s%s%s", msg,
987 show_body ? "\n" : "",
988 show_body ? body_buf.buf : "");
989 }
990
991 if( server_expect_yn ) {
992 snprintf(msg, DEFAULT_BUFFER_SIZE, _("Status line output matched \"%s\" - "), server_expect);
993 if (verbose)
994 printf ("%s\n",msg);
995 result = STATE_OK;
996 }
997 else {
998 /* illegal return codes result in a critical state */
999 if (code >= 600 || code < 100) {
1000 die (STATE_CRITICAL, _("HTTP CRITICAL: Invalid Status (%d, %.40s)\n"), status_line.http_code, status_line.msg);
1001 /* server errors result in a critical state */
1002 } else if (code >= 500) {
1003 result = STATE_CRITICAL;
1004 /* client errors result in a warning state */
1005 } else if (code >= 400) {
1006 result = STATE_WARNING;
1007 /* check redirected page if specified */
1008 } else if (code >= 300) {
1009 if (onredirect == STATE_DEPENDENT) {
1010 if( followmethod == FOLLOW_LIBCURL ) {
1011 code = status_line.http_code;
1012 } else {
1013 /* old check_http style redirection, if we come
1014 * back here, we are in the same status as with
1015 * the libcurl method
1016 */
1017 redir (&header_buf);
1018 }
1019 } else {
1020 /* this is a specific code in the command line to
1021 * be returned when a redirection is encountered
1022 */
1023 }
1024 result = max_state_alt (onredirect, result);
1025 /* all other codes are considered ok */
1026 } else {
1027 result = STATE_OK;
1028 }
1029 }
1030
1031 /* libcurl redirection internally, handle error states here */
1032 if( followmethod == FOLLOW_LIBCURL ) {
1033 handle_curl_option_return_code (curl_easy_getinfo (curl, CURLINFO_REDIRECT_COUNT, &redir_depth), "CURLINFO_REDIRECT_COUNT");
1034 if (verbose >= 2)
1035 printf(_("* curl LIBINFO_REDIRECT_COUNT is %d\n"), redir_depth);
1036 if (redir_depth > max_depth) {
1037 snprintf (msg, DEFAULT_BUFFER_SIZE, "maximum redirection depth %d exceeded in libcurl",
1038 max_depth);
1039 die (STATE_WARNING, "HTTP WARNING - %s", msg);
1040 }
1041 }
1042
1043 /* check status codes, set exit status accordingly */
1044 if( status_line.http_code != code ) {
1045 die (STATE_CRITICAL, _("HTTP CRITICAL %s %d %s - different HTTP codes (cUrl has %ld)\n"),
1046 string_statuscode (status_line.http_major, status_line.http_minor),
1047 status_line.http_code, status_line.msg, code);
1048 }
1049
1050 if (maximum_age >= 0) {
1051 result = max_state_alt(check_document_dates(&header_buf, &msg), result);
1052 }
1053
1054 /* Page and Header content checks go here */
1055
1056 if (strlen (header_expect)) {
1057 if (!strstr (header_buf.buf, header_expect)) {
1058
1059 strncpy(&output_header_search[0],header_expect,sizeof(output_header_search));
1060
1061 if(output_header_search[sizeof(output_header_search)-1]!='\0') {
1062 bcopy("...",&output_header_search[sizeof(output_header_search)-4],4);
1063 }
1064 942
1065 char tmp[DEFAULT_BUFFER_SIZE]; 943 /* return a CRITICAL status if we couldn't read any data */
944 if (strlen(header_buf.buf) == 0 && strlen(body_buf.buf) == 0)
945 die(STATE_CRITICAL, _("HTTP CRITICAL - No header received from host\n"));
1066 946
1067 snprintf (tmp, 947 /* get status line of answer, check sanity of HTTP code */
1068 DEFAULT_BUFFER_SIZE, 948 if (curlhelp_parse_statusline(header_buf.buf, &status_line) < 0) {
1069 _("%sheader '%s' not found on '%s://%s:%d%s', "), 949 snprintf(msg, DEFAULT_BUFFER_SIZE, "Unparsable status line in %.3g seconds response time|%s\n", total_time, perfstring);
1070 msg, 950 /* we cannot know the major/minor version here for sure as we cannot parse the first line */
1071 output_header_search, 951 die(STATE_CRITICAL, "HTTP CRITICAL HTTP/x.x %ld unknown - %s", code, msg);
1072 use_ssl ? "https" : "http", 952 }
1073 host_name ? host_name : server_address, 953 status_line_initialized = true;
1074 server_port,
1075 server_url);
1076 954
1077 strcpy(msg, tmp); 955 /* get result code from cURL */
956 handle_curl_option_return_code(curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code), "CURLINFO_RESPONSE_CODE");
957 if (verbose >= 2)
958 printf("* curl CURLINFO_RESPONSE_CODE is %ld\n", code);
1078 959
1079 result = STATE_CRITICAL; 960 /* print status line, header, body if verbose */
1080 } 961 if (verbose >= 2) {
1081 } 962 printf("**** HEADER ****\n%s\n**** CONTENT ****\n%s\n", header_buf.buf, (no_body ? " [[ skipped ]]" : body_buf.buf));
963 }
1082 964
1083 if (strlen (string_expect)) { 965 /* make sure the status line matches the response we are looking for */
1084 if (!strstr (body_buf.buf, string_expect)) { 966 if (!expected_statuscode(status_line.first_line, server_expect)) {
967 if (server_port == HTTP_PORT)
968 snprintf(msg, DEFAULT_BUFFER_SIZE, _("Invalid HTTP response received from host: %s\n"), status_line.first_line);
969 else
970 snprintf(msg, DEFAULT_BUFFER_SIZE, _("Invalid HTTP response received from host on port %d: %s\n"), server_port,
971 status_line.first_line);
972 die(STATE_CRITICAL, "HTTP CRITICAL - %s%s%s", msg, show_body ? "\n" : "", show_body ? body_buf.buf : "");
973 }
1085 974
1086 strncpy(&output_string_search[0],string_expect,sizeof(output_string_search)); 975 if (server_expect_yn) {
976 snprintf(msg, DEFAULT_BUFFER_SIZE, _("Status line output matched \"%s\" - "), server_expect);
977 if (verbose)
978 printf("%s\n", msg);
979 result = STATE_OK;
980 } else {
981 /* illegal return codes result in a critical state */
982 if (code >= 600 || code < 100) {
983 die(STATE_CRITICAL, _("HTTP CRITICAL: Invalid Status (%d, %.40s)\n"), status_line.http_code, status_line.msg);
984 /* server errors result in a critical state */
985 } else if (code >= 500) {
986 result = STATE_CRITICAL;
987 /* client errors result in a warning state */
988 } else if (code >= 400) {
989 result = STATE_WARNING;
990 /* check redirected page if specified */
991 } else if (code >= 300) {
992 if (onredirect == STATE_DEPENDENT) {
993 if (followmethod == FOLLOW_LIBCURL) {
994 code = status_line.http_code;
995 } else {
996 /* old check_http style redirection, if we come
997 * back here, we are in the same status as with
998 * the libcurl method
999 */
1000 redir(&header_buf);
1001 }
1002 } else {
1003 /* this is a specific code in the command line to
1004 * be returned when a redirection is encountered
1005 */
1006 }
1007 result = max_state_alt(onredirect, result);
1008 /* all other codes are considered ok */
1009 } else {
1010 result = STATE_OK;
1011 }
1012 }
1087 1013
1088 if(output_string_search[sizeof(output_string_search)-1]!='\0') { 1014 /* libcurl redirection internally, handle error states here */
1089 bcopy("...",&output_string_search[sizeof(output_string_search)-4],4); 1015 if (followmethod == FOLLOW_LIBCURL) {
1090 } 1016 handle_curl_option_return_code(curl_easy_getinfo(curl, CURLINFO_REDIRECT_COUNT, &redir_depth), "CURLINFO_REDIRECT_COUNT");
1017 if (verbose >= 2)
1018 printf(_("* curl LIBINFO_REDIRECT_COUNT is %d\n"), redir_depth);
1019 if (redir_depth > max_depth) {
1020 snprintf(msg, DEFAULT_BUFFER_SIZE, "maximum redirection depth %d exceeded in libcurl", max_depth);
1021 die(STATE_WARNING, "HTTP WARNING - %s", msg);
1022 }
1023 }
1024
1025 /* check status codes, set exit status accordingly */
1026 if (status_line.http_code != code) {
1027 die(STATE_CRITICAL, _("HTTP CRITICAL %s %d %s - different HTTP codes (cUrl has %ld)\n"),
1028 string_statuscode(status_line.http_major, status_line.http_minor), status_line.http_code, status_line.msg, code);
1029 }
1030
1031 if (maximum_age >= 0) {
1032 result = max_state_alt(check_document_dates(&header_buf, &msg), result);
1033 }
1034
1035 /* Page and Header content checks go here */
1036
1037 if (strlen(header_expect)) {
1038 if (!strstr(header_buf.buf, header_expect)) {
1039
1040 strncpy(&output_header_search[0], header_expect, sizeof(output_header_search));
1041
1042 if (output_header_search[sizeof(output_header_search) - 1] != '\0') {
1043 bcopy("...", &output_header_search[sizeof(output_header_search) - 4], 4);
1044 }
1045
1046 char tmp[DEFAULT_BUFFER_SIZE];
1047
1048 snprintf(tmp, DEFAULT_BUFFER_SIZE, _("%sheader '%s' not found on '%s://%s:%d%s', "), msg, output_header_search,
1049 use_ssl ? "https" : "http", host_name ? host_name : server_address, server_port, server_url);
1050
1051 strcpy(msg, tmp);
1052
1053 result = STATE_CRITICAL;
1054 }
1055 }
1056
1057 if (strlen(string_expect)) {
1058 if (!strstr(body_buf.buf, string_expect)) {
1059
1060 strncpy(&output_string_search[0], string_expect, sizeof(output_string_search));
1061
1062 if (output_string_search[sizeof(output_string_search) - 1] != '\0') {
1063 bcopy("...", &output_string_search[sizeof(output_string_search) - 4], 4);
1064 }
1091 1065
1092 char tmp[DEFAULT_BUFFER_SIZE]; 1066 char tmp[DEFAULT_BUFFER_SIZE];
1093 1067
1094 snprintf (tmp, 1068 snprintf(tmp, DEFAULT_BUFFER_SIZE, _("%sstring '%s' not found on '%s://%s:%d%s', "), msg, output_string_search,
1095 DEFAULT_BUFFER_SIZE, 1069 use_ssl ? "https" : "http", host_name ? host_name : server_address, server_port, server_url);
1096 _("%sstring '%s' not found on '%s://%s:%d%s', "),
1097 msg,
1098 output_string_search,
1099 use_ssl ? "https" : "http",
1100 host_name ? host_name : server_address,
1101 server_port,
1102 server_url);
1103 1070
1104 strcpy(msg, tmp); 1071 strcpy(msg, tmp);
1105 1072
1106 result = STATE_CRITICAL; 1073 result = STATE_CRITICAL;
1107 } 1074 }
1108 } 1075 }
1109 1076
1110 if (strlen (regexp)) { 1077 if (strlen(regexp)) {
1111 errcode = regexec (&preg, body_buf.buf, REGS, pmatch, 0); 1078 errcode = regexec(&preg, body_buf.buf, REGS, pmatch, 0);
1112 if ((errcode == 0 && !invert_regex) || (errcode == REG_NOMATCH && invert_regex)) { 1079 if ((errcode == 0 && !invert_regex) || (errcode == REG_NOMATCH && invert_regex)) {
1113 /* OK - No-op to avoid changing the logic around it */ 1080 /* OK - No-op to avoid changing the logic around it */
1114 result = max_state_alt(STATE_OK, result); 1081 result = max_state_alt(STATE_OK, result);
1115 } 1082 } else if ((errcode == REG_NOMATCH && !invert_regex) || (errcode == 0 && invert_regex)) {
1116 else if ((errcode == REG_NOMATCH && !invert_regex) || (errcode == 0 && invert_regex)) {
1117 if (!invert_regex) { 1083 if (!invert_regex) {
1118 char tmp[DEFAULT_BUFFER_SIZE]; 1084 char tmp[DEFAULT_BUFFER_SIZE];
1119 1085
1120 snprintf (tmp, DEFAULT_BUFFER_SIZE, _("%spattern not found, "), msg); 1086 snprintf(tmp, DEFAULT_BUFFER_SIZE, _("%spattern not found, "), msg);
1121 strcpy(msg, tmp); 1087 strcpy(msg, tmp);
1122 1088
1123 } else { 1089 } else {
1124 char tmp[DEFAULT_BUFFER_SIZE]; 1090 char tmp[DEFAULT_BUFFER_SIZE];
1125 1091
1126 snprintf (tmp, DEFAULT_BUFFER_SIZE, _("%spattern found, "), msg); 1092 snprintf(tmp, DEFAULT_BUFFER_SIZE, _("%spattern found, "), msg);
1127 strcpy(msg, tmp); 1093 strcpy(msg, tmp);
1128
1129 } 1094 }
1130 result = STATE_CRITICAL; 1095 result = state_regex;
1131 } else { 1096 } else {
1132 regerror (errcode, &preg, errbuf, MAX_INPUT_BUFFER); 1097 regerror(errcode, &preg, errbuf, MAX_INPUT_BUFFER);
1133 1098
1134 char tmp[DEFAULT_BUFFER_SIZE]; 1099 char tmp[DEFAULT_BUFFER_SIZE];
1135 1100
1136 snprintf (tmp, DEFAULT_BUFFER_SIZE, _("%sExecute Error: %s, "), msg, errbuf); 1101 snprintf(tmp, DEFAULT_BUFFER_SIZE, _("%sExecute Error: %s, "), msg, errbuf);
1137 strcpy(msg, tmp); 1102 strcpy(msg, tmp);
1138 result = STATE_UNKNOWN; 1103 result = STATE_UNKNOWN;
1139 } 1104 }
1140 } 1105 }
1141 1106
1142 /* make sure the page is of an appropriate size */ 1107 /* make sure the page is of an appropriate size */
1143 if ((max_page_len > 0) && (page_len > max_page_len)) { 1108 if ((max_page_len > 0) && (page_len > max_page_len)) {
1144 char tmp[DEFAULT_BUFFER_SIZE]; 1109 char tmp[DEFAULT_BUFFER_SIZE];
1145 1110
1146 snprintf (tmp, DEFAULT_BUFFER_SIZE, _("%spage size %d too large, "), msg, page_len); 1111 snprintf(tmp, DEFAULT_BUFFER_SIZE, _("%spage size %d too large, "), msg, page_len);
1147 1112
1148 strcpy(msg, tmp); 1113 strcpy(msg, tmp);
1149 1114
@@ -1152,1256 +1117,1230 @@ GOT_FIRST_CERT:
1152 } else if ((min_page_len > 0) && (page_len < min_page_len)) { 1117 } else if ((min_page_len > 0) && (page_len < min_page_len)) {
1153 char tmp[DEFAULT_BUFFER_SIZE]; 1118 char tmp[DEFAULT_BUFFER_SIZE];
1154 1119
1155 snprintf (tmp, DEFAULT_BUFFER_SIZE, _("%spage size %d too small, "), msg, page_len); 1120 snprintf(tmp, DEFAULT_BUFFER_SIZE, _("%spage size %d too small, "), msg, page_len);
1156 strcpy(msg, tmp); 1121 strcpy(msg, tmp);
1157 result = max_state_alt(STATE_WARNING, result); 1122 result = max_state_alt(STATE_WARNING, result);
1158 } 1123 }
1159 1124
1160 /* -w, -c: check warning and critical level */ 1125 /* -w, -c: check warning and critical level */
1161 result = max_state_alt(get_status(total_time, thlds), result); 1126 result = max_state_alt(get_status(total_time, thlds), result);
1162 1127
1163 /* Cut-off trailing characters */ 1128 /* Cut-off trailing characters */
1164 if (strlen(msg) >= 2) { 1129 if (strlen(msg) >= 2) {
1165 if(msg[strlen(msg)-2] == ',') 1130 if (msg[strlen(msg) - 2] == ',')
1166 msg[strlen(msg)-2] = '\0'; 1131 msg[strlen(msg) - 2] = '\0';
1167 else 1132 else
1168 msg[strlen(msg)-3] = '\0'; 1133 msg[strlen(msg) - 3] = '\0';
1169 } 1134 }
1170 1135
1171 /* TODO: separate _() msg and status code: die (result, "HTTP %s: %s\n", state_text(result), msg); */ 1136 /* TODO: separate _() msg and status code: die (result, "HTTP %s: %s\n", state_text(result), msg); */
1172 die (result, "HTTP %s: %s %d %s%s%s - %d bytes in %.3f second response time %s|%s\n%s%s", 1137 die(max_state_alt(result, result_ssl), "HTTP %s: %s %d %s%s%s - %d bytes in %.3f second response time %s|%s\n%s%s", state_text(result),
1173 state_text(result), string_statuscode (status_line.http_major, status_line.http_minor), 1138 string_statuscode(status_line.http_major, status_line.http_minor), status_line.http_code, status_line.msg,
1174 status_line.http_code, status_line.msg, 1139 strlen(msg) > 0 ? " - " : "", msg, page_len, total_time, (display_html ? "</A>" : ""), perfstring, (show_body ? body_buf.buf : ""),
1175 strlen(msg) > 0 ? " - " : "", 1140 (show_body ? "\n" : ""));
1176 msg, page_len, total_time, 1141
1177 (display_html ? "</A>" : ""), 1142 return max_state_alt(result, result_ssl);
1178 perfstring,
1179 (show_body ? body_buf.buf : ""),
1180 (show_body ? "\n" : "") );
1181
1182 return result;
1183} 1143}
1184 1144
1185int 1145int uri_strcmp(const UriTextRangeA range, const char *s) {
1186uri_strcmp (const UriTextRangeA range, const char* s) 1146 if (!range.first)
1187{ 1147 return -1;
1188 if (!range.first) return -1; 1148 if ((size_t)(range.afterLast - range.first) < strlen(s))
1189 if ( (size_t)(range.afterLast - range.first) < strlen (s) ) return -1; 1149 return -1;
1190 return strncmp (s, range.first, min( (size_t)(range.afterLast - range.first), strlen (s))); 1150 return strncmp(s, range.first, min((size_t)(range.afterLast - range.first), strlen(s)));
1191} 1151}
1192 1152
1193char* 1153char *uri_string(const UriTextRangeA range, char *buf, size_t buflen) {
1194uri_string (const UriTextRangeA range, char* buf, size_t buflen) 1154 if (!range.first)
1195{ 1155 return "(null)";
1196 if (!range.first) return "(null)"; 1156 strncpy(buf, range.first, max(buflen - 1, (size_t)(range.afterLast - range.first)));
1197 strncpy (buf, range.first, max (buflen-1, (size_t)(range.afterLast - range.first))); 1157 buf[max(buflen - 1, (size_t)(range.afterLast - range.first))] = '\0';
1198 buf[max (buflen-1, (size_t)(range.afterLast - range.first))] = '\0'; 1158 buf[range.afterLast - range.first] = '\0';
1199 buf[range.afterLast - range.first] = '\0'; 1159 return buf;
1200 return buf;
1201} 1160}
1202 1161
1203void 1162void redir(curlhelp_write_curlbuf *header_buf) {
1204redir (curlhelp_write_curlbuf* header_buf) 1163 char *location = NULL;
1205{ 1164 curlhelp_statusline status_line;
1206 char *location = NULL; 1165 struct phr_header headers[255];
1207 curlhelp_statusline status_line; 1166 size_t nof_headers = 255;
1208 struct phr_header headers[255]; 1167 size_t msglen;
1209 size_t nof_headers = 255; 1168 char buf[DEFAULT_BUFFER_SIZE];
1210 size_t msglen; 1169 char ipstr[INET_ADDR_MAX_SIZE];
1211 char buf[DEFAULT_BUFFER_SIZE]; 1170 int new_port;
1212 char ipstr[INET_ADDR_MAX_SIZE]; 1171 char *new_host;
1213 int new_port; 1172 char *new_url;
1214 char *new_host; 1173
1215 char *new_url; 1174 int res = phr_parse_response(header_buf->buf, header_buf->buflen, &status_line.http_major, &status_line.http_minor,
1216 1175 &status_line.http_code, &status_line.msg, &msglen, headers, &nof_headers, 0);
1217 int res = phr_parse_response (header_buf->buf, header_buf->buflen,
1218 &status_line.http_major, &status_line.http_minor, &status_line.http_code, &status_line.msg, &msglen,
1219 headers, &nof_headers, 0);
1220 1176
1221 if (res == -1) { 1177 if (res == -1) {
1222 die (STATE_UNKNOWN, _("HTTP UNKNOWN - Failed to parse Response\n")); 1178 die(STATE_UNKNOWN, _("HTTP UNKNOWN - Failed to parse Response\n"));
1223 } 1179 }
1224 1180
1225 location = get_header_value (headers, nof_headers, "location"); 1181 location = get_header_value(headers, nof_headers, "location");
1226 1182
1227 if (verbose >= 2) 1183 if (verbose >= 2)
1228 printf(_("* Seen redirect location %s\n"), location); 1184 printf(_("* Seen redirect location %s\n"), location);
1229 1185
1230 if (++redir_depth > max_depth) 1186 if (++redir_depth > max_depth)
1231 die (STATE_WARNING, 1187 die(STATE_WARNING, _("HTTP WARNING - maximum redirection depth %d exceeded - %s%s\n"), max_depth, location,
1232 _("HTTP WARNING - maximum redirection depth %d exceeded - %s%s\n"), 1188 (display_html ? "</A>" : ""));
1233 max_depth, location, (display_html ? "</A>" : "")); 1189
1234 1190 UriParserStateA state;
1235 UriParserStateA state; 1191 UriUriA uri;
1236 UriUriA uri; 1192 state.uri = &uri;
1237 state.uri = &uri; 1193 if (uriParseUriA(&state, location) != URI_SUCCESS) {
1238 if (uriParseUriA (&state, location) != URI_SUCCESS) { 1194 if (state.errorCode == URI_ERROR_SYNTAX) {
1239 if (state.errorCode == URI_ERROR_SYNTAX) { 1195 die(STATE_UNKNOWN, _("HTTP UNKNOWN - Could not parse redirect location '%s'%s\n"), location, (display_html ? "</A>" : ""));
1240 die (STATE_UNKNOWN, 1196 } else if (state.errorCode == URI_ERROR_MALLOC) {
1241 _("HTTP UNKNOWN - Could not parse redirect location '%s'%s\n"), 1197 die(STATE_UNKNOWN, _("HTTP UNKNOWN - Could not allocate URL\n"));
1242 location, (display_html ? "</A>" : "")); 1198 }
1243 } else if (state.errorCode == URI_ERROR_MALLOC) { 1199 }
1244 die (STATE_UNKNOWN, _("HTTP UNKNOWN - Could not allocate URL\n")); 1200
1245 } 1201 if (verbose >= 2) {
1246 } 1202 printf(_("** scheme: %s\n"), uri_string(uri.scheme, buf, DEFAULT_BUFFER_SIZE));
1247 1203 printf(_("** host: %s\n"), uri_string(uri.hostText, buf, DEFAULT_BUFFER_SIZE));
1248 if (verbose >= 2) { 1204 printf(_("** port: %s\n"), uri_string(uri.portText, buf, DEFAULT_BUFFER_SIZE));
1249 printf (_("** scheme: %s\n"), 1205 if (uri.hostData.ip4) {
1250 uri_string (uri.scheme, buf, DEFAULT_BUFFER_SIZE)); 1206 inet_ntop(AF_INET, uri.hostData.ip4->data, ipstr, sizeof(ipstr));
1251 printf (_("** host: %s\n"), 1207 printf(_("** IPv4: %s\n"), ipstr);
1252 uri_string (uri.hostText, buf, DEFAULT_BUFFER_SIZE)); 1208 }
1253 printf (_("** port: %s\n"), 1209 if (uri.hostData.ip6) {
1254 uri_string (uri.portText, buf, DEFAULT_BUFFER_SIZE)); 1210 inet_ntop(AF_INET, uri.hostData.ip6->data, ipstr, sizeof(ipstr));
1255 if (uri.hostData.ip4) { 1211 printf(_("** IPv6: %s\n"), ipstr);
1256 inet_ntop (AF_INET, uri.hostData.ip4->data, ipstr, sizeof (ipstr)); 1212 }
1257 printf (_("** IPv4: %s\n"), ipstr); 1213 if (uri.pathHead) {
1258 } 1214 printf(_("** path: "));
1259 if (uri.hostData.ip6) { 1215 const UriPathSegmentA *p = uri.pathHead;
1260 inet_ntop (AF_INET, uri.hostData.ip6->data, ipstr, sizeof (ipstr)); 1216 for (; p; p = p->next) {
1261 printf (_("** IPv6: %s\n"), ipstr); 1217 printf("/%s", uri_string(p->text, buf, DEFAULT_BUFFER_SIZE));
1262 } 1218 }
1263 if (uri.pathHead) { 1219 puts("");
1264 printf (_("** path: ")); 1220 }
1265 const UriPathSegmentA* p = uri.pathHead; 1221 if (uri.query.first) {
1266 for (; p; p = p->next) { 1222 printf(_("** query: %s\n"), uri_string(uri.query, buf, DEFAULT_BUFFER_SIZE));
1267 printf ("/%s", uri_string (p->text, buf, DEFAULT_BUFFER_SIZE)); 1223 }
1268 } 1224 if (uri.fragment.first) {
1269 puts (""); 1225 printf(_("** fragment: %s\n"), uri_string(uri.fragment, buf, DEFAULT_BUFFER_SIZE));
1270 } 1226 }
1271 if (uri.query.first) { 1227 }
1272 printf (_("** query: %s\n"), 1228
1273 uri_string (uri.query, buf, DEFAULT_BUFFER_SIZE)); 1229 if (uri.scheme.first) {
1274 } 1230 if (!uri_strcmp(uri.scheme, "https"))
1275 if (uri.fragment.first) { 1231 use_ssl = true;
1276 printf (_("** fragment: %s\n"), 1232 else
1277 uri_string (uri.fragment, buf, DEFAULT_BUFFER_SIZE)); 1233 use_ssl = false;
1278 } 1234 }
1279 } 1235
1280 1236 /* we do a sloppy test here only, because uriparser would have failed
1281 if (!uri_strcmp (uri.scheme, "https")) 1237 * above, if the port would be invalid, we just check for MAX_PORT
1282 use_ssl = true; 1238 */
1283 else 1239 if (uri.portText.first) {
1284 use_ssl = false; 1240 new_port = atoi(uri_string(uri.portText, buf, DEFAULT_BUFFER_SIZE));
1285 1241 } else {
1286 /* we do a sloppy test here only, because uriparser would have failed 1242 new_port = HTTP_PORT;
1287 * above, if the port would be invalid, we just check for MAX_PORT 1243 if (use_ssl)
1288 */ 1244 new_port = HTTPS_PORT;
1289 if (uri.portText.first) { 1245 }
1290 new_port = atoi (uri_string (uri.portText, buf, DEFAULT_BUFFER_SIZE)); 1246 if (new_port > MAX_PORT)
1291 } else { 1247 die(STATE_UNKNOWN, _("HTTP UNKNOWN - Redirection to port above %d - %s%s\n"), MAX_PORT, location, display_html ? "</A>" : "");
1292 new_port = HTTP_PORT; 1248
1293 if (use_ssl) 1249 /* by RFC 7231 relative URLs in Location should be taken relative to
1294 new_port = HTTPS_PORT; 1250 * the original URL, so we try to form a new absolute URL here
1295 } 1251 */
1296 if (new_port > MAX_PORT) 1252 if (!uri.scheme.first && !uri.hostText.first) {
1297 die (STATE_UNKNOWN, 1253 new_host = strdup(host_name ? host_name : server_address);
1298 _("HTTP UNKNOWN - Redirection to port above %d - %s%s\n"), 1254 new_port = server_port;
1299 MAX_PORT, location, display_html ? "</A>" : ""); 1255 if (use_ssl)
1300 1256 uri_string(uri.scheme, "https", DEFAULT_BUFFER_SIZE);
1301 /* by RFC 7231 relative URLs in Location should be taken relative to 1257 } else {
1302 * the original URL, so wy try to form a new absolute URL here 1258 new_host = strdup(uri_string(uri.hostText, buf, DEFAULT_BUFFER_SIZE));
1303 */ 1259 }
1304 if (!uri.scheme.first && !uri.hostText.first) { 1260
1305 new_host = strdup (host_name ? host_name : server_address); 1261 /* compose new path */
1306 } else { 1262 /* TODO: handle fragments and query part of URL */
1307 new_host = strdup (uri_string (uri.hostText, buf, DEFAULT_BUFFER_SIZE)); 1263 new_url = (char *)calloc(1, DEFAULT_BUFFER_SIZE);
1308 } 1264 if (uri.pathHead) {
1309 1265 const UriPathSegmentA *p = uri.pathHead;
1310 /* compose new path */ 1266 for (; p; p = p->next) {
1311 /* TODO: handle fragments and query part of URL */ 1267 strncat(new_url, "/", DEFAULT_BUFFER_SIZE);
1312 new_url = (char *)calloc( 1, DEFAULT_BUFFER_SIZE); 1268 strncat(new_url, uri_string(p->text, buf, DEFAULT_BUFFER_SIZE), DEFAULT_BUFFER_SIZE - 1);
1313 if (uri.pathHead) { 1269 }
1314 const UriPathSegmentA* p = uri.pathHead; 1270 }
1315 for (; p; p = p->next) { 1271
1316 strncat (new_url, "/", DEFAULT_BUFFER_SIZE); 1272 if (server_port == new_port && !strncmp(server_address, new_host, MAX_IPV4_HOSTLENGTH) &&
1317 strncat (new_url, uri_string (p->text, buf, DEFAULT_BUFFER_SIZE), DEFAULT_BUFFER_SIZE-1); 1273 (host_name && !strncmp(host_name, new_host, MAX_IPV4_HOSTLENGTH)) && !strcmp(server_url, new_url))
1318 } 1274 die(STATE_CRITICAL, _("HTTP CRITICAL - redirection creates an infinite loop - %s://%s:%d%s%s\n"), use_ssl ? "https" : "http",
1319 } 1275 new_host, new_port, new_url, (display_html ? "</A>" : ""));
1320 1276
1321 if (server_port==new_port && 1277 /* set new values for redirected request */
1322 !strncmp(server_address, new_host, MAX_IPV4_HOSTLENGTH) && 1278
1323 (host_name && !strncmp(host_name, new_host, MAX_IPV4_HOSTLENGTH)) && 1279 if (!(followsticky & STICKY_HOST)) {
1324 !strcmp(server_url, new_url)) 1280 free(server_address);
1325 die (STATE_CRITICAL, 1281 server_address = strndup(new_host, MAX_IPV4_HOSTLENGTH);
1326 _("HTTP CRITICAL - redirection creates an infinite loop - %s://%s:%d%s%s\n"), 1282 }
1327 use_ssl ? "https" : "http", new_host, new_port, new_url, (display_html ? "</A>" : "")); 1283 if (!(followsticky & STICKY_PORT)) {
1328 1284 server_port = (unsigned short)new_port;
1329 /* set new values for redirected request */ 1285 }
1330 1286
1331 if (!(followsticky & STICKY_HOST)) { 1287 free(host_name);
1332 free (server_address); 1288 host_name = strndup(new_host, MAX_IPV4_HOSTLENGTH);
1333 server_address = strndup (new_host, MAX_IPV4_HOSTLENGTH); 1289
1334 } 1290 /* reset virtual port */
1335 if (!(followsticky & STICKY_PORT)) { 1291 virtual_port = server_port;
1336 server_port = (unsigned short)new_port; 1292
1337 } 1293 free(new_host);
1338 1294 free(server_url);
1339 free (host_name); 1295 server_url = new_url;
1340 host_name = strndup (new_host, MAX_IPV4_HOSTLENGTH); 1296
1341 1297 uriFreeUriMembersA(&uri);
1342 /* reset virtual port */ 1298
1343 virtual_port = server_port; 1299 if (verbose)
1344 1300 printf(_("Redirection to %s://%s:%d%s\n"), use_ssl ? "https" : "http", host_name ? host_name : server_address, server_port,
1345 free(new_host); 1301 server_url);
1346 free (server_url); 1302
1347 server_url = new_url; 1303 /* TODO: the hash component MUST be taken from the original URL and
1348 1304 * attached to the URL in Location
1349 uriFreeUriMembersA (&uri); 1305 */
1350 1306
1351 if (verbose) 1307 cleanup();
1352 printf (_("Redirection to %s://%s:%d%s\n"), use_ssl ? "https" : "http", 1308 check_http();
1353 host_name ? host_name : server_address, server_port, server_url);
1354
1355 /* TODO: the hash component MUST be taken from the original URL and
1356 * attached to the URL in Location
1357 */
1358
1359 cleanup ();
1360 check_http ();
1361} 1309}
1362 1310
1363/* check whether a file exists */ 1311/* check whether a file exists */
1364void 1312void test_file(char *path) {
1365test_file (char *path) 1313 if (access(path, R_OK) == 0)
1366{ 1314 return;
1367 if (access(path, R_OK) == 0) 1315 usage2(_("file does not exist or is not readable"), path);
1368 return;
1369 usage2 (_("file does not exist or is not readable"), path);
1370} 1316}
1371 1317
1372bool 1318bool process_arguments(int argc, char **argv) {
1373process_arguments (int argc, char **argv) 1319 char *p;
1374{ 1320 int c = 1;
1375 char *p; 1321 char *temp;
1376 int c = 1; 1322
1377 char *temp; 1323 enum {
1378 1324 INVERT_REGEX = CHAR_MAX + 1,
1379 enum { 1325 SNI_OPTION,
1380 INVERT_REGEX = CHAR_MAX + 1, 1326 MAX_REDIRS_OPTION,
1381 SNI_OPTION, 1327 CONTINUE_AFTER_CHECK_CERT,
1382 MAX_REDIRS_OPTION, 1328 CA_CERT_OPTION,
1383 CONTINUE_AFTER_CHECK_CERT, 1329 HTTP_VERSION_OPTION,
1384 CA_CERT_OPTION, 1330 AUTOMATIC_DECOMPRESSION,
1385 HTTP_VERSION_OPTION, 1331 COOKIE_JAR,
1386 AUTOMATIC_DECOMPRESSION, 1332 HAPROXY_PROTOCOL,
1387 COOKIE_JAR 1333 STATE_REGEX
1388 }; 1334 };
1389 1335
1390 int option = 0; 1336 int option = 0;
1391 int got_plus = 0; 1337 int got_plus = 0;
1392 static struct option longopts[] = { 1338 static struct option longopts[] = {STD_LONG_OPTS,
1393 STD_LONG_OPTS, 1339 {"link", no_argument, 0, 'L'},
1394 {"link", no_argument, 0, 'L'}, 1340 {"nohtml", no_argument, 0, 'n'},
1395 {"nohtml", no_argument, 0, 'n'}, 1341 {"ssl", optional_argument, 0, 'S'},
1396 {"ssl", optional_argument, 0, 'S'}, 1342 {"sni", no_argument, 0, SNI_OPTION},
1397 {"sni", no_argument, 0, SNI_OPTION}, 1343 {"post", required_argument, 0, 'P'},
1398 {"post", required_argument, 0, 'P'}, 1344 {"method", required_argument, 0, 'j'},
1399 {"method", required_argument, 0, 'j'}, 1345 {"IP-address", required_argument, 0, 'I'},
1400 {"IP-address", required_argument, 0, 'I'}, 1346 {"url", required_argument, 0, 'u'},
1401 {"url", required_argument, 0, 'u'}, 1347 {"port", required_argument, 0, 'p'},
1402 {"port", required_argument, 0, 'p'}, 1348 {"authorization", required_argument, 0, 'a'},
1403 {"authorization", required_argument, 0, 'a'}, 1349 {"proxy-authorization", required_argument, 0, 'b'},
1404 {"proxy-authorization", required_argument, 0, 'b'}, 1350 {"header-string", required_argument, 0, 'd'},
1405 {"header-string", required_argument, 0, 'd'}, 1351 {"string", required_argument, 0, 's'},
1406 {"string", required_argument, 0, 's'}, 1352 {"expect", required_argument, 0, 'e'},
1407 {"expect", required_argument, 0, 'e'}, 1353 {"regex", required_argument, 0, 'r'},
1408 {"regex", required_argument, 0, 'r'}, 1354 {"ereg", required_argument, 0, 'r'},
1409 {"ereg", required_argument, 0, 'r'}, 1355 {"eregi", required_argument, 0, 'R'},
1410 {"eregi", required_argument, 0, 'R'}, 1356 {"linespan", no_argument, 0, 'l'},
1411 {"linespan", no_argument, 0, 'l'}, 1357 {"onredirect", required_argument, 0, 'f'},
1412 {"onredirect", required_argument, 0, 'f'}, 1358 {"certificate", required_argument, 0, 'C'},
1413 {"certificate", required_argument, 0, 'C'}, 1359 {"client-cert", required_argument, 0, 'J'},
1414 {"client-cert", required_argument, 0, 'J'}, 1360 {"private-key", required_argument, 0, 'K'},
1415 {"private-key", required_argument, 0, 'K'}, 1361 {"ca-cert", required_argument, 0, CA_CERT_OPTION},
1416 {"ca-cert", required_argument, 0, CA_CERT_OPTION}, 1362 {"verify-cert", no_argument, 0, 'D'},
1417 {"verify-cert", no_argument, 0, 'D'}, 1363 {"continue-after-certificate", no_argument, 0, CONTINUE_AFTER_CHECK_CERT},
1418 {"continue-after-certificate", no_argument, 0, CONTINUE_AFTER_CHECK_CERT}, 1364 {"useragent", required_argument, 0, 'A'},
1419 {"useragent", required_argument, 0, 'A'}, 1365 {"header", required_argument, 0, 'k'},
1420 {"header", required_argument, 0, 'k'}, 1366 {"no-body", no_argument, 0, 'N'},
1421 {"no-body", no_argument, 0, 'N'}, 1367 {"max-age", required_argument, 0, 'M'},
1422 {"max-age", required_argument, 0, 'M'}, 1368 {"content-type", required_argument, 0, 'T'},
1423 {"content-type", required_argument, 0, 'T'}, 1369 {"pagesize", required_argument, 0, 'm'},
1424 {"pagesize", required_argument, 0, 'm'}, 1370 {"invert-regex", no_argument, NULL, INVERT_REGEX},
1425 {"invert-regex", no_argument, NULL, INVERT_REGEX}, 1371 {"state-regex", required_argument, 0, STATE_REGEX},
1426 {"use-ipv4", no_argument, 0, '4'}, 1372 {"use-ipv4", no_argument, 0, '4'},
1427 {"use-ipv6", no_argument, 0, '6'}, 1373 {"use-ipv6", no_argument, 0, '6'},
1428 {"extended-perfdata", no_argument, 0, 'E'}, 1374 {"extended-perfdata", no_argument, 0, 'E'},
1429 {"show-body", no_argument, 0, 'B'}, 1375 {"show-body", no_argument, 0, 'B'},
1430 {"max-redirs", required_argument, 0, MAX_REDIRS_OPTION}, 1376 {"max-redirs", required_argument, 0, MAX_REDIRS_OPTION},
1431 {"http-version", required_argument, 0, HTTP_VERSION_OPTION}, 1377 {"http-version", required_argument, 0, HTTP_VERSION_OPTION},
1432 {"enable-automatic-decompression", no_argument, 0, AUTOMATIC_DECOMPRESSION}, 1378 {"enable-automatic-decompression", no_argument, 0, AUTOMATIC_DECOMPRESSION},
1433 {"cookie-jar", required_argument, 0, COOKIE_JAR}, 1379 {"cookie-jar", required_argument, 0, COOKIE_JAR},
1434 {0, 0, 0, 0} 1380 {"haproxy-protocol", no_argument, 0, HAPROXY_PROTOCOL},
1435 }; 1381 {0, 0, 0, 0}};
1436 1382
1437 if (argc < 2) 1383 if (argc < 2)
1438 return false; 1384 return false;
1439 1385
1440 /* support check_http compatible arguments */ 1386 /* support check_http compatible arguments */
1441 for (c = 1; c < argc; c++) { 1387 for (c = 1; c < argc; c++) {
1442 if (strcmp ("-to", argv[c]) == 0) 1388 if (strcmp("-to", argv[c]) == 0)
1443 strcpy (argv[c], "-t"); 1389 strcpy(argv[c], "-t");
1444 if (strcmp ("-hn", argv[c]) == 0) 1390 if (strcmp("-hn", argv[c]) == 0)
1445 strcpy (argv[c], "-H"); 1391 strcpy(argv[c], "-H");
1446 if (strcmp ("-wt", argv[c]) == 0) 1392 if (strcmp("-wt", argv[c]) == 0)
1447 strcpy (argv[c], "-w"); 1393 strcpy(argv[c], "-w");
1448 if (strcmp ("-ct", argv[c]) == 0) 1394 if (strcmp("-ct", argv[c]) == 0)
1449 strcpy (argv[c], "-c"); 1395 strcpy(argv[c], "-c");
1450 if (strcmp ("-nohtml", argv[c]) == 0) 1396 if (strcmp("-nohtml", argv[c]) == 0)
1451 strcpy (argv[c], "-n"); 1397 strcpy(argv[c], "-n");
1452 } 1398 }
1453 1399
1454 server_url = strdup(DEFAULT_SERVER_URL); 1400 server_url = strdup(DEFAULT_SERVER_URL);
1455 1401
1456 while (1) { 1402 while (1) {
1457 c = getopt_long (argc, argv, "Vvh46t:c:w:A:k:H:P:j:T:I:a:b:d:e:p:s:R:r:u:f:C:J:K:DnlLS::m:M:NEB", longopts, &option); 1403 c = getopt_long(argc, argv, "Vvh46t:c:w:A:k:H:P:j:T:I:a:b:d:e:p:s:R:r:u:f:C:J:K:DnlLS::m:M:NEB", longopts, &option);
1458 if (c == -1 || c == EOF || c == 1) 1404 if (c == -1 || c == EOF || c == 1)
1459 break; 1405 break;
1460 1406
1461 switch (c) { 1407 switch (c) {
1462 case 'h': 1408 case 'h':
1463 print_help(); 1409 print_help();
1464 exit(STATE_UNKNOWN); 1410 exit(STATE_UNKNOWN);
1465 break; 1411 break;
1466 case 'V': 1412 case 'V':
1467 print_revision(progname, NP_VERSION); 1413 print_revision(progname, NP_VERSION);
1468 print_curl_version(); 1414 print_curl_version();
1469 exit(STATE_UNKNOWN); 1415 exit(STATE_UNKNOWN);
1470 break; 1416 break;
1471 case 'v': 1417 case 'v':
1472 verbose++; 1418 verbose++;
1473 break; 1419 break;
1474 case 't': /* timeout period */ 1420 case 't': /* timeout period */
1475 if (!is_intnonneg (optarg)) 1421 if (!is_intnonneg(optarg))
1476 usage2 (_("Timeout interval must be a positive integer"), optarg); 1422 usage2(_("Timeout interval must be a positive integer"), optarg);
1477 else 1423 else
1478 socket_timeout = (int)strtol (optarg, NULL, 10); 1424 socket_timeout = (int)strtol(optarg, NULL, 10);
1479 break; 1425 break;
1480 case 'c': /* critical time threshold */ 1426 case 'c': /* critical time threshold */
1481 critical_thresholds = optarg; 1427 critical_thresholds = optarg;
1482 break; 1428 break;
1483 case 'w': /* warning time threshold */ 1429 case 'w': /* warning time threshold */
1484 warning_thresholds = optarg; 1430 warning_thresholds = optarg;
1485 break; 1431 break;
1486 case 'H': /* virtual host */ 1432 case 'H': /* virtual host */
1487 host_name = strdup (optarg); 1433 host_name = strdup(optarg);
1488 if (host_name[0] == '[') { 1434 if (host_name[0] == '[') {
1489 if ((p = strstr (host_name, "]:")) != NULL) { /* [IPv6]:port */ 1435 if ((p = strstr(host_name, "]:")) != NULL) { /* [IPv6]:port */
1490 virtual_port = atoi (p + 2); 1436 virtual_port = atoi(p + 2);
1491 /* cut off the port */ 1437 /* cut off the port */
1492 host_name_length = strlen (host_name) - strlen (p) - 1; 1438 host_name_length = strlen(host_name) - strlen(p) - 1;
1493 free (host_name); 1439 free(host_name);
1494 host_name = strndup (optarg, host_name_length); 1440 host_name = strndup(optarg, host_name_length);
1495 } 1441 }
1496 } else if ((p = strchr (host_name, ':')) != NULL 1442 } else if ((p = strchr(host_name, ':')) != NULL && strchr(++p, ':') == NULL) { /* IPv4:port or host:port */
1497 && strchr (++p, ':') == NULL) { /* IPv4:port or host:port */ 1443 virtual_port = atoi(p);
1498 virtual_port = atoi (p); 1444 /* cut off the port */
1499 /* cut off the port */ 1445 host_name_length = strlen(host_name) - strlen(p) - 1;
1500 host_name_length = strlen (host_name) - strlen (p) - 1; 1446 free(host_name);
1501 free (host_name); 1447 host_name = strndup(optarg, host_name_length);
1502 host_name = strndup (optarg, host_name_length); 1448 }
1503 } 1449 break;
1504 break; 1450 case 'I': /* internet address */
1505 case 'I': /* internet address */ 1451 server_address = strdup(optarg);
1506 server_address = strdup (optarg); 1452 break;
1507 break; 1453 case 'u': /* URL path */
1508 case 'u': /* URL path */ 1454 server_url = strdup(optarg);
1509 server_url = strdup (optarg); 1455 break;
1510 break; 1456 case 'p': /* Server port */
1511 case 'p': /* Server port */ 1457 if (!is_intnonneg(optarg))
1512 if (!is_intnonneg (optarg)) 1458 usage2(_("Invalid port number, expecting a non-negative number"), optarg);
1513 usage2 (_("Invalid port number, expecting a non-negative number"), optarg); 1459 else {
1514 else { 1460 if (strtol(optarg, NULL, 10) > MAX_PORT)
1515 if( strtol(optarg, NULL, 10) > MAX_PORT) 1461 usage2(_("Invalid port number, supplied port number is too big"), optarg);
1516 usage2 (_("Invalid port number, supplied port number is too big"), optarg); 1462 server_port = (unsigned short)strtol(optarg, NULL, 10);
1517 server_port = (unsigned short)strtol(optarg, NULL, 10); 1463 specify_port = true;
1518 specify_port = true; 1464 }
1519 } 1465 break;
1520 break; 1466 case 'a': /* authorization info */
1521 case 'a': /* authorization info */ 1467 strncpy(user_auth, optarg, MAX_INPUT_BUFFER - 1);
1522 strncpy (user_auth, optarg, MAX_INPUT_BUFFER - 1); 1468 user_auth[MAX_INPUT_BUFFER - 1] = 0;
1523 user_auth[MAX_INPUT_BUFFER - 1] = 0; 1469 break;
1524 break; 1470 case 'b': /* proxy-authorization info */
1525 case 'b': /* proxy-authorization info */ 1471 strncpy(proxy_auth, optarg, MAX_INPUT_BUFFER - 1);
1526 strncpy (proxy_auth, optarg, MAX_INPUT_BUFFER - 1); 1472 proxy_auth[MAX_INPUT_BUFFER - 1] = 0;
1527 proxy_auth[MAX_INPUT_BUFFER - 1] = 0; 1473 break;
1528 break; 1474 case 'P': /* HTTP POST data in URL encoded format; ignored if settings already */
1529 case 'P': /* HTTP POST data in URL encoded format; ignored if settings already */ 1475 if (!http_post_data)
1530 if (! http_post_data) 1476 http_post_data = strdup(optarg);
1531 http_post_data = strdup (optarg); 1477 if (!http_method)
1532 if (! http_method) 1478 http_method = strdup("POST");
1533 http_method = strdup("POST"); 1479 break;
1534 break; 1480 case 'j': /* Set HTTP method */
1535 case 'j': /* Set HTTP method */ 1481 if (http_method)
1536 if (http_method) 1482 free(http_method);
1537 free(http_method); 1483 http_method = strdup(optarg);
1538 http_method = strdup (optarg); 1484 break;
1539 break; 1485 case 'A': /* useragent */
1540 case 'A': /* useragent */ 1486 strncpy(user_agent, optarg, DEFAULT_BUFFER_SIZE);
1541 strncpy (user_agent, optarg, DEFAULT_BUFFER_SIZE); 1487 user_agent[DEFAULT_BUFFER_SIZE - 1] = '\0';
1542 user_agent[DEFAULT_BUFFER_SIZE-1] = '\0'; 1488 break;
1543 break; 1489 case 'k': /* Additional headers */
1544 case 'k': /* Additional headers */ 1490 if (http_opt_headers_count == 0)
1545 if (http_opt_headers_count == 0) 1491 http_opt_headers = malloc(sizeof(char *) * (++http_opt_headers_count));
1546 http_opt_headers = malloc (sizeof (char *) * (++http_opt_headers_count)); 1492 else
1547 else 1493 http_opt_headers = realloc(http_opt_headers, sizeof(char *) * (++http_opt_headers_count));
1548 http_opt_headers = realloc (http_opt_headers, sizeof (char *) * (++http_opt_headers_count)); 1494 http_opt_headers[http_opt_headers_count - 1] = optarg;
1549 http_opt_headers[http_opt_headers_count - 1] = optarg; 1495 break;
1550 break; 1496 case 'L': /* show html link */
1551 case 'L': /* show html link */ 1497 display_html = true;
1552 display_html = true; 1498 break;
1553 break; 1499 case 'n': /* do not show html link */
1554 case 'n': /* do not show html link */ 1500 display_html = false;
1555 display_html = false; 1501 break;
1556 break; 1502 case 'C': /* Check SSL cert validity */
1557 case 'C': /* Check SSL cert validity */
1558#ifdef LIBCURL_FEATURE_SSL 1503#ifdef LIBCURL_FEATURE_SSL
1559 if ((temp=strchr(optarg,','))!=NULL) { 1504 if ((temp = strchr(optarg, ',')) != NULL) {
1560 *temp='\0'; 1505 *temp = '\0';
1561 if (!is_intnonneg (optarg)) 1506 if (!is_intnonneg(optarg))
1562 usage2 (_("Invalid certificate expiration period"), optarg); 1507 usage2(_("Invalid certificate expiration period"), optarg);
1563 days_till_exp_warn = atoi(optarg); 1508 days_till_exp_warn = atoi(optarg);
1564 *temp=','; 1509 *temp = ',';
1565 temp++; 1510 temp++;
1566 if (!is_intnonneg (temp)) 1511 if (!is_intnonneg(temp))
1567 usage2 (_("Invalid certificate expiration period"), temp); 1512 usage2(_("Invalid certificate expiration period"), temp);
1568 days_till_exp_crit = atoi (temp); 1513 days_till_exp_crit = atoi(temp);
1569 } 1514 } else {
1570 else { 1515 days_till_exp_crit = 0;
1571 days_till_exp_crit=0; 1516 if (!is_intnonneg(optarg))
1572 if (!is_intnonneg (optarg)) 1517 usage2(_("Invalid certificate expiration period"), optarg);
1573 usage2 (_("Invalid certificate expiration period"), optarg); 1518 days_till_exp_warn = atoi(optarg);
1574 days_till_exp_warn = atoi (optarg); 1519 }
1575 } 1520 check_cert = true;
1576 check_cert = true; 1521 goto enable_ssl;
1577 goto enable_ssl;
1578#endif 1522#endif
1579 case CONTINUE_AFTER_CHECK_CERT: /* don't stop after the certificate is checked */ 1523 case CONTINUE_AFTER_CHECK_CERT: /* don't stop after the certificate is checked */
1580#ifdef HAVE_SSL 1524#ifdef HAVE_SSL
1581 continue_after_check_cert = true; 1525 continue_after_check_cert = true;
1582 break; 1526 break;
1583#endif 1527#endif
1584 case 'J': /* use client certificate */ 1528 case 'J': /* use client certificate */
1585#ifdef LIBCURL_FEATURE_SSL 1529#ifdef LIBCURL_FEATURE_SSL
1586 test_file(optarg); 1530 test_file(optarg);
1587 client_cert = optarg; 1531 client_cert = optarg;
1588 goto enable_ssl; 1532 goto enable_ssl;
1589#endif 1533#endif
1590 case 'K': /* use client private key */ 1534 case 'K': /* use client private key */
1591#ifdef LIBCURL_FEATURE_SSL 1535#ifdef LIBCURL_FEATURE_SSL
1592 test_file(optarg); 1536 test_file(optarg);
1593 client_privkey = optarg; 1537 client_privkey = optarg;
1594 goto enable_ssl; 1538 goto enable_ssl;
1595#endif 1539#endif
1596#ifdef LIBCURL_FEATURE_SSL 1540#ifdef LIBCURL_FEATURE_SSL
1597 case CA_CERT_OPTION: /* use CA chain file */ 1541 case CA_CERT_OPTION: /* use CA chain file */
1598 test_file(optarg); 1542 test_file(optarg);
1599 ca_cert = optarg; 1543 ca_cert = optarg;
1600 goto enable_ssl; 1544 goto enable_ssl;
1601#endif 1545#endif
1602#ifdef LIBCURL_FEATURE_SSL 1546#ifdef LIBCURL_FEATURE_SSL
1603 case 'D': /* verify peer certificate & host */ 1547 case 'D': /* verify peer certificate & host */
1604 verify_peer_and_host = true; 1548 verify_peer_and_host = true;
1605 break; 1549 break;
1606#endif 1550#endif
1607 case 'S': /* use SSL */ 1551 case 'S': /* use SSL */
1608#ifdef LIBCURL_FEATURE_SSL 1552#ifdef LIBCURL_FEATURE_SSL
1609 enable_ssl: 1553 enable_ssl:
1610 use_ssl = true; 1554 use_ssl = true;
1611 /* ssl_version initialized to CURL_SSLVERSION_DEFAULT as a default. 1555 /* ssl_version initialized to CURL_SSLVERSION_DEFAULT as a default.
1612 * Only set if it's non-zero. This helps when we include multiple 1556 * Only set if it's non-zero. This helps when we include multiple
1613 * parameters, like -S and -C combinations */ 1557 * parameters, like -S and -C combinations */
1614 ssl_version = CURL_SSLVERSION_DEFAULT; 1558 ssl_version = CURL_SSLVERSION_DEFAULT;
1615 if (c=='S' && optarg != NULL) { 1559 if (c == 'S' && optarg != NULL) {
1616 char *plus_ptr = strchr(optarg, '+'); 1560 char *plus_ptr = strchr(optarg, '+');
1617 if (plus_ptr) { 1561 if (plus_ptr) {
1618 got_plus = 1; 1562 got_plus = 1;
1619 *plus_ptr = '\0'; 1563 *plus_ptr = '\0';
1620 } 1564 }
1621 1565
1622 if (optarg[0] == '2') 1566 if (optarg[0] == '2')
1623 ssl_version = CURL_SSLVERSION_SSLv2; 1567 ssl_version = CURL_SSLVERSION_SSLv2;
1624 else if (optarg[0] == '3') 1568 else if (optarg[0] == '3')
1625 ssl_version = CURL_SSLVERSION_SSLv3; 1569 ssl_version = CURL_SSLVERSION_SSLv3;
1626 else if (!strcmp (optarg, "1") || !strcmp (optarg, "1.0")) 1570 else if (!strcmp(optarg, "1") || !strcmp(optarg, "1.0"))
1627#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) 1571# if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0)
1628 ssl_version = CURL_SSLVERSION_TLSv1_0; 1572 ssl_version = CURL_SSLVERSION_TLSv1_0;
1629#else 1573# else
1630 ssl_version = CURL_SSLVERSION_DEFAULT; 1574 ssl_version = CURL_SSLVERSION_DEFAULT;
1631#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) */ 1575# endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) */
1632 else if (!strcmp (optarg, "1.1")) 1576 else if (!strcmp(optarg, "1.1"))
1633#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) 1577# if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0)
1634 ssl_version = CURL_SSLVERSION_TLSv1_1; 1578 ssl_version = CURL_SSLVERSION_TLSv1_1;
1635#else 1579# else
1636 ssl_version = CURL_SSLVERSION_DEFAULT; 1580 ssl_version = CURL_SSLVERSION_DEFAULT;
1637#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) */ 1581# endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) */
1638 else if (!strcmp (optarg, "1.2")) 1582 else if (!strcmp(optarg, "1.2"))
1639#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) 1583# if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0)
1640 ssl_version = CURL_SSLVERSION_TLSv1_2; 1584 ssl_version = CURL_SSLVERSION_TLSv1_2;
1641#else 1585# else
1642 ssl_version = CURL_SSLVERSION_DEFAULT; 1586 ssl_version = CURL_SSLVERSION_DEFAULT;
1643#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) */ 1587# endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) */
1644 else if (!strcmp (optarg, "1.3")) 1588 else if (!strcmp(optarg, "1.3"))
1645#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 52, 0) 1589# if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 52, 0)
1646 ssl_version = CURL_SSLVERSION_TLSv1_3; 1590 ssl_version = CURL_SSLVERSION_TLSv1_3;
1647#else 1591# else
1648 ssl_version = CURL_SSLVERSION_DEFAULT; 1592 ssl_version = CURL_SSLVERSION_DEFAULT;
1649#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 52, 0) */ 1593# endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 52, 0) */
1650 else 1594 else
1651 usage4 (_("Invalid option - Valid SSL/TLS versions: 2, 3, 1, 1.1, 1.2, 1.3 (with optional '+' suffix)")); 1595 usage4(_("Invalid option - Valid SSL/TLS versions: 2, 3, 1, 1.1, 1.2, 1.3 (with optional '+' suffix)"));
1652 } 1596 }
1653#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 54, 0) 1597# if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 54, 0)
1654 if (got_plus) { 1598 if (got_plus) {
1655 switch (ssl_version) { 1599 switch (ssl_version) {
1656 case CURL_SSLVERSION_TLSv1_3: 1600 case CURL_SSLVERSION_TLSv1_3:
1657 ssl_version |= CURL_SSLVERSION_MAX_TLSv1_3; 1601 ssl_version |= CURL_SSLVERSION_MAX_TLSv1_3;
1658 break; 1602 break;
1659 case CURL_SSLVERSION_TLSv1_2: 1603 case CURL_SSLVERSION_TLSv1_2:
1660 case CURL_SSLVERSION_TLSv1_1: 1604 case CURL_SSLVERSION_TLSv1_1:
1661 case CURL_SSLVERSION_TLSv1_0: 1605 case CURL_SSLVERSION_TLSv1_0:
1662 ssl_version |= CURL_SSLVERSION_MAX_DEFAULT; 1606 ssl_version |= CURL_SSLVERSION_MAX_DEFAULT;
1663 break; 1607 break;
1664 } 1608 }
1665 } else { 1609 } else {
1666 switch (ssl_version) { 1610 switch (ssl_version) {
1667 case CURL_SSLVERSION_TLSv1_3: 1611 case CURL_SSLVERSION_TLSv1_3:
1668 ssl_version |= CURL_SSLVERSION_MAX_TLSv1_3; 1612 ssl_version |= CURL_SSLVERSION_MAX_TLSv1_3;
1669 break; 1613 break;
1670 case CURL_SSLVERSION_TLSv1_2: 1614 case CURL_SSLVERSION_TLSv1_2:
1671 ssl_version |= CURL_SSLVERSION_MAX_TLSv1_2; 1615 ssl_version |= CURL_SSLVERSION_MAX_TLSv1_2;
1672 break; 1616 break;
1673 case CURL_SSLVERSION_TLSv1_1: 1617 case CURL_SSLVERSION_TLSv1_1:
1674 ssl_version |= CURL_SSLVERSION_MAX_TLSv1_1; 1618 ssl_version |= CURL_SSLVERSION_MAX_TLSv1_1;
1675 break; 1619 break;
1676 case CURL_SSLVERSION_TLSv1_0: 1620 case CURL_SSLVERSION_TLSv1_0:
1677 ssl_version |= CURL_SSLVERSION_MAX_TLSv1_0; 1621 ssl_version |= CURL_SSLVERSION_MAX_TLSv1_0;
1678 break; 1622 break;
1679 } 1623 }
1680 } 1624 }
1681#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 54, 0) */ 1625# endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 54, 0) */
1682 if (verbose >= 2) 1626 if (verbose >= 2)
1683 printf(_("* Set SSL/TLS version to %d\n"), ssl_version); 1627 printf(_("* Set SSL/TLS version to %d\n"), ssl_version);
1684 if (!specify_port) 1628 if (!specify_port)
1685 server_port = HTTPS_PORT; 1629 server_port = HTTPS_PORT;
1686 break; 1630 break;
1687#else /* LIBCURL_FEATURE_SSL */ 1631#else /* LIBCURL_FEATURE_SSL */
1688 /* -C -J and -K fall through to here without SSL */ 1632 /* -C -J and -K fall through to here without SSL */
1689 usage4 (_("Invalid option - SSL is not available")); 1633 usage4(_("Invalid option - SSL is not available"));
1690 break; 1634 break;
1691 case SNI_OPTION: /* --sni is parsed, but ignored, the default is true with libcurl */ 1635 case SNI_OPTION: /* --sni is parsed, but ignored, the default is true with libcurl */
1692 use_sni = true; 1636 use_sni = true;
1693 break; 1637 break;
1694#endif /* LIBCURL_FEATURE_SSL */ 1638#endif /* LIBCURL_FEATURE_SSL */
1695 case MAX_REDIRS_OPTION: 1639 case MAX_REDIRS_OPTION:
1696 if (!is_intnonneg (optarg)) 1640 if (!is_intnonneg(optarg))
1697 usage2 (_("Invalid max_redirs count"), optarg); 1641 usage2(_("Invalid max_redirs count"), optarg);
1698 else { 1642 else {
1699 max_depth = atoi (optarg); 1643 max_depth = atoi(optarg);
1700 } 1644 }
1701 break; 1645 break;
1702 case 'f': /* onredirect */ 1646 case 'f': /* onredirect */
1703 if (!strcmp (optarg, "ok")) 1647 if (!strcmp(optarg, "ok"))
1704 onredirect = STATE_OK; 1648 onredirect = STATE_OK;
1705 else if (!strcmp (optarg, "warning")) 1649 else if (!strcmp(optarg, "warning"))
1706 onredirect = STATE_WARNING; 1650 onredirect = STATE_WARNING;
1707 else if (!strcmp (optarg, "critical")) 1651 else if (!strcmp(optarg, "critical"))
1708 onredirect = STATE_CRITICAL; 1652 onredirect = STATE_CRITICAL;
1709 else if (!strcmp (optarg, "unknown")) 1653 else if (!strcmp(optarg, "unknown"))
1710 onredirect = STATE_UNKNOWN; 1654 onredirect = STATE_UNKNOWN;
1711 else if (!strcmp (optarg, "follow")) 1655 else if (!strcmp(optarg, "follow"))
1712 onredirect = STATE_DEPENDENT; 1656 onredirect = STATE_DEPENDENT;
1713 else if (!strcmp (optarg, "stickyport")) 1657 else if (!strcmp(optarg, "stickyport"))
1714 onredirect = STATE_DEPENDENT, followmethod = FOLLOW_HTTP_CURL, followsticky = STICKY_HOST|STICKY_PORT; 1658 onredirect = STATE_DEPENDENT, followmethod = FOLLOW_HTTP_CURL, followsticky = STICKY_HOST | STICKY_PORT;
1715 else if (!strcmp (optarg, "sticky")) 1659 else if (!strcmp(optarg, "sticky"))
1716 onredirect = STATE_DEPENDENT, followmethod = FOLLOW_HTTP_CURL, followsticky = STICKY_HOST; 1660 onredirect = STATE_DEPENDENT, followmethod = FOLLOW_HTTP_CURL, followsticky = STICKY_HOST;
1717 else if (!strcmp (optarg, "follow")) 1661 else if (!strcmp(optarg, "follow"))
1718 onredirect = STATE_DEPENDENT, followmethod = FOLLOW_HTTP_CURL, followsticky = STICKY_NONE; 1662 onredirect = STATE_DEPENDENT, followmethod = FOLLOW_HTTP_CURL, followsticky = STICKY_NONE;
1719 else if (!strcmp (optarg, "curl")) 1663 else if (!strcmp(optarg, "curl"))
1720 onredirect = STATE_DEPENDENT, followmethod = FOLLOW_LIBCURL; 1664 onredirect = STATE_DEPENDENT, followmethod = FOLLOW_LIBCURL;
1721 else usage2 (_("Invalid onredirect option"), optarg); 1665 else
1722 if (verbose >= 2) 1666 usage2(_("Invalid onredirect option"), optarg);
1723 printf(_("* Following redirects set to %s\n"), state_text(onredirect)); 1667 if (verbose >= 2)
1724 break; 1668 printf(_("* Following redirects set to %s\n"), state_text(onredirect));
1725 case 'd': /* string or substring */ 1669 break;
1726 strncpy (header_expect, optarg, MAX_INPUT_BUFFER - 1); 1670 case 'd': /* string or substring */
1727 header_expect[MAX_INPUT_BUFFER - 1] = 0; 1671 strncpy(header_expect, optarg, MAX_INPUT_BUFFER - 1);
1728 break; 1672 header_expect[MAX_INPUT_BUFFER - 1] = 0;
1729 case 's': /* string or substring */ 1673 break;
1730 strncpy (string_expect, optarg, MAX_INPUT_BUFFER - 1); 1674 case 's': /* string or substring */
1731 string_expect[MAX_INPUT_BUFFER - 1] = 0; 1675 strncpy(string_expect, optarg, MAX_INPUT_BUFFER - 1);
1732 break; 1676 string_expect[MAX_INPUT_BUFFER - 1] = 0;
1733 case 'e': /* string or substring */ 1677 break;
1734 strncpy (server_expect, optarg, MAX_INPUT_BUFFER - 1); 1678 case 'e': /* string or substring */
1735 server_expect[MAX_INPUT_BUFFER - 1] = 0; 1679 strncpy(server_expect, optarg, MAX_INPUT_BUFFER - 1);
1736 server_expect_yn = 1; 1680 server_expect[MAX_INPUT_BUFFER - 1] = 0;
1737 break; 1681 server_expect_yn = 1;
1738 case 'T': /* Content-type */ 1682 break;
1739 http_content_type = strdup (optarg); 1683 case 'T': /* Content-type */
1740 break; 1684 http_content_type = strdup(optarg);
1741 case 'l': /* linespan */ 1685 break;
1742 cflags &= ~REG_NEWLINE; 1686 case 'l': /* linespan */
1743 break; 1687 cflags &= ~REG_NEWLINE;
1744 case 'R': /* regex */ 1688 break;
1745 cflags |= REG_ICASE; 1689 case 'R': /* regex */
1690 cflags |= REG_ICASE;
1746 // fall through 1691 // fall through
1747 case 'r': /* regex */ 1692 case 'r': /* regex */
1748 strncpy (regexp, optarg, MAX_RE_SIZE - 1); 1693 strncpy(regexp, optarg, MAX_RE_SIZE - 1);
1749 regexp[MAX_RE_SIZE - 1] = 0; 1694 regexp[MAX_RE_SIZE - 1] = 0;
1750 errcode = regcomp (&preg, regexp, cflags); 1695 errcode = regcomp(&preg, regexp, cflags);
1751 if (errcode != 0) { 1696 if (errcode != 0) {
1752 (void) regerror (errcode, &preg, errbuf, MAX_INPUT_BUFFER); 1697 (void)regerror(errcode, &preg, errbuf, MAX_INPUT_BUFFER);
1753 printf (_("Could Not Compile Regular Expression: %s"), errbuf); 1698 printf(_("Could Not Compile Regular Expression: %s"), errbuf);
1754 return false; 1699 return false;
1755 } 1700 }
1756 break; 1701 break;
1757 case INVERT_REGEX: 1702 case INVERT_REGEX:
1758 invert_regex = true; 1703 invert_regex = true;
1759 break; 1704 break;
1760 case '4': 1705 case STATE_REGEX:
1761 address_family = AF_INET; 1706 if (!strcasecmp(optarg, "critical"))
1762 break; 1707 state_regex = STATE_CRITICAL;
1763 case '6': 1708 else if (!strcasecmp(optarg, "warning"))
1764#if defined (USE_IPV6) && defined (LIBCURL_FEATURE_IPV6) 1709 state_regex = STATE_WARNING;
1765 address_family = AF_INET6; 1710 else
1711 usage2(_("Invalid state-regex option"), optarg);
1712 break;
1713 case '4':
1714 address_family = AF_INET;
1715 break;
1716 case '6':
1717#if defined(USE_IPV6) && defined(LIBCURL_FEATURE_IPV6)
1718 address_family = AF_INET6;
1766#else 1719#else
1767 usage4 (_("IPv6 support not available")); 1720 usage4(_("IPv6 support not available"));
1768#endif 1721#endif
1769 break; 1722 break;
1770 case 'm': /* min_page_length */ 1723 case 'm': /* min_page_length */
1771 { 1724 {
1772 char *tmp; 1725 char *tmp;
1773 if (strchr(optarg, ':') != (char *)NULL) { 1726 if (strchr(optarg, ':') != (char *)NULL) {
1774 /* range, so get two values, min:max */ 1727 /* range, so get two values, min:max */
1775 tmp = strtok(optarg, ":"); 1728 tmp = strtok(optarg, ":");
1776 if (tmp == NULL) { 1729 if (tmp == NULL) {
1777 printf("Bad format: try \"-m min:max\"\n"); 1730 printf("Bad format: try \"-m min:max\"\n");
1778 exit (STATE_WARNING); 1731 exit(STATE_WARNING);
1779 } else 1732 } else
1780 min_page_len = atoi(tmp); 1733 min_page_len = atoi(tmp);
1781 1734
1782 tmp = strtok(NULL, ":"); 1735 tmp = strtok(NULL, ":");
1783 if (tmp == NULL) { 1736 if (tmp == NULL) {
1784 printf("Bad format: try \"-m min:max\"\n"); 1737 printf("Bad format: try \"-m min:max\"\n");
1785 exit (STATE_WARNING); 1738 exit(STATE_WARNING);
1786 } else 1739 } else
1787 max_page_len = atoi(tmp); 1740 max_page_len = atoi(tmp);
1788 } else 1741 } else
1789 min_page_len = atoi (optarg); 1742 min_page_len = atoi(optarg);
1790 break; 1743 break;
1791 } 1744 }
1792 case 'N': /* no-body */ 1745 case 'N': /* no-body */
1793 no_body = true; 1746 no_body = true;
1794 break; 1747 break;
1795 case 'M': /* max-age */ 1748 case 'M': /* max-age */
1796 { 1749 {
1797 int L = strlen(optarg); 1750 int L = strlen(optarg);
1798 if (L && optarg[L-1] == 'm') 1751 if (L && optarg[L - 1] == 'm')
1799 maximum_age = atoi (optarg) * 60; 1752 maximum_age = atoi(optarg) * 60;
1800 else if (L && optarg[L-1] == 'h') 1753 else if (L && optarg[L - 1] == 'h')
1801 maximum_age = atoi (optarg) * 60 * 60; 1754 maximum_age = atoi(optarg) * 60 * 60;
1802 else if (L && optarg[L-1] == 'd') 1755 else if (L && optarg[L - 1] == 'd')
1803 maximum_age = atoi (optarg) * 60 * 60 * 24; 1756 maximum_age = atoi(optarg) * 60 * 60 * 24;
1804 else if (L && (optarg[L-1] == 's' || 1757 else if (L && (optarg[L - 1] == 's' || isdigit(optarg[L - 1])))
1805 isdigit (optarg[L-1]))) 1758 maximum_age = atoi(optarg);
1806 maximum_age = atoi (optarg); 1759 else {
1807 else { 1760 fprintf(stderr, "unparsable max-age: %s\n", optarg);
1808 fprintf (stderr, "unparsable max-age: %s\n", optarg); 1761 exit(STATE_WARNING);
1809 exit (STATE_WARNING); 1762 }
1810 } 1763 if (verbose >= 2)
1811 if (verbose >= 2) 1764 printf("* Maximal age of document set to %d seconds\n", maximum_age);
1812 printf ("* Maximal age of document set to %d seconds\n", maximum_age); 1765 } break;
1813 } 1766 case 'E': /* show extended perfdata */
1814 break; 1767 show_extended_perfdata = true;
1815 case 'E': /* show extended perfdata */ 1768 break;
1816 show_extended_perfdata = true; 1769 case 'B': /* print body content after status line */
1817 break; 1770 show_body = true;
1818 case 'B': /* print body content after status line */ 1771 break;
1819 show_body = true; 1772 case HTTP_VERSION_OPTION:
1820 break; 1773 curl_http_version = CURL_HTTP_VERSION_NONE;
1821 case HTTP_VERSION_OPTION: 1774 if (strcmp(optarg, "1.0") == 0) {
1822 curl_http_version = CURL_HTTP_VERSION_NONE; 1775 curl_http_version = CURL_HTTP_VERSION_1_0;
1823 if (strcmp (optarg, "1.0") == 0) { 1776 } else if (strcmp(optarg, "1.1") == 0) {
1824 curl_http_version = CURL_HTTP_VERSION_1_0; 1777 curl_http_version = CURL_HTTP_VERSION_1_1;
1825 } else if (strcmp (optarg, "1.1") == 0) { 1778 } else if ((strcmp(optarg, "2.0") == 0) || (strcmp(optarg, "2") == 0)) {
1826 curl_http_version = CURL_HTTP_VERSION_1_1;
1827 } else if ((strcmp (optarg, "2.0") == 0) || (strcmp (optarg, "2") == 0)) {
1828#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 33, 0) 1779#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 33, 0)
1829 curl_http_version = CURL_HTTP_VERSION_2_0; 1780 curl_http_version = CURL_HTTP_VERSION_2_0;
1830#else 1781#else
1831 curl_http_version = CURL_HTTP_VERSION_NONE; 1782 curl_http_version = CURL_HTTP_VERSION_NONE;
1832#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 33, 0) */ 1783#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 33, 0) */
1833 } else { 1784 } else {
1834 fprintf (stderr, "unknown http-version parameter: %s\n", optarg); 1785 fprintf(stderr, "unknown http-version parameter: %s\n", optarg);
1835 exit (STATE_WARNING); 1786 exit(STATE_WARNING);
1836 } 1787 }
1837 break; 1788 break;
1838 case AUTOMATIC_DECOMPRESSION: 1789 case AUTOMATIC_DECOMPRESSION:
1839 automatic_decompression = true; 1790 automatic_decompression = true;
1840 break; 1791 break;
1841 case COOKIE_JAR: 1792 case COOKIE_JAR:
1842 cookie_jar_file = optarg; 1793 cookie_jar_file = optarg;
1843 break; 1794 break;
1844 case '?': 1795 case HAPROXY_PROTOCOL:
1845 /* print short usage statement if args not parsable */ 1796 haproxy_protocol = true;
1846 usage5 (); 1797 break;
1847 break; 1798 case '?':
1848 } 1799 /* print short usage statement if args not parsable */
1849 } 1800 usage5();
1850 1801 break;
1851 c = optind; 1802 }
1852 1803 }
1853 if (server_address == NULL && c < argc) 1804
1854 server_address = strdup (argv[c++]); 1805 c = optind;
1855 1806
1856 if (host_name == NULL && c < argc) 1807 if (server_address == NULL && c < argc)
1857 host_name = strdup (argv[c++]); 1808 server_address = strdup(argv[c++]);
1858 1809
1859 if (server_address == NULL) { 1810 if (host_name == NULL && c < argc)
1860 if (host_name == NULL) 1811 host_name = strdup(argv[c++]);
1861 usage4 (_("You must specify a server address or host name")); 1812
1862 else 1813 if (server_address == NULL) {
1863 server_address = strdup (host_name); 1814 if (host_name == NULL)
1864 } 1815 usage4(_("You must specify a server address or host name"));
1865 1816 else
1866 set_thresholds(&thlds, warning_thresholds, critical_thresholds); 1817 server_address = strdup(host_name);
1867 1818 }
1868 if (critical_thresholds && thlds->critical->end>(double)socket_timeout) 1819
1869 socket_timeout = (int)thlds->critical->end + 1; 1820 set_thresholds(&thlds, warning_thresholds, critical_thresholds);
1870 if (verbose >= 2) 1821
1871 printf ("* Socket timeout set to %ld seconds\n", socket_timeout); 1822 if (critical_thresholds && thlds->critical->end > (double)socket_timeout)
1872 1823 socket_timeout = (int)thlds->critical->end + 1;
1873 if (http_method == NULL) 1824 if (verbose >= 2)
1874 http_method = strdup ("GET"); 1825 printf("* Socket timeout set to %ld seconds\n", socket_timeout);
1875 1826
1876 if (client_cert && !client_privkey) 1827 if (http_method == NULL)
1877 usage4 (_("If you use a client certificate you must also specify a private key file")); 1828 http_method = strdup("GET");
1878 1829
1879 if (virtual_port == 0) 1830 if (client_cert && !client_privkey)
1880 virtual_port = server_port; 1831 usage4(_("If you use a client certificate you must also specify a private key file"));
1881 else { 1832
1882 if ((use_ssl && server_port == HTTPS_PORT) || (!use_ssl && server_port == HTTP_PORT)) 1833 if (virtual_port == 0)
1883 if(!specify_port) 1834 virtual_port = server_port;
1884 server_port = virtual_port; 1835 else {
1885 } 1836 if ((use_ssl && server_port == HTTPS_PORT) || (!use_ssl && server_port == HTTP_PORT))
1886 1837 if (!specify_port)
1887 return true; 1838 server_port = virtual_port;
1839 }
1840
1841 return true;
1888} 1842}
1889 1843
1890char *perfd_time (double elapsed_time) 1844char *perfd_time(double elapsed_time) {
1891{ 1845 return fperfdata("time", elapsed_time, "s", thlds->warning ? true : false, thlds->warning ? thlds->warning->end : 0,
1892 return fperfdata ("time", elapsed_time, "s", 1846 thlds->critical ? true : false, thlds->critical ? thlds->critical->end : 0, true, 0, true, socket_timeout);
1893 thlds->warning?true:false, thlds->warning?thlds->warning->end:0,
1894 thlds->critical?true:false, thlds->critical?thlds->critical->end:0,
1895 true, 0, true, socket_timeout);
1896} 1847}
1897 1848
1898char *perfd_time_connect (double elapsed_time_connect) 1849char *perfd_time_connect(double elapsed_time_connect) {
1899{ 1850 return fperfdata("time_connect", elapsed_time_connect, "s", false, 0, false, 0, false, 0, true, socket_timeout);
1900 return fperfdata ("time_connect", elapsed_time_connect, "s", false, 0, false, 0, false, 0, true, socket_timeout);
1901} 1851}
1902 1852
1903char *perfd_time_ssl (double elapsed_time_ssl) 1853char *perfd_time_ssl(double elapsed_time_ssl) {
1904{ 1854 return fperfdata("time_ssl", elapsed_time_ssl, "s", false, 0, false, 0, false, 0, true, socket_timeout);
1905 return fperfdata ("time_ssl", elapsed_time_ssl, "s", false, 0, false, 0, false, 0, true, socket_timeout);
1906} 1855}
1907 1856
1908char *perfd_time_headers (double elapsed_time_headers) 1857char *perfd_time_headers(double elapsed_time_headers) {
1909{ 1858 return fperfdata("time_headers", elapsed_time_headers, "s", false, 0, false, 0, false, 0, true, socket_timeout);
1910 return fperfdata ("time_headers", elapsed_time_headers, "s", false, 0, false, 0, false, 0, true, socket_timeout);
1911} 1859}
1912 1860
1913char *perfd_time_firstbyte (double elapsed_time_firstbyte) 1861char *perfd_time_firstbyte(double elapsed_time_firstbyte) {
1914{ 1862 return fperfdata("time_firstbyte", elapsed_time_firstbyte, "s", false, 0, false, 0, false, 0, true, socket_timeout);
1915 return fperfdata ("time_firstbyte", elapsed_time_firstbyte, "s", false, 0, false, 0, false, 0, true, socket_timeout);
1916} 1863}
1917 1864
1918char *perfd_time_transfer (double elapsed_time_transfer) 1865char *perfd_time_transfer(double elapsed_time_transfer) {
1919{ 1866 return fperfdata("time_transfer", elapsed_time_transfer, "s", false, 0, false, 0, false, 0, true, socket_timeout);
1920 return fperfdata ("time_transfer", elapsed_time_transfer, "s", false, 0, false, 0, false, 0, true, socket_timeout);
1921} 1867}
1922 1868
1923char *perfd_size (int page_len) 1869char *perfd_size(int page_len) {
1924{ 1870 return perfdata("size", page_len, "B", (min_page_len > 0 ? true : false), min_page_len, (min_page_len > 0 ? true : false), 0, true, 0,
1925 return perfdata ("size", page_len, "B", 1871 false, 0);
1926 (min_page_len>0?true:false), min_page_len,
1927 (min_page_len>0?true:false), 0,
1928 true, 0, false, 0);
1929} 1872}
1930 1873
1931void 1874void print_help(void) {
1932print_help (void) 1875 print_revision(progname, NP_VERSION);
1933{
1934 print_revision (progname, NP_VERSION);
1935 1876
1936 printf ("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n"); 1877 printf("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n");
1937 printf (COPYRIGHT, copyright, email); 1878 printf(COPYRIGHT, copyright, email);
1938 1879
1939 printf ("%s\n", _("This plugin tests the HTTP service on the specified host. It can test")); 1880 printf("%s\n", _("This plugin tests the HTTP service on the specified host. It can test"));
1940 printf ("%s\n", _("normal (http) and secure (https) servers, follow redirects, search for")); 1881 printf("%s\n", _("normal (http) and secure (https) servers, follow redirects, search for"));
1941 printf ("%s\n", _("strings and regular expressions, check connection times, and report on")); 1882 printf("%s\n", _("strings and regular expressions, check connection times, and report on"));
1942 printf ("%s\n", _("certificate expiration times.")); 1883 printf("%s\n", _("certificate expiration times."));
1943 printf ("\n"); 1884 printf("\n");
1944 printf ("%s\n", _("It makes use of libcurl to do so. It tries to be as compatible to check_http")); 1885 printf("%s\n", _("It makes use of libcurl to do so. It tries to be as compatible to check_http"));
1945 printf ("%s\n", _("as possible.")); 1886 printf("%s\n", _("as possible."));
1946 1887
1947 printf ("\n\n"); 1888 printf("\n\n");
1948 1889
1949 print_usage (); 1890 print_usage();
1950 1891
1951 printf (_("NOTE: One or both of -H and -I must be specified")); 1892 printf(_("NOTE: One or both of -H and -I must be specified"));
1952 1893
1953 printf ("\n"); 1894 printf("\n");
1954 1895
1955 printf (UT_HELP_VRSN); 1896 printf(UT_HELP_VRSN);
1956 printf (UT_EXTRA_OPTS); 1897 printf(UT_EXTRA_OPTS);
1957 1898
1958 printf (" %s\n", "-H, --hostname=ADDRESS"); 1899 printf(" %s\n", "-H, --hostname=ADDRESS");
1959 printf (" %s\n", _("Host name argument for servers using host headers (virtual host)")); 1900 printf(" %s\n", _("Host name argument for servers using host headers (virtual host)"));
1960 printf (" %s\n", _("Append a port to include it in the header (eg: example.com:5000)")); 1901 printf(" %s\n", _("Append a port to include it in the header (eg: example.com:5000)"));
1961 printf (" %s\n", "-I, --IP-address=ADDRESS"); 1902 printf(" %s\n", "-I, --IP-address=ADDRESS");
1962 printf (" %s\n", _("IP address or name (use numeric address if possible to bypass DNS lookup).")); 1903 printf(" %s\n", _("IP address or name (use numeric address if possible to bypass DNS lookup)."));
1963 printf (" %s\n", "-p, --port=INTEGER"); 1904 printf(" %s\n", "-p, --port=INTEGER");
1964 printf (" %s", _("Port number (default: ")); 1905 printf(" %s", _("Port number (default: "));
1965 printf ("%d)\n", HTTP_PORT); 1906 printf("%d)\n", HTTP_PORT);
1966 1907
1967 printf (UT_IPv46); 1908 printf(UT_IPv46);
1968 1909
1969#ifdef LIBCURL_FEATURE_SSL 1910#ifdef LIBCURL_FEATURE_SSL
1970 printf (" %s\n", "-S, --ssl=VERSION[+]"); 1911 printf(" %s\n", "-S, --ssl=VERSION[+]");
1971 printf (" %s\n", _("Connect via SSL. Port defaults to 443. VERSION is optional, and prevents")); 1912 printf(" %s\n", _("Connect via SSL. Port defaults to 443. VERSION is optional, and prevents"));
1972 printf (" %s\n", _("auto-negotiation (2 = SSLv2, 3 = SSLv3, 1 = TLSv1, 1.1 = TLSv1.1,")); 1913 printf(" %s\n", _("auto-negotiation (2 = SSLv2, 3 = SSLv3, 1 = TLSv1, 1.1 = TLSv1.1,"));
1973 printf (" %s\n", _("1.2 = TLSv1.2, 1.3 = TLSv1.3). With a '+' suffix, newer versions are also accepted.")); 1914 printf(" %s\n", _("1.2 = TLSv1.2, 1.3 = TLSv1.3). With a '+' suffix, newer versions are also accepted."));
1974 printf (" %s\n", _("Note: SSLv2 and SSLv3 are deprecated and are usually disabled in libcurl")); 1915 printf(" %s\n", _("Note: SSLv2 and SSLv3 are deprecated and are usually disabled in libcurl"));
1975 printf (" %s\n", "--sni"); 1916 printf(" %s\n", "--sni");
1976 printf (" %s\n", _("Enable SSL/TLS hostname extension support (SNI)")); 1917 printf(" %s\n", _("Enable SSL/TLS hostname extension support (SNI)"));
1977#if LIBCURL_VERSION_NUM >= 0x071801 1918# if LIBCURL_VERSION_NUM >= 0x071801
1978 printf (" %s\n", _("Note: --sni is the default in libcurl as SSLv2 and SSLV3 are deprecated and")); 1919 printf(" %s\n", _("Note: --sni is the default in libcurl as SSLv2 and SSLV3 are deprecated and"));
1979 printf (" %s\n", _(" SNI only really works since TLSv1.0")); 1920 printf(" %s\n", _(" SNI only really works since TLSv1.0"));
1980#else 1921# else
1981 printf (" %s\n", _("Note: SNI is not supported in libcurl before 7.18.1")); 1922 printf(" %s\n", _("Note: SNI is not supported in libcurl before 7.18.1"));
1982#endif 1923# endif
1983 printf (" %s\n", "-C, --certificate=INTEGER[,INTEGER]"); 1924 printf(" %s\n", "-C, --certificate=INTEGER[,INTEGER]");
1984 printf (" %s\n", _("Minimum number of days a certificate has to be valid. Port defaults to 443")); 1925 printf(" %s\n", _("Minimum number of days a certificate has to be valid. Port defaults to 443."));
1985 printf (" %s\n", _("(when this option is used the URL is not checked by default. You can use")); 1926 printf(" %s\n", _("A STATE_WARNING is returned if the certificate has a validity less than the"));
1986 printf (" %s\n", _(" --continue-after-certificate to override this behavior)")); 1927 printf(" %s\n", _("first agument's value. If there is a second argument and the certificate's"));
1987 printf (" %s\n", "--continue-after-certificate"); 1928 printf(" %s\n", _("validity is less than its value, a STATE_CRITICAL is returned."));
1988 printf (" %s\n", _("Allows the HTTP check to continue after performing the certificate check.")); 1929 printf(" %s\n", _("(When this option is used the URL is not checked by default. You can use"));
1989 printf (" %s\n", _("Does nothing unless -C is used.")); 1930 printf(" %s\n", _(" --continue-after-certificate to override this behavior)"));
1990 printf (" %s\n", "-J, --client-cert=FILE"); 1931 printf(" %s\n", "--continue-after-certificate");
1991 printf (" %s\n", _("Name of file that contains the client certificate (PEM format)")); 1932 printf(" %s\n", _("Allows the HTTP check to continue after performing the certificate check."));
1992 printf (" %s\n", _("to be used in establishing the SSL session")); 1933 printf(" %s\n", _("Does nothing unless -C is used."));
1993 printf (" %s\n", "-K, --private-key=FILE"); 1934 printf(" %s\n", "-J, --client-cert=FILE");
1994 printf (" %s\n", _("Name of file containing the private key (PEM format)")); 1935 printf(" %s\n", _("Name of file that contains the client certificate (PEM format)"));
1995 printf (" %s\n", _("matching the client certificate")); 1936 printf(" %s\n", _("to be used in establishing the SSL session"));
1996 printf (" %s\n", "--ca-cert=FILE"); 1937 printf(" %s\n", "-K, --private-key=FILE");
1997 printf (" %s\n", _("CA certificate file to verify peer against")); 1938 printf(" %s\n", _("Name of file containing the private key (PEM format)"));
1998 printf (" %s\n", "-D, --verify-cert"); 1939 printf(" %s\n", _("matching the client certificate"));
1999 printf (" %s\n", _("Verify the peer's SSL certificate and hostname")); 1940 printf(" %s\n", "--ca-cert=FILE");
1941 printf(" %s\n", _("CA certificate file to verify peer against"));
1942 printf(" %s\n", "-D, --verify-cert");
1943 printf(" %s\n", _("Verify the peer's SSL certificate and hostname"));
2000#endif 1944#endif
2001 1945
2002 printf (" %s\n", "-e, --expect=STRING"); 1946 printf(" %s\n", "-e, --expect=STRING");
2003 printf (" %s\n", _("Comma-delimited list of strings, at least one of them is expected in")); 1947 printf(" %s\n", _("Comma-delimited list of strings, at least one of them is expected in"));
2004 printf (" %s", _("the first (status) line of the server response (default: ")); 1948 printf(" %s", _("the first (status) line of the server response (default: "));
2005 printf ("%s)\n", HTTP_EXPECT); 1949 printf("%s)\n", HTTP_EXPECT);
2006 printf (" %s\n", _("If specified skips all other status line logic (ex: 3xx, 4xx, 5xx processing)")); 1950 printf(" %s\n", _("If specified skips all other status line logic (ex: 3xx, 4xx, 5xx processing)"));
2007 printf (" %s\n", "-d, --header-string=STRING"); 1951 printf(" %s\n", "-d, --header-string=STRING");
2008 printf (" %s\n", _("String to expect in the response headers")); 1952 printf(" %s\n", _("String to expect in the response headers"));
2009 printf (" %s\n", "-s, --string=STRING"); 1953 printf(" %s\n", "-s, --string=STRING");
2010 printf (" %s\n", _("String to expect in the content")); 1954 printf(" %s\n", _("String to expect in the content"));
2011 printf (" %s\n", "-u, --url=PATH"); 1955 printf(" %s\n", "-u, --url=PATH");
2012 printf (" %s\n", _("URL to GET or POST (default: /)")); 1956 printf(" %s\n", _("URL to GET or POST (default: /)"));
2013 printf (" %s\n", "-P, --post=STRING"); 1957 printf(" %s\n", "-P, --post=STRING");
2014 printf (" %s\n", _("URL encoded http POST data")); 1958 printf(" %s\n", _("URL decoded http POST data"));
2015 printf (" %s\n", "-j, --method=STRING (for example: HEAD, OPTIONS, TRACE, PUT, DELETE, CONNECT)"); 1959 printf(" %s\n", "-j, --method=STRING (for example: HEAD, OPTIONS, TRACE, PUT, DELETE, CONNECT)");
2016 printf (" %s\n", _("Set HTTP method.")); 1960 printf(" %s\n", _("Set HTTP method."));
2017 printf (" %s\n", "-N, --no-body"); 1961 printf(" %s\n", "-N, --no-body");
2018 printf (" %s\n", _("Don't wait for document body: stop reading after headers.")); 1962 printf(" %s\n", _("Don't wait for document body: stop reading after headers."));
2019 printf (" %s\n", _("(Note that this still does an HTTP GET or POST, not a HEAD.)")); 1963 printf(" %s\n", _("(Note that this still does an HTTP GET or POST, not a HEAD.)"));
2020 printf (" %s\n", "-M, --max-age=SECONDS"); 1964 printf(" %s\n", "-M, --max-age=SECONDS");
2021 printf (" %s\n", _("Warn if document is more than SECONDS old. the number can also be of")); 1965 printf(" %s\n", _("Warn if document is more than SECONDS old. the number can also be of"));
2022 printf (" %s\n", _("the form \"10m\" for minutes, \"10h\" for hours, or \"10d\" for days.")); 1966 printf(" %s\n", _("the form \"10m\" for minutes, \"10h\" for hours, or \"10d\" for days."));
2023 printf (" %s\n", "-T, --content-type=STRING"); 1967 printf(" %s\n", "-T, --content-type=STRING");
2024 printf (" %s\n", _("specify Content-Type header media type when POSTing\n")); 1968 printf(" %s\n", _("specify Content-Type header media type when POSTing\n"));
2025 printf (" %s\n", "-l, --linespan"); 1969 printf(" %s\n", "-l, --linespan");
2026 printf (" %s\n", _("Allow regex to span newlines (must precede -r or -R)")); 1970 printf(" %s\n", _("Allow regex to span newlines (must precede -r or -R)"));
2027 printf (" %s\n", "-r, --regex, --ereg=STRING"); 1971 printf(" %s\n", "-r, --regex, --ereg=STRING");
2028 printf (" %s\n", _("Search page for regex STRING")); 1972 printf(" %s\n", _("Search page for regex STRING"));
2029 printf (" %s\n", "-R, --eregi=STRING"); 1973 printf(" %s\n", "-R, --eregi=STRING");
2030 printf (" %s\n", _("Search page for case-insensitive regex STRING")); 1974 printf(" %s\n", _("Search page for case-insensitive regex STRING"));
2031 printf (" %s\n", "--invert-regex"); 1975 printf(" %s\n", "--invert-regex");
2032 printf (" %s\n", _("Return CRITICAL if found, OK if not\n")); 1976 printf(" %s\n", _("Return STATE if found, OK if not (STATE is CRITICAL, per default)"));
2033 printf (" %s\n", "-a, --authorization=AUTH_PAIR"); 1977 printf(" %s\n", _("can be changed with --state--regex)"));
2034 printf (" %s\n", _("Username:password on sites with basic authentication")); 1978 printf(" %s\n", "--state-regex=STATE");
2035 printf (" %s\n", "-b, --proxy-authorization=AUTH_PAIR"); 1979 printf(" %s\n", _("Return STATE if regex is found, OK if not. STATE can be one of \"critical\",\"warning\""));
2036 printf (" %s\n", _("Username:password on proxy-servers with basic authentication")); 1980 printf(" %s\n", "-a, --authorization=AUTH_PAIR");
2037 printf (" %s\n", "-A, --useragent=STRING"); 1981 printf(" %s\n", _("Username:password on sites with basic authentication"));
2038 printf (" %s\n", _("String to be sent in http header as \"User Agent\"")); 1982 printf(" %s\n", "-b, --proxy-authorization=AUTH_PAIR");
2039 printf (" %s\n", "-k, --header=STRING"); 1983 printf(" %s\n", _("Username:password on proxy-servers with basic authentication"));
2040 printf (" %s\n", _("Any other tags to be sent in http header. Use multiple times for additional headers")); 1984 printf(" %s\n", "-A, --useragent=STRING");
2041 printf (" %s\n", "-E, --extended-perfdata"); 1985 printf(" %s\n", _("String to be sent in http header as \"User Agent\""));
2042 printf (" %s\n", _("Print additional performance data")); 1986 printf(" %s\n", "-k, --header=STRING");
2043 printf (" %s\n", "-B, --show-body"); 1987 printf(" %s\n", _("Any other tags to be sent in http header. Use multiple times for additional headers"));
2044 printf (" %s\n", _("Print body content below status line")); 1988 printf(" %s\n", "-E, --extended-perfdata");
2045 printf (" %s\n", "-L, --link"); 1989 printf(" %s\n", _("Print additional performance data"));
2046 printf (" %s\n", _("Wrap output in HTML link (obsoleted by urlize)")); 1990 printf(" %s\n", "-B, --show-body");
2047 printf (" %s\n", "-f, --onredirect=<ok|warning|critical|follow|sticky|stickyport|curl>"); 1991 printf(" %s\n", _("Print body content below status line"));
2048 printf (" %s\n", _("How to handle redirected pages. sticky is like follow but stick to the")); 1992 printf(" %s\n", "-L, --link");
2049 printf (" %s\n", _("specified IP address. stickyport also ensures port stays the same.")); 1993 printf(" %s\n", _("Wrap output in HTML link (obsoleted by urlize)"));
2050 printf (" %s\n", _("follow uses the old redirection algorithm of check_http.")); 1994 printf(" %s\n", "-f, --onredirect=<ok|warning|critical|follow|sticky|stickyport|curl>");
2051 printf (" %s\n", _("curl uses CURL_FOLLOWLOCATION built into libcurl.")); 1995 printf(" %s\n", _("How to handle redirected pages. sticky is like follow but stick to the"));
2052 printf (" %s\n", "--max-redirs=INTEGER"); 1996 printf(" %s\n", _("specified IP address. stickyport also ensures port stays the same."));
2053 printf (" %s", _("Maximal number of redirects (default: ")); 1997 printf(" %s\n", _("follow uses the old redirection algorithm of check_http."));
2054 printf ("%d)\n", DEFAULT_MAX_REDIRS); 1998 printf(" %s\n", _("curl uses CURL_FOLLOWLOCATION built into libcurl."));
2055 printf (" %s\n", "-m, --pagesize=INTEGER<:INTEGER>"); 1999 printf(" %s\n", "--max-redirs=INTEGER");
2056 printf (" %s\n", _("Minimum page size required (bytes) : Maximum page size required (bytes)")); 2000 printf(" %s", _("Maximal number of redirects (default: "));
2057 printf ("\n"); 2001 printf("%d)\n", DEFAULT_MAX_REDIRS);
2058 printf (" %s\n", "--http-version=VERSION"); 2002 printf(" %s\n", "-m, --pagesize=INTEGER<:INTEGER>");
2059 printf (" %s\n", _("Connect via specific HTTP protocol.")); 2003 printf(" %s\n", _("Minimum page size required (bytes) : Maximum page size required (bytes)"));
2060 printf (" %s\n", _("1.0 = HTTP/1.0, 1.1 = HTTP/1.1, 2.0 = HTTP/2 (HTTP/2 will fail without -S)")); 2004 printf("\n");
2061 printf (" %s\n", "--enable-automatic-decompression"); 2005 printf(" %s\n", "--http-version=VERSION");
2062 printf (" %s\n", _("Enable automatic decompression of body (CURLOPT_ACCEPT_ENCODING).")); 2006 printf(" %s\n", _("Connect via specific HTTP protocol."));
2063 printf (" %s\n", "---cookie-jar=FILE"); 2007 printf(" %s\n", _("1.0 = HTTP/1.0, 1.1 = HTTP/1.1, 2.0 = HTTP/2 (HTTP/2 will fail without -S)"));
2064 printf (" %s\n", _("Store cookies in the cookie jar and send them out when requested.")); 2008 printf(" %s\n", "--enable-automatic-decompression");
2065 printf ("\n"); 2009 printf(" %s\n", _("Enable automatic decompression of body (CURLOPT_ACCEPT_ENCODING)."));
2066 2010 printf(" %s\n", "--haproxy-protocol");
2067 printf (UT_WARN_CRIT); 2011 printf(" %s\n", _("Send HAProxy proxy protocol v1 header (CURLOPT_HAPROXYPROTOCOL)."));
2068 2012 printf(" %s\n", "--cookie-jar=FILE");
2069 printf (UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); 2013 printf(" %s\n", _("Store cookies in the cookie jar and send them out when requested."));
2070 2014 printf("\n");
2071 printf (UT_VERBOSE); 2015
2072 2016 printf(UT_WARN_CRIT);
2073 printf ("\n"); 2017
2074 printf ("%s\n", _("Notes:")); 2018 printf(UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
2075 printf (" %s\n", _("This plugin will attempt to open an HTTP connection with the host.")); 2019
2076 printf (" %s\n", _("Successful connects return STATE_OK, refusals and timeouts return STATE_CRITICAL")); 2020 printf(UT_VERBOSE);
2077 printf (" %s\n", _("other errors return STATE_UNKNOWN. Successful connects, but incorrect response")); 2021
2078 printf (" %s\n", _("messages from the host result in STATE_WARNING return values. If you are")); 2022 printf("\n");
2079 printf (" %s\n", _("checking a virtual server that uses 'host headers' you must supply the FQDN")); 2023 printf("%s\n", _("Notes:"));
2080 printf (" %s\n", _("(fully qualified domain name) as the [host_name] argument.")); 2024 printf(" %s\n", _("This plugin will attempt to open an HTTP connection with the host."));
2025 printf(" %s\n", _("Successful connects return STATE_OK, refusals and timeouts return STATE_CRITICAL"));
2026 printf(" %s\n", _("other errors return STATE_UNKNOWN. Successful connects, but incorrect response"));
2027 printf(" %s\n", _("messages from the host result in STATE_WARNING return values. If you are"));
2028 printf(" %s\n", _("checking a virtual server that uses 'host headers' you must supply the FQDN"));
2029 printf(" %s\n", _("(fully qualified domain name) as the [host_name] argument."));
2081 2030
2082#ifdef LIBCURL_FEATURE_SSL 2031#ifdef LIBCURL_FEATURE_SSL
2083 printf ("\n"); 2032 printf("\n");
2084 printf (" %s\n", _("This plugin can also check whether an SSL enabled web server is able to")); 2033 printf(" %s\n", _("This plugin can also check whether an SSL enabled web server is able to"));
2085 printf (" %s\n", _("serve content (optionally within a specified time) or whether the X509 ")); 2034 printf(" %s\n", _("serve content (optionally within a specified time) or whether the X509 "));
2086 printf (" %s\n", _("certificate is still valid for the specified number of days.")); 2035 printf(" %s\n", _("certificate is still valid for the specified number of days."));
2087 printf ("\n"); 2036 printf("\n");
2088 printf (" %s\n", _("Please note that this plugin does not check if the presented server")); 2037 printf(" %s\n", _("Please note that this plugin does not check if the presented server"));
2089 printf (" %s\n", _("certificate matches the hostname of the server, or if the certificate")); 2038 printf(" %s\n", _("certificate matches the hostname of the server, or if the certificate"));
2090 printf (" %s\n", _("has a valid chain of trust to one of the locally installed CAs.")); 2039 printf(" %s\n", _("has a valid chain of trust to one of the locally installed CAs."));
2091 printf ("\n"); 2040 printf("\n");
2092 printf ("%s\n", _("Examples:")); 2041 printf("%s\n", _("Examples:"));
2093 printf (" %s\n\n", "CHECK CONTENT: check_curl -w 5 -c 10 --ssl -H www.verisign.com"); 2042 printf(" %s\n\n", "CHECK CONTENT: check_curl -w 5 -c 10 --ssl -H www.verisign.com");
2094 printf (" %s\n", _("When the 'www.verisign.com' server returns its content within 5 seconds,")); 2043 printf(" %s\n", _("When the 'www.verisign.com' server returns its content within 5 seconds,"));
2095 printf (" %s\n", _("a STATE_OK will be returned. When the server returns its content but exceeds")); 2044 printf(" %s\n", _("a STATE_OK will be returned. When the server returns its content but exceeds"));
2096 printf (" %s\n", _("the 5-second threshold, a STATE_WARNING will be returned. When an error occurs,")); 2045 printf(" %s\n", _("the 5-second threshold, a STATE_WARNING will be returned. When an error occurs,"));
2097 printf (" %s\n", _("a STATE_CRITICAL will be returned.")); 2046 printf(" %s\n", _("a STATE_CRITICAL will be returned."));
2098 printf ("\n"); 2047 printf("\n");
2099 printf (" %s\n\n", "CHECK CERTIFICATE: check_curl -H www.verisign.com -C 14"); 2048 printf(" %s\n\n", "CHECK CERTIFICATE: check_curl -H www.verisign.com -C 14");
2100 printf (" %s\n", _("When the certificate of 'www.verisign.com' is valid for more than 14 days,")); 2049 printf(" %s\n", _("When the certificate of 'www.verisign.com' is valid for more than 14 days,"));
2101 printf (" %s\n", _("a STATE_OK is returned. When the certificate is still valid, but for less than")); 2050 printf(" %s\n", _("a STATE_OK is returned. When the certificate is still valid, but for less than"));
2102 printf (" %s\n", _("14 days, a STATE_WARNING is returned. A STATE_CRITICAL will be returned when")); 2051 printf(" %s\n", _("14 days, a STATE_WARNING is returned. A STATE_CRITICAL will be returned when"));
2103 printf (" %s\n\n", _("the certificate is expired.")); 2052 printf(" %s\n\n", _("the certificate is expired."));
2104 printf ("\n"); 2053 printf("\n");
2105 printf (" %s\n\n", "CHECK CERTIFICATE: check_curl -H www.verisign.com -C 30,14"); 2054 printf(" %s\n\n", "CHECK CERTIFICATE: check_curl -H www.verisign.com -C 30,14");
2106 printf (" %s\n", _("When the certificate of 'www.verisign.com' is valid for more than 30 days,")); 2055 printf(" %s\n", _("When the certificate of 'www.verisign.com' is valid for more than 30 days,"));
2107 printf (" %s\n", _("a STATE_OK is returned. When the certificate is still valid, but for less than")); 2056 printf(" %s\n", _("a STATE_OK is returned. When the certificate is still valid, but for less than"));
2108 printf (" %s\n", _("30 days, but more than 14 days, a STATE_WARNING is returned.")); 2057 printf(" %s\n", _("30 days, but more than 14 days, a STATE_WARNING is returned."));
2109 printf (" %s\n", _("A STATE_CRITICAL will be returned when certificate expires in less than 14 days")); 2058 printf(" %s\n", _("A STATE_CRITICAL will be returned when certificate expires in less than 14 days"));
2110#endif 2059#endif
2111 2060
2112 printf ("\n %s\n", "CHECK WEBSERVER CONTENT VIA PROXY:"); 2061 printf("\n %s\n", "CHECK WEBSERVER CONTENT VIA PROXY:");
2113 printf (" %s\n", _("It is recommended to use an environment proxy like:")); 2062 printf(" %s\n", _("It is recommended to use an environment proxy like:"));
2114 printf (" %s\n", _("http_proxy=http://192.168.100.35:3128 ./check_curl -H www.monitoring-plugins.org")); 2063 printf(" %s\n", _("http_proxy=http://192.168.100.35:3128 ./check_curl -H www.monitoring-plugins.org"));
2115 printf (" %s\n", _("legacy proxy requests in check_http style still work:")); 2064 printf(" %s\n", _("legacy proxy requests in check_http style still work:"));
2116 printf (" %s\n", _("check_curl -I 192.168.100.35 -p 3128 -u http://www.monitoring-plugins.org/ -H www.monitoring-plugins.org")); 2065 printf(" %s\n", _("check_curl -I 192.168.100.35 -p 3128 -u http://www.monitoring-plugins.org/ -H www.monitoring-plugins.org"));
2117 2066
2118#ifdef LIBCURL_FEATURE_SSL 2067#ifdef LIBCURL_FEATURE_SSL
2119 printf ("\n %s\n", "CHECK SSL WEBSERVER CONTENT VIA PROXY USING HTTP 1.1 CONNECT: "); 2068 printf("\n %s\n", "CHECK SSL WEBSERVER CONTENT VIA PROXY USING HTTP 1.1 CONNECT: ");
2120 printf (" %s\n", _("It is recommended to use an environment proxy like:")); 2069 printf(" %s\n", _("It is recommended to use an environment proxy like:"));
2121 printf (" %s\n", _("https_proxy=http://192.168.100.35:3128 ./check_curl -H www.verisign.com -S")); 2070 printf(" %s\n", _("https_proxy=http://192.168.100.35:3128 ./check_curl -H www.verisign.com -S"));
2122 printf (" %s\n", _("legacy proxy requests in check_http style still work:")); 2071 printf(" %s\n", _("legacy proxy requests in check_http style still work:"));
2123 printf (" %s\n", _("check_curl -I 192.168.100.35 -p 3128 -u https://www.verisign.com/ -S -j CONNECT -H www.verisign.com ")); 2072 printf(" %s\n", _("check_curl -I 192.168.100.35 -p 3128 -u https://www.verisign.com/ -S -j CONNECT -H www.verisign.com "));
2124 printf (" %s\n", _("all these options are needed: -I <proxy> -p <proxy-port> -u <check-url> -S(sl) -j CONNECT -H <webserver>")); 2073 printf(" %s\n", _("all these options are needed: -I <proxy> -p <proxy-port> -u <check-url> -S(sl) -j CONNECT -H <webserver>"));
2125 printf (" %s\n", _("a STATE_OK will be returned. When the server returns its content but exceeds")); 2074 printf(" %s\n", _("a STATE_OK will be returned. When the server returns its content but exceeds"));
2126 printf (" %s\n", _("the 5-second threshold, a STATE_WARNING will be returned. When an error occurs,")); 2075 printf(" %s\n", _("the 5-second threshold, a STATE_WARNING will be returned. When an error occurs,"));
2127 printf (" %s\n", _("a STATE_CRITICAL will be returned.")); 2076 printf(" %s\n", _("a STATE_CRITICAL will be returned."));
2128 2077
2129#endif 2078#endif
2130 2079
2131 printf (UT_SUPPORT); 2080 printf(UT_SUPPORT);
2132
2133} 2081}
2134 2082
2135 2083void print_usage(void) {
2136 2084 printf("%s\n", _("Usage:"));
2137void 2085 printf(" %s -H <vhost> | -I <IP-address> [-u <uri>] [-p <port>]\n", progname);
2138print_usage (void) 2086 printf(" [-J <client certificate file>] [-K <private key>] [--ca-cert <CA certificate file>] [-D]\n");
2139{ 2087 printf(" [-w <warn time>] [-c <critical time>] [-t <timeout>] [-L] [-E] [-a auth]\n");
2140 printf ("%s\n", _("Usage:")); 2088 printf(" [-b proxy_auth] [-f <ok|warning|critical|follow|sticky|stickyport|curl>]\n");
2141 printf (" %s -H <vhost> | -I <IP-address> [-u <uri>] [-p <port>]\n",progname); 2089 printf(" [-e <expect>] [-d string] [-s string] [-l] [-r <regex> | -R <case-insensitive regex>]\n");
2142 printf (" [-J <client certificate file>] [-K <private key>] [--ca-cert <CA certificate file>] [-D]\n"); 2090 printf(" [-P string] [-m <min_pg_size>:<max_pg_size>] [-4|-6] [-N] [-M <age>]\n");
2143 printf (" [-w <warn time>] [-c <critical time>] [-t <timeout>] [-L] [-E] [-a auth]\n"); 2091 printf(" [-A string] [-k string] [-S <version>] [--sni] [--haproxy-protocol]\n");
2144 printf (" [-b proxy_auth] [-f <ok|warning|critical|follow|sticky|stickyport|curl>]\n"); 2092 printf(" [-T <content-type>] [-j method]\n");
2145 printf (" [-e <expect>] [-d string] [-s string] [-l] [-r <regex> | -R <case-insensitive regex>]\n"); 2093 printf(" [--http-version=<version>] [--enable-automatic-decompression]\n");
2146 printf (" [-P string] [-m <min_pg_size>:<max_pg_size>] [-4|-6] [-N] [-M <age>]\n"); 2094 printf(" [--cookie-jar=<cookie jar file>\n");
2147 printf (" [-A string] [-k string] [-S <version>] [--sni]\n"); 2095 printf(" %s -H <vhost> | -I <IP-address> -C <warn_age>[,<crit_age>]\n", progname);
2148 printf (" [-T <content-type>] [-j method]\n"); 2096 printf(" [-p <port>] [-t <timeout>] [-4|-6] [--sni]\n");
2149 printf (" [--http-version=<version>] [--enable-automatic-decompression]\n"); 2097 printf("\n");
2150 printf (" [--cookie-jar=<cookie jar file>\n");
2151 printf (" %s -H <vhost> | -I <IP-address> -C <warn_age>[,<crit_age>]\n",progname);
2152 printf (" [-p <port>] [-t <timeout>] [-4|-6] [--sni]\n");
2153 printf ("\n");
2154#ifdef LIBCURL_FEATURE_SSL 2098#ifdef LIBCURL_FEATURE_SSL
2155 printf ("%s\n", _("In the first form, make an HTTP request.")); 2099 printf("%s\n", _("In the first form, make an HTTP request."));
2156 printf ("%s\n\n", _("In the second form, connect to the server and check the TLS certificate.")); 2100 printf("%s\n\n", _("In the second form, connect to the server and check the TLS certificate."));
2157#endif 2101#endif
2158 printf ("%s\n", _("WARNING: check_curl is experimental. Please use"));
2159 printf ("%s\n\n", _("check_http if you need a stable version."));
2160} 2102}
2161 2103
2162void 2104void print_curl_version(void) { printf("%s\n", curl_version()); }
2163print_curl_version (void)
2164{
2165 printf( "%s\n", curl_version());
2166}
2167 2105
2168int 2106int curlhelp_initwritebuffer(curlhelp_write_curlbuf *buf) {
2169curlhelp_initwritebuffer (curlhelp_write_curlbuf *buf) 2107 buf->bufsize = DEFAULT_BUFFER_SIZE;
2170{ 2108 buf->buflen = 0;
2171 buf->bufsize = DEFAULT_BUFFER_SIZE; 2109 buf->buf = (char *)malloc((size_t)buf->bufsize);
2172 buf->buflen = 0; 2110 if (buf->buf == NULL)
2173 buf->buf = (char *)malloc ((size_t)buf->bufsize); 2111 return -1;
2174 if (buf->buf == NULL) return -1; 2112 return 0;
2175 return 0;
2176} 2113}
2177 2114
2178size_t curlhelp_buffer_write_callback (void *buffer, size_t size, size_t nmemb, void *stream) 2115size_t curlhelp_buffer_write_callback(void *buffer, size_t size, size_t nmemb, void *stream) {
2179{ 2116 curlhelp_write_curlbuf *buf = (curlhelp_write_curlbuf *)stream;
2180 curlhelp_write_curlbuf *buf = (curlhelp_write_curlbuf *)stream;
2181 2117
2182 while (buf->bufsize < buf->buflen + size * nmemb + 1) { 2118 while (buf->bufsize < buf->buflen + size * nmemb + 1) {
2183 buf->bufsize = buf->bufsize * 2; 2119 buf->bufsize = buf->bufsize * 2;
2184 buf->buf = (char *)realloc (buf->buf, buf->bufsize); 2120 buf->buf = (char *)realloc(buf->buf, buf->bufsize);
2185 if (buf->buf == NULL) { 2121 if (buf->buf == NULL) {
2186 fprintf(stderr, "malloc failed (%d) %s\n", errno, strerror(errno)); 2122 fprintf(stderr, "malloc failed (%d) %s\n", errno, strerror(errno));
2187 return -1; 2123 return -1;
2188 } 2124 }
2189 } 2125 }
2190 2126
2191 memcpy (buf->buf + buf->buflen, buffer, size * nmemb); 2127 memcpy(buf->buf + buf->buflen, buffer, size * nmemb);
2192 buf->buflen += size * nmemb; 2128 buf->buflen += size * nmemb;
2193 buf->buf[buf->buflen] = '\0'; 2129 buf->buf[buf->buflen] = '\0';
2194 2130
2195 return (int)(size * nmemb); 2131 return (int)(size * nmemb);
2196} 2132}
2197 2133
2198size_t curlhelp_buffer_read_callback(void *buffer, size_t size, size_t nmemb, void *stream) 2134size_t curlhelp_buffer_read_callback(void *buffer, size_t size, size_t nmemb, void *stream) {
2199{ 2135 curlhelp_read_curlbuf *buf = (curlhelp_read_curlbuf *)stream;
2200 curlhelp_read_curlbuf *buf = (curlhelp_read_curlbuf *)stream;
2201 2136
2202 size_t n = min (nmemb * size, buf->buflen - buf->pos); 2137 size_t n = min(nmemb * size, buf->buflen - buf->pos);
2203 2138
2204 memcpy (buffer, buf->buf + buf->pos, n); 2139 memcpy(buffer, buf->buf + buf->pos, n);
2205 buf->pos += n; 2140 buf->pos += n;
2206 2141
2207 return (int)n; 2142 return (int)n;
2208} 2143}
2209 2144
2210void 2145void curlhelp_freewritebuffer(curlhelp_write_curlbuf *buf) {
2211curlhelp_freewritebuffer (curlhelp_write_curlbuf *buf) 2146 free(buf->buf);
2212{ 2147 buf->buf = NULL;
2213 free (buf->buf);
2214 buf->buf = NULL;
2215} 2148}
2216 2149
2217int 2150int curlhelp_initreadbuffer(curlhelp_read_curlbuf *buf, const char *data, size_t datalen) {
2218curlhelp_initreadbuffer (curlhelp_read_curlbuf *buf, const char *data, size_t datalen) 2151 buf->buflen = datalen;
2219{ 2152 buf->buf = (char *)malloc((size_t)buf->buflen);
2220 buf->buflen = datalen; 2153 if (buf->buf == NULL)
2221 buf->buf = (char *)malloc ((size_t)buf->buflen); 2154 return -1;
2222 if (buf->buf == NULL) return -1; 2155 memcpy(buf->buf, data, datalen);
2223 memcpy (buf->buf, data, datalen); 2156 buf->pos = 0;
2224 buf->pos = 0; 2157 return 0;
2225 return 0;
2226} 2158}
2227 2159
2228void 2160void curlhelp_freereadbuffer(curlhelp_read_curlbuf *buf) {
2229curlhelp_freereadbuffer (curlhelp_read_curlbuf *buf) 2161 free(buf->buf);
2230{ 2162 buf->buf = NULL;
2231 free (buf->buf);
2232 buf->buf = NULL;
2233} 2163}
2234 2164
2235/* TODO: where to put this, it's actually part of sstrings2 (logically)? 2165/* TODO: where to put this, it's actually part of sstrings2 (logically)?
2236 */ 2166 */
2237const char* 2167const char *strrstr2(const char *haystack, const char *needle) {
2238strrstr2(const char *haystack, const char *needle) 2168 int counter;
2239{ 2169 size_t len;
2240 int counter; 2170 const char *prev_pos;
2241 size_t len; 2171 const char *pos;
2242 const char *prev_pos; 2172
2243 const char *pos; 2173 if (haystack == NULL || needle == NULL)
2244 2174 return NULL;
2245 if (haystack == NULL || needle == NULL) 2175
2246 return NULL; 2176 if (haystack[0] == '\0' || needle[0] == '\0')
2247 2177 return NULL;
2248 if (haystack[0] == '\0' || needle[0] == '\0') 2178
2249 return NULL; 2179 counter = 0;
2250 2180 prev_pos = NULL;
2251 counter = 0; 2181 pos = haystack;
2252 prev_pos = NULL; 2182 len = strlen(needle);
2253 pos = haystack; 2183 for (;;) {
2254 len = strlen (needle); 2184 pos = strstr(pos, needle);
2255 for (;;) { 2185 if (pos == NULL) {
2256 pos = strstr (pos, needle); 2186 if (counter == 0)
2257 if (pos == NULL) { 2187 return NULL;
2258 if (counter == 0) 2188 return prev_pos;
2259 return NULL; 2189 }
2260 else 2190 counter++;
2261 return prev_pos; 2191 prev_pos = pos;
2262 } 2192 pos += len;
2263 counter++; 2193 if (*pos == '\0')
2264 prev_pos = pos; 2194 return prev_pos;
2265 pos += len; 2195 }
2266 if (*pos == '\0') return prev_pos;
2267 }
2268} 2196}
2269 2197
2270int 2198int curlhelp_parse_statusline(const char *buf, curlhelp_statusline *status_line) {
2271curlhelp_parse_statusline (const char *buf, curlhelp_statusline *status_line) 2199 char *first_line_end;
2272{ 2200 char *p;
2273 char *first_line_end; 2201 size_t first_line_len;
2274 char *p; 2202 char *pp;
2275 size_t first_line_len; 2203 const char *start;
2276 char *pp; 2204 char *first_line_buf;
2277 const char *start; 2205
2278 char *first_line_buf; 2206 /* find last start of a new header */
2279 2207 start = strrstr2(buf, "\r\nHTTP/");
2280 /* find last start of a new header */ 2208 if (start != NULL) {
2281 start = strrstr2 (buf, "\r\nHTTP/"); 2209 start += 2;
2282 if (start != NULL) { 2210 buf = start;
2283 start += 2; 2211 }
2284 buf = start;
2285 }
2286
2287 first_line_end = strstr(buf, "\r\n");
2288 if (first_line_end == NULL) return -1;
2289
2290 first_line_len = (size_t)(first_line_end - buf);
2291 status_line->first_line = (char *)malloc (first_line_len + 1);
2292 if (status_line->first_line == NULL) return -1;
2293 memcpy (status_line->first_line, buf, first_line_len);
2294 status_line->first_line[first_line_len] = '\0';
2295 first_line_buf = strdup( status_line->first_line );
2296
2297 /* protocol and version: "HTTP/x.x" SP or "HTTP/2" SP */
2298
2299 p = strtok(first_line_buf, "/");
2300 if( p == NULL ) { free( first_line_buf ); return -1; }
2301 if( strcmp( p, "HTTP" ) != 0 ) { free( first_line_buf ); return -1; }
2302
2303 p = strtok( NULL, " " );
2304 if( p == NULL ) { free( first_line_buf ); return -1; }
2305 if( strchr( p, '.' ) != NULL ) {
2306
2307 /* HTTP 1.x case */
2308 strtok( p, "." );
2309 status_line->http_major = (int)strtol( p, &pp, 10 );
2310 if( *pp != '\0' ) { free( first_line_buf ); return -1; }
2311 strtok( NULL, " " );
2312 status_line->http_minor = (int)strtol( p, &pp, 10 );
2313 if( *pp != '\0' ) { free( first_line_buf ); return -1; }
2314 p += 4; /* 1.x SP */
2315 } else {
2316 /* HTTP 2 case */
2317 status_line->http_major = (int)strtol( p, &pp, 10 );
2318 status_line->http_minor = 0;
2319 p += 2; /* 2 SP */
2320 }
2321
2322 /* status code: "404" or "404.1", then SP */
2323
2324 p = strtok( p, " " );
2325 if( p == NULL ) { free( first_line_buf ); return -1; }
2326 if( strchr( p, '.' ) != NULL ) {
2327 char *ppp;
2328 ppp = strtok( p, "." );
2329 status_line->http_code = (int)strtol( ppp, &pp, 10 );
2330 if( *pp != '\0' ) { free( first_line_buf ); return -1; }
2331 ppp = strtok( NULL, "" );
2332 status_line->http_subcode = (int)strtol( ppp, &pp, 10 );
2333 if( *pp != '\0' ) { free( first_line_buf ); return -1; }
2334 p += 6; /* 400.1 SP */
2335 } else {
2336 status_line->http_code = (int)strtol( p, &pp, 10 );
2337 status_line->http_subcode = -1;
2338 if( *pp != '\0' ) { free( first_line_buf ); return -1; }
2339 p += 4; /* 400 SP */
2340 }
2341
2342 /* Human readable message: "Not Found" CRLF */
2343
2344 p = strtok( p, "" );
2345 if( p == NULL ) { status_line->msg = ""; return 0; }
2346 status_line->msg = status_line->first_line + ( p - first_line_buf );
2347 free( first_line_buf );
2348
2349 return 0;
2350}
2351 2212
2352void 2213 first_line_end = strstr(buf, "\r\n");
2353curlhelp_free_statusline (curlhelp_statusline *status_line) 2214 if (first_line_end == NULL)
2354{ 2215 return -1;
2355 free (status_line->first_line); 2216
2356} 2217 first_line_len = (size_t)(first_line_end - buf);
2218 status_line->first_line = (char *)malloc(first_line_len + 1);
2219 if (status_line->first_line == NULL)
2220 return -1;
2221 memcpy(status_line->first_line, buf, first_line_len);
2222 status_line->first_line[first_line_len] = '\0';
2223 first_line_buf = strdup(status_line->first_line);
2224
2225 /* protocol and version: "HTTP/x.x" SP or "HTTP/2" SP */
2226
2227 p = strtok(first_line_buf, "/");
2228 if (p == NULL) {
2229 free(first_line_buf);
2230 return -1;
2231 }
2232 if (strcmp(p, "HTTP") != 0) {
2233 free(first_line_buf);
2234 return -1;
2235 }
2236
2237 p = strtok(NULL, " ");
2238 if (p == NULL) {
2239 free(first_line_buf);
2240 return -1;
2241 }
2242 if (strchr(p, '.') != NULL) {
2243
2244 /* HTTP 1.x case */
2245 strtok(p, ".");
2246 status_line->http_major = (int)strtol(p, &pp, 10);
2247 if (*pp != '\0') {
2248 free(first_line_buf);
2249 return -1;
2250 }
2251 strtok(NULL, " ");
2252 status_line->http_minor = (int)strtol(p, &pp, 10);
2253 if (*pp != '\0') {
2254 free(first_line_buf);
2255 return -1;
2256 }
2257 p += 4; /* 1.x SP */
2258 } else {
2259 /* HTTP 2 case */
2260 status_line->http_major = (int)strtol(p, &pp, 10);
2261 status_line->http_minor = 0;
2262 p += 2; /* 2 SP */
2263 }
2357 2264
2358void 2265 /* status code: "404" or "404.1", then SP */
2359remove_newlines (char *s)
2360{
2361 char *p;
2362 2266
2363 for (p = s; *p != '\0'; p++) 2267 p = strtok(p, " ");
2364 if (*p == '\r' || *p == '\n') 2268 if (p == NULL) {
2365 *p = ' '; 2269 free(first_line_buf);
2270 return -1;
2271 }
2272 if (strchr(p, '.') != NULL) {
2273 char *ppp;
2274 ppp = strtok(p, ".");
2275 status_line->http_code = (int)strtol(ppp, &pp, 10);
2276 if (*pp != '\0') {
2277 free(first_line_buf);
2278 return -1;
2279 }
2280 ppp = strtok(NULL, "");
2281 status_line->http_subcode = (int)strtol(ppp, &pp, 10);
2282 if (*pp != '\0') {
2283 free(first_line_buf);
2284 return -1;
2285 }
2286 p += 6; /* 400.1 SP */
2287 } else {
2288 status_line->http_code = (int)strtol(p, &pp, 10);
2289 status_line->http_subcode = -1;
2290 if (*pp != '\0') {
2291 free(first_line_buf);
2292 return -1;
2293 }
2294 p += 4; /* 400 SP */
2295 }
2296
2297 /* Human readable message: "Not Found" CRLF */
2298
2299 p = strtok(p, "");
2300 if (p == NULL) {
2301 status_line->msg = "";
2302 return 0;
2303 }
2304 status_line->msg = status_line->first_line + (p - first_line_buf);
2305 free(first_line_buf);
2306
2307 return 0;
2366} 2308}
2367 2309
2368char * 2310void curlhelp_free_statusline(curlhelp_statusline *status_line) { free(status_line->first_line); }
2369get_header_value (const struct phr_header* headers, const size_t nof_headers, const char* header) 2311
2370{ 2312char *get_header_value(const struct phr_header *headers, const size_t nof_headers, const char *header) {
2371 for(size_t i = 0; i < nof_headers; i++ ) { 2313 for (size_t i = 0; i < nof_headers; i++) {
2372 if(headers[i].name != NULL && strncasecmp( header, headers[i].name, max( headers[i].name_len, 4 ) ) == 0 ) { 2314 if (headers[i].name != NULL && strncasecmp(header, headers[i].name, max(headers[i].name_len, 4)) == 0) {
2373 return strndup( headers[i].value, headers[i].value_len ); 2315 return strndup(headers[i].value, headers[i].value_len);
2374 } 2316 }
2375 } 2317 }
2376 return NULL; 2318 return NULL;
2377} 2319}
2378 2320
2379int 2321int check_document_dates(const curlhelp_write_curlbuf *header_buf, char (*msg)[DEFAULT_BUFFER_SIZE]) {
2380check_document_dates (const curlhelp_write_curlbuf *header_buf, char (*msg)[DEFAULT_BUFFER_SIZE]) 2322 char *server_date = NULL;
2381{ 2323 char *document_date = NULL;
2382 char *server_date = NULL; 2324 int date_result = STATE_OK;
2383 char *document_date = NULL; 2325 curlhelp_statusline status_line;
2384 int date_result = STATE_OK; 2326 struct phr_header headers[255];
2385 curlhelp_statusline status_line; 2327 size_t nof_headers = 255;
2386 struct phr_header headers[255]; 2328 size_t msglen;
2387 size_t nof_headers = 255; 2329
2388 size_t msglen; 2330 int res = phr_parse_response(header_buf->buf, header_buf->buflen, &status_line.http_major, &status_line.http_minor,
2389 2331 &status_line.http_code, &status_line.msg, &msglen, headers, &nof_headers, 0);
2390 int res = phr_parse_response (header_buf->buf, header_buf->buflen,
2391 &status_line.http_major, &status_line.http_minor, &status_line.http_code, &status_line.msg, &msglen,
2392 headers, &nof_headers, 0);
2393 2332
2394 if (res == -1) { 2333 if (res == -1) {
2395 die (STATE_UNKNOWN, _("HTTP UNKNOWN - Failed to parse Response\n")); 2334 die(STATE_UNKNOWN, _("HTTP UNKNOWN - Failed to parse Response\n"));
2396 } 2335 }
2397 2336
2398 server_date = get_header_value (headers, nof_headers, "date"); 2337 server_date = get_header_value(headers, nof_headers, "date");
2399 document_date = get_header_value (headers, nof_headers, "last-modified"); 2338 document_date = get_header_value(headers, nof_headers, "last-modified");
2400 2339
2401 if (!server_date || !*server_date) { 2340 if (!server_date || !*server_date) {
2402 char tmp[DEFAULT_BUFFER_SIZE]; 2341 char tmp[DEFAULT_BUFFER_SIZE];
2403 2342
2404 snprintf (tmp, DEFAULT_BUFFER_SIZE, _("%sServer date unknown, "), *msg); 2343 snprintf(tmp, DEFAULT_BUFFER_SIZE, _("%sServer date unknown, "), *msg);
2405 strcpy(*msg, tmp); 2344 strcpy(*msg, tmp);
2406 2345
2407 date_result = max_state_alt(STATE_UNKNOWN, date_result); 2346 date_result = max_state_alt(STATE_UNKNOWN, date_result);
@@ -2409,34 +2348,34 @@ check_document_dates (const curlhelp_write_curlbuf *header_buf, char (*msg)[DEFA
2409 } else if (!document_date || !*document_date) { 2348 } else if (!document_date || !*document_date) {
2410 char tmp[DEFAULT_BUFFER_SIZE]; 2349 char tmp[DEFAULT_BUFFER_SIZE];
2411 2350
2412 snprintf (tmp, DEFAULT_BUFFER_SIZE, _("%sDocument modification date unknown, "), *msg); 2351 snprintf(tmp, DEFAULT_BUFFER_SIZE, _("%sDocument modification date unknown, "), *msg);
2413 strcpy(*msg, tmp); 2352 strcpy(*msg, tmp);
2414 2353
2415 date_result = max_state_alt(STATE_CRITICAL, date_result); 2354 date_result = max_state_alt(STATE_CRITICAL, date_result);
2416 2355
2417 } else { 2356 } else {
2418 time_t srv_data = curl_getdate (server_date, NULL); 2357 time_t srv_data = curl_getdate(server_date, NULL);
2419 time_t doc_data = curl_getdate (document_date, NULL); 2358 time_t doc_data = curl_getdate(document_date, NULL);
2420 if (verbose >= 2) 2359 if (verbose >= 2)
2421 printf ("* server date: '%s' (%d), doc_date: '%s' (%d)\n", server_date, (int)srv_data, document_date, (int)doc_data); 2360 printf("* server date: '%s' (%d), doc_date: '%s' (%d)\n", server_date, (int)srv_data, document_date, (int)doc_data);
2422 if (srv_data <= 0) { 2361 if (srv_data <= 0) {
2423 char tmp[DEFAULT_BUFFER_SIZE]; 2362 char tmp[DEFAULT_BUFFER_SIZE];
2424 2363
2425 snprintf (tmp, DEFAULT_BUFFER_SIZE, _("%sServer date \"%100s\" unparsable, "), *msg, server_date); 2364 snprintf(tmp, DEFAULT_BUFFER_SIZE, _("%sServer date \"%100s\" unparsable, "), *msg, server_date);
2426 strcpy(*msg, tmp); 2365 strcpy(*msg, tmp);
2427 2366
2428 date_result = max_state_alt(STATE_CRITICAL, date_result); 2367 date_result = max_state_alt(STATE_CRITICAL, date_result);
2429 } else if (doc_data <= 0) { 2368 } else if (doc_data <= 0) {
2430 char tmp[DEFAULT_BUFFER_SIZE]; 2369 char tmp[DEFAULT_BUFFER_SIZE];
2431 2370
2432 snprintf (tmp, DEFAULT_BUFFER_SIZE, _("%sDocument date \"%100s\" unparsable, "), *msg, document_date); 2371 snprintf(tmp, DEFAULT_BUFFER_SIZE, _("%sDocument date \"%100s\" unparsable, "), *msg, document_date);
2433 strcpy(*msg, tmp); 2372 strcpy(*msg, tmp);
2434 2373
2435 date_result = max_state_alt(STATE_CRITICAL, date_result); 2374 date_result = max_state_alt(STATE_CRITICAL, date_result);
2436 } else if (doc_data > srv_data + 30) { 2375 } else if (doc_data > srv_data + 30) {
2437 char tmp[DEFAULT_BUFFER_SIZE]; 2376 char tmp[DEFAULT_BUFFER_SIZE];
2438 2377
2439 snprintf (tmp, DEFAULT_BUFFER_SIZE, _("%sDocument is %d seconds in the future, "), *msg, (int)doc_data - (int)srv_data); 2378 snprintf(tmp, DEFAULT_BUFFER_SIZE, _("%sDocument is %d seconds in the future, "), *msg, (int)doc_data - (int)srv_data);
2440 strcpy(*msg, tmp); 2379 strcpy(*msg, tmp);
2441 2380
2442 date_result = max_state_alt(STATE_CRITICAL, date_result); 2381 date_result = max_state_alt(STATE_CRITICAL, date_result);
@@ -2445,14 +2384,14 @@ check_document_dates (const curlhelp_write_curlbuf *header_buf, char (*msg)[DEFA
2445 if (n > (60 * 60 * 24 * 2)) { 2384 if (n > (60 * 60 * 24 * 2)) {
2446 char tmp[DEFAULT_BUFFER_SIZE]; 2385 char tmp[DEFAULT_BUFFER_SIZE];
2447 2386
2448 snprintf (tmp, DEFAULT_BUFFER_SIZE, _("%sLast modified %.1f days ago, "), *msg, ((float) n) / (60 * 60 * 24)); 2387 snprintf(tmp, DEFAULT_BUFFER_SIZE, _("%sLast modified %.1f days ago, "), *msg, ((float)n) / (60 * 60 * 24));
2449 strcpy(*msg, tmp); 2388 strcpy(*msg, tmp);
2450 2389
2451 date_result = max_state_alt(STATE_CRITICAL, date_result); 2390 date_result = max_state_alt(STATE_CRITICAL, date_result);
2452 } else { 2391 } else {
2453 char tmp[DEFAULT_BUFFER_SIZE]; 2392 char tmp[DEFAULT_BUFFER_SIZE];
2454 2393
2455 snprintf (tmp, DEFAULT_BUFFER_SIZE, _("%sLast modified %d:%02d:%02d ago, "), *msg, n / (60 * 60), (n / 60) % 60, n % 60); 2394 snprintf(tmp, DEFAULT_BUFFER_SIZE, _("%sLast modified %d:%02d:%02d ago, "), *msg, n / (60 * 60), (n / 60) % 60, n % 60);
2456 strcpy(*msg, tmp); 2395 strcpy(*msg, tmp);
2457 2396
2458 date_result = max_state_alt(STATE_CRITICAL, date_result); 2397 date_result = max_state_alt(STATE_CRITICAL, date_result);
@@ -2460,132 +2399,128 @@ check_document_dates (const curlhelp_write_curlbuf *header_buf, char (*msg)[DEFA
2460 } 2399 }
2461 } 2400 }
2462 2401
2463 if (server_date) free (server_date); 2402 if (server_date)
2464 if (document_date) free (document_date); 2403 free(server_date);
2404 if (document_date)
2405 free(document_date);
2465 2406
2466 return date_result; 2407 return date_result;
2467} 2408}
2468 2409
2410int get_content_length(const curlhelp_write_curlbuf *header_buf, const curlhelp_write_curlbuf *body_buf) {
2411 size_t content_length = 0;
2412 struct phr_header headers[255];
2413 size_t nof_headers = 255;
2414 size_t msglen;
2415 char *content_length_s = NULL;
2416 curlhelp_statusline status_line;
2469 2417
2470int 2418 int res = phr_parse_response(header_buf->buf, header_buf->buflen, &status_line.http_major, &status_line.http_minor,
2471get_content_length (const curlhelp_write_curlbuf* header_buf, const curlhelp_write_curlbuf* body_buf) 2419 &status_line.http_code, &status_line.msg, &msglen, headers, &nof_headers, 0);
2472{
2473 size_t content_length = 0;
2474 struct phr_header headers[255];
2475 size_t nof_headers = 255;
2476 size_t msglen;
2477 char *content_length_s = NULL;
2478 curlhelp_statusline status_line;
2479
2480 int res = phr_parse_response (header_buf->buf, header_buf->buflen,
2481 &status_line.http_major, &status_line.http_minor, &status_line.http_code, &status_line.msg, &msglen,
2482 headers, &nof_headers, 0);
2483 2420
2484 if (res == -1) { 2421 if (res == -1) {
2485 die (STATE_UNKNOWN, _("HTTP UNKNOWN - Failed to parse Response\n")); 2422 die(STATE_UNKNOWN, _("HTTP UNKNOWN - Failed to parse Response\n"));
2486 } 2423 }
2487 2424
2488 content_length_s = get_header_value (headers, nof_headers, "content-length"); 2425 content_length_s = get_header_value(headers, nof_headers, "content-length");
2489 if (!content_length_s) { 2426 if (!content_length_s) {
2490 return header_buf->buflen + body_buf->buflen; 2427 return header_buf->buflen + body_buf->buflen;
2491 } 2428 }
2492 content_length_s += strspn (content_length_s, " \t"); 2429 content_length_s += strspn(content_length_s, " \t");
2493 content_length = atoi (content_length_s); 2430 content_length = atoi(content_length_s);
2494 if (content_length != body_buf->buflen) { 2431 if (content_length != body_buf->buflen) {
2495 /* TODO: should we warn if the actual and the reported body length don't match? */ 2432 /* TODO: should we warn if the actual and the reported body length don't match? */
2496 } 2433 }
2497 2434
2498 if (content_length_s) free (content_length_s); 2435 if (content_length_s)
2436 free(content_length_s);
2499 2437
2500 return header_buf->buflen + body_buf->buflen; 2438 return header_buf->buflen + body_buf->buflen;
2501} 2439}
2502 2440
2503/* TODO: is there a better way in libcurl to check for the SSL library? */ 2441/* TODO: is there a better way in libcurl to check for the SSL library? */
2504curlhelp_ssl_library 2442curlhelp_ssl_library curlhelp_get_ssl_library(void) {
2505curlhelp_get_ssl_library () 2443 curl_version_info_data *version_data;
2506{ 2444 char *ssl_version;
2507 curl_version_info_data* version_data; 2445 char *library;
2508 char *ssl_version; 2446 curlhelp_ssl_library ssl_library = CURLHELP_SSL_LIBRARY_UNKNOWN;
2509 char *library; 2447
2510 curlhelp_ssl_library ssl_library = CURLHELP_SSL_LIBRARY_UNKNOWN; 2448 version_data = curl_version_info(CURLVERSION_NOW);
2511 2449 if (version_data == NULL)
2512 version_data = curl_version_info (CURLVERSION_NOW); 2450 return CURLHELP_SSL_LIBRARY_UNKNOWN;
2513 if (version_data == NULL) return CURLHELP_SSL_LIBRARY_UNKNOWN; 2451
2514 2452 ssl_version = strdup(version_data->ssl_version);
2515 ssl_version = strdup (version_data->ssl_version); 2453 if (ssl_version == NULL)
2516 if (ssl_version == NULL ) return CURLHELP_SSL_LIBRARY_UNKNOWN; 2454 return CURLHELP_SSL_LIBRARY_UNKNOWN;
2517 2455
2518 library = strtok (ssl_version, "/"); 2456 library = strtok(ssl_version, "/");
2519 if (library == NULL) return CURLHELP_SSL_LIBRARY_UNKNOWN; 2457 if (library == NULL)
2520 2458 return CURLHELP_SSL_LIBRARY_UNKNOWN;
2521 if (strcmp (library, "OpenSSL") == 0) 2459
2522 ssl_library = CURLHELP_SSL_LIBRARY_OPENSSL; 2460 if (strcmp(library, "OpenSSL") == 0)
2523 else if (strcmp (library, "LibreSSL") == 0) 2461 ssl_library = CURLHELP_SSL_LIBRARY_OPENSSL;
2524 ssl_library = CURLHELP_SSL_LIBRARY_LIBRESSL; 2462 else if (strcmp(library, "LibreSSL") == 0)
2525 else if (strcmp (library, "GnuTLS") == 0) 2463 ssl_library = CURLHELP_SSL_LIBRARY_LIBRESSL;
2526 ssl_library = CURLHELP_SSL_LIBRARY_GNUTLS; 2464 else if (strcmp(library, "GnuTLS") == 0)
2527 else if (strcmp (library, "NSS") == 0) 2465 ssl_library = CURLHELP_SSL_LIBRARY_GNUTLS;
2528 ssl_library = CURLHELP_SSL_LIBRARY_NSS; 2466 else if (strcmp(library, "NSS") == 0)
2529 2467 ssl_library = CURLHELP_SSL_LIBRARY_NSS;
2530 if (verbose >= 2) 2468
2531 printf ("* SSL library string is : %s %s (%d)\n", version_data->ssl_version, library, ssl_library); 2469 if (verbose >= 2)
2532 2470 printf("* SSL library string is : %s %s (%d)\n", version_data->ssl_version, library, ssl_library);
2533 free (ssl_version); 2471
2534 2472 free(ssl_version);
2535 return ssl_library; 2473
2474 return ssl_library;
2536} 2475}
2537 2476
2538const char* 2477const char *curlhelp_get_ssl_library_string(curlhelp_ssl_library ssl_library) {
2539curlhelp_get_ssl_library_string (curlhelp_ssl_library ssl_library) 2478 switch (ssl_library) {
2540{ 2479 case CURLHELP_SSL_LIBRARY_OPENSSL:
2541 switch (ssl_library) { 2480 return "OpenSSL";
2542 case CURLHELP_SSL_LIBRARY_OPENSSL: 2481 case CURLHELP_SSL_LIBRARY_LIBRESSL:
2543 return "OpenSSL"; 2482 return "LibreSSL";
2544 case CURLHELP_SSL_LIBRARY_LIBRESSL: 2483 case CURLHELP_SSL_LIBRARY_GNUTLS:
2545 return "LibreSSL"; 2484 return "GnuTLS";
2546 case CURLHELP_SSL_LIBRARY_GNUTLS: 2485 case CURLHELP_SSL_LIBRARY_NSS:
2547 return "GnuTLS"; 2486 return "NSS";
2548 case CURLHELP_SSL_LIBRARY_NSS: 2487 case CURLHELP_SSL_LIBRARY_UNKNOWN:
2549 return "NSS"; 2488 default:
2550 case CURLHELP_SSL_LIBRARY_UNKNOWN: 2489 return "unknown";
2551 default: 2490 }
2552 return "unknown";
2553 }
2554} 2491}
2555 2492
2556#ifdef LIBCURL_FEATURE_SSL 2493#ifdef LIBCURL_FEATURE_SSL
2557#ifndef USE_OPENSSL 2494# ifndef USE_OPENSSL
2558time_t 2495time_t parse_cert_date(const char *s) {
2559parse_cert_date (const char *s) 2496 struct tm tm;
2560{ 2497 time_t date;
2561 struct tm tm; 2498 char *res;
2562 time_t date; 2499
2563 char *res; 2500 if (!s)
2564 2501 return -1;
2565 if (!s) return -1; 2502
2566 2503 /* Jan 17 14:25:12 2020 GMT */
2567 /* Jan 17 14:25:12 2020 GMT */ 2504 res = strptime(s, "%Y-%m-%d %H:%M:%S GMT", &tm);
2568 res = strptime (s, "%Y-%m-%d %H:%M:%S GMT", &tm); 2505 /* Sep 11 12:00:00 2020 GMT */
2569 /* Sep 11 12:00:00 2020 GMT */ 2506 if (res == NULL)
2570 if (res == NULL) strptime (s, "%Y %m %d %H:%M:%S GMT", &tm); 2507 strptime(s, "%Y %m %d %H:%M:%S GMT", &tm);
2571 date = mktime (&tm); 2508 date = mktime(&tm);
2572 2509
2573 return date; 2510 return date;
2574} 2511}
2575 2512
2576/* TODO: this needs cleanup in the sslutils.c, maybe we the #else case to 2513/* TODO: this needs cleanup in the sslutils.c, maybe we the #else case to
2577 * OpenSSL could be this function 2514 * OpenSSL could be this function
2578 */ 2515 */
2579int 2516int net_noopenssl_check_certificate(cert_ptr_union *cert_ptr, int days_till_exp_warn, int days_till_exp_crit) {
2580net_noopenssl_check_certificate (cert_ptr_union* cert_ptr, int days_till_exp_warn, int days_till_exp_crit) 2517 int i;
2581{ 2518 struct curl_slist *slist;
2582 int i; 2519 int cname_found = 0;
2583 struct curl_slist* slist; 2520 char *start_date_str = NULL;
2584 int cname_found = 0; 2521 char *end_date_str = NULL;
2585 char* start_date_str = NULL; 2522 time_t start_date;
2586 char* end_date_str = NULL; 2523 time_t end_date;
2587 time_t start_date;
2588 time_t end_date;
2589 char *tz; 2524 char *tz;
2590 float time_left; 2525 float time_left;
2591 int days_left; 2526 int days_left;
@@ -2593,66 +2528,64 @@ net_noopenssl_check_certificate (cert_ptr_union* cert_ptr, int days_till_exp_war
2593 char timestamp[50] = ""; 2528 char timestamp[50] = "";
2594 int status = STATE_UNKNOWN; 2529 int status = STATE_UNKNOWN;
2595 2530
2596 if (verbose >= 2) 2531 if (verbose >= 2)
2597 printf ("**** REQUEST CERTIFICATES ****\n"); 2532 printf("**** REQUEST CERTIFICATES ****\n");
2598 2533
2599 for (i = 0; i < cert_ptr->to_certinfo->num_of_certs; i++) { 2534 for (i = 0; i < cert_ptr->to_certinfo->num_of_certs; i++) {
2600 for (slist = cert_ptr->to_certinfo->certinfo[i]; slist; slist = slist->next) { 2535 for (slist = cert_ptr->to_certinfo->certinfo[i]; slist; slist = slist->next) {
2601 /* find first common name in subject, 2536 /* find first common name in subject,
2602 * TODO: check alternative subjects for 2537 * TODO: check alternative subjects for
2603 * TODO: have a decent parser here and not a hack 2538 * TODO: have a decent parser here and not a hack
2604 * multi-host certificate, check wildcards 2539 * multi-host certificate, check wildcards
2605 */ 2540 */
2606 if (strncasecmp (slist->data, "Subject:", 8) == 0) { 2541 if (strncasecmp(slist->data, "Subject:", 8) == 0) {
2607 int d = 3; 2542 int d = 3;
2608 char* p = strstr (slist->data, "CN="); 2543 char *p = strstr(slist->data, "CN=");
2609 if (p == NULL) { 2544 if (p == NULL) {
2610 d = 5; 2545 d = 5;
2611 p = strstr (slist->data, "CN = "); 2546 p = strstr(slist->data, "CN = ");
2612 } 2547 }
2613 if (p != NULL) { 2548 if (p != NULL) {
2614 if (strncmp (host_name, p+d, strlen (host_name)) == 0) { 2549 if (strncmp(host_name, p + d, strlen(host_name)) == 0) {
2615 cname_found = 1; 2550 cname_found = 1;
2616 } 2551 }
2617 } 2552 }
2618 } else if (strncasecmp (slist->data, "Start Date:", 11) == 0) { 2553 } else if (strncasecmp(slist->data, "Start Date:", 11) == 0) {
2619 start_date_str = &slist->data[11]; 2554 start_date_str = &slist->data[11];
2620 } else if (strncasecmp (slist->data, "Expire Date:", 12) == 0) { 2555 } else if (strncasecmp(slist->data, "Expire Date:", 12) == 0) {
2621 end_date_str = &slist->data[12]; 2556 end_date_str = &slist->data[12];
2622 } else if (strncasecmp (slist->data, "Cert:", 5) == 0) { 2557 } else if (strncasecmp(slist->data, "Cert:", 5) == 0) {
2623 goto HAVE_FIRST_CERT; 2558 goto HAVE_FIRST_CERT;
2624 } 2559 }
2625 if (verbose >= 2) 2560 if (verbose >= 2)
2626 printf ("%d ** %s\n", i, slist->data); 2561 printf("%d ** %s\n", i, slist->data);
2627 } 2562 }
2628 } 2563 }
2629HAVE_FIRST_CERT: 2564HAVE_FIRST_CERT:
2630 2565
2631 if (verbose >= 2) 2566 if (verbose >= 2)
2632 printf ("**** REQUEST CERTIFICATES ****\n"); 2567 printf("**** REQUEST CERTIFICATES ****\n");
2633 2568
2634 if (!cname_found) { 2569 if (!cname_found) {
2635 printf("%s\n",_("CRITICAL - Cannot retrieve certificate subject.")); 2570 printf("%s\n", _("CRITICAL - Cannot retrieve certificate subject."));
2636 return STATE_CRITICAL; 2571 return STATE_CRITICAL;
2637 } 2572 }
2638 2573
2639 start_date = parse_cert_date (start_date_str); 2574 start_date = parse_cert_date(start_date_str);
2640 if (start_date <= 0) { 2575 if (start_date <= 0) {
2641 snprintf (msg, DEFAULT_BUFFER_SIZE, _("WARNING - Unparsable 'Start Date' in certificate: '%s'"), 2576 snprintf(msg, DEFAULT_BUFFER_SIZE, _("WARNING - Unparsable 'Start Date' in certificate: '%s'"), start_date_str);
2642 start_date_str); 2577 puts(msg);
2643 puts (msg); 2578 return STATE_WARNING;
2644 return STATE_WARNING; 2579 }
2645 } 2580
2646 2581 end_date = parse_cert_date(end_date_str);
2647 end_date = parse_cert_date (end_date_str); 2582 if (end_date <= 0) {
2648 if (end_date <= 0) { 2583 snprintf(msg, DEFAULT_BUFFER_SIZE, _("WARNING - Unparsable 'Expire Date' in certificate: '%s'"), start_date_str);
2649 snprintf (msg, DEFAULT_BUFFER_SIZE, _("WARNING - Unparsable 'Expire Date' in certificate: '%s'"), 2584 puts(msg);
2650 start_date_str); 2585 return STATE_WARNING;
2651 puts (msg); 2586 }
2652 return STATE_WARNING; 2587
2653 } 2588 time_left = difftime(end_date, time(NULL));
2654
2655 time_left = difftime (end_date, time(NULL));
2656 days_left = time_left / 86400; 2589 days_left = time_left / 86400;
2657 tz = getenv("TZ"); 2590 tz = getenv("TZ");
2658 setenv("TZ", "GMT", 1); 2591 setenv("TZ", "GMT", 1);
@@ -2665,30 +2598,31 @@ HAVE_FIRST_CERT:
2665 tzset(); 2598 tzset();
2666 2599
2667 if (days_left > 0 && days_left <= days_till_exp_warn) { 2600 if (days_left > 0 && days_left <= days_till_exp_warn) {
2668 printf (_("%s - Certificate '%s' expires in %d day(s) (%s).\n"), (days_left>days_till_exp_crit)?"WARNING":"CRITICAL", host_name, days_left, timestamp); 2601 printf(_("%s - Certificate '%s' expires in %d day(s) (%s).\n"), (days_left > days_till_exp_crit) ? "WARNING" : "CRITICAL",
2602 host_name, days_left, timestamp);
2669 if (days_left > days_till_exp_crit) 2603 if (days_left > days_till_exp_crit)
2670 status = STATE_WARNING; 2604 status = STATE_WARNING;
2671 else 2605 else
2672 status = STATE_CRITICAL; 2606 status = STATE_CRITICAL;
2673 } else if (days_left == 0 && time_left > 0) { 2607 } else if (days_left == 0 && time_left > 0) {
2674 if (time_left >= 3600) 2608 if (time_left >= 3600)
2675 time_remaining = (int) time_left / 3600; 2609 time_remaining = (int)time_left / 3600;
2676 else 2610 else
2677 time_remaining = (int) time_left / 60; 2611 time_remaining = (int)time_left / 60;
2678 2612
2679 printf (_("%s - Certificate '%s' expires in %u %s (%s)\n"), 2613 printf(_("%s - Certificate '%s' expires in %u %s (%s)\n"), (days_left > days_till_exp_crit) ? "WARNING" : "CRITICAL", host_name,
2680 (days_left>days_till_exp_crit) ? "WARNING" : "CRITICAL", host_name, time_remaining, 2614 time_remaining, time_left >= 3600 ? "hours" : "minutes", timestamp);
2681 time_left >= 3600 ? "hours" : "minutes", timestamp);
2682 2615
2683 if ( days_left > days_till_exp_crit) 2616 if (days_left > days_till_exp_crit)
2684 status = STATE_WARNING; 2617 status = STATE_WARNING;
2685 else 2618 else
2686 status = STATE_CRITICAL; 2619 status = STATE_CRITICAL;
2687 } else if (time_left < 0) { 2620 } else if (time_left < 0) {
2688 printf(_("CRITICAL - Certificate '%s' expired on %s.\n"), host_name, timestamp); 2621 printf(_("CRITICAL - Certificate '%s' expired on %s.\n"), host_name, timestamp);
2689 status=STATE_CRITICAL; 2622 status = STATE_CRITICAL;
2690 } else if (days_left == 0) { 2623 } else if (days_left == 0) {
2691 printf (_("%s - Certificate '%s' just expired (%s).\n"), (days_left>days_till_exp_crit)?"WARNING":"CRITICAL", host_name, timestamp); 2624 printf(_("%s - Certificate '%s' just expired (%s).\n"), (days_left > days_till_exp_crit) ? "WARNING" : "CRITICAL", host_name,
2625 timestamp);
2692 if (days_left > days_till_exp_crit) 2626 if (days_left > days_till_exp_crit)
2693 status = STATE_WARNING; 2627 status = STATE_WARNING;
2694 else 2628 else
@@ -2699,5 +2633,5 @@ HAVE_FIRST_CERT:
2699 } 2633 }
2700 return status; 2634 return status;
2701} 2635}
2702#endif /* USE_OPENSSL */ 2636# endif /* USE_OPENSSL */
2703#endif /* LIBCURL_FEATURE_SSL */ 2637#endif /* LIBCURL_FEATURE_SSL */
diff --git a/plugins/check_dbi.c b/plugins/check_dbi.c
index 29c85206..96575672 100644
--- a/plugins/check_dbi.c
+++ b/plugins/check_dbi.c
@@ -1,36 +1,36 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring check_dbi plugin 3 * Monitoring check_dbi plugin
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 2011 Monitoring Plugins Development Team 6 * Copyright (c) 2011-2024 Monitoring Plugins Development Team
7* Author: Sebastian 'tokkee' Harl <sh@teamix.net> 7 * Original Author: Sebastian 'tokkee' Harl <sh@teamix.net>
8* 8 *
9* Description: 9 * Description:
10* 10 *
11* This file contains the check_dbi plugin 11 * This file contains the check_dbi plugin
12* 12 *
13* Runs an arbitrary (SQL) command and checks the result. 13 * Runs an arbitrary (SQL) command and checks the result.
14* 14 *
15* 15 *
16* This program is free software: you can redistribute it and/or modify 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 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 18 * the Free Software Foundation, either version 3 of the License, or
19* (at your option) any later version. 19 * (at your option) any later version.
20* 20 *
21* This program is distributed in the hope that it will be useful, 21 * This program is distributed in the hope that it will be useful,
22* but WITHOUT ANY WARRANTY; without even the implied warranty of 22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24* GNU General Public License for more details. 24 * GNU General Public License for more details.
25* 25 *
26* You should have received a copy of the GNU General Public License 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/>. 27 * along with this program. If not, see <http://www.gnu.org/licenses/>.
28* 28 *
29* 29 *
30*****************************************************************************/ 30 *****************************************************************************/
31 31
32const char *progname = "check_dbi"; 32const char *progname = "check_dbi";
33const char *copyright = "2011"; 33const char *copyright = "2011-2024";
34const char *email = "devel@monitoring-plugins.org"; 34const char *email = "devel@monitoring-plugins.org";
35 35
36#include "common.h" 36#include "common.h"
@@ -43,7 +43,7 @@ const char *email = "devel@monitoring-plugins.org";
43 43
44/* required for NAN */ 44/* required for NAN */
45#ifndef _ISOC99_SOURCE 45#ifndef _ISOC99_SOURCE
46#define _ISOC99_SOURCE 46# define _ISOC99_SOURCE
47#endif 47#endif
48 48
49#include <assert.h> 49#include <assert.h>
@@ -70,42 +70,40 @@ typedef struct {
70 char *value; 70 char *value;
71} driver_option_t; 71} driver_option_t;
72 72
73char *host = NULL; 73static char *host = NULL;
74int verbose = 0; 74static int verbose = 0;
75 75
76char *warning_range = NULL; 76static char *warning_range = NULL;
77char *critical_range = NULL; 77static char *critical_range = NULL;
78thresholds *dbi_thresholds = NULL; 78static thresholds *dbi_thresholds = NULL;
79 79
80char *expect = NULL; 80static char *expect = NULL;
81 81
82regex_t expect_re; 82static regex_t expect_re;
83char *expect_re_str = NULL; 83static char *expect_re_str = NULL;
84int expect_re_cflags = 0; 84static int expect_re_cflags = 0;
85 85
86np_dbi_metric_t metric = METRIC_QUERY_RESULT; 86static np_dbi_metric_t metric = METRIC_QUERY_RESULT;
87np_dbi_type_t type = TYPE_NUMERIC; 87static np_dbi_type_t type = TYPE_NUMERIC;
88 88
89char *np_dbi_driver = NULL; 89static char *np_dbi_driver = NULL;
90driver_option_t *np_dbi_options = NULL; 90static driver_option_t *np_dbi_options = NULL;
91int np_dbi_options_num = 0; 91static int np_dbi_options_num = 0;
92char *np_dbi_database = NULL; 92static char *np_dbi_database = NULL;
93char *np_dbi_query = NULL; 93static char *np_dbi_query = NULL;
94 94
95int process_arguments (int, char **); 95static int process_arguments(int, char **);
96int validate_arguments (void); 96static int validate_arguments(void);
97void print_usage (void); 97void print_usage(void);
98void print_help (void); 98static void print_help(void);
99 99
100double timediff (struct timeval, struct timeval); 100static double timediff(struct timeval, struct timeval);
101 101
102void np_dbi_print_error (dbi_conn, char *, ...); 102static void np_dbi_print_error(dbi_conn, char *, ...);
103 103
104int do_query (dbi_conn, const char **, double *, double *); 104static int do_query(dbi_conn, const char **, double *, double *);
105 105
106int 106int main(int argc, char **argv) {
107main (int argc, char **argv)
108{
109 int status = STATE_UNKNOWN; 107 int status = STATE_UNKNOWN;
110 108
111 dbi_driver driver; 109 dbi_driver driver;
@@ -113,7 +111,8 @@ main (int argc, char **argv)
113 111
114 unsigned int server_version; 112 unsigned int server_version;
115 113
116 struct timeval start_timeval, end_timeval; 114 struct timeval start_timeval;
115 struct timeval end_timeval;
117 double conn_time = 0.0; 116 double conn_time = 0.0;
118 double query_time = 0.0; 117 double query_time = 0.0;
119 118
@@ -122,59 +121,58 @@ main (int argc, char **argv)
122 121
123 int i; 122 int i;
124 123
125 setlocale (LC_ALL, ""); 124 setlocale(LC_ALL, "");
126 bindtextdomain (PACKAGE, LOCALEDIR); 125 bindtextdomain(PACKAGE, LOCALEDIR);
127 textdomain (PACKAGE); 126 textdomain(PACKAGE);
128 127
129 /* Parse extra opts if any */ 128 /* Parse extra opts if any */
130 argv = np_extra_opts (&argc, argv, progname); 129 argv = np_extra_opts(&argc, argv, progname);
131 130
132 if (process_arguments (argc, argv) == ERROR) 131 if (process_arguments(argc, argv) == ERROR)
133 usage4 (_("Could not parse arguments")); 132 usage4(_("Could not parse arguments"));
134 133
135 /* Set signal handling and alarm */ 134 /* Set signal handling and alarm */
136 if (signal (SIGALRM, timeout_alarm_handler) == SIG_ERR) { 135 if (signal(SIGALRM, timeout_alarm_handler) == SIG_ERR) {
137 usage4 (_("Cannot catch SIGALRM")); 136 usage4(_("Cannot catch SIGALRM"));
138 } 137 }
139 alarm (timeout_interval); 138 alarm(timeout_interval);
140 139
141 if (verbose > 2) 140 if (verbose > 2)
142 printf ("Initializing DBI\n"); 141 printf("Initializing DBI\n");
143 142
144 dbi_inst *instance_p = { 0 }; 143 dbi_inst *instance_p = {0};
145 144
146 if (dbi_initialize_r(NULL, instance_p) < 0) { 145 if (dbi_initialize_r(NULL, instance_p) < 0) {
147 printf ("UNKNOWN - failed to initialize DBI; possibly you don't have any drivers installed.\n"); 146 printf("UNKNOWN - failed to initialize DBI; possibly you don't have any drivers installed.\n");
148 return STATE_UNKNOWN; 147 return STATE_UNKNOWN;
149 } 148 }
150 149
151 if (instance_p == NULL) { 150 if (instance_p == NULL) {
152 printf ("UNKNOWN - failed to initialize DBI.\n"); 151 printf("UNKNOWN - failed to initialize DBI.\n");
153 return STATE_UNKNOWN; 152 return STATE_UNKNOWN;
154 } 153 }
155 154
156 if (verbose) 155 if (verbose)
157 printf ("Opening DBI driver '%s'\n", np_dbi_driver); 156 printf("Opening DBI driver '%s'\n", np_dbi_driver);
158 157
159 driver = dbi_driver_open_r(np_dbi_driver, instance_p); 158 driver = dbi_driver_open_r(np_dbi_driver, instance_p);
160 if (! driver) { 159 if (!driver) {
161 printf ("UNKNOWN - failed to open DBI driver '%s'; possibly it's not installed.\n", 160 printf("UNKNOWN - failed to open DBI driver '%s'; possibly it's not installed.\n", np_dbi_driver);
162 np_dbi_driver);
163 161
164 printf ("Known drivers:\n"); 162 printf("Known drivers:\n");
165 for (driver = dbi_driver_list_r(NULL, instance_p); driver; driver = dbi_driver_list_r(driver, instance_p)) { 163 for (driver = dbi_driver_list_r(NULL, instance_p); driver; driver = dbi_driver_list_r(driver, instance_p)) {
166 printf (" - %s\n", dbi_driver_get_name (driver)); 164 printf(" - %s\n", dbi_driver_get_name(driver));
167 } 165 }
168 return STATE_UNKNOWN; 166 return STATE_UNKNOWN;
169 } 167 }
170 168
171 /* make a connection to the database */ 169 /* make a connection to the database */
172 gettimeofday (&start_timeval, NULL); 170 gettimeofday(&start_timeval, NULL);
173 171
174 conn = dbi_conn_open (driver); 172 conn = dbi_conn_open(driver);
175 if (! conn) { 173 if (!conn) {
176 printf ("UNKNOWN - failed top open connection object.\n"); 174 printf("UNKNOWN - failed top open connection object.\n");
177 dbi_conn_close (conn); 175 dbi_conn_close(conn);
178 return STATE_UNKNOWN; 176 return STATE_UNKNOWN;
179 } 177 }
180 178
@@ -182,210 +180,190 @@ main (int argc, char **argv)
182 const char *opt; 180 const char *opt;
183 181
184 if (verbose > 1) 182 if (verbose > 1)
185 printf ("Setting DBI driver option '%s' to '%s'\n", 183 printf("Setting DBI driver option '%s' to '%s'\n", np_dbi_options[i].key, np_dbi_options[i].value);
186 np_dbi_options[i].key, np_dbi_options[i].value);
187 184
188 if (! dbi_conn_set_option (conn, np_dbi_options[i].key, np_dbi_options[i].value)) 185 if (!dbi_conn_set_option(conn, np_dbi_options[i].key, np_dbi_options[i].value))
189 continue; 186 continue;
190 /* else: status != 0 */ 187 /* else: status != 0 */
191 188
192 np_dbi_print_error (conn, "UNKNOWN - failed to set option '%s' to '%s'", 189 np_dbi_print_error(conn, "UNKNOWN - failed to set option '%s' to '%s'", np_dbi_options[i].key, np_dbi_options[i].value);
193 np_dbi_options[i].key, np_dbi_options[i].value); 190 printf("Known driver options:\n");
194 printf ("Known driver options:\n");
195 191
196 for (opt = dbi_conn_get_option_list (conn, NULL); opt; 192 for (opt = dbi_conn_get_option_list(conn, NULL); opt; opt = dbi_conn_get_option_list(conn, opt)) {
197 opt = dbi_conn_get_option_list (conn, opt)) { 193 printf(" - %s\n", opt);
198 printf (" - %s\n", opt);
199 } 194 }
200 dbi_conn_close (conn); 195 dbi_conn_close(conn);
201 return STATE_UNKNOWN; 196 return STATE_UNKNOWN;
202 } 197 }
203 198
204 if (host) { 199 if (host) {
205 if (verbose > 1) 200 if (verbose > 1)
206 printf ("Setting DBI driver option 'host' to '%s'\n", host); 201 printf("Setting DBI driver option 'host' to '%s'\n", host);
207 dbi_conn_set_option (conn, "host", host); 202 dbi_conn_set_option(conn, "host", host);
208 } 203 }
209 204
210 if (verbose) { 205 if (verbose) {
211 const char *dbname, *host; 206 const char *dbname;
207 const char *host;
212 208
213 dbname = dbi_conn_get_option (conn, "dbname"); 209 dbname = dbi_conn_get_option(conn, "dbname");
214 host = dbi_conn_get_option (conn, "host"); 210 host = dbi_conn_get_option(conn, "host");
215 211
216 if (! dbname) 212 if (!dbname)
217 dbname = "<unspecified>"; 213 dbname = "<unspecified>";
218 if (! host) 214 if (!host)
219 host = "<unspecified>"; 215 host = "<unspecified>";
220 216
221 printf ("Connecting to database '%s' at host '%s'\n", 217 printf("Connecting to database '%s' at host '%s'\n", dbname, host);
222 dbname, host);
223 } 218 }
224 219
225 if (dbi_conn_connect (conn) < 0) { 220 if (dbi_conn_connect(conn) < 0) {
226 np_dbi_print_error (conn, "UNKNOWN - failed to connect to database"); 221 np_dbi_print_error(conn, "UNKNOWN - failed to connect to database");
227 return STATE_UNKNOWN; 222 return STATE_UNKNOWN;
228 } 223 }
229 224
230 gettimeofday (&end_timeval, NULL); 225 gettimeofday(&end_timeval, NULL);
231 conn_time = timediff (start_timeval, end_timeval); 226 conn_time = timediff(start_timeval, end_timeval);
232 227
233 server_version = dbi_conn_get_engine_version (conn); 228 server_version = dbi_conn_get_engine_version(conn);
234 if (verbose) 229 if (verbose)
235 printf ("Connected to server version %u\n", server_version); 230 printf("Connected to server version %u\n", server_version);
236 231
237 if (metric == METRIC_SERVER_VERSION) 232 if (metric == METRIC_SERVER_VERSION)
238 status = get_status (server_version, dbi_thresholds); 233 status = get_status(server_version, dbi_thresholds);
239 234
240 if (verbose) 235 if (verbose)
241 printf ("Time elapsed: %f\n", conn_time); 236 printf("Time elapsed: %f\n", conn_time);
242 237
243 if (metric == METRIC_CONN_TIME) 238 if (metric == METRIC_CONN_TIME)
244 status = get_status (conn_time, dbi_thresholds); 239 status = get_status(conn_time, dbi_thresholds);
245 240
246 /* select a database */ 241 /* select a database */
247 if (np_dbi_database) { 242 if (np_dbi_database) {
248 if (verbose > 1) 243 if (verbose > 1)
249 printf ("Selecting database '%s'\n", np_dbi_database); 244 printf("Selecting database '%s'\n", np_dbi_database);
250 245
251 if (dbi_conn_select_db (conn, np_dbi_database)) { 246 if (dbi_conn_select_db(conn, np_dbi_database)) {
252 np_dbi_print_error (conn, "UNKNOWN - failed to select database '%s'", 247 np_dbi_print_error(conn, "UNKNOWN - failed to select database '%s'", np_dbi_database);
253 np_dbi_database);
254 return STATE_UNKNOWN; 248 return STATE_UNKNOWN;
255 } 249 }
256 } 250 }
257 251
258 if (np_dbi_query) { 252 if (np_dbi_query) {
259 /* execute query */ 253 /* execute query */
260 status = do_query (conn, &query_val_str, &query_val, &query_time); 254 status = do_query(conn, &query_val_str, &query_val, &query_time);
261 if (status != STATE_OK) 255 if (status != STATE_OK)
262 /* do_query prints an error message in this case */ 256 /* do_query prints an error message in this case */
263 return status; 257 return status;
264 258
265 if (metric == METRIC_QUERY_RESULT) { 259 if (metric == METRIC_QUERY_RESULT) {
266 if (expect) { 260 if (expect) {
267 if ((! query_val_str) || strcmp (query_val_str, expect)) 261 if ((!query_val_str) || strcmp(query_val_str, expect))
268 status = STATE_CRITICAL; 262 status = STATE_CRITICAL;
269 else 263 else
270 status = STATE_OK; 264 status = STATE_OK;
271 } 265 } else if (expect_re_str) {
272 else if (expect_re_str) {
273 int err; 266 int err;
274 267
275 err = regexec (&expect_re, query_val_str, 0, NULL, /* flags = */ 0); 268 err = regexec(&expect_re, query_val_str, 0, NULL, /* flags = */ 0);
276 if (! err) 269 if (!err)
277 status = STATE_OK; 270 status = STATE_OK;
278 else if (err == REG_NOMATCH) 271 else if (err == REG_NOMATCH)
279 status = STATE_CRITICAL; 272 status = STATE_CRITICAL;
280 else { 273 else {
281 char errmsg[1024]; 274 char errmsg[1024];
282 regerror (err, &expect_re, errmsg, sizeof (errmsg)); 275 regerror(err, &expect_re, errmsg, sizeof(errmsg));
283 printf ("ERROR - failed to execute regular expression: %s\n", 276 printf("ERROR - failed to execute regular expression: %s\n", errmsg);
284 errmsg);
285 status = STATE_CRITICAL; 277 status = STATE_CRITICAL;
286 } 278 }
287 } 279 } else
288 else 280 status = get_status(query_val, dbi_thresholds);
289 status = get_status (query_val, dbi_thresholds); 281 } else if (metric == METRIC_QUERY_TIME)
290 } 282 status = get_status(query_time, dbi_thresholds);
291 else if (metric == METRIC_QUERY_TIME)
292 status = get_status (query_time, dbi_thresholds);
293 } 283 }
294 284
295 if (verbose) 285 if (verbose)
296 printf("Closing connection\n"); 286 printf("Closing connection\n");
297 dbi_conn_close (conn); 287 dbi_conn_close(conn);
298 288
299 /* In case of METRIC_QUERY_RESULT, isnan(query_val) indicates an error 289 /* In case of METRIC_QUERY_RESULT, isnan(query_val) indicates an error
300 * which should have been reported and handled (abort) before 290 * which should have been reported and handled (abort) before
301 * ... unless we expected a string to be returned */ 291 * ... unless we expected a string to be returned */
302 assert ((metric != METRIC_QUERY_RESULT) || (! isnan (query_val)) 292 assert((metric != METRIC_QUERY_RESULT) || (!isnan(query_val)) || (type == TYPE_STRING));
303 || (type == TYPE_STRING));
304 293
305 assert ((type != TYPE_STRING) || (expect || expect_re_str)); 294 assert((type != TYPE_STRING) || (expect || expect_re_str));
306 295
307 printf ("%s - connection time: %fs", state_text (status), conn_time); 296 printf("%s - connection time: %fs", state_text(status), conn_time);
308 if (np_dbi_query) { 297 if (np_dbi_query) {
309 if (type == TYPE_STRING) { 298 if (type == TYPE_STRING) {
310 assert (expect || expect_re_str); 299 assert(expect || expect_re_str);
311 printf (", '%s' returned '%s' in %fs", np_dbi_query, 300 printf(", '%s' returned '%s' in %fs", np_dbi_query, query_val_str ? query_val_str : "<nothing>", query_time);
312 query_val_str ? query_val_str : "<nothing>", query_time);
313 if (status != STATE_OK) { 301 if (status != STATE_OK) {
314 if (expect) 302 if (expect)
315 printf (" (expected '%s')", expect); 303 printf(" (expected '%s')", expect);
316 else if (expect_re_str) 304 else if (expect_re_str)
317 printf (" (expected regex /%s/%s)", expect_re_str, 305 printf(" (expected regex /%s/%s)", expect_re_str, ((expect_re_cflags & REG_ICASE) ? "i" : ""));
318 ((expect_re_cflags & REG_ICASE) ? "i" : ""));
319 } 306 }
320 } 307 } else if (isnan(query_val))
321 else if (isnan (query_val)) 308 printf(", '%s' query execution time: %fs", np_dbi_query, query_time);
322 printf (", '%s' query execution time: %fs", np_dbi_query, query_time);
323 else 309 else
324 printf (", '%s' returned %f in %fs", np_dbi_query, query_val, query_time); 310 printf(", '%s' returned %f in %fs", np_dbi_query, query_val, query_time);
325 } 311 }
326 312
327 printf (" | conntime=%fs;%s;%s;0; server_version=%u;%s;%s;0;", conn_time, 313 printf(" | conntime=%fs;%s;%s;0; server_version=%u;%s;%s;0;", conn_time,
328 ((metric == METRIC_CONN_TIME) && warning_range) ? warning_range : "", 314 ((metric == METRIC_CONN_TIME) && warning_range) ? warning_range : "",
329 ((metric == METRIC_CONN_TIME) && critical_range) ? critical_range : "", 315 ((metric == METRIC_CONN_TIME) && critical_range) ? critical_range : "", server_version,
330 server_version, 316 ((metric == METRIC_SERVER_VERSION) && warning_range) ? warning_range : "",
331 ((metric == METRIC_SERVER_VERSION) && warning_range) ? warning_range : "", 317 ((metric == METRIC_SERVER_VERSION) && critical_range) ? critical_range : "");
332 ((metric == METRIC_SERVER_VERSION) && critical_range) ? critical_range : "");
333 if (np_dbi_query) { 318 if (np_dbi_query) {
334 if (! isnan (query_val)) /* this is also true when -e is used */ 319 if (!isnan(query_val)) /* this is also true when -e is used */
335 printf (" query=%f;%s;%s;;", query_val, 320 printf(" query=%f;%s;%s;;", query_val, ((metric == METRIC_QUERY_RESULT) && warning_range) ? warning_range : "",
336 ((metric == METRIC_QUERY_RESULT) && warning_range) ? warning_range : "", 321 ((metric == METRIC_QUERY_RESULT) && critical_range) ? critical_range : "");
337 ((metric == METRIC_QUERY_RESULT) && critical_range) ? critical_range : ""); 322 printf(" querytime=%fs;%s;%s;0;", query_time, ((metric == METRIC_QUERY_TIME) && warning_range) ? warning_range : "",
338 printf (" querytime=%fs;%s;%s;0;", query_time, 323 ((metric == METRIC_QUERY_TIME) && critical_range) ? critical_range : "");
339 ((metric == METRIC_QUERY_TIME) && warning_range) ? warning_range : "",
340 ((metric == METRIC_QUERY_TIME) && critical_range) ? critical_range : "");
341 } 324 }
342 printf ("\n"); 325 printf("\n");
343 return status; 326 return status;
344} 327}
345 328
346/* process command-line arguments */ 329/* process command-line arguments */
347int 330int process_arguments(int argc, char **argv) {
348process_arguments (int argc, char **argv)
349{
350 int c; 331 int c;
351 332
352 int option = 0; 333 int option = 0;
353 static struct option longopts[] = { 334 static struct option longopts[] = {STD_LONG_OPTS,
354 STD_LONG_OPTS, 335
355 336 {"expect", required_argument, 0, 'e'},
356 {"expect", required_argument, 0, 'e'}, 337 {"regex", required_argument, 0, 'r'},
357 {"regex", required_argument, 0, 'r'}, 338 {"regexi", required_argument, 0, 'R'},
358 {"regexi", required_argument, 0, 'R'}, 339 {"metric", required_argument, 0, 'm'},
359 {"metric", required_argument, 0, 'm'}, 340 {"driver", required_argument, 0, 'd'},
360 {"driver", required_argument, 0, 'd'}, 341 {"option", required_argument, 0, 'o'},
361 {"option", required_argument, 0, 'o'}, 342 {"query", required_argument, 0, 'q'},
362 {"query", required_argument, 0, 'q'}, 343 {"database", required_argument, 0, 'D'},
363 {"database", required_argument, 0, 'D'}, 344 {0, 0, 0, 0}};
364 {0, 0, 0, 0}
365 };
366 345
367 while (1) { 346 while (1) {
368 c = getopt_long (argc, argv, "Vvht:c:w:e:r:R:m:H:d:o:q:D:", 347 c = getopt_long(argc, argv, "Vvht:c:w:e:r:R:m:H:d:o:q:D:", longopts, &option);
369 longopts, &option);
370 348
371 if (c == EOF) 349 if (c == EOF)
372 break; 350 break;
373 351
374 switch (c) { 352 switch (c) {
375 case '?': /* usage */ 353 case '?': /* usage */
376 usage5 (); 354 usage5();
377 case 'h': /* help */ 355 case 'h': /* help */
378 print_help (); 356 print_help();
379 exit (STATE_UNKNOWN); 357 exit(STATE_UNKNOWN);
380 case 'V': /* version */ 358 case 'V': /* version */
381 print_revision (progname, NP_VERSION); 359 print_revision(progname, NP_VERSION);
382 exit (STATE_UNKNOWN); 360 exit(STATE_UNKNOWN);
383 361
384 case 'c': /* critical range */ 362 case 'c': /* critical range */
385 critical_range = optarg; 363 critical_range = optarg;
386 type = TYPE_NUMERIC; 364 type = TYPE_NUMERIC;
387 break; 365 break;
388 case 'w': /* warning range */ 366 case 'w': /* warning range */
389 warning_range = optarg; 367 warning_range = optarg;
390 type = TYPE_NUMERIC; 368 type = TYPE_NUMERIC;
391 break; 369 break;
@@ -396,47 +374,45 @@ process_arguments (int argc, char **argv)
396 case 'R': 374 case 'R':
397 expect_re_cflags = REG_ICASE; 375 expect_re_cflags = REG_ICASE;
398 /* fall through */ 376 /* fall through */
399 case 'r': 377 case 'r': {
400 { 378 int err;
401 int err;
402 379
403 expect_re_cflags |= REG_EXTENDED | REG_NOSUB | REG_NEWLINE; 380 expect_re_cflags |= REG_EXTENDED | REG_NOSUB | REG_NEWLINE;
404 expect_re_str = optarg; 381 expect_re_str = optarg;
405 type = TYPE_STRING; 382 type = TYPE_STRING;
406 383
407 err = regcomp (&expect_re, expect_re_str, expect_re_cflags); 384 err = regcomp(&expect_re, expect_re_str, expect_re_cflags);
408 if (err) { 385 if (err) {
409 char errmsg[1024]; 386 char errmsg[1024];
410 regerror (err, &expect_re, errmsg, sizeof (errmsg)); 387 regerror(err, &expect_re, errmsg, sizeof(errmsg));
411 printf ("ERROR - failed to compile regular expression: %s\n", 388 printf("ERROR - failed to compile regular expression: %s\n", errmsg);
412 errmsg); 389 return ERROR;
413 return ERROR;
414 }
415 break;
416 } 390 }
391 break;
392 }
417 393
418 case 'm': 394 case 'm':
419 if (! strcasecmp (optarg, "CONN_TIME")) 395 if (!strcasecmp(optarg, "CONN_TIME"))
420 metric = METRIC_CONN_TIME; 396 metric = METRIC_CONN_TIME;
421 else if (! strcasecmp (optarg, "SERVER_VERSION")) 397 else if (!strcasecmp(optarg, "SERVER_VERSION"))
422 metric = METRIC_SERVER_VERSION; 398 metric = METRIC_SERVER_VERSION;
423 else if (! strcasecmp (optarg, "QUERY_RESULT")) 399 else if (!strcasecmp(optarg, "QUERY_RESULT"))
424 metric = METRIC_QUERY_RESULT; 400 metric = METRIC_QUERY_RESULT;
425 else if (! strcasecmp (optarg, "QUERY_TIME")) 401 else if (!strcasecmp(optarg, "QUERY_TIME"))
426 metric = METRIC_QUERY_TIME; 402 metric = METRIC_QUERY_TIME;
427 else 403 else
428 usage2 (_("Invalid metric"), optarg); 404 usage2(_("Invalid metric"), optarg);
429 break; 405 break;
430 case 't': /* timeout */ 406 case 't': /* timeout */
431 if (!is_intnonneg (optarg)) 407 if (!is_intnonneg(optarg))
432 usage2 (_("Timeout interval must be a positive integer"), optarg); 408 usage2(_("Timeout interval must be a positive integer"), optarg);
433 else 409 else
434 timeout_interval = atoi (optarg); 410 timeout_interval = atoi(optarg);
435 411
436 break; 412 break;
437 case 'H': /* host */ 413 case 'H': /* host */
438 if (!is_host (optarg)) 414 if (!is_host(optarg))
439 usage2 (_("Invalid hostname/address"), optarg); 415 usage2(_("Invalid hostname/address"), optarg);
440 else 416 else
441 host = optarg; 417 host = optarg;
442 break; 418 break;
@@ -447,36 +423,34 @@ process_arguments (int argc, char **argv)
447 case 'd': 423 case 'd':
448 np_dbi_driver = optarg; 424 np_dbi_driver = optarg;
449 break; 425 break;
450 case 'o': 426 case 'o': {
451 { 427 driver_option_t *new;
452 driver_option_t *new;
453 428
454 char *k, *v; 429 char *k;
430 char *v;
455 431
456 k = optarg; 432 k = optarg;
457 v = strchr (k, (int)'='); 433 v = strchr(k, (int)'=');
458 434
459 if (! v) 435 if (!v)
460 usage2 (_("Option must be '<key>=<value>'"), optarg); 436 usage2(_("Option must be '<key>=<value>'"), optarg);
461 437
462 *v = '\0'; 438 *v = '\0';
463 ++v; 439 ++v;
464 440
465 new = realloc (np_dbi_options, 441 new = realloc(np_dbi_options, (np_dbi_options_num + 1) * sizeof(*new));
466 (np_dbi_options_num + 1) * sizeof (*new)); 442 if (!new) {
467 if (! new) { 443 printf("UNKNOWN - failed to reallocate memory\n");
468 printf ("UNKNOWN - failed to reallocate memory\n"); 444 exit(STATE_UNKNOWN);
469 exit (STATE_UNKNOWN); 445 }
470 }
471 446
472 np_dbi_options = new; 447 np_dbi_options = new;
473 new = np_dbi_options + np_dbi_options_num; 448 new = np_dbi_options + np_dbi_options_num;
474 ++np_dbi_options_num; 449 ++np_dbi_options_num;
475 450
476 new->key = k; 451 new->key = k;
477 new->value = v; 452 new->value = v;
478 } 453 } break;
479 break;
480 case 'q': 454 case 'q':
481 np_dbi_query = optarg; 455 np_dbi_query = optarg;
482 break; 456 break;
@@ -486,341 +460,314 @@ process_arguments (int argc, char **argv)
486 } 460 }
487 } 461 }
488 462
489 set_thresholds (&dbi_thresholds, warning_range, critical_range); 463 set_thresholds(&dbi_thresholds, warning_range, critical_range);
490 464
491 return validate_arguments (); 465 return validate_arguments();
492} 466}
493 467
494int 468int validate_arguments(void) {
495validate_arguments () 469 if (!np_dbi_driver)
496{ 470 usage("Must specify a DBI driver");
497 if (! np_dbi_driver)
498 usage ("Must specify a DBI driver");
499 471
500 if (((metric == METRIC_QUERY_RESULT) || (metric == METRIC_QUERY_TIME)) 472 if (((metric == METRIC_QUERY_RESULT) || (metric == METRIC_QUERY_TIME)) && (!np_dbi_query))
501 && (! np_dbi_query)) 473 usage("Must specify a query to execute (metric == QUERY_RESULT)");
502 usage ("Must specify a query to execute (metric == QUERY_RESULT)");
503 474
504 if ((metric != METRIC_CONN_TIME) 475 if ((metric != METRIC_CONN_TIME) && (metric != METRIC_SERVER_VERSION) && (metric != METRIC_QUERY_RESULT) &&
505 && (metric != METRIC_SERVER_VERSION) 476 (metric != METRIC_QUERY_TIME))
506 && (metric != METRIC_QUERY_RESULT) 477 usage("Invalid metric specified");
507 && (metric != METRIC_QUERY_TIME))
508 usage ("Invalid metric specified");
509 478
510 if (expect && (warning_range || critical_range || expect_re_str)) 479 if (expect && (warning_range || critical_range || expect_re_str))
511 usage ("Do not mix -e and -w/-c/-r/-R"); 480 usage("Do not mix -e and -w/-c/-r/-R");
512 481
513 if (expect_re_str && (warning_range || critical_range || expect)) 482 if (expect_re_str && (warning_range || critical_range || expect))
514 usage ("Do not mix -r/-R and -w/-c/-e"); 483 usage("Do not mix -r/-R and -w/-c/-e");
515 484
516 if (expect && (metric != METRIC_QUERY_RESULT)) 485 if (expect && (metric != METRIC_QUERY_RESULT))
517 usage ("Option -e requires metric QUERY_RESULT"); 486 usage("Option -e requires metric QUERY_RESULT");
518 487
519 if (expect_re_str && (metric != METRIC_QUERY_RESULT)) 488 if (expect_re_str && (metric != METRIC_QUERY_RESULT))
520 usage ("Options -r/-R require metric QUERY_RESULT"); 489 usage("Options -r/-R require metric QUERY_RESULT");
521 490
522 return OK; 491 return OK;
523} 492}
524 493
525void 494void print_help(void) {
526print_help (void) 495 print_revision(progname, NP_VERSION);
527{
528 print_revision (progname, NP_VERSION);
529 496
530 printf (COPYRIGHT, copyright, email); 497 printf(COPYRIGHT, copyright, email);
531 498
532 printf (_("This program connects to an (SQL) database using DBI and checks the\n" 499 printf(_("This program connects to an (SQL) database using DBI and checks the\n"
533 "specified metric against threshold levels. The default metric is\n" 500 "specified metric against threshold levels. The default metric is\n"
534 "the result of the specified query.\n")); 501 "the result of the specified query.\n"));
535 502
536 printf ("\n\n"); 503 printf("\n\n");
537 504
538 print_usage (); 505 print_usage();
539 506
540 printf (UT_HELP_VRSN); 507 printf(UT_HELP_VRSN);
541/* include this conditionally to avoid 'zero-length printf format string' 508/* include this conditionally to avoid 'zero-length printf format string'
542 * compiler warnings */ 509 * compiler warnings */
543#ifdef NP_EXTRA_OPTS 510#ifdef NP_EXTRA_OPTS
544 printf (UT_EXTRA_OPTS); 511 printf(UT_EXTRA_OPTS);
545#endif 512#endif
546 printf ("\n"); 513 printf("\n");
547 514
548 printf (" %s\n", "-d, --driver=STRING"); 515 printf(" %s\n", "-d, --driver=STRING");
549 printf (" %s\n", _("DBI driver to use")); 516 printf(" %s\n", _("DBI driver to use"));
550 printf (" %s\n", "-o, --option=STRING"); 517 printf(" %s\n", "-o, --option=STRING");
551 printf (" %s\n", _("DBI driver options")); 518 printf(" %s\n", _("DBI driver options"));
552 printf (" %s\n", "-q, --query=STRING"); 519 printf(" %s\n", "-q, --query=STRING");
553 printf (" %s\n", _("query to execute")); 520 printf(" %s\n", _("query to execute"));
554 printf ("\n"); 521 printf("\n");
555 522
556 printf (UT_WARN_CRIT_RANGE); 523 printf(UT_WARN_CRIT_RANGE);
557 printf (" %s\n", "-e, --expect=STRING"); 524 printf(" %s\n", "-e, --expect=STRING");
558 printf (" %s\n", _("String to expect as query result")); 525 printf(" %s\n", _("String to expect as query result"));
559 printf (" %s\n", _("Do not mix with -w, -c, -r, or -R!")); 526 printf(" %s\n", _("Do not mix with -w, -c, -r, or -R!"));
560 printf (" %s\n", "-r, --regex=REGEX"); 527 printf(" %s\n", "-r, --regex=REGEX");
561 printf (" %s\n", _("Extended POSIX regular expression to check query result against")); 528 printf(" %s\n", _("Extended POSIX regular expression to check query result against"));
562 printf (" %s\n", _("Do not mix with -w, -c, -e, or -R!")); 529 printf(" %s\n", _("Do not mix with -w, -c, -e, or -R!"));
563 printf (" %s\n", "-R, --regexi=REGEX"); 530 printf(" %s\n", "-R, --regexi=REGEX");
564 printf (" %s\n", _("Case-insensitive extended POSIX regex to check query result against")); 531 printf(" %s\n", _("Case-insensitive extended POSIX regex to check query result against"));
565 printf (" %s\n", _("Do not mix with -w, -c, -e, or -r!")); 532 printf(" %s\n", _("Do not mix with -w, -c, -e, or -r!"));
566 printf (" %s\n", "-m, --metric=METRIC"); 533 printf(" %s\n", "-m, --metric=METRIC");
567 printf (" %s\n", _("Metric to check thresholds against. Available metrics:")); 534 printf(" %s\n", _("Metric to check thresholds against. Available metrics:"));
568 printf (" CONN_TIME - %s\n", _("time used for setting up the database connection")); 535 printf(" CONN_TIME - %s\n", _("time used for setting up the database connection"));
569 printf (" QUERY_RESULT - %s\n", _("result (first column of first row) of the query")); 536 printf(" QUERY_RESULT - %s\n", _("result (first column of first row) of the query"));
570 printf (" QUERY_TIME - %s\n", _("time used to execute the query")); 537 printf(" QUERY_TIME - %s\n", _("time used to execute the query"));
571 printf (" %s\n", _("(ignore the query result)")); 538 printf(" %s\n", _("(ignore the query result)"));
572 printf ("\n"); 539 printf("\n");
573 540
574 printf (UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); 541 printf(UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
575 542
576 printf (UT_VERBOSE); 543 printf(UT_VERBOSE);
577 544
578 printf ("\n"); 545 printf("\n");
579 printf (" %s\n", _("A DBI driver (-d option) is required. If the specified metric operates")); 546 printf(" %s\n", _("A DBI driver (-d option) is required. If the specified metric operates"));
580 printf (" %s\n\n", _("on a query, one has to be specified (-q option).")); 547 printf(" %s\n\n", _("on a query, one has to be specified (-q option)."));
581 548
582 printf (" %s\n", _("This plugin connects to an (SQL) database using libdbi and, optionally,")); 549 printf(" %s\n", _("This plugin connects to an (SQL) database using libdbi and, optionally,"));
583 printf (" %s\n", _("executes the specified query. The first column of the first row of the")); 550 printf(" %s\n", _("executes the specified query. The first column of the first row of the"));
584 printf (" %s\n", _("result will be parsed and, in QUERY_RESULT mode, compared with the")); 551 printf(" %s\n", _("result will be parsed and, in QUERY_RESULT mode, compared with the"));
585 printf (" %s\n", _("warning and critical ranges. The result from the query has to be numeric")); 552 printf(" %s\n", _("warning and critical ranges. The result from the query has to be numeric"));
586 printf (" %s\n\n", _("(strings representing numbers are fine).")); 553 printf(" %s\n\n", _("(strings representing numbers are fine)."));
587 554
588 printf (" %s\n", _("The number and type of required DBI driver options depends on the actual")); 555 printf(" %s\n", _("The number and type of required DBI driver options depends on the actual"));
589 printf (" %s\n", _("driver. See its documentation at http://libdbi-drivers.sourceforge.net/")); 556 printf(" %s\n", _("driver. See its documentation at http://libdbi-drivers.sourceforge.net/"));
590 printf (" %s\n\n", _("for details.")); 557 printf(" %s\n\n", _("for details."));
591 558
592 printf (" %s\n", _("Examples:")); 559 printf(" %s\n", _("Examples:"));
593 printf (" check_dbi -d pgsql -o username=postgres -m QUERY_RESULT \\\n"); 560 printf(" check_dbi -d pgsql -o username=postgres -m QUERY_RESULT \\\n");
594 printf (" -q 'SELECT COUNT(*) FROM pg_stat_activity' -w 5 -c 10\n"); 561 printf(" -q 'SELECT COUNT(*) FROM pg_stat_activity' -w 5 -c 10\n");
595 printf (" Warning if more than five connections; critical if more than ten.\n\n"); 562 printf(" Warning if more than five connections; critical if more than ten.\n\n");
596 563
597 printf (" check_dbi -d mysql -H localhost -o username=user -o password=secret \\\n"); 564 printf(" check_dbi -d mysql -H localhost -o username=user -o password=secret \\\n");
598 printf (" -q 'SELECT COUNT(*) FROM logged_in_users -w 5:20 -c 0:50\n"); 565 printf(" -q 'SELECT COUNT(*) FROM logged_in_users -w 5:20 -c 0:50\n");
599 printf (" Warning if less than 5 or more than 20 users are logged in; critical\n"); 566 printf(" Warning if less than 5 or more than 20 users are logged in; critical\n");
600 printf (" if more than 50 users.\n\n"); 567 printf(" if more than 50 users.\n\n");
601 568
602 printf (" check_dbi -d firebird -o username=user -o password=secret -o dbname=foo \\\n"); 569 printf(" check_dbi -d firebird -o username=user -o password=secret -o dbname=foo \\\n");
603 printf (" -m CONN_TIME -w 0.5 -c 2\n"); 570 printf(" -m CONN_TIME -w 0.5 -c 2\n");
604 printf (" Warning if connecting to the database takes more than half of a second;\n"); 571 printf(" Warning if connecting to the database takes more than half of a second;\n");
605 printf (" critical if it takes more than 2 seconds.\n\n"); 572 printf(" critical if it takes more than 2 seconds.\n\n");
606 573
607 printf (" check_dbi -d mysql -H localhost -o username=user \\\n"); 574 printf(" check_dbi -d mysql -H localhost -o username=user \\\n");
608 printf (" -q 'SELECT concat(@@version, \" \", @@version_comment)' \\\n"); 575 printf(" -q 'SELECT concat(@@version, \" \", @@version_comment)' \\\n");
609 printf (" -r '^5\\.[01].*MySQL Enterprise Server'\n"); 576 printf(" -r '^5\\.[01].*MySQL Enterprise Server'\n");
610 printf (" Critical if the database server is not a MySQL enterprise server in either\n"); 577 printf(" Critical if the database server is not a MySQL enterprise server in either\n");
611 printf (" version 5.0.x or 5.1.x.\n\n"); 578 printf(" version 5.0.x or 5.1.x.\n\n");
612 579
613 printf (" check_dbi -d pgsql -u username=user -m SERVER_VERSION \\\n"); 580 printf(" check_dbi -d pgsql -u username=user -m SERVER_VERSION \\\n");
614 printf (" -w 090000:090099 -c 090000:090199\n"); 581 printf(" -w 090000:090099 -c 090000:090199\n");
615 printf (" Warn if the PostgreSQL server version is not 9.0.x; critical if the version\n"); 582 printf(" Warn if the PostgreSQL server version is not 9.0.x; critical if the version\n");
616 printf (" is less than 9.x or higher than 9.1.x.\n"); 583 printf(" is less than 9.x or higher than 9.1.x.\n");
617 584
618 printf (UT_SUPPORT); 585 printf(UT_SUPPORT);
619} 586}
620 587
621void 588void print_usage(void) {
622print_usage (void) 589 printf("%s\n", _("Usage:"));
623{ 590 printf("%s -d <DBI driver> [-o <DBI driver option> [...]] [-q <query>]\n", progname);
624 printf ("%s\n", _("Usage:")); 591 printf(" [-H <host>] [-c <critical range>] [-w <warning range>] [-m <metric>]\n");
625 printf ("%s -d <DBI driver> [-o <DBI driver option> [...]] [-q <query>]\n", progname); 592 printf(" [-e <string>] [-r|-R <regex>]\n");
626 printf (" [-H <host>] [-c <critical range>] [-w <warning range>] [-m <metric>]\n");
627 printf (" [-e <string>] [-r|-R <regex>]\n");
628} 593}
629 594
630#define CHECK_IGNORE_ERROR(s) \ 595#define CHECK_IGNORE_ERROR(s) \
631 do { \ 596 do { \
632 if (metric != METRIC_QUERY_RESULT) \ 597 if (metric != METRIC_QUERY_RESULT) \
633 return (s); \ 598 return (s); \
634 } while (0) 599 } while (0)
635 600
636const char * 601const char *get_field_str(dbi_conn conn, dbi_result res, unsigned short field_type) {
637get_field_str (dbi_conn conn, dbi_result res, unsigned short field_type)
638{
639 const char *str; 602 const char *str;
640 603
641 if (field_type != DBI_TYPE_STRING) { 604 if (field_type != DBI_TYPE_STRING) {
642 printf ("CRITICAL - result value is not a string\n"); 605 printf("CRITICAL - result value is not a string\n");
643 return NULL; 606 return NULL;
644 } 607 }
645 608
646 str = dbi_result_get_string_idx (res, 1); 609 str = dbi_result_get_string_idx(res, 1);
647 if ((! str) || (strcmp (str, "ERROR") == 0)) { 610 if ((!str) || (strcmp(str, "ERROR") == 0)) {
648 CHECK_IGNORE_ERROR (NULL); 611 CHECK_IGNORE_ERROR(NULL);
649 np_dbi_print_error (conn, "CRITICAL - failed to fetch string value"); 612 np_dbi_print_error(conn, "CRITICAL - failed to fetch string value");
650 return NULL; 613 return NULL;
651 } 614 }
652 615
653 if ((verbose && (type == TYPE_STRING)) || (verbose > 2)) 616 if ((verbose && (type == TYPE_STRING)) || (verbose > 2))
654 printf ("Query returned string '%s'\n", str); 617 printf("Query returned string '%s'\n", str);
655 return str; 618 return str;
656} 619}
657 620
658double 621double get_field(dbi_conn conn, dbi_result res, unsigned short *field_type) {
659get_field (dbi_conn conn, dbi_result res, unsigned short *field_type)
660{
661 double val = NAN; 622 double val = NAN;
662 623
663 if (*field_type == DBI_TYPE_INTEGER) { 624 if (*field_type == DBI_TYPE_INTEGER) {
664 val = (double)dbi_result_get_longlong_idx (res, 1); 625 val = (double)dbi_result_get_longlong_idx(res, 1);
665 } 626 } else if (*field_type == DBI_TYPE_DECIMAL) {
666 else if (*field_type == DBI_TYPE_DECIMAL) { 627 val = dbi_result_get_double_idx(res, 1);
667 val = dbi_result_get_double_idx (res, 1); 628 } else if (*field_type == DBI_TYPE_STRING) {
668 }
669 else if (*field_type == DBI_TYPE_STRING) {
670 const char *val_str; 629 const char *val_str;
671 char *endptr = NULL; 630 char *endptr = NULL;
672 631
673 val_str = get_field_str (conn, res, *field_type); 632 val_str = get_field_str(conn, res, *field_type);
674 if (! val_str) { 633 if (!val_str) {
675 CHECK_IGNORE_ERROR (NAN); 634 CHECK_IGNORE_ERROR(NAN);
676 *field_type = DBI_TYPE_ERROR; 635 *field_type = DBI_TYPE_ERROR;
677 return NAN; 636 return NAN;
678 } 637 }
679 638
680 val = strtod (val_str, &endptr); 639 val = strtod(val_str, &endptr);
681 if (endptr == val_str) { 640 if (endptr == val_str) {
682 CHECK_IGNORE_ERROR (NAN); 641 CHECK_IGNORE_ERROR(NAN);
683 printf ("CRITICAL - result value is not a numeric: %s\n", val_str); 642 printf("CRITICAL - result value is not a numeric: %s\n", val_str);
684 *field_type = DBI_TYPE_ERROR; 643 *field_type = DBI_TYPE_ERROR;
685 return NAN; 644 return NAN;
686 } 645 }
687 else if ((endptr != NULL) && (*endptr != '\0')) { 646 if ((endptr != NULL) && (*endptr != '\0')) {
688 if (verbose) 647 if (verbose)
689 printf ("Garbage after value: %s\n", endptr); 648 printf("Garbage after value: %s\n", endptr);
690 } 649 }
691 } 650 } else {
692 else { 651 CHECK_IGNORE_ERROR(NAN);
693 CHECK_IGNORE_ERROR (NAN); 652 printf("CRITICAL - cannot parse value of type %s (%i)\n",
694 printf ("CRITICAL - cannot parse value of type %s (%i)\n", 653 (*field_type == DBI_TYPE_BINARY) ? "BINARY"
695 (*field_type == DBI_TYPE_BINARY) 654 : (*field_type == DBI_TYPE_DATETIME) ? "DATETIME"
696 ? "BINARY" 655 : "<unknown>",
697 : (*field_type == DBI_TYPE_DATETIME) 656 *field_type);
698 ? "DATETIME"
699 : "<unknown>",
700 *field_type);
701 *field_type = DBI_TYPE_ERROR; 657 *field_type = DBI_TYPE_ERROR;
702 return NAN; 658 return NAN;
703 } 659 }
704 return val; 660 return val;
705} 661}
706 662
707double 663double get_query_result(dbi_conn conn, dbi_result res, const char **res_val_str, double *res_val) {
708get_query_result (dbi_conn conn, dbi_result res, const char **res_val_str, double *res_val)
709{
710 unsigned short field_type; 664 unsigned short field_type;
711 double val = NAN; 665 double val = NAN;
712 666
713 if (dbi_result_get_numrows (res) == DBI_ROW_ERROR) { 667 if (dbi_result_get_numrows(res) == DBI_ROW_ERROR) {
714 CHECK_IGNORE_ERROR (STATE_OK); 668 CHECK_IGNORE_ERROR(STATE_OK);
715 np_dbi_print_error (conn, "CRITICAL - failed to fetch rows"); 669 np_dbi_print_error(conn, "CRITICAL - failed to fetch rows");
716 return STATE_CRITICAL; 670 return STATE_CRITICAL;
717 } 671 }
718 672
719 if (dbi_result_get_numrows (res) < 1) { 673 if (dbi_result_get_numrows(res) < 1) {
720 CHECK_IGNORE_ERROR (STATE_OK); 674 CHECK_IGNORE_ERROR(STATE_OK);
721 printf ("WARNING - no rows returned\n"); 675 printf("WARNING - no rows returned\n");
722 return STATE_WARNING; 676 return STATE_WARNING;
723 } 677 }
724 678
725 if (dbi_result_get_numfields (res) == DBI_FIELD_ERROR) { 679 if (dbi_result_get_numfields(res) == DBI_FIELD_ERROR) {
726 CHECK_IGNORE_ERROR (STATE_OK); 680 CHECK_IGNORE_ERROR(STATE_OK);
727 np_dbi_print_error (conn, "CRITICAL - failed to fetch fields"); 681 np_dbi_print_error(conn, "CRITICAL - failed to fetch fields");
728 return STATE_CRITICAL; 682 return STATE_CRITICAL;
729 } 683 }
730 684
731 if (dbi_result_get_numfields (res) < 1) { 685 if (dbi_result_get_numfields(res) < 1) {
732 CHECK_IGNORE_ERROR (STATE_OK); 686 CHECK_IGNORE_ERROR(STATE_OK);
733 printf ("WARNING - no fields returned\n"); 687 printf("WARNING - no fields returned\n");
734 return STATE_WARNING; 688 return STATE_WARNING;
735 } 689 }
736 690
737 if (dbi_result_first_row (res) != 1) { 691 if (dbi_result_first_row(res) != 1) {
738 CHECK_IGNORE_ERROR (STATE_OK); 692 CHECK_IGNORE_ERROR(STATE_OK);
739 np_dbi_print_error (conn, "CRITICAL - failed to fetch first row"); 693 np_dbi_print_error(conn, "CRITICAL - failed to fetch first row");
740 return STATE_CRITICAL; 694 return STATE_CRITICAL;
741 } 695 }
742 696
743 field_type = dbi_result_get_field_type_idx (res, 1); 697 field_type = dbi_result_get_field_type_idx(res, 1);
744 if (field_type != DBI_TYPE_ERROR) { 698 if (field_type != DBI_TYPE_ERROR) {
745 if (type == TYPE_STRING) 699 if (type == TYPE_STRING)
746 /* the value will be freed in dbi_result_free */ 700 /* the value will be freed in dbi_result_free */
747 *res_val_str = strdup (get_field_str (conn, res, field_type)); 701 *res_val_str = strdup(get_field_str(conn, res, field_type));
748 else 702 else
749 val = get_field (conn, res, &field_type); 703 val = get_field(conn, res, &field_type);
750 } 704 }
751 705
752 *res_val = val; 706 *res_val = val;
753 707
754 if (field_type == DBI_TYPE_ERROR) { 708 if (field_type == DBI_TYPE_ERROR) {
755 CHECK_IGNORE_ERROR (STATE_OK); 709 CHECK_IGNORE_ERROR(STATE_OK);
756 np_dbi_print_error (conn, "CRITICAL - failed to fetch data"); 710 np_dbi_print_error(conn, "CRITICAL - failed to fetch data");
757 return STATE_CRITICAL; 711 return STATE_CRITICAL;
758 } 712 }
759 713
760 dbi_result_free (res); 714 dbi_result_free(res);
761 return STATE_OK; 715 return STATE_OK;
762} 716}
763 717
764#undef CHECK_IGNORE_ERROR 718#undef CHECK_IGNORE_ERROR
765 719
766int 720int do_query(dbi_conn conn, const char **res_val_str, double *res_val, double *res_time) {
767do_query (dbi_conn conn, const char **res_val_str, double *res_val, double *res_time)
768{
769 dbi_result res; 721 dbi_result res;
770 722
771 struct timeval timeval_start, timeval_end; 723 struct timeval timeval_start;
724 struct timeval timeval_end;
772 int status = STATE_OK; 725 int status = STATE_OK;
773 726
774 assert (np_dbi_query); 727 assert(np_dbi_query);
775 728
776 if (verbose) 729 if (verbose)
777 printf ("Executing query '%s'\n", np_dbi_query); 730 printf("Executing query '%s'\n", np_dbi_query);
778 731
779 gettimeofday (&timeval_start, NULL); 732 gettimeofday(&timeval_start, NULL);
780 733
781 res = dbi_conn_query (conn, np_dbi_query); 734 res = dbi_conn_query(conn, np_dbi_query);
782 if (! res) { 735 if (!res) {
783 np_dbi_print_error (conn, "CRITICAL - failed to execute query '%s'", np_dbi_query); 736 np_dbi_print_error(conn, "CRITICAL - failed to execute query '%s'", np_dbi_query);
784 return STATE_CRITICAL; 737 return STATE_CRITICAL;
785 } 738 }
786 739
787 status = get_query_result (conn, res, res_val_str, res_val); 740 status = get_query_result(conn, res, res_val_str, res_val);
788 741
789 gettimeofday (&timeval_end, NULL); 742 gettimeofday(&timeval_end, NULL);
790 *res_time = timediff (timeval_start, timeval_end); 743 *res_time = timediff(timeval_start, timeval_end);
791 744
792 if (verbose) 745 if (verbose)
793 printf ("Time elapsed: %f\n", *res_time); 746 printf("Time elapsed: %f\n", *res_time);
794 747
795 return status; 748 return status;
796} 749}
797 750
798double 751double timediff(struct timeval start, struct timeval end) {
799timediff (struct timeval start, struct timeval end)
800{
801 double diff; 752 double diff;
802 753
803 while (start.tv_usec > end.tv_usec) { 754 while (start.tv_usec > end.tv_usec) {
804 --end.tv_sec; 755 --end.tv_sec;
805 end.tv_usec += 1000000; 756 end.tv_usec += 1000000;
806 } 757 }
807 diff = (double)(end.tv_sec - start.tv_sec) 758 diff = (double)(end.tv_sec - start.tv_sec) + (double)(end.tv_usec - start.tv_usec) / 1000000.0;
808 + (double)(end.tv_usec - start.tv_usec) / 1000000.0;
809 return diff; 759 return diff;
810} 760}
811 761
812void 762void np_dbi_print_error(dbi_conn conn, char *fmt, ...) {
813np_dbi_print_error (dbi_conn conn, char *fmt, ...)
814{
815 const char *errmsg = NULL; 763 const char *errmsg = NULL;
816 va_list ap; 764 va_list ap;
817 765
818 va_start (ap, fmt); 766 va_start(ap, fmt);
819 767
820 dbi_conn_error (conn, &errmsg); 768 dbi_conn_error(conn, &errmsg);
821 vprintf (fmt, ap); 769 vprintf(fmt, ap);
822 printf (": %s\n", errmsg); 770 printf(": %s\n", errmsg);
823 771
824 va_end (ap); 772 va_end(ap);
825} 773}
826
diff --git a/plugins/check_dig.c b/plugins/check_dig.c
index be7a6101..2bbd1e05 100644
--- a/plugins/check_dig.c
+++ b/plugins/check_dig.c
@@ -1,30 +1,30 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring check_dig plugin 3 * Monitoring check_dig plugin
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 2002-2008 Monitoring Plugins Development Team 6 * Copyright (c) 2002-2024 Monitoring Plugins Development Team
7* 7 *
8* Description: 8 * Description:
9* 9 *
10* This file contains the check_dig plugin 10 * This file contains the check_dig plugin
11* 11 *
12* 12 *
13* This program is free software: you can redistribute it and/or modify 13 * This program is free software: you can redistribute it and/or modify
14* it under the terms of the GNU General Public License as published by 14 * it under the terms of the GNU General Public License as published by
15* the Free Software Foundation, either version 3 of the License, or 15 * the Free Software Foundation, either version 3 of the License, or
16* (at your option) any later version. 16 * (at your option) any later version.
17* 17 *
18* This program is distributed in the hope that it will be useful, 18 * This program is distributed in the hope that it will be useful,
19* but WITHOUT ANY WARRANTY; without even the implied warranty of 19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21* GNU General Public License for more details. 21 * GNU General Public License for more details.
22* 22 *
23* You should have received a copy of the GNU General Public License 23 * You should have received a copy of the GNU General Public License
24* along with this program. If not, see <http://www.gnu.org/licenses/>. 24 * along with this program. If not, see <http://www.gnu.org/licenses/>.
25* 25 *
26* 26 *
27*****************************************************************************/ 27 *****************************************************************************/
28 28
29/* Hackers note: 29/* Hackers note:
30 * There are typecasts to (char *) from _("foo bar") in this file. 30 * There are typecasts to (char *) from _("foo bar") in this file.
@@ -33,7 +33,7 @@
33 * because on some architectures those strings are in non-writable memory */ 33 * because on some architectures those strings are in non-writable memory */
34 34
35const char *progname = "check_dig"; 35const char *progname = "check_dig";
36const char *copyright = "2002-2008"; 36const char *copyright = "2002-2024";
37const char *email = "devel@monitoring-plugins.org"; 37const char *email = "devel@monitoring-plugins.org";
38 38
39#include "common.h" 39#include "common.h"
@@ -41,340 +41,312 @@ const char *email = "devel@monitoring-plugins.org";
41#include "utils.h" 41#include "utils.h"
42#include "runcmd.h" 42#include "runcmd.h"
43 43
44int process_arguments (int, char **); 44static int process_arguments(int /*argc*/, char ** /*argv*/);
45int validate_arguments (void); 45static int validate_arguments(void);
46void print_help (void); 46static void print_help(void);
47void print_usage (void); 47void print_usage(void);
48 48
49#define UNDEFINED 0 49#define UNDEFINED 0
50#define DEFAULT_PORT 53 50#define DEFAULT_PORT 53
51#define DEFAULT_TRIES 2 51#define DEFAULT_TRIES 2
52 52
53char *query_address = NULL; 53static char *query_address = NULL;
54char *record_type = "A"; 54static char *record_type = "A";
55char *expected_address = NULL; 55static char *expected_address = NULL;
56char *dns_server = NULL; 56static char *dns_server = NULL;
57char *dig_args = ""; 57static char *dig_args = "";
58char *query_transport = ""; 58static char *query_transport = "";
59bool verbose = false; 59static bool verbose = false;
60int server_port = DEFAULT_PORT; 60static int server_port = DEFAULT_PORT;
61int number_tries = DEFAULT_TRIES; 61static int number_tries = DEFAULT_TRIES;
62double warning_interval = UNDEFINED; 62static double warning_interval = UNDEFINED;
63double critical_interval = UNDEFINED; 63static double critical_interval = UNDEFINED;
64struct timeval tv; 64static struct timeval tv;
65 65
66int 66int main(int argc, char **argv) {
67main (int argc, char **argv) 67 char *command_line;
68{ 68 output chld_out;
69 char *command_line; 69 output chld_err;
70 output chld_out, chld_err; 70 char *msg = NULL;
71 char *msg = NULL; 71 size_t i;
72 size_t i; 72 char *t;
73 char *t; 73 long microsec;
74 long microsec; 74 double elapsed_time;
75 double elapsed_time; 75 int result = STATE_UNKNOWN;
76 int result = STATE_UNKNOWN; 76 int timeout_interval_dig;
77 int timeout_interval_dig; 77
78 78 setlocale(LC_ALL, "");
79 setlocale (LC_ALL, ""); 79 bindtextdomain(PACKAGE, LOCALEDIR);
80 bindtextdomain (PACKAGE, LOCALEDIR); 80 textdomain(PACKAGE);
81 textdomain (PACKAGE); 81
82 82 /* Set signal handling and alarm */
83 /* Set signal handling and alarm */ 83 if (signal(SIGALRM, runcmd_timeout_alarm_handler) == SIG_ERR)
84 if (signal (SIGALRM, runcmd_timeout_alarm_handler) == SIG_ERR) 84 usage_va(_("Cannot catch SIGALRM"));
85 usage_va(_("Cannot catch SIGALRM")); 85
86 86 /* Parse extra opts if any */
87 /* Parse extra opts if any */ 87 argv = np_extra_opts(&argc, argv, progname);
88 argv=np_extra_opts (&argc, argv, progname); 88
89 89 if (process_arguments(argc, argv) == ERROR)
90 if (process_arguments (argc, argv) == ERROR) 90 usage_va(_("Could not parse arguments"));
91 usage_va(_("Could not parse arguments")); 91
92 92 /* dig applies the timeout to each try, so we need to work around this */
93 /* dig applies the timeout to each try, so we need to work around this */ 93 timeout_interval_dig = timeout_interval / number_tries + number_tries;
94 timeout_interval_dig = timeout_interval / number_tries + number_tries; 94
95 95 /* get the command to run */
96 /* get the command to run */ 96 xasprintf(&command_line, "%s %s %s -p %d @%s %s %s +retry=%d +time=%d", PATH_TO_DIG, dig_args, query_transport, server_port, dns_server,
97 xasprintf (&command_line, "%s %s %s -p %d @%s %s %s +retry=%d +time=%d", 97 query_address, record_type, number_tries, timeout_interval_dig);
98 PATH_TO_DIG, dig_args, query_transport, server_port, dns_server, query_address, record_type, number_tries, timeout_interval_dig); 98
99 99 alarm(timeout_interval);
100 alarm (timeout_interval); 100 gettimeofday(&tv, NULL);
101 gettimeofday (&tv, NULL); 101
102 102 if (verbose) {
103 if (verbose) { 103 printf("%s\n", command_line);
104 printf ("%s\n", command_line); 104 if (expected_address != NULL) {
105 if(expected_address != NULL) { 105 printf(_("Looking for: '%s'\n"), expected_address);
106 printf (_("Looking for: '%s'\n"), expected_address); 106 } else {
107 } else { 107 printf(_("Looking for: '%s'\n"), query_address);
108 printf (_("Looking for: '%s'\n"), query_address); 108 }
109 } 109 }
110 } 110
111 111 /* run the command */
112 /* run the command */ 112 if (np_runcmd(command_line, &chld_out, &chld_err, 0) != 0) {
113 if(np_runcmd(command_line, &chld_out, &chld_err, 0) != 0) { 113 result = STATE_WARNING;
114 result = STATE_WARNING; 114 msg = (char *)_("dig returned an error status");
115 msg = (char *)_("dig returned an error status"); 115 }
116 } 116
117 117 for (i = 0; i < chld_out.lines; i++) {
118 for(i = 0; i < chld_out.lines; i++) { 118 /* the server is responding, we just got the host name... */
119 /* the server is responding, we just got the host name... */ 119 if (strstr(chld_out.line[i], ";; ANSWER SECTION:")) {
120 if (strstr (chld_out.line[i], ";; ANSWER SECTION:")) { 120
121 121 /* loop through the whole 'ANSWER SECTION' */
122 /* loop through the whole 'ANSWER SECTION' */ 122 for (; i < chld_out.lines; i++) {
123 for(; i < chld_out.lines; i++) { 123 /* get the host address */
124 /* get the host address */ 124 if (verbose)
125 if (verbose) 125 printf("%s\n", chld_out.line[i]);
126 printf ("%s\n", chld_out.line[i]); 126
127 127 if (strcasestr(chld_out.line[i], (expected_address == NULL ? query_address : expected_address)) != NULL) {
128 if (strcasestr (chld_out.line[i], (expected_address == NULL ? query_address : expected_address)) != NULL) { 128 msg = chld_out.line[i];
129 msg = chld_out.line[i]; 129 result = STATE_OK;
130 result = STATE_OK; 130
131 131 /* Translate output TAB -> SPACE */
132 /* Translate output TAB -> SPACE */ 132 t = msg;
133 t = msg; 133 while ((t = strchr(t, '\t')) != NULL)
134 while ((t = strchr(t, '\t')) != NULL) *t = ' '; 134 *t = ' ';
135 break; 135 break;
136 } 136 }
137 } 137 }
138 138
139 if (result == STATE_UNKNOWN) { 139 if (result == STATE_UNKNOWN) {
140 msg = (char *)_("Server not found in ANSWER SECTION"); 140 msg = (char *)_("Server not found in ANSWER SECTION");
141 result = STATE_WARNING; 141 result = STATE_WARNING;
142 } 142 }
143 143
144 /* we found the answer section, so break out of the loop */ 144 /* we found the answer section, so break out of the loop */
145 break; 145 break;
146 } 146 }
147 } 147 }
148 148
149 if (result == STATE_UNKNOWN) { 149 if (result == STATE_UNKNOWN) {
150 msg = (char *)_("No ANSWER SECTION found"); 150 msg = (char *)_("No ANSWER SECTION found");
151 result = STATE_CRITICAL; 151 result = STATE_CRITICAL;
152 } 152 }
153 153
154 /* If we get anything on STDERR, at least set warning */ 154 /* If we get anything on STDERR, at least set warning */
155 if(chld_err.buflen > 0) { 155 if (chld_err.buflen > 0) {
156 result = max_state(result, STATE_WARNING); 156 result = max_state(result, STATE_WARNING);
157 if(!msg) for(i = 0; i < chld_err.lines; i++) { 157 if (!msg)
158 msg = strchr(chld_err.line[0], ':'); 158 for (i = 0; i < chld_err.lines; i++) {
159 if(msg) { 159 msg = strchr(chld_err.line[0], ':');
160 msg++; 160 if (msg) {
161 break; 161 msg++;
162 } 162 break;
163 } 163 }
164 } 164 }
165 165 }
166 microsec = deltime (tv); 166
167 elapsed_time = (double)microsec / 1.0e6; 167 microsec = deltime(tv);
168 168 elapsed_time = (double)microsec / 1.0e6;
169 if (critical_interval > UNDEFINED && elapsed_time > critical_interval) 169
170 result = STATE_CRITICAL; 170 if (critical_interval > UNDEFINED && elapsed_time > critical_interval)
171 171 result = STATE_CRITICAL;
172 else if (warning_interval > UNDEFINED && elapsed_time > warning_interval) 172
173 result = STATE_WARNING; 173 else if (warning_interval > UNDEFINED && elapsed_time > warning_interval)
174 174 result = STATE_WARNING;
175 printf ("DNS %s - %.3f seconds response time (%s)|%s\n", 175
176 state_text (result), elapsed_time, 176 printf("DNS %s - %.3f seconds response time (%s)|%s\n", state_text(result), elapsed_time,
177 msg ? msg : _("Probably a non-existent host/domain"), 177 msg ? msg : _("Probably a non-existent host/domain"),
178 fperfdata("time", elapsed_time, "s", 178 fperfdata("time", elapsed_time, "s", (warning_interval > UNDEFINED ? true : false), warning_interval,
179 (warning_interval>UNDEFINED ? true:false), 179 (critical_interval > UNDEFINED ? true : false), critical_interval, true, 0, false, 0));
180 warning_interval, 180 return result;
181 (critical_interval>UNDEFINED ? true:false),
182 critical_interval,
183 true, 0, false, 0));
184 return result;
185} 181}
186 182
187
188
189/* process command-line arguments */ 183/* process command-line arguments */
190int 184int process_arguments(int argc, char **argv) {
191process_arguments (int argc, char **argv) 185 int c;
192{ 186
193 int c; 187 int option = 0;
194 188 static struct option longopts[] = {{"hostname", required_argument, 0, 'H'},
195 int option = 0; 189 {"query_address", required_argument, 0, 'l'},
196 static struct option longopts[] = { 190 {"warning", required_argument, 0, 'w'},
197 {"hostname", required_argument, 0, 'H'}, 191 {"critical", required_argument, 0, 'c'},
198 {"query_address", required_argument, 0, 'l'}, 192 {"timeout", required_argument, 0, 't'},
199 {"warning", required_argument, 0, 'w'}, 193 {"dig-arguments", required_argument, 0, 'A'},
200 {"critical", required_argument, 0, 'c'}, 194 {"verbose", no_argument, 0, 'v'},
201 {"timeout", required_argument, 0, 't'}, 195 {"version", no_argument, 0, 'V'},
202 {"dig-arguments", required_argument, 0, 'A'}, 196 {"help", no_argument, 0, 'h'},
203 {"verbose", no_argument, 0, 'v'}, 197 {"record_type", required_argument, 0, 'T'},
204 {"version", no_argument, 0, 'V'}, 198 {"expected_address", required_argument, 0, 'a'},
205 {"help", no_argument, 0, 'h'}, 199 {"port", required_argument, 0, 'p'},
206 {"record_type", required_argument, 0, 'T'}, 200 {"use-ipv4", no_argument, 0, '4'},
207 {"expected_address", required_argument, 0, 'a'}, 201 {"use-ipv6", no_argument, 0, '6'},
208 {"port", required_argument, 0, 'p'}, 202 {0, 0, 0, 0}};
209 {"use-ipv4", no_argument, 0, '4'}, 203
210 {"use-ipv6", no_argument, 0, '6'}, 204 if (argc < 2)
211 {0, 0, 0, 0} 205 return ERROR;
212 }; 206
213 207 while (1) {
214 if (argc < 2) 208 c = getopt_long(argc, argv, "hVvt:l:H:w:c:T:p:a:A:46", longopts, &option);
215 return ERROR; 209
216 210 if (c == -1 || c == EOF)
217 while (1) { 211 break;
218 c = getopt_long (argc, argv, "hVvt:l:H:w:c:T:p:a:A:46", longopts, &option); 212
219 213 switch (c) {
220 if (c == -1 || c == EOF) 214 case 'h': /* help */
221 break; 215 print_help();
222 216 exit(STATE_UNKNOWN);
223 switch (c) { 217 case 'V': /* version */
224 case 'h': /* help */ 218 print_revision(progname, NP_VERSION);
225 print_help (); 219 exit(STATE_UNKNOWN);
226 exit (STATE_UNKNOWN); 220 case 'H': /* hostname */
227 case 'V': /* version */ 221 host_or_die(optarg);
228 print_revision (progname, NP_VERSION); 222 dns_server = optarg;
229 exit (STATE_UNKNOWN); 223 break;
230 case 'H': /* hostname */ 224 case 'p': /* server port */
231 host_or_die(optarg); 225 if (is_intpos(optarg)) {
232 dns_server = optarg; 226 server_port = atoi(optarg);
233 break; 227 } else {
234 case 'p': /* server port */ 228 usage_va(_("Port must be a positive integer - %s"), optarg);
235 if (is_intpos (optarg)) { 229 }
236 server_port = atoi (optarg); 230 break;
237 } 231 case 'l': /* address to lookup */
238 else { 232 query_address = optarg;
239 usage_va(_("Port must be a positive integer - %s"), optarg); 233 break;
240 } 234 case 'w': /* warning */
241 break; 235 if (is_nonnegative(optarg)) {
242 case 'l': /* address to lookup */ 236 warning_interval = strtod(optarg, NULL);
243 query_address = optarg; 237 } else {
244 break; 238 usage_va(_("Warning interval must be a positive integer - %s"), optarg);
245 case 'w': /* warning */ 239 }
246 if (is_nonnegative (optarg)) { 240 break;
247 warning_interval = strtod (optarg, NULL); 241 case 'c': /* critical */
248 } 242 if (is_nonnegative(optarg)) {
249 else { 243 critical_interval = strtod(optarg, NULL);
250 usage_va(_("Warning interval must be a positive integer - %s"), optarg); 244 } else {
251 } 245 usage_va(_("Critical interval must be a positive integer - %s"), optarg);
252 break; 246 }
253 case 'c': /* critical */ 247 break;
254 if (is_nonnegative (optarg)) { 248 case 't': /* timeout */
255 critical_interval = strtod (optarg, NULL); 249 if (is_intnonneg(optarg)) {
256 } 250 timeout_interval = atoi(optarg);
257 else { 251 } else {
258 usage_va(_("Critical interval must be a positive integer - %s"), optarg); 252 usage_va(_("Timeout interval must be a positive integer - %s"), optarg);
259 } 253 }
260 break; 254 break;
261 case 't': /* timeout */ 255 case 'A': /* dig arguments */
262 if (is_intnonneg (optarg)) { 256 dig_args = strdup(optarg);
263 timeout_interval = atoi (optarg); 257 break;
264 } 258 case 'v': /* verbose */
265 else { 259 verbose = true;
266 usage_va(_("Timeout interval must be a positive integer - %s"), optarg); 260 break;
267 } 261 case 'T':
268 break; 262 record_type = optarg;
269 case 'A': /* dig arguments */ 263 break;
270 dig_args = strdup(optarg); 264 case 'a':
271 break; 265 expected_address = optarg;
272 case 'v': /* verbose */ 266 break;
273 verbose = true; 267 case '4':
274 break; 268 query_transport = "-4";
275 case 'T': 269 break;
276 record_type = optarg; 270 case '6':
277 break; 271 query_transport = "-6";
278 case 'a': 272 break;
279 expected_address = optarg; 273 default: /* usage5 */
280 break; 274 usage5();
281 case '4': 275 }
282 query_transport = "-4"; 276 }
283 break; 277
284 case '6': 278 c = optind;
285 query_transport = "-6"; 279 if (dns_server == NULL) {
286 break; 280 if (c < argc) {
287 default: /* usage5 */ 281 host_or_die(argv[c]);
288 usage5(); 282 dns_server = argv[c];
289 } 283 } else {
290 } 284 if (strcmp(query_transport, "-6") == 0)
291 285 dns_server = strdup("::1");
292 c = optind; 286 else
293 if (dns_server == NULL) { 287 dns_server = strdup("127.0.0.1");
294 if (c < argc) { 288 }
295 host_or_die(argv[c]); 289 }
296 dns_server = argv[c]; 290
297 } 291 return validate_arguments();
298 else {
299 if (strcmp(query_transport,"-6") == 0)
300 dns_server = strdup("::1");
301 else
302 dns_server = strdup ("127.0.0.1");
303 }
304 }
305
306 return validate_arguments ();
307} 292}
308 293
309 294int validate_arguments(void) {
310 295 if (query_address != NULL)
311int 296 return OK;
312validate_arguments (void) 297 return ERROR;
313{
314 if (query_address != NULL)
315 return OK;
316 else
317 return ERROR;
318} 298}
319 299
300void print_help(void) {
301 char *myport;
320 302
303 xasprintf(&myport, "%d", DEFAULT_PORT);
321 304
322void 305 print_revision(progname, NP_VERSION);
323print_help (void)
324{
325 char *myport;
326 306
327 xasprintf (&myport, "%d", DEFAULT_PORT); 307 printf("Copyright (c) 2000 Karl DeBisschop <kdebisschop@users.sourceforge.net>\n");
308 printf(COPYRIGHT, copyright, email);
328 309
329 print_revision (progname, NP_VERSION); 310 printf(_("This plugin tests the DNS service on the specified host using dig"));
330 311
331 printf ("Copyright (c) 2000 Karl DeBisschop <kdebisschop@users.sourceforge.net>\n"); 312 printf("\n\n");
332 printf (COPYRIGHT, copyright, email);
333 313
334 printf (_("This plugin tests the DNS service on the specified host using dig")); 314 print_usage();
335 315
336 printf ("\n\n"); 316 printf(UT_HELP_VRSN);
337 317
338 print_usage (); 318 printf(UT_EXTRA_OPTS);
339 319
340 printf (UT_HELP_VRSN); 320 printf(UT_HOST_PORT, 'p', myport);
341 321
342 printf (UT_EXTRA_OPTS); 322 printf(" %s\n", "-4, --use-ipv4");
323 printf(" %s\n", _("Force dig to only use IPv4 query transport"));
324 printf(" %s\n", "-6, --use-ipv6");
325 printf(" %s\n", _("Force dig to only use IPv6 query transport"));
326 printf(" %s\n", "-l, --query_address=STRING");
327 printf(" %s\n", _("Machine name to lookup"));
328 printf(" %s\n", "-T, --record_type=STRING");
329 printf(" %s\n", _("Record type to lookup (default: A)"));
330 printf(" %s\n", "-a, --expected_address=STRING");
331 printf(" %s\n", _("An address expected to be in the answer section. If not set, uses whatever"));
332 printf(" %s\n", _("was in -l"));
333 printf(" %s\n", "-A, --dig-arguments=STRING");
334 printf(" %s\n", _("Pass STRING as argument(s) to dig"));
335 printf(UT_WARN_CRIT);
336 printf(UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
337 printf(UT_VERBOSE);
343 338
344 printf (UT_HOST_PORT, 'p', myport); 339 printf("\n");
340 printf("%s\n", _("Examples:"));
341 printf(" %s\n", "check_dig -H DNSSERVER -l www.example.com -A \"+tcp\"");
342 printf(" %s\n", "This will send a tcp query to DNSSERVER for www.example.com");
345 343
346 printf (" %s\n","-4, --use-ipv4"); 344 printf(UT_SUPPORT);
347 printf (" %s\n",_("Force dig to only use IPv4 query transport"));
348 printf (" %s\n","-6, --use-ipv6");
349 printf (" %s\n",_("Force dig to only use IPv6 query transport"));
350 printf (" %s\n","-l, --query_address=STRING");
351 printf (" %s\n",_("Machine name to lookup"));
352 printf (" %s\n","-T, --record_type=STRING");
353 printf (" %s\n",_("Record type to lookup (default: A)"));
354 printf (" %s\n","-a, --expected_address=STRING");
355 printf (" %s\n",_("An address expected to be in the answer section. If not set, uses whatever"));
356 printf (" %s\n",_("was in -l"));
357 printf (" %s\n","-A, --dig-arguments=STRING");
358 printf (" %s\n",_("Pass STRING as argument(s) to dig"));
359 printf (UT_WARN_CRIT);
360 printf (UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
361 printf (UT_VERBOSE);
362
363 printf ("\n");
364 printf ("%s\n", _("Examples:"));
365 printf (" %s\n", "check_dig -H DNSSERVER -l www.example.com -A \"+tcp\"");
366 printf (" %s\n", "This will send a tcp query to DNSSERVER for www.example.com");
367
368 printf (UT_SUPPORT);
369} 345}
370 346
371 347void print_usage(void) {
372 348 printf("%s\n", _("Usage:"));
373void 349 printf("%s -l <query_address> [-H <host>] [-p <server port>]\n", progname);
374print_usage (void) 350 printf(" [-T <query type>] [-w <warning interval>] [-c <critical interval>]\n");
375{ 351 printf(" [-t <timeout>] [-a <expected answer address>] [-v]\n");
376 printf ("%s\n", _("Usage:"));
377 printf ("%s -l <query_address> [-H <host>] [-p <server port>]\n", progname);
378 printf (" [-T <query type>] [-w <warning interval>] [-c <critical interval>]\n");
379 printf (" [-t <timeout>] [-a <expected answer address>] [-v]\n");
380} 352}
diff --git a/plugins/check_disk.c b/plugins/check_disk.c
index c6bba243..d1d1b92a 100644
--- a/plugins/check_disk.c
+++ b/plugins/check_disk.c
@@ -1,43 +1,42 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring check_disk plugin 3 * Monitoring check_disk plugin
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 1999-2008 Monitoring Plugins Development Team 6 * Copyright (c) 1999-2024 Monitoring Plugins Development Team
7* 7 *
8* Description: 8 * Description:
9* 9 *
10* This file contains the check_disk plugin 10 * This file contains the check_disk plugin
11* 11 *
12* 12 *
13* This program is free software: you can redistribute it and/or modify 13 * This program is free software: you can redistribute it and/or modify
14* it under the terms of the GNU General Public License as published by 14 * it under the terms of the GNU General Public License as published by
15* the Free Software Foundation, either version 3 of the License, or 15 * the Free Software Foundation, either version 3 of the License, or
16* (at your option) any later version. 16 * (at your option) any later version.
17* 17 *
18* This program is distributed in the hope that it will be useful, 18 * This program is distributed in the hope that it will be useful,
19* but WITHOUT ANY WARRANTY; without even the implied warranty of 19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21* GNU General Public License for more details. 21 * GNU General Public License for more details.
22* 22 *
23* You should have received a copy of the GNU General Public License 23 * You should have received a copy of the GNU General Public License
24* along with this program. If not, see <http://www.gnu.org/licenses/>. 24 * along with this program. If not, see <http://www.gnu.org/licenses/>.
25* 25 *
26* 26 *
27*****************************************************************************/ 27 *****************************************************************************/
28 28
29const char *progname = "check_disk"; 29const char *progname = "check_disk";
30const char *program_name = "check_disk"; /* Required for coreutils libs */ 30const char *program_name = "check_disk"; /* Required for coreutils libs */
31const char *copyright = "1999-2008"; 31const char *copyright = "1999-2024";
32const char *email = "devel@monitoring-plugins.org"; 32const char *email = "devel@monitoring-plugins.org";
33 33
34
35#include "common.h" 34#include "common.h"
36#ifdef HAVE_SYS_STAT_H 35#ifdef HAVE_SYS_STAT_H
37# include <sys/stat.h> 36# include <sys/stat.h>
38#endif 37#endif
39#if HAVE_INTTYPES_H 38#if HAVE_INTTYPES_H
40# include <inttypes.h> 39# include <inttypes.h>
41#endif 40#endif
42#include <assert.h> 41#include <assert.h>
43#include "popen.h" 42#include "popen.h"
@@ -46,16 +45,16 @@ const char *email = "devel@monitoring-plugins.org";
46#include <stdarg.h> 45#include <stdarg.h>
47#include "fsusage.h" 46#include "fsusage.h"
48#include "mountlist.h" 47#include "mountlist.h"
49#include "intprops.h" /* necessary for TYPE_MAXIMUM */ 48#include <float.h>
50#if HAVE_LIMITS_H 49#if HAVE_LIMITS_H
51# include <limits.h> 50# include <limits.h>
52#endif 51#endif
53#include "regex.h" 52#include "regex.h"
54 53
55#ifdef __CYGWIN__ 54#ifdef __CYGWIN__
56# include <windows.h> 55# include <windows.h>
57# undef ERROR 56# undef ERROR
58# define ERROR -1 57# define ERROR -1
59#endif 58#endif
60 59
61/* If nonzero, show even filesystems with zero size or 60/* If nonzero, show even filesystems with zero size or
@@ -108,1062 +107,1007 @@ static struct mount_entry *mount_list;
108 107
109/* For long options that have no equivalent short option, use a 108/* For long options that have no equivalent short option, use a
110 non-character as a pseudo short option, starting with CHAR_MAX + 1. */ 109 non-character as a pseudo short option, starting with CHAR_MAX + 1. */
111enum 110enum {
112{ 111 SYNC_OPTION = CHAR_MAX + 1,
113 SYNC_OPTION = CHAR_MAX + 1, 112 NO_SYNC_OPTION,
114 NO_SYNC_OPTION, 113 BLOCK_SIZE_OPTION
115 BLOCK_SIZE_OPTION
116}; 114};
117 115
118#ifdef _AIX 116#ifdef _AIX
119#pragma alloca 117# pragma alloca
120#endif 118#endif
121 119
122int process_arguments (int, char **); 120static int process_arguments(int /*argc*/, char ** /*argv*/);
123void print_path (const char *mypath); 121static void set_all_thresholds(struct parameter_list *path);
124void set_all_thresholds (struct parameter_list *path); 122static void print_help(void);
125int validate_arguments (uintmax_t, uintmax_t, double, double, double, double, char *); 123void print_usage(void);
126void print_help (void); 124static double calculate_percent(uintmax_t, uintmax_t);
127void print_usage (void); 125static bool stat_path(struct parameter_list *p);
128double calculate_percent(uintmax_t, uintmax_t); 126static void get_stats(struct parameter_list *p, struct fs_usage *fsp);
129bool stat_path (struct parameter_list *p); 127static void get_path_stats(struct parameter_list *p, struct fs_usage *fsp);
130void get_stats (struct parameter_list *p, struct fs_usage *fsp); 128
131void get_path_stats (struct parameter_list *p, struct fs_usage *fsp); 129static char *units;
132 130static uintmax_t mult = 1024 * 1024;
133char *exclude_device; 131static int verbose = 0;
134char *units; 132static bool erronly = false;
135uintmax_t mult = 1024 * 1024; 133static bool display_mntp = false;
136int verbose = 0; 134static bool exact_match = false;
137bool erronly = false; 135static bool ignore_missing = false;
138bool display_mntp = false; 136static bool freespace_ignore_reserved = false;
139bool exact_match = false; 137static bool display_inodes_perfdata = false;
140bool ignore_missing = false; 138static char *warn_freespace_units = NULL;
141bool freespace_ignore_reserved = false; 139static char *crit_freespace_units = NULL;
142bool display_inodes_perfdata = false; 140static char *warn_freespace_percent = NULL;
143char *warn_freespace_units = NULL; 141static char *crit_freespace_percent = NULL;
144char *crit_freespace_units = NULL; 142static char *warn_usedspace_units = NULL;
145char *warn_freespace_percent = NULL; 143static char *crit_usedspace_units = NULL;
146char *crit_freespace_percent = NULL; 144static char *warn_usedspace_percent = NULL;
147char *warn_usedspace_units = NULL; 145static char *crit_usedspace_percent = NULL;
148char *crit_usedspace_units = NULL; 146static char *warn_usedinodes_percent = NULL;
149char *warn_usedspace_percent = NULL; 147static char *crit_usedinodes_percent = NULL;
150char *crit_usedspace_percent = NULL; 148static char *warn_freeinodes_percent = NULL;
151char *warn_usedinodes_percent = NULL; 149static char *crit_freeinodes_percent = NULL;
152char *crit_usedinodes_percent = NULL; 150static bool path_selected = false;
153char *warn_freeinodes_percent = NULL; 151static bool path_ignored = false;
154char *crit_freeinodes_percent = NULL; 152static char *group = NULL;
155bool path_selected = false; 153static struct stat *stat_buf;
156bool path_ignored = false; 154static struct name_list *seen = NULL;
157char *group = NULL; 155
158struct stat *stat_buf; 156int main(int argc, char **argv) {
159struct name_list *seen = NULL; 157 int result = STATE_UNKNOWN;
160 158 int disk_result = STATE_UNKNOWN;
161 159 char *output;
162int 160 char *ignored;
163main (int argc, char **argv) 161 char *details;
164{ 162 char *perf;
165 int result = STATE_UNKNOWN; 163 char *perf_ilabel;
166 int disk_result = STATE_UNKNOWN; 164 char *preamble = " - free space:";
167 char *output; 165 char *ignored_preamble = " - ignored paths:";
168 char *ignored; 166 char *flag_header;
169 char *details; 167 int temp_result;
170 char *perf; 168
171 char *perf_ilabel; 169 struct mount_entry *me;
172 char *preamble = " - free space:"; 170 struct fs_usage fsp;
173 char *ignored_preamble = " - ignored paths:"; 171 struct parameter_list *temp_list;
174 char *flag_header; 172 struct parameter_list *path;
175 int temp_result;
176
177 struct mount_entry *me;
178 struct fs_usage fsp;
179 struct parameter_list *temp_list, *path;
180 173
181#ifdef __CYGWIN__ 174#ifdef __CYGWIN__
182 char mountdir[32]; 175 char mountdir[32];
183#endif 176#endif
184 177
185 output = strdup (""); 178 output = strdup("");
186 ignored = strdup (""); 179 ignored = strdup("");
187 details = strdup (""); 180 details = strdup("");
188 perf = strdup (""); 181 perf = strdup("");
189 perf_ilabel = strdup (""); 182 perf_ilabel = strdup("");
190 stat_buf = malloc(sizeof *stat_buf); 183 stat_buf = malloc(sizeof *stat_buf);
191 184
192 setlocale (LC_ALL, ""); 185 setlocale(LC_ALL, "");
193 bindtextdomain (PACKAGE, LOCALEDIR); 186 bindtextdomain(PACKAGE, LOCALEDIR);
194 textdomain (PACKAGE); 187 textdomain(PACKAGE);
195 188
196 mount_list = read_file_system_list (0); 189 mount_list = read_file_system_list(0);
197 190
198 /* Parse extra opts if any */ 191 /* Parse extra opts if any */
199 argv = np_extra_opts (&argc, argv, progname); 192 argv = np_extra_opts(&argc, argv, progname);
200 193
201 if (process_arguments (argc, argv) == ERROR) 194 if (process_arguments(argc, argv) == ERROR)
202 usage4 (_("Could not parse arguments")); 195 usage4(_("Could not parse arguments"));
203 196
204 /* If a list of paths has not been selected, find entire 197 /* If a list of paths has not been selected, find entire
205 mount list and create list of paths 198 mount list and create list of paths
206 */ 199 */
207 if (path_selected == false && path_ignored == false) { 200 if (path_selected == false && path_ignored == false) {
208 for (me = mount_list; me; me = me->me_next) { 201 for (me = mount_list; me; me = me->me_next) {
209 if (! (path = np_find_parameter(path_select_list, me->me_mountdir))) { 202 if (!(path = np_find_parameter(path_select_list, me->me_mountdir))) {
210 path = np_add_parameter(&path_select_list, me->me_mountdir); 203 path = np_add_parameter(&path_select_list, me->me_mountdir);
211 } 204 }
212 path->best_match = me; 205 path->best_match = me;
213 path->group = group; 206 path->group = group;
214 set_all_thresholds(path); 207 set_all_thresholds(path);
215 } 208 }
216 } 209 }
217 210
218 if (path_ignored == false) { 211 if (path_ignored == false) {
219 np_set_best_match(path_select_list, mount_list, exact_match); 212 np_set_best_match(path_select_list, mount_list, exact_match);
220 } 213 }
221 214
222 /* Error if no match found for specified paths */ 215 /* Error if no match found for specified paths */
223 temp_list = path_select_list; 216 temp_list = path_select_list;
224 217
225 while (path_select_list) { 218 while (path_select_list) {
226 if (! path_select_list->best_match && ignore_missing == true) { 219 if (!path_select_list->best_match && ignore_missing == true) {
227 /* If the first element will be deleted, the temp_list must be updated with the new start address as well */ 220 /* If the first element will be deleted, the temp_list must be updated with the new start address as well */
228 if (path_select_list == temp_list) { 221 if (path_select_list == temp_list) {
229 temp_list = path_select_list->name_next; 222 temp_list = path_select_list->name_next;
230 } 223 }
231 /* Add path argument to list of ignored paths to inform about missing paths being ignored and not alerted */ 224 /* Add path argument to list of ignored paths to inform about missing paths being ignored and not alerted */
232 xasprintf (&ignored, "%s %s;", ignored, path_select_list->name); 225 xasprintf(&ignored, "%s %s;", ignored, path_select_list->name);
233 /* Delete the path from the list so that it is not stat-checked later in the code. */ 226 /* Delete the path from the list so that it is not stat-checked later in the code. */
234 path_select_list = np_del_parameter(path_select_list, path_select_list->name_prev); 227 path_select_list = np_del_parameter(path_select_list, path_select_list->name_prev);
235 } else if (! path_select_list->best_match) { 228 } else if (!path_select_list->best_match) {
236 /* Without --ignore-missing option, exit with Critical state. */ 229 /* Without --ignore-missing option, exit with Critical state. */
237 die (STATE_CRITICAL, _("DISK %s: %s not found\n"), _("CRITICAL"), path_select_list->name); 230 die(STATE_CRITICAL, _("DISK %s: %s not found\n"), _("CRITICAL"), path_select_list->name);
238 } else { 231 } else {
239 /* Continue jumping through the list */ 232 /* Continue jumping through the list */
240 path_select_list = path_select_list->name_next; 233 path_select_list = path_select_list->name_next;
241 } 234 }
242 } 235 }
243 236
244 path_select_list = temp_list; 237 path_select_list = temp_list;
245 238
246 if (! path_select_list && ignore_missing == true) { 239 if (!path_select_list && ignore_missing == true) {
247 result = STATE_OK; 240 result = STATE_OK;
248 if (verbose >= 2) { 241 if (verbose >= 2) {
249 printf ("None of the provided paths were found\n"); 242 printf("None of the provided paths were found\n");
250 } 243 }
251 } 244 }
252 245
253 /* Process for every path in list */ 246 /* Process for every path in list */
254 for (path = path_select_list; path; path=path->name_next) { 247 for (path = path_select_list; path; path = path->name_next) {
255 if (verbose >= 3 && path->freespace_percent->warning != NULL && path->freespace_percent->critical != NULL) 248 if (verbose >= 3 && path->freespace_percent->warning != NULL && path->freespace_percent->critical != NULL)
256 printf("Thresholds(pct) for %s warn: %f crit %f\n", 249 printf("Thresholds(pct) for %s warn: %f crit %f\n", path->name, path->freespace_percent->warning->end,
257 path->name, 250 path->freespace_percent->critical->end);
258 path->freespace_percent->warning->end, 251
259 path->freespace_percent->critical->end); 252 if (verbose >= 3 && path->group != NULL)
260 253 printf("Group of %s: %s\n", path->name, path->group);
261 if (verbose >= 3 && path->group != NULL) 254
262 printf("Group of %s: %s\n",path->name,path->group); 255 /* reset disk result */
263 256 disk_result = STATE_UNKNOWN;
264 /* reset disk result */ 257
265 disk_result = STATE_UNKNOWN; 258 me = path->best_match;
266 259
267 me = path->best_match; 260 if (!me) {
268 261 continue;
269 if (!me) { 262 }
270 continue;
271 }
272 263
273#ifdef __CYGWIN__ 264#ifdef __CYGWIN__
274 if (strncmp(path->name, "/cygdrive/", 10) != 0 || strlen(path->name) > 11) 265 if (strncmp(path->name, "/cygdrive/", 10) != 0 || strlen(path->name) > 11)
275 continue; 266 continue;
276 snprintf(mountdir, sizeof(mountdir), "%s:\\", me->me_mountdir + 10); 267 snprintf(mountdir, sizeof(mountdir), "%s:\\", me->me_mountdir + 10);
277 if (GetDriveType(mountdir) != DRIVE_FIXED) 268 if (GetDriveType(mountdir) != DRIVE_FIXED)
278 me->me_remote = 1; 269 me->me_remote = 1;
279#endif 270#endif
280 /* Filters */ 271 /* Filters */
281 272
282 /* Remove filesystems already seen */ 273 /* Remove filesystems already seen */
283 if (np_seen_name(seen, me->me_mountdir)) { 274 if (np_seen_name(seen, me->me_mountdir)) {
284 continue; 275 continue;
285 } 276 }
286 np_add_name(&seen, me->me_mountdir); 277 np_add_name(&seen, me->me_mountdir);
287 278
288 if (path->group == NULL) { 279 if (path->group == NULL) {
289 /* Skip remote filesystems if we're not interested in them */ 280 /* Skip remote filesystems if we're not interested in them */
290 if (me->me_remote && show_local_fs) { 281 if (me->me_remote && show_local_fs) {
291 if (stat_remote_fs) { 282 if (stat_remote_fs) {
292 if (!stat_path(path) && ignore_missing == true) { 283 if (!stat_path(path) && ignore_missing == true) {
293 result = STATE_OK; 284 result = STATE_OK;
294 xasprintf (&ignored, "%s %s;", ignored, path->name); 285 xasprintf(&ignored, "%s %s;", ignored, path->name);
295 } 286 }
296 } 287 }
297 continue; 288 continue;
298 /* Skip pseudo fs's if we haven't asked for all fs's */ 289 /* Skip pseudo fs's if we haven't asked for all fs's */
299 } else if (me->me_dummy && !show_all_fs) { 290 }
300 continue; 291 if (me->me_dummy && !show_all_fs) {
301 /* Skip excluded fstypes */ 292 continue;
302 } else if (fs_exclude_list && np_find_regmatch (fs_exclude_list, me->me_type)) { 293 /* Skip excluded fstypes */
303 continue; 294 }
304 /* Skip excluded fs's */ 295 if (fs_exclude_list && np_find_regmatch(fs_exclude_list, me->me_type)) {
305 } else if (dp_exclude_list && 296 continue;
306 (np_find_name (dp_exclude_list, me->me_devname) || 297 /* Skip excluded fs's */
307 np_find_name (dp_exclude_list, me->me_mountdir))) { 298 }
308 continue; 299 if (dp_exclude_list && (np_find_name(dp_exclude_list, me->me_devname) || np_find_name(dp_exclude_list, me->me_mountdir))) {
309 /* Skip not included fstypes */ 300 continue;
310 } else if (fs_include_list && !np_find_regmatch(fs_include_list, me->me_type)) { 301 /* Skip not included fstypes */
311 continue; 302 }
312 } 303 if (fs_include_list && !np_find_regmatch(fs_include_list, me->me_type)) {
313 } 304 continue;
314 305 }
315 if (!stat_path(path)) { 306 }
316 if (ignore_missing == true) { 307
317 result = STATE_OK; 308 if (!stat_path(path)) {
318 xasprintf (&ignored, "%s %s;", ignored, path->name); 309 if (ignore_missing == true) {
319 } 310 result = STATE_OK;
320 continue; 311 xasprintf(&ignored, "%s %s;", ignored, path->name);
321 } 312 }
322 get_fs_usage (me->me_mountdir, me->me_devname, &fsp); 313 continue;
323 314 }
324 if (fsp.fsu_blocks && strcmp ("none", me->me_mountdir)) { 315 get_fs_usage(me->me_mountdir, me->me_devname, &fsp);
325 get_stats (path, &fsp); 316
326 317 if (fsp.fsu_blocks && strcmp("none", me->me_mountdir)) {
327 if (verbose >= 3) { 318 get_stats(path, &fsp);
328 printf ("For %s, used_pct=%g free_pct=%g used_units=%lu free_units=%lu total_units=%lu used_inodes_pct=%g free_inodes_pct=%g fsp.fsu_blocksize=%lu mult=%lu\n", 319
329 me->me_mountdir, 320 if (verbose >= 3) {
330 path->dused_pct, 321 printf("For %s, used_pct=%f free_pct=%f used_units=%lu free_units=%lu total_units=%lu used_inodes_pct=%f "
331 path->dfree_pct, 322 "free_inodes_pct=%f fsp.fsu_blocksize=%lu mult=%lu\n",
332 path->dused_units, 323 me->me_mountdir, path->dused_pct, path->dfree_pct, path->dused_units, path->dfree_units, path->dtotal_units,
333 path->dfree_units, 324 path->dused_inodes_percent, path->dfree_inodes_percent, fsp.fsu_blocksize, mult);
334 path->dtotal_units, 325 }
335 path->dused_inodes_percent, 326
336 path->dfree_inodes_percent, 327 /* Threshold comparisons */
337 fsp.fsu_blocksize, 328
338 mult); 329 temp_result = get_status(path->dfree_units, path->freespace_units);
339 } 330 if (verbose >= 3)
340 331 printf("Freespace_units result=%d\n", temp_result);
341 /* Threshold comparisons */ 332 disk_result = max_state(disk_result, temp_result);
342 333
343 temp_result = get_status(path->dfree_units, path->freespace_units); 334 temp_result = get_status(path->dfree_pct, path->freespace_percent);
344 if (verbose >=3) printf("Freespace_units result=%d\n", temp_result); 335 if (verbose >= 3)
345 disk_result = max_state( disk_result, temp_result ); 336 printf("Freespace%% result=%d\n", temp_result);
346 337 disk_result = max_state(disk_result, temp_result);
347 temp_result = get_status(path->dfree_pct, path->freespace_percent); 338
348 if (verbose >=3) printf("Freespace%% result=%d\n", temp_result); 339 temp_result = get_status(path->dused_units, path->usedspace_units);
349 disk_result = max_state( disk_result, temp_result ); 340 if (verbose >= 3)
350 341 printf("Usedspace_units result=%d\n", temp_result);
351 temp_result = get_status(path->dused_units, path->usedspace_units); 342 disk_result = max_state(disk_result, temp_result);
352 if (verbose >=3) printf("Usedspace_units result=%d\n", temp_result); 343
353 disk_result = max_state( disk_result, temp_result ); 344 temp_result = get_status(path->dused_pct, path->usedspace_percent);
354 345 if (verbose >= 3)
355 temp_result = get_status(path->dused_pct, path->usedspace_percent); 346 printf("Usedspace_percent result=%d\n", temp_result);
356 if (verbose >=3) printf("Usedspace_percent result=%d\n", temp_result); 347 disk_result = max_state(disk_result, temp_result);
357 disk_result = max_state( disk_result, temp_result ); 348
358 349 temp_result = get_status(path->dused_inodes_percent, path->usedinodes_percent);
359 temp_result = get_status(path->dused_inodes_percent, path->usedinodes_percent); 350 if (verbose >= 3)
360 if (verbose >=3) printf("Usedinodes_percent result=%d\n", temp_result); 351 printf("Usedinodes_percent result=%d\n", temp_result);
361 disk_result = max_state( disk_result, temp_result ); 352 disk_result = max_state(disk_result, temp_result);
362 353
363 temp_result = get_status(path->dfree_inodes_percent, path->freeinodes_percent); 354 temp_result = get_status(path->dfree_inodes_percent, path->freeinodes_percent);
364 if (verbose >=3) printf("Freeinodes_percent result=%d\n", temp_result); 355 if (verbose >= 3)
365 disk_result = max_state( disk_result, temp_result ); 356 printf("Freeinodes_percent result=%d\n", temp_result);
366 357 disk_result = max_state(disk_result, temp_result);
367 result = max_state(result, disk_result); 358
368 359 result = max_state(result, disk_result);
369 /* What a mess of units. The output shows free space, the perf data shows used space. Yikes! 360
370 Hack here. Trying to get warn/crit levels from freespace_(units|percent) for perf 361 /* What a mess of units. The output shows free space, the perf data shows used space. Yikes!
371 data. Assumption that start=0. Roll on new syntax... 362 Hack here. Trying to get warn/crit levels from freespace_(units|percent) for perf
372 */ 363 data. Assumption that start=0. Roll on new syntax...
373 364 */
374 /* *_high_tide must be reinitialized at each run */ 365
375 uint64_t warning_high_tide = UINT64_MAX; 366 /* *_high_tide must be reinitialized at each run */
376 367 uint64_t warning_high_tide = UINT64_MAX;
377 if (path->freespace_units->warning != NULL) { 368
378 warning_high_tide = (path->dtotal_units - path->freespace_units->warning->end) * mult; 369 if (path->freespace_units->warning != NULL) {
379 } 370 warning_high_tide = (path->dtotal_units - path->freespace_units->warning->end) * mult;
380 if (path->freespace_percent->warning != NULL) { 371 }
381 warning_high_tide = min( warning_high_tide, (uint64_t)((1.0 - path->freespace_percent->warning->end/100) * (path->dtotal_units * mult)) ); 372 if (path->freespace_percent->warning != NULL) {
382 } 373 warning_high_tide =
383 374 min(warning_high_tide, (uint64_t)((1.0 - path->freespace_percent->warning->end / 100) * (path->dtotal_units * mult)));
384 uint64_t critical_high_tide = UINT64_MAX; 375 }
385 376
386 if (path->freespace_units->critical != NULL) { 377 uint64_t critical_high_tide = UINT64_MAX;
387 critical_high_tide = (path->dtotal_units - path->freespace_units->critical->end) * mult; 378
388 } 379 if (path->freespace_units->critical != NULL) {
389 if (path->freespace_percent->critical != NULL) { 380 critical_high_tide = (path->dtotal_units - path->freespace_units->critical->end) * mult;
390 critical_high_tide = min( critical_high_tide, (uint64_t)((1.0 - path->freespace_percent->critical->end/100) * (path->dtotal_units * mult)) ); 381 }
391 } 382 if (path->freespace_percent->critical != NULL) {
392 383 critical_high_tide =
393 /* Nb: *_high_tide are unset when == UINT64_MAX */ 384 min(critical_high_tide, (uint64_t)((1.0 - path->freespace_percent->critical->end / 100) * (path->dtotal_units * mult)));
394 xasprintf (&perf, "%s %s", perf, 385 }
395 perfdata_uint64 ( 386
396 (!strcmp(me->me_mountdir, "none") || display_mntp) ? me->me_devname : me->me_mountdir, 387 /* Nb: *_high_tide are unset when == UINT64_MAX */
397 path->dused_units * mult, "B", 388 xasprintf(&perf, "%s %s", perf,
398 (warning_high_tide == UINT64_MAX ? false : true), warning_high_tide, 389 perfdata_uint64((!strcmp(me->me_mountdir, "none") || display_mntp) ? me->me_devname : me->me_mountdir,
399 (critical_high_tide == UINT64_MAX ? false : true), critical_high_tide, 390 path->dused_units * mult, "B", (warning_high_tide == UINT64_MAX ? false : true), warning_high_tide,
400 true, 0, 391 (critical_high_tide == UINT64_MAX ? false : true), critical_high_tide, true, 0, true,
401 true, path->dtotal_units * mult)); 392 path->dtotal_units * mult));
402 393
403 if (display_inodes_perfdata) { 394 if (display_inodes_perfdata) {
404 /* *_high_tide must be reinitialized at each run */ 395 /* *_high_tide must be reinitialized at each run */
405 warning_high_tide = UINT64_MAX; 396 warning_high_tide = UINT64_MAX;
406 critical_high_tide = UINT64_MAX; 397 critical_high_tide = UINT64_MAX;
407 398
408 if (path->freeinodes_percent->warning != NULL) { 399 if (path->freeinodes_percent->warning != NULL) {
409 warning_high_tide = (uint64_t) fabs( min( (double) warning_high_tide, (double) (1.0 - path->freeinodes_percent->warning->end/100)*path->inodes_total )); 400 warning_high_tide = (uint64_t)fabs(
410 } 401 min((double)warning_high_tide, (double)(1.0 - path->freeinodes_percent->warning->end / 100) * path->inodes_total));
411 if (path->freeinodes_percent->critical != NULL) { 402 }
412 critical_high_tide = (uint64_t) fabs( min( (double) critical_high_tide, (double) (1.0 - path->freeinodes_percent->critical->end/100)*path->inodes_total )); 403 if (path->freeinodes_percent->critical != NULL) {
413 } 404 critical_high_tide = (uint64_t)fabs(min(
414 405 (double)critical_high_tide, (double)(1.0 - path->freeinodes_percent->critical->end / 100) * path->inodes_total));
415 xasprintf (&perf_ilabel, "%s (inodes)", (!strcmp(me->me_mountdir, "none") || display_mntp) ? me->me_devname : me->me_mountdir); 406 }
416 /* Nb: *_high_tide are unset when == UINT64_MAX */ 407
417 xasprintf (&perf, "%s %s", perf, 408 xasprintf(&perf_ilabel, "%s (inodes)",
418 perfdata_uint64 (perf_ilabel, 409 (!strcmp(me->me_mountdir, "none") || display_mntp) ? me->me_devname : me->me_mountdir);
419 path->inodes_used, "", 410 /* Nb: *_high_tide are unset when == UINT64_MAX */
420 (warning_high_tide != UINT64_MAX ? true : false), warning_high_tide, 411 xasprintf(&perf, "%s %s", perf,
421 (critical_high_tide != UINT64_MAX ? true : false), critical_high_tide, 412 perfdata_uint64(perf_ilabel, path->inodes_used, "", (warning_high_tide != UINT64_MAX ? true : false),
422 true, 0, 413 warning_high_tide, (critical_high_tide != UINT64_MAX ? true : false), critical_high_tide, true, 0,
423 true, path->inodes_total)); 414 true, path->inodes_total));
424 } 415 }
425 416
426 if (disk_result==STATE_OK && erronly && !verbose) 417 if (disk_result == STATE_OK && erronly && !verbose)
427 continue; 418 continue;
428 419
429 if(disk_result && verbose >= 1) { 420 if (disk_result && verbose >= 1) {
430 xasprintf(&flag_header, " %s [", state_text (disk_result)); 421 xasprintf(&flag_header, " %s [", state_text(disk_result));
431 } else { 422 } else {
432 xasprintf(&flag_header, ""); 423 xasprintf(&flag_header, "");
433 } 424 }
434 xasprintf (&output, "%s%s %s %llu%s (%.0f%%", 425 xasprintf(&output, "%s%s %s %llu%s (%.1f%%", output, flag_header,
435 output, flag_header, 426 (!strcmp(me->me_mountdir, "none") || display_mntp) ? me->me_devname : me->me_mountdir, path->dfree_units, units,
436 (!strcmp(me->me_mountdir, "none") || display_mntp) ? me->me_devname : me->me_mountdir, 427 path->dfree_pct);
437 path->dfree_units, 428 if (path->dused_inodes_percent < 0) {
438 units, 429 xasprintf(&output, "%s inode=-)%s;", output, (disk_result ? "]" : ""));
439 path->dfree_pct); 430 } else {
440 if (path->dused_inodes_percent < 0) { 431 xasprintf(&output, "%s inode=%.0f%%)%s;", output, path->dfree_inodes_percent, ((disk_result && verbose >= 1) ? "]" : ""));
441 xasprintf(&output, "%s inode=-)%s;", output, (disk_result ? "]" : "")); 432 }
442 } else { 433 free(flag_header);
443 xasprintf(&output, "%s inode=%.0f%%)%s;", output, path->dfree_inodes_percent, ((disk_result && verbose >= 1) ? "]" : "")); 434 }
444 } 435 }
445 free(flag_header); 436
446 } 437 if (verbose >= 2)
447 } 438 xasprintf(&output, "%s%s", output, details);
448 439
449 if (verbose >= 2) 440 if (strcmp(output, "") == 0 && !erronly) {
450 xasprintf (&output, "%s%s", output, details); 441 preamble = "";
451 442 xasprintf(&output, " - No disks were found for provided parameters");
452 if (strcmp(output, "") == 0 && ! erronly) { 443 }
453 preamble = ""; 444
454 xasprintf (&output, " - No disks were found for provided parameters"); 445 printf("DISK %s%s%s%s%s|%s\n", state_text(result), ((erronly && result == STATE_OK)) ? "" : preamble, output,
455 } 446 (strcmp(ignored, "") == 0) ? "" : ignored_preamble, ignored, perf);
456 447 return result;
457 printf ("DISK %s%s%s%s%s|%s\n", state_text (result), ((erronly && result==STATE_OK)) ? "" : preamble, output, (strcmp(ignored, "") == 0) ? "" : ignored_preamble, ignored, perf);
458 return result;
459} 448}
460 449
461
462double calculate_percent(uintmax_t value, uintmax_t total) { 450double calculate_percent(uintmax_t value, uintmax_t total) {
463 double pct = -1; 451 double pct = -1;
464 /* I don't understand the below, but it is taken from coreutils' df */ 452 if (value <= DBL_MAX && total != 0) {
465 /* Seems to be calculating pct, in the best possible way */ 453 pct = (double)value / total * 100.0;
466 if (value <= TYPE_MAXIMUM(uintmax_t) / 100 454 }
467 && total != 0) { 455 return pct;
468 uintmax_t u100 = value * 100;
469 pct = u100 / total + (u100 % total != 0);
470 } else {
471 /* Possible rounding errors - see coreutils' df for more explanation */
472 double u = value;
473 double t = total;
474 if (t) {
475 long int lipct = pct = u * 100 / t;
476 double ipct = lipct;
477
478 /* Like 'pct = ceil (dpct);', but without ceil - from coreutils again */
479 if (ipct - 1 < pct && pct <= ipct + 1)
480 pct = ipct + (ipct < pct);
481 }
482 }
483 return pct;
484} 456}
485 457
486/* process command-line arguments */ 458/* process command-line arguments */
487int 459int process_arguments(int argc, char **argv) {
488process_arguments (int argc, char **argv) 460 int c;
489{ 461 int err;
490 int c, err; 462 struct parameter_list *se;
491 struct parameter_list *se; 463 struct parameter_list *temp_list = NULL;
492 struct parameter_list *temp_list = NULL, *previous = NULL; 464 struct parameter_list *previous = NULL;
493 struct mount_entry *me; 465 struct mount_entry *me;
494 regex_t re; 466 regex_t re;
495 int cflags = REG_NOSUB | REG_EXTENDED; 467 int cflags = REG_NOSUB | REG_EXTENDED;
496 int default_cflags = cflags; 468 int default_cflags = cflags;
497 char errbuf[MAX_INPUT_BUFFER]; 469 char errbuf[MAX_INPUT_BUFFER];
498 int fnd = 0; 470 int fnd = 0;
499 471
500 int option = 0; 472 int option = 0;
501 static struct option longopts[] = { 473 static struct option longopts[] = {{"timeout", required_argument, 0, 't'},
502 {"timeout", required_argument, 0, 't'}, 474 {"warning", required_argument, 0, 'w'},
503 {"warning", required_argument, 0, 'w'}, 475 {"critical", required_argument, 0, 'c'},
504 {"critical", required_argument, 0, 'c'}, 476 {"iwarning", required_argument, 0, 'W'},
505 {"iwarning", required_argument, 0, 'W'}, 477 /* Dang, -C is taken. We might want to reshuffle this. */
506 /* Dang, -C is taken. We might want to reshuffle this. */ 478 {"icritical", required_argument, 0, 'K'},
507 {"icritical", required_argument, 0, 'K'}, 479 {"kilobytes", no_argument, 0, 'k'},
508 {"kilobytes", no_argument, 0, 'k'}, 480 {"megabytes", no_argument, 0, 'm'},
509 {"megabytes", no_argument, 0, 'm'}, 481 {"units", required_argument, 0, 'u'},
510 {"units", required_argument, 0, 'u'}, 482 {"path", required_argument, 0, 'p'},
511 {"path", required_argument, 0, 'p'}, 483 {"partition", required_argument, 0, 'p'},
512 {"partition", required_argument, 0, 'p'}, 484 {"exclude_device", required_argument, 0, 'x'},
513 {"exclude_device", required_argument, 0, 'x'}, 485 {"exclude-type", required_argument, 0, 'X'},
514 {"exclude-type", required_argument, 0, 'X'}, 486 {"include-type", required_argument, 0, 'N'},
515 {"include-type", required_argument, 0, 'N'}, 487 {"group", required_argument, 0, 'g'},
516 {"group", required_argument, 0, 'g'}, 488 {"eregi-path", required_argument, 0, 'R'},
517 {"eregi-path", required_argument, 0, 'R'}, 489 {"eregi-partition", required_argument, 0, 'R'},
518 {"eregi-partition", required_argument, 0, 'R'}, 490 {"ereg-path", required_argument, 0, 'r'},
519 {"ereg-path", required_argument, 0, 'r'}, 491 {"ereg-partition", required_argument, 0, 'r'},
520 {"ereg-partition", required_argument, 0, 'r'}, 492 {"freespace-ignore-reserved", no_argument, 0, 'f'},
521 {"freespace-ignore-reserved", no_argument, 0, 'f'}, 493 {"ignore-ereg-path", required_argument, 0, 'i'},
522 {"ignore-ereg-path", required_argument, 0, 'i'}, 494 {"ignore-ereg-partition", required_argument, 0, 'i'},
523 {"ignore-ereg-partition", required_argument, 0, 'i'}, 495 {"ignore-eregi-path", required_argument, 0, 'I'},
524 {"ignore-eregi-path", required_argument, 0, 'I'}, 496 {"ignore-eregi-partition", required_argument, 0, 'I'},
525 {"ignore-eregi-partition", required_argument, 0, 'I'}, 497 {"ignore-missing", no_argument, 0, 'n'},
526 {"ignore-missing", no_argument, 0, 'n'}, 498 {"local", no_argument, 0, 'l'},
527 {"local", no_argument, 0, 'l'}, 499 {"stat-remote-fs", no_argument, 0, 'L'},
528 {"stat-remote-fs", no_argument, 0, 'L'}, 500 {"iperfdata", no_argument, 0, 'P'},
529 {"iperfdata", no_argument, 0, 'P'}, 501 {"mountpoint", no_argument, 0, 'M'},
530 {"mountpoint", no_argument, 0, 'M'}, 502 {"errors-only", no_argument, 0, 'e'},
531 {"errors-only", no_argument, 0, 'e'}, 503 {"exact-match", no_argument, 0, 'E'},
532 {"exact-match", no_argument, 0, 'E'}, 504 {"all", no_argument, 0, 'A'},
533 {"all", no_argument, 0, 'A'}, 505 {"verbose", no_argument, 0, 'v'},
534 {"verbose", no_argument, 0, 'v'}, 506 {"quiet", no_argument, 0, 'q'},
535 {"quiet", no_argument, 0, 'q'}, 507 {"clear", no_argument, 0, 'C'},
536 {"clear", no_argument, 0, 'C'}, 508 {"version", no_argument, 0, 'V'},
537 {"version", no_argument, 0, 'V'}, 509 {"help", no_argument, 0, 'h'},
538 {"help", no_argument, 0, 'h'}, 510 {0, 0, 0, 0}};
539 {0, 0, 0, 0} 511
540 }; 512 if (argc < 2)
541 513 return ERROR;
542 if (argc < 2) 514
543 return ERROR; 515 np_add_regex(&fs_exclude_list, "iso9660", REG_EXTENDED);
544 516
545 np_add_regex(&fs_exclude_list, "iso9660", REG_EXTENDED); 517 for (c = 1; c < argc; c++)
546 518 if (strcmp("-to", argv[c]) == 0)
547 for (c = 1; c < argc; c++) 519 strcpy(argv[c], "-t");
548 if (strcmp ("-to", argv[c]) == 0) 520
549 strcpy (argv[c], "-t"); 521 while (1) {
550 522 c = getopt_long(argc, argv, "+?VqhvefCt:c:w:K:W:u:p:x:X:N:mklLPg:R:r:i:I:MEAn", longopts, &option);
551 while (1) { 523
552 c = getopt_long (argc, argv, "+?VqhvefCt:c:w:K:W:u:p:x:X:N:mklLPg:R:r:i:I:MEAn", longopts, &option); 524 if (c == -1 || c == EOF)
553 525 break;
554 if (c == -1 || c == EOF) 526
555 break; 527 switch (c) {
556 528 case 't': /* timeout period */
557 switch (c) { 529 if (is_integer(optarg)) {
558 case 't': /* timeout period */ 530 timeout_interval = atoi(optarg);
559 if (is_integer (optarg)) { 531 break;
560 timeout_interval = atoi (optarg); 532 } else {
561 break; 533 usage2(_("Timeout interval must be a positive integer"), optarg);
562 } 534 }
563 else { 535
564 usage2 (_("Timeout interval must be a positive integer"), optarg); 536 /* See comments for 'c' */
565 } 537 case 'w': /* warning threshold */
566 538 if (!is_percentage_expression(optarg) && !is_numeric(optarg)) {
567 /* See comments for 'c' */ 539 die(STATE_UNKNOWN, "Argument for --warning invalid or missing: %s\n", optarg);
568 case 'w': /* warning threshold */ 540 }
569 if (strstr(optarg, "%")) { 541
570 if (*optarg == '@') { 542 if (strstr(optarg, "%")) {
571 warn_freespace_percent = optarg; 543 if (*optarg == '@') {
572 } else { 544 warn_freespace_percent = optarg;
573 xasprintf(&warn_freespace_percent, "@%s", optarg); 545 } else {
574 } 546 xasprintf(&warn_freespace_percent, "@%s", optarg);
575 } else { 547 }
576 if (*optarg == '@') { 548 } else {
577 warn_freespace_units = optarg; 549 if (*optarg == '@') {
578 } else { 550 warn_freespace_units = optarg;
579 xasprintf(&warn_freespace_units, "@%s", optarg); 551 } else {
580 } 552 xasprintf(&warn_freespace_units, "@%s", optarg);
581 } 553 }
582 break; 554 }
583 555 break;
584 /* Awful mistake where the range values do not make sense. Normally, 556
585 you alert if the value is within the range, but since we are using 557 /* Awful mistake where the range values do not make sense. Normally,
586 freespace, we have to alert if outside the range. Thus we artificially 558 you alert if the value is within the range, but since we are using
587 force @ at the beginning of the range, so that it is backwards compatible 559 freespace, we have to alert if outside the range. Thus we artificially
588 */ 560 force @ at the beginning of the range, so that it is backwards compatible
589 case 'c': /* critical threshold */ 561 */
590 if (strstr(optarg, "%")) { 562 case 'c': /* critical threshold */
591 if (*optarg == '@') { 563 if (!is_percentage_expression(optarg) && !is_numeric(optarg)) {
592 crit_freespace_percent = optarg; 564 die(STATE_UNKNOWN, "Argument for --critical invalid or missing: %s\n", optarg);
593 } else { 565 }
594 xasprintf(&crit_freespace_percent, "@%s", optarg); 566
595 } 567 if (strstr(optarg, "%")) {
596 } else { 568 if (*optarg == '@') {
597 if (*optarg == '@') { 569 crit_freespace_percent = optarg;
598 crit_freespace_units = optarg; 570 } else {
599 } else { 571 xasprintf(&crit_freespace_percent, "@%s", optarg);
600 xasprintf(&crit_freespace_units, "@%s", optarg); 572 }
601 } 573 } else {
602 } 574 if (*optarg == '@') {
603 break; 575 crit_freespace_units = optarg;
604 576 } else {
605 case 'W': /* warning inode threshold */ 577 xasprintf(&crit_freespace_units, "@%s", optarg);
606 if (*optarg == '@') { 578 }
607 warn_freeinodes_percent = optarg; 579 }
608 } else { 580 break;
609 xasprintf(&warn_freeinodes_percent, "@%s", optarg); 581
610 } 582 case 'W': /* warning inode threshold */
611 break; 583 if (*optarg == '@') {
612 case 'K': /* critical inode threshold */ 584 warn_freeinodes_percent = optarg;
613 if (*optarg == '@') { 585 } else {
614 crit_freeinodes_percent = optarg; 586 xasprintf(&warn_freeinodes_percent, "@%s", optarg);
615 } else { 587 }
616 xasprintf(&crit_freeinodes_percent, "@%s", optarg); 588 break;
617 } 589 case 'K': /* critical inode threshold */
618 break; 590 if (*optarg == '@') {
619 case 'u': 591 crit_freeinodes_percent = optarg;
620 if (units) 592 } else {
621 free(units); 593 xasprintf(&crit_freeinodes_percent, "@%s", optarg);
622 if (! strcasecmp (optarg, "bytes")) { 594 }
623 mult = (uintmax_t)1; 595 break;
624 units = strdup ("B"); 596 case 'u':
625 } else if (!strcmp(optarg, "KiB")) { 597 if (units)
626 mult = (uintmax_t)1024; 598 free(units);
627 units = strdup ("KiB"); 599 if (!strcasecmp(optarg, "bytes")) {
628 } else if (! strcmp (optarg, "kB")) { 600 mult = (uintmax_t)1;
629 mult = (uintmax_t)1000; 601 units = strdup("B");
630 units = strdup ("kB"); 602 } else if (!strcmp(optarg, "KiB")) {
631 } else if (!strcmp(optarg, "MiB")) { 603 mult = (uintmax_t)1024;
632 mult = (uintmax_t)1024 * 1024; 604 units = strdup("KiB");
633 units = strdup ("MiB"); 605 } else if (!strcmp(optarg, "kB")) {
634 } else if (! strcmp (optarg, "MB")) { 606 mult = (uintmax_t)1000;
635 mult = (uintmax_t)1000 * 1000; 607 units = strdup("kB");
636 units = strdup ("MB"); 608 } else if (!strcmp(optarg, "MiB")) {
637 } else if (!strcmp(optarg, "GiB")) { 609 mult = (uintmax_t)1024 * 1024;
638 mult = (uintmax_t)1024 * 1024 * 1024; 610 units = strdup("MiB");
639 units = strdup ("GiB"); 611 } else if (!strcmp(optarg, "MB")) {
640 } else if (! strcmp (optarg, "GB")){ 612 mult = (uintmax_t)1000 * 1000;
641 mult = (uintmax_t)1000 * 1000 * 1000; 613 units = strdup("MB");
642 units = strdup ("GB"); 614 } else if (!strcmp(optarg, "GiB")) {
643 } else if (!strcmp(optarg, "TiB")) { 615 mult = (uintmax_t)1024 * 1024 * 1024;
644 mult = (uintmax_t)1024 * 1024 * 1024 * 1024; 616 units = strdup("GiB");
645 units = strdup ("TiB"); 617 } else if (!strcmp(optarg, "GB")) {
646 } else if (! strcmp (optarg, "TB")) { 618 mult = (uintmax_t)1000 * 1000 * 1000;
647 mult = (uintmax_t)1000 * 1000 * 1000 * 1000; 619 units = strdup("GB");
648 units = strdup ("TB"); 620 } else if (!strcmp(optarg, "TiB")) {
649 } else if (!strcmp(optarg, "PiB")) { 621 mult = (uintmax_t)1024 * 1024 * 1024 * 1024;
650 mult = (uintmax_t)1024 * 1024 * 1024 * 1024 * 1024; 622 units = strdup("TiB");
651 units = strdup ("PiB"); 623 } else if (!strcmp(optarg, "TB")) {
652 } else if (! strcmp (optarg, "PB")){ 624 mult = (uintmax_t)1000 * 1000 * 1000 * 1000;
653 mult = (uintmax_t)1000 * 1000 * 1000 * 1000 * 1000; 625 units = strdup("TB");
654 units = strdup ("PB"); 626 } else if (!strcmp(optarg, "PiB")) {
655 } else { 627 mult = (uintmax_t)1024 * 1024 * 1024 * 1024 * 1024;
656 die (STATE_UNKNOWN, _("unit type %s not known\n"), optarg); 628 units = strdup("PiB");
657 } 629 } else if (!strcmp(optarg, "PB")) {
658 if (units == NULL) 630 mult = (uintmax_t)1000 * 1000 * 1000 * 1000 * 1000;
659 die (STATE_UNKNOWN, _("failed allocating storage for '%s'\n"), "units"); 631 units = strdup("PB");
660 break; 632 } else {
661 case 'k': /* display mountpoint */ 633 die(STATE_UNKNOWN, _("unit type %s not known\n"), optarg);
662 mult = 1024; 634 }
663 if (units) 635 if (units == NULL)
664 free(units); 636 die(STATE_UNKNOWN, _("failed allocating storage for '%s'\n"), "units");
665 units = strdup ("kiB"); 637 break;
666 break; 638 case 'k': /* display mountpoint */
667 case 'm': /* display mountpoint */ 639 mult = 1024;
668 mult = 1024 * 1024; 640 if (units)
669 if (units) 641 free(units);
670 free(units); 642 units = strdup("kiB");
671 units = strdup ("MiB"); 643 break;
672 break; 644 case 'm': /* display mountpoint */
673 case 'L': 645 mult = 1024 * 1024;
674 stat_remote_fs = 1; 646 if (units)
675 /* fallthrough */ 647 free(units);
676 case 'l': 648 units = strdup("MiB");
677 show_local_fs = 1; 649 break;
678 break; 650 case 'L':
679 case 'P': 651 stat_remote_fs = 1;
680 display_inodes_perfdata = 1; 652 /* fallthrough */
681 break; 653 case 'l':
682 case 'p': /* select path */ 654 show_local_fs = 1;
683 if (! (warn_freespace_units || crit_freespace_units || warn_freespace_percent || 655 break;
684 crit_freespace_percent || warn_usedspace_units || crit_usedspace_units || 656 case 'P':
685 warn_usedspace_percent || crit_usedspace_percent || warn_usedinodes_percent || 657 display_inodes_perfdata = 1;
686 crit_usedinodes_percent || warn_freeinodes_percent || crit_freeinodes_percent )) { 658 break;
687 die (STATE_UNKNOWN, "DISK %s: %s", _("UNKNOWN"), _("Must set a threshold value before using -p\n")); 659 case 'p': /* select path */
688 } 660 if (!(warn_freespace_units || crit_freespace_units || warn_freespace_percent || crit_freespace_percent ||
689 661 warn_usedspace_units || crit_usedspace_units || warn_usedspace_percent || crit_usedspace_percent ||
690 /* add parameter if not found. overwrite thresholds if path has already been added */ 662 warn_usedinodes_percent || crit_usedinodes_percent || warn_freeinodes_percent || crit_freeinodes_percent)) {
691 if (! (se = np_find_parameter(path_select_list, optarg))) { 663 die(STATE_UNKNOWN, "DISK %s: %s", _("UNKNOWN"), _("Must set a threshold value before using -p\n"));
692 se = np_add_parameter(&path_select_list, optarg); 664 }
693 665
694 if (stat(optarg, &stat_buf[0]) && ignore_missing == true) { 666 /* add parameter if not found. overwrite thresholds if path has already been added */
695 path_ignored = true; 667 if (!(se = np_find_parameter(path_select_list, optarg))) {
696 break; 668 se = np_add_parameter(&path_select_list, optarg);
697 } 669
698 } 670 if (stat(optarg, &stat_buf[0]) && ignore_missing == true) {
699 se->group = group; 671 path_ignored = true;
700 set_all_thresholds(se); 672 break;
701 673 }
702 /* With autofs, it is required to stat() the path before re-populating the mount_list */ 674 }
703 if (!stat_path(se)) { 675 se->group = group;
704 break; 676 set_all_thresholds(se);
705 } 677
706 /* NB: We can't free the old mount_list "just like that": both list pointers and struct 678 /* With autofs, it is required to stat() the path before re-populating the mount_list */
707 * pointers are copied around. One of the reason it wasn't done yet is that other parts 679 if (!stat_path(se)) {
708 * of check_disk need the same kind of cleanup so it'd better be done as a whole */ 680 break;
709 mount_list = read_file_system_list (0); 681 }
710 np_set_best_match(se, mount_list, exact_match); 682 /* NB: We can't free the old mount_list "just like that": both list pointers and struct
711 683 * pointers are copied around. One of the reason it wasn't done yet is that other parts
712 path_selected = true; 684 * of check_disk need the same kind of cleanup so it'd better be done as a whole */
713 break; 685 mount_list = read_file_system_list(0);
714 case 'x': /* exclude path or partition */ 686 np_set_best_match(se, mount_list, exact_match);
715 np_add_name(&dp_exclude_list, optarg); 687
716 break; 688 path_selected = true;
717 case 'X': /* exclude file system type */ 689 break;
718 err = np_add_regex(&fs_exclude_list, optarg, REG_EXTENDED); 690 case 'x': /* exclude path or partition */
719 if (err != 0) { 691 np_add_name(&dp_exclude_list, optarg);
720 regerror (err, &fs_exclude_list->regex, errbuf, MAX_INPUT_BUFFER); 692 break;
721 die (STATE_UNKNOWN, "DISK %s: %s - %s\n",_("UNKNOWN"), _("Could not compile regular expression"), errbuf); 693 case 'X': /* exclude file system type */
722 } 694 err = np_add_regex(&fs_exclude_list, optarg, REG_EXTENDED);
723 break; 695 if (err != 0) {
724 case 'N': /* include file system type */ 696 regerror(err, &fs_exclude_list->regex, errbuf, MAX_INPUT_BUFFER);
725 err = np_add_regex(&fs_include_list, optarg, REG_EXTENDED); 697 die(STATE_UNKNOWN, "DISK %s: %s - %s\n", _("UNKNOWN"), _("Could not compile regular expression"), errbuf);
726 if (err != 0) { 698 }
727 regerror (err, &fs_exclude_list->regex, errbuf, MAX_INPUT_BUFFER); 699 break;
728 die (STATE_UNKNOWN, "DISK %s: %s - %s\n",_("UNKNOWN"), _("Could not compile regular expression"), errbuf); 700 case 'N': /* include file system type */
729 } 701 err = np_add_regex(&fs_include_list, optarg, REG_EXTENDED);
730 break; 702 if (err != 0) {
731 case 'v': /* verbose */ 703 regerror(err, &fs_exclude_list->regex, errbuf, MAX_INPUT_BUFFER);
732 verbose++; 704 die(STATE_UNKNOWN, "DISK %s: %s - %s\n", _("UNKNOWN"), _("Could not compile regular expression"), errbuf);
733 break; 705 }
734 case 'q': /* TODO: this function should eventually go away (removed 2007-09-20) */ 706 break;
735 /* verbose--; **replaced by line below**. -q was only a broken way of implementing -e */ 707 case 'v': /* verbose */
736 erronly = true; 708 verbose++;
737 break; 709 break;
738 case 'e': 710 case 'q': /* TODO: this function should eventually go away (removed 2007-09-20) */
739 erronly = true; 711 /* verbose--; **replaced by line below**. -q was only a broken way of implementing -e */
740 break; 712 erronly = true;
741 case 'E': 713 break;
742 if (path_selected) 714 case 'e':
743 die (STATE_UNKNOWN, "DISK %s: %s", _("UNKNOWN"), _("Must set -E before selecting paths\n")); 715 erronly = true;
744 exact_match = true; 716 break;
745 break; 717 case 'E':
746 case 'f': 718 if (path_selected)
747 freespace_ignore_reserved = true; 719 die(STATE_UNKNOWN, "DISK %s: %s", _("UNKNOWN"), _("Must set -E before selecting paths\n"));
748 break; 720 exact_match = true;
749 case 'g': 721 break;
750 if (path_selected) 722 case 'f':
751 die (STATE_UNKNOWN, "DISK %s: %s", _("UNKNOWN"), _("Must set group value before selecting paths\n")); 723 freespace_ignore_reserved = true;
752 group = optarg; 724 break;
753 break; 725 case 'g':
754 case 'I': 726 if (path_selected)
755 cflags |= REG_ICASE; 727 die(STATE_UNKNOWN, "DISK %s: %s", _("UNKNOWN"), _("Must set group value before selecting paths\n"));
756 // Intentional fallthrough 728 group = optarg;
757 case 'i': 729 break;
758 if (!path_selected) 730 case 'I':
759 die (STATE_UNKNOWN, "DISK %s: %s\n", _("UNKNOWN"), _("Paths need to be selected before using -i/-I. Use -A to select all paths explicitly")); 731 cflags |= REG_ICASE;
760 err = regcomp(&re, optarg, cflags); 732 // Intentional fallthrough
761 if (err != 0) { 733 case 'i':
762 regerror (err, &re, errbuf, MAX_INPUT_BUFFER); 734 if (!path_selected)
763 die (STATE_UNKNOWN, "DISK %s: %s - %s\n",_("UNKNOWN"), _("Could not compile regular expression"), errbuf); 735 die(STATE_UNKNOWN, "DISK %s: %s\n", _("UNKNOWN"),
764 } 736 _("Paths need to be selected before using -i/-I. Use -A to select all paths explicitly"));
765 737 err = regcomp(&re, optarg, cflags);
766 temp_list = path_select_list; 738 if (err != 0) {
767 739 regerror(err, &re, errbuf, MAX_INPUT_BUFFER);
768 previous = NULL; 740 die(STATE_UNKNOWN, "DISK %s: %s - %s\n", _("UNKNOWN"), _("Could not compile regular expression"), errbuf);
769 while (temp_list) { 741 }
770 if (temp_list->best_match) { 742
771 if (np_regex_match_mount_entry(temp_list->best_match, &re)) { 743 temp_list = path_select_list;
772 744
773 if (verbose >=3) 745 previous = NULL;
774 printf("ignoring %s matching regex\n", temp_list->name); 746 while (temp_list) {
775 747 if (temp_list->best_match) {
776 temp_list = np_del_parameter(temp_list, previous); 748 if (np_regex_match_mount_entry(temp_list->best_match, &re)) {
777 /* pointer to first element needs to be updated if first item gets deleted */ 749
778 if (previous == NULL) 750 if (verbose >= 3)
779 path_select_list = temp_list; 751 printf("ignoring %s matching regex\n", temp_list->name);
780 } else { 752
781 previous = temp_list; 753 temp_list = np_del_parameter(temp_list, previous);
782 temp_list = temp_list->name_next; 754 /* pointer to first element needs to be updated if first item gets deleted */
783 } 755 if (previous == NULL)
784 } else { 756 path_select_list = temp_list;
785 previous = temp_list; 757 } else {
786 temp_list = temp_list->name_next; 758 previous = temp_list;
787 } 759 temp_list = temp_list->name_next;
788 } 760 }
789 761 } else {
790 762 previous = temp_list;
791 cflags = default_cflags; 763 temp_list = temp_list->name_next;
792 break; 764 }
793 765 }
794 case 'n': 766
795 ignore_missing = true; 767 cflags = default_cflags;
796 break; 768 break;
797 case 'A': 769
798 optarg = strdup(".*"); 770 case 'n':
799 // Intentional fallthrough 771 ignore_missing = true;
800 case 'R': 772 break;
801 cflags |= REG_ICASE; 773 case 'A':
802 // Intentional fallthrough 774 optarg = strdup(".*");
803 case 'r': 775 // Intentional fallthrough
804 if (! (warn_freespace_units || crit_freespace_units || warn_freespace_percent || 776 case 'R':
805 crit_freespace_percent || warn_usedspace_units || crit_usedspace_units || 777 cflags |= REG_ICASE;
806 warn_usedspace_percent || crit_usedspace_percent || warn_usedinodes_percent || 778 // Intentional fallthrough
807 crit_usedinodes_percent || warn_freeinodes_percent || crit_freeinodes_percent )) { 779 case 'r':
808 die (STATE_UNKNOWN, "DISK %s: %s", _("UNKNOWN"), _("Must set a threshold value before using -r/-R/-A (--ereg-path/--eregi-path/--all)\n")); 780 if (!(warn_freespace_units || crit_freespace_units || warn_freespace_percent || crit_freespace_percent ||
809 } 781 warn_usedspace_units || crit_usedspace_units || warn_usedspace_percent || crit_usedspace_percent ||
810 782 warn_usedinodes_percent || crit_usedinodes_percent || warn_freeinodes_percent || crit_freeinodes_percent)) {
811 err = regcomp(&re, optarg, cflags); 783 die(STATE_UNKNOWN, "DISK %s: %s", _("UNKNOWN"),
812 if (err != 0) { 784 _("Must set a threshold value before using -r/-R/-A (--ereg-path/--eregi-path/--all)\n"));
813 regerror (err, &re, errbuf, MAX_INPUT_BUFFER); 785 }
814 die (STATE_UNKNOWN, "DISK %s: %s - %s\n",_("UNKNOWN"), _("Could not compile regular expression"), errbuf); 786
815 } 787 err = regcomp(&re, optarg, cflags);
816 788 if (err != 0) {
817 for (me = mount_list; me; me = me->me_next) { 789 regerror(err, &re, errbuf, MAX_INPUT_BUFFER);
818 if (np_regex_match_mount_entry(me, &re)) { 790 die(STATE_UNKNOWN, "DISK %s: %s - %s\n", _("UNKNOWN"), _("Could not compile regular expression"), errbuf);
819 fnd = true; 791 }
820 if (verbose >= 3) 792
821 printf("%s %s matching expression %s\n", me->me_devname, me->me_mountdir, optarg); 793 for (me = mount_list; me; me = me->me_next) {
822 794 if (np_regex_match_mount_entry(me, &re)) {
823 /* add parameter if not found. overwrite thresholds if path has already been added */ 795 fnd = true;
824 if (! (se = np_find_parameter(path_select_list, me->me_mountdir))) { 796 if (verbose >= 3)
825 se = np_add_parameter(&path_select_list, me->me_mountdir); 797 printf("%s %s matching expression %s\n", me->me_devname, me->me_mountdir, optarg);
826 } 798
827 se->group = group; 799 /* add parameter if not found. overwrite thresholds if path has already been added */
828 set_all_thresholds(se); 800 if (!(se = np_find_parameter(path_select_list, me->me_mountdir))) {
829 } 801 se = np_add_parameter(&path_select_list, me->me_mountdir);
830 } 802 }
831 803 se->group = group;
832 if (!fnd && ignore_missing == true) { 804 set_all_thresholds(se);
833 path_ignored = true; 805 }
834 path_selected = true; 806 }
835 break; 807
836 } else if (!fnd) 808 if (!fnd && ignore_missing == true) {
837 die (STATE_UNKNOWN, "DISK %s: %s - %s\n",_("UNKNOWN"), 809 path_ignored = true;
838 _("Regular expression did not match any path or disk"), optarg); 810 path_selected = true;
839 811 break;
840 fnd = false; 812 }
841 path_selected = true; 813 if (!fnd)
842 np_set_best_match(path_select_list, mount_list, exact_match); 814 die(STATE_UNKNOWN, "DISK %s: %s - %s\n", _("UNKNOWN"), _("Regular expression did not match any path or disk"), optarg);
843 cflags = default_cflags; 815
844 816 fnd = false;
845 break; 817 path_selected = true;
846 case 'M': /* display mountpoint */ 818 np_set_best_match(path_select_list, mount_list, exact_match);
847 display_mntp = true; 819 cflags = default_cflags;
848 break; 820
849 case 'C': 821 break;
850 /* add all mount entries to path_select list if no partitions have been explicitly defined using -p */ 822 case 'M': /* display mountpoint */
851 if (path_selected == false) { 823 display_mntp = true;
852 struct parameter_list *path; 824 break;
853 for (me = mount_list; me; me = me->me_next) { 825 case 'C':
854 if (! (path = np_find_parameter(path_select_list, me->me_mountdir))) 826 /* add all mount entries to path_select list if no partitions have been explicitly defined using -p */
855 path = np_add_parameter(&path_select_list, me->me_mountdir); 827 if (path_selected == false) {
856 path->best_match = me; 828 struct parameter_list *path;
857 path->group = group; 829 for (me = mount_list; me; me = me->me_next) {
858 set_all_thresholds(path); 830 if (!(path = np_find_parameter(path_select_list, me->me_mountdir)))
859 } 831 path = np_add_parameter(&path_select_list, me->me_mountdir);
860 } 832 path->best_match = me;
861 warn_freespace_units = NULL; 833 path->group = group;
862 crit_freespace_units = NULL; 834 set_all_thresholds(path);
863 warn_usedspace_units = NULL; 835 }
864 crit_usedspace_units = NULL; 836 }
865 warn_freespace_percent = NULL; 837 warn_freespace_units = NULL;
866 crit_freespace_percent = NULL; 838 crit_freespace_units = NULL;
867 warn_usedspace_percent = NULL; 839 warn_usedspace_units = NULL;
868 crit_usedspace_percent = NULL; 840 crit_usedspace_units = NULL;
869 warn_usedinodes_percent = NULL; 841 warn_freespace_percent = NULL;
870 crit_usedinodes_percent = NULL; 842 crit_freespace_percent = NULL;
871 warn_freeinodes_percent = NULL; 843 warn_usedspace_percent = NULL;
872 crit_freeinodes_percent = NULL; 844 crit_usedspace_percent = NULL;
873 845 warn_usedinodes_percent = NULL;
874 path_selected = false; 846 crit_usedinodes_percent = NULL;
875 group = NULL; 847 warn_freeinodes_percent = NULL;
876 break; 848 crit_freeinodes_percent = NULL;
877 case 'V': /* version */ 849
878 print_revision (progname, NP_VERSION); 850 path_selected = false;
879 exit (STATE_UNKNOWN); 851 group = NULL;
880 case 'h': /* help */ 852 break;
881 print_help (); 853 case 'V': /* version */
882 exit (STATE_UNKNOWN); 854 print_revision(progname, NP_VERSION);
883 case '?': /* help */ 855 exit(STATE_UNKNOWN);
884 usage (_("Unknown argument")); 856 case 'h': /* help */
885 } 857 print_help();
886 } 858 exit(STATE_UNKNOWN);
887 859 case '?': /* help */
888 /* Support for "check_disk warn crit [fs]" with thresholds at used% level */ 860 usage(_("Unknown argument"));
889 c = optind; 861 }
890 if (warn_usedspace_percent == NULL && argc > c && is_intnonneg (argv[c])) 862 }
891 warn_usedspace_percent = argv[c++]; 863
892 864 /* Support for "check_disk warn crit [fs]" with thresholds at used% level */
893 if (crit_usedspace_percent == NULL && argc > c && is_intnonneg (argv[c])) 865 c = optind;
894 crit_usedspace_percent = argv[c++]; 866 if (warn_usedspace_percent == NULL && argc > c && is_intnonneg(argv[c]))
895 867 warn_usedspace_percent = argv[c++];
896 if (argc > c) { 868
897 se = np_add_parameter(&path_select_list, strdup(argv[c++])); 869 if (crit_usedspace_percent == NULL && argc > c && is_intnonneg(argv[c]))
898 path_selected = true; 870 crit_usedspace_percent = argv[c++];
899 set_all_thresholds(se); 871
900 } 872 if (argc > c) {
901 873 se = np_add_parameter(&path_select_list, strdup(argv[c++]));
902 if (units == NULL) { 874 path_selected = true;
903 units = strdup ("MiB"); 875 set_all_thresholds(se);
904 mult = (uintmax_t)1024 * 1024; 876 }
905 } 877
906 878 if (units == NULL) {
907 return true; 879 units = strdup("MiB");
880 mult = (uintmax_t)1024 * 1024;
881 }
882
883 return true;
908} 884}
909 885
910 886void set_all_thresholds(struct parameter_list *path) {
911 887 if (path->freespace_units != NULL)
912void 888 free(path->freespace_units);
913print_path (const char *mypath) 889 set_thresholds(&path->freespace_units, warn_freespace_units, crit_freespace_units);
914{ 890 if (path->freespace_percent != NULL)
915 if (mypath == NULL) 891 free(path->freespace_percent);
916 printf ("\n"); 892 set_thresholds(&path->freespace_percent, warn_freespace_percent, crit_freespace_percent);
917 else 893 if (path->usedspace_units != NULL)
918 printf (_(" for %s\n"), mypath); 894 free(path->usedspace_units);
895 set_thresholds(&path->usedspace_units, warn_usedspace_units, crit_usedspace_units);
896 if (path->usedspace_percent != NULL)
897 free(path->usedspace_percent);
898 set_thresholds(&path->usedspace_percent, warn_usedspace_percent, crit_usedspace_percent);
899 if (path->usedinodes_percent != NULL)
900 free(path->usedinodes_percent);
901 set_thresholds(&path->usedinodes_percent, warn_usedinodes_percent, crit_usedinodes_percent);
902 if (path->freeinodes_percent != NULL)
903 free(path->freeinodes_percent);
904 set_thresholds(&path->freeinodes_percent, warn_freeinodes_percent, crit_freeinodes_percent);
919} 905}
920 906
921 907void print_help(void) {
922void 908 print_revision(progname, NP_VERSION);
923set_all_thresholds (struct parameter_list *path) 909
924{ 910 printf("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n");
925 if (path->freespace_units != NULL) free(path->freespace_units); 911 printf(COPYRIGHT, copyright, email);
926 set_thresholds(&path->freespace_units, warn_freespace_units, crit_freespace_units); 912
927 if (path->freespace_percent != NULL) free (path->freespace_percent); 913 printf("%s\n", _("This plugin checks the amount of used disk space on a mounted file system"));
928 set_thresholds(&path->freespace_percent, warn_freespace_percent, crit_freespace_percent); 914 printf("%s\n", _("and generates an alert if free space is less than one of the threshold values"));
929 if (path->usedspace_units != NULL) free (path->usedspace_units); 915
930 set_thresholds(&path->usedspace_units, warn_usedspace_units, crit_usedspace_units); 916 printf("\n\n");
931 if (path->usedspace_percent != NULL) free (path->usedspace_percent); 917
932 set_thresholds(&path->usedspace_percent, warn_usedspace_percent, crit_usedspace_percent); 918 print_usage();
933 if (path->usedinodes_percent != NULL) free (path->usedinodes_percent); 919
934 set_thresholds(&path->usedinodes_percent, warn_usedinodes_percent, crit_usedinodes_percent); 920 printf(UT_HELP_VRSN);
935 if (path->freeinodes_percent != NULL) free (path->freeinodes_percent); 921 printf(UT_EXTRA_OPTS);
936 set_thresholds(&path->freeinodes_percent, warn_freeinodes_percent, crit_freeinodes_percent); 922
923 printf(" %s\n", "-w, --warning=INTEGER");
924 printf(" %s\n", _("Exit with WARNING status if less than INTEGER units of disk are free"));
925 printf(" %s\n", "-w, --warning=PERCENT%");
926 printf(" %s\n", _("Exit with WARNING status if less than PERCENT of disk space is free"));
927 printf(" %s\n", "-c, --critical=INTEGER");
928 printf(" %s\n", _("Exit with CRITICAL status if less than INTEGER units of disk are free"));
929 printf(" %s\n", "-c, --critical=PERCENT%");
930 printf(" %s\n", _("Exit with CRITICAL status if less than PERCENT of disk space is free"));
931 printf(" %s\n", "-W, --iwarning=PERCENT%");
932 printf(" %s\n", _("Exit with WARNING status if less than PERCENT of inode space is free"));
933 printf(" %s\n", "-K, --icritical=PERCENT%");
934 printf(" %s\n", _("Exit with CRITICAL status if less than PERCENT of inode space is free"));
935 printf(" %s\n", "-p, --path=PATH, --partition=PARTITION");
936 printf(" %s\n", _("Mount point or block device as emitted by the mount(8) command (may be repeated)"));
937 printf(" %s\n", "-x, --exclude_device=PATH <STRING>");
938 printf(" %s\n", _("Ignore device (only works if -p unspecified)"));
939 printf(" %s\n", "-C, --clear");
940 printf(" %s\n", _("Clear thresholds"));
941 printf(" %s\n", "-E, --exact-match");
942 printf(" %s\n", _("For paths or partitions specified with -p, only check for exact paths"));
943 printf(" %s\n", "-e, --errors-only");
944 printf(" %s\n", _("Display only devices/mountpoints with errors"));
945 printf(" %s\n", "-f, --freespace-ignore-reserved");
946 printf(" %s\n", _("Don't account root-reserved blocks into freespace in perfdata"));
947 printf(" %s\n", "-P, --iperfdata");
948 printf(" %s\n", _("Display inode usage in perfdata"));
949 printf(" %s\n", "-g, --group=NAME");
950 printf(" %s\n", _("Group paths. Thresholds apply to (free-)space of all partitions together"));
951 printf(" %s\n", "-k, --kilobytes");
952 printf(" %s\n", _("Same as '--units kB'"));
953 printf(" %s\n", "-l, --local");
954 printf(" %s\n", _("Only check local filesystems"));
955 printf(" %s\n", "-L, --stat-remote-fs");
956 printf(" %s\n", _("Only check local filesystems against thresholds. Yet call stat on remote filesystems"));
957 printf(" %s\n", _("to test if they are accessible (e.g. to detect Stale NFS Handles)"));
958 printf(" %s\n", "-M, --mountpoint");
959 printf(" %s\n", _("Display the (block) device instead of the mount point"));
960 printf(" %s\n", "-m, --megabytes");
961 printf(" %s\n", _("Same as '--units MB'"));
962 printf(" %s\n", "-A, --all");
963 printf(" %s\n", _("Explicitly select all paths. This is equivalent to -R '.*'"));
964 printf(" %s\n", "-R, --eregi-path=PATH, --eregi-partition=PARTITION");
965 printf(" %s\n", _("Case insensitive regular expression for path/partition (may be repeated)"));
966 printf(" %s\n", "-r, --ereg-path=PATH, --ereg-partition=PARTITION");
967 printf(" %s\n", _("Regular expression for path or partition (may be repeated)"));
968 printf(" %s\n", "-I, --ignore-eregi-path=PATH, --ignore-eregi-partition=PARTITION");
969 printf(" %s\n", _("Regular expression to ignore selected path/partition (case insensitive) (may be repeated)"));
970 printf(" %s\n", "-i, --ignore-ereg-path=PATH, --ignore-ereg-partition=PARTITION");
971 printf(" %s\n", _("Regular expression to ignore selected path or partition (may be repeated)"));
972 printf(" %s\n", "-n, --ignore-missing");
973 printf(" %s\n", _("Return OK if no filesystem matches, filesystem does not exist or is inaccessible."));
974 printf(" %s\n", _("(Provide this option before -p / -r / --ereg-path if used)"));
975 printf(UT_PLUG_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
976 printf(" %s\n", "-u, --units=STRING");
977 printf(" %s\n", _("Choose bytes, kB, MB, GB, TB (default: MB)"));
978 printf(UT_VERBOSE);
979 printf(" %s\n", "-X, --exclude-type=TYPE_REGEX");
980 printf(" %s\n", _("Ignore all filesystems of types matching given regex(7) (may be repeated)"));
981 printf(" %s\n", "-N, --include-type=TYPE_REGEX");
982 printf(" %s\n", _("Check only filesystems where the type matches this given regex(7) (may be repeated)"));
983
984 printf("\n");
985 printf("%s\n", _("General usage hints:"));
986 printf(" %s\n", _("- Arguments are positional! \"-w 5 -c 1 -p /foo -w6 -c2 -p /bar\" is not the same as"));
987 printf(" %s\n", _("\"-w 5 -c 1 -p /bar w6 -c2 -p /foo\"."));
988 printf(" %s\n", _("- The syntax is broadly: \"{thresholds a} {paths a} -C {thresholds b} {thresholds b} ...\""));
989
990 printf("\n");
991 printf("%s\n", _("Examples:"));
992 printf(" %s\n", "check_disk -w 10% -c 5% -p /tmp -p /var -C -w 100000 -c 50000 -p /");
993 printf(" %s\n\n", _("Checks /tmp and /var at 10% and 5%, and / at 100MB and 50MB"));
994 printf(" %s\n", "check_disk -w 100 -c 50 -C -w 1000 -c 500 -g sidDATA -r '^/oracle/SID/data.*$'");
995 printf(" %s\n", _("Checks all filesystems not matching -r at 100M and 50M. The fs matching the -r regex"));
996 printf(" %s\n\n", _("are grouped which means the freespace thresholds are applied to all disks together"));
997 printf(" %s\n", "check_disk -w 100 -c 50 -C -w 1000 -c 500 -p /foo -C -w 5% -c 3% -p /bar");
998 printf(" %s\n", _("Checks /foo for 1000M/500M and /bar for 5/3%. All remaining volumes use 100M/50M"));
999
1000 printf(UT_SUPPORT);
937} 1001}
938 1002
939void 1003void print_usage(void) {
940print_help (void) 1004 printf("%s\n", _("Usage:"));
941{ 1005 printf(" %s {-w absolute_limit |-w percentage_limit%% | -W inode_percentage_limit } {-c absolute_limit|-c percentage_limit%% | -K "
942 print_revision (progname, NP_VERSION); 1006 "inode_percentage_limit } {-p path | -x device}\n",
943 1007 progname);
944 printf ("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n"); 1008 printf("[-C] [-E] [-e] [-f] [-g group ] [-k] [-l] [-M] [-m] [-R path ] [-r path ]\n");
945 printf (COPYRIGHT, copyright, email); 1009 printf("[-t timeout] [-u unit] [-v] [-X type_regex] [-N type]\n");
946
947 printf ("%s\n", _("This plugin checks the amount of used disk space on a mounted file system"));
948 printf ("%s\n", _("and generates an alert if free space is less than one of the threshold values"));
949
950 printf ("\n\n");
951
952 print_usage ();
953
954 printf (UT_HELP_VRSN);
955 printf (UT_EXTRA_OPTS);
956
957 printf (" %s\n", "-w, --warning=INTEGER");
958 printf (" %s\n", _("Exit with WARNING status if less than INTEGER units of disk are free"));
959 printf (" %s\n", "-w, --warning=PERCENT%");
960 printf (" %s\n", _("Exit with WARNING status if less than PERCENT of disk space is free"));
961 printf (" %s\n", "-c, --critical=INTEGER");
962 printf (" %s\n", _("Exit with CRITICAL status if less than INTEGER units of disk are free"));
963 printf (" %s\n", "-c, --critical=PERCENT%");
964 printf (" %s\n", _("Exit with CRITICAL status if less than PERCENT of disk space is free"));
965 printf (" %s\n", "-W, --iwarning=PERCENT%");
966 printf (" %s\n", _("Exit with WARNING status if less than PERCENT of inode space is free"));
967 printf (" %s\n", "-K, --icritical=PERCENT%");
968 printf (" %s\n", _("Exit with CRITICAL status if less than PERCENT of inode space is free"));
969 printf (" %s\n", "-p, --path=PATH, --partition=PARTITION");
970 printf (" %s\n", _("Mount point or block device as emitted by the mount(8) command (may be repeated)"));
971 printf (" %s\n", "-x, --exclude_device=PATH <STRING>");
972 printf (" %s\n", _("Ignore device (only works if -p unspecified)"));
973 printf (" %s\n", "-C, --clear");
974 printf (" %s\n", _("Clear thresholds"));
975 printf (" %s\n", "-E, --exact-match");
976 printf (" %s\n", _("For paths or partitions specified with -p, only check for exact paths"));
977 printf (" %s\n", "-e, --errors-only");
978 printf (" %s\n", _("Display only devices/mountpoints with errors"));
979 printf (" %s\n", "-f, --freespace-ignore-reserved");
980 printf (" %s\n", _("Don't account root-reserved blocks into freespace in perfdata"));
981 printf (" %s\n", "-P, --iperfdata");
982 printf (" %s\n", _("Display inode usage in perfdata"));
983 printf (" %s\n", "-g, --group=NAME");
984 printf (" %s\n", _("Group paths. Thresholds apply to (free-)space of all partitions together"));
985 printf (" %s\n", "-k, --kilobytes");
986 printf (" %s\n", _("Same as '--units kB'"));
987 printf (" %s\n", "-l, --local");
988 printf (" %s\n", _("Only check local filesystems"));
989 printf (" %s\n", "-L, --stat-remote-fs");
990 printf (" %s\n", _("Only check local filesystems against thresholds. Yet call stat on remote filesystems"));
991 printf (" %s\n", _("to test if they are accessible (e.g. to detect Stale NFS Handles)"));
992 printf (" %s\n", "-M, --mountpoint");
993 printf (" %s\n", _("Display the (block) device instead of the mount point"));
994 printf (" %s\n", "-m, --megabytes");
995 printf (" %s\n", _("Same as '--units MB'"));
996 printf (" %s\n", "-A, --all");
997 printf (" %s\n", _("Explicitly select all paths. This is equivalent to -R '.*'"));
998 printf (" %s\n", "-R, --eregi-path=PATH, --eregi-partition=PARTITION");
999 printf (" %s\n", _("Case insensitive regular expression for path/partition (may be repeated)"));
1000 printf (" %s\n", "-r, --ereg-path=PATH, --ereg-partition=PARTITION");
1001 printf (" %s\n", _("Regular expression for path or partition (may be repeated)"));
1002 printf (" %s\n", "-I, --ignore-eregi-path=PATH, --ignore-eregi-partition=PARTITION");
1003 printf (" %s\n", _("Regular expression to ignore selected path/partition (case insensitive) (may be repeated)"));
1004 printf (" %s\n", "-i, --ignore-ereg-path=PATH, --ignore-ereg-partition=PARTITION");
1005 printf (" %s\n", _("Regular expression to ignore selected path or partition (may be repeated)"));
1006 printf (" %s\n", "-n, --ignore-missing");
1007 printf (" %s\n", _("Return OK if no filesystem matches, filesystem does not exist or is inaccessible."));
1008 printf (" %s\n", _("(Provide this option before -p / -r / --ereg-path if used)"));
1009 printf (UT_PLUG_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
1010 printf (" %s\n", "-u, --units=STRING");
1011 printf (" %s\n", _("Choose bytes, kB, MB, GB, TB (default: MB)"));
1012 printf (UT_VERBOSE);
1013 printf (" %s\n", "-X, --exclude-type=TYPE_REGEX");
1014 printf (" %s\n", _("Ignore all filesystems of types matching given regex(7) (may be repeated)"));
1015 printf (" %s\n", "-N, --include-type=TYPE_REGEX");
1016 printf (" %s\n", _("Check only filesystems where the type matches this given regex(7) (may be repeated)"));
1017
1018 printf ("\n");
1019 printf ("%s\n", _("General usage hints:"));
1020 printf (" %s\n", _("- Arguments are positional! \"-w 5 -c 1 -p /foo -w6 -c2 -p /bar\" is not the same as"));
1021 printf (" %s\n", _("\"-w 5 -c 1 -p /bar w6 -c2 -p /foo\"."));
1022 printf (" %s\n", _("- The syntax is broadly: \"{thresholds a} {paths a} -C {thresholds b} {thresholds b} ...\""));
1023
1024
1025
1026 printf ("\n");
1027 printf ("%s\n", _("Examples:"));
1028 printf (" %s\n", "check_disk -w 10% -c 5% -p /tmp -p /var -C -w 100000 -c 50000 -p /");
1029 printf (" %s\n\n", _("Checks /tmp and /var at 10% and 5%, and / at 100MB and 50MB"));
1030 printf (" %s\n", "check_disk -w 100 -c 50 -C -w 1000 -c 500 -g sidDATA -r '^/oracle/SID/data.*$'");
1031 printf (" %s\n", _("Checks all filesystems not matching -r at 100M and 50M. The fs matching the -r regex"));
1032 printf (" %s\n\n", _("are grouped which means the freespace thresholds are applied to all disks together"));
1033 printf (" %s\n", "check_disk -w 100 -c 50 -C -w 1000 -c 500 -p /foo -C -w 5% -c 3% -p /bar");
1034 printf (" %s\n", _("Checks /foo for 1000M/500M and /bar for 5/3%. All remaining volumes use 100M/50M"));
1035
1036 printf (UT_SUPPORT);
1037} 1010}
1038 1011
1039 1012bool stat_path(struct parameter_list *p) {
1040 1013 /* Stat entry to check that dir exists and is accessible */
1041void 1014 if (verbose >= 3)
1042print_usage (void) 1015 printf("calling stat on %s\n", p->name);
1043{ 1016 if (stat(p->name, &stat_buf[0])) {
1044 printf ("%s\n", _("Usage:")); 1017 if (verbose >= 3)
1045 printf (" %s {-w absolute_limit |-w percentage_limit%% | -W inode_percentage_limit } {-c absolute_limit|-c percentage_limit%% | -K inode_percentage_limit } {-p path | -x device}\n", progname); 1018 printf("stat failed on %s\n", p->name);
1046 printf ("[-C] [-E] [-e] [-f] [-g group ] [-k] [-l] [-M] [-m] [-R path ] [-r path ]\n"); 1019 if (ignore_missing == true) {
1047 printf ("[-t timeout] [-u unit] [-v] [-X type_regex] [-N type]\n"); 1020 return false;
1048} 1021 }
1049 1022 printf("DISK %s - ", _("CRITICAL"));
1050bool 1023 die(STATE_CRITICAL, _("%s %s: %s\n"), p->name, _("is not accessible"), strerror(errno));
1051stat_path (struct parameter_list *p) 1024 }
1052{ 1025 return true;
1053 /* Stat entry to check that dir exists and is accessible */
1054 if (verbose >= 3)
1055 printf("calling stat on %s\n", p->name);
1056 if (stat (p->name, &stat_buf[0])) {
1057 if (verbose >= 3)
1058 printf("stat failed on %s\n", p->name);
1059 if (ignore_missing == true) {
1060 return false;
1061 } else {
1062 printf("DISK %s - ", _("CRITICAL"));
1063 die (STATE_CRITICAL, _("%s %s: %s\n"), p->name, _("is not accessible"), strerror(errno));
1064 }
1065 }
1066 return true;
1067} 1026}
1068 1027
1028void get_stats(struct parameter_list *p, struct fs_usage *fsp) {
1029 struct parameter_list *p_list;
1030 struct fs_usage tmpfsp;
1031 int first = 1;
1069 1032
1070void 1033 if (p->group == NULL) {
1071get_stats (struct parameter_list *p, struct fs_usage *fsp) { 1034 get_path_stats(p, fsp);
1072 struct parameter_list *p_list; 1035 } else {
1073 struct fs_usage tmpfsp; 1036 /* find all group members */
1074 int first = 1; 1037 for (p_list = path_select_list; p_list; p_list = p_list->name_next) {
1075
1076 if (p->group == NULL) {
1077 get_path_stats(p,fsp);
1078 } else {
1079 /* find all group members */
1080 for (p_list = path_select_list; p_list; p_list=p_list->name_next) {
1081#ifdef __CYGWIN__ 1038#ifdef __CYGWIN__
1082 if (strncmp(p_list->name, "/cygdrive/", 10) != 0) 1039 if (strncmp(p_list->name, "/cygdrive/", 10) != 0)
1083 continue; 1040 continue;
1084#endif 1041#endif
1085 if (p_list->group && ! (strcmp(p_list->group, p->group))) { 1042 if (p_list->group && !(strcmp(p_list->group, p->group))) {
1086 if (! stat_path(p_list)) 1043 if (!stat_path(p_list))
1087 continue; 1044 continue;
1088 get_fs_usage (p_list->best_match->me_mountdir, p_list->best_match->me_devname, &tmpfsp); 1045 get_fs_usage(p_list->best_match->me_mountdir, p_list->best_match->me_devname, &tmpfsp);
1089 get_path_stats(p_list, &tmpfsp); 1046 get_path_stats(p_list, &tmpfsp);
1090 if (verbose >= 3) 1047 if (verbose >= 3)
1091 printf("Group %s: adding %lu blocks sized %lu, (%s) used_units=%lu free_units=%lu total_units=%lu mult=%lu\n", 1048 printf("Group %s: adding %lu blocks sized %lu, (%s) used_units=%lu free_units=%lu total_units=%lu mult=%lu\n",
1092 p_list->group, 1049 p_list->group, tmpfsp.fsu_blocks, tmpfsp.fsu_blocksize, p_list->best_match->me_mountdir, p_list->dused_units,
1093 tmpfsp.fsu_blocks, 1050 p_list->dfree_units, p_list->dtotal_units, mult);
1094 tmpfsp.fsu_blocksize, 1051
1095 p_list->best_match->me_mountdir, 1052 /* prevent counting the first FS of a group twice since its parameter_list entry
1096 p_list->dused_units, 1053 * is used to carry the information of all file systems of the entire group */
1097 p_list->dfree_units, 1054 if (!first) {
1098 p_list->dtotal_units, 1055 p->total += p_list->total;
1099 mult); 1056 p->available += p_list->available;
1100 1057 p->available_to_root += p_list->available_to_root;
1101 /* prevent counting the first FS of a group twice since its parameter_list entry 1058 p->used += p_list->used;
1102 * is used to carry the information of all file systems of the entire group */ 1059
1103 if (! first) { 1060 p->dused_units += p_list->dused_units;
1104 p->total += p_list->total; 1061 p->dfree_units += p_list->dfree_units;
1105 p->available += p_list->available; 1062 p->dtotal_units += p_list->dtotal_units;
1106 p->available_to_root += p_list->available_to_root; 1063 p->inodes_total += p_list->inodes_total;
1107 p->used += p_list->used; 1064 p->inodes_free += p_list->inodes_free;
1108 1065 p->inodes_free_to_root += p_list->inodes_free_to_root;
1109 p->dused_units += p_list->dused_units; 1066 p->inodes_used += p_list->inodes_used;
1110 p->dfree_units += p_list->dfree_units; 1067 }
1111 p->dtotal_units += p_list->dtotal_units; 1068 first = 0;
1112 p->inodes_total += p_list->inodes_total; 1069 }
1113 p->inodes_free += p_list->inodes_free; 1070 if (verbose >= 3)
1114 p->inodes_free_to_root += p_list->inodes_free_to_root; 1071 printf("Group %s now has: used_units=%lu free_units=%lu total_units=%lu fsu_blocksize=%lu mult=%lu\n", p->group,
1115 p->inodes_used += p_list->inodes_used; 1072 p->dused_units, p->dfree_units, p->dtotal_units, tmpfsp.fsu_blocksize, mult);
1116 } 1073 }
1117 first = 0; 1074 /* modify devname and mountdir for output */
1118 } 1075 p->best_match->me_mountdir = p->best_match->me_devname = p->group;
1119 if (verbose >= 3) 1076 }
1120 printf("Group %s now has: used_units=%lu free_units=%lu total_units=%lu fsu_blocksize=%lu mult=%lu\n", 1077 /* finally calculate percentages for either plain FS or summed up group */
1121 p->group, 1078 p->dused_pct = calculate_percent(p->used, p->used + p->available); /* used + available can never be > uintmax */
1122 p->dused_units, 1079 p->dfree_pct = 100.0 - p->dused_pct;
1123 p->dfree_units, 1080 p->dused_inodes_percent = calculate_percent(p->inodes_total - p->inodes_free, p->inodes_total);
1124 p->dtotal_units, 1081 p->dfree_inodes_percent = 100 - p->dused_inodes_percent;
1125 tmpfsp.fsu_blocksize,
1126 mult);
1127 }
1128 /* modify devname and mountdir for output */
1129 p->best_match->me_mountdir = p->best_match->me_devname = p->group;
1130 }
1131 /* finally calculate percentages for either plain FS or summed up group */
1132 p->dused_pct = calculate_percent( p->used, p->used + p->available ); /* used + available can never be > uintmax */
1133 p->dfree_pct = 100 - p->dused_pct;
1134 p->dused_inodes_percent = calculate_percent(p->inodes_total - p->inodes_free, p->inodes_total);
1135 p->dfree_inodes_percent = 100 - p->dused_inodes_percent;
1136
1137} 1082}
1138 1083
1139void 1084void get_path_stats(struct parameter_list *p, struct fs_usage *fsp) {
1140get_path_stats (struct parameter_list *p, struct fs_usage *fsp) { 1085 p->available = fsp->fsu_bavail;
1141 p->available = fsp->fsu_bavail; 1086 p->available_to_root = fsp->fsu_bfree;
1142 p->available_to_root = fsp->fsu_bfree; 1087 p->used = fsp->fsu_blocks - fsp->fsu_bfree;
1143 p->used = fsp->fsu_blocks - fsp->fsu_bfree; 1088 if (freespace_ignore_reserved) {
1144 if (freespace_ignore_reserved) { 1089 /* option activated : we subtract the root-reserved space from the total */
1145 /* option activated : we subtract the root-reserved space from the total */ 1090 p->total = fsp->fsu_blocks - p->available_to_root + p->available;
1146 p->total = fsp->fsu_blocks - p->available_to_root + p->available; 1091 } else {
1147 } else { 1092 /* default behaviour : take all the blocks into account */
1148 /* default behaviour : take all the blocks into account */ 1093 p->total = fsp->fsu_blocks;
1149 p->total = fsp->fsu_blocks; 1094 }
1150 } 1095
1151 1096 p->dused_units = p->used * fsp->fsu_blocksize / mult;
1152 p->dused_units = p->used*fsp->fsu_blocksize/mult; 1097 p->dfree_units = p->available * fsp->fsu_blocksize / mult;
1153 p->dfree_units = p->available*fsp->fsu_blocksize/mult; 1098 p->dtotal_units = p->total * fsp->fsu_blocksize / mult;
1154 p->dtotal_units = p->total*fsp->fsu_blocksize/mult; 1099 /* Free file nodes. Not sure the workaround is required, but in case...*/
1155 /* Free file nodes. Not sure the workaround is required, but in case...*/ 1100 p->inodes_free = fsp->fsu_ffree;
1156 p->inodes_free = fsp->fsu_ffree; 1101 p->inodes_free_to_root = fsp->fsu_ffree; /* Free file nodes for root. */
1157 p->inodes_free_to_root = fsp->fsu_ffree; /* Free file nodes for root. */ 1102 p->inodes_used = fsp->fsu_files - fsp->fsu_ffree;
1158 p->inodes_used = fsp->fsu_files - fsp->fsu_ffree; 1103 if (freespace_ignore_reserved) {
1159 if (freespace_ignore_reserved) { 1104 /* option activated : we subtract the root-reserved inodes from the total */
1160 /* option activated : we subtract the root-reserved inodes from the total */ 1105 /* not all OS report fsp->fsu_favail, only the ones with statvfs syscall */
1161 /* not all OS report fsp->fsu_favail, only the ones with statvfs syscall */ 1106 /* for others, fsp->fsu_ffree == fsp->fsu_favail */
1162 /* for others, fsp->fsu_ffree == fsp->fsu_favail */ 1107 p->inodes_total = fsp->fsu_files - p->inodes_free_to_root + p->inodes_free;
1163 p->inodes_total = fsp->fsu_files - p->inodes_free_to_root + p->inodes_free; 1108 } else {
1164 } else { 1109 /* default behaviour : take all the inodes into account */
1165 /* default behaviour : take all the inodes into account */ 1110 p->inodes_total = fsp->fsu_files;
1166 p->inodes_total = fsp->fsu_files; 1111 }
1167 } 1112 np_add_name(&seen, p->best_match->me_mountdir);
1168 np_add_name(&seen, p->best_match->me_mountdir);
1169} 1113}
diff --git a/plugins/check_dns.c b/plugins/check_dns.c
index 468bc958..e1e7c00e 100644
--- a/plugins/check_dns.c
+++ b/plugins/check_dns.c
@@ -1,36 +1,36 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring check_dns plugin 3 * Monitoring check_dns plugin
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 2000-2008 Monitoring Plugins Development Team 6 * Copyright (c) 2000-2024 Monitoring Plugins Development Team
7* 7 *
8* Description: 8 * Description:
9* 9 *
10* This file contains the check_dns plugin 10 * This file contains the check_dns plugin
11* 11 *
12* LIMITATION: nslookup on Solaris 7 can return output over 2 lines, which 12 * LIMITATION: nslookup on Solaris 7 can return output over 2 lines, which
13* will not be picked up by this plugin 13 * will not be picked up by this plugin
14* 14 *
15* 15 *
16* This program is free software: you can redistribute it and/or modify 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 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 18 * the Free Software Foundation, either version 3 of the License, or
19* (at your option) any later version. 19 * (at your option) any later version.
20* 20 *
21* This program is distributed in the hope that it will be useful, 21 * This program is distributed in the hope that it will be useful,
22* but WITHOUT ANY WARRANTY; without even the implied warranty of 22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24* GNU General Public License for more details. 24 * GNU General Public License for more details.
25* 25 *
26* You should have received a copy of the GNU General Public License 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/>. 27 * along with this program. If not, see <http://www.gnu.org/licenses/>.
28* 28 *
29* 29 *
30*****************************************************************************/ 30 *****************************************************************************/
31 31
32const char *progname = "check_dns"; 32const char *progname = "check_dns";
33const char *copyright = "2000-2008"; 33const char *copyright = "2000-2024";
34const char *email = "devel@monitoring-plugins.org"; 34const char *email = "devel@monitoring-plugins.org";
35 35
36#include "common.h" 36#include "common.h"
@@ -39,579 +39,534 @@ const char *email = "devel@monitoring-plugins.org";
39#include "netutils.h" 39#include "netutils.h"
40#include "runcmd.h" 40#include "runcmd.h"
41 41
42int process_arguments (int, char **); 42static int process_arguments(int /*argc*/, char ** /*argv*/);
43int validate_arguments (void); 43static int validate_arguments(void);
44int error_scan (char *, bool *); 44static int error_scan(char * /*input_buffer*/, bool *);
45bool ip_match_cidr(const char *, const char *); 45static bool ip_match_cidr(const char * /*addr*/, const char * /*cidr_ro*/);
46unsigned long ip2long(const char *); 46static unsigned long ip2long(const char * /*src*/);
47void print_help (void); 47static void print_help(void);
48void print_usage (void); 48void print_usage(void);
49 49
50#define ADDRESS_LENGTH 256 50#define ADDRESS_LENGTH 256
51char query_address[ADDRESS_LENGTH] = ""; 51static char query_address[ADDRESS_LENGTH] = "";
52char dns_server[ADDRESS_LENGTH] = ""; 52static char dns_server[ADDRESS_LENGTH] = "";
53char ptr_server[ADDRESS_LENGTH] = ""; 53static char ptr_server[ADDRESS_LENGTH] = "";
54bool verbose = false; 54static bool verbose = false;
55char **expected_address = NULL; 55static char **expected_address = NULL;
56int expected_address_cnt = 0; 56static int expected_address_cnt = 0;
57bool expect_nxdomain = false; 57static bool expect_nxdomain = false;
58 58
59bool expect_authority = false; 59static bool expect_authority = false;
60bool all_match = false; 60static bool all_match = false;
61thresholds *time_thresholds = NULL; 61static thresholds *time_thresholds = NULL;
62 62
63static int 63static int qstrcmp(const void *p1, const void *p2) {
64qstrcmp(const void *p1, const void *p2)
65{
66 /* The actual arguments to this function are "pointers to 64 /* The actual arguments to this function are "pointers to
67 pointers to char", but strcmp() arguments are "pointers 65 pointers to char", but strcmp() arguments are "pointers
68 to char", hence the following cast plus dereference */ 66 to char", hence the following cast plus dereference */
69 return strcmp(* (char * const *) p1, * (char * const *) p2); 67 return strcmp(*(char *const *)p1, *(char *const *)p2);
70} 68}
71 69
70int main(int argc, char **argv) {
71 char *command_line = NULL;
72 char input_buffer[MAX_INPUT_BUFFER];
73 char *address = NULL; /* comma separated str with addrs/ptrs (sorted) */
74 char **addresses = NULL;
75 int n_addresses = 0;
76 char *msg = NULL;
77 char *temp_buffer = NULL;
78 bool non_authoritative = false;
79 int result = STATE_UNKNOWN;
80 double elapsed_time;
81 long microsec;
82 struct timeval tv;
83 bool parse_address = false; /* This flag scans for Address: but only after Name: */
84 output chld_out;
85 output chld_err;
86 bool is_nxdomain = false;
87
88 setlocale(LC_ALL, "");
89 bindtextdomain(PACKAGE, LOCALEDIR);
90 textdomain(PACKAGE);
91
92 /* Set signal handling and alarm */
93 if (signal(SIGALRM, runcmd_timeout_alarm_handler) == SIG_ERR) {
94 usage_va(_("Cannot catch SIGALRM"));
95 }
96
97 /* Parse extra opts if any */
98 argv = np_extra_opts(&argc, argv, progname);
99
100 if (process_arguments(argc, argv) == ERROR) {
101 usage_va(_("Could not parse arguments"));
102 }
103
104 /* get the command to run */
105 xasprintf(&command_line, "%s %s %s", NSLOOKUP_COMMAND, query_address, dns_server);
106
107 alarm(timeout_interval);
108 gettimeofday(&tv, NULL);
109
110 if (verbose)
111 printf("%s\n", command_line);
112
113 /* run the command */
114 if ((np_runcmd(command_line, &chld_out, &chld_err, 0)) != 0) {
115 msg = (char *)_("nslookup returned an error status");
116 result = STATE_WARNING;
117 }
118
119 /* scan stdout */
120 for (size_t i = 0; i < chld_out.lines; i++) {
121 if (addresses == NULL)
122 addresses = malloc(sizeof(*addresses) * 10);
123 else if (!(n_addresses % 10))
124 addresses = realloc(addresses, sizeof(*addresses) * (n_addresses + 10));
125
126 if (verbose)
127 puts(chld_out.line[i]);
128
129 if (strcasestr(chld_out.line[i], ".in-addr.arpa") || strcasestr(chld_out.line[i], ".ip6.arpa")) {
130 if ((temp_buffer = strstr(chld_out.line[i], "name = ")))
131 addresses[n_addresses++] = strdup(temp_buffer + 7);
132 else {
133 msg = (char *)_("Warning plugin error");
134 result = STATE_WARNING;
135 }
136 }
137
138 /* bug ID: 2946553 - Older versions of bind will use all available dns
139 servers, we have to match the one specified */
140 if (strstr(chld_out.line[i], "Server:") && strlen(dns_server) > 0) {
141 temp_buffer = strchr(chld_out.line[i], ':');
142 temp_buffer++;
143
144 /* Strip leading tabs */
145 for (; *temp_buffer != '\0' && *temp_buffer == '\t'; temp_buffer++)
146 /* NOOP */;
147
148 strip(temp_buffer);
149 if (temp_buffer == NULL || strlen(temp_buffer) == 0) {
150 die(STATE_CRITICAL, _("DNS CRITICAL - '%s' returned empty server string\n"), NSLOOKUP_COMMAND);
151 }
152
153 if (strcmp(temp_buffer, dns_server) != 0) {
154 die(STATE_CRITICAL, _("DNS CRITICAL - No response from DNS %s\n"), dns_server);
155 }
156 }
157
158 /* the server is responding, we just got the host name... */
159 if (strstr(chld_out.line[i], "Name:"))
160 parse_address = true;
161 else if (parse_address && (strstr(chld_out.line[i], "Address:") || strstr(chld_out.line[i], "Addresses:"))) {
162 temp_buffer = index(chld_out.line[i], ':');
163 temp_buffer++;
164
165 /* Strip leading spaces */
166 while (*temp_buffer == ' ')
167 temp_buffer++;
168
169 strip(temp_buffer);
170 if (temp_buffer == NULL || strlen(temp_buffer) == 0) {
171 die(STATE_CRITICAL, _("DNS CRITICAL - '%s' returned empty host name string\n"), NSLOOKUP_COMMAND);
172 }
173
174 addresses[n_addresses++] = strdup(temp_buffer);
175 } else if (strstr(chld_out.line[i], _("Non-authoritative answer:"))) {
176 non_authoritative = true;
177 }
178
179 result = error_scan(chld_out.line[i], &is_nxdomain);
180 if (result != STATE_OK) {
181 msg = strchr(chld_out.line[i], ':');
182 if (msg)
183 msg++;
184 break;
185 }
186 }
187
188 /* scan stderr */
189 for (size_t i = 0; i < chld_err.lines; i++) {
190 if (verbose)
191 puts(chld_err.line[i]);
192
193 if (error_scan(chld_err.line[i], &is_nxdomain) != STATE_OK) {
194 result = max_state(result, error_scan(chld_err.line[i], &is_nxdomain));
195 msg = strchr(input_buffer, ':');
196 if (msg)
197 msg++;
198 else
199 msg = input_buffer;
200 }
201 }
202
203 if (is_nxdomain && !expect_nxdomain) {
204 die(STATE_CRITICAL, _("Domain '%s' was not found by the server\n"), query_address);
205 }
72 206
73int 207 if (addresses) {
74main (int argc, char **argv) 208 int i;
75{ 209 int slen;
76 char *command_line = NULL; 210 char *adrp;
77 char input_buffer[MAX_INPUT_BUFFER]; 211 qsort(addresses, n_addresses, sizeof(*addresses), qstrcmp);
78 char *address = NULL; /* comma separated str with addrs/ptrs (sorted) */ 212 for (i = 0, slen = 1; i < n_addresses; i++) {
79 char **addresses = NULL; 213 slen += strlen(addresses[i]) + 1;
80 int n_addresses = 0; 214 }
81 char *msg = NULL; 215 adrp = address = malloc(slen);
82 char *temp_buffer = NULL; 216 for (i = 0; i < n_addresses; i++) {
83 bool non_authoritative = false; 217 if (i)
84 int result = STATE_UNKNOWN; 218 *adrp++ = ',';
85 double elapsed_time; 219 strcpy(adrp, addresses[i]);
86 long microsec; 220 adrp += strlen(addresses[i]);
87 struct timeval tv; 221 }
88 bool parse_address = false; /* This flag scans for Address: but only after Name: */ 222 *adrp = 0;
89 output chld_out, chld_err; 223 } else
90 bool is_nxdomain = false; 224 die(STATE_CRITICAL, _("DNS CRITICAL - '%s' msg parsing exited with no address\n"), NSLOOKUP_COMMAND);
91 225
92 setlocale (LC_ALL, ""); 226 /* compare to expected address */
93 bindtextdomain (PACKAGE, LOCALEDIR); 227 if (result == STATE_OK && expected_address_cnt > 0) {
94 textdomain (PACKAGE); 228 result = STATE_CRITICAL;
95 229 temp_buffer = "";
96 /* Set signal handling and alarm */ 230 unsigned long expect_match = (1 << expected_address_cnt) - 1;
97 if (signal (SIGALRM, runcmd_timeout_alarm_handler) == SIG_ERR) { 231 unsigned long addr_match = (1 << n_addresses) - 1;
98 usage_va(_("Cannot catch SIGALRM")); 232
99 } 233 for (int i = 0; i < expected_address_cnt; i++) {
100 234 int j;
101 /* Parse extra opts if any */ 235 /* check if we get a match on 'raw' ip or cidr */
102 argv=np_extra_opts (&argc, argv, progname); 236 for (j = 0; j < n_addresses; j++) {
103 237 if (strcmp(addresses[j], expected_address[i]) == 0 || ip_match_cidr(addresses[j], expected_address[i])) {
104 if (process_arguments (argc, argv) == ERROR) { 238 result = STATE_OK;
105 usage_va(_("Could not parse arguments")); 239 addr_match &= ~(1 << j);
106 } 240 expect_match &= ~(1 << i);
107 241 }
108 /* get the command to run */ 242 }
109 xasprintf (&command_line, "%s %s %s", NSLOOKUP_COMMAND, query_address, dns_server); 243
110 244 /* prepare an error string */
111 alarm (timeout_interval); 245 xasprintf(&temp_buffer, "%s%s; ", temp_buffer, expected_address[i]);
112 gettimeofday (&tv, NULL); 246 }
113 247 /* check if expected_address must cover all in addresses and none may be missing */
114 if (verbose) 248 if (all_match && (expect_match != 0 || addr_match != 0))
115 printf ("%s\n", command_line); 249 result = STATE_CRITICAL;
116 250 if (result == STATE_CRITICAL) {
117 /* run the command */ 251 /* Strip off last semicolon... */
118 if((np_runcmd(command_line, &chld_out, &chld_err, 0)) != 0) { 252 temp_buffer[strlen(temp_buffer) - 2] = '\0';
119 msg = (char *)_("nslookup returned an error status"); 253 xasprintf(&msg, _("expected '%s' but got '%s'"), temp_buffer, address);
120 result = STATE_WARNING; 254 }
121 } 255 }
122 256
123 /* scan stdout */ 257 if (expect_nxdomain) {
124 for(size_t i = 0; i < chld_out.lines; i++) { 258 if (!is_nxdomain) {
125 if (addresses == NULL) 259 result = STATE_CRITICAL;
126 addresses = malloc(sizeof(*addresses)*10); 260 xasprintf(&msg, _("Domain '%s' was found by the server: '%s'\n"), query_address, address);
127 else if (!(n_addresses % 10)) 261 } else {
128 addresses = realloc(addresses,sizeof(*addresses) * (n_addresses + 10)); 262 if (address != NULL)
129 263 free(address);
130 if (verbose) 264 address = "NXDOMAIN";
131 puts(chld_out.line[i]); 265 }
132 266 }
133 if (strcasestr (chld_out.line[i], ".in-addr.arpa") || strcasestr (chld_out.line[i], ".ip6.arpa")) { 267
134 if ((temp_buffer = strstr (chld_out.line[i], "name = "))) 268 /* check if authoritative */
135 addresses[n_addresses++] = strdup (temp_buffer + 7); 269 if (result == STATE_OK && expect_authority && non_authoritative) {
136 else { 270 result = STATE_CRITICAL;
137 msg = (char *)_("Warning plugin error"); 271 xasprintf(&msg, _("server %s is not authoritative for %s"), dns_server, query_address);
138 result = STATE_WARNING; 272 }
139 } 273
140 } 274 microsec = deltime(tv);
141 275 elapsed_time = (double)microsec / 1.0e6;
142 /* bug ID: 2946553 - Older versions of bind will use all available dns 276
143 servers, we have to match the one specified */ 277 if (result == STATE_OK) {
144 if (strstr (chld_out.line[i], "Server:") && strlen(dns_server) > 0) { 278 result = get_status(elapsed_time, time_thresholds);
145 temp_buffer = strchr (chld_out.line[i], ':'); 279 if (result == STATE_OK) {
146 temp_buffer++; 280 printf("DNS %s: ", _("OK"));
147 281 } else if (result == STATE_WARNING) {
148 /* Strip leading tabs */ 282 printf("DNS %s: ", _("WARNING"));
149 for (; *temp_buffer != '\0' && *temp_buffer == '\t'; temp_buffer++) 283 } else if (result == STATE_CRITICAL) {
150 /* NOOP */; 284 printf("DNS %s: ", _("CRITICAL"));
151 285 }
152 strip(temp_buffer); 286 printf(ngettext("%.3f second response time", "%.3f seconds response time", elapsed_time), elapsed_time);
153 if (temp_buffer==NULL || strlen(temp_buffer)==0) { 287 printf(_(". %s returns %s"), query_address, address);
154 die (STATE_CRITICAL, 288 if ((time_thresholds->warning != NULL) && (time_thresholds->critical != NULL)) {
155 _("DNS CRITICAL - '%s' returned empty server string\n"), 289 printf("|%s\n", fperfdata("time", elapsed_time, "s", true, time_thresholds->warning->end, true, time_thresholds->critical->end,
156 NSLOOKUP_COMMAND); 290 true, 0, false, 0));
157 } 291 } else if ((time_thresholds->warning == NULL) && (time_thresholds->critical != NULL)) {
158 292 printf("|%s\n", fperfdata("time", elapsed_time, "s", false, 0, true, time_thresholds->critical->end, true, 0, false, 0));
159 if (strcmp(temp_buffer, dns_server) != 0) { 293 } else if ((time_thresholds->warning != NULL) && (time_thresholds->critical == NULL)) {
160 die (STATE_CRITICAL, _("DNS CRITICAL - No response from DNS %s\n"), dns_server); 294 printf("|%s\n", fperfdata("time", elapsed_time, "s", true, time_thresholds->warning->end, false, 0, true, 0, false, 0));
161 } 295 } else
162 } 296 printf("|%s\n", fperfdata("time", elapsed_time, "s", false, 0, false, 0, true, 0, false, 0));
163 297 } else if (result == STATE_WARNING)
164 /* the server is responding, we just got the host name... */ 298 printf(_("DNS WARNING - %s\n"), !strcmp(msg, "") ? _(" Probably a non-existent host/domain") : msg);
165 if (strstr (chld_out.line[i], "Name:")) 299 else if (result == STATE_CRITICAL)
166 parse_address = true; 300 printf(_("DNS CRITICAL - %s\n"), !strcmp(msg, "") ? _(" Probably a non-existent host/domain") : msg);
167 else if (parse_address && (strstr (chld_out.line[i], "Address:") || 301 else
168 strstr (chld_out.line[i], "Addresses:"))) { 302 printf(_("DNS UNKNOWN - %s\n"), !strcmp(msg, "") ? _(" Probably a non-existent host/domain") : msg);
169 temp_buffer = index (chld_out.line[i], ':'); 303
170 temp_buffer++; 304 return result;
171
172 /* Strip leading spaces */
173 while (*temp_buffer == ' ')
174 temp_buffer++;
175
176 strip(temp_buffer);
177 if (temp_buffer==NULL || strlen(temp_buffer)==0) {
178 die (STATE_CRITICAL,
179 _("DNS CRITICAL - '%s' returned empty host name string\n"),
180 NSLOOKUP_COMMAND);
181 }
182
183 addresses[n_addresses++] = strdup(temp_buffer);
184 }
185 else if (strstr (chld_out.line[i], _("Non-authoritative answer:"))) {
186 non_authoritative = true;
187 }
188
189
190 result = error_scan (chld_out.line[i], &is_nxdomain);
191 if (result != STATE_OK) {
192 msg = strchr (chld_out.line[i], ':');
193 if(msg) msg++;
194 break;
195 }
196 }
197
198 /* scan stderr */
199 for(size_t i = 0; i < chld_err.lines; i++) {
200 if (verbose)
201 puts(chld_err.line[i]);
202
203 if (error_scan (chld_err.line[i], &is_nxdomain) != STATE_OK) {
204 result = max_state (result, error_scan (chld_err.line[i], &is_nxdomain));
205 msg = strchr(input_buffer, ':');
206 if(msg)
207 msg++;
208 else
209 msg = input_buffer;
210 }
211 }
212
213 if (is_nxdomain && !expect_nxdomain) {
214 die (STATE_CRITICAL, _("Domain '%s' was not found by the server\n"), query_address);
215 }
216
217 if (addresses) {
218 int i,slen;
219 char *adrp;
220 qsort(addresses, n_addresses, sizeof(*addresses), qstrcmp);
221 for(i=0, slen=1; i < n_addresses; i++) {
222 slen += strlen(addresses[i])+1;
223 }
224 adrp = address = malloc(slen);
225 for(i=0; i < n_addresses; i++) {
226 if (i) *adrp++ = ',';
227 strcpy(adrp, addresses[i]);
228 adrp += strlen(addresses[i]);
229 }
230 *adrp = 0;
231 } else
232 die (STATE_CRITICAL,
233 _("DNS CRITICAL - '%s' msg parsing exited with no address\n"),
234 NSLOOKUP_COMMAND);
235
236 /* compare to expected address */
237 if (result == STATE_OK && expected_address_cnt > 0) {
238 result = STATE_CRITICAL;
239 temp_buffer = "";
240 unsigned long expect_match = (1 << expected_address_cnt) - 1;
241 unsigned long addr_match = (1 << n_addresses) - 1;
242
243 for (int i=0; i<expected_address_cnt; i++) {
244 int j;
245 /* check if we get a match on 'raw' ip or cidr */
246 for (j=0; j<n_addresses; j++) {
247 if ( strcmp(addresses[j], expected_address[i]) == 0
248 || ip_match_cidr(addresses[j], expected_address[i]) ) {
249 result = STATE_OK;
250 addr_match &= ~(1 << j);
251 expect_match &= ~(1 << i);
252 }
253 }
254
255 /* prepare an error string */
256 xasprintf(&temp_buffer, "%s%s; ", temp_buffer, expected_address[i]);
257 }
258 /* check if expected_address must cover all in addresses and none may be missing */
259 if (all_match && (expect_match != 0 || addr_match != 0))
260 result = STATE_CRITICAL;
261 if (result == STATE_CRITICAL) {
262 /* Strip off last semicolon... */
263 temp_buffer[strlen(temp_buffer)-2] = '\0';
264 xasprintf(&msg, _("expected '%s' but got '%s'"), temp_buffer, address);
265 }
266 }
267
268 if (expect_nxdomain) {
269 if (!is_nxdomain) {
270 result = STATE_CRITICAL;
271 xasprintf(&msg, _("Domain '%s' was found by the server: '%s'\n"), query_address, address);
272 } else {
273 if (address != NULL) free(address);
274 address = "NXDOMAIN";
275 }
276 }
277
278 /* check if authoritative */
279 if (result == STATE_OK && expect_authority && non_authoritative) {
280 result = STATE_CRITICAL;
281 xasprintf(&msg, _("server %s is not authoritative for %s"), dns_server, query_address);
282 }
283
284 microsec = deltime (tv);
285 elapsed_time = (double)microsec / 1.0e6;
286
287 if (result == STATE_OK) {
288 result = get_status(elapsed_time, time_thresholds);
289 if (result == STATE_OK) {
290 printf ("DNS %s: ", _("OK"));
291 } else if (result == STATE_WARNING) {
292 printf ("DNS %s: ", _("WARNING"));
293 } else if (result == STATE_CRITICAL) {
294 printf ("DNS %s: ", _("CRITICAL"));
295 }
296 printf (ngettext("%.3f second response time", "%.3f seconds response time", elapsed_time), elapsed_time);
297 printf (_(". %s returns %s"), query_address, address);
298 if ((time_thresholds->warning != NULL) && (time_thresholds->critical != NULL)) {
299 printf ("|%s\n", fperfdata ("time", elapsed_time, "s",
300 true, time_thresholds->warning->end,
301 true, time_thresholds->critical->end,
302 true, 0, false, 0));
303 } else if ((time_thresholds->warning == NULL) && (time_thresholds->critical != NULL)) {
304 printf ("|%s\n", fperfdata ("time", elapsed_time, "s",
305 false, 0,
306 true, time_thresholds->critical->end,
307 true, 0, false, 0));
308 } else if ((time_thresholds->warning != NULL) && (time_thresholds->critical == NULL)) {
309 printf ("|%s\n", fperfdata ("time", elapsed_time, "s",
310 true, time_thresholds->warning->end,
311 false, 0,
312 true, 0, false, 0));
313 } else
314 printf ("|%s\n", fperfdata ("time", elapsed_time, "s", false, 0, false, 0, true, 0, false, 0));
315 }
316 else if (result == STATE_WARNING)
317 printf (_("DNS WARNING - %s\n"),
318 !strcmp (msg, "") ? _(" Probably a non-existent host/domain") : msg);
319 else if (result == STATE_CRITICAL)
320 printf (_("DNS CRITICAL - %s\n"),
321 !strcmp (msg, "") ? _(" Probably a non-existent host/domain") : msg);
322 else
323 printf (_("DNS UNKNOWN - %s\n"),
324 !strcmp (msg, "") ? _(" Probably a non-existent host/domain") : msg);
325
326 return result;
327} 305}
328 306
329bool ip_match_cidr(const char *addr, const char *cidr_ro) { 307bool ip_match_cidr(const char *addr, const char *cidr_ro) {
330 char *subnet, *mask_c, *cidr = strdup(cidr_ro); 308 char *subnet;
331 int mask; 309 char *mask_c;
332 subnet = strtok(cidr, "/"); 310 char *cidr = strdup(cidr_ro);
333 mask_c = strtok(NULL, "\0"); 311 int mask;
334 if (!subnet || !mask_c) { 312 subnet = strtok(cidr, "/");
335 return false; 313 mask_c = strtok(NULL, "\0");
314 if (!subnet || !mask_c) {
315 return false;
336 } 316 }
337 mask = atoi(mask_c); 317 mask = atoi(mask_c);
338 318
339 /* https://www.cryptobells.com/verifying-ips-in-a-subnet-in-php/ */ 319 /* https://www.cryptobells.com/verifying-ips-in-a-subnet-in-php/ */
340 return (ip2long(addr) & ~((1 << (32 - mask)) - 1)) == (ip2long(subnet) >> (32 - mask)) << (32 - mask); 320 return (ip2long(addr) & ~((1 << (32 - mask)) - 1)) == (ip2long(subnet) >> (32 - mask)) << (32 - mask);
341} 321}
342 322
343unsigned long 323unsigned long ip2long(const char *src) {
344ip2long(const char* src) { 324 unsigned long ip[4];
345 unsigned long ip[4]; 325 /* http://computer-programming-forum.com/47-c-language/1376ffb92a12c471.htm */
346 /* http://computer-programming-forum.com/47-c-language/1376ffb92a12c471.htm */ 326 return (sscanf(src, "%3lu.%3lu.%3lu.%3lu", &ip[0], &ip[1], &ip[2], &ip[3]) == 4 && ip[0] < 256 && ip[1] < 256 && ip[2] < 256 &&
347 return (sscanf(src, "%3lu.%3lu.%3lu.%3lu", 327 ip[3] < 256)
348 &ip[0], &ip[1], &ip[2], &ip[3]) == 4 && 328 ? ip[0] << 24 | ip[1] << 16 | ip[2] << 8 | ip[3]
349 ip[0] < 256 && ip[1] < 256 && 329 : 0;
350 ip[2] < 256 && ip[3] < 256)
351 ? ip[0] << 24 | ip[1] << 16 | ip[2] << 8 | ip[3]
352 : 0;
353} 330}
354 331
355int 332int error_scan(char *input_buffer, bool *is_nxdomain) {
356error_scan (char *input_buffer, bool *is_nxdomain)
357{
358
359 const int nxdomain = strstr (input_buffer, "Non-existent") ||
360 strstr (input_buffer, "** server can't find") ||
361 strstr (input_buffer, "** Can't find") ||
362 strstr (input_buffer, "NXDOMAIN");
363 if (nxdomain) *is_nxdomain = true;
364
365 /* the DNS lookup timed out */
366 if (strstr (input_buffer, _("Note: nslookup is deprecated and may be removed from future releases.")) ||
367 strstr (input_buffer, _("Consider using the `dig' or `host' programs instead. Run nslookup with")) ||
368 strstr (input_buffer, _("the `-sil[ent]' option to prevent this message from appearing.")))
369 return STATE_OK;
370
371 /* DNS server is not running... */
372 else if (strstr (input_buffer, "No response from server"))
373 die (STATE_CRITICAL, _("No response from DNS %s\n"), dns_server);
374 else if (strstr (input_buffer, "no servers could be reached"))
375 die (STATE_CRITICAL, _("No response from DNS %s\n"), dns_server);
376
377 /* Host name is valid, but server doesn't have records... */
378 else if (strstr (input_buffer, "No records"))
379 die (STATE_CRITICAL, _("DNS %s has no records\n"), dns_server);
380
381 /* Connection was refused */
382 else if (strstr (input_buffer, "Connection refused") ||
383 strstr (input_buffer, "Couldn't find server") ||
384 strstr (input_buffer, "Refused") ||
385 (strstr (input_buffer, "** server can't find") &&
386 strstr (input_buffer, ": REFUSED")))
387 die (STATE_CRITICAL, _("Connection to DNS %s was refused\n"), dns_server);
388
389 /* Query refused (usually by an ACL in the namserver) */
390 else if (strstr (input_buffer, "Query refused"))
391 die (STATE_CRITICAL, _("Query was refused by DNS server at %s\n"), dns_server);
392
393 /* No information (e.g. nameserver IP has two PTR records) */
394 else if (strstr (input_buffer, "No information"))
395 die (STATE_CRITICAL, _("No information returned by DNS server at %s\n"), dns_server);
396
397 /* Network is unreachable */
398 else if (strstr (input_buffer, "Network is unreachable"))
399 die (STATE_CRITICAL, _("Network is unreachable\n"));
400
401 /* Internal server failure */
402 else if (strstr (input_buffer, "Server failure"))
403 die (STATE_CRITICAL, _("DNS failure for %s\n"), dns_server);
404
405 /* Request error or the DNS lookup timed out */
406 else if (strstr (input_buffer, "Format error") ||
407 strstr (input_buffer, "Timed out"))
408 return STATE_WARNING;
409
410 return STATE_OK;
411 333
412} 334 const int nxdomain = strstr(input_buffer, "Non-existent") || strstr(input_buffer, "** server can't find") ||
335 strstr(input_buffer, "** Can't find") || strstr(input_buffer, "NXDOMAIN");
336 if (nxdomain)
337 *is_nxdomain = true;
338
339 /* the DNS lookup timed out */
340 if (strstr(input_buffer, _("Note: nslookup is deprecated and may be removed from future releases.")) ||
341 strstr(input_buffer, _("Consider using the `dig' or `host' programs instead. Run nslookup with")) ||
342 strstr(input_buffer, _("the `-sil[ent]' option to prevent this message from appearing.")))
343 return STATE_OK;
344
345 /* DNS server is not running... */
346 else if (strstr(input_buffer, "No response from server"))
347 die(STATE_CRITICAL, _("No response from DNS %s\n"), dns_server);
348 else if (strstr(input_buffer, "no servers could be reached"))
349 die(STATE_CRITICAL, _("No response from DNS %s\n"), dns_server);
350
351 /* Host name is valid, but server doesn't have records... */
352 else if (strstr(input_buffer, "No records"))
353 die(STATE_CRITICAL, _("DNS %s has no records\n"), dns_server);
354
355 /* Connection was refused */
356 else if (strstr(input_buffer, "Connection refused") || strstr(input_buffer, "Couldn't find server") ||
357 strstr(input_buffer, "Refused") || (strstr(input_buffer, "** server can't find") && strstr(input_buffer, ": REFUSED")))
358 die(STATE_CRITICAL, _("Connection to DNS %s was refused\n"), dns_server);
359
360 /* Query refused (usually by an ACL in the namserver) */
361 else if (strstr(input_buffer, "Query refused"))
362 die(STATE_CRITICAL, _("Query was refused by DNS server at %s\n"), dns_server);
363
364 /* No information (e.g. nameserver IP has two PTR records) */
365 else if (strstr(input_buffer, "No information"))
366 die(STATE_CRITICAL, _("No information returned by DNS server at %s\n"), dns_server);
367
368 /* Network is unreachable */
369 else if (strstr(input_buffer, "Network is unreachable"))
370 die(STATE_CRITICAL, _("Network is unreachable\n"));
371
372 /* Internal server failure */
373 else if (strstr(input_buffer, "Server failure"))
374 die(STATE_CRITICAL, _("DNS failure for %s\n"), dns_server);
413 375
376 /* Request error or the DNS lookup timed out */
377 else if (strstr(input_buffer, "Format error") || strstr(input_buffer, "Timed out"))
378 return STATE_WARNING;
379
380 return STATE_OK;
381}
414 382
415/* process command-line arguments */ 383/* process command-line arguments */
416int 384int process_arguments(int argc, char **argv) {
417process_arguments (int argc, char **argv) 385 int c;
418{ 386 char *warning = NULL;
419 int c; 387 char *critical = NULL;
420 char *warning = NULL; 388
421 char *critical = NULL; 389 int opt_index = 0;
422 390 static struct option long_opts[] = {{"help", no_argument, 0, 'h'},
423 int opt_index = 0; 391 {"version", no_argument, 0, 'V'},
424 static struct option long_opts[] = { 392 {"verbose", no_argument, 0, 'v'},
425 {"help", no_argument, 0, 'h'}, 393 {"timeout", required_argument, 0, 't'},
426 {"version", no_argument, 0, 'V'}, 394 {"hostname", required_argument, 0, 'H'},
427 {"verbose", no_argument, 0, 'v'}, 395 {"server", required_argument, 0, 's'},
428 {"timeout", required_argument, 0, 't'}, 396 {"reverse-server", required_argument, 0, 'r'},
429 {"hostname", required_argument, 0, 'H'}, 397 {"expected-address", required_argument, 0, 'a'},
430 {"server", required_argument, 0, 's'}, 398 {"expect-nxdomain", no_argument, 0, 'n'},
431 {"reverse-server", required_argument, 0, 'r'}, 399 {"expect-authority", no_argument, 0, 'A'},
432 {"expected-address", required_argument, 0, 'a'}, 400 {"all", no_argument, 0, 'L'},
433 {"expect-nxdomain", no_argument, 0, 'n'}, 401 {"warning", required_argument, 0, 'w'},
434 {"expect-authority", no_argument, 0, 'A'}, 402 {"critical", required_argument, 0, 'c'},
435 {"all", no_argument, 0, 'L'}, 403 {0, 0, 0, 0}};
436 {"warning", required_argument, 0, 'w'}, 404
437 {"critical", required_argument, 0, 'c'}, 405 if (argc < 2)
438 {0, 0, 0, 0} 406 return ERROR;
439 }; 407
440 408 for (c = 1; c < argc; c++)
441 if (argc < 2) 409 if (strcmp("-to", argv[c]) == 0)
442 return ERROR; 410 strcpy(argv[c], "-t");
443 411
444 for (c = 1; c < argc; c++) 412 while (1) {
445 if (strcmp ("-to", argv[c]) == 0) 413 c = getopt_long(argc, argv, "hVvALnt:H:s:r:a:w:c:", long_opts, &opt_index);
446 strcpy (argv[c], "-t"); 414
447 415 if (c == -1 || c == EOF)
448 while (1) { 416 break;
449 c = getopt_long (argc, argv, "hVvALnt:H:s:r:a:w:c:", long_opts, &opt_index); 417
450 418 switch (c) {
451 if (c == -1 || c == EOF) 419 case 'h': /* help */
452 break; 420 print_help();
453 421 exit(STATE_UNKNOWN);
454 switch (c) { 422 case 'V': /* version */
455 case 'h': /* help */ 423 print_revision(progname, NP_VERSION);
456 print_help (); 424 exit(STATE_UNKNOWN);
457 exit (STATE_UNKNOWN); 425 case 'v': /* version */
458 case 'V': /* version */ 426 verbose = true;
459 print_revision (progname, NP_VERSION); 427 break;
460 exit (STATE_UNKNOWN); 428 case 't': /* timeout period */
461 case 'v': /* version */ 429 timeout_interval = atoi(optarg);
462 verbose = true; 430 break;
463 break; 431 case 'H': /* hostname */
464 case 't': /* timeout period */ 432 if (strlen(optarg) >= ADDRESS_LENGTH)
465 timeout_interval = atoi (optarg); 433 die(STATE_UNKNOWN, _("Input buffer overflow\n"));
466 break; 434 strcpy(query_address, optarg);
467 case 'H': /* hostname */ 435 break;
468 if (strlen (optarg) >= ADDRESS_LENGTH) 436 case 's': /* server name */
469 die (STATE_UNKNOWN, _("Input buffer overflow\n")); 437 /* TODO: this host_or_die check is probably unnecessary.
470 strcpy (query_address, optarg); 438 * Better to confirm nslookup response matches */
471 break; 439 host_or_die(optarg);
472 case 's': /* server name */ 440 if (strlen(optarg) >= ADDRESS_LENGTH)
473 /* TODO: this host_or_die check is probably unnecessary. 441 die(STATE_UNKNOWN, _("Input buffer overflow\n"));
474 * Better to confirm nslookup response matches */ 442 strcpy(dns_server, optarg);
475 host_or_die(optarg); 443 break;
476 if (strlen (optarg) >= ADDRESS_LENGTH) 444 case 'r': /* reverse server name */
477 die (STATE_UNKNOWN, _("Input buffer overflow\n")); 445 /* TODO: Is this host_or_die necessary? */
478 strcpy (dns_server, optarg); 446 host_or_die(optarg);
479 break; 447 if (strlen(optarg) >= ADDRESS_LENGTH)
480 case 'r': /* reverse server name */ 448 die(STATE_UNKNOWN, _("Input buffer overflow\n"));
481 /* TODO: Is this host_or_die necessary? */ 449 strcpy(ptr_server, optarg);
482 host_or_die(optarg); 450 break;
483 if (strlen (optarg) >= ADDRESS_LENGTH) 451 case 'a': /* expected address */
484 die (STATE_UNKNOWN, _("Input buffer overflow\n")); 452 if (strlen(optarg) >= ADDRESS_LENGTH)
485 strcpy (ptr_server, optarg); 453 die(STATE_UNKNOWN, _("Input buffer overflow\n"));
486 break; 454 if (strchr(optarg, ',') != NULL) {
487 case 'a': /* expected address */ 455 char *comma = strchr(optarg, ',');
488 if (strlen (optarg) >= ADDRESS_LENGTH) 456 while (comma != NULL) {
489 die (STATE_UNKNOWN, _("Input buffer overflow\n")); 457 expected_address = (char **)realloc(expected_address, (expected_address_cnt + 1) * sizeof(char **));
490 if (strchr(optarg, ',') != NULL) { 458 expected_address[expected_address_cnt] = strndup(optarg, comma - optarg);
491 char *comma = strchr(optarg, ','); 459 expected_address_cnt++;
492 while (comma != NULL) { 460 optarg = comma + 1;
493 expected_address = (char **)realloc(expected_address, (expected_address_cnt+1) * sizeof(char**)); 461 comma = strchr(optarg, ',');
494 expected_address[expected_address_cnt] = strndup(optarg, comma - optarg); 462 }
495 expected_address_cnt++; 463 expected_address = (char **)realloc(expected_address, (expected_address_cnt + 1) * sizeof(char **));
496 optarg = comma + 1; 464 expected_address[expected_address_cnt] = strdup(optarg);
497 comma = strchr(optarg, ','); 465 expected_address_cnt++;
466 } else {
467 expected_address = (char **)realloc(expected_address, (expected_address_cnt + 1) * sizeof(char **));
468 expected_address[expected_address_cnt] = strdup(optarg);
469 expected_address_cnt++;
470 }
471 break;
472 case 'n': /* expect NXDOMAIN */
473 expect_nxdomain = true;
474 break;
475 case 'A': /* expect authority */
476 expect_authority = true;
477 break;
478 case 'L': /* all must match */
479 all_match = true;
480 break;
481 case 'w':
482 warning = optarg;
483 break;
484 case 'c':
485 critical = optarg;
486 break;
487 default: /* args not parsable */
488 usage5();
489 }
498 } 490 }
499 expected_address = (char **)realloc(expected_address, (expected_address_cnt+1) * sizeof(char**));
500 expected_address[expected_address_cnt] = strdup(optarg);
501 expected_address_cnt++;
502 } else {
503 expected_address = (char **)realloc(expected_address, (expected_address_cnt+1) * sizeof(char**));
504 expected_address[expected_address_cnt] = strdup(optarg);
505 expected_address_cnt++;
506 }
507 break;
508 case 'n': /* expect NXDOMAIN */
509 expect_nxdomain = true;
510 break;
511 case 'A': /* expect authority */
512 expect_authority = true;
513 break;
514 case 'L': /* all must match */
515 all_match = true;
516 break;
517 case 'w':
518 warning = optarg;
519 break;
520 case 'c':
521 critical = optarg;
522 break;
523 default: /* args not parsable */
524 usage5();
525 }
526 }
527
528 c = optind;
529 if (strlen(query_address)==0 && c<argc) {
530 if (strlen(argv[c])>=ADDRESS_LENGTH)
531 die (STATE_UNKNOWN, _("Input buffer overflow\n"));
532 strcpy (query_address, argv[c++]);
533 }
534
535 if (strlen(dns_server)==0 && c<argc) {
536 /* TODO: See -s option */
537 host_or_die(argv[c]);
538 if (strlen(argv[c]) >= ADDRESS_LENGTH)
539 die (STATE_UNKNOWN, _("Input buffer overflow\n"));
540 strcpy (dns_server, argv[c++]);
541 }
542
543 set_thresholds(&time_thresholds, warning, critical);
544
545 return validate_arguments ();
546}
547 491
492 c = optind;
493 if (strlen(query_address) == 0 && c < argc) {
494 if (strlen(argv[c]) >= ADDRESS_LENGTH)
495 die(STATE_UNKNOWN, _("Input buffer overflow\n"));
496 strcpy(query_address, argv[c++]);
497 }
548 498
549int 499 if (strlen(dns_server) == 0 && c < argc) {
550validate_arguments () 500 /* TODO: See -s option */
551{ 501 host_or_die(argv[c]);
552 if (query_address[0] == 0) { 502 if (strlen(argv[c]) >= ADDRESS_LENGTH)
553 printf ("missing --host argument\n"); 503 die(STATE_UNKNOWN, _("Input buffer overflow\n"));
554 return ERROR; 504 strcpy(dns_server, argv[c++]);
555 } 505 }
556 506
557 if (expected_address_cnt > 0 && expect_nxdomain) { 507 set_thresholds(&time_thresholds, warning, critical);
558 printf ("--expected-address and --expect-nxdomain cannot be combined\n");
559 return ERROR;
560 }
561 508
562 return OK; 509 return validate_arguments();
563} 510}
564 511
512int validate_arguments(void) {
513 if (query_address[0] == 0) {
514 printf("missing --host argument\n");
515 return ERROR;
516 }
517
518 if (expected_address_cnt > 0 && expect_nxdomain) {
519 printf("--expected-address and --expect-nxdomain cannot be combined\n");
520 return ERROR;
521 }
565 522
566void 523 return OK;
567print_help (void)
568{
569 print_revision (progname, NP_VERSION);
570
571 printf ("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n");
572 printf (COPYRIGHT, copyright, email);
573
574 printf ("%s\n", _("This plugin uses the nslookup program to obtain the IP address for the given host/domain query."));
575 printf ("%s\n", _("An optional DNS server to use may be specified."));
576 printf ("%s\n", _("If no DNS server is specified, the default server(s) specified in /etc/resolv.conf will be used."));
577
578 printf ("\n\n");
579
580 print_usage ();
581
582 printf (UT_HELP_VRSN);
583 printf (UT_EXTRA_OPTS);
584
585 printf (" -H, --hostname=HOST\n");
586 printf (" %s\n", _("The name or address you want to query"));
587 printf (" -s, --server=HOST\n");
588 printf (" %s\n", _("Optional DNS server you want to use for the lookup"));
589 printf (" -a, --expected-address=IP-ADDRESS|CIDR|HOST\n");
590 printf (" %s\n", _("Optional IP-ADDRESS/CIDR you expect the DNS server to return. HOST must end"));
591 printf (" %s\n", _("with a dot (.). This option can be repeated multiple times (Returns OK if any"));
592 printf (" %s\n", _("value matches)."));
593 printf (" -n, --expect-nxdomain\n");
594 printf (" %s\n", _("Expect the DNS server to return NXDOMAIN (i.e. the domain was not found)"));
595 printf (" %s\n", _("Cannot be used together with -a"));
596 printf (" -A, --expect-authority\n");
597 printf (" %s\n", _("Optionally expect the DNS server to be authoritative for the lookup"));
598 printf (" -w, --warning=seconds\n");
599 printf (" %s\n", _("Return warning if elapsed time exceeds value. Default off"));
600 printf (" -c, --critical=seconds\n");
601 printf (" %s\n", _("Return critical if elapsed time exceeds value. Default off"));
602 printf (" -L, --all\n");
603 printf (" %s\n", _("Return critical if the list of expected addresses does not match all addresses"));
604 printf (" %s\n", _("returned. Default off"));
605
606 printf (UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
607
608 printf (UT_SUPPORT);
609} 524}
610 525
526void print_help(void) {
527 print_revision(progname, NP_VERSION);
528
529 printf("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n");
530 printf(COPYRIGHT, copyright, email);
531
532 printf("%s\n", _("This plugin uses the nslookup program to obtain the IP address for the given host/domain query."));
533 printf("%s\n", _("An optional DNS server to use may be specified."));
534 printf("%s\n", _("If no DNS server is specified, the default server(s) specified in /etc/resolv.conf will be used."));
535
536 printf("\n\n");
537
538 print_usage();
539
540 printf(UT_HELP_VRSN);
541 printf(UT_EXTRA_OPTS);
542
543 printf(" -H, --hostname=HOST\n");
544 printf(" %s\n", _("The name or address you want to query"));
545 printf(" -s, --server=HOST\n");
546 printf(" %s\n", _("Optional DNS server you want to use for the lookup"));
547 printf(" -a, --expected-address=IP-ADDRESS|CIDR|HOST\n");
548 printf(" %s\n", _("Optional IP-ADDRESS/CIDR you expect the DNS server to return. HOST must end"));
549 printf(" %s\n", _("with a dot (.). This option can be repeated multiple times (Returns OK if any"));
550 printf(" %s\n", _("value matches)."));
551 printf(" -n, --expect-nxdomain\n");
552 printf(" %s\n", _("Expect the DNS server to return NXDOMAIN (i.e. the domain was not found)"));
553 printf(" %s\n", _("Cannot be used together with -a"));
554 printf(" -A, --expect-authority\n");
555 printf(" %s\n", _("Optionally expect the DNS server to be authoritative for the lookup"));
556 printf(" -w, --warning=seconds\n");
557 printf(" %s\n", _("Return warning if elapsed time exceeds value. Default off"));
558 printf(" -c, --critical=seconds\n");
559 printf(" %s\n", _("Return critical if elapsed time exceeds value. Default off"));
560 printf(" -L, --all\n");
561 printf(" %s\n", _("Return critical if the list of expected addresses does not match all addresses"));
562 printf(" %s\n", _("returned. Default off"));
563
564 printf(UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
565
566 printf(UT_SUPPORT);
567}
611 568
612void 569void print_usage(void) {
613print_usage (void) 570 printf("%s\n", _("Usage:"));
614{ 571 printf("%s -H host [-s server] [-a expected-address] [-n] [-A] [-t timeout] [-w warn] [-c crit] [-L]\n", progname);
615 printf ("%s\n", _("Usage:"));
616 printf ("%s -H host [-s server] [-a expected-address] [-n] [-A] [-t timeout] [-w warn] [-c crit] [-L]\n", progname);
617} 572}
diff --git a/plugins/check_dummy.c b/plugins/check_dummy.c
index 212a1344..19f6c046 100644
--- a/plugins/check_dummy.c
+++ b/plugins/check_dummy.c
@@ -1,124 +1,111 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring check_dummy plugin 3 * Monitoring check_dummy plugin
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 1999-2007 Monitoring Plugins Development Team 6 * Copyright (c) 1999-2024 Monitoring Plugins Development Team
7* 7 *
8* Description: 8 * Description:
9* 9 *
10* This file contains the check_dummy plugin 10 * This file contains the check_dummy plugin
11* 11 *
12* This plugin will simply return the state corresponding to the numeric value 12 * This plugin will simply return the state corresponding to the numeric value
13* 13 *
14* 14 *
15* This program is free software: you can redistribute it and/or modify 15 * This program is free software: you can redistribute it and/or modify
16* it under the terms of the GNU General Public License as published by 16 * it under the terms of the GNU General Public License as published by
17* the Free Software Foundation, either version 3 of the License, or 17 * the Free Software Foundation, either version 3 of the License, or
18* (at your option) any later version. 18 * (at your option) any later version.
19* 19 *
20* This program is distributed in the hope that it will be useful, 20 * This program is distributed in the hope that it will be useful,
21* but WITHOUT ANY WARRANTY; without even the implied warranty of 21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23* GNU General Public License for more details. 23 * GNU General Public License for more details.
24* 24 *
25* You should have received a copy of the GNU General Public License 25 * You should have received a copy of the GNU General Public License
26* along with this program. If not, see <http://www.gnu.org/licenses/>. 26 * along with this program. If not, see <http://www.gnu.org/licenses/>.
27* 27 *
28* 28 *
29*****************************************************************************/ 29 *****************************************************************************/
30 30
31const char *progname = "check_dummy"; 31const char *progname = "check_dummy";
32const char *copyright = "1999-2007"; 32const char *copyright = "1999-2024";
33const char *email = "devel@monitoring-plugins.org"; 33const char *email = "devel@monitoring-plugins.org";
34 34
35#include "common.h" 35#include "common.h"
36#include "utils.h" 36#include "utils.h"
37 37
38void print_help (void); 38static void print_help(void);
39void print_usage (void); 39void print_usage(void);
40 40
41 41int main(int argc, char **argv) {
42int 42 int result = STATE_UNKNOWN;
43main (int argc, char **argv) 43
44{ 44 setlocale(LC_ALL, "");
45 int result = STATE_UNKNOWN; 45 bindtextdomain(PACKAGE, LOCALEDIR);
46 46 textdomain(PACKAGE);
47 setlocale (LC_ALL, ""); 47
48 bindtextdomain (PACKAGE, LOCALEDIR); 48 if (argc < 2)
49 textdomain (PACKAGE); 49 usage4(_("Could not parse arguments"));
50 50 else if (strcmp(argv[1], "-V") == 0 || strcmp(argv[1], "--version") == 0) {
51 if (argc < 2) 51 print_revision(progname, NP_VERSION);
52 usage4 (_("Could not parse arguments")); 52 exit(STATE_UNKNOWN);
53 else if (strcmp (argv[1], "-V") == 0 || strcmp (argv[1], "--version") == 0) { 53 } else if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0) {
54 print_revision (progname, NP_VERSION); 54 print_help();
55 exit (STATE_UNKNOWN); 55 exit(STATE_UNKNOWN);
56 } 56 } else if (!is_integer(argv[1]))
57 else if (strcmp (argv[1], "-h") == 0 || strcmp (argv[1], "--help") == 0) { 57 usage4(_("Arguments to check_dummy must be an integer"));
58 print_help (); 58 else
59 exit (STATE_UNKNOWN); 59 result = atoi(argv[1]);
60 } 60
61 else if (!is_integer (argv[1])) 61 switch (result) {
62 usage4 (_("Arguments to check_dummy must be an integer")); 62 case STATE_OK:
63 else 63 printf(_("OK"));
64 result = atoi (argv[1]); 64 break;
65 65 case STATE_WARNING:
66 switch (result) { 66 printf(_("WARNING"));
67 case STATE_OK: 67 break;
68 printf (_("OK")); 68 case STATE_CRITICAL:
69 break; 69 printf(_("CRITICAL"));
70 case STATE_WARNING: 70 break;
71 printf (_("WARNING")); 71 case STATE_UNKNOWN:
72 break; 72 printf(_("UNKNOWN"));
73 case STATE_CRITICAL: 73 break;
74 printf (_("CRITICAL")); 74 default:
75 break; 75 printf(_("UNKNOWN"));
76 case STATE_UNKNOWN: 76 printf(": ");
77 printf (_("UNKNOWN")); 77 printf(_("Status %d is not a supported error state\n"), result);
78 break; 78 return STATE_UNKNOWN;
79 default: 79 }
80 printf (_("UNKNOWN")); 80
81 printf (": "); 81 if (argc >= 3)
82 printf (_("Status %d is not a supported error state\n"), result); 82 printf(": %s", argv[2]);
83 return STATE_UNKNOWN; 83
84 } 84 printf("\n");
85 85
86 if (argc >= 3) 86 return result;
87 printf (": %s", argv[2]);
88
89 printf("\n");
90
91 return result;
92} 87}
93 88
89void print_help(void) {
90 print_revision(progname, NP_VERSION);
94 91
92 printf("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n");
93 printf(COPYRIGHT, copyright, email);
95 94
96void 95 printf("%s\n", _("This plugin will simply return the state corresponding to the numeric value"));
97print_help (void)
98{
99 print_revision (progname, NP_VERSION);
100 96
101 printf ("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n"); 97 printf("%s\n", _("of the <state> argument with optional text"));
102 printf (COPYRIGHT, copyright, email);
103 98
104 printf ("%s\n", _("This plugin will simply return the state corresponding to the numeric value")); 99 printf("\n\n");
105 100
106 printf ("%s\n", _("of the <state> argument with optional text")); 101 print_usage();
107 102
108 printf ("\n\n"); 103 printf(UT_HELP_VRSN);
109 104
110 print_usage (); 105 printf(UT_SUPPORT);
111
112 printf (UT_HELP_VRSN);
113
114 printf (UT_SUPPORT);
115} 106}
116 107
117 108void print_usage(void) {
118 109 printf("%s\n", _("Usage:"));
119void 110 printf(" %s <integer state> [optional text]\n", progname);
120print_usage (void)
121{
122 printf ("%s\n", _("Usage:"));
123 printf (" %s <integer state> [optional text]\n", progname);
124} 111}
diff --git a/plugins/check_fping.c b/plugins/check_fping.c
index 70d6f9fc..49235e28 100644
--- a/plugins/check_fping.c
+++ b/plugins/check_fping.c
@@ -1,36 +1,36 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring check_fping plugin 3 * Monitoring check_fping plugin
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 2000-2007 Monitoring Plugins Development Team 6 * Copyright (c) 2000-2024 Monitoring Plugins Development Team
7* 7 *
8* Description: 8 * Description:
9* 9 *
10* This file contains the check_disk plugin 10 * This file contains the check_disk plugin
11* 11 *
12* This plugin will use the fping command to ping the specified host for a 12 * This plugin will use the fping command to ping the specified host for a
13* fast check 13 * fast check
14* 14 *
15* 15 *
16* This program is free software: you can redistribute it and/or modify 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 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 18 * the Free Software Foundation, either version 3 of the License, or
19* (at your option) any later version. 19 * (at your option) any later version.
20* 20 *
21* This program is distributed in the hope that it will be useful, 21 * This program is distributed in the hope that it will be useful,
22* but WITHOUT ANY WARRANTY; without even the implied warranty of 22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24* GNU General Public License for more details. 24 * GNU General Public License for more details.
25* 25 *
26* You should have received a copy of the GNU General Public License 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/>. 27 * along with this program. If not, see <http://www.gnu.org/licenses/>.
28* 28 *
29* 29 *
30*****************************************************************************/ 30 *****************************************************************************/
31 31
32const char *progname = "check_fping"; 32const char *progname = "check_fping";
33const char *copyright = "2000-2007"; 33const char *copyright = "2000-2024";
34const char *email = "devel@monitoring-plugins.org"; 34const char *email = "devel@monitoring-plugins.org";
35 35
36#include "common.h" 36#include "common.h"
@@ -40,488 +40,449 @@ const char *email = "devel@monitoring-plugins.org";
40#include <stdbool.h> 40#include <stdbool.h>
41 41
42enum { 42enum {
43 PACKET_COUNT = 1, 43 PACKET_COUNT = 1,
44 PACKET_SIZE = 56, 44 PACKET_SIZE = 56,
45 PL = 0, 45 PL = 0,
46 RTA = 1 46 RTA = 1
47}; 47};
48 48
49int textscan (char *buf); 49static int textscan(char *buf);
50int process_arguments (int, char **); 50static int process_arguments(int /*argc*/, char ** /*argv*/);
51int get_threshold (char *arg, char *rv[2]); 51static int get_threshold(char *arg, char *rv[2]);
52void print_help (void); 52static void print_help(void);
53void print_usage (void); 53void print_usage(void);
54 54
55char *server_name = NULL; 55static char *server_name = NULL;
56char *sourceip = NULL; 56static char *sourceip = NULL;
57char *sourceif = NULL; 57static char *sourceif = NULL;
58int packet_size = PACKET_SIZE; 58static int packet_size = PACKET_SIZE;
59int packet_count = PACKET_COUNT; 59static int packet_count = PACKET_COUNT;
60int target_timeout = 0; 60static int target_timeout = 0;
61int packet_interval = 0; 61static int packet_interval = 0;
62bool verbose = false; 62static bool verbose = false;
63int cpl; 63static int cpl;
64int wpl; 64static int wpl;
65double crta; 65static double crta;
66double wrta; 66static double wrta;
67bool cpl_p = false; 67static bool cpl_p = false;
68bool wpl_p = false; 68static bool wpl_p = false;
69bool alive_p = false; 69static bool alive_p = false;
70bool crta_p = false; 70static bool crta_p = false;
71bool wrta_p = false; 71static bool wrta_p = false;
72 72
73int 73int main(int argc, char **argv) {
74main (int argc, char **argv) 74 /* normally should be int result = STATE_UNKNOWN; */
75{ 75
76/* normally should be int result = STATE_UNKNOWN; */ 76 int status = STATE_UNKNOWN;
77 77 int result = 0;
78 int status = STATE_UNKNOWN; 78 char *fping_prog = NULL;
79 int result = 0; 79 char *server = NULL;
80 char *fping_prog = NULL; 80 char *command_line = NULL;
81 char *server = NULL; 81 char *input_buffer = NULL;
82 char *command_line = NULL; 82 char *option_string = "";
83 char *input_buffer = NULL; 83 input_buffer = malloc(MAX_INPUT_BUFFER);
84 char *option_string = ""; 84
85 input_buffer = malloc (MAX_INPUT_BUFFER); 85 setlocale(LC_ALL, "");
86 86 bindtextdomain(PACKAGE, LOCALEDIR);
87 setlocale (LC_ALL, ""); 87 textdomain(PACKAGE);
88 bindtextdomain (PACKAGE, LOCALEDIR); 88
89 textdomain (PACKAGE); 89 /* Parse extra opts if any */
90 90 argv = np_extra_opts(&argc, argv, progname);
91 /* Parse extra opts if any */ 91
92 argv=np_extra_opts (&argc, argv, progname); 92 if (process_arguments(argc, argv) == ERROR)
93 93 usage4(_("Could not parse arguments"));
94 if (process_arguments (argc, argv) == ERROR) 94
95 usage4 (_("Could not parse arguments")); 95 server = strscpy(server, server_name);
96 96
97 server = strscpy (server, server_name); 97 /* compose the command */
98 98 if (target_timeout)
99 /* compose the command */ 99 xasprintf(&option_string, "%s-t %d ", option_string, target_timeout);
100 if (target_timeout) 100 if (packet_interval)
101 xasprintf(&option_string, "%s-t %d ", option_string, target_timeout); 101 xasprintf(&option_string, "%s-p %d ", option_string, packet_interval);
102 if (packet_interval) 102 if (sourceip)
103 xasprintf(&option_string, "%s-p %d ", option_string, packet_interval); 103 xasprintf(&option_string, "%s-S %s ", option_string, sourceip);
104 if (sourceip) 104 if (sourceif)
105 xasprintf(&option_string, "%s-S %s ", option_string, sourceip); 105 xasprintf(&option_string, "%s-I %s ", option_string, sourceif);
106 if (sourceif)
107 xasprintf(&option_string, "%s-I %s ", option_string, sourceif);
108 106
109#ifdef PATH_TO_FPING6 107#ifdef PATH_TO_FPING6
110 if (address_family != AF_INET && is_inet6_addr(server)) 108 if (address_family != AF_INET && is_inet6_addr(server))
111 fping_prog = strdup(PATH_TO_FPING6); 109 fping_prog = strdup(PATH_TO_FPING6);
112 else 110 else
113 fping_prog = strdup(PATH_TO_FPING); 111 fping_prog = strdup(PATH_TO_FPING);
114#else 112#else
115 fping_prog = strdup(PATH_TO_FPING); 113 fping_prog = strdup(PATH_TO_FPING);
116#endif 114#endif
117 115
118 xasprintf (&command_line, "%s %s-b %d -c %d %s", fping_prog, 116 xasprintf(&command_line, "%s %s-b %d -c %d %s", fping_prog, option_string, packet_size, packet_count, server);
119 option_string, packet_size, packet_count, server); 117
120 118 if (verbose)
121 if (verbose) 119 printf("%s\n", command_line);
122 printf ("%s\n", command_line); 120
123 121 /* run the command */
124 /* run the command */ 122 child_process = spopen(command_line);
125 child_process = spopen (command_line); 123 if (child_process == NULL) {
126 if (child_process == NULL) { 124 printf(_("Could not open pipe: %s\n"), command_line);
127 printf (_("Could not open pipe: %s\n"), command_line); 125 return STATE_UNKNOWN;
128 return STATE_UNKNOWN; 126 }
129 } 127
130 128 child_stderr = fdopen(child_stderr_array[fileno(child_process)], "r");
131 child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r"); 129 if (child_stderr == NULL) {
132 if (child_stderr == NULL) { 130 printf(_("Could not open stderr for %s\n"), command_line);
133 printf (_("Could not open stderr for %s\n"), command_line); 131 }
134 } 132
135 133 while (fgets(input_buffer, MAX_INPUT_BUFFER - 1, child_process)) {
136 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) { 134 if (verbose)
137 if (verbose) 135 printf("%s", input_buffer);
138 printf ("%s", input_buffer); 136 status = max_state(status, textscan(input_buffer));
139 status = max_state (status, textscan (input_buffer)); 137 }
140 } 138
141 139 /* If we get anything on STDERR, at least set warning */
142 /* If we get anything on STDERR, at least set warning */ 140 while (fgets(input_buffer, MAX_INPUT_BUFFER - 1, child_stderr)) {
143 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr)) { 141 status = max_state(status, STATE_WARNING);
144 status = max_state (status, STATE_WARNING); 142 if (verbose)
145 if (verbose) 143 printf("%s", input_buffer);
146 printf ("%s", input_buffer); 144 status = max_state(status, textscan(input_buffer));
147 status = max_state (status, textscan (input_buffer)); 145 }
148 } 146 (void)fclose(child_stderr);
149 (void) fclose (child_stderr); 147
150 148 /* close the pipe */
151 /* close the pipe */ 149 result = spclose(child_process);
152 result = spclose (child_process); 150 if (result) {
153 if (result) { 151 /* need to use max_state not max */
154 /* need to use max_state not max */ 152 status = max_state(status, STATE_WARNING);
155 status = max_state (status, STATE_WARNING); 153 }
156 } 154
157 155 if (result > 1) {
158 if (result > 1 ) { 156 status = max_state(status, STATE_UNKNOWN);
159 status = max_state (status, STATE_UNKNOWN); 157 if (result == 2) {
160 if (result == 2) { 158 die(STATE_UNKNOWN, _("FPING UNKNOWN - IP address not found\n"));
161 die (STATE_UNKNOWN, _("FPING UNKNOWN - IP address not found\n")); 159 }
162 } 160 if (result == 3) {
163 if (result == 3) { 161 die(STATE_UNKNOWN, _("FPING UNKNOWN - invalid commandline argument\n"));
164 die (STATE_UNKNOWN, _("FPING UNKNOWN - invalid commandline argument\n")); 162 }
165 } 163 if (result == 4) {
166 if (result == 4) { 164 die(STATE_UNKNOWN, _("FPING UNKNOWN - failed system call\n"));
167 die (STATE_UNKNOWN, _("FPING UNKNOWN - failed system call\n")); 165 }
168 } 166 }
169 167
170 } 168 printf("FPING %s - %s\n", state_text(status), server_name);
171 169
172 printf ("FPING %s - %s\n", state_text (status), server_name); 170 return status;
173
174 return status;
175} 171}
176 172
177 173int textscan(char *buf) {
178int textscan (char *buf) { 174 char *rtastr = NULL;
179 char *rtastr = NULL; 175 char *losstr = NULL;
180 char *losstr = NULL; 176 char *xmtstr = NULL;
181 char *xmtstr = NULL; 177 double loss;
182 double loss; 178 double rta;
183 double rta; 179 double xmt;
184 double xmt; 180 int status = STATE_UNKNOWN;
185 int status = STATE_UNKNOWN; 181
186 182 /* stops testing after the first successful reply. */
187 /* stops testing after the first successful reply. */ 183 if (alive_p && strstr(buf, "avg, 0% loss)")) {
188 if (alive_p && strstr(buf, "avg, 0% loss)")) { 184 rtastr = strstr(buf, "ms (");
189 rtastr = strstr (buf, "ms ("); 185 rtastr = 1 + index(rtastr, '(');
190 rtastr = 1 + index(rtastr, '('); 186 rta = strtod(rtastr, NULL);
191 rta = strtod(rtastr, NULL); 187 loss = strtod("0", NULL);
192 loss=strtod("0",NULL); 188 die(STATE_OK, _("FPING %s - %s (rta=%f ms)|%s\n"), state_text(STATE_OK), server_name, rta,
193 die (STATE_OK, 189 /* No loss since we only waited for the first reply
194 _("FPING %s - %s (rta=%f ms)|%s\n"), 190 perfdata ("loss", (long int)loss, "%", wpl_p, wpl, cpl_p, cpl, true, 0, true, 100), */
195 state_text (STATE_OK), server_name,rta, 191 fperfdata("rta", rta / 1.0e3, "s", wrta_p, wrta / 1.0e3, crta_p, crta / 1.0e3, true, 0, false, 0));
196 /* No loss since we only waited for the first reply 192 }
197 perfdata ("loss", (long int)loss, "%", wpl_p, wpl, cpl_p, cpl, true, 0, true, 100), */ 193
198 fperfdata ("rta", rta/1.0e3, "s", wrta_p, wrta/1.0e3, crta_p, crta/1.0e3, true, 0, false, 0)); 194 if (strstr(buf, "not found")) {
199 } 195 die(STATE_CRITICAL, _("FPING UNKNOWN - %s not found\n"), server_name);
200 196
201 if (strstr (buf, "not found")) { 197 } else if (strstr(buf, "is unreachable") || strstr(buf, "Unreachable")) {
202 die (STATE_CRITICAL, _("FPING UNKNOWN - %s not found\n"), server_name); 198 die(STATE_CRITICAL, _("FPING CRITICAL - %s is unreachable\n"), "host");
203 199
204 } 200 } else if (strstr(buf, "Operation not permitted") || strstr(buf, "No such device")) {
205 else if (strstr (buf, "is unreachable") || strstr (buf, "Unreachable")) { 201 die(STATE_UNKNOWN, _("FPING UNKNOWN - %s parameter error\n"), "host");
206 die (STATE_CRITICAL, _("FPING CRITICAL - %s is unreachable\n"), 202 } else if (strstr(buf, "is down")) {
207 "host"); 203 die(STATE_CRITICAL, _("FPING CRITICAL - %s is down\n"), server_name);
208 204
209 } 205 } else if (strstr(buf, "is alive")) {
210 else if (strstr (buf, "Operation not permitted") || strstr (buf, "No such device") ) { 206 status = STATE_OK;
211 die (STATE_UNKNOWN, _("FPING UNKNOWN - %s parameter error\n"), 207
212 "host"); 208 } else if (strstr(buf, "xmt/rcv/%loss") && strstr(buf, "min/avg/max")) {
213 } 209 losstr = strstr(buf, "=");
214 else if (strstr (buf, "is down")) { 210 losstr = 1 + strstr(losstr, "/");
215 die (STATE_CRITICAL, _("FPING CRITICAL - %s is down\n"), server_name); 211 losstr = 1 + strstr(losstr, "/");
216 212 rtastr = strstr(buf, "min/avg/max");
217 } 213 rtastr = strstr(rtastr, "=");
218 else if (strstr (buf, "is alive")) { 214 rtastr = 1 + index(rtastr, '/');
219 status = STATE_OK; 215 loss = strtod(losstr, NULL);
220 216 rta = strtod(rtastr, NULL);
221 } 217 if (cpl_p && loss > cpl)
222 else if (strstr (buf, "xmt/rcv/%loss") && strstr (buf, "min/avg/max")) { 218 status = STATE_CRITICAL;
223 losstr = strstr (buf, "="); 219 else if (crta_p && rta > crta)
224 losstr = 1 + strstr (losstr, "/"); 220 status = STATE_CRITICAL;
225 losstr = 1 + strstr (losstr, "/"); 221 else if (wpl_p && loss > wpl)
226 rtastr = strstr (buf, "min/avg/max"); 222 status = STATE_WARNING;
227 rtastr = strstr (rtastr, "="); 223 else if (wrta_p && rta > wrta)
228 rtastr = 1 + index (rtastr, '/'); 224 status = STATE_WARNING;
229 loss = strtod (losstr, NULL); 225 else
230 rta = strtod (rtastr, NULL); 226 status = STATE_OK;
231 if (cpl_p && loss > cpl) 227 die(status, _("FPING %s - %s (loss=%.0f%%, rta=%f ms)|%s %s\n"), state_text(status), server_name, loss, rta,
232 status = STATE_CRITICAL; 228 perfdata("loss", (long int)loss, "%", wpl_p, wpl, cpl_p, cpl, true, 0, true, 100),
233 else if (crta_p && rta > crta) 229 fperfdata("rta", rta / 1.0e3, "s", wrta_p, wrta / 1.0e3, crta_p, crta / 1.0e3, true, 0, false, 0));
234 status = STATE_CRITICAL; 230
235 else if (wpl_p && loss > wpl) 231 } else if (strstr(buf, "xmt/rcv/%loss")) {
236 status = STATE_WARNING; 232 /* no min/max/avg if host was unreachable in fping v2.2.b1 */
237 else if (wrta_p && rta > wrta) 233 /* in v2.4b2: 10.99.0.1 : xmt/rcv/%loss = 0/0/0% */
238 status = STATE_WARNING; 234 losstr = strstr(buf, "=");
239 else 235 xmtstr = 1 + losstr;
240 status = STATE_OK; 236 xmt = strtod(xmtstr, NULL);
241 die (status, 237 if (xmt == 0)
242 _("FPING %s - %s (loss=%.0f%%, rta=%f ms)|%s %s\n"), 238 die(STATE_CRITICAL, _("FPING CRITICAL - %s is down\n"), server_name);
243 state_text (status), server_name, loss, rta, 239 losstr = 1 + strstr(losstr, "/");
244 perfdata ("loss", (long int)loss, "%", wpl_p, wpl, cpl_p, cpl, true, 0, true, 100), 240 losstr = 1 + strstr(losstr, "/");
245 fperfdata ("rta", rta/1.0e3, "s", wrta_p, wrta/1.0e3, crta_p, crta/1.0e3, true, 0, false, 0)); 241 loss = strtod(losstr, NULL);
246 242 if (atoi(losstr) == 100)
247 } 243 status = STATE_CRITICAL;
248 else if(strstr (buf, "xmt/rcv/%loss") ) { 244 else if (cpl_p && loss > cpl)
249 /* no min/max/avg if host was unreachable in fping v2.2.b1 */ 245 status = STATE_CRITICAL;
250 /* in v2.4b2: 10.99.0.1 : xmt/rcv/%loss = 0/0/0% */ 246 else if (wpl_p && loss > wpl)
251 losstr = strstr (buf, "="); 247 status = STATE_WARNING;
252 xmtstr = 1 + losstr; 248 else
253 xmt = strtod (xmtstr, NULL); 249 status = STATE_OK;
254 if(xmt == 0) 250 /* loss=%.0f%%;%d;%d;0;100 */
255 die (STATE_CRITICAL, _("FPING CRITICAL - %s is down\n"), server_name); 251 die(status, _("FPING %s - %s (loss=%.0f%% )|%s\n"), state_text(status), server_name, loss,
256 losstr = 1 + strstr (losstr, "/"); 252 perfdata("loss", (long int)loss, "%", wpl_p, wpl, cpl_p, cpl, true, 0, true, 100));
257 losstr = 1 + strstr (losstr, "/"); 253
258 loss = strtod (losstr, NULL); 254 } else {
259 if (atoi(losstr) == 100) 255 status = max_state(status, STATE_WARNING);
260 status = STATE_CRITICAL; 256 }
261 else if (cpl_p && loss > cpl) 257
262 status = STATE_CRITICAL; 258 return status;
263 else if (wpl_p && loss > wpl)
264 status = STATE_WARNING;
265 else
266 status = STATE_OK;
267 /* loss=%.0f%%;%d;%d;0;100 */
268 die (status, _("FPING %s - %s (loss=%.0f%% )|%s\n"),
269 state_text (status), server_name, loss ,
270 perfdata ("loss", (long int)loss, "%", wpl_p, wpl, cpl_p, cpl, true, 0, true, 100));
271
272 }
273 else {
274 status = max_state (status, STATE_WARNING);
275 }
276
277 return status;
278} 259}
279 260
280
281
282/* process command-line arguments */ 261/* process command-line arguments */
283int 262int process_arguments(int argc, char **argv) {
284process_arguments (int argc, char **argv) 263 int c;
285{ 264 char *rv[2];
286 int c; 265
287 char *rv[2]; 266 int option = 0;
288 267 static struct option longopts[] = {{"hostname", required_argument, 0, 'H'},
289 int option = 0; 268 {"sourceip", required_argument, 0, 'S'},
290 static struct option longopts[] = { 269 {"sourceif", required_argument, 0, 'I'},
291 {"hostname", required_argument, 0, 'H'}, 270 {"critical", required_argument, 0, 'c'},
292 {"sourceip", required_argument, 0, 'S'}, 271 {"warning", required_argument, 0, 'w'},
293 {"sourceif", required_argument, 0, 'I'}, 272 {"alive", no_argument, 0, 'a'},
294 {"critical", required_argument, 0, 'c'}, 273 {"bytes", required_argument, 0, 'b'},
295 {"warning", required_argument, 0, 'w'}, 274 {"number", required_argument, 0, 'n'},
296 {"alive", no_argument, 0, 'a'}, 275 {"target-timeout", required_argument, 0, 'T'},
297 {"bytes", required_argument, 0, 'b'}, 276 {"interval", required_argument, 0, 'i'},
298 {"number", required_argument, 0, 'n'}, 277 {"verbose", no_argument, 0, 'v'},
299 {"target-timeout", required_argument, 0, 'T'}, 278 {"version", no_argument, 0, 'V'},
300 {"interval", required_argument, 0, 'i'}, 279 {"help", no_argument, 0, 'h'},
301 {"verbose", no_argument, 0, 'v'}, 280 {"use-ipv4", no_argument, 0, '4'},
302 {"version", no_argument, 0, 'V'}, 281 {"use-ipv6", no_argument, 0, '6'},
303 {"help", no_argument, 0, 'h'}, 282 {0, 0, 0, 0}};
304 {"use-ipv4", no_argument, 0, '4'}, 283
305 {"use-ipv6", no_argument, 0, '6'}, 284 rv[PL] = NULL;
306 {0, 0, 0, 0} 285 rv[RTA] = NULL;
307 }; 286
308 287 if (argc < 2)
309 rv[PL] = NULL; 288 return ERROR;
310 rv[RTA] = NULL; 289
311 290 if (!is_option(argv[1])) {
312 if (argc < 2) 291 server_name = argv[1];
313 return ERROR; 292 argv[1] = argv[0];
314 293 argv = &argv[1];
315 if (!is_option (argv[1])) { 294 argc--;
316 server_name = argv[1]; 295 }
317 argv[1] = argv[0]; 296
318 argv = &argv[1]; 297 while (1) {
319 argc--; 298 c = getopt_long(argc, argv, "+hVvaH:S:c:w:b:n:T:i:I:46", longopts, &option);
320 } 299
321 300 if (c == -1 || c == EOF || c == 1)
322 while (1) { 301 break;
323 c = getopt_long (argc, argv, "+hVvaH:S:c:w:b:n:T:i:I:46", longopts, &option); 302
324 303 switch (c) {
325 if (c == -1 || c == EOF || c == 1) 304 case '?': /* print short usage statement if args not parsable */
326 break; 305 usage5();
327 306 case 'a': /* host alive mode */
328 switch (c) { 307 alive_p = true;
329 case '?': /* print short usage statement if args not parsable */ 308 break;
330 usage5 (); 309 case 'h': /* help */
331 case 'a': /* host alive mode */ 310 print_help();
332 alive_p = true; 311 exit(STATE_UNKNOWN);
333 break; 312 case 'V': /* version */
334 case 'h': /* help */ 313 print_revision(progname, NP_VERSION);
335 print_help (); 314 exit(STATE_UNKNOWN);
336 exit (STATE_UNKNOWN); 315 case 'v': /* verbose mode */
337 case 'V': /* version */ 316 verbose = true;
338 print_revision (progname, NP_VERSION); 317 break;
339 exit (STATE_UNKNOWN); 318 case 'H': /* hostname */
340 case 'v': /* verbose mode */ 319 if (is_host(optarg) == false) {
341 verbose = true; 320 usage2(_("Invalid hostname/address"), optarg);
342 break; 321 }
343 case 'H': /* hostname */ 322 server_name = strscpy(server_name, optarg);
344 if (is_host (optarg) == false) { 323 break;
345 usage2 (_("Invalid hostname/address"), optarg); 324 case 'S': /* sourceip */
346 } 325 if (is_host(optarg) == false) {
347 server_name = strscpy (server_name, optarg); 326 usage2(_("Invalid hostname/address"), optarg);
348 break; 327 }
349 case 'S': /* sourceip */ 328 sourceip = strscpy(sourceip, optarg);
350 if (is_host (optarg) == false) { 329 break;
351 usage2 (_("Invalid hostname/address"), optarg); 330 case 'I': /* sourceip */
352 } 331 sourceif = strscpy(sourceif, optarg);
353 sourceip = strscpy (sourceip, optarg); 332 break;
354 break; 333 case '4': /* IPv4 only */
355 case 'I': /* sourceip */ 334 address_family = AF_INET;
356 sourceif = strscpy (sourceif, optarg);
357 break; 335 break;
358 case '4': /* IPv4 only */ 336 case '6': /* IPv6 only */
359 address_family = AF_INET;
360 break;
361 case '6': /* IPv6 only */
362#ifdef USE_IPV6 337#ifdef USE_IPV6
363 address_family = AF_INET6; 338 address_family = AF_INET6;
364#else 339#else
365 usage (_("IPv6 support not available\n")); 340 usage(_("IPv6 support not available\n"));
366#endif 341#endif
367 break; 342 break;
368 case 'c': 343 case 'c':
369 get_threshold (optarg, rv); 344 get_threshold(optarg, rv);
370 if (rv[RTA]) { 345 if (rv[RTA]) {
371 crta = strtod (rv[RTA], NULL); 346 crta = strtod(rv[RTA], NULL);
372 crta_p = true; 347 crta_p = true;
373 rv[RTA] = NULL; 348 rv[RTA] = NULL;
374 } 349 }
375 if (rv[PL]) { 350 if (rv[PL]) {
376 cpl = atoi (rv[PL]); 351 cpl = atoi(rv[PL]);
377 cpl_p = true; 352 cpl_p = true;
378 rv[PL] = NULL; 353 rv[PL] = NULL;
379 } 354 }
380 break; 355 break;
381 case 'w': 356 case 'w':
382 get_threshold (optarg, rv); 357 get_threshold(optarg, rv);
383 if (rv[RTA]) { 358 if (rv[RTA]) {
384 wrta = strtod (rv[RTA], NULL); 359 wrta = strtod(rv[RTA], NULL);
385 wrta_p = true; 360 wrta_p = true;
386 rv[RTA] = NULL; 361 rv[RTA] = NULL;
387 } 362 }
388 if (rv[PL]) { 363 if (rv[PL]) {
389 wpl = atoi (rv[PL]); 364 wpl = atoi(rv[PL]);
390 wpl_p = true; 365 wpl_p = true;
391 rv[PL] = NULL; 366 rv[PL] = NULL;
392 } 367 }
393 break; 368 break;
394 case 'b': /* bytes per packet */ 369 case 'b': /* bytes per packet */
395 if (is_intpos (optarg)) 370 if (is_intpos(optarg))
396 packet_size = atoi (optarg); 371 packet_size = atoi(optarg);
397 else 372 else
398 usage (_("Packet size must be a positive integer")); 373 usage(_("Packet size must be a positive integer"));
399 break; 374 break;
400 case 'n': /* number of packets */ 375 case 'n': /* number of packets */
401 if (is_intpos (optarg)) 376 if (is_intpos(optarg))
402 packet_count = atoi (optarg); 377 packet_count = atoi(optarg);
403 else 378 else
404 usage (_("Packet count must be a positive integer")); 379 usage(_("Packet count must be a positive integer"));
405 break; 380 break;
406 case 'T': /* timeout in msec */ 381 case 'T': /* timeout in msec */
407 if (is_intpos (optarg)) 382 if (is_intpos(optarg))
408 target_timeout = atoi (optarg); 383 target_timeout = atoi(optarg);
409 else 384 else
410 usage (_("Target timeout must be a positive integer")); 385 usage(_("Target timeout must be a positive integer"));
411 break; 386 break;
412 case 'i': /* interval in msec */ 387 case 'i': /* interval in msec */
413 if (is_intpos (optarg)) 388 if (is_intpos(optarg))
414 packet_interval = atoi (optarg); 389 packet_interval = atoi(optarg);
415 else 390 else
416 usage (_("Interval must be a positive integer")); 391 usage(_("Interval must be a positive integer"));
417 break; 392 break;
418 } 393 }
419 } 394 }
420
421 if (server_name == NULL)
422 usage4 (_("Hostname was not supplied"));
423
424 return OK;
425}
426 395
396 if (server_name == NULL)
397 usage4(_("Hostname was not supplied"));
427 398
428int 399 return OK;
429get_threshold (char *arg, char *rv[2])
430{
431 char *arg1 = NULL;
432 char *arg2 = NULL;
433
434 arg1 = strscpy (arg1, arg);
435 if (strpbrk (arg1, ",:"))
436 arg2 = 1 + strpbrk (arg1, ",:");
437
438 if (arg2) {
439 arg1[strcspn (arg1, ",:")] = 0;
440 if (strstr (arg1, "%") && strstr (arg2, "%"))
441 die (STATE_UNKNOWN,
442 _("%s: Only one threshold may be packet loss (%s)\n"), progname,
443 arg);
444 if (!strstr (arg1, "%") && !strstr (arg2, "%"))
445 die (STATE_UNKNOWN,
446 _("%s: Only one threshold must be packet loss (%s)\n"),
447 progname, arg);
448 }
449
450 if (arg2 && strstr (arg2, "%")) {
451 rv[PL] = arg2;
452 rv[RTA] = arg1;
453 }
454 else if (arg2) {
455 rv[PL] = arg1;
456 rv[RTA] = arg2;
457 }
458 else if (strstr (arg1, "%")) {
459 rv[PL] = arg1;
460 }
461 else {
462 rv[RTA] = arg1;
463 }
464
465 return OK;
466} 400}
467 401
402int get_threshold(char *arg, char *rv[2]) {
403 char *arg1 = NULL;
404 char *arg2 = NULL;
405
406 arg1 = strscpy(arg1, arg);
407 if (strpbrk(arg1, ",:"))
408 arg2 = 1 + strpbrk(arg1, ",:");
409
410 if (arg2) {
411 arg1[strcspn(arg1, ",:")] = 0;
412 if (strstr(arg1, "%") && strstr(arg2, "%"))
413 die(STATE_UNKNOWN, _("%s: Only one threshold may be packet loss (%s)\n"), progname, arg);
414 if (!strstr(arg1, "%") && !strstr(arg2, "%"))
415 die(STATE_UNKNOWN, _("%s: Only one threshold must be packet loss (%s)\n"), progname, arg);
416 }
417
418 if (arg2 && strstr(arg2, "%")) {
419 rv[PL] = arg2;
420 rv[RTA] = arg1;
421 } else if (arg2) {
422 rv[PL] = arg1;
423 rv[RTA] = arg2;
424 } else if (strstr(arg1, "%")) {
425 rv[PL] = arg1;
426 } else {
427 rv[RTA] = arg1;
428 }
429
430 return OK;
431}
468 432
469void print_help (void) { 433void print_help(void) {
470 434
471 print_revision (progname, NP_VERSION); 435 print_revision(progname, NP_VERSION);
472 436
473 printf ("Copyright (c) 1999 Didi Rieder <adrieder@sbox.tu-graz.ac.at>\n"); 437 printf("Copyright (c) 1999 Didi Rieder <adrieder@sbox.tu-graz.ac.at>\n");
474 printf (COPYRIGHT, copyright, email); 438 printf(COPYRIGHT, copyright, email);
475 439
476 printf ("%s\n", _("This plugin will use the fping command to ping the specified host for a fast check")); 440 printf("%s\n", _("This plugin will use the fping command to ping the specified host for a fast check"));
477 441
478 printf ("%s\n", _("Note that it is necessary to set the suid flag on fping.")); 442 printf("%s\n", _("Note that it is necessary to set the suid flag on fping."));
479 443
480 printf ("\n\n"); 444 printf("\n\n");
481 445
482 print_usage (); 446 print_usage();
483 447
484 printf (UT_HELP_VRSN); 448 printf(UT_HELP_VRSN);
485 printf (UT_EXTRA_OPTS); 449 printf(UT_EXTRA_OPTS);
486 450
487 printf (UT_IPv46); 451 printf(UT_IPv46);
488 452
489 printf (" %s\n", "-H, --hostname=HOST"); 453 printf(" %s\n", "-H, --hostname=HOST");
490 printf (" %s\n", _("name or IP Address of host to ping (IP Address bypasses name lookup, reducing system load)")); 454 printf(" %s\n", _("name or IP Address of host to ping (IP Address bypasses name lookup, reducing system load)"));
491 printf (" %s\n", "-w, --warning=THRESHOLD"); 455 printf(" %s\n", "-w, --warning=THRESHOLD");
492 printf (" %s\n", _("warning threshold pair")); 456 printf(" %s\n", _("warning threshold pair"));
493 printf (" %s\n", "-c, --critical=THRESHOLD"); 457 printf(" %s\n", "-c, --critical=THRESHOLD");
494 printf (" %s\n", _("critical threshold pair")); 458 printf(" %s\n", _("critical threshold pair"));
495 printf (" %s\n", "-a, --alive"); 459 printf(" %s\n", "-a, --alive");
496 printf (" %s\n", _("Return OK after first successful reply")); 460 printf(" %s\n", _("Return OK after first successful reply"));
497 printf (" %s\n", "-b, --bytes=INTEGER"); 461 printf(" %s\n", "-b, --bytes=INTEGER");
498 printf (" %s (default: %d)\n", _("size of ICMP packet"),PACKET_SIZE); 462 printf(" %s (default: %d)\n", _("size of ICMP packet"), PACKET_SIZE);
499 printf (" %s\n", "-n, --number=INTEGER"); 463 printf(" %s\n", "-n, --number=INTEGER");
500 printf (" %s (default: %d)\n", _("number of ICMP packets to send"),PACKET_COUNT); 464 printf(" %s (default: %d)\n", _("number of ICMP packets to send"), PACKET_COUNT);
501 printf (" %s\n", "-T, --target-timeout=INTEGER"); 465 printf(" %s\n", "-T, --target-timeout=INTEGER");
502 printf (" %s (default: fping's default for -t)\n", _("Target timeout (ms)")); 466 printf(" %s (default: fping's default for -t)\n", _("Target timeout (ms)"));
503 printf (" %s\n", "-i, --interval=INTEGER"); 467 printf(" %s\n", "-i, --interval=INTEGER");
504 printf (" %s (default: fping's default for -p)\n", _("Interval (ms) between sending packets")); 468 printf(" %s (default: fping's default for -p)\n", _("Interval (ms) between sending packets"));
505 printf (" %s\n", "-S, --sourceip=HOST"); 469 printf(" %s\n", "-S, --sourceip=HOST");
506 printf (" %s\n", _("name or IP Address of sourceip")); 470 printf(" %s\n", _("name or IP Address of sourceip"));
507 printf (" %s\n", "-I, --sourceif=IF"); 471 printf(" %s\n", "-I, --sourceif=IF");
508 printf (" %s\n", _("source interface name")); 472 printf(" %s\n", _("source interface name"));
509 printf (UT_VERBOSE); 473 printf(UT_VERBOSE);
510 printf ("\n"); 474 printf("\n");
511 printf (" %s\n", _("THRESHOLD is <rta>,<pl>%% where <rta> is the round trip average travel time (ms)")); 475 printf(" %s\n", _("THRESHOLD is <rta>,<pl>%% where <rta> is the round trip average travel time (ms)"));
512 printf (" %s\n", _("which triggers a WARNING or CRITICAL state, and <pl> is the percentage of")); 476 printf(" %s\n", _("which triggers a WARNING or CRITICAL state, and <pl> is the percentage of"));
513 printf (" %s\n", _("packet loss to trigger an alarm state.")); 477 printf(" %s\n", _("packet loss to trigger an alarm state."));
514 478
515 printf ("\n"); 479 printf("\n");
516 printf (" %s\n", _("IPv4 is used by default. Specify -6 to use IPv6.")); 480 printf(" %s\n", _("IPv4 is used by default. Specify -6 to use IPv6."));
517 481
518 printf (UT_SUPPORT); 482 printf(UT_SUPPORT);
519} 483}
520 484
521 485void print_usage(void) {
522void 486 printf("%s\n", _("Usage:"));
523print_usage (void) 487 printf(" %s <host_address> -w limit -c limit [-b size] [-n number] [-T number] [-i number]\n", progname);
524{
525 printf ("%s\n", _("Usage:"));
526 printf (" %s <host_address> -w limit -c limit [-b size] [-n number] [-T number] [-i number]\n", progname);
527} 488}
diff --git a/plugins/check_game.c b/plugins/check_game.c
index ca126973..619277e7 100644
--- a/plugins/check_game.c
+++ b/plugins/check_game.c
@@ -1,335 +1,308 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring check_game plugin 3 * Monitoring check_game plugin
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 2002-2007 Monitoring Plugins Development Team 6 * Copyright (c) 2002-2024 Monitoring Plugins Development Team
7* 7 *
8* Description: 8 * Description:
9* 9 *
10* This file contains the check_game plugin 10 * This file contains the check_game plugin
11* 11 *
12* This plugin tests game server connections with the specified host. 12 * This plugin tests game server connections with the specified host.
13* using the qstat program 13 * using the qstat program
14* 14 *
15* 15 *
16* This program is free software: you can redistribute it and/or modify 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 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 18 * the Free Software Foundation, either version 3 of the License, or
19* (at your option) any later version. 19 * (at your option) any later version.
20* 20 *
21* This program is distributed in the hope that it will be useful, 21 * This program is distributed in the hope that it will be useful,
22* but WITHOUT ANY WARRANTY; without even the implied warranty of 22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24* GNU General Public License for more details. 24 * GNU General Public License for more details.
25* 25 *
26* You should have received a copy of the GNU General Public License 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/>. 27 * along with this program. If not, see <http://www.gnu.org/licenses/>.
28* 28 *
29* 29 *
30*****************************************************************************/ 30 *****************************************************************************/
31 31
32const char *progname = "check_game"; 32const char *progname = "check_game";
33const char *copyright = "2002-2007"; 33const char *copyright = "2002-2024";
34const char *email = "devel@monitoring-plugins.org"; 34const char *email = "devel@monitoring-plugins.org";
35 35
36#include "common.h" 36#include "common.h"
37#include "utils.h" 37#include "utils.h"
38#include "runcmd.h" 38#include "runcmd.h"
39 39
40int process_arguments (int, char **); 40static int process_arguments(int /*argc*/, char ** /*argv*/);
41int validate_arguments (void); 41static int validate_arguments(void);
42void print_help (void); 42static void print_help(void);
43void print_usage (void); 43void print_usage(void);
44 44
45#define QSTAT_DATA_DELIMITER "," 45#define QSTAT_DATA_DELIMITER ","
46 46
47#define QSTAT_HOST_ERROR "ERROR" 47#define QSTAT_HOST_ERROR "ERROR"
48#define QSTAT_HOST_DOWN "DOWN" 48#define QSTAT_HOST_DOWN "DOWN"
49#define QSTAT_HOST_TIMEOUT "TIMEOUT" 49#define QSTAT_HOST_TIMEOUT "TIMEOUT"
50#define QSTAT_MAX_RETURN_ARGS 12 50#define QSTAT_MAX_RETURN_ARGS 12
51 51
52char *server_ip; 52static char *server_ip;
53char *game_type; 53static char *game_type;
54int port = 0; 54static int port = 0;
55 55
56bool verbose = false; 56static bool verbose = false;
57 57
58int qstat_game_players_max = -1; 58static int qstat_game_players_max = -1;
59int qstat_game_players = -1; 59static int qstat_game_players = -1;
60int qstat_game_field = -1; 60static int qstat_game_field = -1;
61int qstat_map_field = -1; 61static int qstat_map_field = -1;
62int qstat_ping_field = -1; 62static int qstat_ping_field = -1;
63 63
64 64int main(int argc, char **argv) {
65int 65 char *command_line;
66main (int argc, char **argv) 66 int result = STATE_UNKNOWN;
67{ 67 char *p;
68 char *command_line; 68 char *ret[QSTAT_MAX_RETURN_ARGS];
69 int result = STATE_UNKNOWN; 69 size_t i = 0;
70 char *p, *ret[QSTAT_MAX_RETURN_ARGS]; 70 output chld_out;
71 size_t i = 0; 71
72 output chld_out; 72 setlocale(LC_ALL, "");
73 73 bindtextdomain(PACKAGE, LOCALEDIR);
74 setlocale (LC_ALL, ""); 74 textdomain(PACKAGE);
75 bindtextdomain (PACKAGE, LOCALEDIR); 75
76 textdomain (PACKAGE); 76 /* Parse extra opts if any */
77 77 argv = np_extra_opts(&argc, argv, progname);
78 /* Parse extra opts if any */ 78
79 argv=np_extra_opts (&argc, argv, progname); 79 if (process_arguments(argc, argv) == ERROR)
80 80 usage_va(_("Could not parse arguments"));
81 if (process_arguments (argc, argv) == ERROR) 81
82 usage_va(_("Could not parse arguments")); 82 result = STATE_OK;
83 83
84 result = STATE_OK; 84 /* create the command line to execute */
85 85 xasprintf(&command_line, "%s -raw %s -%s %s", PATH_TO_QSTAT, QSTAT_DATA_DELIMITER, game_type, server_ip);
86 /* create the command line to execute */ 86
87 xasprintf (&command_line, "%s -raw %s -%s %s", 87 if (port)
88 PATH_TO_QSTAT, QSTAT_DATA_DELIMITER, game_type, server_ip); 88 xasprintf(&command_line, "%s:%-d", command_line, port);
89 89
90 if (port) 90 if (verbose)
91 xasprintf (&command_line, "%s:%-d", command_line, port); 91 printf("%s\n", command_line);
92 92
93 if (verbose) 93 /* run the command. historically, this plugin ignores output on stderr,
94 printf ("%s\n", command_line); 94 * as well as return status of the qstat program */
95 95 (void)np_runcmd(command_line, &chld_out, NULL, 0);
96 /* run the command. historically, this plugin ignores output on stderr, 96
97 * as well as return status of the qstat program */ 97 /* sanity check */
98 (void)np_runcmd(command_line, &chld_out, NULL, 0); 98 /* was thinking about running qstat without any options, capturing the
99 99 -default line, parsing it & making an array of all know server types
100 /* sanity check */ 100 but thought this would be too much hassle considering this is a tool
101 /* was thinking about running qstat without any options, capturing the 101 for intelligent sysadmins (ha). Could put a static array of known
102 -default line, parsing it & making an array of all know server types 102 server types in a header file but then we'd be limiting ourselves
103 but thought this would be too much hassle considering this is a tool 103
104 for intelligent sysadmins (ha). Could put a static array of known 104 In the end, I figured I'd simply let an error occur & then trap it
105 server types in a header file but then we'd be limiting ourselves 105 */
106 106
107 In the end, I figured I'd simply let an error occur & then trap it 107 if (!strncmp(chld_out.line[0], "unknown option", 14)) {
108 */ 108 printf(_("CRITICAL - Host type parameter incorrect!\n"));
109 109 result = STATE_CRITICAL;
110 if (!strncmp (chld_out.line[0], "unknown option", 14)) { 110 return result;
111 printf (_("CRITICAL - Host type parameter incorrect!\n")); 111 }
112 result = STATE_CRITICAL; 112
113 return result; 113 p = (char *)strtok(chld_out.line[0], QSTAT_DATA_DELIMITER);
114 } 114 while (p != NULL) {
115 115 ret[i] = p;
116 p = (char *) strtok (chld_out.line[0], QSTAT_DATA_DELIMITER); 116 p = (char *)strtok(NULL, QSTAT_DATA_DELIMITER);
117 while (p != NULL) { 117 i++;
118 ret[i] = p; 118 if (i >= QSTAT_MAX_RETURN_ARGS)
119 p = (char *) strtok (NULL, QSTAT_DATA_DELIMITER); 119 break;
120 i++; 120 }
121 if (i >= QSTAT_MAX_RETURN_ARGS) 121
122 break; 122 if (strstr(ret[2], QSTAT_HOST_ERROR)) {
123 } 123 printf(_("CRITICAL - Host not found\n"));
124 124 result = STATE_CRITICAL;
125 if (strstr (ret[2], QSTAT_HOST_ERROR)) { 125 } else if (strstr(ret[2], QSTAT_HOST_DOWN)) {
126 printf (_("CRITICAL - Host not found\n")); 126 printf(_("CRITICAL - Game server down or unavailable\n"));
127 result = STATE_CRITICAL; 127 result = STATE_CRITICAL;
128 } 128 } else if (strstr(ret[2], QSTAT_HOST_TIMEOUT)) {
129 else if (strstr (ret[2], QSTAT_HOST_DOWN)) { 129 printf(_("CRITICAL - Game server timeout\n"));
130 printf (_("CRITICAL - Game server down or unavailable\n")); 130 result = STATE_CRITICAL;
131 result = STATE_CRITICAL; 131 } else {
132 } 132 printf("OK: %s/%s %s (%s), Ping: %s ms|%s %s\n", ret[qstat_game_players], ret[qstat_game_players_max], ret[qstat_game_field],
133 else if (strstr (ret[2], QSTAT_HOST_TIMEOUT)) { 133 ret[qstat_map_field], ret[qstat_ping_field],
134 printf (_("CRITICAL - Game server timeout\n")); 134 perfdata("players", atol(ret[qstat_game_players]), "", false, 0, false, 0, true, 0, true, atol(ret[qstat_game_players_max])),
135 result = STATE_CRITICAL; 135 fperfdata("ping", strtod(ret[qstat_ping_field], NULL), "", false, 0, false, 0, true, 0, false, 0));
136 } 136 }
137 else { 137
138 printf ("OK: %s/%s %s (%s), Ping: %s ms|%s %s\n", 138 return result;
139 ret[qstat_game_players],
140 ret[qstat_game_players_max],
141 ret[qstat_game_field],
142 ret[qstat_map_field],
143 ret[qstat_ping_field],
144 perfdata ("players", atol(ret[qstat_game_players]), "",
145 false, 0, false, 0,
146 true, 0, true, atol(ret[qstat_game_players_max])),
147 fperfdata ("ping", strtod(ret[qstat_ping_field], NULL), "",
148 false, 0, false, 0,
149 true, 0, false, 0));
150 }
151
152 return result;
153} 139}
154 140
155 141int process_arguments(int argc, char **argv) {
156int 142 int c;
157process_arguments (int argc, char **argv) 143
158{ 144 int opt_index = 0;
159 int c; 145 static struct option long_opts[] = {{"help", no_argument, 0, 'h'},
160 146 {"version", no_argument, 0, 'V'},
161 int opt_index = 0; 147 {"verbose", no_argument, 0, 'v'},
162 static struct option long_opts[] = { 148 {"timeout", required_argument, 0, 't'},
163 {"help", no_argument, 0, 'h'}, 149 {"hostname", required_argument, 0, 'H'},
164 {"version", no_argument, 0, 'V'}, 150 {"port", required_argument, 0, 'P'},
165 {"verbose", no_argument, 0, 'v'}, 151 {"game-type", required_argument, 0, 'G'},
166 {"timeout", required_argument, 0, 't'}, 152 {"map-field", required_argument, 0, 'm'},
167 {"hostname", required_argument, 0, 'H'}, 153 {"ping-field", required_argument, 0, 'p'},
168 {"port", required_argument, 0, 'P'}, 154 {"game-field", required_argument, 0, 'g'},
169 {"game-type", required_argument, 0, 'G'}, 155 {"players-field", required_argument, 0, 129},
170 {"map-field", required_argument, 0, 'm'}, 156 {"max-players-field", required_argument, 0, 130},
171 {"ping-field", required_argument, 0, 'p'}, 157 {0, 0, 0, 0}};
172 {"game-field", required_argument, 0, 'g'}, 158
173 {"players-field", required_argument, 0, 129}, 159 if (argc < 2)
174 {"max-players-field", required_argument, 0, 130}, 160 return ERROR;
175 {0, 0, 0, 0} 161
176 }; 162 for (c = 1; c < argc; c++) {
177 163 if (strcmp("-mf", argv[c]) == 0)
178 if (argc < 2) 164 strcpy(argv[c], "-m");
179 return ERROR; 165 else if (strcmp("-pf", argv[c]) == 0)
180 166 strcpy(argv[c], "-p");
181 for (c = 1; c < argc; c++) { 167 else if (strcmp("-gf", argv[c]) == 0)
182 if (strcmp ("-mf", argv[c]) == 0) 168 strcpy(argv[c], "-g");
183 strcpy (argv[c], "-m"); 169 }
184 else if (strcmp ("-pf", argv[c]) == 0) 170
185 strcpy (argv[c], "-p"); 171 while (1) {
186 else if (strcmp ("-gf", argv[c]) == 0) 172 c = getopt_long(argc, argv, "hVvt:H:P:G:g:p:m:", long_opts, &opt_index);
187 strcpy (argv[c], "-g"); 173
188 } 174 if (c == -1 || c == EOF)
189 175 break;
190 while (1) { 176
191 c = getopt_long (argc, argv, "hVvt:H:P:G:g:p:m:", long_opts, &opt_index); 177 switch (c) {
192 178 case 'h': /* help */
193 if (c == -1 || c == EOF) 179 print_help();
194 break; 180 exit(STATE_UNKNOWN);
195 181 case 'V': /* version */
196 switch (c) { 182 print_revision(progname, NP_VERSION);
197 case 'h': /* help */ 183 exit(STATE_UNKNOWN);
198 print_help (); 184 case 'v': /* version */
199 exit (STATE_UNKNOWN); 185 verbose = true;
200 case 'V': /* version */ 186 break;
201 print_revision (progname, NP_VERSION); 187 case 't': /* timeout period */
202 exit (STATE_UNKNOWN); 188 timeout_interval = atoi(optarg);
203 case 'v': /* version */ 189 break;
204 verbose = true; 190 case 'H': /* hostname */
205 break; 191 if (strlen(optarg) >= MAX_HOST_ADDRESS_LENGTH)
206 case 't': /* timeout period */ 192 die(STATE_UNKNOWN, _("Input buffer overflow\n"));
207 timeout_interval = atoi (optarg); 193 server_ip = optarg;
208 break; 194 break;
209 case 'H': /* hostname */ 195 case 'P': /* port */
210 if (strlen (optarg) >= MAX_HOST_ADDRESS_LENGTH) 196 port = atoi(optarg);
211 die (STATE_UNKNOWN, _("Input buffer overflow\n")); 197 break;
212 server_ip = optarg; 198 case 'G': /* hostname */
213 break; 199 if (strlen(optarg) >= MAX_INPUT_BUFFER)
214 case 'P': /* port */ 200 die(STATE_UNKNOWN, _("Input buffer overflow\n"));
215 port = atoi (optarg); 201 game_type = optarg;
216 break; 202 break;
217 case 'G': /* hostname */ 203 case 'p': /* index of ping field */
218 if (strlen (optarg) >= MAX_INPUT_BUFFER) 204 qstat_ping_field = atoi(optarg);
219 die (STATE_UNKNOWN, _("Input buffer overflow\n")); 205 if (qstat_ping_field < 0 || qstat_ping_field > QSTAT_MAX_RETURN_ARGS)
220 game_type = optarg; 206 return ERROR;
221 break; 207 break;
222 case 'p': /* index of ping field */ 208 case 'm': /* index on map field */
223 qstat_ping_field = atoi (optarg); 209 qstat_map_field = atoi(optarg);
224 if (qstat_ping_field < 0 || qstat_ping_field > QSTAT_MAX_RETURN_ARGS) 210 if (qstat_map_field < 0 || qstat_map_field > QSTAT_MAX_RETURN_ARGS)
225 return ERROR; 211 return ERROR;
226 break; 212 break;
227 case 'm': /* index on map field */ 213 case 'g': /* index of game field */
228 qstat_map_field = atoi (optarg); 214 qstat_game_field = atoi(optarg);
229 if (qstat_map_field < 0 || qstat_map_field > QSTAT_MAX_RETURN_ARGS) 215 if (qstat_game_field < 0 || qstat_game_field > QSTAT_MAX_RETURN_ARGS)
230 return ERROR; 216 return ERROR;
231 break; 217 break;
232 case 'g': /* index of game field */ 218 case 129: /* index of player count field */
233 qstat_game_field = atoi (optarg); 219 qstat_game_players = atoi(optarg);
234 if (qstat_game_field < 0 || qstat_game_field > QSTAT_MAX_RETURN_ARGS) 220 if (qstat_game_players_max == 0)
235 return ERROR; 221 qstat_game_players_max = qstat_game_players - 1;
236 break; 222 if (qstat_game_players < 0 || qstat_game_players > QSTAT_MAX_RETURN_ARGS)
237 case 129: /* index of player count field */ 223 return ERROR;
238 qstat_game_players = atoi (optarg); 224 break;
239 if (qstat_game_players_max == 0) 225 case 130: /* index of max players field */
240 qstat_game_players_max = qstat_game_players - 1; 226 qstat_game_players_max = atoi(optarg);
241 if (qstat_game_players < 0 || qstat_game_players > QSTAT_MAX_RETURN_ARGS) 227 if (qstat_game_players_max < 0 || qstat_game_players_max > QSTAT_MAX_RETURN_ARGS)
242 return ERROR; 228 return ERROR;
243 break; 229 break;
244 case 130: /* index of max players field */ 230 default: /* args not parsable */
245 qstat_game_players_max = atoi (optarg); 231 usage5();
246 if (qstat_game_players_max < 0 || qstat_game_players_max > QSTAT_MAX_RETURN_ARGS) 232 }
247 return ERROR; 233 }
248 break; 234
249 default: /* args not parsable */ 235 c = optind;
250 usage5(); 236 /* first option is the game type */
251 } 237 if (!game_type && c < argc)
252 } 238 game_type = strdup(argv[c++]);
253 239
254 c = optind; 240 /* Second option is the server name */
255 /* first option is the game type */ 241 if (!server_ip && c < argc)
256 if (!game_type && c<argc) 242 server_ip = strdup(argv[c++]);
257 game_type = strdup (argv[c++]); 243
258 244 return validate_arguments();
259 /* Second option is the server name */
260 if (!server_ip && c<argc)
261 server_ip = strdup (argv[c++]);
262
263 return validate_arguments ();
264} 245}
265 246
247int validate_arguments(void) {
248 if (qstat_game_players_max < 0)
249 qstat_game_players_max = 4;
266 250
267int 251 if (qstat_game_players < 0)
268validate_arguments (void) 252 qstat_game_players = 5;
269{
270 if (qstat_game_players_max < 0)
271 qstat_game_players_max = 4;
272 253
273 if (qstat_game_players < 0) 254 if (qstat_game_field < 0)
274 qstat_game_players = 5; 255 qstat_game_field = 2;
275 256
276 if (qstat_game_field < 0) 257 if (qstat_map_field < 0)
277 qstat_game_field = 2; 258 qstat_map_field = 3;
278 259
279 if (qstat_map_field < 0) 260 if (qstat_ping_field < 0)
280 qstat_map_field = 3; 261 qstat_ping_field = 5;
281 262
282 if (qstat_ping_field < 0) 263 return OK;
283 qstat_ping_field = 5;
284
285 return OK;
286} 264}
287 265
266void print_help(void) {
267 print_revision(progname, NP_VERSION);
288 268
289void 269 printf("Copyright (c) 1999 Ian Cass, Knowledge Matters Limited\n");
290print_help (void) 270 printf(COPYRIGHT, copyright, email);
291{
292 print_revision (progname, NP_VERSION);
293
294 printf ("Copyright (c) 1999 Ian Cass, Knowledge Matters Limited\n");
295 printf (COPYRIGHT, copyright, email);
296 271
297 printf (_("This plugin tests game server connections with the specified host.")); 272 printf(_("This plugin tests game server connections with the specified host."));
298 273
299 printf ("\n\n"); 274 printf("\n\n");
300 275
301 print_usage (); 276 print_usage();
302 277
303 printf (UT_HELP_VRSN); 278 printf(UT_HELP_VRSN);
304 printf (UT_EXTRA_OPTS); 279 printf(UT_EXTRA_OPTS);
305 280
306 printf (" %s\n", "-p"); 281 printf(" %s\n", "-p");
307 printf (" %s\n", _("Optional port of which to connect")); 282 printf(" %s\n", _("Optional port of which to connect"));
308 printf (" %s\n", "gf"); 283 printf(" %s\n", "gf");
309 printf (" %s\n", _("Field number in raw qstat output that contains game name")); 284 printf(" %s\n", _("Field number in raw qstat output that contains game name"));
310 printf (" %s\n", "-mf"); 285 printf(" %s\n", "-mf");
311 printf (" %s\n", _("Field number in raw qstat output that contains map name")); 286 printf(" %s\n", _("Field number in raw qstat output that contains map name"));
312 printf (" %s\n", "-pf"); 287 printf(" %s\n", "-pf");
313 printf (" %s\n", _("Field number in raw qstat output that contains ping time")); 288 printf(" %s\n", _("Field number in raw qstat output that contains ping time"));
314 289
315 printf (UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); 290 printf(UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
316 291
317 printf ("\n"); 292 printf("\n");
318 printf ("%s\n", _("Notes:")); 293 printf("%s\n", _("Notes:"));
319 printf (" %s\n", _("This plugin uses the 'qstat' command, the popular game server status query tool.")); 294 printf(" %s\n", _("This plugin uses the 'qstat' command, the popular game server status query tool."));
320 printf (" %s\n", _("If you don't have the package installed, you will need to download it from")); 295 printf(" %s\n", _("If you don't have the package installed, you will need to download it from"));
321 printf (" %s\n", _("https://github.com/multiplay/qstat before you can use this plugin.")); 296 printf(" %s\n", _("https://github.com/multiplay/qstat before you can use this plugin."));
322 297
323 printf (UT_SUPPORT); 298 printf(UT_SUPPORT);
324} 299}
325 300
326 301void print_usage(void) {
327 302 printf("%s\n", _("Usage:"));
328void 303 printf(" %s [-hvV] [-P port] [-t timeout] [-g game_field] [-m map_field] [-p ping_field] [-G game-time] [-H hostname] <game> "
329print_usage (void) 304 "<ip_address>\n",
330{ 305 progname);
331 printf ("%s\n", _("Usage:"));
332 printf (" %s [-hvV] [-P port] [-t timeout] [-g game_field] [-m map_field] [-p ping_field] [-G game-time] [-H hostname] <game> <ip_address>\n", progname);
333} 306}
334 307
335/****************************************************************************** 308/******************************************************************************
diff --git a/plugins/check_hpjd.c b/plugins/check_hpjd.c
index c34bb082..b39bccff 100644
--- a/plugins/check_hpjd.c
+++ b/plugins/check_hpjd.c
@@ -1,36 +1,36 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring check_hpjd plugin 3 * Monitoring check_hpjd plugin
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 2000-2007 Monitoring Plugins Development Team 6 * Copyright (c) 2000-2024 Monitoring Plugins Development Team
7* 7 *
8* Description: 8 * Description:
9* 9 *
10* This file contains the check_hpjd plugin 10 * This file contains the check_hpjd plugin
11* 11 *
12* This plugin tests the STATUS of an HP printer with a JetDirect card. 12 * This plugin tests the STATUS of an HP printer with a JetDirect card.
13* Net-SNMP must be installed on the computer running the plugin. 13 * Net-SNMP must be installed on the computer running the plugin.
14* 14 *
15* 15 *
16* This program is free software: you can redistribute it and/or modify 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 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 18 * the Free Software Foundation, either version 3 of the License, or
19* (at your option) any later version. 19 * (at your option) any later version.
20* 20 *
21* This program is distributed in the hope that it will be useful, 21 * This program is distributed in the hope that it will be useful,
22* but WITHOUT ANY WARRANTY; without even the implied warranty of 22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24* GNU General Public License for more details. 24 * GNU General Public License for more details.
25* 25 *
26* You should have received a copy of the GNU General Public License 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/>. 27 * along with this program. If not, see <http://www.gnu.org/licenses/>.
28* 28 *
29* 29 *
30*****************************************************************************/ 30 *****************************************************************************/
31 31
32const char *progname = "check_hpjd"; 32const char *progname = "check_hpjd";
33const char *copyright = "2000-2007"; 33const char *copyright = "2000-2024";
34const char *email = "devel@monitoring-plugins.org"; 34const char *email = "devel@monitoring-plugins.org";
35 35
36#include "common.h" 36#include "common.h"
@@ -39,9 +39,7 @@ const char *email = "devel@monitoring-plugins.org";
39#include "netutils.h" 39#include "netutils.h"
40 40
41#define DEFAULT_COMMUNITY "public" 41#define DEFAULT_COMMUNITY "public"
42#define DEFAULT_PORT "161" 42#define DEFAULT_PORT "161"
43
44const char *option_summary = "-H host [-C community]\n";
45 43
46#define HPJD_LINE_STATUS ".1.3.6.1.4.1.11.2.3.9.1.1.2.1" 44#define HPJD_LINE_STATUS ".1.3.6.1.4.1.11.2.3.9.1.1.2.1"
47#define HPJD_PAPER_STATUS ".1.3.6.1.4.1.11.2.3.9.1.1.2.2" 45#define HPJD_PAPER_STATUS ".1.3.6.1.4.1.11.2.3.9.1.1.2.2"
@@ -56,22 +54,20 @@ const char *option_summary = "-H host [-C community]\n";
56#define HPJD_GD_PAPER_OUTPUT ".1.3.6.1.4.1.11.2.3.9.1.1.2.19" 54#define HPJD_GD_PAPER_OUTPUT ".1.3.6.1.4.1.11.2.3.9.1.1.2.19"
57#define HPJD_GD_STATUS_DISPLAY ".1.3.6.1.4.1.11.2.3.9.1.1.3" 55#define HPJD_GD_STATUS_DISPLAY ".1.3.6.1.4.1.11.2.3.9.1.1.3"
58 56
59#define ONLINE 0 57#define ONLINE 0
60#define OFFLINE 1 58#define OFFLINE 1
61 59
62int process_arguments (int, char **); 60static int process_arguments(int /*argc*/, char ** /*argv*/);
63int validate_arguments (void); 61static int validate_arguments(void);
64void print_help (void); 62static void print_help(void);
65void print_usage (void); 63void print_usage(void);
66 64
67char *community = NULL; 65static char *community = NULL;
68char *address = NULL; 66static char *address = NULL;
69unsigned int port = 0; 67static unsigned int port = 0;
70int check_paper_out = 1; 68static int check_paper_out = 1;
71 69
72int 70int main(int argc, char **argv) {
73main (int argc, char **argv)
74{
75 char command_line[1024]; 71 char command_line[1024];
76 int result = STATE_UNKNOWN; 72 int result = STATE_UNKNOWN;
77 int line; 73 int line;
@@ -94,116 +90,99 @@ main (int argc, char **argv)
94 90
95 errmsg = malloc(MAX_INPUT_BUFFER); 91 errmsg = malloc(MAX_INPUT_BUFFER);
96 92
97 setlocale (LC_ALL, ""); 93 setlocale(LC_ALL, "");
98 bindtextdomain (PACKAGE, LOCALEDIR); 94 bindtextdomain(PACKAGE, LOCALEDIR);
99 textdomain (PACKAGE); 95 textdomain(PACKAGE);
100 96
101 /* Parse extra opts if any */ 97 /* Parse extra opts if any */
102 argv=np_extra_opts (&argc, argv, progname); 98 argv = np_extra_opts(&argc, argv, progname);
103 99
104 if (process_arguments (argc, argv) == ERROR) 100 if (process_arguments(argc, argv) == ERROR)
105 usage4 (_("Could not parse arguments")); 101 usage4(_("Could not parse arguments"));
106 102
107 /* removed ' 2>1' at end of command 10/27/1999 - EG */ 103 /* removed ' 2>1' at end of command 10/27/1999 - EG */
108 /* create the query string */ 104 /* create the query string */
109 sprintf 105 sprintf(query_string, "%s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0", HPJD_LINE_STATUS, HPJD_PAPER_STATUS,
110 (query_string, 106 HPJD_INTERVENTION_REQUIRED, HPJD_GD_PERIPHERAL_ERROR, HPJD_GD_PAPER_JAM, HPJD_GD_PAPER_OUT, HPJD_GD_TONER_LOW,
111 "%s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0", 107 HPJD_GD_PAGE_PUNT, HPJD_GD_MEMORY_OUT, HPJD_GD_DOOR_OPEN, HPJD_GD_PAPER_OUTPUT, HPJD_GD_STATUS_DISPLAY);
112 HPJD_LINE_STATUS,
113 HPJD_PAPER_STATUS,
114 HPJD_INTERVENTION_REQUIRED,
115 HPJD_GD_PERIPHERAL_ERROR,
116 HPJD_GD_PAPER_JAM,
117 HPJD_GD_PAPER_OUT,
118 HPJD_GD_TONER_LOW,
119 HPJD_GD_PAGE_PUNT,
120 HPJD_GD_MEMORY_OUT,
121 HPJD_GD_DOOR_OPEN, HPJD_GD_PAPER_OUTPUT, HPJD_GD_STATUS_DISPLAY);
122 108
123 /* get the command to run */ 109 /* get the command to run */
124 sprintf (command_line, "%s -OQa -m : -v 1 -c %s %s:%u %s", 110 sprintf(command_line, "%s -OQa -m : -v 1 -c %s %s:%u %s", PATH_TO_SNMPGET, community, address, port, query_string);
125 PATH_TO_SNMPGET,
126 community,
127 address,
128 port,
129 query_string);
130 111
131 /* run the command */ 112 /* run the command */
132 child_process = spopen (command_line); 113 child_process = spopen(command_line);
133 if (child_process == NULL) { 114 if (child_process == NULL) {
134 printf (_("Could not open pipe: %s\n"), command_line); 115 printf(_("Could not open pipe: %s\n"), command_line);
135 return STATE_UNKNOWN; 116 return STATE_UNKNOWN;
136 } 117 }
137 118
138 child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r"); 119 child_stderr = fdopen(child_stderr_array[fileno(child_process)], "r");
139 if (child_stderr == NULL) { 120 if (child_stderr == NULL) {
140 printf (_("Could not open stderr for %s\n"), command_line); 121 printf(_("Could not open stderr for %s\n"), command_line);
141 } 122 }
142 123
143 result = STATE_OK; 124 result = STATE_OK;
144 125
145 line = 0; 126 line = 0;
146 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) { 127 while (fgets(input_buffer, MAX_INPUT_BUFFER - 1, child_process)) {
147 128
148 /* strip the newline character from the end of the input */ 129 /* strip the newline character from the end of the input */
149 if (input_buffer[strlen (input_buffer) - 1] == '\n') 130 if (input_buffer[strlen(input_buffer) - 1] == '\n')
150 input_buffer[strlen (input_buffer) - 1] = 0; 131 input_buffer[strlen(input_buffer) - 1] = 0;
151 132
152 line++; 133 line++;
153 134
154 temp_buffer = strtok (input_buffer, "="); 135 temp_buffer = strtok(input_buffer, "=");
155 temp_buffer = strtok (NULL, "="); 136 temp_buffer = strtok(NULL, "=");
156 137
157 if (temp_buffer == NULL && line < 13) { 138 if (temp_buffer == NULL && line < 13) {
158 139
159 result = STATE_UNKNOWN; 140 result = STATE_UNKNOWN;
160 strcpy (errmsg, input_buffer); 141 strcpy(errmsg, input_buffer);
161 142
162 } else { 143 } else {
163 144
164 switch (line) { 145 switch (line) {
165 146
166 case 1: /* 1st line should contain the line status */ 147 case 1: /* 1st line should contain the line status */
167 line_status = atoi (temp_buffer); 148 line_status = atoi(temp_buffer);
168 break; 149 break;
169 case 2: /* 2nd line should contain the paper status */ 150 case 2: /* 2nd line should contain the paper status */
170 paper_status = atoi (temp_buffer); 151 paper_status = atoi(temp_buffer);
171 break; 152 break;
172 case 3: /* 3rd line should be intervention required */ 153 case 3: /* 3rd line should be intervention required */
173 intervention_required = atoi (temp_buffer); 154 intervention_required = atoi(temp_buffer);
174 break; 155 break;
175 case 4: /* 4th line should be peripheral error */ 156 case 4: /* 4th line should be peripheral error */
176 peripheral_error = atoi (temp_buffer); 157 peripheral_error = atoi(temp_buffer);
177 break; 158 break;
178 case 5: /* 5th line should contain the paper jam status */ 159 case 5: /* 5th line should contain the paper jam status */
179 paper_jam = atoi (temp_buffer); 160 paper_jam = atoi(temp_buffer);
180 break; 161 break;
181 case 6: /* 6th line should contain the paper out status */ 162 case 6: /* 6th line should contain the paper out status */
182 paper_out = atoi (temp_buffer); 163 paper_out = atoi(temp_buffer);
183 break; 164 break;
184 case 7: /* 7th line should contain the toner low status */ 165 case 7: /* 7th line should contain the toner low status */
185 toner_low = atoi (temp_buffer); 166 toner_low = atoi(temp_buffer);
186 break; 167 break;
187 case 8: /* did data come too slow for engine */ 168 case 8: /* did data come too slow for engine */
188 page_punt = atoi (temp_buffer); 169 page_punt = atoi(temp_buffer);
189 break; 170 break;
190 case 9: /* did we run out of memory */ 171 case 9: /* did we run out of memory */
191 memory_out = atoi (temp_buffer); 172 memory_out = atoi(temp_buffer);
192 break; 173 break;
193 case 10: /* is there a door open */ 174 case 10: /* is there a door open */
194 door_open = atoi (temp_buffer); 175 door_open = atoi(temp_buffer);
195 break; 176 break;
196 case 11: /* is output tray full */ 177 case 11: /* is output tray full */
197 paper_output = atoi (temp_buffer); 178 paper_output = atoi(temp_buffer);
198 break; 179 break;
199 case 12: /* display panel message */ 180 case 12: /* display panel message */
200 strcpy (display_message, temp_buffer + 1); 181 strcpy(display_message, temp_buffer + 1);
201 break; 182 break;
202 default: /* fold multiline message */ 183 default: /* fold multiline message */
203 strncat (display_message, input_buffer, 184 strncat(display_message, input_buffer, sizeof(display_message) - strlen(display_message) - 1);
204 sizeof (display_message) - strlen (display_message) - 1);
205 } 185 }
206
207 } 186 }
208 187
209 /* break out of the read loop if we encounter an error */ 188 /* break out of the read loop if we encounter an error */
@@ -212,29 +191,27 @@ main (int argc, char **argv)
212 } 191 }
213 192
214 /* WARNING if output found on stderr */ 193 /* WARNING if output found on stderr */
215 if (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr)) { 194 if (fgets(input_buffer, MAX_INPUT_BUFFER - 1, child_stderr)) {
216 result = max_state (result, STATE_WARNING); 195 result = max_state(result, STATE_WARNING);
217 /* remove CRLF */ 196 /* remove CRLF */
218 if (input_buffer[strlen (input_buffer) - 1] == '\n') 197 if (input_buffer[strlen(input_buffer) - 1] == '\n')
219 input_buffer[strlen (input_buffer) - 1] = 0; 198 input_buffer[strlen(input_buffer) - 1] = 0;
220 sprintf (errmsg, "%s", input_buffer ); 199 sprintf(errmsg, "%s", input_buffer);
221
222 } 200 }
223 201
224 /* close stderr */ 202 /* close stderr */
225 (void) fclose (child_stderr); 203 (void)fclose(child_stderr);
226 204
227 /* close the pipe */ 205 /* close the pipe */
228 if (spclose (child_process)) 206 if (spclose(child_process))
229 result = max_state (result, STATE_WARNING); 207 result = max_state(result, STATE_WARNING);
230 208
231 /* if there wasn't any output, display an error */ 209 /* if there wasn't any output, display an error */
232 if (line == 0) { 210 if (line == 0) {
233 211
234 /* might not be the problem, but most likely is. */ 212 /* might not be the problem, but most likely is. */
235 result = STATE_UNKNOWN ; 213 result = STATE_UNKNOWN;
236 xasprintf (&errmsg, "%s : Timeout from host %s\n", errmsg, address ); 214 xasprintf(&errmsg, "%s : Timeout from host %s\n", errmsg, address);
237
238 } 215 }
239 216
240 /* if we had no read errors, check the printer status results... */ 217 /* if we had no read errors, check the printer status results... */
@@ -242,201 +219,171 @@ main (int argc, char **argv)
242 219
243 if (paper_jam) { 220 if (paper_jam) {
244 result = STATE_WARNING; 221 result = STATE_WARNING;
245 strcpy (errmsg, _("Paper Jam")); 222 strcpy(errmsg, _("Paper Jam"));
246 } 223 } else if (paper_out) {
247 else if (paper_out) {
248 if (check_paper_out) 224 if (check_paper_out)
249 result = STATE_WARNING; 225 result = STATE_WARNING;
250 strcpy (errmsg, _("Out of Paper")); 226 strcpy(errmsg, _("Out of Paper"));
251 } 227 } else if (line_status == OFFLINE) {
252 else if (line_status == OFFLINE) { 228 if (strcmp(errmsg, "POWERSAVE ON") != 0) {
253 if (strcmp (errmsg, "POWERSAVE ON") != 0) {
254 result = STATE_WARNING; 229 result = STATE_WARNING;
255 strcpy (errmsg, _("Printer Offline")); 230 strcpy(errmsg, _("Printer Offline"));
256 } 231 }
257 } 232 } else if (peripheral_error) {
258 else if (peripheral_error) {
259 result = STATE_WARNING; 233 result = STATE_WARNING;
260 strcpy (errmsg, _("Peripheral Error")); 234 strcpy(errmsg, _("Peripheral Error"));
261 } 235 } else if (intervention_required) {
262 else if (intervention_required) {
263 result = STATE_WARNING; 236 result = STATE_WARNING;
264 strcpy (errmsg, _("Intervention Required")); 237 strcpy(errmsg, _("Intervention Required"));
265 } 238 } else if (toner_low) {
266 else if (toner_low) {
267 result = STATE_WARNING; 239 result = STATE_WARNING;
268 strcpy (errmsg, _("Toner Low")); 240 strcpy(errmsg, _("Toner Low"));
269 } 241 } else if (memory_out) {
270 else if (memory_out) {
271 result = STATE_WARNING; 242 result = STATE_WARNING;
272 strcpy (errmsg, _("Insufficient Memory")); 243 strcpy(errmsg, _("Insufficient Memory"));
273 } 244 } else if (door_open) {
274 else if (door_open) {
275 result = STATE_WARNING; 245 result = STATE_WARNING;
276 strcpy (errmsg, _("A Door is Open")); 246 strcpy(errmsg, _("A Door is Open"));
277 } 247 } else if (paper_output) {
278 else if (paper_output) {
279 result = STATE_WARNING; 248 result = STATE_WARNING;
280 strcpy (errmsg, _("Output Tray is Full")); 249 strcpy(errmsg, _("Output Tray is Full"));
281 } 250 } else if (page_punt) {
282 else if (page_punt) {
283 result = STATE_WARNING; 251 result = STATE_WARNING;
284 strcpy (errmsg, _("Data too Slow for Engine")); 252 strcpy(errmsg, _("Data too Slow for Engine"));
285 } 253 } else if (paper_status) {
286 else if (paper_status) {
287 result = STATE_WARNING; 254 result = STATE_WARNING;
288 strcpy (errmsg, _("Unknown Paper Error")); 255 strcpy(errmsg, _("Unknown Paper Error"));
289 } 256 }
290 } 257 }
291 258
292 if (result == STATE_OK) 259 if (result == STATE_OK)
293 printf (_("Printer ok - (%s)\n"), display_message); 260 printf(_("Printer ok - (%s)\n"), display_message);
294 261
295 else if (result == STATE_UNKNOWN) { 262 else if (result == STATE_UNKNOWN) {
296 263
297 printf ("%s\n", errmsg); 264 printf("%s\n", errmsg);
298 265
299 /* if printer could not be reached, escalate to critical */ 266 /* if printer could not be reached, escalate to critical */
300 if (strstr (errmsg, "Timeout")) 267 if (strstr(errmsg, "Timeout"))
301 result = STATE_CRITICAL; 268 result = STATE_CRITICAL;
302 } 269 }
303 270
304 else if (result == STATE_WARNING) 271 else if (result == STATE_WARNING)
305 printf ("%s (%s)\n", errmsg, display_message); 272 printf("%s (%s)\n", errmsg, display_message);
306 273
307 return result; 274 return result;
308} 275}
309 276
310
311/* process command-line arguments */ 277/* process command-line arguments */
312int 278int process_arguments(int argc, char **argv) {
313process_arguments (int argc, char **argv)
314{
315 int c; 279 int c;
316 280
317 int option = 0; 281 int option = 0;
318 static struct option longopts[] = { 282 static struct option longopts[] = {{"hostname", required_argument, 0, 'H'},
319 {"hostname", required_argument, 0, 'H'}, 283 {"community", required_argument, 0, 'C'},
320 {"community", required_argument, 0, 'C'}, 284 /* {"critical", required_argument,0,'c'}, */
321/* {"critical", required_argument,0,'c'}, */ 285 /* {"warning", required_argument,0,'w'}, */
322/* {"warning", required_argument,0,'w'}, */ 286 {"port", required_argument, 0, 'p'},
323 {"port", required_argument,0,'p'}, 287 {"version", no_argument, 0, 'V'},
324 {"version", no_argument, 0, 'V'}, 288 {"help", no_argument, 0, 'h'},
325 {"help", no_argument, 0, 'h'}, 289 {0, 0, 0, 0}};
326 {0, 0, 0, 0}
327 };
328 290
329 if (argc < 2) 291 if (argc < 2)
330 return ERROR; 292 return ERROR;
331 293
332
333 while (1) { 294 while (1) {
334 c = getopt_long (argc, argv, "+hVH:C:p:D", longopts, &option); 295 c = getopt_long(argc, argv, "+hVH:C:p:D", longopts, &option);
335 296
336 if (c == -1 || c == EOF || c == 1) 297 if (c == -1 || c == EOF || c == 1)
337 break; 298 break;
338 299
339 switch (c) { 300 switch (c) {
340 case 'H': /* hostname */ 301 case 'H': /* hostname */
341 if (is_host (optarg)) { 302 if (is_host(optarg)) {
342 address = strscpy(address, optarg) ; 303 address = strscpy(address, optarg);
343 } 304 } else {
344 else { 305 usage2(_("Invalid hostname/address"), optarg);
345 usage2 (_("Invalid hostname/address"), optarg);
346 } 306 }
347 break; 307 break;
348 case 'C': /* community */ 308 case 'C': /* community */
349 community = strscpy (community, optarg); 309 community = strscpy(community, optarg);
350 break; 310 break;
351 case 'p': 311 case 'p':
352 if (!is_intpos(optarg)) 312 if (!is_intpos(optarg))
353 usage2 (_("Port must be a positive short integer"), optarg); 313 usage2(_("Port must be a positive short integer"), optarg);
354 else 314 else
355 port = atoi(optarg); 315 port = atoi(optarg);
356 break; 316 break;
357 case 'D': /* disable paper out check*/ 317 case 'D': /* disable paper out check*/
358 check_paper_out = 0; 318 check_paper_out = 0;
359 break; 319 break;
360 case 'V': /* version */ 320 case 'V': /* version */
361 print_revision (progname, NP_VERSION); 321 print_revision(progname, NP_VERSION);
362 exit (STATE_UNKNOWN); 322 exit(STATE_UNKNOWN);
363 case 'h': /* help */ 323 case 'h': /* help */
364 print_help (); 324 print_help();
365 exit (STATE_UNKNOWN); 325 exit(STATE_UNKNOWN);
366 case '?': /* help */ 326 case '?': /* help */
367 usage5 (); 327 usage5();
368 } 328 }
369 } 329 }
370 330
371 c = optind; 331 c = optind;
372 if (address == NULL) { 332 if (address == NULL) {
373 if (is_host (argv[c])) { 333 if (is_host(argv[c])) {
374 address = argv[c++]; 334 address = argv[c++];
375 } 335 } else {
376 else { 336 usage2(_("Invalid hostname/address"), argv[c]);
377 usage2 (_("Invalid hostname/address"), argv[c]);
378 } 337 }
379 } 338 }
380 339
381 if (community == NULL) { 340 if (community == NULL) {
382 if (argv[c] != NULL ) 341 if (argv[c] != NULL)
383 community = argv[c]; 342 community = argv[c];
384 else 343 else
385 community = strdup (DEFAULT_COMMUNITY); 344 community = strdup(DEFAULT_COMMUNITY);
386 } 345 }
387 346
388 if (port == 0) { 347 if (port == 0) {
389 port = atoi(DEFAULT_PORT); 348 port = atoi(DEFAULT_PORT);
390 } 349 }
391 350
392 return validate_arguments (); 351 return validate_arguments();
393}
394
395
396int
397validate_arguments (void)
398{
399 return OK;
400} 352}
401 353
354int validate_arguments(void) { return OK; }
402 355
403void 356void print_help(void) {
404print_help (void) 357 print_revision(progname, NP_VERSION);
405{
406 print_revision (progname, NP_VERSION);
407 358
408 printf ("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n"); 359 printf("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n");
409 printf (COPYRIGHT, copyright, email); 360 printf(COPYRIGHT, copyright, email);
410 361
411 printf ("%s\n", _("This plugin tests the STATUS of an HP printer with a JetDirect card.")); 362 printf("%s\n", _("This plugin tests the STATUS of an HP printer with a JetDirect card."));
412 printf ("%s\n", _("Net-snmp must be installed on the computer running the plugin.")); 363 printf("%s\n", _("Net-snmp must be installed on the computer running the plugin."));
413 364
414 printf ("\n\n"); 365 printf("\n\n");
415 366
416 print_usage (); 367 print_usage();
417 368
418 printf (UT_HELP_VRSN); 369 printf(UT_HELP_VRSN);
419 printf (UT_EXTRA_OPTS); 370 printf(UT_EXTRA_OPTS);
420 371
421 printf (" %s\n", "-C, --community=STRING"); 372 printf(" %s\n", "-C, --community=STRING");
422 printf (" %s", _("The SNMP community name ")); 373 printf(" %s", _("The SNMP community name "));
423 printf (_("(default=%s)"), DEFAULT_COMMUNITY); 374 printf(_("(default=%s)"), DEFAULT_COMMUNITY);
424 printf ("\n"); 375 printf("\n");
425 printf (" %s\n", "-p, --port=STRING"); 376 printf(" %s\n", "-p, --port=STRING");
426 printf (" %s", _("Specify the port to check ")); 377 printf(" %s", _("Specify the port to check "));
427 printf (_("(default=%s)"), DEFAULT_PORT); 378 printf(_("(default=%s)"), DEFAULT_PORT);
428 printf ("\n"); 379 printf("\n");
429 printf (" %s\n", "-D"); 380 printf(" %s\n", "-D");
430 printf (" %s", _("Disable paper check ")); 381 printf(" %s", _("Disable paper check "));
431 382
432 printf (UT_SUPPORT); 383 printf(UT_SUPPORT);
433} 384}
434 385
435 386void print_usage(void) {
436 387 printf("%s\n", _("Usage:"));
437void 388 printf("%s -H host [-C community] [-p port] [-D]\n", progname);
438print_usage (void)
439{
440 printf ("%s\n", _("Usage:"));
441 printf ("%s -H host [-C community] [-p port] [-D]\n", progname);
442} 389}
diff --git a/plugins/check_http.c b/plugins/check_http.c
index 425ce86b..97c0e39a 100644
--- a/plugins/check_http.c
+++ b/plugins/check_http.c
@@ -3,7 +3,7 @@
3* Monitoring check_http plugin 3* Monitoring check_http plugin
4* 4*
5* License: GPL 5* License: GPL
6* Copyright (c) 1999-2013 Monitoring Plugins Development Team 6* Copyright (c) 1999-2024 Monitoring Plugins Development Team
7* 7*
8* Description: 8* Description:
9* 9*
@@ -32,7 +32,7 @@
32*****************************************************************************/ 32*****************************************************************************/
33 33
34const char *progname = "check_http"; 34const char *progname = "check_http";
35const char *copyright = "1999-2022"; 35const char *copyright = "1999-2024";
36const char *email = "devel@monitoring-plugins.org"; 36const char *email = "devel@monitoring-plugins.org";
37 37
38// Do NOT sort those headers, it will break the build 38// Do NOT sort those headers, it will break the build
@@ -85,6 +85,7 @@ char errbuf[MAX_INPUT_BUFFER];
85int cflags = REG_NOSUB | REG_EXTENDED | REG_NEWLINE; 85int cflags = REG_NOSUB | REG_EXTENDED | REG_NEWLINE;
86int errcode; 86int errcode;
87int invert_regex = 0; 87int invert_regex = 0;
88int state_regex = STATE_CRITICAL;
88 89
89struct timeval tv; 90struct timeval tv;
90struct timeval tv_temp; 91struct timeval tv_temp;
@@ -210,7 +211,8 @@ bool process_arguments (int argc, char **argv)
210 INVERT_REGEX = CHAR_MAX + 1, 211 INVERT_REGEX = CHAR_MAX + 1,
211 SNI_OPTION, 212 SNI_OPTION,
212 MAX_REDIRS_OPTION, 213 MAX_REDIRS_OPTION,
213 CONTINUE_AFTER_CHECK_CERT 214 CONTINUE_AFTER_CHECK_CERT,
215 STATE_REGEX
214 }; 216 };
215 217
216 int option = 0; 218 int option = 0;
@@ -246,6 +248,7 @@ bool process_arguments (int argc, char **argv)
246 {"content-type", required_argument, 0, 'T'}, 248 {"content-type", required_argument, 0, 'T'},
247 {"pagesize", required_argument, 0, 'm'}, 249 {"pagesize", required_argument, 0, 'm'},
248 {"invert-regex", no_argument, NULL, INVERT_REGEX}, 250 {"invert-regex", no_argument, NULL, INVERT_REGEX},
251 {"state-regex", required_argument, 0, STATE_REGEX},
249 {"use-ipv4", no_argument, 0, '4'}, 252 {"use-ipv4", no_argument, 0, '4'},
250 {"use-ipv6", no_argument, 0, '6'}, 253 {"use-ipv6", no_argument, 0, '6'},
251 {"extended-perfdata", no_argument, 0, 'E'}, 254 {"extended-perfdata", no_argument, 0, 'E'},
@@ -511,6 +514,13 @@ bool process_arguments (int argc, char **argv)
511 case INVERT_REGEX: 514 case INVERT_REGEX:
512 invert_regex = 1; 515 invert_regex = 1;
513 break; 516 break;
517 case STATE_REGEX:
518 if (!strcmp (optarg, "critical"))
519 state_regex = STATE_CRITICAL;
520 else if (!strcmp (optarg, "warning"))
521 state_regex = STATE_WARNING;
522 else usage2 (_("Invalid state-regex option"), optarg);
523 break;
514 case '4': 524 case '4':
515 address_family = AF_INET; 525 address_family = AF_INET;
516 break; 526 break;
@@ -1317,7 +1327,7 @@ check_http (void)
1317 xasprintf (&msg, _("%spattern not found, "), msg); 1327 xasprintf (&msg, _("%spattern not found, "), msg);
1318 else 1328 else
1319 xasprintf (&msg, _("%spattern found, "), msg); 1329 xasprintf (&msg, _("%spattern found, "), msg);
1320 result = STATE_CRITICAL; 1330 result = state_regex;
1321 } 1331 }
1322 else { 1332 else {
1323 /* FIXME: Shouldn't that be UNKNOWN? */ 1333 /* FIXME: Shouldn't that be UNKNOWN? */
@@ -1774,7 +1784,7 @@ print_help (void)
1774 printf (" %s\n", "-u, --url=PATH"); 1784 printf (" %s\n", "-u, --url=PATH");
1775 printf (" %s\n", _("URL to GET or POST (default: /)")); 1785 printf (" %s\n", _("URL to GET or POST (default: /)"));
1776 printf (" %s\n", "-P, --post=STRING"); 1786 printf (" %s\n", "-P, --post=STRING");
1777 printf (" %s\n", _("URL encoded http POST data")); 1787 printf (" %s\n", _("URL decoded http POST data"));
1778 printf (" %s\n", "-j, --method=STRING (for example: HEAD, OPTIONS, TRACE, PUT, DELETE, CONNECT, CONNECT:POST)"); 1788 printf (" %s\n", "-j, --method=STRING (for example: HEAD, OPTIONS, TRACE, PUT, DELETE, CONNECT, CONNECT:POST)");
1779 printf (" %s\n", _("Set HTTP method.")); 1789 printf (" %s\n", _("Set HTTP method."));
1780 printf (" %s\n", "-N, --no-body"); 1790 printf (" %s\n", "-N, --no-body");
@@ -1793,7 +1803,10 @@ print_help (void)
1793 printf (" %s\n", "-R, --eregi=STRING"); 1803 printf (" %s\n", "-R, --eregi=STRING");
1794 printf (" %s\n", _("Search page for case-insensitive regex STRING")); 1804 printf (" %s\n", _("Search page for case-insensitive regex STRING"));
1795 printf (" %s\n", "--invert-regex"); 1805 printf (" %s\n", "--invert-regex");
1796 printf (" %s\n", _("Return CRITICAL if found, OK if not\n")); 1806 printf (" %s\n", _("Return STATE if found, OK if not (STATE is CRITICAL, per default)"));
1807 printf (" %s\n", _("can be changed with --state--regex)"));
1808 printf (" %s\n", "--regex-state=STATE");
1809 printf (" %s\n", _("Return STATE if regex is found, OK if not\n"));
1797 1810
1798 printf (" %s\n", "-a, --authorization=AUTH_PAIR"); 1811 printf (" %s\n", "-a, --authorization=AUTH_PAIR");
1799 printf (" %s\n", _("Username:password on sites with basic authentication")); 1812 printf (" %s\n", _("Username:password on sites with basic authentication"));
diff --git a/plugins/check_ide_smart.c b/plugins/check_ide_smart.c
index 3872e341..381dbd80 100644
--- a/plugins/check_ide_smart.c
+++ b/plugins/check_ide_smart.c
@@ -1,112 +1,105 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring check_ide_smart plugin 3 * Monitoring check_ide_smart plugin
4* ide-smart 1.3 - IDE S.M.A.R.T. checking tool 4 * ide-smart 1.3 - IDE S.M.A.R.T. checking tool
5* 5 *
6* License: GPL 6 * License: GPL
7* Copyright (C) 1998-1999 Ragnar Hojland Espinosa <ragnar@lightside.dhis.org> 7 * Copyright (C) 1998-1999 Ragnar Hojland Espinosa <ragnar@lightside.dhis.org>
8* 1998 Gadi Oxman <gadio@netvision.net.il> 8 * 1998 Gadi Oxman <gadio@netvision.net.il>
9* Copyright (c) 2000 Robert Dale <rdale@digital-mission.com> 9 * Copyright (c) 2000 Robert Dale <rdale@digital-mission.com>
10* Copyright (c) 2000-2007 Monitoring Plugins Development Team 10 * Copyright (c) 2000-2024 Monitoring Plugins Development Team
11* 11 *
12* Description: 12 * Description:
13* 13 *
14* This file contains the check_ide_smart plugin 14 * This file contains the check_ide_smart plugin
15* 15 *
16* This plugin checks a local hard drive with the (Linux specific) SMART 16 * This plugin checks a local hard drive with the (Linux specific) SMART
17* interface 17 * interface
18* 18 *
19* 19 *
20* This program is free software: you can redistribute it and/or modify 20 * This program is free software: you can redistribute it and/or modify
21* it under the terms of the GNU General Public License as published by 21 * it under the terms of the GNU General Public License as published by
22* the Free Software Foundation, either version 3 of the License, or 22 * the Free Software Foundation, either version 3 of the License, or
23* (at your option) any later version. 23 * (at your option) any later version.
24* 24 *
25* This program is distributed in the hope that it will be useful, 25 * This program is distributed in the hope that it will be useful,
26* but WITHOUT ANY WARRANTY; without even the implied warranty of 26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28* GNU General Public License for more details. 28 * GNU General Public License for more details.
29* 29 *
30* You should have received a copy of the GNU General Public License 30 * You should have received a copy of the GNU General Public License
31* along with this program. If not, see <http://www.gnu.org/licenses/>. 31 * along with this program. If not, see <http://www.gnu.org/licenses/>.
32* 32 *
33* 33 *
34*****************************************************************************/ 34 *****************************************************************************/
35 35
36const char *progname = "check_ide_smart"; 36const char *progname = "check_ide_smart";
37const char *copyright = "1998-2007"; 37const char *copyright = "1998-2024";
38const char *email = "devel@monitoring-plugins.org"; 38const char *email = "devel@monitoring-plugins.org";
39 39
40#include "common.h" 40#include "common.h"
41#include "utils.h" 41#include "utils.h"
42 42
43void print_help (void); 43static void print_help(void);
44void print_usage (void); 44void print_usage(void);
45 45
46#include <sys/stat.h> 46#include <sys/stat.h>
47#include <sys/ioctl.h> 47#include <sys/ioctl.h>
48#include <fcntl.h> 48#include <fcntl.h>
49#ifdef __linux__ 49#ifdef __linux__
50#include <linux/hdreg.h> 50# include <linux/hdreg.h>
51#include <linux/types.h> 51# include <linux/types.h>
52 52
53#define OPEN_MODE O_RDONLY 53# define OPEN_MODE O_RDONLY
54#endif /* __linux__ */ 54#endif /* __linux__ */
55#ifdef __NetBSD__ 55#ifdef __NetBSD__
56#include <sys/device.h> 56# include <sys/device.h>
57#include <sys/param.h> 57# include <sys/param.h>
58#include <sys/sysctl.h> 58# include <sys/sysctl.h>
59#include <sys/videoio.h> /* for __u8 and friends */ 59# include <sys/videoio.h> /* for __u8 and friends */
60#include <sys/scsiio.h> 60# include <sys/scsiio.h>
61#include <sys/ataio.h> 61# include <sys/ataio.h>
62#include <dev/ata/atareg.h> 62# include <dev/ata/atareg.h>
63#include <dev/ic/wdcreg.h> 63# include <dev/ic/wdcreg.h>
64 64
65#define SMART_ENABLE WDSM_ENABLE_OPS 65# define SMART_ENABLE WDSM_ENABLE_OPS
66#define SMART_DISABLE WDSM_DISABLE_OPS 66# define SMART_DISABLE WDSM_DISABLE_OPS
67#define SMART_IMMEDIATE_OFFLINE WDSM_EXEC_OFFL_IMM 67# define SMART_IMMEDIATE_OFFLINE WDSM_EXEC_OFFL_IMM
68#define SMART_AUTO_OFFLINE 0xdb /* undefined in NetBSD headers */ 68# define SMART_AUTO_OFFLINE 0xdb /* undefined in NetBSD headers */
69 69
70#define OPEN_MODE O_RDWR 70# define OPEN_MODE O_RDWR
71#endif /* __NetBSD__ */ 71#endif /* __NetBSD__ */
72#include <errno.h> 72#include <errno.h>
73 73
74#define NR_ATTRIBUTES 30 74#define NR_ATTRIBUTES 30
75 75
76#define PREFAILURE 2 76#define PREFAILURE 2
77#define ADVISORY 1 77#define ADVISORY 1
78#define OPERATIONAL 0 78#define OPERATIONAL 0
79#define UNKNOWN -1 79#define UNKNOWN -1
80 80
81typedef struct threshold_s 81typedef struct threshold_s {
82{
83 __u8 id; 82 __u8 id;
84 __u8 threshold; 83 __u8 threshold;
85 __u8 reserved[10]; 84 __u8 reserved[10];
86} 85} __attribute__((packed)) threshold_t;
87__attribute__ ((packed)) threshold_t;
88 86
89typedef struct thresholds_s 87typedef struct thresholds_s {
90{
91 __u16 revision; 88 __u16 revision;
92 threshold_t thresholds[NR_ATTRIBUTES]; 89 threshold_t thresholds[NR_ATTRIBUTES];
93 __u8 reserved[18]; 90 __u8 reserved[18];
94 __u8 vendor[131]; 91 __u8 vendor[131];
95 __u8 checksum; 92 __u8 checksum;
96} 93} __attribute__((packed)) thresholds_t;
97__attribute__ ((packed)) thresholds_t;
98 94
99typedef struct value_s 95typedef struct value_s {
100{
101 __u8 id; 96 __u8 id;
102 __u16 status; 97 __u16 status;
103 __u8 value; 98 __u8 value;
104 __u8 vendor[8]; 99 __u8 vendor[8];
105} 100} __attribute__((packed)) value_t;
106__attribute__ ((packed)) value_t;
107 101
108typedef struct values_s 102typedef struct values_s {
109{
110 __u16 revision; 103 __u16 revision;
111 value_t values[NR_ATTRIBUTES]; 104 value_t values[NR_ATTRIBUTES];
112 __u8 offline_status; 105 __u8 offline_status;
@@ -118,90 +111,71 @@ typedef struct values_s
118 __u8 reserved[16]; 111 __u8 reserved[16];
119 __u8 vendor[125]; 112 __u8 vendor[125];
120 __u8 checksum; 113 __u8 checksum;
121} 114} __attribute__((packed)) values_t;
122__attribute__ ((packed)) values_t;
123 115
124struct 116struct {
125{
126 __u8 value; 117 __u8 value;
127 char *text; 118 char *text;
128} 119}
129 120
130offline_status_text[] = 121static offline_status_text[] = {{0x00, "NeverStarted"}, {0x02, "Completed"}, {0x04, "Suspended"},
131 { 122 {0x05, "Aborted"}, {0x06, "Failed"}, {0, 0}};
132 {0x00, "NeverStarted"}, 123
133 {0x02, "Completed"}, 124static struct {
134 {0x04, "Suspended"},
135 {0x05, "Aborted"},
136 {0x06, "Failed"},
137 {0, 0}
138 };
139
140struct
141{
142 __u8 value; 125 __u8 value;
143 char *text; 126 char *text;
144} 127} smart_command[] = {{SMART_ENABLE, "SMART_ENABLE"},
145 128 {SMART_DISABLE, "SMART_DISABLE"},
146smart_command[] = 129 {SMART_IMMEDIATE_OFFLINE, "SMART_IMMEDIATE_OFFLINE"},
147 { 130 {SMART_AUTO_OFFLINE, "SMART_AUTO_OFFLINE"}};
148 {SMART_ENABLE, "SMART_ENABLE"}, 131
149 {SMART_DISABLE, "SMART_DISABLE"}, 132/* Index to smart_command table, keep in order */
150 {SMART_IMMEDIATE_OFFLINE, "SMART_IMMEDIATE_OFFLINE"}, 133enum SmartCommand {
151 {SMART_AUTO_OFFLINE, "SMART_AUTO_OFFLINE"} 134 SMART_CMD_ENABLE,
152 }; 135 SMART_CMD_DISABLE,
153 136 SMART_CMD_IMMEDIATE_OFFLINE,
154 137 SMART_CMD_AUTO_OFFLINE
155/* Index to smart_command table, keep in order */ 138};
156enum SmartCommand 139
157 { SMART_CMD_ENABLE, 140static char *get_offline_text(int);
158 SMART_CMD_DISABLE, 141static int smart_read_values(int, values_t *);
159 SMART_CMD_IMMEDIATE_OFFLINE, 142static int nagios(values_t *, thresholds_t *);
160 SMART_CMD_AUTO_OFFLINE 143static void print_value(value_t *, threshold_t *);
161 }; 144static void print_values(values_t *, thresholds_t *);
162 145static int smart_cmd_simple(int, enum SmartCommand, __u8, bool);
163char *get_offline_text (int); 146static int smart_read_thresholds(int, thresholds_t *);
164int smart_read_values (int, values_t *); 147static bool verbose = false;
165int nagios (values_t *, thresholds_t *); 148
166void print_value (value_t *, threshold_t *); 149int main(int argc, char *argv[]) {
167void print_values (values_t *, thresholds_t *);
168int smart_cmd_simple (int, enum SmartCommand, __u8, bool);
169int smart_read_thresholds (int, thresholds_t *);
170bool verbose = false;
171
172int
173main (int argc, char *argv[])
174{
175 char *device = NULL; 150 char *device = NULL;
176 int o, longindex; 151 int o;
152 int longindex;
177 int retval = 0; 153 int retval = 0;
178 154
179 thresholds_t thresholds; 155 thresholds_t thresholds;
180 values_t values; 156 values_t values;
181 int fd; 157 int fd;
182 158
183 static struct option longopts[] = { 159 static struct option longopts[] = {{"device", required_argument, 0, 'd'},
184 {"device", required_argument, 0, 'd'}, 160 {"immediate", no_argument, 0, 'i'},
185 {"immediate", no_argument, 0, 'i'}, 161 {"quiet-check", no_argument, 0, 'q'},
186 {"quiet-check", no_argument, 0, 'q'}, 162 {"auto-on", no_argument, 0, '1'},
187 {"auto-on", no_argument, 0, '1'}, 163 {"auto-off", no_argument, 0, '0'},
188 {"auto-off", no_argument, 0, '0'}, 164 {"nagios", no_argument, 0, 'n'}, /* DEPRECATED, but we still accept it */
189 {"nagios", no_argument, 0, 'n'}, /* DEPRECATED, but we still accept it */ 165 {"help", no_argument, 0, 'h'},
190 {"help", no_argument, 0, 'h'}, 166 {"version", no_argument, 0, 'V'},
191 {"version", no_argument, 0, 'V'}, 167 {0, 0, 0, 0}};
192 {0, 0, 0, 0}
193 };
194 168
195 /* Parse extra opts if any */ 169 /* Parse extra opts if any */
196 argv=np_extra_opts (&argc, argv, progname); 170 argv = np_extra_opts(&argc, argv, progname);
197 171
198 setlocale (LC_ALL, ""); 172 setlocale(LC_ALL, "");
199 bindtextdomain (PACKAGE, LOCALEDIR); 173 bindtextdomain(PACKAGE, LOCALEDIR);
200 textdomain (PACKAGE); 174 textdomain(PACKAGE);
201 175
202 while (true) { 176 while (true) {
203 177
204 o = getopt_long (argc, argv, "+d:iq10nhVv", longopts, &longindex); 178 o = getopt_long(argc, argv, "+d:iq10nhVv", longopts, &longindex);
205 179
206 if (o == -1 || o == EOF || o == 1) 180 if (o == -1 || o == EOF || o == 1)
207 break; 181 break;
@@ -211,30 +185,30 @@ main (int argc, char *argv[])
211 device = optarg; 185 device = optarg;
212 break; 186 break;
213 case 'q': 187 case 'q':
214 fprintf (stderr, "%s\n", _("DEPRECATION WARNING: the -q switch (quiet output) is no longer \"quiet\".")); 188 fprintf(stderr, "%s\n", _("DEPRECATION WARNING: the -q switch (quiet output) is no longer \"quiet\"."));
215 fprintf (stderr, "%s\n", _("Nagios-compatible output is now always returned.")); 189 fprintf(stderr, "%s\n", _("Nagios-compatible output is now always returned."));
216 break; 190 break;
217 case 'i': 191 case 'i':
218 case '1': 192 case '1':
219 case '0': 193 case '0':
220 printf ("%s\n", _("SMART commands are broken and have been disabled (See Notes in --help).")); 194 printf("%s\n", _("SMART commands are broken and have been disabled (See Notes in --help)."));
221 return STATE_CRITICAL; 195 return STATE_CRITICAL;
222 break; 196 break;
223 case 'n': 197 case 'n':
224 fprintf (stderr, "%s\n", _("DEPRECATION WARNING: the -n switch (Nagios-compatible output) is now the")); 198 fprintf(stderr, "%s\n", _("DEPRECATION WARNING: the -n switch (Nagios-compatible output) is now the"));
225 fprintf (stderr, "%s\n", _("default and will be removed from future releases.")); 199 fprintf(stderr, "%s\n", _("default and will be removed from future releases."));
226 break; 200 break;
227 case 'v': /* verbose */ 201 case 'v': /* verbose */
228 verbose = true; 202 verbose = true;
229 break; 203 break;
230 case 'h': 204 case 'h':
231 print_help (); 205 print_help();
232 return STATE_UNKNOWN; 206 return STATE_UNKNOWN;
233 case 'V': 207 case 'V':
234 print_revision (progname, NP_VERSION); 208 print_revision(progname, NP_VERSION);
235 return STATE_UNKNOWN; 209 return STATE_UNKNOWN;
236 default: 210 default:
237 usage5 (); 211 usage5();
238 } 212 }
239 } 213 }
240 214
@@ -243,36 +217,33 @@ main (int argc, char *argv[])
243 } 217 }
244 218
245 if (!device) { 219 if (!device) {
246 print_help (); 220 print_help();
247 return STATE_UNKNOWN; 221 return STATE_UNKNOWN;
248 } 222 }
249 223
250 fd = open (device, OPEN_MODE); 224 fd = open(device, OPEN_MODE);
251 225
252 if (fd < 0) { 226 if (fd < 0) {
253 printf (_("CRITICAL - Couldn't open device %s: %s\n"), device, strerror (errno)); 227 printf(_("CRITICAL - Couldn't open device %s: %s\n"), device, strerror(errno));
254 return STATE_CRITICAL; 228 return STATE_CRITICAL;
255 } 229 }
256 230
257 if (smart_cmd_simple (fd, SMART_CMD_ENABLE, 0, false)) { 231 if (smart_cmd_simple(fd, SMART_CMD_ENABLE, 0, false)) {
258 printf (_("CRITICAL - SMART_CMD_ENABLE\n")); 232 printf(_("CRITICAL - SMART_CMD_ENABLE\n"));
259 return STATE_CRITICAL; 233 return STATE_CRITICAL;
260 } 234 }
261 235
262 smart_read_values (fd, &values); 236 smart_read_values(fd, &values);
263 smart_read_thresholds (fd, &thresholds); 237 smart_read_thresholds(fd, &thresholds);
264 retval = nagios (&values, &thresholds); 238 retval = nagios(&values, &thresholds);
265 if (verbose) print_values (&values, &thresholds); 239 if (verbose)
240 print_values(&values, &thresholds);
266 241
267 close (fd); 242 close(fd);
268 return retval; 243 return retval;
269} 244}
270 245
271 246char *get_offline_text(int status) {
272
273char *
274get_offline_text (int status)
275{
276 int i; 247 int i;
277 for (i = 0; offline_status_text[i].text; i++) { 248 for (i = 0; offline_status_text[i].text; i++) {
278 if (offline_status_text[i].value == status) { 249 if (offline_status_text[i].value == status) {
@@ -282,11 +253,7 @@ get_offline_text (int status)
282 return "UNKNOWN"; 253 return "UNKNOWN";
283} 254}
284 255
285 256int smart_read_values(int fd, values_t *values) {
286
287int
288smart_read_values (int fd, values_t * values)
289{
290#ifdef __linux__ 257#ifdef __linux__
291 int e; 258 int e;
292 __u8 args[4 + 512]; 259 __u8 args[4 + 512];
@@ -294,12 +261,12 @@ smart_read_values (int fd, values_t * values)
294 args[1] = 0; 261 args[1] = 0;
295 args[2] = SMART_READ_VALUES; 262 args[2] = SMART_READ_VALUES;
296 args[3] = 1; 263 args[3] = 1;
297 if (ioctl (fd, HDIO_DRIVE_CMD, &args)) { 264 if (ioctl(fd, HDIO_DRIVE_CMD, &args)) {
298 e = errno; 265 e = errno;
299 printf (_("CRITICAL - SMART_READ_VALUES: %s\n"), strerror (errno)); 266 printf(_("CRITICAL - SMART_READ_VALUES: %s\n"), strerror(errno));
300 return e; 267 return e;
301 } 268 }
302 memcpy (values, args + 4, 512); 269 memcpy(values, args + 4, 512);
303#endif /* __linux__ */ 270#endif /* __linux__ */
304#ifdef __NetBSD__ 271#ifdef __NetBSD__
305 struct atareq req; 272 struct atareq req;
@@ -323,7 +290,7 @@ smart_read_values (int fd, values_t * values)
323 290
324 if (errno != 0) { 291 if (errno != 0) {
325 int e = errno; 292 int e = errno;
326 printf (_("CRITICAL - SMART_READ_VALUES: %s\n"), strerror (errno)); 293 printf(_("CRITICAL - SMART_READ_VALUES: %s\n"), strerror(errno));
327 return e; 294 return e;
328 } 295 }
329 296
@@ -332,13 +299,9 @@ smart_read_values (int fd, values_t * values)
332 return 0; 299 return 0;
333} 300}
334 301
335 302int nagios(values_t *p, thresholds_t *t) {
336 303 value_t *value = p->values;
337int 304 threshold_t *threshold = t->thresholds;
338nagios (values_t * p, thresholds_t * t)
339{
340 value_t * value = p->values;
341 threshold_t * threshold = t->thresholds;
342 int status = OPERATIONAL; 305 int status = OPERATIONAL;
343 int prefailure = 0; 306 int prefailure = 0;
344 int advisory = 0; 307 int advisory = 0;
@@ -353,13 +316,11 @@ nagios (values_t * p, thresholds_t * t)
353 if (value->status & 1) { 316 if (value->status & 1) {
354 status = PREFAILURE; 317 status = PREFAILURE;
355 ++prefailure; 318 ++prefailure;
356 } 319 } else {
357 else {
358 status = ADVISORY; 320 status = ADVISORY;
359 ++advisory; 321 ++advisory;
360 } 322 }
361 } 323 } else {
362 else {
363 ++passed; 324 ++passed;
364 } 325 }
365 ++total; 326 ++total;
@@ -369,81 +330,49 @@ nagios (values_t * p, thresholds_t * t)
369 } 330 }
370 switch (status) { 331 switch (status) {
371 case PREFAILURE: 332 case PREFAILURE:
372 printf (_("CRITICAL - %d Harddrive PreFailure%cDetected! %d/%d tests failed.\n"), 333 printf(_("CRITICAL - %d Harddrive PreFailure%cDetected! %d/%d tests failed.\n"), prefailure, prefailure > 1 ? 's' : ' ', failed,
373 prefailure, 334 total);
374 prefailure > 1 ? 's' : ' ', 335 status = STATE_CRITICAL;
375 failed,
376 total);
377 status=STATE_CRITICAL;
378 break; 336 break;
379 case ADVISORY: 337 case ADVISORY:
380 printf (_("WARNING - %d Harddrive Advisor%s Detected. %d/%d tests failed.\n"), 338 printf(_("WARNING - %d Harddrive Advisor%s Detected. %d/%d tests failed.\n"), advisory, advisory > 1 ? "ies" : "y", failed, total);
381 advisory, 339 status = STATE_WARNING;
382 advisory > 1 ? "ies" : "y",
383 failed,
384 total);
385 status=STATE_WARNING;
386 break; 340 break;
387 case OPERATIONAL: 341 case OPERATIONAL:
388 printf (_("OK - Operational (%d/%d tests passed)\n"), passed, total); 342 printf(_("OK - Operational (%d/%d tests passed)\n"), passed, total);
389 status=STATE_OK; 343 status = STATE_OK;
390 break; 344 break;
391 default: 345 default:
392 printf (_("ERROR - Status '%d' unknown. %d/%d tests passed\n"), status, 346 printf(_("ERROR - Status '%d' unknown. %d/%d tests passed\n"), status, passed, total);
393 passed, total);
394 status = STATE_UNKNOWN; 347 status = STATE_UNKNOWN;
395 break; 348 break;
396 } 349 }
397 return status; 350 return status;
398} 351}
399 352
400 353void print_value(value_t *p, threshold_t *t) {
401 354 printf("Id=%3d, Status=%2d {%s , %s}, Value=%3d, Threshold=%3d, %s\n", p->id, p->status, p->status & 1 ? "PreFailure" : "Advisory ",
402void 355 p->status & 2 ? "OnLine " : "OffLine", p->value, t->threshold, p->value >= t->threshold ? "Passed" : "Failed");
403print_value (value_t * p, threshold_t * t)
404{
405 printf ("Id=%3d, Status=%2d {%s , %s}, Value=%3d, Threshold=%3d, %s\n",
406 p->id, p->status, p->status & 1 ? "PreFailure" : "Advisory ",
407 p->status & 2 ? "OnLine " : "OffLine", p->value, t->threshold,
408 p->value >= t->threshold ? "Passed" : "Failed");
409} 356}
410 357
411 358void print_values(values_t *p, thresholds_t *t) {
412 359 value_t *value = p->values;
413void 360 threshold_t *threshold = t->thresholds;
414print_values (values_t * p, thresholds_t * t)
415{
416 value_t * value = p->values;
417 threshold_t * threshold = t->thresholds;
418 int i; 361 int i;
419 for (i = 0; i < NR_ATTRIBUTES; i++) { 362 for (i = 0; i < NR_ATTRIBUTES; i++) {
420 if (value->id && threshold->id && value->id == threshold->id) { 363 if (value->id && threshold->id && value->id == threshold->id) {
421 print_value (value++, threshold++); 364 print_value(value++, threshold++);
422 } 365 }
423 } 366 }
424 printf 367 printf(_("OffLineStatus=%d {%s}, AutoOffLine=%s, OffLineTimeout=%d minutes\n"), p->offline_status,
425 (_("OffLineStatus=%d {%s}, AutoOffLine=%s, OffLineTimeout=%d minutes\n"), 368 get_offline_text(p->offline_status & 0x7f), (p->offline_status & 0x80 ? "Yes" : "No"), p->offline_timeout / 60);
426 p->offline_status, 369 printf(_("OffLineCapability=%d {%s %s %s}\n"), p->offline_capability, p->offline_capability & 1 ? "Immediate" : "",
427 get_offline_text (p->offline_status & 0x7f), 370 p->offline_capability & 2 ? "Auto" : "", p->offline_capability & 4 ? "AbortOnCmd" : "SuspendOnCmd");
428 (p->offline_status & 0x80 ? "Yes" : "No"), 371 printf(_("SmartRevision=%d, CheckSum=%d, SmartCapability=%d {%s %s}\n"), p->revision, p->checksum, p->smart_capability,
429 p->offline_timeout / 60); 372 p->smart_capability & 1 ? "SaveOnStandBy" : "", p->smart_capability & 2 ? "AutoSave" : "");
430 printf
431 (_("OffLineCapability=%d {%s %s %s}\n"),
432 p->offline_capability,
433 p->offline_capability & 1 ? "Immediate" : "",
434 p->offline_capability & 2 ? "Auto" : "",
435 p->offline_capability & 4 ? "AbortOnCmd" : "SuspendOnCmd");
436 printf
437 (_("SmartRevision=%d, CheckSum=%d, SmartCapability=%d {%s %s}\n"),
438 p->revision,
439 p->checksum,
440 p->smart_capability,
441 p->smart_capability & 1 ? "SaveOnStandBy" : "",
442 p->smart_capability & 2 ? "AutoSave" : "");
443} 373}
444 374
445 375int smart_cmd_simple(int fd, enum SmartCommand command, __u8 val0, bool show_error) {
446int smart_cmd_simple (int fd, enum SmartCommand command, __u8 val0, bool show_error) {
447 int e = STATE_UNKNOWN; 376 int e = STATE_UNKNOWN;
448#ifdef __linux__ 377#ifdef __linux__
449 __u8 args[4]; 378 __u8 args[4];
@@ -451,14 +380,14 @@ int smart_cmd_simple (int fd, enum SmartCommand command, __u8 val0, bool show_er
451 args[1] = val0; 380 args[1] = val0;
452 args[2] = smart_command[command].value; 381 args[2] = smart_command[command].value;
453 args[3] = 0; 382 args[3] = 0;
454 if (ioctl (fd, HDIO_DRIVE_CMD, &args)) { 383 if (ioctl(fd, HDIO_DRIVE_CMD, &args)) {
455 e = STATE_CRITICAL; 384 e = STATE_CRITICAL;
456 if (show_error) 385 if (show_error)
457 printf (_("CRITICAL - %s: %s\n"), smart_command[command].text, strerror (errno)); 386 printf(_("CRITICAL - %s: %s\n"), smart_command[command].text, strerror(errno));
458 } else { 387 } else {
459 e = STATE_OK; 388 e = STATE_OK;
460 if (show_error) 389 if (show_error)
461 printf (_("OK - Command sent (%s)\n"), smart_command[command].text); 390 printf(_("OK - Command sent (%s)\n"), smart_command[command].text);
462 } 391 }
463 392
464#endif /* __linux__ */ 393#endif /* __linux__ */
@@ -483,35 +412,31 @@ int smart_cmd_simple (int fd, enum SmartCommand command, __u8 val0, bool show_er
483 if (errno != 0) { 412 if (errno != 0) {
484 e = STATE_CRITICAL; 413 e = STATE_CRITICAL;
485 if (show_error) 414 if (show_error)
486 printf (_("CRITICAL - %s: %s\n"), smart_command[command].text, strerror (errno)); 415 printf(_("CRITICAL - %s: %s\n"), smart_command[command].text, strerror(errno));
487 } else { 416 } else {
488 e = STATE_OK; 417 e = STATE_OK;
489 if (show_error) 418 if (show_error)
490 printf (_("OK - Command sent (%s)\n"), smart_command[command].text); 419 printf(_("OK - Command sent (%s)\n"), smart_command[command].text);
491 } 420 }
492 421
493#endif /* __NetBSD__ */ 422#endif /* __NetBSD__ */
494 return e; 423 return e;
495} 424}
496 425
497 426int smart_read_thresholds(int fd, thresholds_t *thresholds) {
498
499int
500smart_read_thresholds (int fd, thresholds_t * thresholds)
501{
502#ifdef __linux__ 427#ifdef __linux__
503 int e; 428 int e;
504 __u8 args[4 + 512]; 429 __u8 args[4 + 512];
505 args[0] = WIN_SMART; 430 args[0] = WIN_SMART;
506 args[1] = 0; 431 args[1] = 0;
507 args[2] = SMART_READ_THRESHOLDS; 432 args[2] = SMART_READ_THRESHOLDS;
508 args[3] = 1; 433 args[3] = 1;
509 if (ioctl (fd, HDIO_DRIVE_CMD, &args)) { 434 if (ioctl(fd, HDIO_DRIVE_CMD, &args)) {
510 e = errno; 435 e = errno;
511 printf (_("CRITICAL - SMART_READ_THRESHOLDS: %s\n"), strerror (errno)); 436 printf(_("CRITICAL - SMART_READ_THRESHOLDS: %s\n"), strerror(errno));
512 return e; 437 return e;
513 } 438 }
514 memcpy (thresholds, args + 4, 512); 439 memcpy(thresholds, args + 4, 512);
515#endif /* __linux__ */ 440#endif /* __linux__ */
516#ifdef __NetBSD__ 441#ifdef __NetBSD__
517 struct atareq req; 442 struct atareq req;
@@ -535,7 +460,7 @@ smart_read_thresholds (int fd, thresholds_t * thresholds)
535 460
536 if (errno != 0) { 461 if (errno != 0) {
537 int e = errno; 462 int e = errno;
538 printf (_("CRITICAL - SMART_READ_THRESHOLDS: %s\n"), strerror (errno)); 463 printf(_("CRITICAL - SMART_READ_THRESHOLDS: %s\n"), strerror(errno));
539 return e; 464 return e;
540 } 465 }
541 466
@@ -544,45 +469,43 @@ smart_read_thresholds (int fd, thresholds_t * thresholds)
544 return 0; 469 return 0;
545} 470}
546 471
472void print_help(void) {
473 print_revision(progname, NP_VERSION);
547 474
548void 475 printf("(C) 1999 Ragnar Hojland Espinosa <ragnar@lightside.dhis.org>\n");
549print_help (void) 476 printf("Plugin implementation - 1999 Robert Dale <rdale@digital-mission.com>\n");
550{ 477 printf(COPYRIGHT, copyright, email);
551 print_revision (progname, NP_VERSION);
552 478
553 printf ("(C) 1999 Ragnar Hojland Espinosa <ragnar@lightside.dhis.org>\n"); 479 printf(_("This plugin checks a local hard drive with the (Linux specific) SMART interface "
554 printf ("Plugin implementation - 1999 Robert Dale <rdale@digital-mission.com>\n"); 480 "[http://smartlinux.sourceforge.net/smart/index.php]."));
555 printf (COPYRIGHT, copyright, email);
556 481
557 printf (_("This plugin checks a local hard drive with the (Linux specific) SMART interface [http://smartlinux.sourceforge.net/smart/index.php].")); 482 printf("\n\n");
558 483
559 printf ("\n\n"); 484 print_usage();
560 485
561 print_usage (); 486 printf(UT_HELP_VRSN);
487 printf(UT_EXTRA_OPTS);
562 488
563 printf (UT_HELP_VRSN); 489 printf(" %s\n", "-d, --device=DEVICE");
564 printf (UT_EXTRA_OPTS); 490 printf(" %s\n", _("Select device DEVICE"));
491 printf(" %s\n", _("Note: if the device is specified without this option, any further option will"));
492 printf(" %s\n", _("be ignored."));
565 493
566 printf (" %s\n", "-d, --device=DEVICE"); 494 printf(UT_VERBOSE);
567 printf (" %s\n", _("Select device DEVICE"));
568 printf (" %s\n", _("Note: if the device is specified without this option, any further option will"));
569 printf (" %s\n", _("be ignored."));
570 495
571 printf (UT_VERBOSE); 496 printf("\n");
497 printf("%s\n", _("Notes:"));
498 printf(" %s\n", _("The SMART command modes (-i/--immediate, -0/--auto-off and -1/--auto-on) were"));
499 printf(" %s\n", _("broken in an underhand manner and have been disabled. You can use smartctl"));
500 printf(" %s\n", _("instead:"));
501 printf(" %s\n", _("-0/--auto-off: use \"smartctl --offlineauto=off\""));
502 printf(" %s\n", _("-1/--auto-on: use \"smartctl --offlineauto=on\""));
503 printf(" %s\n", _("-i/--immediate: use \"smartctl --test=offline\""));
572 504
573 printf ("\n"); 505 printf(UT_SUPPORT);
574 printf ("%s\n", _("Notes:"));
575 printf (" %s\n", _("The SMART command modes (-i/--immediate, -0/--auto-off and -1/--auto-on) were"));
576 printf (" %s\n", _("broken in an underhand manner and have been disabled. You can use smartctl"));
577 printf (" %s\n", _("instead:"));
578 printf (" %s\n", _("-0/--auto-off: use \"smartctl --offlineauto=off\""));
579 printf (" %s\n", _("-1/--auto-on: use \"smartctl --offlineauto=on\""));
580 printf (" %s\n", _("-i/--immediate: use \"smartctl --test=offline\""));
581
582 printf (UT_SUPPORT);
583} 506}
584 507
585 /* todo : add to the long nanual as example 508/* todo : add to the long nanual as example
586 * 509 *
587 * Run with: check_ide-smart --nagios [-d] <DRIVE> 510 * Run with: check_ide-smart --nagios [-d] <DRIVE>
588 * Where DRIVE is an IDE drive, ie. /dev/hda, /dev/hdb, /dev/hdc 511 * Where DRIVE is an IDE drive, ie. /dev/hda, /dev/hdb, /dev/hdc
@@ -593,10 +516,7 @@ print_help (void)
593 * - Returns -1 not too often 516 * - Returns -1 not too often
594 */ 517 */
595 518
596 519void print_usage(void) {
597void 520 printf("%s\n", _("Usage:"));
598print_usage (void) 521 printf("%s [-d <device>] [-v]", progname);
599{
600 printf ("%s\n", _("Usage:"));
601 printf ("%s [-d <device>] [-v]", progname);
602} 522}
diff --git a/plugins/check_ldap.c b/plugins/check_ldap.c
index 868ffc1e..1c728292 100644
--- a/plugins/check_ldap.c
+++ b/plugins/check_ldap.c
@@ -3,7 +3,7 @@
3* Monitoring check_ldap plugin 3* Monitoring check_ldap plugin
4* 4*
5* License: GPL 5* License: GPL
6* Copyright (c) 2000-2008 Monitoring Plugins Development Team 6* Copyright (c) 2000-2024 Monitoring Plugins Development Team
7* 7*
8* Description: 8* Description:
9* 9*
@@ -28,7 +28,7 @@
28 28
29/* progname may be check_ldaps */ 29/* progname may be check_ldaps */
30char *progname = "check_ldap"; 30char *progname = "check_ldap";
31const char *copyright = "2000-2008"; 31const char *copyright = "2000-2024";
32const char *email = "devel@monitoring-plugins.org"; 32const char *email = "devel@monitoring-plugins.org";
33 33
34#include "common.h" 34#include "common.h"
diff --git a/plugins/check_load.c b/plugins/check_load.c
index 313df8ad..1431d130 100644
--- a/plugins/check_load.c
+++ b/plugins/check_load.c
@@ -110,10 +110,6 @@ main (int argc, char **argv)
110 double la[3] = { 0.0, 0.0, 0.0 }; /* NetBSD complains about uninitialized arrays */ 110 double la[3] = { 0.0, 0.0, 0.0 }; /* NetBSD complains about uninitialized arrays */
111#ifndef HAVE_GETLOADAVG 111#ifndef HAVE_GETLOADAVG
112 char input_buffer[MAX_INPUT_BUFFER]; 112 char input_buffer[MAX_INPUT_BUFFER];
113# ifdef HAVE_PROC_LOADAVG
114 FILE *fp;
115 char *str, *next;
116# endif
117#endif 113#endif
118 114
119 setlocale (LC_ALL, ""); 115 setlocale (LC_ALL, "");
@@ -132,23 +128,6 @@ main (int argc, char **argv)
132 if (result != 3) 128 if (result != 3)
133 return STATE_UNKNOWN; 129 return STATE_UNKNOWN;
134#else 130#else
135# ifdef HAVE_PROC_LOADAVG
136 fp = fopen (PROC_LOADAVG, "r");
137 if (fp == NULL) {
138 printf (_("Error opening %s\n"), PROC_LOADAVG);
139 return STATE_UNKNOWN;
140 }
141
142 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, fp)) {
143 str = (char *)input_buffer;
144 for(i = 0; i < 3; i++) {
145 la[i] = strtod(str, &next);
146 str = next;
147 }
148 }
149
150 fclose (fp);
151# else
152 child_process = spopen (PATH_TO_UPTIME); 131 child_process = spopen (PATH_TO_UPTIME);
153 if (child_process == NULL) { 132 if (child_process == NULL) {
154 printf (_("Error opening %s\n"), PATH_TO_UPTIME); 133 printf (_("Error opening %s\n"), PATH_TO_UPTIME);
@@ -175,18 +154,13 @@ main (int argc, char **argv)
175 printf (_("Error code %d returned in %s\n"), result, PATH_TO_UPTIME); 154 printf (_("Error code %d returned in %s\n"), result, PATH_TO_UPTIME);
176 return STATE_UNKNOWN; 155 return STATE_UNKNOWN;
177 } 156 }
178# endif
179#endif 157#endif
180 158
181 if ((la[0] < 0.0) || (la[1] < 0.0) || (la[2] < 0.0)) { 159 if ((la[0] < 0.0) || (la[1] < 0.0) || (la[2] < 0.0)) {
182#ifdef HAVE_GETLOADAVG 160#ifdef HAVE_GETLOADAVG
183 printf (_("Error in getloadavg()\n")); 161 printf (_("Error in getloadavg()\n"));
184#else 162#else
185# ifdef HAVE_PROC_LOADAVG
186 printf (_("Error processing %s\n"), PROC_LOADAVG);
187# else
188 printf (_("Error processing %s\n"), PATH_TO_UPTIME); 163 printf (_("Error processing %s\n"), PATH_TO_UPTIME);
189# endif
190#endif 164#endif
191 return STATE_UNKNOWN; 165 return STATE_UNKNOWN;
192 } 166 }
diff --git a/plugins/check_mrtg.c b/plugins/check_mrtg.c
index 826b77e9..632e66fb 100644
--- a/plugins/check_mrtg.c
+++ b/plugins/check_mrtg.c
@@ -1,88 +1,79 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring check_mrtg plugin 3 * Monitoring check_mrtg plugin
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 1999-2007 Monitoring Plugins Development Team 6 * Copyright (c) 1999-2024 Monitoring Plugins Development Team
7* 7 *
8* Description: 8 * Description:
9* 9 *
10* This file contains the check_mrtg plugin 10 * This file contains the check_mrtg plugin
11* 11 *
12* This plugin will check either the average or maximum value of one of the 12 * This plugin will check either the average or maximum value of one of the
13* two variables recorded in an MRTG log file. 13 * two variables recorded in an MRTG log file.
14* 14 *
15* 15 *
16* This program is free software: you can redistribute it and/or modify 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 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 18 * the Free Software Foundation, either version 3 of the License, or
19* (at your option) any later version. 19 * (at your option) any later version.
20* 20 *
21* This program is distributed in the hope that it will be useful, 21 * This program is distributed in the hope that it will be useful,
22* but WITHOUT ANY WARRANTY; without even the implied warranty of 22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24* GNU General Public License for more details. 24 * GNU General Public License for more details.
25* 25 *
26* You should have received a copy of the GNU General Public License 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/>. 27 * along with this program. If not, see <http://www.gnu.org/licenses/>.
28* 28 *
29* 29 *
30*****************************************************************************/ 30 *****************************************************************************/
31 31
32const char *progname = "check_mrtg"; 32const char *progname = "check_mrtg";
33const char *copyright = "1999-2007"; 33const char *copyright = "1999-2024";
34const char *email = "devel@monitoring-plugins.org"; 34const char *email = "devel@monitoring-plugins.org";
35 35
36#include "common.h" 36#include "common.h"
37#include "utils.h" 37#include "utils.h"
38 38
39int process_arguments (int, char **); 39static int process_arguments(int /*argc*/, char ** /*argv*/);
40int validate_arguments (void); 40static int validate_arguments(void);
41void print_help (void); 41static void print_help(void);
42void print_usage (void); 42void print_usage(void);
43 43
44char *log_file = NULL; 44static char *log_file = NULL;
45int expire_minutes = 0; 45static int expire_minutes = 0;
46bool use_average = true; 46static bool use_average = true;
47int variable_number = -1; 47static int variable_number = -1;
48unsigned long value_warning_threshold = 0L; 48static unsigned long value_warning_threshold = 0L;
49unsigned long value_critical_threshold = 0L; 49static unsigned long value_critical_threshold = 0L;
50char *label; 50static char *label;
51char *units; 51static char *units;
52 52
53int 53int main(int argc, char **argv) {
54main (int argc, char **argv) 54 setlocale(LC_ALL, "");
55{ 55 bindtextdomain(PACKAGE, LOCALEDIR);
56 int result = STATE_OK; 56 textdomain(PACKAGE);
57 FILE *fp;
58 int line;
59 char input_buffer[MAX_INPUT_BUFFER];
60 char *temp_buffer;
61 time_t current_time;
62 time_t timestamp = 0L;
63 unsigned long average_value_rate = 0L;
64 unsigned long maximum_value_rate = 0L;
65 unsigned long rate = 0L;
66
67 setlocale (LC_ALL, "");
68 bindtextdomain (PACKAGE, LOCALEDIR);
69 textdomain (PACKAGE);
70 57
71 /* Parse extra opts if any */ 58 /* Parse extra opts if any */
72 argv=np_extra_opts (&argc, argv, progname); 59 argv = np_extra_opts(&argc, argv, progname);
73 60
74 if (process_arguments (argc, argv) == ERROR) 61 if (process_arguments(argc, argv) == ERROR)
75 usage4 (_("Could not parse arguments\n")); 62 usage4(_("Could not parse arguments\n"));
76 63
77 /* open the MRTG log file for reading */ 64 /* open the MRTG log file for reading */
78 fp = fopen (log_file, "r"); 65 FILE *mtrg_log_file = fopen(log_file, "r");
79 if (fp == NULL) { 66 if (mtrg_log_file == NULL) {
80 printf (_("Unable to open MRTG log file\n")); 67 printf(_("Unable to open MRTG log file\n"));
81 return STATE_UNKNOWN; 68 return STATE_UNKNOWN;
82 } 69 }
83 70
84 line = 0; 71 time_t timestamp = 0L;
85 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, fp)) { 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)) {
86 77
87 line++; 78 line++;
88 79
@@ -95,291 +86,260 @@ main (int argc, char **argv)
95 break; 86 break;
96 87
97 /* grab the timestamp */ 88 /* grab the timestamp */
98 temp_buffer = strtok (input_buffer, " "); 89 char *temp_buffer = strtok(input_buffer, " ");
99 timestamp = strtoul (temp_buffer, NULL, 10); 90 timestamp = strtoul(temp_buffer, NULL, 10);
100 91
101 /* grab the average value 1 rate */ 92 /* grab the average value 1 rate */
102 temp_buffer = strtok (NULL, " "); 93 temp_buffer = strtok(NULL, " ");
103 if (variable_number == 1) 94 if (variable_number == 1)
104 average_value_rate = strtoul (temp_buffer, NULL, 10); 95 average_value_rate = strtoul(temp_buffer, NULL, 10);
105 96
106 /* grab the average value 2 rate */ 97 /* grab the average value 2 rate */
107 temp_buffer = strtok (NULL, " "); 98 temp_buffer = strtok(NULL, " ");
108 if (variable_number == 2) 99 if (variable_number == 2)
109 average_value_rate = strtoul (temp_buffer, NULL, 10); 100 average_value_rate = strtoul(temp_buffer, NULL, 10);
110 101
111 /* grab the maximum value 1 rate */ 102 /* grab the maximum value 1 rate */
112 temp_buffer = strtok (NULL, " "); 103 temp_buffer = strtok(NULL, " ");
113 if (variable_number == 1) 104 if (variable_number == 1)
114 maximum_value_rate = strtoul (temp_buffer, NULL, 10); 105 maximum_value_rate = strtoul(temp_buffer, NULL, 10);
115 106
116 /* grab the maximum value 2 rate */ 107 /* grab the maximum value 2 rate */
117 temp_buffer = strtok (NULL, " "); 108 temp_buffer = strtok(NULL, " ");
118 if (variable_number == 2) 109 if (variable_number == 2)
119 maximum_value_rate = strtoul (temp_buffer, NULL, 10); 110 maximum_value_rate = strtoul(temp_buffer, NULL, 10);
120 } 111 }
121 112
122 /* close the log file */ 113 /* close the log file */
123 fclose (fp); 114 fclose(mtrg_log_file);
124 115
125 /* if we couldn't read enough data, return an unknown error */ 116 /* if we couldn't read enough data, return an unknown error */
126 if (line <= 2) { 117 if (line <= 2) {
127 printf (_("Unable to process MRTG log file\n")); 118 printf(_("Unable to process MRTG log file\n"));
128 return STATE_UNKNOWN; 119 return STATE_UNKNOWN;
129 } 120 }
130 121
131 /* make sure the MRTG data isn't too old */ 122 /* make sure the MRTG data isn't too old */
132 time (&current_time); 123 time_t current_time;
133 if (expire_minutes > 0 124 time(&current_time);
134 && (current_time - timestamp) > (expire_minutes * 60)) { 125 if (expire_minutes > 0 && (current_time - timestamp) > (expire_minutes * 60)) {
135 printf (_("MRTG data has expired (%d minutes old)\n"), 126 printf(_("MRTG data has expired (%d minutes old)\n"), (int)((current_time - timestamp) / 60));
136 (int) ((current_time - timestamp) / 60));
137 return STATE_WARNING; 127 return STATE_WARNING;
138 } 128 }
139 129
130 unsigned long rate = 0L;
140 /* else check the incoming/outgoing rates */ 131 /* else check the incoming/outgoing rates */
141 if (use_average) 132 if (use_average)
142 rate = average_value_rate; 133 rate = average_value_rate;
143 else 134 else
144 rate = maximum_value_rate; 135 rate = maximum_value_rate;
145 136
137 int result = STATE_OK;
146 if (rate > value_critical_threshold) 138 if (rate > value_critical_threshold)
147 result = STATE_CRITICAL; 139 result = STATE_CRITICAL;
148 else if (rate > value_warning_threshold) 140 else if (rate > value_warning_threshold)
149 result = STATE_WARNING; 141 result = STATE_WARNING;
150 142
151 printf("%s. %s = %lu %s|%s\n", 143 printf("%s. %s = %lu %s|%s\n", (use_average) ? _("Avg") : _("Max"), label, rate, units,
152 (use_average) ? _("Avg") : _("Max"), 144 perfdata(label, (long)rate, units, (int)value_warning_threshold, (long)value_warning_threshold, (int)value_critical_threshold,
153 label, rate, units, 145 (long)value_critical_threshold, 0, 0, 0, 0));
154 perfdata(label, (long) rate, units,
155 (int) value_warning_threshold, (long) value_warning_threshold,
156 (int) value_critical_threshold, (long) value_critical_threshold,
157 0, 0, 0, 0));
158 146
159 return result; 147 return result;
160} 148}
161 149
162
163
164/* process command-line arguments */ 150/* process command-line arguments */
165int 151int process_arguments(int argc, char **argv) {
166process_arguments (int argc, char **argv)
167{
168 int c;
169
170 int option = 0;
171 static struct option longopts[] = { 152 static struct option longopts[] = {
172 {"logfile", required_argument, 0, 'F'}, 153 {"logfile", required_argument, 0, 'F'}, {"expires", required_argument, 0, 'e'}, {"aggregation", required_argument, 0, 'a'},
173 {"expires", required_argument, 0, 'e'}, 154 {"variable", required_argument, 0, 'v'}, {"critical", required_argument, 0, 'c'}, {"warning", required_argument, 0, 'w'},
174 {"aggregation", required_argument, 0, 'a'}, 155 {"label", required_argument, 0, 'l'}, {"units", required_argument, 0, 'u'}, {"variable", required_argument, 0, 'v'},
175 {"variable", required_argument, 0, 'v'}, 156 {"version", no_argument, 0, 'V'}, {"help", no_argument, 0, 'h'}, {0, 0, 0, 0}};
176 {"critical", required_argument, 0, 'c'},
177 {"warning", required_argument, 0, 'w'},
178 {"label", required_argument, 0, 'l'},
179 {"units", required_argument, 0, 'u'},
180 {"variable", required_argument, 0, 'v'},
181 {"version", no_argument, 0, 'V'},
182 {"help", no_argument, 0, 'h'},
183 {0, 0, 0, 0}
184 };
185 157
186 if (argc < 2) 158 if (argc < 2)
187 return ERROR; 159 return ERROR;
188 160
189 for (c = 1; c < argc; c++) { 161 for (int i = 1; i < argc; i++) {
190 if (strcmp ("-to", argv[c]) == 0) 162 if (strcmp("-to", argv[i]) == 0)
191 strcpy (argv[c], "-t"); 163 strcpy(argv[i], "-t");
192 else if (strcmp ("-wt", argv[c]) == 0) 164 else if (strcmp("-wt", argv[i]) == 0)
193 strcpy (argv[c], "-w"); 165 strcpy(argv[i], "-w");
194 else if (strcmp ("-ct", argv[c]) == 0) 166 else if (strcmp("-ct", argv[i]) == 0)
195 strcpy (argv[c], "-c"); 167 strcpy(argv[i], "-c");
196 } 168 }
197 169
170 int option_char;
171 int option = 0;
198 while (1) { 172 while (1) {
199 c = getopt_long (argc, argv, "hVF:e:a:v:c:w:l:u:", longopts, 173 option_char = getopt_long(argc, argv, "hVF:e:a:v:c:w:l:u:", longopts, &option);
200 &option);
201 174
202 if (c == -1 || c == EOF) 175 if (option_char == -1 || option_char == EOF)
203 break; 176 break;
204 177
205 switch (c) { 178 switch (option_char) {
206 case 'F': /* input file */ 179 case 'F': /* input file */
207 log_file = optarg; 180 log_file = optarg;
208 break; 181 break;
209 case 'e': /* ups name */ 182 case 'e': /* ups name */
210 expire_minutes = atoi (optarg); 183 expire_minutes = atoi(optarg);
211 break; 184 break;
212 case 'a': /* port */ 185 case 'a': /* port */
213 if (!strcmp (optarg, "MAX")) 186 if (!strcmp(optarg, "MAX"))
214 use_average = false; 187 use_average = false;
215 else 188 else
216 use_average = true; 189 use_average = true;
217 break; 190 break;
218 case 'v': 191 case 'v':
219 variable_number = atoi (optarg); 192 variable_number = atoi(optarg);
220 if (variable_number < 1 || variable_number > 2) 193 if (variable_number < 1 || variable_number > 2)
221 usage4 (_("Invalid variable number")); 194 usage4(_("Invalid variable number"));
222 break; 195 break;
223 case 'w': /* critical time threshold */ 196 case 'w': /* critical time threshold */
224 value_warning_threshold = strtoul (optarg, NULL, 10); 197 value_warning_threshold = strtoul(optarg, NULL, 10);
225 break; 198 break;
226 case 'c': /* warning time threshold */ 199 case 'c': /* warning time threshold */
227 value_critical_threshold = strtoul (optarg, NULL, 10); 200 value_critical_threshold = strtoul(optarg, NULL, 10);
228 break; 201 break;
229 case 'l': /* label */ 202 case 'l': /* label */
230 label = optarg; 203 label = optarg;
231 break; 204 break;
232 case 'u': /* timeout */ 205 case 'u': /* timeout */
233 units = optarg; 206 units = optarg;
234 break; 207 break;
235 case 'V': /* version */ 208 case 'V': /* version */
236 print_revision (progname, NP_VERSION); 209 print_revision(progname, NP_VERSION);
237 exit (STATE_UNKNOWN); 210 exit(STATE_UNKNOWN);
238 case 'h': /* help */ 211 case 'h': /* help */
239 print_help (); 212 print_help();
240 exit (STATE_UNKNOWN); 213 exit(STATE_UNKNOWN);
241 case '?': /* help */ 214 case '?': /* help */
242 usage5 (); 215 usage5();
243 } 216 }
244 } 217 }
245 218
246 c = optind; 219 option_char = optind;
247 if (log_file == NULL && argc > c) { 220 if (log_file == NULL && argc > option_char) {
248 log_file = argv[c++]; 221 log_file = argv[option_char++];
249 } 222 }
250 223
251 if (expire_minutes <= 0 && argc > c) { 224 if (expire_minutes <= 0 && argc > option_char) {
252 if (is_intpos (argv[c])) 225 if (is_intpos(argv[option_char]))
253 expire_minutes = atoi (argv[c++]); 226 expire_minutes = atoi(argv[option_char++]);
254 else 227 else
255 die (STATE_UNKNOWN, 228 die(STATE_UNKNOWN, _("%s is not a valid expiration time\nUse '%s -h' for additional help\n"), argv[option_char], progname);
256 _("%s is not a valid expiration time\nUse '%s -h' for additional help\n"),
257 argv[c], progname);
258 } 229 }
259 230
260 if (argc > c && strcmp (argv[c], "MAX") == 0) { 231 if (argc > option_char && strcmp(argv[option_char], "MAX") == 0) {
261 use_average = false; 232 use_average = false;
262 c++; 233 option_char++;
263 } 234 } else if (argc > option_char && strcmp(argv[option_char], "AVG") == 0) {
264 else if (argc > c && strcmp (argv[c], "AVG") == 0) {
265 use_average = true; 235 use_average = true;
266 c++; 236 option_char++;
267 } 237 }
268 238
269 if (argc > c && variable_number == -1) { 239 if (argc > option_char && variable_number == -1) {
270 variable_number = atoi (argv[c++]); 240 variable_number = atoi(argv[option_char++]);
271 if (variable_number < 1 || variable_number > 2) { 241 if (variable_number < 1 || variable_number > 2) {
272 printf ("%s :", argv[c]); 242 printf("%s :", argv[option_char]);
273 usage (_("Invalid variable number\n")); 243 usage(_("Invalid variable number\n"));
274 } 244 }
275 } 245 }
276 246
277 if (argc > c && value_warning_threshold == 0) { 247 if (argc > option_char && value_warning_threshold == 0) {
278 value_warning_threshold = strtoul (argv[c++], NULL, 10); 248 value_warning_threshold = strtoul(argv[option_char++], NULL, 10);
279 } 249 }
280 250
281 if (argc > c && value_critical_threshold == 0) { 251 if (argc > option_char && value_critical_threshold == 0) {
282 value_critical_threshold = strtoul (argv[c++], NULL, 10); 252 value_critical_threshold = strtoul(argv[option_char++], NULL, 10);
283 } 253 }
284 254
285 if (argc > c && strlen (label) == 0) { 255 if (argc > option_char && strlen(label) == 0) {
286 label = argv[c++]; 256 label = argv[option_char++];
287 } 257 }
288 258
289 if (argc > c && strlen (units) == 0) { 259 if (argc > option_char && strlen(units) == 0) {
290 units = argv[c++]; 260 units = argv[option_char++];
291 } 261 }
292 262
293 return validate_arguments (); 263 return validate_arguments();
294} 264}
295 265
296int 266int validate_arguments(void) {
297validate_arguments (void)
298{
299 if (variable_number == -1) 267 if (variable_number == -1)
300 usage4 (_("You must supply the variable number")); 268 usage4(_("You must supply the variable number"));
301 269
302 if (label == NULL) 270 if (label == NULL)
303 label = strdup ("value"); 271 label = strdup("value");
304 272
305 if (units == NULL) 273 if (units == NULL)
306 units = strdup (""); 274 units = strdup("");
307 275
308 return OK; 276 return OK;
309} 277}
310 278
311 279void print_help(void) {
312 280 print_revision(progname, NP_VERSION);
313void 281
314print_help (void) 282 printf("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n");
315{ 283 printf(COPYRIGHT, copyright, email);
316 print_revision (progname, NP_VERSION); 284
317 285 printf("%s\n", _("This plugin will check either the average or maximum value of one of the"));
318 printf ("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n"); 286 printf("%s\n", _("two variables recorded in an MRTG log file."));
319 printf (COPYRIGHT, copyright, email); 287
320 288 printf("\n\n");
321 printf ("%s\n", _("This plugin will check either the average or maximum value of one of the")); 289
322 printf ("%s\n", _("two variables recorded in an MRTG log file.")); 290 print_usage();
323 291
324 printf ("\n\n"); 292 printf(UT_HELP_VRSN);
325 293 printf(UT_EXTRA_OPTS);
326 print_usage (); 294
327 295 printf(" %s\n", "-F, --logfile=FILE");
328 printf (UT_HELP_VRSN); 296 printf(" %s\n", _("The MRTG log file containing the data you want to monitor"));
329 printf (UT_EXTRA_OPTS); 297 printf(" %s\n", "-e, --expires=MINUTES");
330 298 printf(" %s\n", _("Minutes before MRTG data is considered to be too old"));
331 printf (" %s\n", "-F, --logfile=FILE"); 299 printf(" %s\n", "-a, --aggregation=AVG|MAX");
332 printf (" %s\n", _("The MRTG log file containing the data you want to monitor")); 300 printf(" %s\n", _("Should we check average or maximum values?"));
333 printf (" %s\n", "-e, --expires=MINUTES"); 301 printf(" %s\n", "-v, --variable=INTEGER");
334 printf (" %s\n", _("Minutes before MRTG data is considered to be too old")); 302 printf(" %s\n", _("Which variable set should we inspect? (1 or 2)"));
335 printf (" %s\n", "-a, --aggregation=AVG|MAX"); 303 printf(" %s\n", "-w, --warning=INTEGER");
336 printf (" %s\n", _("Should we check average or maximum values?")); 304 printf(" %s\n", _("Threshold value for data to result in WARNING status"));
337 printf (" %s\n", "-v, --variable=INTEGER"); 305 printf(" %s\n", "-c, --critical=INTEGER");
338 printf (" %s\n", _("Which variable set should we inspect? (1 or 2)")); 306 printf(" %s\n", _("Threshold value for data to result in CRITICAL status"));
339 printf (" %s\n", "-w, --warning=INTEGER"); 307 printf(" %s\n", "-l, --label=STRING");
340 printf (" %s\n", _("Threshold value for data to result in WARNING status")); 308 printf(" %s\n", _("Type label for data (Examples: Conns, \"Processor Load\", In, Out)"));
341 printf (" %s\n", "-c, --critical=INTEGER"); 309 printf(" %s\n", "-u, --units=STRING");
342 printf (" %s\n", _("Threshold value for data to result in CRITICAL status")); 310 printf(" %s\n", _("Option units label for data (Example: Packets/Sec, Errors/Sec,"));
343 printf (" %s\n", "-l, --label=STRING"); 311 printf(" %s\n", _("\"Bytes Per Second\", \"%% Utilization\")"));
344 printf (" %s\n", _("Type label for data (Examples: Conns, \"Processor Load\", In, Out)")); 312
345 printf (" %s\n", "-u, --units=STRING"); 313 printf("\n");
346 printf (" %s\n", _("Option units label for data (Example: Packets/Sec, Errors/Sec,")); 314 printf(" %s\n", _("If the value exceeds the <vwl> threshold, a WARNING status is returned. If"));
347 printf (" %s\n", _("\"Bytes Per Second\", \"%% Utilization\")")); 315 printf(" %s\n", _("the value exceeds the <vcl> threshold, a CRITICAL status is returned. If"));
348 316 printf(" %s\n", _("the data in the log file is older than <expire_minutes> old, a WARNING"));
349 printf ("\n"); 317 printf(" %s\n", _("status is returned and a warning message is printed."));
350 printf (" %s\n", _("If the value exceeds the <vwl> threshold, a WARNING status is returned. If")); 318
351 printf (" %s\n", _("the value exceeds the <vcl> threshold, a CRITICAL status is returned. If")); 319 printf("\n");
352 printf (" %s\n", _("the data in the log file is older than <expire_minutes> old, a WARNING")); 320 printf(" %s\n", _("This plugin is useful for monitoring MRTG data that does not correspond to"));
353 printf (" %s\n", _("status is returned and a warning message is printed.")); 321 printf(" %s\n", _("bandwidth usage. (Use the check_mrtgtraf plugin for monitoring bandwidth)."));
354 322 printf(" %s\n", _("It can be used to monitor any kind of data that MRTG is monitoring - errors,"));
355 printf ("\n"); 323 printf(" %s\n", _("packets/sec, etc. I use MRTG in conjunction with the Novell NLM that allows"));
356 printf (" %s\n", _("This plugin is useful for monitoring MRTG data that does not correspond to")); 324 printf(" %s\n", _("me to track processor utilization, user connections, drive space, etc and"));
357 printf (" %s\n", _("bandwidth usage. (Use the check_mrtgtraf plugin for monitoring bandwidth).")); 325 printf(" %s\n\n", _("this plugin works well for monitoring that kind of data as well."));
358 printf (" %s\n", _("It can be used to monitor any kind of data that MRTG is monitoring - errors,")); 326
359 printf (" %s\n", _("packets/sec, etc. I use MRTG in conjunction with the Novell NLM that allows")); 327 printf("%s\n", _("Notes:"));
360 printf (" %s\n", _("me to track processor utilization, user connections, drive space, etc and")); 328 printf(" %s\n", _("- This plugin only monitors one of the two variables stored in the MRTG log"));
361 printf (" %s\n\n", _("this plugin works well for monitoring that kind of data as well.")); 329 printf(" %s\n", _("file. If you want to monitor both values you will have to define two"));
362 330 printf(" %s\n", _("commands with different values for the <variable> argument. Of course,"));
363 printf ("%s\n", _("Notes:")); 331 printf(" %s\n", _("you can always hack the code to make this plugin work for you..."));
364 printf (" %s\n", _("- This plugin only monitors one of the two variables stored in the MRTG log")); 332 printf(" %s\n", _("- MRTG stands for the Multi Router Traffic Grapher. It can be downloaded from"));
365 printf (" %s\n", _("file. If you want to monitor both values you will have to define two")); 333 printf(" %s\n", "http://ee-staff.ethz.ch/~oetiker/webtools/mrtg/mrtg.html");
366 printf (" %s\n", _("commands with different values for the <variable> argument. Of course,")); 334
367 printf (" %s\n", _("you can always hack the code to make this plugin work for you...")); 335 printf(UT_SUPPORT);
368 printf (" %s\n", _("- MRTG stands for the Multi Router Traffic Grapher. It can be downloaded from"));
369 printf (" %s\n", "http://ee-staff.ethz.ch/~oetiker/webtools/mrtg/mrtg.html");
370
371 printf (UT_SUPPORT);
372} 336}
373 337
374
375
376/* original command line: 338/* original command line:
377 <log_file> <expire_minutes> <AVG|MAX> <variable> <vwl> <vcl> <label> [units] */ 339 <log_file> <expire_minutes> <AVG|MAX> <variable> <vwl> <vcl> <label> [units] */
378 340
379void 341void print_usage(void) {
380print_usage (void) 342 printf("%s\n", _("Usage:"));
381{ 343 printf("%s -F log_file -a <AVG | MAX> -v variable -w warning -c critical\n", progname);
382 printf ("%s\n", _("Usage:")); 344 printf("[-l label] [-u units] [-e expire_minutes] [-t timeout] [-v]\n");
383 printf ("%s -F log_file -a <AVG | MAX> -v variable -w warning -c critical\n",progname);
384 printf ("[-l label] [-u units] [-e expire_minutes] [-t timeout] [-v]\n");
385} 345}
diff --git a/plugins/check_mrtgtraf.c b/plugins/check_mrtgtraf.c
index bd25d47d..e5a2e2ad 100644
--- a/plugins/check_mrtgtraf.c
+++ b/plugins/check_mrtgtraf.c
@@ -1,94 +1,77 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring check_mrtgtraf plugin 3 * Monitoring check_mrtgtraf plugin
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 1999-2007 Monitoring Plugins Development Team 6 * Copyright (c) 1999-2024 Monitoring Plugins Development Team
7* 7 *
8* Description: 8 * Description:
9* 9 *
10* This file contains the check_mtrgtraf plugin 10 * This file contains the check_mtrgtraf plugin
11* 11 *
12* This plugin will check the incoming/outgoing transfer rates of a router 12 * This plugin will check the incoming/outgoing transfer rates of a router
13* switch, etc recorded in an MRTG log. 13 * switch, etc recorded in an MRTG log.
14* 14 *
15* 15 *
16* This program is free software: you can redistribute it and/or modify 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 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 18 * the Free Software Foundation, either version 3 of the License, or
19* (at your option) any later version. 19 * (at your option) any later version.
20* 20 *
21* This program is distributed in the hope that it will be useful, 21 * This program is distributed in the hope that it will be useful,
22* but WITHOUT ANY WARRANTY; without even the implied warranty of 22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24* GNU General Public License for more details. 24 * GNU General Public License for more details.
25* 25 *
26* You should have received a copy of the GNU General Public License 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/>. 27 * along with this program. If not, see <http://www.gnu.org/licenses/>.
28* 28 *
29* 29 *
30*****************************************************************************/ 30 *****************************************************************************/
31 31
32#include "common.h" 32#include "common.h"
33#include "utils.h" 33#include "utils.h"
34 34
35const char *progname = "check_mrtgtraf"; 35const char *progname = "check_mrtgtraf";
36const char *copyright = "1999-2007"; 36const char *copyright = "1999-2024";
37const char *email = "devel@monitoring-plugins.org"; 37const char *email = "devel@monitoring-plugins.org";
38 38
39int process_arguments (int, char **); 39static int process_arguments(int /*argc*/, char ** /*argv*/);
40int validate_arguments (void); 40static void print_help(void);
41void print_help(void);
42void print_usage(void); 41void print_usage(void);
43 42
44char *log_file = NULL; 43static char *log_file = NULL;
45int expire_minutes = -1; 44static int expire_minutes = -1;
46bool use_average = true; 45static bool use_average = true;
47unsigned long incoming_warning_threshold = 0L; 46static unsigned long incoming_warning_threshold = 0L;
48unsigned long incoming_critical_threshold = 0L; 47static unsigned long incoming_critical_threshold = 0L;
49unsigned long outgoing_warning_threshold = 0L; 48static unsigned long outgoing_warning_threshold = 0L;
50unsigned long outgoing_critical_threshold = 0L; 49static unsigned long outgoing_critical_threshold = 0L;
51 50
52 51int main(int argc, char **argv) {
53int 52 setlocale(LC_ALL, "");
54main (int argc, char **argv) 53 bindtextdomain(PACKAGE, LOCALEDIR);
55{ 54 textdomain(PACKAGE);
56 int result = STATE_OK;
57 FILE *fp;
58 int line;
59 char input_buffer[MAX_INPUT_BUFFER];
60 char *temp_buffer;
61 time_t current_time;
62 char *error_message;
63 time_t timestamp = 0L;
64 unsigned long average_incoming_rate = 0L;
65 unsigned long average_outgoing_rate = 0L;
66 unsigned long maximum_incoming_rate = 0L;
67 unsigned long maximum_outgoing_rate = 0L;
68 unsigned long incoming_rate = 0L;
69 unsigned long outgoing_rate = 0L;
70 double adjusted_incoming_rate = 0.0;
71 double adjusted_outgoing_rate = 0.0;
72 char incoming_speed_rating[8];
73 char outgoing_speed_rating[8];
74
75 setlocale (LC_ALL, "");
76 bindtextdomain (PACKAGE, LOCALEDIR);
77 textdomain (PACKAGE);
78 55
79 /* Parse extra opts if any */ 56 /* Parse extra opts if any */
80 argv=np_extra_opts (&argc, argv, progname); 57 argv = np_extra_opts(&argc, argv, progname);
81 58
82 if (process_arguments (argc, argv) == ERROR) 59 if (process_arguments(argc, argv) == ERROR)
83 usage4 (_("Could not parse arguments")); 60 usage4(_("Could not parse arguments"));
84 61
85 /* open the MRTG log file for reading */ 62 /* open the MRTG log file for reading */
86 fp = fopen (log_file, "r"); 63 FILE *mrtg_log_file_ptr = fopen(log_file, "r");
87 if (fp == NULL) 64 if (mrtg_log_file_ptr == NULL)
88 usage4 (_("Unable to open MRTG log file")); 65 usage4(_("Unable to open MRTG log file"));
89 66
90 line = 0; 67 time_t timestamp = 0L;
91 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, fp)) { 68 char input_buffer[MAX_INPUT_BUFFER];
69 unsigned long average_incoming_rate = 0L;
70 unsigned long average_outgoing_rate = 0L;
71 unsigned long maximum_incoming_rate = 0L;
72 unsigned long maximum_outgoing_rate = 0L;
73 int line = 0;
74 while (fgets(input_buffer, MAX_INPUT_BUFFER - 1, mrtg_log_file_ptr)) {
92 75
93 line++; 76 line++;
94 77
@@ -102,280 +85,254 @@ main (int argc, char **argv)
102 break; 85 break;
103 86
104 /* grab the timestamp */ 87 /* grab the timestamp */
105 temp_buffer = strtok (input_buffer, " "); 88 char *temp_buffer = strtok(input_buffer, " ");
106 timestamp = strtoul (temp_buffer, NULL, 10); 89 timestamp = strtoul(temp_buffer, NULL, 10);
107 90
108 /* grab the average incoming transfer rate */ 91 /* grab the average incoming transfer rate */
109 temp_buffer = strtok (NULL, " "); 92 temp_buffer = strtok(NULL, " ");
110 average_incoming_rate = strtoul (temp_buffer, NULL, 10); 93 average_incoming_rate = strtoul(temp_buffer, NULL, 10);
111 94
112 /* grab the average outgoing transfer rate */ 95 /* grab the average outgoing transfer rate */
113 temp_buffer = strtok (NULL, " "); 96 temp_buffer = strtok(NULL, " ");
114 average_outgoing_rate = strtoul (temp_buffer, NULL, 10); 97 average_outgoing_rate = strtoul(temp_buffer, NULL, 10);
115 98
116 /* grab the maximum incoming transfer rate */ 99 /* grab the maximum incoming transfer rate */
117 temp_buffer = strtok (NULL, " "); 100 temp_buffer = strtok(NULL, " ");
118 maximum_incoming_rate = strtoul (temp_buffer, NULL, 10); 101 maximum_incoming_rate = strtoul(temp_buffer, NULL, 10);
119 102
120 /* grab the maximum outgoing transfer rate */ 103 /* grab the maximum outgoing transfer rate */
121 temp_buffer = strtok (NULL, " "); 104 temp_buffer = strtok(NULL, " ");
122 maximum_outgoing_rate = strtoul (temp_buffer, NULL, 10); 105 maximum_outgoing_rate = strtoul(temp_buffer, NULL, 10);
123 } 106 }
124 107
125 /* close the log file */ 108 /* close the log file */
126 fclose (fp); 109 fclose(mrtg_log_file_ptr);
127 110
128 /* if we couldn't read enough data, return an unknown error */ 111 /* if we couldn't read enough data, return an unknown error */
129 if (line <= 2) 112 if (line <= 2)
130 usage4 (_("Unable to process MRTG log file")); 113 usage4(_("Unable to process MRTG log file"));
131 114
132 /* make sure the MRTG data isn't too old */ 115 /* make sure the MRTG data isn't too old */
133 time (&current_time); 116 time_t current_time;
134 if ((expire_minutes > 0) && 117 time(&current_time);
135 (current_time - timestamp) > (expire_minutes * 60)) 118 if ((expire_minutes > 0) && (current_time - timestamp) > (expire_minutes * 60))
136 die (STATE_WARNING, _("MRTG data has expired (%d minutes old)\n"), 119 die(STATE_WARNING, _("MRTG data has expired (%d minutes old)\n"), (int)((current_time - timestamp) / 60));
137 (int) ((current_time - timestamp) / 60));
138 120
121 unsigned long incoming_rate = 0L;
122 unsigned long outgoing_rate = 0L;
139 /* else check the incoming/outgoing rates */ 123 /* else check the incoming/outgoing rates */
140 if (use_average) { 124 if (use_average) {
141 incoming_rate = average_incoming_rate; 125 incoming_rate = average_incoming_rate;
142 outgoing_rate = average_outgoing_rate; 126 outgoing_rate = average_outgoing_rate;
143 } 127 } else {
144 else {
145 incoming_rate = maximum_incoming_rate; 128 incoming_rate = maximum_incoming_rate;
146 outgoing_rate = maximum_outgoing_rate; 129 outgoing_rate = maximum_outgoing_rate;
147 } 130 }
148 131
132 double adjusted_incoming_rate = 0.0;
133 char incoming_speed_rating[8];
149 /* report incoming traffic in Bytes/sec */ 134 /* report incoming traffic in Bytes/sec */
150 if (incoming_rate < 1024) { 135 if (incoming_rate < 1024) {
151 strcpy (incoming_speed_rating, "B"); 136 strcpy(incoming_speed_rating, "B");
152 adjusted_incoming_rate = (double) incoming_rate; 137 adjusted_incoming_rate = (double)incoming_rate;
153 } 138 }
154 139
155 /* report incoming traffic in KBytes/sec */ 140 /* report incoming traffic in KBytes/sec */
156 else if (incoming_rate < (1024 * 1024)) { 141 else if (incoming_rate < (1024 * 1024)) {
157 strcpy (incoming_speed_rating, "KB"); 142 strcpy(incoming_speed_rating, "KB");
158 adjusted_incoming_rate = (double) (incoming_rate / 1024.0); 143 adjusted_incoming_rate = (double)(incoming_rate / 1024.0);
159 } 144 }
160 145
161 /* report incoming traffic in MBytes/sec */ 146 /* report incoming traffic in MBytes/sec */
162 else { 147 else {
163 strcpy (incoming_speed_rating, "MB"); 148 strcpy(incoming_speed_rating, "MB");
164 adjusted_incoming_rate = (double) (incoming_rate / 1024.0 / 1024.0); 149 adjusted_incoming_rate = (double)(incoming_rate / 1024.0 / 1024.0);
165 } 150 }
166 151
152 double adjusted_outgoing_rate = 0.0;
153 char outgoing_speed_rating[8];
167 /* report outgoing traffic in Bytes/sec */ 154 /* report outgoing traffic in Bytes/sec */
168 if (outgoing_rate < 1024) { 155 if (outgoing_rate < 1024) {
169 strcpy (outgoing_speed_rating, "B"); 156 strcpy(outgoing_speed_rating, "B");
170 adjusted_outgoing_rate = (double) outgoing_rate; 157 adjusted_outgoing_rate = (double)outgoing_rate;
171 } 158 }
172 159
173 /* report outgoing traffic in KBytes/sec */ 160 /* report outgoing traffic in KBytes/sec */
174 else if (outgoing_rate < (1024 * 1024)) { 161 else if (outgoing_rate < (1024 * 1024)) {
175 strcpy (outgoing_speed_rating, "KB"); 162 strcpy(outgoing_speed_rating, "KB");
176 adjusted_outgoing_rate = (double) (outgoing_rate / 1024.0); 163 adjusted_outgoing_rate = (double)(outgoing_rate / 1024.0);
177 } 164 }
178 165
179 /* report outgoing traffic in MBytes/sec */ 166 /* report outgoing traffic in MBytes/sec */
180 else { 167 else {
181 strcpy (outgoing_speed_rating, "MB"); 168 strcpy(outgoing_speed_rating, "MB");
182 adjusted_outgoing_rate = (double) (outgoing_rate / 1024.0 / 1024.0); 169 adjusted_outgoing_rate = (double)(outgoing_rate / 1024.0 / 1024.0);
183 } 170 }
184 171
185 if (incoming_rate > incoming_critical_threshold 172 int result = STATE_OK;
186 || outgoing_rate > outgoing_critical_threshold) { 173 if (incoming_rate > incoming_critical_threshold || outgoing_rate > outgoing_critical_threshold) {
187 result = STATE_CRITICAL; 174 result = STATE_CRITICAL;
188 } 175 } else if (incoming_rate > incoming_warning_threshold || outgoing_rate > outgoing_warning_threshold) {
189 else if (incoming_rate > incoming_warning_threshold
190 || outgoing_rate > outgoing_warning_threshold) {
191 result = STATE_WARNING; 176 result = STATE_WARNING;
192 } 177 }
193 178
194 xasprintf (&error_message, _("%s. In = %0.1f %s/s, %s. Out = %0.1f %s/s|%s %s\n"), 179 char *error_message;
195 (use_average) ? _("Avg") : _("Max"), adjusted_incoming_rate, 180 xasprintf(&error_message, _("%s. In = %0.1f %s/s, %s. Out = %0.1f %s/s|%s %s\n"), (use_average) ? _("Avg") : _("Max"),
196 incoming_speed_rating, (use_average) ? _("Avg") : _("Max"), 181 adjusted_incoming_rate, incoming_speed_rating, (use_average) ? _("Avg") : _("Max"), adjusted_outgoing_rate,
197 adjusted_outgoing_rate, outgoing_speed_rating, 182 outgoing_speed_rating,
198 fperfdata("in", adjusted_incoming_rate, incoming_speed_rating, 183 fperfdata("in", adjusted_incoming_rate, incoming_speed_rating, (int)incoming_warning_threshold, incoming_warning_threshold,
199 (int)incoming_warning_threshold, incoming_warning_threshold, 184 (int)incoming_critical_threshold, incoming_critical_threshold, true, 0, false, 0),
200 (int)incoming_critical_threshold, incoming_critical_threshold, 185 fperfdata("out", adjusted_outgoing_rate, outgoing_speed_rating, (int)outgoing_warning_threshold, outgoing_warning_threshold,
201 true, 0, false, 0), 186 (int)outgoing_critical_threshold, outgoing_critical_threshold, true, 0, false, 0));
202 fperfdata("out", adjusted_outgoing_rate, outgoing_speed_rating, 187
203 (int)outgoing_warning_threshold, outgoing_warning_threshold, 188 printf(_("Traffic %s - %s\n"), state_text(result), error_message);
204 (int)outgoing_critical_threshold, outgoing_critical_threshold,
205 true, 0, false, 0));
206
207 printf (_("Traffic %s - %s\n"), state_text(result), error_message);
208 189
209 return result; 190 return result;
210} 191}
211 192
212
213
214/* process command-line arguments */ 193/* process command-line arguments */
215int 194int process_arguments(int argc, char **argv) {
216process_arguments (int argc, char **argv) 195 static struct option longopts[] = {{"filename", required_argument, 0, 'F'},
217{ 196 {"expires", required_argument, 0, 'e'},
218 int c; 197 {"aggregation", required_argument, 0, 'a'},
219 198 {"critical", required_argument, 0, 'c'},
220 int option = 0; 199 {"warning", required_argument, 0, 'w'},
221 static struct option longopts[] = { 200 {"version", no_argument, 0, 'V'},
222 {"filename", required_argument, 0, 'F'}, 201 {"help", no_argument, 0, 'h'},
223 {"expires", required_argument, 0, 'e'}, 202 {0, 0, 0, 0}};
224 {"aggregation", required_argument, 0, 'a'},
225 {"critical", required_argument, 0, 'c'},
226 {"warning", required_argument, 0, 'w'},
227 {"version", no_argument, 0, 'V'},
228 {"help", no_argument, 0, 'h'},
229 {0, 0, 0, 0}
230 };
231 203
232 if (argc < 2) 204 if (argc < 2)
233 return ERROR; 205 return ERROR;
234 206
235 for (c = 1; c < argc; c++) { 207 for (int i = 1; i < argc; i++) {
236 if (strcmp ("-to", argv[c]) == 0) 208 if (strcmp("-to", argv[i]) == 0)
237 strcpy (argv[c], "-t"); 209 strcpy(argv[i], "-t");
238 else if (strcmp ("-wt", argv[c]) == 0) 210 else if (strcmp("-wt", argv[i]) == 0)
239 strcpy (argv[c], "-w"); 211 strcpy(argv[i], "-w");
240 else if (strcmp ("-ct", argv[c]) == 0) 212 else if (strcmp("-ct", argv[i]) == 0)
241 strcpy (argv[c], "-c"); 213 strcpy(argv[i], "-c");
242 } 214 }
243 215
216 int option_char;
217 int option = 0;
244 while (1) { 218 while (1) {
245 c = getopt_long (argc, argv, "hVF:e:a:c:w:", longopts, &option); 219 option_char = getopt_long(argc, argv, "hVF:e:a:c:w:", longopts, &option);
246 220
247 if (c == -1 || c == EOF) 221 if (option_char == -1 || option_char == EOF)
248 break; 222 break;
249 223
250 switch (c) { 224 switch (option_char) {
251 case 'F': /* input file */ 225 case 'F': /* input file */
252 log_file = optarg; 226 log_file = optarg;
253 break; 227 break;
254 case 'e': /* expiration time */ 228 case 'e': /* expiration time */
255 expire_minutes = atoi (optarg); 229 expire_minutes = atoi(optarg);
256 break; 230 break;
257 case 'a': /* aggregation (AVE or MAX) */ 231 case 'a': /* aggregation (AVE or MAX) */
258 if (!strcmp (optarg, "MAX")) 232 if (!strcmp(optarg, "MAX"))
259 use_average = false; 233 use_average = false;
260 else 234 else
261 use_average = true; 235 use_average = true;
262 break; 236 break;
263 case 'c': /* warning threshold */ 237 case 'c': /* warning threshold */
264 sscanf (optarg, "%lu,%lu", &incoming_critical_threshold, 238 sscanf(optarg, "%lu,%lu", &incoming_critical_threshold, &outgoing_critical_threshold);
265 &outgoing_critical_threshold);
266 break; 239 break;
267 case 'w': /* critical threshold */ 240 case 'w': /* critical threshold */
268 sscanf (optarg, "%lu,%lu", &incoming_warning_threshold, 241 sscanf(optarg, "%lu,%lu", &incoming_warning_threshold, &outgoing_warning_threshold);
269 &outgoing_warning_threshold);
270 break; 242 break;
271 case 'V': /* version */ 243 case 'V': /* version */
272 print_revision (progname, NP_VERSION); 244 print_revision(progname, NP_VERSION);
273 exit (STATE_UNKNOWN); 245 exit(STATE_UNKNOWN);
274 case 'h': /* help */ 246 case 'h': /* help */
275 print_help (); 247 print_help();
276 exit (STATE_UNKNOWN); 248 exit(STATE_UNKNOWN);
277 case '?': /* help */ 249 case '?': /* help */
278 usage5 (); 250 usage5();
279 } 251 }
280 } 252 }
281 253
282 c = optind; 254 option_char = optind;
283 if (argc > c && log_file == NULL) { 255 if (argc > option_char && log_file == NULL) {
284 log_file = argv[c++]; 256 log_file = argv[option_char++];
285 } 257 }
286 258
287 if (argc > c && expire_minutes == -1) { 259 if (argc > option_char && expire_minutes == -1) {
288 expire_minutes = atoi (argv[c++]); 260 expire_minutes = atoi(argv[option_char++]);
289 } 261 }
290 262
291 if (argc > c && strcmp (argv[c], "MAX") == 0) { 263 if (argc > option_char && strcmp(argv[option_char], "MAX") == 0) {
292 use_average = false; 264 use_average = false;
293 c++; 265 option_char++;
294 } 266 } else if (argc > option_char && strcmp(argv[option_char], "AVG") == 0) {
295 else if (argc > c && strcmp (argv[c], "AVG") == 0) {
296 use_average = true; 267 use_average = true;
297 c++; 268 option_char++;
298 } 269 }
299 270
300 if (argc > c && incoming_warning_threshold == 0) { 271 if (argc > option_char && incoming_warning_threshold == 0) {
301 incoming_warning_threshold = strtoul (argv[c++], NULL, 10); 272 incoming_warning_threshold = strtoul(argv[option_char++], NULL, 10);
302 } 273 }
303 274
304 if (argc > c && incoming_critical_threshold == 0) { 275 if (argc > option_char && incoming_critical_threshold == 0) {
305 incoming_critical_threshold = strtoul (argv[c++], NULL, 10); 276 incoming_critical_threshold = strtoul(argv[option_char++], NULL, 10);
306 } 277 }
307 278
308 if (argc > c && outgoing_warning_threshold == 0) { 279 if (argc > option_char && outgoing_warning_threshold == 0) {
309 outgoing_warning_threshold = strtoul (argv[c++], NULL, 10); 280 outgoing_warning_threshold = strtoul(argv[option_char++], NULL, 10);
310 }
311
312 if (argc > c && outgoing_critical_threshold == 0) {
313 outgoing_critical_threshold = strtoul (argv[c++], NULL, 10);
314 } 281 }
315 282
316 return validate_arguments (); 283 if (argc > option_char && outgoing_critical_threshold == 0) {
317} 284 outgoing_critical_threshold = strtoul(argv[option_char++], NULL, 10);
318 285 }
319 286
320int
321validate_arguments (void)
322{
323 return OK; 287 return OK;
324} 288}
325 289
326 290void print_help(void) {
327void 291 print_revision(progname, NP_VERSION);
328print_help (void) 292
329{ 293 printf("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n");
330 print_revision (progname, NP_VERSION); 294 printf(COPYRIGHT, copyright, email);
331 295
332 printf ("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n"); 296 printf("%s\n", _("This plugin will check the incoming/outgoing transfer rates of a router,"));
333 printf (COPYRIGHT, copyright, email); 297 printf("%s\n", _("switch, etc recorded in an MRTG log. If the newest log entry is older"));
334 298 printf("%s\n", _("than <expire_minutes>, a WARNING status is returned. If either the"));
335 printf ("%s\n", _("This plugin will check the incoming/outgoing transfer rates of a router,")); 299 printf("%s\n", _("incoming or outgoing rates exceed the <icl> or <ocl> thresholds (in"));
336 printf ("%s\n", _("switch, etc recorded in an MRTG log. If the newest log entry is older")); 300 printf("%s\n", _("Bytes/sec), a CRITICAL status results. If either of the rates exceed"));
337 printf ("%s\n", _("than <expire_minutes>, a WARNING status is returned. If either the")); 301 printf("%s\n", _("the <iwl> or <owl> thresholds (in Bytes/sec), a WARNING status results."));
338 printf ("%s\n", _("incoming or outgoing rates exceed the <icl> or <ocl> thresholds (in")); 302
339 printf ("%s\n", _("Bytes/sec), a CRITICAL status results. If either of the rates exceed")); 303 printf("\n\n");
340 printf ("%s\n", _("the <iwl> or <owl> thresholds (in Bytes/sec), a WARNING status results.")); 304
341 305 print_usage();
342 printf ("\n\n"); 306
343 307 printf(UT_HELP_VRSN);
344 print_usage (); 308 printf(UT_EXTRA_OPTS);
345 309
346 printf (UT_HELP_VRSN); 310 printf(" %s\n", "-F, --filename=STRING");
347 printf (UT_EXTRA_OPTS); 311 printf(" %s\n", _("File to read log from"));
348 312 printf(" %s\n", "-e, --expires=INTEGER");
349 printf (" %s\n", "-F, --filename=STRING"); 313 printf(" %s\n", _("Minutes after which log expires"));
350 printf (" %s\n", _("File to read log from")); 314 printf(" %s\n", "-a, --aggregation=(AVG|MAX)");
351 printf (" %s\n", "-e, --expires=INTEGER"); 315 printf(" %s\n", _("Test average or maximum"));
352 printf (" %s\n", _("Minutes after which log expires")); 316 printf(" %s\n", "-w, --warning");
353 printf (" %s\n", "-a, --aggregation=(AVG|MAX)"); 317 printf(" %s\n", _("Warning threshold pair <incoming>,<outgoing>"));
354 printf (" %s\n", _("Test average or maximum")); 318 printf(" %s\n", "-c, --critical");
355 printf (" %s\n", "-w, --warning"); 319 printf(" %s\n", _("Critical threshold pair <incoming>,<outgoing>"));
356 printf (" %s\n", _("Warning threshold pair <incoming>,<outgoing>")); 320
357 printf (" %s\n", "-c, --critical"); 321 printf("\n");
358 printf (" %s\n", _("Critical threshold pair <incoming>,<outgoing>")); 322 printf("%s\n", _("Notes:"));
359 323 printf(" %s\n", _("- MRTG stands for Multi Router Traffic Grapher. It can be downloaded from"));
360 printf ("\n"); 324 printf(" %s\n", " http://ee-staff.ethz.ch/~oetiker/webtools/mrtg/mrtg.html");
361 printf ("%s\n", _("Notes:")); 325 printf(" %s\n", _("- While MRTG can monitor things other than traffic rates, this"));
362 printf (" %s\n", _("- MRTG stands for Multi Router Traffic Grapher. It can be downloaded from")); 326 printf(" %s\n", _(" plugin probably won't work with much else without modification."));
363 printf (" %s\n", " http://ee-staff.ethz.ch/~oetiker/webtools/mrtg/mrtg.html"); 327 printf(" %s\n", _("- The calculated i/o rates are a little off from what MRTG actually"));
364 printf (" %s\n", _("- While MRTG can monitor things other than traffic rates, this")); 328 printf(" %s\n", _(" reports. I'm not sure why this is right now, but will look into it"));
365 printf (" %s\n", _(" plugin probably won't work with much else without modification.")); 329 printf(" %s\n", _(" for future enhancements of this plugin."));
366 printf (" %s\n", _("- The calculated i/o rates are a little off from what MRTG actually")); 330
367 printf (" %s\n", _(" reports. I'm not sure why this is right now, but will look into it")); 331 printf(UT_SUPPORT);
368 printf (" %s\n", _(" for future enhancements of this plugin."));
369
370 printf (UT_SUPPORT);
371} 332}
372 333
373 334void print_usage(void) {
374 335 printf(_("Usage"));
375void 336 printf(" %s -F <log_file> -a <AVG | MAX> -w <warning_pair>\n", progname);
376print_usage (void) 337 printf("-c <critical_pair> [-e expire_minutes]\n");
377{
378 printf (_("Usage"));
379 printf (" %s -F <log_file> -a <AVG | MAX> -w <warning_pair>\n",progname);
380 printf ("-c <critical_pair> [-e expire_minutes]\n");
381} 338}
diff --git a/plugins/check_mysql.c b/plugins/check_mysql.c
index 6a7daf11..1f0b7099 100644
--- a/plugins/check_mysql.c
+++ b/plugins/check_mysql.c
@@ -5,7 +5,7 @@
5* License: GPL 5* License: GPL
6* Copyright (c) 1999 Didi Rieder (adrieder@sbox.tu-graz.ac.at) 6* Copyright (c) 1999 Didi Rieder (adrieder@sbox.tu-graz.ac.at)
7* Copyright (c) 2000 Karl DeBisschop (kdebisschop@users.sourceforge.net) 7* Copyright (c) 2000 Karl DeBisschop (kdebisschop@users.sourceforge.net)
8* Copyright (c) 1999-2011 Monitoring Plugins Development Team 8* Copyright (c) 1999-2024 Monitoring Plugins Development Team
9* 9*
10* Description: 10* Description:
11* 11*
@@ -31,7 +31,7 @@
31*****************************************************************************/ 31*****************************************************************************/
32 32
33const char *progname = "check_mysql"; 33const char *progname = "check_mysql";
34const char *copyright = "1999-2011"; 34const char *copyright = "1999-2024";
35const char *email = "devel@monitoring-plugins.org"; 35const char *email = "devel@monitoring-plugins.org";
36 36
37#define SLAVERESULTSIZE 96 37#define SLAVERESULTSIZE 96
@@ -59,8 +59,8 @@ bool ssl = false;
59char *opt_file = NULL; 59char *opt_file = NULL;
60char *opt_group = NULL; 60char *opt_group = NULL;
61unsigned int db_port = MYSQL_PORT; 61unsigned int db_port = MYSQL_PORT;
62int check_slave = 0, warn_sec = 0, crit_sec = 0; 62bool check_slave = false;
63int ignore_auth = 0; 63bool ignore_auth = false;
64int verbose = 0; 64int verbose = 0;
65 65
66static double warning_time = 0; 66static double warning_time = 0;
@@ -456,10 +456,10 @@ process_arguments (int argc, char **argv)
456 db_port = atoi (optarg); 456 db_port = atoi (optarg);
457 break; 457 break;
458 case 'S': 458 case 'S':
459 check_slave = 1; /* check-slave */ 459 check_slave = true; /* check-slave */
460 break; 460 break;
461 case 'n': 461 case 'n':
462 ignore_auth = 1; /* ignore-auth */ 462 ignore_auth = true; /* ignore-auth */
463 break; 463 break;
464 case 'w': 464 case 'w':
465 warning = optarg; 465 warning = optarg;
diff --git a/plugins/check_mysql_query.c b/plugins/check_mysql_query.c
index 842b7a2f..79b6e2f4 100644
--- a/plugins/check_mysql_query.c
+++ b/plugins/check_mysql_query.c
@@ -1,36 +1,36 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring check_mysql_query plugin 3 * Monitoring check_mysql_query plugin
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 2006-2009 Monitoring Plugins Development Team 6 * Copyright (c) 2006-2024 Monitoring Plugins Development Team
7* Original code from check_mysql, copyright 1999 Didi Rieder 7 * Original code from check_mysql, copyright 1999 Didi Rieder
8* 8 *
9* Description: 9 * Description:
10* 10 *
11* This file contains the check_mysql_query plugin 11 * This file contains the check_mysql_query plugin
12* 12 *
13* This plugin is for running arbitrary SQL and checking the results 13 * This plugin is for running arbitrary SQL and checking the results
14* 14 *
15* 15 *
16* This program is free software: you can redistribute it and/or modify 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 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 18 * the Free Software Foundation, either version 3 of the License, or
19* (at your option) any later version. 19 * (at your option) any later version.
20* 20 *
21* This program is distributed in the hope that it will be useful, 21 * This program is distributed in the hope that it will be useful,
22* but WITHOUT ANY WARRANTY; without even the implied warranty of 22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24* GNU General Public License for more details. 24 * GNU General Public License for more details.
25* 25 *
26* You should have received a copy of the GNU General Public License 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/>. 27 * along with this program. If not, see <http://www.gnu.org/licenses/>.
28* 28 *
29* 29 *
30*****************************************************************************/ 30 *****************************************************************************/
31 31
32const char *progname = "check_mysql_query"; 32const char *progname = "check_mysql_query";
33const char *copyright = "1999-2007"; 33const char *copyright = "1999-2024";
34const char *email = "devel@monitoring-plugins.org"; 34const char *email = "devel@monitoring-plugins.org";
35 35
36#include "common.h" 36#include "common.h"
@@ -41,117 +41,109 @@ const char *email = "devel@monitoring-plugins.org";
41#include <mysql.h> 41#include <mysql.h>
42#include <errmsg.h> 42#include <errmsg.h>
43 43
44char *db_user = NULL; 44static char *db_user = NULL;
45char *db_host = NULL; 45static char *db_host = NULL;
46char *db_socket = NULL; 46static char *db_socket = NULL;
47char *db_pass = NULL; 47static char *db_pass = NULL;
48char *db = NULL; 48static char *db = NULL;
49char *opt_file = NULL; 49static char *opt_file = NULL;
50char *opt_group = NULL; 50static char *opt_group = NULL;
51unsigned int db_port = MYSQL_PORT; 51static unsigned int db_port = MYSQL_PORT;
52 52
53int process_arguments (int, char **); 53static int process_arguments(int /*argc*/, char ** /*argv*/);
54int validate_arguments (void); 54static int validate_arguments(void);
55void print_help (void); 55static void print_help(void);
56void print_usage (void); 56void print_usage(void);
57 57
58char *sql_query = NULL; 58static char *sql_query = NULL;
59int verbose = 0; 59static int verbose = 0;
60thresholds *my_thresholds = NULL; 60static thresholds *my_thresholds = NULL;
61 61
62 62int main(int argc, char **argv) {
63int 63 setlocale(LC_ALL, "");
64main (int argc, char **argv) 64 bindtextdomain(PACKAGE, LOCALEDIR);
65{ 65 textdomain(PACKAGE);
66
67 MYSQL mysql;
68 MYSQL_RES *res;
69 MYSQL_ROW row;
70
71 double value;
72 char *error = NULL;
73 int status;
74
75 setlocale (LC_ALL, "");
76 bindtextdomain (PACKAGE, LOCALEDIR);
77 textdomain (PACKAGE);
78 66
79 /* Parse extra opts if any */ 67 /* Parse extra opts if any */
80 argv=np_extra_opts (&argc, argv, progname); 68 argv = np_extra_opts(&argc, argv, progname);
81 69
82 if (process_arguments (argc, argv) == ERROR) 70 if (process_arguments(argc, argv) == ERROR)
83 usage4 (_("Could not parse arguments")); 71 usage4(_("Could not parse arguments"));
84 72
73 MYSQL mysql;
85 /* initialize mysql */ 74 /* initialize mysql */
86 mysql_init (&mysql); 75 mysql_init(&mysql);
87 76
88 if (opt_file != NULL) 77 if (opt_file != NULL)
89 mysql_options(&mysql,MYSQL_READ_DEFAULT_FILE,opt_file); 78 mysql_options(&mysql, MYSQL_READ_DEFAULT_FILE, opt_file);
90 79
91 if (opt_group != NULL) 80 if (opt_group != NULL)
92 mysql_options(&mysql,MYSQL_READ_DEFAULT_GROUP,opt_group); 81 mysql_options(&mysql, MYSQL_READ_DEFAULT_GROUP, opt_group);
93 else 82 else
94 mysql_options(&mysql,MYSQL_READ_DEFAULT_GROUP,"client"); 83 mysql_options(&mysql, MYSQL_READ_DEFAULT_GROUP, "client");
95 84
96 /* establish a connection to the server and error checking */ 85 /* establish a connection to the server and error checking */
97 if (!mysql_real_connect(&mysql,db_host,db_user,db_pass,db,db_port,db_socket,0)) { 86 if (!mysql_real_connect(&mysql, db_host, db_user, db_pass, db, db_port, db_socket, 0)) {
98 if (mysql_errno (&mysql) == CR_UNKNOWN_HOST) 87 if (mysql_errno(&mysql) == CR_UNKNOWN_HOST)
99 die (STATE_WARNING, "QUERY %s: %s\n", _("WARNING"), mysql_error (&mysql)); 88 die(STATE_WARNING, "QUERY %s: %s\n", _("WARNING"), mysql_error(&mysql));
100 else if (mysql_errno (&mysql) == CR_VERSION_ERROR) 89 else if (mysql_errno(&mysql) == CR_VERSION_ERROR)
101 die (STATE_WARNING, "QUERY %s: %s\n", _("WARNING"), mysql_error (&mysql)); 90 die(STATE_WARNING, "QUERY %s: %s\n", _("WARNING"), mysql_error(&mysql));
102 else if (mysql_errno (&mysql) == CR_OUT_OF_MEMORY) 91 else if (mysql_errno(&mysql) == CR_OUT_OF_MEMORY)
103 die (STATE_WARNING, "QUERY %s: %s\n", _("WARNING"), mysql_error (&mysql)); 92 die(STATE_WARNING, "QUERY %s: %s\n", _("WARNING"), mysql_error(&mysql));
104 else if (mysql_errno (&mysql) == CR_IPSOCK_ERROR) 93 else if (mysql_errno(&mysql) == CR_IPSOCK_ERROR)
105 die (STATE_WARNING, "QUERY %s: %s\n", _("WARNING"), mysql_error (&mysql)); 94 die(STATE_WARNING, "QUERY %s: %s\n", _("WARNING"), mysql_error(&mysql));
106 else if (mysql_errno (&mysql) == CR_SOCKET_CREATE_ERROR) 95 else if (mysql_errno(&mysql) == CR_SOCKET_CREATE_ERROR)
107 die (STATE_WARNING, "QUERY %s: %s\n", _("WARNING"), mysql_error (&mysql)); 96 die(STATE_WARNING, "QUERY %s: %s\n", _("WARNING"), mysql_error(&mysql));
108 else 97 else
109 die (STATE_CRITICAL, "QUERY %s: %s\n", _("CRITICAL"), mysql_error (&mysql)); 98 die(STATE_CRITICAL, "QUERY %s: %s\n", _("CRITICAL"), mysql_error(&mysql));
110 } 99 }
111 100
112 if (mysql_query (&mysql, sql_query) != 0) { 101 char *error = NULL;
102 if (mysql_query(&mysql, sql_query) != 0) {
113 error = strdup(mysql_error(&mysql)); 103 error = strdup(mysql_error(&mysql));
114 mysql_close (&mysql); 104 mysql_close(&mysql);
115 die (STATE_CRITICAL, "QUERY %s: %s - %s\n", _("CRITICAL"), _("Error with query"), error); 105 die(STATE_CRITICAL, "QUERY %s: %s - %s\n", _("CRITICAL"), _("Error with query"), error);
116 } 106 }
117 107
108 MYSQL_RES *res;
118 /* store the result */ 109 /* store the result */
119 if ( (res = mysql_store_result (&mysql)) == NULL) { 110 if ((res = mysql_store_result(&mysql)) == NULL) {
120 error = strdup(mysql_error(&mysql)); 111 error = strdup(mysql_error(&mysql));
121 mysql_close (&mysql); 112 mysql_close(&mysql);
122 die (STATE_CRITICAL, "QUERY %s: Error with store_result - %s\n", _("CRITICAL"), error); 113 die(STATE_CRITICAL, "QUERY %s: Error with store_result - %s\n", _("CRITICAL"), error);
123 } 114 }
124 115
125 /* Check there is some data */ 116 /* Check there is some data */
126 if (mysql_num_rows(res) == 0) { 117 if (mysql_num_rows(res) == 0) {
127 mysql_close(&mysql); 118 mysql_close(&mysql);
128 die (STATE_WARNING, "QUERY %s: %s\n", _("WARNING"), _("No rows returned")); 119 die(STATE_WARNING, "QUERY %s: %s\n", _("WARNING"), _("No rows returned"));
129 } 120 }
130 121
122 MYSQL_ROW row;
131 /* fetch the first row */ 123 /* fetch the first row */
132 if ( (row = mysql_fetch_row (res)) == NULL) { 124 if ((row = mysql_fetch_row(res)) == NULL) {
133 error = strdup(mysql_error(&mysql)); 125 error = strdup(mysql_error(&mysql));
134 mysql_free_result (res); 126 mysql_free_result(res);
135 mysql_close (&mysql); 127 mysql_close(&mysql);
136 die (STATE_CRITICAL, "QUERY %s: Fetch row error - %s\n", _("CRITICAL"), error); 128 die(STATE_CRITICAL, "QUERY %s: Fetch row error - %s\n", _("CRITICAL"), error);
137 } 129 }
138 130
139 if (! is_numeric(row[0])) { 131 if (!is_numeric(row[0])) {
140 die (STATE_CRITICAL, "QUERY %s: %s - '%s'\n", _("CRITICAL"), _("Is not a numeric"), row[0]); 132 die(STATE_CRITICAL, "QUERY %s: %s - '%s'\n", _("CRITICAL"), _("Is not a numeric"), row[0]);
141 } 133 }
142 134
143 value = strtod(row[0], NULL); 135 double value = strtod(row[0], NULL);
144 136
145 /* free the result */ 137 /* free the result */
146 mysql_free_result (res); 138 mysql_free_result(res);
147 139
148 /* close the connection */ 140 /* close the connection */
149 mysql_close (&mysql); 141 mysql_close(&mysql);
150 142
151 if (verbose >= 3) 143 if (verbose >= 3)
152 printf("mysql result: %f\n", value); 144 printf("mysql result: %f\n", value);
153 145
154 status = get_status(value, my_thresholds); 146 int status = get_status(value, my_thresholds);
155 147
156 if (status == STATE_OK) { 148 if (status == STATE_OK) {
157 printf("QUERY %s: ", _("OK")); 149 printf("QUERY %s: ", _("OK"));
@@ -161,73 +153,54 @@ main (int argc, char **argv)
161 printf("QUERY %s: ", _("CRITICAL")); 153 printf("QUERY %s: ", _("CRITICAL"));
162 } 154 }
163 printf(_("'%s' returned %f | %s"), sql_query, value, 155 printf(_("'%s' returned %f | %s"), sql_query, value,
164 fperfdata("result", value, "", 156 fperfdata("result", value, "", my_thresholds->warning ? true : false, my_thresholds->warning ? my_thresholds->warning->end : 0,
165 my_thresholds->warning?true:false, my_thresholds->warning?my_thresholds->warning->end:0, 157 my_thresholds->critical ? true : false, my_thresholds->critical ? my_thresholds->critical->end : 0, false, 0, false,
166 my_thresholds->critical?true:false, my_thresholds->critical?my_thresholds->critical->end:0, 158 0));
167 false, 0,
168 false, 0)
169 );
170 printf("\n"); 159 printf("\n");
171 160
172 return status; 161 return status;
173} 162}
174 163
175
176/* process command-line arguments */ 164/* process command-line arguments */
177int 165int process_arguments(int argc, char **argv) {
178process_arguments (int argc, char **argv)
179{
180 int c;
181 char *warning = NULL;
182 char *critical = NULL;
183
184 int option = 0;
185 static struct option longopts[] = { 166 static struct option longopts[] = {
186 {"hostname", required_argument, 0, 'H'}, 167 {"hostname", required_argument, 0, 'H'}, {"socket", required_argument, 0, 's'}, {"database", required_argument, 0, 'd'},
187 {"socket", required_argument, 0, 's'}, 168 {"username", required_argument, 0, 'u'}, {"password", required_argument, 0, 'p'}, {"file", required_argument, 0, 'f'},
188 {"database", required_argument, 0, 'd'}, 169 {"group", required_argument, 0, 'g'}, {"port", required_argument, 0, 'P'}, {"verbose", no_argument, 0, 'v'},
189 {"username", required_argument, 0, 'u'}, 170 {"version", no_argument, 0, 'V'}, {"help", no_argument, 0, 'h'}, {"query", required_argument, 0, 'q'},
190 {"password", required_argument, 0, 'p'}, 171 {"warning", required_argument, 0, 'w'}, {"critical", required_argument, 0, 'c'}, {0, 0, 0, 0}};
191 {"file", required_argument, 0, 'f'},
192 {"group", required_argument, 0, 'g'},
193 {"port", required_argument, 0, 'P'},
194 {"verbose", no_argument, 0, 'v'},
195 {"version", no_argument, 0, 'V'},
196 {"help", no_argument, 0, 'h'},
197 {"query", required_argument, 0, 'q'},
198 {"warning", required_argument, 0, 'w'},
199 {"critical", required_argument, 0, 'c'},
200 {0, 0, 0, 0}
201 };
202 172
203 if (argc < 1) 173 if (argc < 1)
204 return ERROR; 174 return ERROR;
205 175
206 while (1) { 176 char *warning = NULL;
207 c = getopt_long (argc, argv, "hvVP:p:u:d:H:s:q:w:c:f:g:", longopts, &option); 177 char *critical = NULL;
178
179 while (true) {
180 int option = 0;
181 int option_char = getopt_long(argc, argv, "hvVP:p:u:d:H:s:q:w:c:f:g:", longopts, &option);
208 182
209 if (c == -1 || c == EOF) 183 if (option_char == -1 || option_char == EOF)
210 break; 184 break;
211 185
212 switch (c) { 186 switch (option_char) {
213 case 'H': /* hostname */ 187 case 'H': /* hostname */
214 if (is_host (optarg)) { 188 if (is_host(optarg)) {
215 db_host = optarg; 189 db_host = optarg;
216 } 190 } else {
217 else { 191 usage2(_("Invalid hostname/address"), optarg);
218 usage2 (_("Invalid hostname/address"), optarg);
219 } 192 }
220 break; 193 break;
221 case 's': /* socket */ 194 case 's': /* socket */
222 db_socket = optarg; 195 db_socket = optarg;
223 break; 196 break;
224 case 'd': /* database */ 197 case 'd': /* database */
225 db = optarg; 198 db = optarg;
226 break; 199 break;
227 case 'u': /* username */ 200 case 'u': /* username */
228 db_user = optarg; 201 db_user = optarg;
229 break; 202 break;
230 case 'p': /* authentication information: password */ 203 case 'p': /* authentication information: password */
231 db_pass = strdup(optarg); 204 db_pass = strdup(optarg);
232 205
233 /* Delete the password from process list */ 206 /* Delete the password from process list */
@@ -236,24 +209,24 @@ process_arguments (int argc, char **argv)
236 optarg++; 209 optarg++;
237 } 210 }
238 break; 211 break;
239 case 'f': /* client options file */ 212 case 'f': /* client options file */
240 opt_file = optarg; 213 opt_file = optarg;
241 break; 214 break;
242 case 'g': /* client options group */ 215 case 'g': /* client options group */
243 opt_group = optarg; 216 opt_group = optarg;
244 break; 217 break;
245 case 'P': /* critical time threshold */ 218 case 'P': /* critical time threshold */
246 db_port = atoi (optarg); 219 db_port = atoi(optarg);
247 break; 220 break;
248 case 'v': 221 case 'v':
249 verbose++; 222 verbose++;
250 break; 223 break;
251 case 'V': /* version */ 224 case 'V': /* version */
252 print_revision (progname, NP_VERSION); 225 print_revision(progname, NP_VERSION);
253 exit (STATE_UNKNOWN); 226 exit(STATE_UNKNOWN);
254 case 'h': /* help */ 227 case 'h': /* help */
255 print_help (); 228 print_help();
256 exit (STATE_UNKNOWN); 229 exit(STATE_UNKNOWN);
257 case 'q': 230 case 'q':
258 xasprintf(&sql_query, "%s", optarg); 231 xasprintf(&sql_query, "%s", optarg);
259 break; 232 break;
@@ -263,22 +236,17 @@ process_arguments (int argc, char **argv)
263 case 'c': 236 case 'c':
264 critical = optarg; 237 critical = optarg;
265 break; 238 break;
266 case '?': /* help */ 239 case '?': /* help */
267 usage5 (); 240 usage5();
268 } 241 }
269 } 242 }
270 243
271 c = optind;
272
273 set_thresholds(&my_thresholds, warning, critical); 244 set_thresholds(&my_thresholds, warning, critical);
274 245
275 return validate_arguments (); 246 return validate_arguments();
276} 247}
277 248
278 249int validate_arguments(void) {
279int
280validate_arguments (void)
281{
282 if (sql_query == NULL) 250 if (sql_query == NULL)
283 usage("Must specify a SQL query to run"); 251 usage("Must specify a SQL query to run");
284 252
@@ -294,61 +262,55 @@ validate_arguments (void)
294 return OK; 262 return OK;
295} 263}
296 264
297 265void print_help(void) {
298void
299print_help (void)
300{
301 char *myport; 266 char *myport;
302 xasprintf (&myport, "%d", MYSQL_PORT); 267 xasprintf(&myport, "%d", MYSQL_PORT);
303 268
304 print_revision (progname, NP_VERSION); 269 print_revision(progname, NP_VERSION);
305 270
306 printf (_(COPYRIGHT), copyright, email); 271 printf(_(COPYRIGHT), copyright, email);
307 272
308 printf ("%s\n", _("This program checks a query result against threshold levels")); 273 printf("%s\n", _("This program checks a query result against threshold levels"));
309 274
310 printf ("\n\n"); 275 printf("\n\n");
311 276
312 print_usage (); 277 print_usage();
313 278
314 printf (UT_HELP_VRSN); 279 printf(UT_HELP_VRSN);
315 printf (UT_EXTRA_OPTS); 280 printf(UT_EXTRA_OPTS);
316 printf (" -q, --query=STRING\n"); 281 printf(" -q, --query=STRING\n");
317 printf (" %s\n", _("SQL query to run. Only first column in first row will be read")); 282 printf(" %s\n", _("SQL query to run. Only first column in first row will be read"));
318 printf (UT_WARN_CRIT_RANGE); 283 printf(UT_WARN_CRIT_RANGE);
319 printf (UT_HOST_PORT, 'P', myport); 284 printf(UT_HOST_PORT, 'P', myport);
320 printf (" %s\n", "-s, --socket=STRING"); 285 printf(" %s\n", "-s, --socket=STRING");
321 printf (" %s\n", _("Use the specified socket (has no effect if -H is used)")); 286 printf(" %s\n", _("Use the specified socket (has no effect if -H is used)"));
322 printf (" -d, --database=STRING\n"); 287 printf(" -d, --database=STRING\n");
323 printf (" %s\n", _("Database to check")); 288 printf(" %s\n", _("Database to check"));
324 printf (" %s\n", "-f, --file=STRING"); 289 printf(" %s\n", "-f, --file=STRING");
325 printf (" %s\n", _("Read from the specified client options file")); 290 printf(" %s\n", _("Read from the specified client options file"));
326 printf (" %s\n", "-g, --group=STRING"); 291 printf(" %s\n", "-g, --group=STRING");
327 printf (" %s\n", _("Use a client options group")); 292 printf(" %s\n", _("Use a client options group"));
328 printf (" -u, --username=STRING\n"); 293 printf(" -u, --username=STRING\n");
329 printf (" %s\n", _("Username to login with")); 294 printf(" %s\n", _("Username to login with"));
330 printf (" -p, --password=STRING\n"); 295 printf(" -p, --password=STRING\n");
331 printf (" %s\n", _("Password to login with")); 296 printf(" %s\n", _("Password to login with"));
332 printf (" ==> %s <==\n", _("IMPORTANT: THIS FORM OF AUTHENTICATION IS NOT SECURE!!!")); 297 printf(" ==> %s <==\n", _("IMPORTANT: THIS FORM OF AUTHENTICATION IS NOT SECURE!!!"));
333 printf (" %s\n", _("Your clear-text password could be visible as a process table entry")); 298 printf(" %s\n", _("Your clear-text password could be visible as a process table entry"));
334 299
335 printf ("\n"); 300 printf("\n");
336 printf (" %s\n", _("A query is required. The result from the query should be numeric.")); 301 printf(" %s\n", _("A query is required. The result from the query should be numeric."));
337 printf (" %s\n", _("For extra security, create a user with minimal access.")); 302 printf(" %s\n", _("For extra security, create a user with minimal access."));
338 303
339 printf ("\n"); 304 printf("\n");
340 printf ("%s\n", _("Notes:")); 305 printf("%s\n", _("Notes:"));
341 printf (" %s\n", _("You must specify -p with an empty string to force an empty password,")); 306 printf(" %s\n", _("You must specify -p with an empty string to force an empty password,"));
342 printf (" %s\n", _("overriding any my.cnf settings.")); 307 printf(" %s\n", _("overriding any my.cnf settings."));
343
344 printf (UT_SUPPORT);
345}
346 308
309 printf(UT_SUPPORT);
310}
347 311
348void 312void print_usage(void) {
349print_usage (void) 313 printf("%s\n", _("Usage:"));
350{ 314 printf(" %s -q SQL_query [-w warn] [-c crit] [-H host] [-P port] [-s socket]\n", progname);
351 printf ("%s\n", _("Usage:")); 315 printf(" [-d database] [-u user] [-p password] [-f optfile] [-g group]\n");
352 printf (" %s -q SQL_query [-w warn] [-c crit] [-H host] [-P port] [-s socket]\n",progname);
353 printf (" [-d database] [-u user] [-p password] [-f optfile] [-g group]\n");
354} 316}
diff --git a/plugins/check_nagios.c b/plugins/check_nagios.c
index 40d68f03..48629be3 100644
--- a/plugins/check_nagios.c
+++ b/plugins/check_nagios.c
@@ -1,58 +1,56 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring check_nagios plugin 3 * Monitoring check_nagios plugin
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 1999-2007 Monitoring Plugins Development Team 6 * Copyright (c) 1999-2024 Monitoring Plugins Development Team
7* 7 *
8* Description: 8 * Description:
9* 9 *
10* This file contains the check_nagios plugin 10 * This file contains the check_nagios plugin
11* 11 *
12* This plugin checks the status of the Nagios process on the local machine. 12 * This plugin checks the status of the Nagios process on the local machine.
13* The plugin will check to make sure the Nagios status log is no older than 13 * The plugin will check to make sure the Nagios status log is no older than
14* the number of minutes specified by the expires option. 14 * the number of minutes specified by the expires option.
15* It also checks the process table for a process matching the command 15 * It also checks the process table for a process matching the command
16* argument. 16 * argument.
17* 17 *
18* 18 *
19* This program is free software: you can redistribute it and/or modify 19 * This program is free software: you can redistribute it and/or modify
20* it under the terms of the GNU General Public License as published by 20 * it under the terms of the GNU General Public License as published by
21* the Free Software Foundation, either version 3 of the License, or 21 * the Free Software Foundation, either version 3 of the License, or
22* (at your option) any later version. 22 * (at your option) any later version.
23* 23 *
24* This program is distributed in the hope that it will be useful, 24 * This program is distributed in the hope that it will be useful,
25* but WITHOUT ANY WARRANTY; without even the implied warranty of 25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27* GNU General Public License for more details. 27 * GNU General Public License for more details.
28* 28 *
29* You should have received a copy of the GNU General Public License 29 * You should have received a copy of the GNU General Public License
30* along with this program. If not, see <http://www.gnu.org/licenses/>. 30 * along with this program. If not, see <http://www.gnu.org/licenses/>.
31* 31 *
32* 32 *
33*****************************************************************************/ 33 *****************************************************************************/
34 34
35const char *progname = "check_nagios"; 35const char *progname = "check_nagios";
36const char *copyright = "1999-2007"; 36const char *copyright = "1999-2024";
37const char *email = "devel@monitoring-plugins.org"; 37const char *email = "devel@monitoring-plugins.org";
38 38
39#include "common.h" 39#include "common.h"
40#include "runcmd.h" 40#include "runcmd.h"
41#include "utils.h" 41#include "utils.h"
42 42
43int process_arguments (int, char **); 43static int process_arguments(int /*argc*/, char ** /*argv*/);
44void print_help (void); 44static void print_help(void);
45void print_usage (void); 45void print_usage(void);
46 46
47char *status_log = NULL; 47static char *status_log = NULL;
48char *process_string = NULL; 48static char *process_string = NULL;
49int expire_minutes = 0; 49static int expire_minutes = 0;
50 50
51int verbose = 0; 51static int verbose = 0;
52 52
53int 53int main(int argc, char **argv) {
54main (int argc, char **argv)
55{
56 int result = STATE_UNKNOWN; 54 int result = STATE_UNKNOWN;
57 char input_buffer[MAX_INPUT_BUFFER]; 55 char input_buffer[MAX_INPUT_BUFFER];
58 unsigned long latest_entry_time = 0L; 56 unsigned long latest_entry_time = 0L;
@@ -73,253 +71,231 @@ main (int argc, char **argv)
73#endif /* PS_USES_PROCETIME */ 71#endif /* PS_USES_PROCETIME */
74 char procprog[MAX_INPUT_BUFFER]; 72 char procprog[MAX_INPUT_BUFFER];
75 char *procargs; 73 char *procargs;
76 int pos, cols; 74 int pos;
75 int cols;
77 int expected_cols = PS_COLS - 1; 76 int expected_cols = PS_COLS - 1;
78 const char *zombie = "Z"; 77 const char *zombie = "Z";
79 char *temp_string; 78 char *temp_string;
80 output chld_out, chld_err; 79 output chld_out;
80 output chld_err;
81 size_t i; 81 size_t i;
82 82
83 setlocale (LC_ALL, ""); 83 setlocale(LC_ALL, "");
84 bindtextdomain (PACKAGE, LOCALEDIR); 84 bindtextdomain(PACKAGE, LOCALEDIR);
85 textdomain (PACKAGE); 85 textdomain(PACKAGE);
86 86
87 /* Parse extra opts if any */ 87 /* Parse extra opts if any */
88 argv=np_extra_opts (&argc, argv, progname); 88 argv = np_extra_opts(&argc, argv, progname);
89 89
90 if (process_arguments (argc, argv) == ERROR) 90 if (process_arguments(argc, argv) == ERROR)
91 usage_va(_("Could not parse arguments")); 91 usage_va(_("Could not parse arguments"));
92 92
93 /* Set signal handling and alarm timeout */ 93 /* Set signal handling and alarm timeout */
94 if (signal (SIGALRM, timeout_alarm_handler) == SIG_ERR) { 94 if (signal(SIGALRM, timeout_alarm_handler) == SIG_ERR) {
95 usage_va(_("Cannot catch SIGALRM")); 95 usage_va(_("Cannot catch SIGALRM"));
96 } 96 }
97 97
98 /* handle timeouts gracefully... */ 98 /* handle timeouts gracefully... */
99 alarm (timeout_interval); 99 alarm(timeout_interval);
100 100
101 /* open the status log */ 101 /* open the status log */
102 fp = fopen (status_log, "r"); 102 fp = fopen(status_log, "r");
103 if (fp == NULL) { 103 if (fp == NULL) {
104 die (STATE_CRITICAL, "NAGIOS %s: %s\n", _("CRITICAL"), _("Cannot open status log for reading!")); 104 die(STATE_CRITICAL, "NAGIOS %s: %s\n", _("CRITICAL"), _("Cannot open status log for reading!"));
105 } 105 }
106 106
107 /* get the date/time of the last item updated in the log */ 107 /* get the date/time of the last item updated in the log */
108 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, fp)) { 108 while (fgets(input_buffer, MAX_INPUT_BUFFER - 1, fp)) {
109 if ((temp_ptr = strstr (input_buffer, "created=")) != NULL) { 109 if ((temp_ptr = strstr(input_buffer, "created=")) != NULL) {
110 temp_entry_time = strtoul (temp_ptr + 8, NULL, 10); 110 temp_entry_time = strtoul(temp_ptr + 8, NULL, 10);
111 latest_entry_time = temp_entry_time; 111 latest_entry_time = temp_entry_time;
112 break; 112 break;
113 } else if ((temp_ptr = strtok (input_buffer, "]")) != NULL) { 113 }
114 temp_entry_time = strtoul (temp_ptr + 1, NULL, 10); 114 if ((temp_ptr = strtok(input_buffer, "]")) != NULL) {
115 temp_entry_time = strtoul(temp_ptr + 1, NULL, 10);
115 if (temp_entry_time > latest_entry_time) 116 if (temp_entry_time > latest_entry_time)
116 latest_entry_time = temp_entry_time; 117 latest_entry_time = temp_entry_time;
117 } 118 }
118 } 119 }
119 fclose (fp); 120 fclose(fp);
120 121
121 if (verbose >= 2) 122 if (verbose >= 2)
122 printf("command: %s\n", PS_COMMAND); 123 printf("command: %s\n", PS_COMMAND);
123 124
124 /* run the command to check for the Nagios process.. */ 125 /* run the command to check for the Nagios process.. */
125 if((result = np_runcmd(PS_COMMAND, &chld_out, &chld_err, 0)) != 0) 126 if ((result = np_runcmd(PS_COMMAND, &chld_out, &chld_err, 0)) != 0)
126 result = STATE_WARNING; 127 result = STATE_WARNING;
127 128
128 /* count the number of matching Nagios processes... */ 129 /* count the number of matching Nagios processes... */
129 for(i = 0; i < chld_out.lines; i++) { 130 for (i = 0; i < chld_out.lines; i++) {
130 cols = sscanf (chld_out.line[i], PS_FORMAT, PS_VARLIST); 131 cols = sscanf(chld_out.line[i], PS_FORMAT, PS_VARLIST);
131 /* Zombie processes do not give a procprog command */ 132 /* Zombie processes do not give a procprog command */
132 if ( cols == (expected_cols - 1) && strstr(procstat, zombie) ) { 133 if (cols == (expected_cols - 1) && strstr(procstat, zombie)) {
133 cols = expected_cols; 134 cols = expected_cols;
134 /* Set some value for procargs for the strip command further below 135 /* Set some value for procargs for the strip command further below
135 * Seen to be a problem on some Solaris 7 and 8 systems */ 136 * Seen to be a problem on some Solaris 7 and 8 systems */
136 chld_out.line[i][pos] = '\n'; 137 chld_out.line[i][pos] = '\n';
137 chld_out.line[i][pos+1] = 0x0; 138 chld_out.line[i][pos + 1] = 0x0;
138 } 139 }
139 if ( cols >= expected_cols ) { 140 if (cols >= expected_cols) {
140 xasprintf (&procargs, "%s", chld_out.line[i] + pos); 141 xasprintf(&procargs, "%s", chld_out.line[i] + pos);
141 strip (procargs); 142 strip(procargs);
142 143
143 /* Some ps return full pathname for command. This removes path */ 144 /* Some ps return full pathname for command. This removes path */
144 temp_string = strtok ((char *)procprog, "/"); 145 temp_string = strtok((char *)procprog, "/");
145 while (temp_string) { 146 while (temp_string) {
146 strcpy(procprog, temp_string); 147 strcpy(procprog, temp_string);
147 temp_string = strtok (NULL, "/"); 148 temp_string = strtok(NULL, "/");
148 } 149 }
149 150
150 /* May get empty procargs */ 151 /* May get empty procargs */
151 if (!strstr(procargs, argv[0]) && strstr(procargs, process_string) && strcmp(procargs,"")) { 152 if (!strstr(procargs, argv[0]) && strstr(procargs, process_string) && strcmp(procargs, "")) {
152 proc_entries++; 153 proc_entries++;
153 if (verbose >= 2) { 154 if (verbose >= 2) {
154 printf (_("Found process: %s %s\n"), procprog, procargs); 155 printf(_("Found process: %s %s\n"), procprog, procargs);
155 } 156 }
156 } 157 }
157 } 158 }
158 } 159 }
159 160
160 /* If we get anything on stderr, at least set warning */ 161 /* If we get anything on stderr, at least set warning */
161 if(chld_err.buflen) 162 if (chld_err.buflen)
162 result = max_state (result, STATE_WARNING); 163 result = max_state(result, STATE_WARNING);
163 164
164 /* reset the alarm handler */ 165 /* reset the alarm handler */
165 alarm (0); 166 alarm(0);
166 167
167 if (proc_entries == 0) { 168 if (proc_entries == 0) {
168 die (STATE_CRITICAL, "NAGIOS %s: %s\n", _("CRITICAL"), _("Could not locate a running Nagios process!")); 169 die(STATE_CRITICAL, "NAGIOS %s: %s\n", _("CRITICAL"), _("Could not locate a running Nagios process!"));
169 } 170 }
170 171
171 if (latest_entry_time == 0L) { 172 if (latest_entry_time == 0L) {
172 die (STATE_CRITICAL, "NAGIOS %s: %s\n", _("CRITICAL"), _("Cannot parse Nagios log file for valid time")); 173 die(STATE_CRITICAL, "NAGIOS %s: %s\n", _("CRITICAL"), _("Cannot parse Nagios log file for valid time"));
173 } 174 }
174 175
175 time (&current_time); 176 time(&current_time);
176 if ((int)(current_time - latest_entry_time) > (expire_minutes * 60)) { 177 if ((int)(current_time - latest_entry_time) > (expire_minutes * 60)) {
177 result = STATE_WARNING; 178 result = STATE_WARNING;
178 } else { 179 } else {
179 result = STATE_OK; 180 result = STATE_OK;
180 } 181 }
181 182
182 printf ("NAGIOS %s: ", (result == STATE_OK) ? _("OK") : _("WARNING")); 183 printf("NAGIOS %s: ", (result == STATE_OK) ? _("OK") : _("WARNING"));
183 printf (ngettext ("%d process", "%d processes", proc_entries), proc_entries); 184 printf(ngettext("%d process", "%d processes", proc_entries), proc_entries);
184 printf (", "); 185 printf(", ");
185 printf ( 186 printf(ngettext("status log updated %d second ago", "status log updated %d seconds ago", (int)(current_time - latest_entry_time)),
186 ngettext ("status log updated %d second ago", 187 (int)(current_time - latest_entry_time));
187 "status log updated %d seconds ago", 188 printf("\n");
188 (int) (current_time - latest_entry_time) ),
189 (int) (current_time - latest_entry_time) );
190 printf ("\n");
191 189
192 return result; 190 return result;
193} 191}
194 192
195
196
197/* process command-line arguments */ 193/* process command-line arguments */
198int 194int process_arguments(int argc, char **argv) {
199process_arguments (int argc, char **argv)
200{
201 int c; 195 int c;
202 196
203 int option = 0; 197 int option = 0;
204 static struct option longopts[] = { 198 static struct option longopts[] = {{"filename", required_argument, 0, 'F'}, {"expires", required_argument, 0, 'e'},
205 {"filename", required_argument, 0, 'F'}, 199 {"command", required_argument, 0, 'C'}, {"timeout", optional_argument, 0, 't'},
206 {"expires", required_argument, 0, 'e'}, 200 {"version", no_argument, 0, 'V'}, {"help", no_argument, 0, 'h'},
207 {"command", required_argument, 0, 'C'}, 201 {"verbose", no_argument, 0, 'v'}, {0, 0, 0, 0}};
208 {"timeout", optional_argument, 0, 't'},
209 {"version", no_argument, 0, 'V'},
210 {"help", no_argument, 0, 'h'},
211 {"verbose", no_argument, 0, 'v'},
212 {0, 0, 0, 0}
213 };
214 202
215 if (argc < 2) 203 if (argc < 2)
216 return ERROR; 204 return ERROR;
217 205
218 if (!is_option (argv[1])) { 206 if (!is_option(argv[1])) {
219 status_log = argv[1]; 207 status_log = argv[1];
220 if (is_intnonneg (argv[2])) 208 if (is_intnonneg(argv[2]))
221 expire_minutes = atoi (argv[2]); 209 expire_minutes = atoi(argv[2]);
222 else 210 else
223 die (STATE_UNKNOWN, 211 die(STATE_UNKNOWN, _("Expiration time must be an integer (seconds)\n"));
224 _("Expiration time must be an integer (seconds)\n"));
225 process_string = argv[3]; 212 process_string = argv[3];
226 return OK; 213 return OK;
227 } 214 }
228 215
229 while (1) { 216 while (1) {
230 c = getopt_long (argc, argv, "+hVvF:C:e:t:", longopts, &option); 217 c = getopt_long(argc, argv, "+hVvF:C:e:t:", longopts, &option);
231 218
232 if (c == -1 || c == EOF || c == 1) 219 if (c == -1 || c == EOF || c == 1)
233 break; 220 break;
234 221
235 switch (c) { 222 switch (c) {
236 case 'h': /* help */ 223 case 'h': /* help */
237 print_help (); 224 print_help();
238 exit (STATE_UNKNOWN); 225 exit(STATE_UNKNOWN);
239 case 'V': /* version */ 226 case 'V': /* version */
240 print_revision (progname, NP_VERSION); 227 print_revision(progname, NP_VERSION);
241 exit (STATE_UNKNOWN); 228 exit(STATE_UNKNOWN);
242 case 'F': /* status log */ 229 case 'F': /* status log */
243 status_log = optarg; 230 status_log = optarg;
244 break; 231 break;
245 case 'C': /* command */ 232 case 'C': /* command */
246 process_string = optarg; 233 process_string = optarg;
247 break; 234 break;
248 case 'e': /* expiry time */ 235 case 'e': /* expiry time */
249 if (is_intnonneg (optarg)) 236 if (is_intnonneg(optarg))
250 expire_minutes = atoi (optarg); 237 expire_minutes = atoi(optarg);
251 else 238 else
252 die (STATE_UNKNOWN, 239 die(STATE_UNKNOWN, _("Expiration time must be an integer (seconds)\n"));
253 _("Expiration time must be an integer (seconds)\n"));
254 break; 240 break;
255 case 't': /* timeout */ 241 case 't': /* timeout */
256 if (is_intnonneg (optarg)) 242 if (is_intnonneg(optarg))
257 timeout_interval = atoi (optarg); 243 timeout_interval = atoi(optarg);
258 else 244 else
259 die (STATE_UNKNOWN, 245 die(STATE_UNKNOWN, _("Timeout must be an integer (seconds)\n"));
260 _("Timeout must be an integer (seconds)\n"));
261 break; 246 break;
262 case 'v': 247 case 'v':
263 verbose++; 248 verbose++;
264 break; 249 break;
265 default: /* print short usage_va statement if args not parsable */ 250 default: /* print short usage_va statement if args not parsable */
266 usage5(); 251 usage5();
267 } 252 }
268 } 253 }
269 254
270
271 if (status_log == NULL) 255 if (status_log == NULL)
272 die (STATE_UNKNOWN, _("You must provide the status_log\n")); 256 die(STATE_UNKNOWN, _("You must provide the status_log\n"));
273 257
274 if (process_string == NULL) 258 if (process_string == NULL)
275 die (STATE_UNKNOWN, _("You must provide a process string\n")); 259 die(STATE_UNKNOWN, _("You must provide a process string\n"));
276 260
277 return OK; 261 return OK;
278} 262}
279 263
264void print_help(void) {
265 print_revision(progname, NP_VERSION);
280 266
267 printf(_(COPYRIGHT), copyright, email);
281 268
282void 269 printf("%s\n", _("This plugin checks the status of the Nagios process on the local machine"));
283print_help (void) 270 printf("%s\n", _("The plugin will check to make sure the Nagios status log is no older than"));
284{ 271 printf("%s\n", _("the number of minutes specified by the expires option."));
285 print_revision (progname, NP_VERSION); 272 printf("%s\n", _("It also checks the process table for a process matching the command argument."));
286 273
287 printf (_(COPYRIGHT), copyright, email); 274 printf("\n\n");
288 275
289 printf ("%s\n", _("This plugin checks the status of the Nagios process on the local machine")); 276 print_usage();
290 printf ("%s\n", _("The plugin will check to make sure the Nagios status log is no older than"));
291 printf ("%s\n", _("the number of minutes specified by the expires option."));
292 printf ("%s\n", _("It also checks the process table for a process matching the command argument."));
293 277
294 printf ("\n\n"); 278 printf(UT_HELP_VRSN);
279 printf(UT_EXTRA_OPTS);
295 280
296 print_usage (); 281 printf(" %s\n", "-F, --filename=FILE");
282 printf(" %s\n", _("Name of the log file to check"));
283 printf(" %s\n", "-e, --expires=INTEGER");
284 printf(" %s\n", _("Minutes aging after which logfile is considered stale"));
285 printf(" %s\n", "-C, --command=STRING");
286 printf(" %s\n", _("Substring to search for in process arguments"));
287 printf(" %s\n", "-t, --timeout=INTEGER");
288 printf(" %s\n", _("Timeout for the plugin in seconds"));
289 printf(UT_VERBOSE);
297 290
298 printf (UT_HELP_VRSN); 291 printf("\n");
299 printf (UT_EXTRA_OPTS); 292 printf("%s\n", _("Examples:"));
293 printf(" %s\n", "check_nagios -t 20 -e 5 -F /usr/local/nagios/var/status.log -C /usr/local/nagios/bin/nagios");
300 294
301 printf (" %s\n", "-F, --filename=FILE"); 295 printf(UT_SUPPORT);
302 printf (" %s\n", _("Name of the log file to check"));
303 printf (" %s\n", "-e, --expires=INTEGER");
304 printf (" %s\n", _("Minutes aging after which logfile is considered stale"));
305 printf (" %s\n", "-C, --command=STRING");
306 printf (" %s\n", _("Substring to search for in process arguments"));
307 printf (" %s\n", "-t, --timeout=INTEGER");
308 printf (" %s\n", _("Timeout for the plugin in seconds"));
309 printf (UT_VERBOSE);
310
311 printf ("\n");
312 printf ("%s\n", _("Examples:"));
313 printf (" %s\n", "check_nagios -t 20 -e 5 -F /usr/local/nagios/var/status.log -C /usr/local/nagios/bin/nagios");
314
315 printf (UT_SUPPORT);
316} 296}
317 297
318 298void print_usage(void) {
319 299 printf("%s\n", _("Usage:"));
320void 300 printf("%s -F <status log file> -t <timeout_seconds> -e <expire_minutes> -C <process_string>\n", progname);
321print_usage (void)
322{
323 printf ("%s\n", _("Usage:"));
324 printf ("%s -F <status log file> -t <timeout_seconds> -e <expire_minutes> -C <process_string>\n", progname);
325} 301}
diff --git a/plugins/check_nt.c b/plugins/check_nt.c
index 19c050de..413aad6b 100644
--- a/plugins/check_nt.c
+++ b/plugins/check_nt.c
@@ -1,39 +1,39 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring check_nt plugin 3 * Monitoring check_nt plugin
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 2000-2002 Yves Rubin (rubiyz@yahoo.com) 6 * Copyright (c) 2000-2002 Yves Rubin (rubiyz@yahoo.com)
7* Copyright (c) 2003-2007 Monitoring Plugins Development Team 7 * Copyright (c) 2003-2024 Monitoring Plugins Development Team
8* 8 *
9* Description: 9 * Description:
10* 10 *
11* This file contains the check_nt plugin 11 * This file contains the check_nt plugin
12* 12 *
13* This plugin collects data from the NSClient service running on a 13 * This plugin collects data from the NSClient service running on a
14* Windows NT/2000/XP/2003 server. 14 * Windows NT/2000/XP/2003 server.
15* This plugin requires NSClient software to run on NT 15 * This plugin requires NSClient software to run on NT
16* (http://nsclient.ready2run.nl/) 16 * (http://nsclient.ready2run.nl/)
17* 17 *
18* 18 *
19* This program is free software: you can redistribute it and/or modify 19 * This program is free software: you can redistribute it and/or modify
20* it under the terms of the GNU General Public License as published by 20 * it under the terms of the GNU General Public License as published by
21* the Free Software Foundation, either version 3 of the License, or 21 * the Free Software Foundation, either version 3 of the License, or
22* (at your option) any later version. 22 * (at your option) any later version.
23* 23 *
24* This program is distributed in the hope that it will be useful, 24 * This program is distributed in the hope that it will be useful,
25* but WITHOUT ANY WARRANTY; without even the implied warranty of 25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27* GNU General Public License for more details. 27 * GNU General Public License for more details.
28* 28 *
29* You should have received a copy of the GNU General Public License 29 * You should have received a copy of the GNU General Public License
30* along with this program. If not, see <http://www.gnu.org/licenses/>. 30 * along with this program. If not, see <http://www.gnu.org/licenses/>.
31* 31 *
32* 32 *
33*****************************************************************************/ 33 *****************************************************************************/
34 34
35const char *progname = "check_nt"; 35const char *progname = "check_nt";
36const char *copyright = "2000-2007"; 36const char *copyright = "2000-2024";
37const char *email = "devel@monitoring-plugins.org"; 37const char *email = "devel@monitoring-plugins.org";
38 38
39#include "common.h" 39#include "common.h"
@@ -59,75 +59,75 @@ enum {
59 PORT = 1248 59 PORT = 1248
60}; 60};
61 61
62char *server_address=NULL; 62char *server_address = NULL;
63char *volume_name=NULL; 63char *volume_name = NULL;
64int server_port=PORT; 64int server_port = PORT;
65char *value_list=NULL; 65char *value_list = NULL;
66char *req_password=NULL; 66char *req_password = NULL;
67unsigned long lvalue_list[MAX_VALUE_LIST]; 67unsigned long lvalue_list[MAX_VALUE_LIST];
68unsigned long warning_value=0L; 68unsigned long warning_value = 0L;
69unsigned long critical_value=0L; 69unsigned long critical_value = 0L;
70bool check_warning_value=false; 70bool check_warning_value = false;
71bool check_critical_value=false; 71bool check_critical_value = false;
72enum checkvars vars_to_check = CHECK_NONE; 72enum checkvars vars_to_check = CHECK_NONE;
73bool show_all = false; 73bool show_all = false;
74 74
75char recv_buffer[MAX_INPUT_BUFFER]; 75char recv_buffer[MAX_INPUT_BUFFER];
76 76
77void fetch_data (const char* address, int port, const char* sendb); 77void fetch_data(const char *address, int port, const char *sendb);
78int process_arguments(int, char **); 78int process_arguments(int, char **);
79void preparelist(char *string); 79void preparelist(char *string);
80bool strtoularray(unsigned long *array, char *string, const char *delim); 80bool strtoularray(unsigned long *array, char *string, const char *delim);
81void print_help(void); 81void print_help(void);
82void print_usage(void); 82void print_usage(void);
83 83
84int main(int argc, char **argv){ 84int main(int argc, char **argv) {
85 85
86/* should be int result = STATE_UNKNOWN; */ 86 /* should be int result = STATE_UNKNOWN; */
87 87
88 int return_code = STATE_UNKNOWN; 88 int return_code = STATE_UNKNOWN;
89 char *send_buffer=NULL; 89 char *send_buffer = NULL;
90 char *output_message=NULL; 90 char *output_message = NULL;
91 char *perfdata=NULL; 91 char *perfdata = NULL;
92 char *temp_string=NULL; 92 char *temp_string = NULL;
93 char *temp_string_perf=NULL; 93 char *temp_string_perf = NULL;
94 char *description=NULL,*counter_unit = NULL; 94 char *description = NULL, *counter_unit = NULL;
95 char *minval = NULL, *maxval = NULL, *errcvt = NULL; 95 char *minval = NULL, *maxval = NULL, *errcvt = NULL;
96 char *fds=NULL, *tds=NULL; 96 char *fds = NULL, *tds = NULL;
97 char *numstr; 97 char *numstr;
98 98
99 double total_disk_space=0; 99 double total_disk_space = 0;
100 double free_disk_space=0; 100 double free_disk_space = 0;
101 double percent_used_space=0; 101 double percent_used_space = 0;
102 double warning_used_space=0; 102 double warning_used_space = 0;
103 double critical_used_space=0; 103 double critical_used_space = 0;
104 double mem_commitLimit=0; 104 double mem_commitLimit = 0;
105 double mem_commitByte=0; 105 double mem_commitByte = 0;
106 double fminval = 0, fmaxval = 0; 106 double fminval = 0, fmaxval = 0;
107 unsigned long utilization; 107 unsigned long utilization;
108 unsigned long uptime; 108 unsigned long uptime;
109 unsigned long age_in_minutes; 109 unsigned long age_in_minutes;
110 double counter_value = 0.0; 110 double counter_value = 0.0;
111 int offset=0; 111 int offset = 0;
112 int updays=0; 112 int updays = 0;
113 int uphours=0; 113 int uphours = 0;
114 int upminutes=0; 114 int upminutes = 0;
115 115
116 bool isPercent = false; 116 bool isPercent = false;
117 bool allRight = false; 117 bool allRight = false;
118 118
119 setlocale (LC_ALL, ""); 119 setlocale(LC_ALL, "");
120 bindtextdomain (PACKAGE, LOCALEDIR); 120 bindtextdomain(PACKAGE, LOCALEDIR);
121 textdomain (PACKAGE); 121 textdomain(PACKAGE);
122 122
123 /* Parse extra opts if any */ 123 /* Parse extra opts if any */
124 argv=np_extra_opts (&argc, argv, progname); 124 argv = np_extra_opts(&argc, argv, progname);
125 125
126 if(process_arguments(argc,argv) == ERROR) 126 if (process_arguments(argc, argv) == ERROR)
127 usage4 (_("Could not parse arguments")); 127 usage4(_("Could not parse arguments"));
128 128
129 /* initialize alarm signal handling */ 129 /* initialize alarm signal handling */
130 signal(SIGALRM,socket_timeout_alarm_handler); 130 signal(SIGALRM, socket_timeout_alarm_handler);
131 131
132 /* set socket timeout */ 132 /* set socket timeout */
133 alarm(socket_timeout); 133 alarm(socket_timeout);
@@ -137,61 +137,58 @@ int main(int argc, char **argv){
137 case CHECK_CLIENTVERSION: 137 case CHECK_CLIENTVERSION:
138 138
139 xasprintf(&send_buffer, "%s&1", req_password); 139 xasprintf(&send_buffer, "%s&1", req_password);
140 fetch_data (server_address, server_port, send_buffer); 140 fetch_data(server_address, server_port, send_buffer);
141 if (value_list != NULL && strcmp(recv_buffer, value_list) != 0) { 141 if (value_list != NULL && strcmp(recv_buffer, value_list) != 0) {
142 xasprintf (&output_message, _("Wrong client version - running: %s, required: %s"), recv_buffer, value_list); 142 xasprintf(&output_message, _("Wrong client version - running: %s, required: %s"), recv_buffer, value_list);
143 return_code = STATE_WARNING; 143 return_code = STATE_WARNING;
144 } else { 144 } else {
145 xasprintf (&output_message, "%s", recv_buffer); 145 xasprintf(&output_message, "%s", recv_buffer);
146 return_code = STATE_OK; 146 return_code = STATE_OK;
147 } 147 }
148 break; 148 break;
149 149
150 case CHECK_CPULOAD: 150 case CHECK_CPULOAD:
151 151
152 if (value_list==NULL) 152 if (value_list == NULL)
153 output_message = strdup (_("missing -l parameters")); 153 output_message = strdup(_("missing -l parameters"));
154 else if (! strtoularray(lvalue_list,value_list,",")) 154 else if (!strtoularray(lvalue_list, value_list, ","))
155 output_message = strdup (_("wrong -l parameter.")); 155 output_message = strdup(_("wrong -l parameter."));
156 else { 156 else {
157 /* -l parameters is present with only integers */ 157 /* -l parameters is present with only integers */
158 return_code=STATE_OK; 158 return_code = STATE_OK;
159 temp_string = strdup (_("CPU Load")); 159 temp_string = strdup(_("CPU Load"));
160 temp_string_perf = strdup (" "); 160 temp_string_perf = strdup(" ");
161 161
162 /* loop until one of the parameters is wrong or not present */ 162 /* loop until one of the parameters is wrong or not present */
163 while (lvalue_list[0+offset]> (unsigned long)0 && 163 while (lvalue_list[0 + offset] > (unsigned long)0 && lvalue_list[0 + offset] <= (unsigned long)17280 &&
164 lvalue_list[0+offset]<=(unsigned long)17280 && 164 lvalue_list[1 + offset] > (unsigned long)0 && lvalue_list[1 + offset] <= (unsigned long)100 &&
165 lvalue_list[1+offset]> (unsigned long)0 && 165 lvalue_list[2 + offset] > (unsigned long)0 && lvalue_list[2 + offset] <= (unsigned long)100) {
166 lvalue_list[1+offset]<=(unsigned long)100 &&
167 lvalue_list[2+offset]> (unsigned long)0 &&
168 lvalue_list[2+offset]<=(unsigned long)100) {
169 166
170 /* Send request and retrieve data */ 167 /* Send request and retrieve data */
171 xasprintf(&send_buffer,"%s&2&%lu",req_password,lvalue_list[0+offset]); 168 xasprintf(&send_buffer, "%s&2&%lu", req_password, lvalue_list[0 + offset]);
172 fetch_data (server_address, server_port, send_buffer); 169 fetch_data(server_address, server_port, send_buffer);
173 170
174 utilization=strtoul(recv_buffer,NULL,10); 171 utilization = strtoul(recv_buffer, NULL, 10);
175 172
176 /* Check if any of the request is in a warning or critical state */ 173 /* Check if any of the request is in a warning or critical state */
177 if(utilization >= lvalue_list[2+offset]) 174 if (utilization >= lvalue_list[2 + offset])
178 return_code=STATE_CRITICAL; 175 return_code = STATE_CRITICAL;
179 else if(utilization >= lvalue_list[1+offset] && return_code<STATE_WARNING) 176 else if (utilization >= lvalue_list[1 + offset] && return_code < STATE_WARNING)
180 return_code=STATE_WARNING; 177 return_code = STATE_WARNING;
181 178
182 xasprintf(&output_message,_(" %lu%% (%lu min average)"), utilization, lvalue_list[0+offset]); 179 xasprintf(&output_message, _(" %lu%% (%lu min average)"), utilization, lvalue_list[0 + offset]);
183 xasprintf(&temp_string,"%s%s",temp_string,output_message); 180 xasprintf(&temp_string, "%s%s", temp_string, output_message);
184 xasprintf(&perfdata,_(" '%lu min avg Load'=%lu%%;%lu;%lu;0;100"), lvalue_list[0+offset], utilization, 181 xasprintf(&perfdata, _(" '%lu min avg Load'=%lu%%;%lu;%lu;0;100"), lvalue_list[0 + offset], utilization,
185 lvalue_list[1+offset], lvalue_list[2+offset]); 182 lvalue_list[1 + offset], lvalue_list[2 + offset]);
186 xasprintf(&temp_string_perf,"%s%s",temp_string_perf,perfdata); 183 xasprintf(&temp_string_perf, "%s%s", temp_string_perf, perfdata);
187 offset+=3; /* move across the array */ 184 offset += 3; /* move across the array */
188 } 185 }
189 186
190 if (strlen(temp_string)>10) { /* we had at least one loop */ 187 if (strlen(temp_string) > 10) { /* we had at least one loop */
191 output_message = strdup (temp_string); 188 output_message = strdup(temp_string);
192 perfdata = temp_string_perf; 189 perfdata = temp_string_perf;
193 } else 190 } else
194 output_message = strdup (_("not enough values for -l parameters")); 191 output_message = strdup(_("not enough values for -l parameters"));
195 } 192 }
196 break; 193 break;
197 194
@@ -200,16 +197,14 @@ int main(int argc, char **argv){
200 if (value_list == NULL) { 197 if (value_list == NULL) {
201 value_list = "minutes"; 198 value_list = "minutes";
202 } 199 }
203 if (strncmp(value_list, "seconds", strlen("seconds") + 1 ) && 200 if (strncmp(value_list, "seconds", strlen("seconds") + 1) && strncmp(value_list, "minutes", strlen("minutes") + 1) &&
204 strncmp(value_list, "minutes", strlen("minutes") + 1) && 201 strncmp(value_list, "hours", strlen("hours") + 1) && strncmp(value_list, "days", strlen("days") + 1)) {
205 strncmp(value_list, "hours", strlen("hours") + 1) &&
206 strncmp(value_list, "days", strlen("days") + 1)) {
207 202
208 output_message = strdup (_("wrong -l argument")); 203 output_message = strdup(_("wrong -l argument"));
209 } else { 204 } else {
210 xasprintf(&send_buffer, "%s&3", req_password); 205 xasprintf(&send_buffer, "%s&3", req_password);
211 fetch_data (server_address, server_port, send_buffer); 206 fetch_data(server_address, server_port, send_buffer);
212 uptime=strtoul(recv_buffer,NULL,10); 207 uptime = strtoul(recv_buffer, NULL, 10);
213 updays = uptime / 86400; 208 updays = uptime / 86400;
214 uphours = (uptime % 86400) / 3600; 209 uphours = (uptime % 86400) / 3600;
215 upminutes = ((uptime % 86400) % 3600) / 60; 210 upminutes = ((uptime % 86400) % 3600) / 60;
@@ -222,57 +217,58 @@ int main(int argc, char **argv){
222 uptime = uptime / 86400; 217 uptime = uptime / 86400;
223 /* else uptime in seconds, nothing to do */ 218 /* else uptime in seconds, nothing to do */
224 219
225 xasprintf(&output_message,_("System Uptime - %u day(s) %u hour(s) %u minute(s) |uptime=%lu"),updays, uphours, upminutes, uptime); 220 xasprintf(&output_message, _("System Uptime - %u day(s) %u hour(s) %u minute(s) |uptime=%lu"), updays, uphours, upminutes,
221 uptime);
226 222
227 if (check_critical_value && uptime <= critical_value) 223 if (check_critical_value && uptime <= critical_value)
228 return_code=STATE_CRITICAL; 224 return_code = STATE_CRITICAL;
229 else if (check_warning_value && uptime <= warning_value) 225 else if (check_warning_value && uptime <= warning_value)
230 return_code=STATE_WARNING; 226 return_code = STATE_WARNING;
231 else 227 else
232 return_code=STATE_OK; 228 return_code = STATE_OK;
233 } 229 }
234 break; 230 break;
235 231
236 case CHECK_USEDDISKSPACE: 232 case CHECK_USEDDISKSPACE:
237 233
238 if (value_list==NULL) 234 if (value_list == NULL)
239 output_message = strdup (_("missing -l parameters")); 235 output_message = strdup(_("missing -l parameters"));
240 else if (strlen(value_list)!=1) 236 else if (strlen(value_list) != 1)
241 output_message = strdup (_("wrong -l argument")); 237 output_message = strdup(_("wrong -l argument"));
242 else { 238 else {
243 xasprintf(&send_buffer,"%s&4&%s", req_password, value_list); 239 xasprintf(&send_buffer, "%s&4&%s", req_password, value_list);
244 fetch_data (server_address, server_port, send_buffer); 240 fetch_data(server_address, server_port, send_buffer);
245 fds=strtok(recv_buffer,"&"); 241 fds = strtok(recv_buffer, "&");
246 tds=strtok(NULL,"&"); 242 tds = strtok(NULL, "&");
247 if(fds!=NULL) 243 if (fds != NULL)
248 free_disk_space=atof(fds); 244 free_disk_space = atof(fds);
249 if(tds!=NULL) 245 if (tds != NULL)
250 total_disk_space=atof(tds); 246 total_disk_space = atof(tds);
251 247
252 if (total_disk_space>0 && free_disk_space>=0) { 248 if (total_disk_space > 0 && free_disk_space >= 0) {
253 percent_used_space = ((total_disk_space - free_disk_space) / total_disk_space) * 100; 249 percent_used_space = ((total_disk_space - free_disk_space) / total_disk_space) * 100;
254 warning_used_space = ((float)warning_value / 100) * total_disk_space; 250 warning_used_space = ((float)warning_value / 100) * total_disk_space;
255 critical_used_space = ((float)critical_value / 100) * total_disk_space; 251 critical_used_space = ((float)critical_value / 100) * total_disk_space;
256 252
257 xasprintf(&temp_string,_("%s:\\ - total: %.2f Gb - used: %.2f Gb (%.0f%%) - free %.2f Gb (%.0f%%)"), 253 xasprintf(&temp_string, _("%s:\\ - total: %.2f Gb - used: %.2f Gb (%.0f%%) - free %.2f Gb (%.0f%%)"), value_list,
258 value_list, total_disk_space / 1073741824, (total_disk_space - free_disk_space) / 1073741824, 254 total_disk_space / 1073741824, (total_disk_space - free_disk_space) / 1073741824, percent_used_space,
259 percent_used_space, free_disk_space / 1073741824, (free_disk_space / total_disk_space)*100); 255 free_disk_space / 1073741824, (free_disk_space / total_disk_space) * 100);
260 xasprintf(&temp_string_perf,_("'%s:\\ Used Space'=%.2fGb;%.2f;%.2f;0.00;%.2f"), value_list, 256 xasprintf(&temp_string_perf, _("'%s:\\ Used Space'=%.2fGb;%.2f;%.2f;0.00;%.2f"), value_list,
261 (total_disk_space - free_disk_space) / 1073741824, warning_used_space / 1073741824, 257 (total_disk_space - free_disk_space) / 1073741824, warning_used_space / 1073741824,
262 critical_used_space / 1073741824, total_disk_space / 1073741824); 258 critical_used_space / 1073741824, total_disk_space / 1073741824);
263 259
264 if(check_critical_value && percent_used_space >= critical_value) 260 if (check_critical_value && percent_used_space >= critical_value)
265 return_code=STATE_CRITICAL; 261 return_code = STATE_CRITICAL;
266 else if (check_warning_value && percent_used_space >= warning_value) 262 else if (check_warning_value && percent_used_space >= warning_value)
267 return_code=STATE_WARNING; 263 return_code = STATE_WARNING;
268 else 264 else
269 return_code=STATE_OK; 265 return_code = STATE_OK;
270 266
271 output_message = strdup (temp_string); 267 output_message = strdup(temp_string);
272 perfdata = temp_string_perf; 268 perfdata = temp_string_perf;
273 } else { 269 } else {
274 output_message = strdup (_("Free disk space : Invalid drive")); 270 output_message = strdup(_("Free disk space : Invalid drive"));
275 return_code=STATE_UNKNOWN; 271 return_code = STATE_UNKNOWN;
276 } 272 }
277 } 273 }
278 break; 274 break;
@@ -280,57 +276,56 @@ int main(int argc, char **argv){
280 case CHECK_SERVICESTATE: 276 case CHECK_SERVICESTATE:
281 case CHECK_PROCSTATE: 277 case CHECK_PROCSTATE:
282 278
283 if (value_list==NULL) 279 if (value_list == NULL)
284 output_message = strdup (_("No service/process specified")); 280 output_message = strdup(_("No service/process specified"));
285 else { 281 else {
286 preparelist(value_list); /* replace , between services with & to send the request */ 282 preparelist(value_list); /* replace , between services with & to send the request */
287 xasprintf(&send_buffer,"%s&%u&%s&%s", req_password,(vars_to_check==CHECK_SERVICESTATE)?5:6, 283 xasprintf(&send_buffer, "%s&%u&%s&%s", req_password, (vars_to_check == CHECK_SERVICESTATE) ? 5 : 6,
288 (show_all) ? "ShowAll" : "ShowFail",value_list); 284 (show_all) ? "ShowAll" : "ShowFail", value_list);
289 fetch_data (server_address, server_port, send_buffer); 285 fetch_data(server_address, server_port, send_buffer);
290 numstr = strtok(recv_buffer,"&"); 286 numstr = strtok(recv_buffer, "&");
291 if (numstr == NULL) 287 if (numstr == NULL)
292 die(STATE_UNKNOWN, _("could not fetch information from server\n")); 288 die(STATE_UNKNOWN, _("could not fetch information from server\n"));
293 return_code=atoi(numstr); 289 return_code = atoi(numstr);
294 temp_string=strtok(NULL,"&"); 290 temp_string = strtok(NULL, "&");
295 output_message = strdup (temp_string); 291 output_message = strdup(temp_string);
296 } 292 }
297 break; 293 break;
298 294
299 case CHECK_MEMUSE: 295 case CHECK_MEMUSE:
300 296
301 xasprintf(&send_buffer,"%s&7", req_password); 297 xasprintf(&send_buffer, "%s&7", req_password);
302 fetch_data (server_address, server_port, send_buffer); 298 fetch_data(server_address, server_port, send_buffer);
303 numstr = strtok(recv_buffer,"&"); 299 numstr = strtok(recv_buffer, "&");
304 if (numstr == NULL) 300 if (numstr == NULL)
305 die(STATE_UNKNOWN, _("could not fetch information from server\n")); 301 die(STATE_UNKNOWN, _("could not fetch information from server\n"));
306 mem_commitLimit=atof(numstr); 302 mem_commitLimit = atof(numstr);
307 numstr = strtok(NULL,"&"); 303 numstr = strtok(NULL, "&");
308 if (numstr == NULL) 304 if (numstr == NULL)
309 die(STATE_UNKNOWN, _("could not fetch information from server\n")); 305 die(STATE_UNKNOWN, _("could not fetch information from server\n"));
310 mem_commitByte=atof(numstr); 306 mem_commitByte = atof(numstr);
311 percent_used_space = (mem_commitByte / mem_commitLimit) * 100; 307 percent_used_space = (mem_commitByte / mem_commitLimit) * 100;
312 warning_used_space = ((float)warning_value / 100) * mem_commitLimit; 308 warning_used_space = ((float)warning_value / 100) * mem_commitLimit;
313 critical_used_space = ((float)critical_value / 100) * mem_commitLimit; 309 critical_used_space = ((float)critical_value / 100) * mem_commitLimit;
314 310
315 /* Divisor should be 1048567, not 3044515, as we are measuring "Commit Charge" here, 311 /* Divisor should be 1048567, not 3044515, as we are measuring "Commit Charge" here,
316 which equals RAM + Pagefiles. */ 312 which equals RAM + Pagefiles. */
317 xasprintf(&output_message,_("Memory usage: total:%.2f MB - used: %.2f MB (%.0f%%) - free: %.2f MB (%.0f%%)"), 313 xasprintf(&output_message, _("Memory usage: total:%.2f MB - used: %.2f MB (%.0f%%) - free: %.2f MB (%.0f%%)"),
318 mem_commitLimit / 1048567, mem_commitByte / 1048567, percent_used_space, 314 mem_commitLimit / 1048567, mem_commitByte / 1048567, percent_used_space, (mem_commitLimit - mem_commitByte) / 1048567,
319 (mem_commitLimit - mem_commitByte) / 1048567, (mem_commitLimit - mem_commitByte) / mem_commitLimit * 100); 315 (mem_commitLimit - mem_commitByte) / mem_commitLimit * 100);
320 xasprintf(&perfdata,_("'Memory usage'=%.2fMB;%.2f;%.2f;0.00;%.2f"), mem_commitByte / 1048567, 316 xasprintf(&perfdata, _("'Memory usage'=%.2fMB;%.2f;%.2f;0.00;%.2f"), mem_commitByte / 1048567, warning_used_space / 1048567,
321 warning_used_space / 1048567, critical_used_space / 1048567, mem_commitLimit / 1048567); 317 critical_used_space / 1048567, mem_commitLimit / 1048567);
322 318
323 return_code=STATE_OK; 319 return_code = STATE_OK;
324 if(check_critical_value && percent_used_space >= critical_value) 320 if (check_critical_value && percent_used_space >= critical_value)
325 return_code=STATE_CRITICAL; 321 return_code = STATE_CRITICAL;
326 else if (check_warning_value && percent_used_space >= warning_value) 322 else if (check_warning_value && percent_used_space >= warning_value)
327 return_code=STATE_WARNING; 323 return_code = STATE_WARNING;
328 324
329 break; 325 break;
330 326
331 case CHECK_COUNTER: 327 case CHECK_COUNTER:
332 328
333
334 /* 329 /*
335 CHECK_COUNTER has been modified to provide extensive perfdata information. 330 CHECK_COUNTER has been modified to provide extensive perfdata information.
336 In order to do this, some modifications have been done to the code 331 In order to do this, some modifications have been done to the code
@@ -353,311 +348,290 @@ int main(int argc, char **argv){
353 */ 348 */
354 349
355 if (value_list == NULL) 350 if (value_list == NULL)
356 output_message = strdup (_("No counter specified")); 351 output_message = strdup(_("No counter specified"));
357 else 352 else {
358 { 353 preparelist(value_list); /* replace , between services with & to send the request */
359 preparelist (value_list); /* replace , between services with & to send the request */ 354 isPercent = (strchr(value_list, '%') != NULL);
360 isPercent = (strchr (value_list, '%') != NULL); 355
361 356 strtok(value_list, "&"); /* burn the first parameters */
362 strtok (value_list, "&"); /* burn the first parameters */ 357 description = strtok(NULL, "&");
363 description = strtok (NULL, "&"); 358 counter_unit = strtok(NULL, "&");
364 counter_unit = strtok (NULL, "&"); 359 xasprintf(&send_buffer, "%s&8&%s", req_password, value_list);
365 xasprintf (&send_buffer, "%s&8&%s", req_password, value_list); 360 fetch_data(server_address, server_port, send_buffer);
366 fetch_data (server_address, server_port, send_buffer); 361 counter_value = atof(recv_buffer);
367 counter_value = atof (recv_buffer);
368 362
369 if (description == NULL) 363 if (description == NULL)
370 xasprintf (&output_message, "%.f", counter_value); 364 xasprintf(&output_message, "%.f", counter_value);
371 else if (isPercent) 365 else if (isPercent) {
372 { 366 counter_unit = strdup("%");
373 counter_unit = strdup ("%");
374 allRight = true; 367 allRight = true;
375 } 368 }
376 369
377 if ((counter_unit != NULL) && (!allRight)) 370 if ((counter_unit != NULL) && (!allRight)) {
378 { 371 minval = strtok(NULL, "&");
379 minval = strtok (NULL, "&"); 372 maxval = strtok(NULL, "&");
380 maxval = strtok (NULL, "&");
381 373
382 /* All parameters specified. Let's check the numbers */ 374 /* All parameters specified. Let's check the numbers */
383 375
384 fminval = (minval != NULL) ? strtod (minval, &errcvt) : -1; 376 fminval = (minval != NULL) ? strtod(minval, &errcvt) : -1;
385 fmaxval = (minval != NULL) ? strtod (maxval, &errcvt) : -1; 377 fmaxval = (minval != NULL) ? strtod(maxval, &errcvt) : -1;
386 378
387 if ((fminval == 0) && (minval == errcvt)) 379 if ((fminval == 0) && (minval == errcvt))
388 output_message = strdup (_("Minimum value contains non-numbers")); 380 output_message = strdup(_("Minimum value contains non-numbers"));
389 else 381 else {
390 {
391 if ((fmaxval == 0) && (maxval == errcvt)) 382 if ((fmaxval == 0) && (maxval == errcvt))
392 output_message = strdup (_("Maximum value contains non-numbers")); 383 output_message = strdup(_("Maximum value contains non-numbers"));
393 else 384 else
394 allRight = true; /* Everything is OK. */ 385 allRight = true; /* Everything is OK. */
395
396 } 386 }
397 } 387 } else if ((counter_unit == NULL) && (description != NULL))
398 else if ((counter_unit == NULL) && (description != NULL)) 388 output_message = strdup(_("No unit counter specified"));
399 output_message = strdup (_("No unit counter specified"));
400 389
401 if (allRight) 390 if (allRight) {
402 {
403 /* Let's format the output string, finally... */ 391 /* Let's format the output string, finally... */
404 if (strstr(description, "%") == NULL) { 392 if (strstr(description, "%") == NULL) {
405 xasprintf (&output_message, "%s = %.2f %s", description, counter_value, counter_unit); 393 xasprintf(&output_message, "%s = %.2f %s", description, counter_value, counter_unit);
406 } else { 394 } else {
407 /* has formatting, will segv if wrong */ 395 /* has formatting, will segv if wrong */
408 xasprintf (&output_message, description, counter_value); 396 xasprintf(&output_message, description, counter_value);
409 } 397 }
410 xasprintf (&output_message, "%s |", output_message); 398 xasprintf(&output_message, "%s |", output_message);
411 xasprintf (&output_message,"%s %s", output_message, 399 xasprintf(&output_message, "%s %s", output_message,
412 fperfdata (description, counter_value, 400 fperfdata(description, counter_value, counter_unit, 1, warning_value, 1, critical_value,
413 counter_unit, 1, warning_value, 1, critical_value, 401 (!(isPercent) && (minval != NULL)), fminval, (!(isPercent) && (minval != NULL)), fmaxval));
414 (!(isPercent) && (minval != NULL)), fminval,
415 (!(isPercent) && (minval != NULL)), fmaxval));
416 } 402 }
417 } 403 }
418 404
419 if (critical_value > warning_value) 405 if (critical_value > warning_value) { /* Normal thresholds */
420 { /* Normal thresholds */
421 if (check_critical_value && counter_value >= critical_value) 406 if (check_critical_value && counter_value >= critical_value)
422 return_code = STATE_CRITICAL; 407 return_code = STATE_CRITICAL;
423 else if (check_warning_value && counter_value >= warning_value) 408 else if (check_warning_value && counter_value >= warning_value)
424 return_code = STATE_WARNING; 409 return_code = STATE_WARNING;
425 else 410 else
426 return_code = STATE_OK; 411 return_code = STATE_OK;
427 } 412 } else { /* inverse thresholds */
428 else
429 { /* inverse thresholds */
430 return_code = STATE_OK; 413 return_code = STATE_OK;
431 if (check_critical_value && counter_value <= critical_value) 414 if (check_critical_value && counter_value <= critical_value)
432 return_code = STATE_CRITICAL; 415 return_code = STATE_CRITICAL;
433 else if (check_warning_value && counter_value <= warning_value) 416 else if (check_warning_value && counter_value <= warning_value)
434 return_code = STATE_WARNING; 417 return_code = STATE_WARNING;
435 } 418 }
436 break; 419 break;
437 420
438 case CHECK_FILEAGE: 421 case CHECK_FILEAGE:
439 422
440 if (value_list==NULL) 423 if (value_list == NULL)
441 output_message = strdup (_("No counter specified")); 424 output_message = strdup(_("No counter specified"));
442 else { 425 else {
443 preparelist(value_list); /* replace , between services with & to send the request */ 426 preparelist(value_list); /* replace , between services with & to send the request */
444 xasprintf(&send_buffer,"%s&9&%s", req_password,value_list); 427 xasprintf(&send_buffer, "%s&9&%s", req_password, value_list);
445 fetch_data (server_address, server_port, send_buffer); 428 fetch_data(server_address, server_port, send_buffer);
446 age_in_minutes = atoi(strtok(recv_buffer,"&")); 429 age_in_minutes = atoi(strtok(recv_buffer, "&"));
447 description = strtok(NULL,"&"); 430 description = strtok(NULL, "&");
448 output_message = strdup (description); 431 output_message = strdup(description);
449 432
450 if (critical_value > warning_value) { /* Normal thresholds */ 433 if (critical_value > warning_value) { /* Normal thresholds */
451 if(check_critical_value && age_in_minutes >= critical_value) 434 if (check_critical_value && age_in_minutes >= critical_value)
452 return_code=STATE_CRITICAL; 435 return_code = STATE_CRITICAL;
453 else if (check_warning_value && age_in_minutes >= warning_value) 436 else if (check_warning_value && age_in_minutes >= warning_value)
454 return_code=STATE_WARNING; 437 return_code = STATE_WARNING;
455 else 438 else
456 return_code=STATE_OK; 439 return_code = STATE_OK;
457 } 440 } else { /* inverse thresholds */
458 else { /* inverse thresholds */ 441 if (check_critical_value && age_in_minutes <= critical_value)
459 if(check_critical_value && age_in_minutes <= critical_value) 442 return_code = STATE_CRITICAL;
460 return_code=STATE_CRITICAL;
461 else if (check_warning_value && age_in_minutes <= warning_value) 443 else if (check_warning_value && age_in_minutes <= warning_value)
462 return_code=STATE_WARNING; 444 return_code = STATE_WARNING;
463 else 445 else
464 return_code=STATE_OK; 446 return_code = STATE_OK;
465 } 447 }
466 } 448 }
467 break; 449 break;
468 450
469 case CHECK_INSTANCES: 451 case CHECK_INSTANCES:
470 if (value_list==NULL) 452 if (value_list == NULL)
471 output_message = strdup (_("No counter specified")); 453 output_message = strdup(_("No counter specified"));
472 else { 454 else {
473 xasprintf(&send_buffer,"%s&10&%s", req_password,value_list); 455 xasprintf(&send_buffer, "%s&10&%s", req_password, value_list);
474 fetch_data (server_address, server_port, send_buffer); 456 fetch_data(server_address, server_port, send_buffer);
475 if (!strncmp(recv_buffer,"ERROR",5)) { 457 if (!strncmp(recv_buffer, "ERROR", 5)) {
476 printf("NSClient - %s\n",recv_buffer); 458 printf("NSClient - %s\n", recv_buffer);
477 exit(STATE_UNKNOWN); 459 exit(STATE_UNKNOWN);
478 } 460 }
479 xasprintf(&output_message,"%s",recv_buffer); 461 xasprintf(&output_message, "%s", recv_buffer);
480 return_code=STATE_OK; 462 return_code = STATE_OK;
481 } 463 }
482 break; 464 break;
483 465
484 case CHECK_NONE: 466 case CHECK_NONE:
485 default: 467 default:
486 usage4 (_("Please specify a variable to check")); 468 usage4(_("Please specify a variable to check"));
487 break; 469 break;
488
489 } 470 }
490 471
491 /* reset timeout */ 472 /* reset timeout */
492 alarm(0); 473 alarm(0);
493 474
494 if (perfdata==NULL) 475 if (perfdata == NULL)
495 printf("%s\n",output_message); 476 printf("%s\n", output_message);
496 else 477 else
497 printf("%s | %s\n",output_message,perfdata); 478 printf("%s | %s\n", output_message, perfdata);
498 return return_code; 479 return return_code;
499} 480}
500 481
501
502
503/* process command-line arguments */ 482/* process command-line arguments */
504int process_arguments(int argc, char **argv){ 483int process_arguments(int argc, char **argv) {
505 int c; 484 int c;
506 485
507 int option = 0; 486 int option = 0;
508 static struct option longopts[] = 487 static struct option longopts[] = {{"port", required_argument, 0, 'p'},
509 { 488 {"timeout", required_argument, 0, 't'},
510 {"port", required_argument,0,'p'}, 489 {"critical", required_argument, 0, 'c'},
511 {"timeout", required_argument,0,'t'}, 490 {"warning", required_argument, 0, 'w'},
512 {"critical", required_argument,0,'c'}, 491 {"variable", required_argument, 0, 'v'},
513 {"warning", required_argument,0,'w'}, 492 {"hostname", required_argument, 0, 'H'},
514 {"variable", required_argument,0,'v'}, 493 {"params", required_argument, 0, 'l'},
515 {"hostname", required_argument,0,'H'}, 494 {"secret", required_argument, 0, 's'},
516 {"params", required_argument,0,'l'}, 495 {"display", required_argument, 0, 'd'},
517 {"secret", required_argument,0,'s'}, 496 {"unknown-timeout", no_argument, 0, 'u'},
518 {"display", required_argument,0,'d'}, 497 {"version", no_argument, 0, 'V'},
519 {"unknown-timeout", no_argument, 0, 'u'}, 498 {"help", no_argument, 0, 'h'},
520 {"version", no_argument, 0,'V'}, 499 {0, 0, 0, 0}};
521 {"help", no_argument, 0,'h'},
522 {0,0,0,0}
523 };
524 500
525 /* no options were supplied */ 501 /* no options were supplied */
526 if(argc<2) return ERROR; 502 if (argc < 2)
503 return ERROR;
527 504
528 /* backwards compatibility */ 505 /* backwards compatibility */
529 if (! is_option(argv[1])) { 506 if (!is_option(argv[1])) {
530 server_address = strdup(argv[1]); 507 server_address = strdup(argv[1]);
531 argv[1]=argv[0]; 508 argv[1] = argv[0];
532 argv=&argv[1]; 509 argv = &argv[1];
533 argc--; 510 argc--;
534 } 511 }
535 512
536 for (c=1;c<argc;c++) { 513 for (c = 1; c < argc; c++) {
537 if(strcmp("-to",argv[c])==0) 514 if (strcmp("-to", argv[c]) == 0)
538 strcpy(argv[c],"-t"); 515 strcpy(argv[c], "-t");
539 else if (strcmp("-wv",argv[c])==0) 516 else if (strcmp("-wv", argv[c]) == 0)
540 strcpy(argv[c],"-w"); 517 strcpy(argv[c], "-w");
541 else if (strcmp("-cv",argv[c])==0) 518 else if (strcmp("-cv", argv[c]) == 0)
542 strcpy(argv[c],"-c"); 519 strcpy(argv[c], "-c");
543 } 520 }
544 521
545 while (1) { 522 while (1) {
546 c = getopt_long(argc,argv,"+hVH:t:c:w:p:v:l:s:d:u",longopts,&option); 523 c = getopt_long(argc, argv, "+hVH:t:c:w:p:v:l:s:d:u", longopts, &option);
547 524
548 if (c==-1||c==EOF||c==1) 525 if (c == -1 || c == EOF || c == 1)
549 break; 526 break;
550 527
551 switch (c) { 528 switch (c) {
552 case '?': /* print short usage statement if args not parsable */ 529 case '?': /* print short usage statement if args not parsable */
553 usage5 (); 530 usage5();
554 case 'h': /* help */ 531 case 'h': /* help */
555 print_help(); 532 print_help();
556 exit(STATE_UNKNOWN); 533 exit(STATE_UNKNOWN);
557 case 'V': /* version */ 534 case 'V': /* version */
558 print_revision(progname, NP_VERSION); 535 print_revision(progname, NP_VERSION);
559 exit(STATE_UNKNOWN); 536 exit(STATE_UNKNOWN);
560 case 'H': /* hostname */ 537 case 'H': /* hostname */
561 server_address = optarg; 538 server_address = optarg;
562 break; 539 break;
563 case 's': /* password */ 540 case 's': /* password */
564 req_password = optarg; 541 req_password = optarg;
565 break; 542 break;
566 case 'p': /* port */ 543 case 'p': /* port */
567 if (is_intnonneg(optarg)) 544 if (is_intnonneg(optarg))
568 server_port=atoi(optarg); 545 server_port = atoi(optarg);
569 else 546 else
570 die(STATE_UNKNOWN,_("Server port must be an integer\n")); 547 die(STATE_UNKNOWN, _("Server port must be an integer\n"));
571 break; 548 break;
572 case 'v': 549 case 'v':
573 if(strlen(optarg)<4) 550 if (strlen(optarg) < 4)
574 return ERROR; 551 return ERROR;
575 if(!strcmp(optarg,"CLIENTVERSION")) 552 if (!strcmp(optarg, "CLIENTVERSION"))
576 vars_to_check=CHECK_CLIENTVERSION; 553 vars_to_check = CHECK_CLIENTVERSION;
577 else if(!strcmp(optarg,"CPULOAD")) 554 else if (!strcmp(optarg, "CPULOAD"))
578 vars_to_check=CHECK_CPULOAD; 555 vars_to_check = CHECK_CPULOAD;
579 else if(!strcmp(optarg,"UPTIME")) 556 else if (!strcmp(optarg, "UPTIME"))
580 vars_to_check=CHECK_UPTIME; 557 vars_to_check = CHECK_UPTIME;
581 else if(!strcmp(optarg,"USEDDISKSPACE")) 558 else if (!strcmp(optarg, "USEDDISKSPACE"))
582 vars_to_check=CHECK_USEDDISKSPACE; 559 vars_to_check = CHECK_USEDDISKSPACE;
583 else if(!strcmp(optarg,"SERVICESTATE")) 560 else if (!strcmp(optarg, "SERVICESTATE"))
584 vars_to_check=CHECK_SERVICESTATE; 561 vars_to_check = CHECK_SERVICESTATE;
585 else if(!strcmp(optarg,"PROCSTATE")) 562 else if (!strcmp(optarg, "PROCSTATE"))
586 vars_to_check=CHECK_PROCSTATE; 563 vars_to_check = CHECK_PROCSTATE;
587 else if(!strcmp(optarg,"MEMUSE")) 564 else if (!strcmp(optarg, "MEMUSE"))
588 vars_to_check=CHECK_MEMUSE; 565 vars_to_check = CHECK_MEMUSE;
589 else if(!strcmp(optarg,"COUNTER")) 566 else if (!strcmp(optarg, "COUNTER"))
590 vars_to_check=CHECK_COUNTER; 567 vars_to_check = CHECK_COUNTER;
591 else if(!strcmp(optarg,"FILEAGE")) 568 else if (!strcmp(optarg, "FILEAGE"))
592 vars_to_check=CHECK_FILEAGE; 569 vars_to_check = CHECK_FILEAGE;
593 else if(!strcmp(optarg,"INSTANCES")) 570 else if (!strcmp(optarg, "INSTANCES"))
594 vars_to_check=CHECK_INSTANCES; 571 vars_to_check = CHECK_INSTANCES;
595 else 572 else
596 return ERROR; 573 return ERROR;
597 break; 574 break;
598 case 'l': /* value list */ 575 case 'l': /* value list */
599 value_list = optarg; 576 value_list = optarg;
600 break; 577 break;
601 case 'w': /* warning threshold */ 578 case 'w': /* warning threshold */
602 warning_value=strtoul(optarg,NULL,10); 579 warning_value = strtoul(optarg, NULL, 10);
603 check_warning_value=true; 580 check_warning_value = true;
604 break; 581 break;
605 case 'c': /* critical threshold */ 582 case 'c': /* critical threshold */
606 critical_value=strtoul(optarg,NULL,10); 583 critical_value = strtoul(optarg, NULL, 10);
607 check_critical_value=true; 584 check_critical_value = true;
608 break; 585 break;
609 case 'd': /* Display select for services */ 586 case 'd': /* Display select for services */
610 if (!strcmp(optarg,"SHOWALL")) 587 if (!strcmp(optarg, "SHOWALL"))
611 show_all = true; 588 show_all = true;
612 break; 589 break;
613 case 'u': 590 case 'u':
614 socket_timeout_state=STATE_UNKNOWN; 591 socket_timeout_state = STATE_UNKNOWN;
615 break; 592 break;
616 case 't': /* timeout */ 593 case 't': /* timeout */
617 socket_timeout=atoi(optarg); 594 socket_timeout = atoi(optarg);
618 if(socket_timeout<=0) 595 if (socket_timeout <= 0)
619 return ERROR; 596 return ERROR;
620 } 597 }
621
622 } 598 }
623 if (server_address == NULL) 599 if (server_address == NULL)
624 usage4 (_("You must provide a server address or host name")); 600 usage4(_("You must provide a server address or host name"));
625 601
626 if (vars_to_check==CHECK_NONE) 602 if (vars_to_check == CHECK_NONE)
627 return ERROR; 603 return ERROR;
628 604
629 if (req_password == NULL) 605 if (req_password == NULL)
630 req_password = strdup (_("None")); 606 req_password = strdup(_("None"));
631 607
632 return OK; 608 return OK;
633} 609}
634 610
635 611void fetch_data(const char *address, int port, const char *sendb) {
636
637void fetch_data (const char *address, int port, const char *sendb) {
638 int result; 612 int result;
639 613
640 result=process_tcp_request(address, port, sendb, recv_buffer,sizeof(recv_buffer)); 614 result = process_tcp_request(address, port, sendb, recv_buffer, sizeof(recv_buffer));
641 615
642 if(result!=STATE_OK) 616 if (result != STATE_OK)
643 die (result, _("could not fetch information from server\n")); 617 die(result, _("could not fetch information from server\n"));
644 618
645 if (!strncmp(recv_buffer,"ERROR",5)) 619 if (!strncmp(recv_buffer, "ERROR", 5))
646 die (STATE_UNKNOWN, "NSClient - %s\n",recv_buffer); 620 die(STATE_UNKNOWN, "NSClient - %s\n", recv_buffer);
647} 621}
648 622
649bool strtoularray(unsigned long *array, char *string, const char *delim) { 623bool strtoularray(unsigned long *array, char *string, const char *delim) {
650 /* split a <delim> delimited string into a long array */ 624 /* split a <delim> delimited string into a long array */
651 int idx=0; 625 int idx = 0;
652 char *t1; 626 char *t1;
653 627
654 for (idx=0;idx<MAX_VALUE_LIST;idx++) 628 for (idx = 0; idx < MAX_VALUE_LIST; idx++)
655 array[idx]=0; 629 array[idx] = 0;
656 630
657 idx=0; 631 idx = 0;
658 for(t1 = strtok(string,delim);t1 != NULL; t1 = strtok(NULL, delim)) { 632 for (t1 = strtok(string, delim); t1 != NULL; t1 = strtok(NULL, delim)) {
659 if (is_numeric(t1) && idx<MAX_VALUE_LIST) { 633 if (is_numeric(t1) && idx < MAX_VALUE_LIST) {
660 array[idx]=strtoul(t1,NULL,10); 634 array[idx] = strtoul(t1, NULL, 10);
661 idx++; 635 idx++;
662 } else 636 } else
663 return false; 637 return false;
@@ -671,131 +645,124 @@ void preparelist(char *string) {
671 645
672 for (i = 0; (size_t)i < strlen(string); i++) 646 for (i = 0; (size_t)i < strlen(string); i++)
673 if (string[i] == ',') { 647 if (string[i] == ',') {
674 string[i]='&'; 648 string[i] = '&';
675 } 649 }
676} 650}
677 651
678 652void print_help(void) {
679
680void print_help(void)
681{
682 print_revision(progname, NP_VERSION); 653 print_revision(progname, NP_VERSION);
683 654
684 printf ("Copyright (c) 2000 Yves Rubin (rubiyz@yahoo.com)\n"); 655 printf("Copyright (c) 2000 Yves Rubin (rubiyz@yahoo.com)\n");
685 printf (COPYRIGHT, copyright, email); 656 printf(COPYRIGHT, copyright, email);
686 657
687 printf ("%s\n", _("This plugin collects data from the NSClient service running on a")); 658 printf("%s\n", _("This plugin collects data from the NSClient service running on a"));
688 printf ("%s\n", _("Windows NT/2000/XP/2003 server.")); 659 printf("%s\n", _("Windows NT/2000/XP/2003 server."));
689 660
690 printf ("\n\n"); 661 printf("\n\n");
691 662
692 print_usage(); 663 print_usage();
693 664
694 printf (UT_HELP_VRSN); 665 printf(UT_HELP_VRSN);
695 printf (UT_EXTRA_OPTS); 666 printf(UT_EXTRA_OPTS);
696 667
697 printf ("%s\n", _("Options:")); 668 printf("%s\n", _("Options:"));
698 printf (" %s\n", "-H, --hostname=HOST"); 669 printf(" %s\n", "-H, --hostname=HOST");
699 printf (" %s\n", _("Name of the host to check")); 670 printf(" %s\n", _("Name of the host to check"));
700 printf (" %s\n", "-p, --port=INTEGER"); 671 printf(" %s\n", "-p, --port=INTEGER");
701 printf (" %s", _("Optional port number (default: ")); 672 printf(" %s", _("Optional port number (default: "));
702 printf ("%d)\n", PORT); 673 printf("%d)\n", PORT);
703 printf (" %s\n", "-s, --secret=<password>"); 674 printf(" %s\n", "-s, --secret=<password>");
704 printf (" %s\n", _("Password needed for the request")); 675 printf(" %s\n", _("Password needed for the request"));
705 printf (" %s\n", "-w, --warning=INTEGER"); 676 printf(" %s\n", "-w, --warning=INTEGER");
706 printf (" %s\n", _("Threshold which will result in a warning status")); 677 printf(" %s\n", _("Threshold which will result in a warning status"));
707 printf (" %s\n", "-c, --critical=INTEGER"); 678 printf(" %s\n", "-c, --critical=INTEGER");
708 printf (" %s\n", _("Threshold which will result in a critical status")); 679 printf(" %s\n", _("Threshold which will result in a critical status"));
709 printf (" %s\n", "-t, --timeout=INTEGER"); 680 printf(" %s\n", "-t, --timeout=INTEGER");
710 printf (" %s", _("Seconds before connection attempt times out (default: ")); 681 printf(" %s", _("Seconds before connection attempt times out (default: "));
711 printf (" %s\n", "-l, --params=<parameters>"); 682 printf(" %s\n", "-l, --params=<parameters>");
712 printf (" %s", _("Parameters passed to specified check (see below)")); 683 printf(" %s", _("Parameters passed to specified check (see below)"));
713 printf (" %s\n", "-d, --display={SHOWALL}"); 684 printf(" %s\n", "-d, --display={SHOWALL}");
714 printf (" %s", _("Display options (currently only SHOWALL works)")); 685 printf(" %s", _("Display options (currently only SHOWALL works)"));
715 printf (" %s\n", "-u, --unknown-timeout"); 686 printf(" %s\n", "-u, --unknown-timeout");
716 printf (" %s", _("Return UNKNOWN on timeouts")); 687 printf(" %s", _("Return UNKNOWN on timeouts"));
717 printf ("%d)\n", DEFAULT_SOCKET_TIMEOUT); 688 printf("%d)\n", DEFAULT_SOCKET_TIMEOUT);
718 printf (" %s\n", "-h, --help"); 689 printf(" %s\n", "-h, --help");
719 printf (" %s\n", _("Print this help screen")); 690 printf(" %s\n", _("Print this help screen"));
720 printf (" %s\n", "-V, --version"); 691 printf(" %s\n", "-V, --version");
721 printf (" %s\n", _("Print version information")); 692 printf(" %s\n", _("Print version information"));
722 printf (" %s\n", "-v, --variable=STRING"); 693 printf(" %s\n", "-v, --variable=STRING");
723 printf (" %s\n\n", _("Variable to check")); 694 printf(" %s\n\n", _("Variable to check"));
724 printf ("%s\n", _("Valid variables are:")); 695 printf("%s\n", _("Valid variables are:"));
725 printf (" %s", "CLIENTVERSION ="); 696 printf(" %s", "CLIENTVERSION =");
726 printf (" %s\n", _("Get the NSClient version")); 697 printf(" %s\n", _("Get the NSClient version"));
727 printf (" %s\n", _("If -l <version> is specified, will return warning if versions differ.")); 698 printf(" %s\n", _("If -l <version> is specified, will return warning if versions differ."));
728 printf (" %s\n", "CPULOAD ="); 699 printf(" %s\n", "CPULOAD =");
729 printf (" %s\n", _("Average CPU load on last x minutes.")); 700 printf(" %s\n", _("Average CPU load on last x minutes."));
730 printf (" %s\n", _("Request a -l parameter with the following syntax:")); 701 printf(" %s\n", _("Request a -l parameter with the following syntax:"));
731 printf (" %s\n", _("-l <minutes range>,<warning threshold>,<critical threshold>.")); 702 printf(" %s\n", _("-l <minutes range>,<warning threshold>,<critical threshold>."));
732 printf (" %s\n", _("<minute range> should be less than 24*60.")); 703 printf(" %s\n", _("<minute range> should be less than 24*60."));
733 printf (" %s\n", _("Thresholds are percentage and up to 10 requests can be done in one shot.")); 704 printf(" %s\n", _("Thresholds are percentage and up to 10 requests can be done in one shot."));
734 printf (" %s\n", "ie: -l 60,90,95,120,90,95"); 705 printf(" %s\n", "ie: -l 60,90,95,120,90,95");
735 printf (" %s\n", "UPTIME ="); 706 printf(" %s\n", "UPTIME =");
736 printf (" %s\n", _("Get the uptime of the machine.")); 707 printf(" %s\n", _("Get the uptime of the machine."));
737 printf (" %s\n", _("-l <unit> ")); 708 printf(" %s\n", _("-l <unit> "));
738 printf (" %s\n", _("<unit> = seconds, minutes, hours, or days. (default: minutes)")); 709 printf(" %s\n", _("<unit> = seconds, minutes, hours, or days. (default: minutes)"));
739 printf (" %s\n", _("Thresholds will use the unit specified above.")); 710 printf(" %s\n", _("Thresholds will use the unit specified above."));
740 printf (" %s\n", "USEDDISKSPACE ="); 711 printf(" %s\n", "USEDDISKSPACE =");
741 printf (" %s\n", _("Size and percentage of disk use.")); 712 printf(" %s\n", _("Size and percentage of disk use."));
742 printf (" %s\n", _("Request a -l parameter containing the drive letter only.")); 713 printf(" %s\n", _("Request a -l parameter containing the drive letter only."));
743 printf (" %s\n", _("Warning and critical thresholds can be specified with -w and -c.")); 714 printf(" %s\n", _("Warning and critical thresholds can be specified with -w and -c."));
744 printf (" %s\n", "MEMUSE ="); 715 printf(" %s\n", "MEMUSE =");
745 printf (" %s\n", _("Memory use.")); 716 printf(" %s\n", _("Memory use."));
746 printf (" %s\n", _("Warning and critical thresholds can be specified with -w and -c.")); 717 printf(" %s\n", _("Warning and critical thresholds can be specified with -w and -c."));
747 printf (" %s\n", "SERVICESTATE ="); 718 printf(" %s\n", "SERVICESTATE =");
748 printf (" %s\n", _("Check the state of one or several services.")); 719 printf(" %s\n", _("Check the state of one or several services."));
749 printf (" %s\n", _("Request a -l parameters with the following syntax:")); 720 printf(" %s\n", _("Request a -l parameters with the following syntax:"));
750 printf (" %s\n", _("-l <service1>,<service2>,<service3>,...")); 721 printf(" %s\n", _("-l <service1>,<service2>,<service3>,..."));
751 printf (" %s\n", _("You can specify -d SHOWALL in case you want to see working services")); 722 printf(" %s\n", _("You can specify -d SHOWALL in case you want to see working services"));
752 printf (" %s\n", _("in the returned string.")); 723 printf(" %s\n", _("in the returned string."));
753 printf (" %s\n", "PROCSTATE ="); 724 printf(" %s\n", "PROCSTATE =");
754 printf (" %s\n", _("Check if one or several process are running.")); 725 printf(" %s\n", _("Check if one or several process are running."));
755 printf (" %s\n", _("Same syntax as SERVICESTATE.")); 726 printf(" %s\n", _("Same syntax as SERVICESTATE."));
756 printf (" %s\n", "COUNTER ="); 727 printf(" %s\n", "COUNTER =");
757 printf (" %s\n", _("Check any performance counter of Windows NT/2000.")); 728 printf(" %s\n", _("Check any performance counter of Windows NT/2000."));
758 printf (" %s\n", _("Request a -l parameters with the following syntax:")); 729 printf(" %s\n", _("Request a -l parameters with the following syntax:"));
759 printf (" %s\n", _("-l \"\\\\<performance object>\\\\counter\",\"<description>")); 730 printf(" %s\n", _("-l \"\\\\<performance object>\\\\counter\",\"<description>"));
760 printf (" %s\n", _("The <description> parameter is optional and is given to a printf ")); 731 printf(" %s\n", _("The <description> parameter is optional and is given to a printf "));
761 printf (" %s\n", _("output command which requires a float parameter.")); 732 printf(" %s\n", _("output command which requires a float parameter."));
762 printf (" %s\n", _("If <description> does not include \"%%\", it is used as a label.")); 733 printf(" %s\n", _("If <description> does not include \"%%\", it is used as a label."));
763 printf (" %s\n", _("Some examples:")); 734 printf(" %s\n", _("Some examples:"));
764 printf (" %s\n", "\"Paging file usage is %%.2f %%%%\""); 735 printf(" %s\n", "\"Paging file usage is %%.2f %%%%\"");
765 printf (" %s\n", "\"%%.f %%%% paging file used.\""); 736 printf(" %s\n", "\"%%.f %%%% paging file used.\"");
766 printf (" %s\n", "INSTANCES ="); 737 printf(" %s\n", "INSTANCES =");
767 printf (" %s\n", _("Check any performance counter object of Windows NT/2000.")); 738 printf(" %s\n", _("Check any performance counter object of Windows NT/2000."));
768 printf (" %s\n", _("Syntax: check_nt -H <hostname> -p <port> -v INSTANCES -l <counter object>")); 739 printf(" %s\n", _("Syntax: check_nt -H <hostname> -p <port> -v INSTANCES -l <counter object>"));
769 printf (" %s\n", _("<counter object> is a Windows Perfmon Counter object (eg. Process),")); 740 printf(" %s\n", _("<counter object> is a Windows Perfmon Counter object (eg. Process),"));
770 printf (" %s\n", _("if it is two words, it should be enclosed in quotes")); 741 printf(" %s\n", _("if it is two words, it should be enclosed in quotes"));
771 printf (" %s\n", _("The returned results will be a comma-separated list of instances on ")); 742 printf(" %s\n", _("The returned results will be a comma-separated list of instances on "));
772 printf (" %s\n", _(" the selected computer for that object.")); 743 printf(" %s\n", _(" the selected computer for that object."));
773 printf (" %s\n", _("The purpose of this is to be run from command line to determine what instances")); 744 printf(" %s\n", _("The purpose of this is to be run from command line to determine what instances"));
774 printf (" %s\n", _(" are available for monitoring without having to log onto the Windows server")); 745 printf(" %s\n", _(" are available for monitoring without having to log onto the Windows server"));
775 printf (" %s\n", _(" to run Perfmon directly.")); 746 printf(" %s\n", _(" to run Perfmon directly."));
776 printf (" %s\n", _("It can also be used in scripts that automatically create the monitoring service")); 747 printf(" %s\n", _("It can also be used in scripts that automatically create the monitoring service"));
777 printf (" %s\n", _(" configuration files.")); 748 printf(" %s\n", _(" configuration files."));
778 printf (" %s\n", _("Some examples:")); 749 printf(" %s\n", _("Some examples:"));
779 printf (" %s\n\n", _("check_nt -H 192.168.1.1 -p 1248 -v INSTANCES -l Process")); 750 printf(" %s\n\n", _("check_nt -H 192.168.1.1 -p 1248 -v INSTANCES -l Process"));
780 751
781 printf ("%s\n", _("Notes:")); 752 printf("%s\n", _("Notes:"));
782 printf (" %s\n", _("- The NSClient service should be running on the server to get any information")); 753 printf(" %s\n", _("- The NSClient service should be running on the server to get any information"));
783 printf (" %s\n", "(http://nsclient.ready2run.nl)."); 754 printf(" %s\n", "(http://nsclient.ready2run.nl).");
784 printf (" %s\n", _("- Critical thresholds should be lower than warning thresholds")); 755 printf(" %s\n", _("- Critical thresholds should be lower than warning thresholds"));
785 printf (" %s\n", _("- Default port 1248 is sometimes in use by other services. The error")); 756 printf(" %s\n", _("- Default port 1248 is sometimes in use by other services. The error"));
786 printf (" %s\n", _("output when this happens contains \"Cannot map xxxxx to protocol number\".")); 757 printf(" %s\n", _("output when this happens contains \"Cannot map xxxxx to protocol number\"."));
787 printf (" %s\n", _("One fix for this is to change the port to something else on check_nt ")); 758 printf(" %s\n", _("One fix for this is to change the port to something else on check_nt "));
788 printf (" %s\n", _("and on the client service it\'s connecting to.")); 759 printf(" %s\n", _("and on the client service it\'s connecting to."));
789 760
790 printf (UT_SUPPORT); 761 printf(UT_SUPPORT);
791} 762}
792 763
793 764void print_usage(void) {
794 765 printf("%s\n", _("Usage:"));
795void print_usage(void) 766 printf("%s -H host -v variable [-p port] [-w warning] [-c critical]\n", progname);
796{ 767 printf("[-l params] [-d SHOWALL] [-u] [-t timeout]\n");
797 printf ("%s\n", _("Usage:"));
798 printf ("%s -H host -v variable [-p port] [-w warning] [-c critical]\n",progname);
799 printf ("[-l params] [-d SHOWALL] [-u] [-t timeout]\n");
800} 768}
801
diff --git a/plugins/check_ntp.c b/plugins/check_ntp.c
index 61b2d699..55a49460 100644
--- a/plugins/check_ntp.c
+++ b/plugins/check_ntp.c
@@ -4,7 +4,7 @@
4* 4*
5* License: GPL 5* License: GPL
6* Copyright (c) 2006 Sean Finney <seanius@seanius.net> 6* Copyright (c) 2006 Sean Finney <seanius@seanius.net>
7* Copyright (c) 2006-2008 Monitoring Plugins Development Team 7* Copyright (c) 2006-2024 Monitoring Plugins Development Team
8* 8*
9* Description: 9* Description:
10* 10*
@@ -31,7 +31,7 @@
31*****************************************************************************/ 31*****************************************************************************/
32 32
33const char *progname = "check_ntp"; 33const char *progname = "check_ntp";
34const char *copyright = "2006-2008"; 34const char *copyright = "2006-2024";
35const char *email = "devel@monitoring-plugins.org"; 35const char *email = "devel@monitoring-plugins.org";
36 36
37#include "common.h" 37#include "common.h"
diff --git a/plugins/check_ntp_peer.c b/plugins/check_ntp_peer.c
index 464a9e10..f99e5032 100644
--- a/plugins/check_ntp_peer.c
+++ b/plugins/check_ntp_peer.c
@@ -1,88 +1,88 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring check_ntp_peer plugin 3 * Monitoring check_ntp_peer plugin
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 2006 Sean Finney <seanius@seanius.net> 6 * Copyright (c) 2006 Sean Finney <seanius@seanius.net>
7* Copyright (c) 2006-2008 Monitoring Plugins Development Team 7 * Copyright (c) 2006-2024 Monitoring Plugins Development Team
8* 8 *
9* Description: 9 * Description:
10* 10 *
11* This file contains the check_ntp_peer plugin 11 * This file contains the check_ntp_peer plugin
12* 12 *
13* This plugin checks an NTP server independent of any commandline 13 * This plugin checks an NTP server independent of any commandline
14* programs or external libraries. 14 * programs or external libraries.
15* 15 *
16* Use this plugin to check the health of an NTP server. It supports 16 * Use this plugin to check the health of an NTP server. It supports
17* checking the offset with the sync peer, the jitter and stratum. This 17 * checking the offset with the sync peer, the jitter and stratum. This
18* plugin will not check the clock offset between the local host and NTP 18 * plugin will not check the clock offset between the local host and NTP
19* server; please use check_ntp_time for that purpose. 19 * server; please use check_ntp_time for that purpose.
20* 20 *
21* 21 *
22* This program is free software: you can redistribute it and/or modify 22 * This program is free software: you can redistribute it and/or modify
23* it under the terms of the GNU General Public License as published by 23 * it under the terms of the GNU General Public License as published by
24* the Free Software Foundation, either version 3 of the License, or 24 * the Free Software Foundation, either version 3 of the License, or
25* (at your option) any later version. 25 * (at your option) any later version.
26* 26 *
27* This program is distributed in the hope that it will be useful, 27 * This program is distributed in the hope that it will be useful,
28* but WITHOUT ANY WARRANTY; without even the implied warranty of 28 * but WITHOUT ANY WARRANTY; without even the implied warranty of
29* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 29 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30* GNU General Public License for more details. 30 * GNU General Public License for more details.
31* 31 *
32* You should have received a copy of the GNU General Public License 32 * You should have received a copy of the GNU General Public License
33* along with this program. If not, see <http://www.gnu.org/licenses/>. 33 * along with this program. If not, see <http://www.gnu.org/licenses/>.
34* 34 *
35* 35 *
36*****************************************************************************/ 36 *****************************************************************************/
37 37
38const char *progname = "check_ntp_peer"; 38const char *progname = "check_ntp_peer";
39const char *copyright = "2006-2008"; 39const char *copyright = "2006-2024";
40const char *email = "devel@monitoring-plugins.org"; 40const char *email = "devel@monitoring-plugins.org";
41 41
42#include "common.h" 42#include "common.h"
43#include "netutils.h" 43#include "netutils.h"
44#include "utils.h" 44#include "utils.h"
45 45
46static char *server_address=NULL; 46static char *server_address = NULL;
47static int port=123; 47static int port = 123;
48static int verbose=0; 48static int verbose = 0;
49static bool quiet = false; 49static bool quiet = false;
50static char *owarn="60"; 50static char *owarn = "60";
51static char *ocrit="120"; 51static char *ocrit = "120";
52static bool do_stratum = false; 52static bool do_stratum = false;
53static char *swarn="-1:16"; 53static char *swarn = "-1:16";
54static char *scrit="-1:16"; 54static char *scrit = "-1:16";
55static bool do_jitter = false; 55static bool do_jitter = false;
56static char *jwarn="-1:5000"; 56static char *jwarn = "-1:5000";
57static char *jcrit="-1:10000"; 57static char *jcrit = "-1:10000";
58static bool do_truechimers = false; 58static bool do_truechimers = false;
59static char *twarn="0:"; 59static char *twarn = "0:";
60static char *tcrit="0:"; 60static char *tcrit = "0:";
61static bool syncsource_found = false; 61static bool syncsource_found = false;
62static bool li_alarm = false; 62static bool li_alarm = false;
63 63
64int process_arguments (int, char **); 64static int process_arguments(int /*argc*/, char ** /*argv*/);
65thresholds *offset_thresholds = NULL; 65static thresholds *offset_thresholds = NULL;
66thresholds *jitter_thresholds = NULL; 66static thresholds *jitter_thresholds = NULL;
67thresholds *stratum_thresholds = NULL; 67static thresholds *stratum_thresholds = NULL;
68thresholds *truechimer_thresholds = NULL; 68static thresholds *truechimer_thresholds = NULL;
69void print_help (void); 69static void print_help(void);
70void print_usage (void); 70void print_usage(void);
71 71
72/* max size of control message data */ 72/* max size of control message data */
73#define MAX_CM_SIZE 468 73#define MAX_CM_SIZE 468
74 74
75/* this structure holds everything in an ntp control message as per rfc1305 */ 75/* this structure holds everything in an ntp control message as per rfc1305 */
76typedef struct { 76typedef struct {
77 uint8_t flags; /* byte with leapindicator,vers,mode. see macros */ 77 uint8_t flags; /* byte with leapindicator,vers,mode. see macros */
78 uint8_t op; /* R,E,M bits and Opcode */ 78 uint8_t op; /* R,E,M bits and Opcode */
79 uint16_t seq; /* Packet sequence */ 79 uint16_t seq; /* Packet sequence */
80 uint16_t status; /* Clock status */ 80 uint16_t status; /* Clock status */
81 uint16_t assoc; /* Association */ 81 uint16_t assoc; /* Association */
82 uint16_t offset; /* Similar to TCP sequence # */ 82 uint16_t offset; /* Similar to TCP sequence # */
83 uint16_t count; /* # bytes of data */ 83 uint16_t count; /* # bytes of data */
84 char data[MAX_CM_SIZE]; /* ASCII data of the request */ 84 char data[MAX_CM_SIZE]; /* ASCII data of the request */
85 /* NB: not necessarily NULL terminated! */ 85 /* NB: not necessarily NULL terminated! */
86} ntp_control_message; 86} ntp_control_message;
87 87
88/* this is an association/status-word pair found in control packet responses */ 88/* this is an association/status-word pair found in control packet responses */
@@ -93,82 +93,96 @@ typedef struct {
93 93
94/* bits 1,2 are the leap indicator */ 94/* bits 1,2 are the leap indicator */
95#define LI_MASK 0xc0 95#define LI_MASK 0xc0
96#define LI(x) ((x&LI_MASK)>>6) 96#define LI(x) ((x & LI_MASK) >> 6)
97#define LI_SET(x,y) do{ x |= ((y<<6)&LI_MASK); }while(0) 97#define LI_SET(x, y) \
98 do { \
99 x |= ((y << 6) & LI_MASK); \
100 } while (0)
98/* and these are the values of the leap indicator */ 101/* and these are the values of the leap indicator */
99#define LI_NOWARNING 0x00 102#define LI_NOWARNING 0x00
100#define LI_EXTRASEC 0x01 103#define LI_EXTRASEC 0x01
101#define LI_MISSINGSEC 0x02 104#define LI_MISSINGSEC 0x02
102#define LI_ALARM 0x03 105#define LI_ALARM 0x03
103/* bits 3,4,5 are the ntp version */ 106/* bits 3,4,5 are the ntp version */
104#define VN_MASK 0x38 107#define VN_MASK 0x38
105#define VN(x) ((x&VN_MASK)>>3) 108#define VN(x) ((x & VN_MASK) >> 3)
106#define VN_SET(x,y) do{ x |= ((y<<3)&VN_MASK); }while(0) 109#define VN_SET(x, y) \
110 do { \
111 x |= ((y << 3) & VN_MASK); \
112 } while (0)
107#define VN_RESERVED 0x02 113#define VN_RESERVED 0x02
108/* bits 6,7,8 are the ntp mode */ 114/* bits 6,7,8 are the ntp mode */
109#define MODE_MASK 0x07 115#define MODE_MASK 0x07
110#define MODE(x) (x&MODE_MASK) 116#define MODE(x) (x & MODE_MASK)
111#define MODE_SET(x,y) do{ x |= (y&MODE_MASK); }while(0) 117#define MODE_SET(x, y) \
118 do { \
119 x |= (y & MODE_MASK); \
120 } while (0)
112/* here are some values */ 121/* here are some values */
113#define MODE_CLIENT 0x03 122#define MODE_CLIENT 0x03
114#define MODE_CONTROLMSG 0x06 123#define MODE_CONTROLMSG 0x06
115/* In control message, bits 8-10 are R,E,M bits */ 124/* In control message, bits 8-10 are R,E,M bits */
116#define REM_MASK 0xe0 125#define REM_MASK 0xe0
117#define REM_RESP 0x80 126#define REM_RESP 0x80
118#define REM_ERROR 0x40 127#define REM_ERROR 0x40
119#define REM_MORE 0x20 128#define REM_MORE 0x20
120/* In control message, bits 11 - 15 are opcode */ 129/* In control message, bits 11 - 15 are opcode */
121#define OP_MASK 0x1f 130#define OP_MASK 0x1f
122#define OP_SET(x,y) do{ x |= (y&OP_MASK); }while(0) 131#define OP_SET(x, y) \
132 do { \
133 x |= (y & OP_MASK); \
134 } while (0)
123#define OP_READSTAT 0x01 135#define OP_READSTAT 0x01
124#define OP_READVAR 0x02 136#define OP_READVAR 0x02
125/* In peer status bytes, bits 6,7,8 determine clock selection status */ 137/* In peer status bytes, bits 6,7,8 determine clock selection status */
126#define PEER_SEL(x) ((ntohs(x)>>8)&0x07) 138#define PEER_SEL(x) ((ntohs(x) >> 8) & 0x07)
127#define PEER_TRUECHIMER 0x02 139#define PEER_TRUECHIMER 0x02
128#define PEER_INCLUDED 0x04 140#define PEER_INCLUDED 0x04
129#define PEER_SYNCSOURCE 0x06 141#define PEER_SYNCSOURCE 0x06
130 142
131/* NTP control message header is 12 bytes, plus any data in the data 143/* NTP control message header is 12 bytes, plus any data in the data
132 * field, plus null padding to the nearest 32-bit boundary per rfc. 144 * field, plus null padding to the nearest 32-bit boundary per rfc.
133 */ 145 */
134#define SIZEOF_NTPCM(m) (12+ntohs(m.count)+((ntohs(m.count)%4)?4-(ntohs(m.count)%4):0)) 146#define SIZEOF_NTPCM(m) (12 + ntohs(m.count) + ((ntohs(m.count) % 4) ? 4 - (ntohs(m.count) % 4) : 0))
135 147
136/* finally, a little helper or two for debugging: */ 148/* finally, a little helper or two for debugging: */
137#define DBG(x) do{if(verbose>1){ x; }}while(0); 149#define DBG(x) \
138#define PRINTSOCKADDR(x) \ 150 do { \
139 do{ \ 151 if (verbose > 1) { \
140 printf("%u.%u.%u.%u", (x>>24)&0xff, (x>>16)&0xff, (x>>8)&0xff, x&0xff);\ 152 x; \
141 }while(0); 153 } \
142 154 } while (0);
143void print_ntp_control_message(const ntp_control_message *p){ 155#define PRINTSOCKADDR(x) \
144 int i=0, numpeers=0; 156 do { \
145 const ntp_assoc_status_pair *peer=NULL; 157 printf("%u.%u.%u.%u", (x >> 24) & 0xff, (x >> 16) & 0xff, (x >> 8) & 0xff, x & 0xff); \
146 158 } while (0);
159
160void print_ntp_control_message(const ntp_control_message *p) {
147 printf("control packet contents:\n"); 161 printf("control packet contents:\n");
148 printf("\tflags: 0x%.2x , 0x%.2x\n", p->flags, p->op); 162 printf("\tflags: 0x%.2x , 0x%.2x\n", p->flags, p->op);
149 printf("\t li=%d (0x%.2x)\n", LI(p->flags), p->flags&LI_MASK); 163 printf("\t li=%d (0x%.2x)\n", LI(p->flags), p->flags & LI_MASK);
150 printf("\t vn=%d (0x%.2x)\n", VN(p->flags), p->flags&VN_MASK); 164 printf("\t vn=%d (0x%.2x)\n", VN(p->flags), p->flags & VN_MASK);
151 printf("\t mode=%d (0x%.2x)\n", MODE(p->flags), p->flags&MODE_MASK); 165 printf("\t mode=%d (0x%.2x)\n", MODE(p->flags), p->flags & MODE_MASK);
152 printf("\t response=%d (0x%.2x)\n", (p->op&REM_RESP)>0, p->op&REM_RESP); 166 printf("\t response=%d (0x%.2x)\n", (p->op & REM_RESP) > 0, p->op & REM_RESP);
153 printf("\t more=%d (0x%.2x)\n", (p->op&REM_MORE)>0, p->op&REM_MORE); 167 printf("\t more=%d (0x%.2x)\n", (p->op & REM_MORE) > 0, p->op & REM_MORE);
154 printf("\t error=%d (0x%.2x)\n", (p->op&REM_ERROR)>0, p->op&REM_ERROR); 168 printf("\t error=%d (0x%.2x)\n", (p->op & REM_ERROR) > 0, p->op & REM_ERROR);
155 printf("\t op=%d (0x%.2x)\n", p->op&OP_MASK, p->op&OP_MASK); 169 printf("\t op=%d (0x%.2x)\n", p->op & OP_MASK, p->op & OP_MASK);
156 printf("\tsequence: %d (0x%.2x)\n", ntohs(p->seq), ntohs(p->seq)); 170 printf("\tsequence: %d (0x%.2x)\n", ntohs(p->seq), ntohs(p->seq));
157 printf("\tstatus: %d (0x%.2x)\n", ntohs(p->status), ntohs(p->status)); 171 printf("\tstatus: %d (0x%.2x)\n", ntohs(p->status), ntohs(p->status));
158 printf("\tassoc: %d (0x%.2x)\n", ntohs(p->assoc), ntohs(p->assoc)); 172 printf("\tassoc: %d (0x%.2x)\n", ntohs(p->assoc), ntohs(p->assoc));
159 printf("\toffset: %d (0x%.2x)\n", ntohs(p->offset), ntohs(p->offset)); 173 printf("\toffset: %d (0x%.2x)\n", ntohs(p->offset), ntohs(p->offset));
160 printf("\tcount: %d (0x%.2x)\n", ntohs(p->count), ntohs(p->count)); 174 printf("\tcount: %d (0x%.2x)\n", ntohs(p->count), ntohs(p->count));
161 numpeers=ntohs(p->count)/(sizeof(ntp_assoc_status_pair)); 175
162 if(p->op&REM_RESP && p->op&OP_READSTAT){ 176 int numpeers = ntohs(p->count) / (sizeof(ntp_assoc_status_pair));
163 peer=(ntp_assoc_status_pair*)p->data; 177 if (p->op & REM_RESP && p->op & OP_READSTAT) {
164 for(i=0;i<numpeers;i++){ 178 const ntp_assoc_status_pair *peer = (ntp_assoc_status_pair *)p->data;
165 printf("\tpeer id %.2x status %.2x", 179 for (int i = 0; i < numpeers; i++) {
166 ntohs(peer[i].assoc), ntohs(peer[i].status)); 180 printf("\tpeer id %.2x status %.2x", ntohs(peer[i].assoc), ntohs(peer[i].status));
167 if(PEER_SEL(peer[i].status) >= PEER_SYNCSOURCE){ 181 if (PEER_SEL(peer[i].status) >= PEER_SYNCSOURCE) {
168 printf(" <-- current sync source"); 182 printf(" <-- current sync source");
169 } else if(PEER_SEL(peer[i].status) >= PEER_INCLUDED){ 183 } else if (PEER_SEL(peer[i].status) >= PEER_INCLUDED) {
170 printf(" <-- current sync candidate"); 184 printf(" <-- current sync candidate");
171 } else if(PEER_SEL(peer[i].status) >= PEER_TRUECHIMER){ 185 } else if (PEER_SEL(peer[i].status) >= PEER_TRUECHIMER) {
172 printf(" <-- outlyer, but truechimer"); 186 printf(" <-- outlyer, but truechimer");
173 } 187 }
174 printf("\n"); 188 printf("\n");
@@ -176,8 +190,7 @@ void print_ntp_control_message(const ntp_control_message *p){
176 } 190 }
177} 191}
178 192
179void 193void setup_control_request(ntp_control_message *p, uint8_t opcode, uint16_t seq) {
180setup_control_request(ntp_control_message *p, uint8_t opcode, uint16_t seq){
181 memset(p, 0, sizeof(ntp_control_message)); 194 memset(p, 0, sizeof(ntp_control_message));
182 LI_SET(p->flags, LI_NOWARNING); 195 LI_SET(p->flags, LI_NOWARNING);
183 VN_SET(p->flags, VN_RESERVED); 196 VN_SET(p->flags, VN_RESERVED);
@@ -198,19 +211,7 @@ setup_control_request(ntp_control_message *p, uint8_t opcode, uint16_t seq){
198 * status is pretty much useless as syncsource_found is a global variable 211 * status is pretty much useless as syncsource_found is a global variable
199 * used later in main to check is the server was synchronized. It works 212 * used later in main to check is the server was synchronized. It works
200 * so I left it alone */ 213 * so I left it alone */
201int ntp_request(double *offset, int *offset_result, double *jitter, int *stratum, int *num_truechimers){ 214int ntp_request(double *offset, int *offset_result, double *jitter, int *stratum, int *num_truechimers) {
202 int conn=-1, i, npeers=0, num_candidates=0;
203 double tmp_offset = 0;
204 int min_peer_sel=PEER_INCLUDED;
205 int peers_size=0, peer_offset=0;
206 int status;
207 ntp_assoc_status_pair *peers=NULL;
208 ntp_control_message req;
209 const char *getvar = "stratum,offset,jitter";
210 char *data, *value, *nptr;
211 void *tmp;
212
213 status = STATE_OK;
214 *offset_result = STATE_UNKNOWN; 215 *offset_result = STATE_UNKNOWN;
215 *jitter = *stratum = -1; 216 *jitter = *stratum = -1;
216 *num_truechimers = 0; 217 *num_truechimers = 0;
@@ -231,11 +232,20 @@ int ntp_request(double *offset, int *offset_result, double *jitter, int *stratum
231 * 4) Extract the offset, jitter and stratum value from the data[] 232 * 4) Extract the offset, jitter and stratum value from the data[]
232 * (it's ASCII) 233 * (it's ASCII)
233 */ 234 */
235 int min_peer_sel = PEER_INCLUDED;
236 int num_candidates = 0;
237 void *tmp;
238 ntp_assoc_status_pair *peers = NULL;
239 int peer_offset = 0;
240 int peers_size = 0;
241 int npeers = 0;
242 int conn = -1;
234 my_udp_connect(server_address, port, &conn); 243 my_udp_connect(server_address, port, &conn);
235 244
236 /* keep sending requests until the server stops setting the 245 /* keep sending requests until the server stops setting the
237 * REM_MORE bit, though usually this is only 1 packet. */ 246 * REM_MORE bit, though usually this is only 1 packet. */
238 do{ 247 ntp_control_message req;
248 do {
239 setup_control_request(&req, OP_READSTAT, 1); 249 setup_control_request(&req, OP_READSTAT, 1);
240 DBG(printf("sending READSTAT request")); 250 DBG(printf("sending READSTAT request"));
241 write(conn, &req, SIZEOF_NTPCM(req)); 251 write(conn, &req, SIZEOF_NTPCM(req));
@@ -243,63 +253,73 @@ int ntp_request(double *offset, int *offset_result, double *jitter, int *stratum
243 253
244 do { 254 do {
245 /* Attempt to read the largest size packet possible */ 255 /* Attempt to read the largest size packet possible */
246 req.count=htons(MAX_CM_SIZE); 256 req.count = htons(MAX_CM_SIZE);
247 DBG(printf("receiving READSTAT response")) 257 DBG(printf("receiving READSTAT response"))
248 if(read(conn, &req, SIZEOF_NTPCM(req)) == -1) 258 if (read(conn, &req, SIZEOF_NTPCM(req)) == -1)
249 die(STATE_CRITICAL, "NTP CRITICAL: No response from NTP server\n"); 259 die(STATE_CRITICAL, "NTP CRITICAL: No response from NTP server\n");
250 DBG(print_ntp_control_message(&req)); 260 DBG(print_ntp_control_message(&req));
251 /* discard obviously invalid packets */ 261 /* discard obviously invalid packets */
252 if (ntohs(req.count) > MAX_CM_SIZE) 262 if (ntohs(req.count) > MAX_CM_SIZE)
253 die(STATE_CRITICAL, "NTP CRITICAL: Invalid packet received from NTP server\n"); 263 die(STATE_CRITICAL, "NTP CRITICAL: Invalid packet received from NTP server\n");
254 } while (!(req.op&OP_READSTAT && ntohs(req.seq) == 1)); 264 } while (!(req.op & OP_READSTAT && ntohs(req.seq) == 1));
255 265
256 if (LI(req.flags) == LI_ALARM) li_alarm = true; 266 if (LI(req.flags) == LI_ALARM)
267 li_alarm = true;
257 /* Each peer identifier is 4 bytes in the data section, which 268 /* Each peer identifier is 4 bytes in the data section, which
258 * we represent as a ntp_assoc_status_pair datatype. 269 * we represent as a ntp_assoc_status_pair datatype.
259 */ 270 */
260 peers_size+=ntohs(req.count); 271 peers_size += ntohs(req.count);
261 if((tmp=realloc(peers, peers_size)) == NULL) 272 if ((tmp = realloc(peers, peers_size)) == NULL)
262 free(peers), die(STATE_UNKNOWN, "can not (re)allocate 'peers' buffer\n"); 273 free(peers), die(STATE_UNKNOWN, "can not (re)allocate 'peers' buffer\n");
263 peers=tmp; 274 peers = tmp;
264 memcpy((void*)((ptrdiff_t)peers+peer_offset), (void*)req.data, ntohs(req.count)); 275 memcpy((void *)((ptrdiff_t)peers + peer_offset), (void *)req.data, ntohs(req.count));
265 npeers=peers_size/sizeof(ntp_assoc_status_pair); 276 npeers = peers_size / sizeof(ntp_assoc_status_pair);
266 peer_offset+=ntohs(req.count); 277 peer_offset += ntohs(req.count);
267 } while(req.op&REM_MORE); 278 } while (req.op & REM_MORE);
268 279
269 /* first, let's find out if we have a sync source, or if there are 280 /* first, let's find out if we have a sync source, or if there are
270 * at least some candidates. In the latter case we'll issue 281 * at least some candidates. In the latter case we'll issue
271 * a warning but go ahead with the check on them. */ 282 * a warning but go ahead with the check on them. */
272 for (i = 0; i < npeers; i++){ 283 for (int i = 0; i < npeers; i++) {
273 if(PEER_SEL(peers[i].status) >= PEER_TRUECHIMER){ 284 if (PEER_SEL(peers[i].status) >= PEER_TRUECHIMER) {
274 (*num_truechimers)++; 285 (*num_truechimers)++;
275 if(PEER_SEL(peers[i].status) >= PEER_INCLUDED){ 286 if (PEER_SEL(peers[i].status) >= PEER_INCLUDED) {
276 num_candidates++; 287 num_candidates++;
277 if(PEER_SEL(peers[i].status) >= PEER_SYNCSOURCE){ 288 if (PEER_SEL(peers[i].status) >= PEER_SYNCSOURCE) {
278 syncsource_found = true; 289 syncsource_found = true;
279 min_peer_sel=PEER_SYNCSOURCE; 290 min_peer_sel = PEER_SYNCSOURCE;
280 } 291 }
281 } 292 }
282 } 293 }
283 } 294 }
284 if(verbose) printf("%d candidate peers available\n", num_candidates); 295
285 if(verbose && syncsource_found) printf("synchronization source found\n"); 296 if (verbose)
286 if(! syncsource_found){ 297 printf("%d candidate peers available\n", num_candidates);
298 if (verbose && syncsource_found)
299 printf("synchronization source found\n");
300
301 int status = STATE_OK;
302 if (!syncsource_found) {
287 status = STATE_WARNING; 303 status = STATE_WARNING;
288 if(verbose) printf("warning: no synchronization source found\n"); 304 if (verbose)
305 printf("warning: no synchronization source found\n");
289 } 306 }
290 if(li_alarm){ 307 if (li_alarm) {
291 status = STATE_WARNING; 308 status = STATE_WARNING;
292 if(verbose) printf("warning: LI_ALARM bit is set\n"); 309 if (verbose)
310 printf("warning: LI_ALARM bit is set\n");
293 } 311 }
294 312
295 313 const char *getvar = "stratum,offset,jitter";
296 for (i = 0; i < npeers; i++){ 314 char *data;
315 for (int i = 0; i < npeers; i++) {
297 /* Only query this server if it is the current sync source */ 316 /* Only query this server if it is the current sync source */
298 /* If there's no sync.peer, query all candidates and use the best one */ 317 /* If there's no sync.peer, query all candidates and use the best one */
299 if (PEER_SEL(peers[i].status) >= min_peer_sel){ 318 if (PEER_SEL(peers[i].status) >= min_peer_sel) {
300 if(verbose) printf("Getting offset, jitter and stratum for peer %.2x\n", ntohs(peers[i].assoc)); 319 if (verbose)
320 printf("Getting offset, jitter and stratum for peer %.2x\n", ntohs(peers[i].assoc));
301 xasprintf(&data, ""); 321 xasprintf(&data, "");
302 do{ 322 do {
303 setup_control_request(&req, OP_READVAR, 2); 323 setup_control_request(&req, OP_READVAR, 2);
304 req.assoc = peers[i].assoc; 324 req.assoc = peers[i].assoc;
305 /* Putting the wanted variable names in the request 325 /* Putting the wanted variable names in the request
@@ -309,7 +329,7 @@ int ntp_request(double *offset, int *offset_result, double *jitter, int *stratum
309 */ 329 */
310 /* Older servers doesn't know what jitter is, so if we get an 330 /* Older servers doesn't know what jitter is, so if we get an
311 * error on the first pass we redo it with "dispersion" */ 331 * error on the first pass we redo it with "dispersion" */
312 strncpy(req.data, getvar, MAX_CM_SIZE-1); 332 strncpy(req.data, getvar, MAX_CM_SIZE - 1);
313 req.count = htons(strlen(getvar)); 333 req.count = htons(strlen(getvar));
314 DBG(printf("sending READVAR request...\n")); 334 DBG(printf("sending READVAR request...\n"));
315 write(conn, &req, SIZEOF_NTPCM(req)); 335 write(conn, &req, SIZEOF_NTPCM(req));
@@ -320,44 +340,53 @@ int ntp_request(double *offset, int *offset_result, double *jitter, int *stratum
320 DBG(printf("receiving READVAR response...\n")); 340 DBG(printf("receiving READVAR response...\n"));
321 read(conn, &req, SIZEOF_NTPCM(req)); 341 read(conn, &req, SIZEOF_NTPCM(req));
322 DBG(print_ntp_control_message(&req)); 342 DBG(print_ntp_control_message(&req));
323 } while (!(req.op&OP_READVAR && ntohs(req.seq) == 2)); 343 } while (!(req.op & OP_READVAR && ntohs(req.seq) == 2));
324 344
325 if(!(req.op&REM_ERROR)) 345 if (!(req.op & REM_ERROR))
326 xasprintf(&data, "%s%s", data, req.data); 346 xasprintf(&data, "%s%s", data, req.data);
327 } while(req.op&REM_MORE); 347 } while (req.op & REM_MORE);
328 348
329 if(req.op&REM_ERROR) { 349 if (req.op & REM_ERROR) {
330 if(strstr(getvar, "jitter")) { 350 if (strstr(getvar, "jitter")) {
331 if(verbose) printf("The command failed. This is usually caused by servers refusing the 'jitter'\nvariable. Restarting with 'dispersion'...\n"); 351 if (verbose)
352 printf("The command failed. This is usually caused by servers refusing the 'jitter'\nvariable. Restarting with "
353 "'dispersion'...\n");
332 getvar = "stratum,offset,dispersion"; 354 getvar = "stratum,offset,dispersion";
333 i--; 355 i--;
334 continue; 356 continue;
335 } else if(strlen(getvar)) { 357 }
336 if(verbose) printf("Server didn't like dispersion either; will retrieve everything\n"); 358 if (strlen(getvar)) {
359 if (verbose)
360 printf("Server didn't like dispersion either; will retrieve everything\n");
337 getvar = ""; 361 getvar = "";
338 i--; 362 i--;
339 continue; 363 continue;
340 } 364 }
341 } 365 }
342 366
343 if(verbose > 1) 367 if (verbose > 1)
344 printf("Server responded: >>>%s<<<\n", data); 368 printf("Server responded: >>>%s<<<\n", data);
345 369
370 double tmp_offset = 0;
371 char *value;
372 char *nptr;
346 /* get the offset */ 373 /* get the offset */
347 if(verbose) 374 if (verbose)
348 printf("parsing offset from peer %.2x: ", ntohs(peers[i].assoc)); 375 printf("parsing offset from peer %.2x: ", ntohs(peers[i].assoc));
349 376
350 value = np_extract_ntpvar(data, "offset"); 377 value = np_extract_ntpvar(data, "offset");
351 nptr=NULL; 378 nptr = NULL;
352 /* Convert the value if we have one */ 379 /* Convert the value if we have one */
353 if(value != NULL) 380 if (value != NULL)
354 tmp_offset = strtod(value, &nptr) / 1000; 381 tmp_offset = strtod(value, &nptr) / 1000;
355 /* If value is null or no conversion was performed */ 382 /* If value is null or no conversion was performed */
356 if(value == NULL || value==nptr) { 383 if (value == NULL || value == nptr) {
357 if(verbose) printf("error: unable to read server offset response.\n"); 384 if (verbose)
385 printf("error: unable to read server offset response.\n");
358 } else { 386 } else {
359 if(verbose) printf("%.10g\n", tmp_offset); 387 if (verbose)
360 if(*offset_result == STATE_UNKNOWN || fabs(tmp_offset) < fabs(*offset)) { 388 printf("%.10g\n", tmp_offset);
389 if (*offset_result == STATE_UNKNOWN || fabs(tmp_offset) < fabs(*offset)) {
361 *offset = tmp_offset; 390 *offset = tmp_offset;
362 *offset_result = STATE_OK; 391 *offset_result = STATE_OK;
363 } else { 392 } else {
@@ -366,85 +395,75 @@ int ntp_request(double *offset, int *offset_result, double *jitter, int *stratum
366 } 395 }
367 } 396 }
368 397
369 if(do_jitter) { 398 if (do_jitter) {
370 /* get the jitter */ 399 /* get the jitter */
371 if(verbose) { 400 if (verbose) {
372 printf("parsing %s from peer %.2x: ", strstr(getvar, "dispersion") != NULL ? "dispersion" : "jitter", ntohs(peers[i].assoc)); 401 printf("parsing %s from peer %.2x: ", strstr(getvar, "dispersion") != NULL ? "dispersion" : "jitter",
402 ntohs(peers[i].assoc));
373 } 403 }
374 value = np_extract_ntpvar(data, strstr(getvar, "dispersion") != NULL ? "dispersion" : "jitter"); 404 value = np_extract_ntpvar(data, strstr(getvar, "dispersion") != NULL ? "dispersion" : "jitter");
375 nptr=NULL; 405 nptr = NULL;
376 /* Convert the value if we have one */ 406 /* Convert the value if we have one */
377 if(value != NULL) 407 if (value != NULL)
378 *jitter = strtod(value, &nptr); 408 *jitter = strtod(value, &nptr);
379 /* If value is null or no conversion was performed */ 409 /* If value is null or no conversion was performed */
380 if(value == NULL || value==nptr) { 410 if (value == NULL || value == nptr) {
381 if(verbose) printf("error: unable to read server jitter/dispersion response.\n"); 411 if (verbose)
412 printf("error: unable to read server jitter/dispersion response.\n");
382 *jitter = -1; 413 *jitter = -1;
383 } else if(verbose) { 414 } else if (verbose) {
384 printf("%.10g\n", *jitter); 415 printf("%.10g\n", *jitter);
385 } 416 }
386 } 417 }
387 418
388 if(do_stratum) { 419 if (do_stratum) {
389 /* get the stratum */ 420 /* get the stratum */
390 if(verbose) { 421 if (verbose) {
391 printf("parsing stratum from peer %.2x: ", ntohs(peers[i].assoc)); 422 printf("parsing stratum from peer %.2x: ", ntohs(peers[i].assoc));
392 } 423 }
393 value = np_extract_ntpvar(data, "stratum"); 424 value = np_extract_ntpvar(data, "stratum");
394 nptr=NULL; 425 nptr = NULL;
395 /* Convert the value if we have one */ 426 /* Convert the value if we have one */
396 if(value != NULL) 427 if (value != NULL)
397 *stratum = strtol(value, &nptr, 10); 428 *stratum = strtol(value, &nptr, 10);
398 if(value == NULL || value==nptr) { 429 if (value == NULL || value == nptr) {
399 if(verbose) printf("error: unable to read server stratum response.\n"); 430 if (verbose)
431 printf("error: unable to read server stratum response.\n");
400 *stratum = -1; 432 *stratum = -1;
401 } else { 433 } else {
402 if(verbose) printf("%i\n", *stratum); 434 if (verbose)
435 printf("%i\n", *stratum);
403 } 436 }
404 } 437 }
405 } /* if (PEER_SEL(peers[i].status) >= min_peer_sel) */ 438 } /* if (PEER_SEL(peers[i].status) >= min_peer_sel) */
406 } /* for (i = 0; i < npeers; i++) */ 439 } /* for (i = 0; i < npeers; i++) */
407 440
408 close(conn); 441 close(conn);
409 if(peers!=NULL) free(peers); 442 if (peers != NULL)
443 free(peers);
410 444
411 return status; 445 return status;
412} 446}
413 447
414int process_arguments(int argc, char **argv){ 448int process_arguments(int argc, char **argv) {
415 int c;
416 int option=0;
417 static struct option longopts[] = { 449 static struct option longopts[] = {
418 {"version", no_argument, 0, 'V'}, 450 {"version", no_argument, 0, 'V'}, {"help", no_argument, 0, 'h'}, {"verbose", no_argument, 0, 'v'},
419 {"help", no_argument, 0, 'h'}, 451 {"use-ipv4", no_argument, 0, '4'}, {"use-ipv6", no_argument, 0, '6'}, {"quiet", no_argument, 0, 'q'},
420 {"verbose", no_argument, 0, 'v'}, 452 {"warning", required_argument, 0, 'w'}, {"critical", required_argument, 0, 'c'}, {"swarn", required_argument, 0, 'W'},
421 {"use-ipv4", no_argument, 0, '4'}, 453 {"scrit", required_argument, 0, 'C'}, {"jwarn", required_argument, 0, 'j'}, {"jcrit", required_argument, 0, 'k'},
422 {"use-ipv6", no_argument, 0, '6'}, 454 {"twarn", required_argument, 0, 'm'}, {"tcrit", required_argument, 0, 'n'}, {"timeout", required_argument, 0, 't'},
423 {"quiet", no_argument, 0, 'q'}, 455 {"hostname", required_argument, 0, 'H'}, {"port", required_argument, 0, 'p'}, {0, 0, 0, 0}};
424 {"warning", required_argument, 0, 'w'},
425 {"critical", required_argument, 0, 'c'},
426 {"swarn", required_argument, 0, 'W'},
427 {"scrit", required_argument, 0, 'C'},
428 {"jwarn", required_argument, 0, 'j'},
429 {"jcrit", required_argument, 0, 'k'},
430 {"twarn", required_argument, 0, 'm'},
431 {"tcrit", required_argument, 0, 'n'},
432 {"timeout", required_argument, 0, 't'},
433 {"hostname", required_argument, 0, 'H'},
434 {"port", required_argument, 0, 'p'},
435 {0, 0, 0, 0}
436 };
437
438 456
439 if (argc < 2) 457 if (argc < 2)
440 usage ("\n"); 458 usage("\n");
441 459
442 while (true) { 460 while (true) {
443 c = getopt_long (argc, argv, "Vhv46qw:c:W:C:j:k:m:n:t:H:p:", longopts, &option); 461 int option = 0;
444 if (c == -1 || c == EOF || c == 1) 462 int option_char = getopt_long(argc, argv, "Vhv46qw:c:W:C:j:k:m:n:t:H:p:", longopts, &option);
463 if (option_char == -1 || option_char == EOF || option_char == 1)
445 break; 464 break;
446 465
447 switch (c) { 466 switch (option_char) {
448 case 'h': 467 case 'h':
449 print_help(); 468 print_help();
450 exit(STATE_UNKNOWN); 469 exit(STATE_UNKNOWN);
@@ -490,15 +509,15 @@ int process_arguments(int argc, char **argv){
490 tcrit = optarg; 509 tcrit = optarg;
491 break; 510 break;
492 case 'H': 511 case 'H':
493 if(!is_host(optarg)) 512 if (!is_host(optarg))
494 usage2(_("Invalid hostname/address"), optarg); 513 usage2(_("Invalid hostname/address"), optarg);
495 server_address = strdup(optarg); 514 server_address = strdup(optarg);
496 break; 515 break;
497 case 'p': 516 case 'p':
498 port=atoi(optarg); 517 port = atoi(optarg);
499 break; 518 break;
500 case 't': 519 case 't':
501 socket_timeout=atoi(optarg); 520 socket_timeout = atoi(optarg);
502 break; 521 break;
503 case '4': 522 case '4':
504 address_family = AF_INET; 523 address_family = AF_INET;
@@ -507,69 +526,53 @@ int process_arguments(int argc, char **argv){
507#ifdef USE_IPV6 526#ifdef USE_IPV6
508 address_family = AF_INET6; 527 address_family = AF_INET6;
509#else 528#else
510 usage4 (_("IPv6 support not available")); 529 usage4(_("IPv6 support not available"));
511#endif 530#endif
512 break; 531 break;
513 case '?': 532 case '?':
514 /* print short usage statement if args not parsable */ 533 /* print short usage statement if args not parsable */
515 usage5 (); 534 usage5();
516 break; 535 break;
517 } 536 }
518 } 537 }
519 538
520 if(server_address == NULL){ 539 if (server_address == NULL) {
521 usage4(_("Hostname was not supplied")); 540 usage4(_("Hostname was not supplied"));
522 } 541 }
523 542
524 return 0; 543 return 0;
525} 544}
526 545
527char *perfd_offset (double offset) 546char *perfd_offset(double offset) {
528{ 547 return fperfdata("offset", offset, "s", true, offset_thresholds->warning->end, true, offset_thresholds->critical->end, false, 0, false,
529 return fperfdata ("offset", offset, "s", 548 0);
530 true, offset_thresholds->warning->end,
531 true, offset_thresholds->critical->end,
532 false, 0, false, 0);
533} 549}
534 550
535char *perfd_jitter (double jitter) 551char *perfd_jitter(double jitter) {
536{ 552 return fperfdata("jitter", jitter, "", do_jitter, jitter_thresholds->warning->end, do_jitter, jitter_thresholds->critical->end, true, 0,
537 return fperfdata ("jitter", jitter, "", 553 false, 0);
538 do_jitter, jitter_thresholds->warning->end,
539 do_jitter, jitter_thresholds->critical->end,
540 true, 0, false, 0);
541} 554}
542 555
543char *perfd_stratum (int stratum) 556char *perfd_stratum(int stratum) {
544{ 557 return perfdata("stratum", stratum, "", do_stratum, (int)stratum_thresholds->warning->end, do_stratum,
545 return perfdata ("stratum", stratum, "", 558 (int)stratum_thresholds->critical->end, true, 0, true, 16);
546 do_stratum, (int)stratum_thresholds->warning->end,
547 do_stratum, (int)stratum_thresholds->critical->end,
548 true, 0, true, 16);
549} 559}
550 560
551char *perfd_truechimers (int num_truechimers) 561char *perfd_truechimers(int num_truechimers) {
552{ 562 return perfdata("truechimers", num_truechimers, "", do_truechimers, (int)truechimer_thresholds->warning->end, do_truechimers,
553 return perfdata ("truechimers", num_truechimers, "", 563 (int)truechimer_thresholds->critical->end, true, 0, false, 0);
554 do_truechimers, (int)truechimer_thresholds->warning->end,
555 do_truechimers, (int)truechimer_thresholds->critical->end,
556 true, 0, false, 0);
557} 564}
558 565
559int main(int argc, char *argv[]){ 566int main(int argc, char *argv[]) {
560 int result, offset_result, stratum, num_truechimers; 567 setlocale(LC_ALL, "");
561 double offset=0, jitter=0; 568 bindtextdomain(PACKAGE, LOCALEDIR);
562 char *result_line, *perfdata_line; 569 textdomain(PACKAGE);
563
564 setlocale (LC_ALL, "");
565 bindtextdomain (PACKAGE, LOCALEDIR);
566 textdomain (PACKAGE);
567 570
568 /* Parse extra opts if any */ 571 /* Parse extra opts if any */
569 argv=np_extra_opts (&argc, argv, progname); 572 argv = np_extra_opts(&argc, argv, progname);
570 573
571 if (process_arguments (argc, argv) == ERROR) 574 if (process_arguments(argc, argv) == ERROR)
572 usage4 (_("Could not parse arguments")); 575 usage4(_("Could not parse arguments"));
573 576
574 set_thresholds(&offset_thresholds, owarn, ocrit); 577 set_thresholds(&offset_thresholds, owarn, ocrit);
575 set_thresholds(&jitter_thresholds, jwarn, jcrit); 578 set_thresholds(&jitter_thresholds, jwarn, jcrit);
@@ -577,15 +580,20 @@ int main(int argc, char *argv[]){
577 set_thresholds(&truechimer_thresholds, twarn, tcrit); 580 set_thresholds(&truechimer_thresholds, twarn, tcrit);
578 581
579 /* initialize alarm signal handling */ 582 /* initialize alarm signal handling */
580 signal (SIGALRM, socket_timeout_alarm_handler); 583 signal(SIGALRM, socket_timeout_alarm_handler);
581 584
582 /* set socket timeout */ 585 /* set socket timeout */
583 alarm (socket_timeout); 586 alarm(socket_timeout);
584 587
588 int offset_result;
589 int stratum;
590 int num_truechimers;
591 double offset = 0;
592 double jitter = 0;
585 /* This returns either OK or WARNING (See comment preceding ntp_request) */ 593 /* This returns either OK or WARNING (See comment preceding ntp_request) */
586 result = ntp_request(&offset, &offset_result, &jitter, &stratum, &num_truechimers); 594 int result = ntp_request(&offset, &offset_result, &jitter, &stratum, &num_truechimers);
587 595
588 if(offset_result == STATE_UNKNOWN) { 596 if (offset_result == STATE_UNKNOWN) {
589 /* if there's no sync peer (this overrides ntp_request output): */ 597 /* if there's no sync peer (this overrides ntp_request output): */
590 result = (quiet ? STATE_UNKNOWN : STATE_CRITICAL); 598 result = (quiet ? STATE_UNKNOWN : STATE_CRITICAL);
591 } else { 599 } else {
@@ -597,50 +605,49 @@ int main(int argc, char *argv[]){
597 605
598 int oresult = result; 606 int oresult = result;
599 607
600
601 int tresult = STATE_UNKNOWN; 608 int tresult = STATE_UNKNOWN;
602 609
603 if(do_truechimers) { 610 if (do_truechimers) {
604 tresult = get_status(num_truechimers, truechimer_thresholds); 611 tresult = get_status(num_truechimers, truechimer_thresholds);
605 result = max_state_alt(result, tresult); 612 result = max_state_alt(result, tresult);
606 } 613 }
607 614
608
609 int sresult = STATE_UNKNOWN; 615 int sresult = STATE_UNKNOWN;
610 616
611 if(do_stratum) { 617 if (do_stratum) {
612 sresult = get_status(stratum, stratum_thresholds); 618 sresult = get_status(stratum, stratum_thresholds);
613 result = max_state_alt(result, sresult); 619 result = max_state_alt(result, sresult);
614 } 620 }
615 621
616
617 int jresult = STATE_UNKNOWN; 622 int jresult = STATE_UNKNOWN;
618 623
619 if(do_jitter) { 624 if (do_jitter) {
620 jresult = get_status(jitter, jitter_thresholds); 625 jresult = get_status(jitter, jitter_thresholds);
621 result = max_state_alt(result, jresult); 626 result = max_state_alt(result, jresult);
622 } 627 }
623 628
629 char *result_line;
624 switch (result) { 630 switch (result) {
625 case STATE_CRITICAL : 631 case STATE_CRITICAL:
626 xasprintf(&result_line, _("NTP CRITICAL:")); 632 xasprintf(&result_line, _("NTP CRITICAL:"));
627 break; 633 break;
628 case STATE_WARNING : 634 case STATE_WARNING:
629 xasprintf(&result_line, _("NTP WARNING:")); 635 xasprintf(&result_line, _("NTP WARNING:"));
630 break; 636 break;
631 case STATE_OK : 637 case STATE_OK:
632 xasprintf(&result_line, _("NTP OK:")); 638 xasprintf(&result_line, _("NTP OK:"));
633 break; 639 break;
634 default : 640 default:
635 xasprintf(&result_line, _("NTP UNKNOWN:")); 641 xasprintf(&result_line, _("NTP UNKNOWN:"));
636 break; 642 break;
637 } 643 }
638 if(!syncsource_found) 644 if (!syncsource_found)
639 xasprintf(&result_line, "%s %s,", result_line, _("Server not synchronized")); 645 xasprintf(&result_line, "%s %s,", result_line, _("Server not synchronized"));
640 else if(li_alarm) 646 else if (li_alarm)
641 xasprintf(&result_line, "%s %s,", result_line, _("Server has the LI_ALARM bit set")); 647 xasprintf(&result_line, "%s %s,", result_line, _("Server has the LI_ALARM bit set"));
642 648
643 if(offset_result == STATE_UNKNOWN){ 649 char *perfdata_line;
650 if (offset_result == STATE_UNKNOWN) {
644 xasprintf(&result_line, "%s %s", result_line, _("Offset unknown")); 651 xasprintf(&result_line, "%s %s", result_line, _("Offset unknown"));
645 xasprintf(&perfdata_line, ""); 652 xasprintf(&perfdata_line, "");
646 } else if (oresult == STATE_WARNING) { 653 } else if (oresult == STATE_WARNING) {
@@ -649,9 +656,9 @@ int main(int argc, char *argv[]){
649 xasprintf(&result_line, "%s %s %.10g secs (CRITICAL)", result_line, _("Offset"), offset); 656 xasprintf(&result_line, "%s %s %.10g secs (CRITICAL)", result_line, _("Offset"), offset);
650 } else { 657 } else {
651 xasprintf(&result_line, "%s %s %.10g secs", result_line, _("Offset"), offset); 658 xasprintf(&result_line, "%s %s %.10g secs", result_line, _("Offset"), offset);
652 } 659 }
653 xasprintf(&perfdata_line, "%s", perfd_offset(offset)); 660 xasprintf(&perfdata_line, "%s", perfd_offset(offset));
654 661
655 if (do_jitter) { 662 if (do_jitter) {
656 if (jresult == STATE_WARNING) { 663 if (jresult == STATE_WARNING) {
657 xasprintf(&result_line, "%s, jitter=%f (WARNING)", result_line, jitter); 664 xasprintf(&result_line, "%s, jitter=%f (WARNING)", result_line, jitter);
@@ -684,45 +691,46 @@ int main(int argc, char *argv[]){
684 } 691 }
685 printf("%s|%s\n", result_line, perfdata_line); 692 printf("%s|%s\n", result_line, perfdata_line);
686 693
687 if(server_address!=NULL) free(server_address); 694 if (server_address != NULL)
695 free(server_address);
688 return result; 696 return result;
689} 697}
690 698
691void print_help(void){ 699void print_help(void) {
692 print_revision(progname, NP_VERSION); 700 print_revision(progname, NP_VERSION);
693 701
694 printf ("Copyright (c) 2006 Sean Finney\n"); 702 printf("Copyright (c) 2006 Sean Finney\n");
695 printf (COPYRIGHT, copyright, email); 703 printf(COPYRIGHT, copyright, email);
696 704
697 printf ("%s\n", _("This plugin checks the selected ntp server")); 705 printf("%s\n", _("This plugin checks the selected ntp server"));
698 706
699 printf ("\n\n"); 707 printf("\n\n");
700 708
701 print_usage(); 709 print_usage();
702 printf (UT_HELP_VRSN); 710 printf(UT_HELP_VRSN);
703 printf (UT_EXTRA_OPTS); 711 printf(UT_EXTRA_OPTS);
704 printf (UT_IPv46); 712 printf(UT_IPv46);
705 printf (UT_HOST_PORT, 'p', "123"); 713 printf(UT_HOST_PORT, 'p', "123");
706 printf (" %s\n", "-q, --quiet"); 714 printf(" %s\n", "-q, --quiet");
707 printf (" %s\n", _("Returns UNKNOWN instead of CRITICAL or WARNING if server isn't synchronized")); 715 printf(" %s\n", _("Returns UNKNOWN instead of CRITICAL or WARNING if server isn't synchronized"));
708 printf (" %s\n", "-w, --warning=THRESHOLD"); 716 printf(" %s\n", "-w, --warning=THRESHOLD");
709 printf (" %s\n", _("Offset to result in warning status (seconds)")); 717 printf(" %s\n", _("Offset to result in warning status (seconds)"));
710 printf (" %s\n", "-c, --critical=THRESHOLD"); 718 printf(" %s\n", "-c, --critical=THRESHOLD");
711 printf (" %s\n", _("Offset to result in critical status (seconds)")); 719 printf(" %s\n", _("Offset to result in critical status (seconds)"));
712 printf (" %s\n", "-W, --swarn=THRESHOLD"); 720 printf(" %s\n", "-W, --swarn=THRESHOLD");
713 printf (" %s\n", _("Warning threshold for stratum of server's synchronization peer")); 721 printf(" %s\n", _("Warning threshold for stratum of server's synchronization peer"));
714 printf (" %s\n", "-C, --scrit=THRESHOLD"); 722 printf(" %s\n", "-C, --scrit=THRESHOLD");
715 printf (" %s\n", _("Critical threshold for stratum of server's synchronization peer")); 723 printf(" %s\n", _("Critical threshold for stratum of server's synchronization peer"));
716 printf (" %s\n", "-j, --jwarn=THRESHOLD"); 724 printf(" %s\n", "-j, --jwarn=THRESHOLD");
717 printf (" %s\n", _("Warning threshold for jitter")); 725 printf(" %s\n", _("Warning threshold for jitter"));
718 printf (" %s\n", "-k, --jcrit=THRESHOLD"); 726 printf(" %s\n", "-k, --jcrit=THRESHOLD");
719 printf (" %s\n", _("Critical threshold for jitter")); 727 printf(" %s\n", _("Critical threshold for jitter"));
720 printf (" %s\n", "-m, --twarn=THRESHOLD"); 728 printf(" %s\n", "-m, --twarn=THRESHOLD");
721 printf (" %s\n", _("Warning threshold for number of usable time sources (\"truechimers\")")); 729 printf(" %s\n", _("Warning threshold for number of usable time sources (\"truechimers\")"));
722 printf (" %s\n", "-n, --tcrit=THRESHOLD"); 730 printf(" %s\n", "-n, --tcrit=THRESHOLD");
723 printf (" %s\n", _("Critical threshold for number of usable time sources (\"truechimers\")")); 731 printf(" %s\n", _("Critical threshold for number of usable time sources (\"truechimers\")"));
724 printf (UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); 732 printf(UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
725 printf (UT_VERBOSE); 733 printf(UT_VERBOSE);
726 734
727 printf("\n"); 735 printf("\n");
728 printf("%s\n", _("This plugin checks an NTP server independent of any commandline")); 736 printf("%s\n", _("This plugin checks an NTP server independent of any commandline"));
@@ -751,13 +759,11 @@ void print_help(void){
751 printf(" %s\n", _("Check only stratum:")); 759 printf(" %s\n", _("Check only stratum:"));
752 printf(" %s\n", ("./check_ntp_peer -H ntpserv -W 4 -C 6")); 760 printf(" %s\n", ("./check_ntp_peer -H ntpserv -W 4 -C 6"));
753 761
754 printf (UT_SUPPORT); 762 printf(UT_SUPPORT);
755} 763}
756 764
757void 765void print_usage(void) {
758print_usage(void) 766 printf("%s\n", _("Usage:"));
759{
760 printf ("%s\n", _("Usage:"));
761 printf(" %s -H <host> [-4|-6] [-w <warn>] [-c <crit>] [-W <warn>] [-C <crit>]\n", progname); 767 printf(" %s -H <host> [-4|-6] [-w <warn>] [-c <crit>] [-W <warn>] [-C <crit>]\n", progname);
762 printf(" [-j <warn>] [-k <crit>] [-v verbose]\n"); 768 printf(" [-j <warn>] [-k <crit>] [-v verbose]\n");
763} 769}
diff --git a/plugins/check_ntp_time.c b/plugins/check_ntp_time.c
index b2e16556..703b69df 100644
--- a/plugins/check_ntp_time.c
+++ b/plugins/check_ntp_time.c
@@ -1,63 +1,63 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring check_ntp_time plugin 3 * Monitoring check_ntp_time plugin
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 2006 Sean Finney <seanius@seanius.net> 6 * Copyright (c) 2006 Sean Finney <seanius@seanius.net>
7* Copyright (c) 2006-2008 Monitoring Plugins Development Team 7 * Copyright (c) 2006-2024 Monitoring Plugins Development Team
8* 8 *
9* Description: 9 * Description:
10* 10 *
11* This file contains the check_ntp_time plugin 11 * This file contains the check_ntp_time plugin
12* 12 *
13* This plugin checks the clock offset between the local host and a 13 * This plugin checks the clock offset between the local host and a
14* remote NTP server. It is independent of any commandline programs or 14 * remote NTP server. It is independent of any commandline programs or
15* external libraries. 15 * external libraries.
16* 16 *
17* If you'd rather want to monitor an NTP server, please use 17 * If you'd rather want to monitor an NTP server, please use
18* check_ntp_peer. 18 * check_ntp_peer.
19* 19 *
20* 20 *
21* This program is free software: you can redistribute it and/or modify 21 * This program is free software: you can redistribute it and/or modify
22* it under the terms of the GNU General Public License as published by 22 * it under the terms of the GNU General Public License as published by
23* the Free Software Foundation, either version 3 of the License, or 23 * the Free Software Foundation, either version 3 of the License, or
24* (at your option) any later version. 24 * (at your option) any later version.
25* 25 *
26* This program is distributed in the hope that it will be useful, 26 * This program is distributed in the hope that it will be useful,
27* but WITHOUT ANY WARRANTY; without even the implied warranty of 27 * but WITHOUT ANY WARRANTY; without even the implied warranty of
28* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29* GNU General Public License for more details. 29 * GNU General Public License for more details.
30* 30 *
31* You should have received a copy of the GNU General Public License 31 * You should have received a copy of the GNU General Public License
32* along with this program. If not, see <http://www.gnu.org/licenses/>. 32 * along with this program. If not, see <http://www.gnu.org/licenses/>.
33* 33 *
34* 34 *
35*****************************************************************************/ 35 *****************************************************************************/
36 36
37const char *progname = "check_ntp_time"; 37const char *progname = "check_ntp_time";
38const char *copyright = "2006-2008"; 38const char *copyright = "2006-2024";
39const char *email = "devel@monitoring-plugins.org"; 39const char *email = "devel@monitoring-plugins.org";
40 40
41#include "common.h" 41#include "common.h"
42#include "netutils.h" 42#include "netutils.h"
43#include "utils.h" 43#include "utils.h"
44 44
45static char *server_address=NULL; 45static char *server_address = NULL;
46static char *port="123"; 46static char *port = "123";
47static int verbose=0; 47static int verbose = 0;
48static bool quiet = false; 48static bool quiet = false;
49static char *owarn="60"; 49static char *owarn = "60";
50static char *ocrit="120"; 50static char *ocrit = "120";
51static int time_offset=0; 51static int time_offset = 0;
52 52
53int process_arguments (int, char **); 53static int process_arguments(int, char **);
54thresholds *offset_thresholds = NULL; 54static thresholds *offset_thresholds = NULL;
55void print_help (void); 55static void print_help(void);
56void print_usage (void); 56void print_usage(void);
57 57
58/* number of times to perform each request to get a good average. */ 58/* number of times to perform each request to get a good average. */
59#ifndef AVG_NUM 59#ifndef AVG_NUM
60#define AVG_NUM 4 60# define AVG_NUM 4
61#endif 61#endif
62 62
63/* max size of control message data */ 63/* max size of control message data */
@@ -65,17 +65,17 @@ void print_usage (void);
65 65
66/* this structure holds everything in an ntp request/response as per rfc1305 */ 66/* this structure holds everything in an ntp request/response as per rfc1305 */
67typedef struct { 67typedef struct {
68 uint8_t flags; /* byte with leapindicator,vers,mode. see macros */ 68 uint8_t flags; /* byte with leapindicator,vers,mode. see macros */
69 uint8_t stratum; /* clock stratum */ 69 uint8_t stratum; /* clock stratum */
70 int8_t poll; /* polling interval */ 70 int8_t poll; /* polling interval */
71 int8_t precision; /* precision of the local clock */ 71 int8_t precision; /* precision of the local clock */
72 int32_t rtdelay; /* total rt delay, as a fixed point num. see macros */ 72 int32_t rtdelay; /* total rt delay, as a fixed point num. see macros */
73 uint32_t rtdisp; /* like above, but for max err to primary src */ 73 uint32_t rtdisp; /* like above, but for max err to primary src */
74 uint32_t refid; /* ref clock identifier */ 74 uint32_t refid; /* ref clock identifier */
75 uint64_t refts; /* reference timestamp. local time local clock */ 75 uint64_t refts; /* reference timestamp. local time local clock */
76 uint64_t origts; /* time at which request departed client */ 76 uint64_t origts; /* time at which request departed client */
77 uint64_t rxts; /* time at which request arrived at server */ 77 uint64_t rxts; /* time at which request arrived at server */
78 uint64_t txts; /* time at which request departed server */ 78 uint64_t txts; /* time at which request departed server */
79} ntp_message; 79} ntp_message;
80 80
81/* this structure holds data about results from querying offset from a peer */ 81/* this structure holds data about results from querying offset from a peer */
@@ -86,43 +86,55 @@ typedef struct {
86 double rtdelay; /* converted from the ntp_message */ 86 double rtdelay; /* converted from the ntp_message */
87 double rtdisp; /* converted from the ntp_message */ 87 double rtdisp; /* converted from the ntp_message */
88 double offset[AVG_NUM]; /* offsets from each response */ 88 double offset[AVG_NUM]; /* offsets from each response */
89 uint8_t flags; /* byte with leapindicator,vers,mode. see macros */ 89 uint8_t flags; /* byte with leapindicator,vers,mode. see macros */
90} ntp_server_results; 90} ntp_server_results;
91 91
92/* bits 1,2 are the leap indicator */ 92/* bits 1,2 are the leap indicator */
93#define LI_MASK 0xc0 93#define LI_MASK 0xc0
94#define LI(x) ((x&LI_MASK)>>6) 94#define LI(x) ((x & LI_MASK) >> 6)
95#define LI_SET(x,y) do{ x |= ((y<<6)&LI_MASK); }while(0) 95#define LI_SET(x, y) \
96 do { \
97 x |= ((y << 6) & LI_MASK); \
98 } while (0)
96/* and these are the values of the leap indicator */ 99/* and these are the values of the leap indicator */
97#define LI_NOWARNING 0x00 100#define LI_NOWARNING 0x00
98#define LI_EXTRASEC 0x01 101#define LI_EXTRASEC 0x01
99#define LI_MISSINGSEC 0x02 102#define LI_MISSINGSEC 0x02
100#define LI_ALARM 0x03 103#define LI_ALARM 0x03
101/* bits 3,4,5 are the ntp version */ 104/* bits 3,4,5 are the ntp version */
102#define VN_MASK 0x38 105#define VN_MASK 0x38
103#define VN(x) ((x&VN_MASK)>>3) 106#define VN(x) ((x & VN_MASK) >> 3)
104#define VN_SET(x,y) do{ x |= ((y<<3)&VN_MASK); }while(0) 107#define VN_SET(x, y) \
108 do { \
109 x |= ((y << 3) & VN_MASK); \
110 } while (0)
105#define VN_RESERVED 0x02 111#define VN_RESERVED 0x02
106/* bits 6,7,8 are the ntp mode */ 112/* bits 6,7,8 are the ntp mode */
107#define MODE_MASK 0x07 113#define MODE_MASK 0x07
108#define MODE(x) (x&MODE_MASK) 114#define MODE(x) (x & MODE_MASK)
109#define MODE_SET(x,y) do{ x |= (y&MODE_MASK); }while(0) 115#define MODE_SET(x, y) \
116 do { \
117 x |= (y & MODE_MASK); \
118 } while (0)
110/* here are some values */ 119/* here are some values */
111#define MODE_CLIENT 0x03 120#define MODE_CLIENT 0x03
112#define MODE_CONTROLMSG 0x06 121#define MODE_CONTROLMSG 0x06
113/* In control message, bits 8-10 are R,E,M bits */ 122/* In control message, bits 8-10 are R,E,M bits */
114#define REM_MASK 0xe0 123#define REM_MASK 0xe0
115#define REM_RESP 0x80 124#define REM_RESP 0x80
116#define REM_ERROR 0x40 125#define REM_ERROR 0x40
117#define REM_MORE 0x20 126#define REM_MORE 0x20
118/* In control message, bits 11 - 15 are opcode */ 127/* In control message, bits 11 - 15 are opcode */
119#define OP_MASK 0x1f 128#define OP_MASK 0x1f
120#define OP_SET(x,y) do{ x |= (y&OP_MASK); }while(0) 129#define OP_SET(x, y) \
130 do { \
131 x |= (y & OP_MASK); \
132 } while (0)
121#define OP_READSTAT 0x01 133#define OP_READSTAT 0x01
122#define OP_READVAR 0x02 134#define OP_READVAR 0x02
123/* In peer status bytes, bits 6,7,8 determine clock selection status */ 135/* In peer status bytes, bits 6,7,8 determine clock selection status */
124#define PEER_SEL(x) ((ntohs(x)>>8)&0x07) 136#define PEER_SEL(x) ((ntohs(x) >> 8) & 0x07)
125#define PEER_INCLUDED 0x04 137#define PEER_INCLUDED 0x04
126#define PEER_SYNCSOURCE 0x06 138#define PEER_SYNCSOURCE 0x06
127 139
128/** 140/**
@@ -136,82 +148,91 @@ typedef struct {
136 148
137/* macros to access the left/right 16 bits of a 32-bit ntp "fixed point" 149/* macros to access the left/right 16 bits of a 32-bit ntp "fixed point"
138 number. note that these can be used as lvalues too */ 150 number. note that these can be used as lvalues too */
139#define L16(x) (((uint16_t*)&x)[0]) 151#define L16(x) (((uint16_t *)&x)[0])
140#define R16(x) (((uint16_t*)&x)[1]) 152#define R16(x) (((uint16_t *)&x)[1])
141/* macros to access the left/right 32 bits of a 64-bit ntp "fixed point" 153/* macros to access the left/right 32 bits of a 64-bit ntp "fixed point"
142 number. these too can be used as lvalues */ 154 number. these too can be used as lvalues */
143#define L32(x) (((uint32_t*)&x)[0]) 155#define L32(x) (((uint32_t *)&x)[0])
144#define R32(x) (((uint32_t*)&x)[1]) 156#define R32(x) (((uint32_t *)&x)[1])
145 157
146/* ntp wants seconds since 1/1/00, epoch is 1/1/70. this is the difference */ 158/* ntp wants seconds since 1/1/00, epoch is 1/1/70. this is the difference */
147#define EPOCHDIFF 0x83aa7e80UL 159#define EPOCHDIFF 0x83aa7e80UL
148 160
149/* extract a 32-bit ntp fixed point number into a double */ 161/* extract a 32-bit ntp fixed point number into a double */
150#define NTP32asDOUBLE(x) (ntohs(L16(x)) + (double)ntohs(R16(x))/65536.0) 162#define NTP32asDOUBLE(x) (ntohs(L16(x)) + (double)ntohs(R16(x)) / 65536.0)
151 163
152/* likewise for a 64-bit ntp fp number */ 164/* likewise for a 64-bit ntp fp number */
153#define NTP64asDOUBLE(n) (double)(((uint64_t)n)?\ 165#define NTP64asDOUBLE(n) \
154 (ntohl(L32(n))-EPOCHDIFF) + \ 166 (double)(((uint64_t)n) ? (ntohl(L32(n)) - EPOCHDIFF) + (.00000001 * (0.5 + (double)(ntohl(R32(n)) / 42.94967296))) : 0)
155 (.00000001*(0.5+(double)(ntohl(R32(n))/42.94967296))):\
156 0)
157 167
158/* convert a struct timeval to a double */ 168/* convert a struct timeval to a double */
159#define TVasDOUBLE(x) (double)(x.tv_sec+(0.000001*x.tv_usec)) 169#define TVasDOUBLE(x) (double)(x.tv_sec + (0.000001 * x.tv_usec))
160 170
161/* convert an ntp 64-bit fp number to a struct timeval */ 171/* convert an ntp 64-bit fp number to a struct timeval */
162#define NTP64toTV(n,t) \ 172#define NTP64toTV(n, t) \
163 do{ if(!n) t.tv_sec = t.tv_usec = 0; \ 173 do { \
164 else { \ 174 if (!n) \
165 t.tv_sec=ntohl(L32(n))-EPOCHDIFF; \ 175 t.tv_sec = t.tv_usec = 0; \
166 t.tv_usec=(int)(0.5+(double)(ntohl(R32(n))/4294.967296)); \ 176 else { \
167 } \ 177 t.tv_sec = ntohl(L32(n)) - EPOCHDIFF; \
168 }while(0) 178 t.tv_usec = (int)(0.5 + (double)(ntohl(R32(n)) / 4294.967296)); \
179 } \
180 } while (0)
169 181
170/* convert a struct timeval to an ntp 64-bit fp number */ 182/* convert a struct timeval to an ntp 64-bit fp number */
171#define TVtoNTP64(t,n) \ 183#define TVtoNTP64(t, n) \
172 do{ if(!t.tv_usec && !t.tv_sec) n=0x0UL; \ 184 do { \
173 else { \ 185 if (!t.tv_usec && !t.tv_sec) \
174 L32(n)=htonl(t.tv_sec + EPOCHDIFF); \ 186 n = 0x0UL; \
175 R32(n)=htonl((uint64_t)((4294.967296*t.tv_usec)+.5)); \ 187 else { \
176 } \ 188 L32(n) = htonl(t.tv_sec + EPOCHDIFF); \
177 } while(0) 189 R32(n) = htonl((uint64_t)((4294.967296 * t.tv_usec) + .5)); \
190 } \
191 } while (0)
178 192
179/* NTP control message header is 12 bytes, plus any data in the data 193/* NTP control message header is 12 bytes, plus any data in the data
180 * field, plus null padding to the nearest 32-bit boundary per rfc. 194 * field, plus null padding to the nearest 32-bit boundary per rfc.
181 */ 195 */
182#define SIZEOF_NTPCM(m) (12+ntohs(m.count)+((m.count)?4-(ntohs(m.count)%4):0)) 196#define SIZEOF_NTPCM(m) (12 + ntohs(m.count) + ((m.count) ? 4 - (ntohs(m.count) % 4) : 0))
183 197
184/* finally, a little helper or two for debugging: */ 198/* finally, a little helper or two for debugging: */
185#define DBG(x) do{if(verbose>1){ x; }}while(0); 199#define DBG(x) \
186#define PRINTSOCKADDR(x) \ 200 do { \
187 do{ \ 201 if (verbose > 1) { \
188 printf("%u.%u.%u.%u", (x>>24)&0xff, (x>>16)&0xff, (x>>8)&0xff, x&0xff);\ 202 x; \
189 }while(0); 203 } \
204 } while (0);
205#define PRINTSOCKADDR(x) \
206 do { \
207 printf("%u.%u.%u.%u", (x >> 24) & 0xff, (x >> 16) & 0xff, (x >> 8) & 0xff, x & 0xff); \
208 } while (0);
190 209
191/* calculate the offset of the local clock */ 210/* calculate the offset of the local clock */
192static inline double calc_offset(const ntp_message *m, const struct timeval *t){ 211static inline double calc_offset(const ntp_message *m, const struct timeval *t) {
193 double client_tx, peer_rx, peer_tx, client_rx; 212 double client_tx = NTP64asDOUBLE(m->origts);
194 client_tx = NTP64asDOUBLE(m->origts); 213 double peer_rx = NTP64asDOUBLE(m->rxts);
195 peer_rx = NTP64asDOUBLE(m->rxts); 214 double peer_tx = NTP64asDOUBLE(m->txts);
196 peer_tx = NTP64asDOUBLE(m->txts); 215 double client_rx = TVasDOUBLE((*t));
197 client_rx=TVasDOUBLE((*t)); 216 return (.5 * ((peer_tx - client_rx) + (peer_rx - client_tx)));
198 return (.5*((peer_tx-client_rx)+(peer_rx-client_tx)));
199} 217}
200 218
201/* print out a ntp packet in human readable/debuggable format */ 219/* print out a ntp packet in human readable/debuggable format */
202void print_ntp_message(const ntp_message *p){ 220void print_ntp_message(const ntp_message *p) {
203 struct timeval ref, orig, rx, tx; 221 struct timeval ref;
222 struct timeval orig;
223 struct timeval rx;
224 struct timeval tx;
204 225
205 NTP64toTV(p->refts,ref); 226 NTP64toTV(p->refts, ref);
206 NTP64toTV(p->origts,orig); 227 NTP64toTV(p->origts, orig);
207 NTP64toTV(p->rxts,rx); 228 NTP64toTV(p->rxts, rx);
208 NTP64toTV(p->txts,tx); 229 NTP64toTV(p->txts, tx);
209 230
210 printf("packet contents:\n"); 231 printf("packet contents:\n");
211 printf("\tflags: 0x%.2x\n", p->flags); 232 printf("\tflags: 0x%.2x\n", p->flags);
212 printf("\t li=%d (0x%.2x)\n", LI(p->flags), p->flags&LI_MASK); 233 printf("\t li=%d (0x%.2x)\n", LI(p->flags), p->flags & LI_MASK);
213 printf("\t vn=%d (0x%.2x)\n", VN(p->flags), p->flags&VN_MASK); 234 printf("\t vn=%d (0x%.2x)\n", VN(p->flags), p->flags & VN_MASK);
214 printf("\t mode=%d (0x%.2x)\n", MODE(p->flags), p->flags&MODE_MASK); 235 printf("\t mode=%d (0x%.2x)\n", MODE(p->flags), p->flags & MODE_MASK);
215 printf("\tstratum = %d\n", p->stratum); 236 printf("\tstratum = %d\n", p->stratum);
216 printf("\tpoll = %g\n", pow(2, p->poll)); 237 printf("\tpoll = %g\n", pow(2, p->poll));
217 printf("\tprecision = %g\n", pow(2, p->precision)); 238 printf("\tprecision = %g\n", pow(2, p->precision));
@@ -224,41 +245,42 @@ void print_ntp_message(const ntp_message *p){
224 printf("\ttxts = %-.16g\n", NTP64asDOUBLE(p->txts)); 245 printf("\ttxts = %-.16g\n", NTP64asDOUBLE(p->txts));
225} 246}
226 247
227void setup_request(ntp_message *p){ 248void setup_request(ntp_message *p) {
228 struct timeval t;
229
230 memset(p, 0, sizeof(ntp_message)); 249 memset(p, 0, sizeof(ntp_message));
231 LI_SET(p->flags, LI_ALARM); 250 LI_SET(p->flags, LI_ALARM);
232 VN_SET(p->flags, 4); 251 VN_SET(p->flags, 4);
233 MODE_SET(p->flags, MODE_CLIENT); 252 MODE_SET(p->flags, MODE_CLIENT);
234 p->poll=4; 253 p->poll = 4;
235 p->precision=(int8_t)0xfa; 254 p->precision = (int8_t)0xfa;
236 L16(p->rtdelay)=htons(1); 255 L16(p->rtdelay) = htons(1);
237 L16(p->rtdisp)=htons(1); 256 L16(p->rtdisp) = htons(1);
238 257
258 struct timeval t;
239 gettimeofday(&t, NULL); 259 gettimeofday(&t, NULL);
240 TVtoNTP64(t,p->txts); 260 TVtoNTP64(t, p->txts);
241} 261}
242 262
243/* select the "best" server from a list of servers, and return its index. 263/* select the "best" server from a list of servers, and return its index.
244 * this is done by filtering servers based on stratum, dispersion, and 264 * this is done by filtering servers based on stratum, dispersion, and
245 * finally round-trip delay. */ 265 * finally round-trip delay. */
246int best_offset_server(const ntp_server_results *slist, int nservers){ 266int best_offset_server(const ntp_server_results *slist, int nservers) {
247 int cserver=0, best_server=-1; 267 int best_server = -1;
248 268
249 /* for each server */ 269 /* for each server */
250 for(cserver=0; cserver<nservers; cserver++){ 270 for (int cserver = 0; cserver < nservers; cserver++) {
251 /* We don't want any servers that fails these tests */ 271 /* We don't want any servers that fails these tests */
252 /* Sort out servers that didn't respond or responede with a 0 stratum; 272 /* Sort out servers that didn't respond or responede with a 0 stratum;
253 * stratum 0 is for reference clocks so no NTP server should ever report 273 * stratum 0 is for reference clocks so no NTP server should ever report
254 * a stratum 0 */ 274 * a stratum 0 */
255 if ( slist[cserver].stratum == 0){ 275 if (slist[cserver].stratum == 0) {
256 if (verbose) printf("discarding peer %d: stratum=%d\n", cserver, slist[cserver].stratum); 276 if (verbose)
277 printf("discarding peer %d: stratum=%d\n", cserver, slist[cserver].stratum);
257 continue; 278 continue;
258 } 279 }
259 /* Sort out servers with error flags */ 280 /* Sort out servers with error flags */
260 if ( LI(slist[cserver].flags) == LI_ALARM ){ 281 if (LI(slist[cserver].flags) == LI_ALARM) {
261 if (verbose) printf("discarding peer %d: flags=%d\n", cserver, LI(slist[cserver].flags)); 282 if (verbose)
283 printf("discarding peer %d: flags=%d\n", cserver, LI(slist[cserver].flags));
262 continue; 284 continue;
263 } 285 }
264 286
@@ -272,13 +294,13 @@ int best_offset_server(const ntp_server_results *slist, int nservers){
272 /* compare the server to the best one we've seen so far */ 294 /* compare the server to the best one we've seen so far */
273 /* does it have an equal or better stratum? */ 295 /* does it have an equal or better stratum? */
274 DBG(printf("comparing peer %d with peer %d\n", cserver, best_server)); 296 DBG(printf("comparing peer %d with peer %d\n", cserver, best_server));
275 if(slist[cserver].stratum <= slist[best_server].stratum){ 297 if (slist[cserver].stratum <= slist[best_server].stratum) {
276 DBG(printf("stratum for peer %d <= peer %d\n", cserver, best_server)); 298 DBG(printf("stratum for peer %d <= peer %d\n", cserver, best_server));
277 /* does it have an equal or better dispersion? */ 299 /* does it have an equal or better dispersion? */
278 if(slist[cserver].rtdisp <= slist[best_server].rtdisp){ 300 if (slist[cserver].rtdisp <= slist[best_server].rtdisp) {
279 DBG(printf("dispersion for peer %d <= peer %d\n", cserver, best_server)); 301 DBG(printf("dispersion for peer %d <= peer %d\n", cserver, best_server));
280 /* does it have a better rtdelay? */ 302 /* does it have a better rtdelay? */
281 if(slist[cserver].rtdelay < slist[best_server].rtdelay){ 303 if (slist[cserver].rtdelay < slist[best_server].rtdelay) {
282 DBG(printf("rtdelay for peer %d < peer %d\n", cserver, best_server)); 304 DBG(printf("rtdelay for peer %d < peer %d\n", cserver, best_server));
283 best_server = cserver; 305 best_server = cserver;
284 DBG(printf("peer %d is now our best candidate\n", best_server)); 306 DBG(printf("peer %d is now our best candidate\n", best_server));
@@ -287,13 +309,12 @@ int best_offset_server(const ntp_server_results *slist, int nservers){
287 } 309 }
288 } 310 }
289 311
290 if(best_server >= 0) { 312 if (best_server >= 0) {
291 DBG(printf("best server selected: peer %d\n", best_server)); 313 DBG(printf("best server selected: peer %d\n", best_server));
292 return best_server; 314 return best_server;
293 } else {
294 DBG(printf("no peers meeting synchronization criteria :(\n"));
295 return -1;
296 } 315 }
316 DBG(printf("no peers meeting synchronization criteria :(\n"));
317 return -1;
297} 318}
298 319
299/* do everything we need to get the total average offset 320/* do everything we need to get the total average offset
@@ -301,178 +322,190 @@ int best_offset_server(const ntp_server_results *slist, int nservers){
301 * we don't waste time sitting around waiting for single packets. 322 * we don't waste time sitting around waiting for single packets.
302 * - we also "manually" handle resolving host names and connecting, because 323 * - we also "manually" handle resolving host names and connecting, because
303 * we have to do it in a way that our lazy macros don't handle currently :( */ 324 * we have to do it in a way that our lazy macros don't handle currently :( */
304double offset_request(const char *host, int *status){ 325double offset_request(const char *host, int *status) {
305 int i=0, j=0, ga_result=0, num_hosts=0, *socklist=NULL, respnum=0;
306 int servers_completed=0, one_read=0, servers_readable=0, best_index=-1;
307 time_t now_time=0, start_ts=0;
308 ntp_message *req=NULL;
309 double avg_offset=0.;
310 struct timeval recv_time;
311 struct addrinfo *ai=NULL, *ai_tmp=NULL, hints;
312 struct pollfd *ufds=NULL;
313 ntp_server_results *servers=NULL;
314
315 /* setup hints to only return results from getaddrinfo that we'd like */ 326 /* setup hints to only return results from getaddrinfo that we'd like */
327 struct addrinfo hints;
316 memset(&hints, 0, sizeof(struct addrinfo)); 328 memset(&hints, 0, sizeof(struct addrinfo));
317 hints.ai_family = address_family; 329 hints.ai_family = address_family;
318 hints.ai_protocol = IPPROTO_UDP; 330 hints.ai_protocol = IPPROTO_UDP;
319 hints.ai_socktype = SOCK_DGRAM; 331 hints.ai_socktype = SOCK_DGRAM;
320 332
321 /* fill in ai with the list of hosts resolved by the host name */ 333 /* fill in ai with the list of hosts resolved by the host name */
322 ga_result = getaddrinfo(host, port, &hints, &ai); 334 struct addrinfo *ai = NULL;
323 if(ga_result!=0){ 335 int ga_result = getaddrinfo(host, port, &hints, &ai);
324 die(STATE_UNKNOWN, "error getting address for %s: %s\n", 336 if (ga_result != 0) {
325 host, gai_strerror(ga_result)); 337 die(STATE_UNKNOWN, "error getting address for %s: %s\n", host, gai_strerror(ga_result));
326 } 338 }
327 339
328 /* count the number of returned hosts, and allocate stuff accordingly */ 340 /* count the number of returned hosts, and allocate stuff accordingly */
329 for(ai_tmp=ai; ai_tmp!=NULL; ai_tmp=ai_tmp->ai_next){ num_hosts++; } 341 int num_hosts = 0;
330 req=(ntp_message*)malloc(sizeof(ntp_message)*num_hosts); 342 for (struct addrinfo *ai_tmp = ai; ai_tmp != NULL; ai_tmp = ai_tmp->ai_next) {
331 if(req==NULL) die(STATE_UNKNOWN, "can not allocate ntp message array"); 343 num_hosts++;
332 socklist=(int*)malloc(sizeof(int)*num_hosts); 344 }
333 if(socklist==NULL) die(STATE_UNKNOWN, "can not allocate socket array"); 345
334 ufds=(struct pollfd*)malloc(sizeof(struct pollfd)*num_hosts); 346 ntp_message *req = (ntp_message *)malloc(sizeof(ntp_message) * num_hosts);
335 if(ufds==NULL) die(STATE_UNKNOWN, "can not allocate socket array"); 347
336 servers=(ntp_server_results*)malloc(sizeof(ntp_server_results)*num_hosts); 348 if (req == NULL)
337 if(servers==NULL) die(STATE_UNKNOWN, "can not allocate server array"); 349 die(STATE_UNKNOWN, "can not allocate ntp message array");
338 memset(servers, 0, sizeof(ntp_server_results)*num_hosts); 350 int *socklist = (int *)malloc(sizeof(int) * num_hosts);
351
352 if (socklist == NULL)
353 die(STATE_UNKNOWN, "can not allocate socket array");
354
355 struct pollfd *ufds = (struct pollfd *)malloc(sizeof(struct pollfd) * num_hosts);
356 if (ufds == NULL)
357 die(STATE_UNKNOWN, "can not allocate socket array");
358
359 ntp_server_results *servers = (ntp_server_results *)malloc(sizeof(ntp_server_results) * num_hosts);
360 if (servers == NULL)
361 die(STATE_UNKNOWN, "can not allocate server array");
362 memset(servers, 0, sizeof(ntp_server_results) * num_hosts);
339 DBG(printf("Found %d peers to check\n", num_hosts)); 363 DBG(printf("Found %d peers to check\n", num_hosts));
340 364
341 /* setup each socket for writing, and the corresponding struct pollfd */ 365 /* setup each socket for writing, and the corresponding struct pollfd */
342 ai_tmp=ai; 366 struct addrinfo *ai_tmp = ai;
343 for(i=0;ai_tmp;i++){ 367 for (int i = 0; ai_tmp; i++) {
344 socklist[i]=socket(ai_tmp->ai_family, SOCK_DGRAM, IPPROTO_UDP); 368 socklist[i] = socket(ai_tmp->ai_family, SOCK_DGRAM, IPPROTO_UDP);
345 if(socklist[i] == -1) { 369 if (socklist[i] == -1) {
346 perror(NULL); 370 perror(NULL);
347 die(STATE_UNKNOWN, "can not create new socket"); 371 die(STATE_UNKNOWN, "can not create new socket");
348 } 372 }
349 if(connect(socklist[i], ai_tmp->ai_addr, ai_tmp->ai_addrlen)){ 373 if (connect(socklist[i], ai_tmp->ai_addr, ai_tmp->ai_addrlen)) {
350 /* don't die here, because it is enough if there is one server 374 /* don't die here, because it is enough if there is one server
351 answering in time. This also would break for dual ipv4/6 stacked 375 answering in time. This also would break for dual ipv4/6 stacked
352 ntp servers when the client only supports on of them. 376 ntp servers when the client only supports on of them.
353 */ 377 */
354 DBG(printf("can't create socket connection on peer %i: %s\n", i, strerror(errno))); 378 DBG(printf("can't create socket connection on peer %i: %s\n", i, strerror(errno)));
355 } else { 379 } else {
356 ufds[i].fd=socklist[i]; 380 ufds[i].fd = socklist[i];
357 ufds[i].events=POLLIN; 381 ufds[i].events = POLLIN;
358 ufds[i].revents=0; 382 ufds[i].revents = 0;
359 } 383 }
360 ai_tmp = ai_tmp->ai_next; 384 ai_tmp = ai_tmp->ai_next;
361 } 385 }
362 386
363 /* now do AVG_NUM checks to each host. We stop before timeout/2 seconds 387 /* now do AVG_NUM checks to each host. We stop before timeout/2 seconds
364 * have passed in order to ensure post-processing and jitter time. */ 388 * have passed in order to ensure post-processing and jitter time. */
365 now_time=start_ts=time(NULL); 389 time_t start_ts = 0;
366 while(servers_completed<num_hosts && now_time-start_ts <= socket_timeout/2){ 390 time_t now_time = 0;
391 now_time = start_ts = time(NULL);
392 int servers_completed = 0;
393 bool one_read = false;
394 while (servers_completed < num_hosts && now_time - start_ts <= socket_timeout / 2) {
367 /* loop through each server and find each one which hasn't 395 /* loop through each server and find each one which hasn't
368 * been touched in the past second or so and is still lacking 396 * been touched in the past second or so and is still lacking
369 * some responses. For each of these servers, send a new request, 397 * some responses. For each of these servers, send a new request,
370 * and update the "waiting" timestamp with the current time. */ 398 * and update the "waiting" timestamp with the current time. */
371 now_time=time(NULL); 399 now_time = time(NULL);
372 400
373 for(i=0; i<num_hosts; i++){ 401 for (int i = 0; i < num_hosts; i++) {
374 if(servers[i].waiting<now_time && servers[i].num_responses<AVG_NUM){ 402 if (servers[i].waiting < now_time && servers[i].num_responses < AVG_NUM) {
375 if(verbose && servers[i].waiting != 0) printf("re-"); 403 if (verbose && servers[i].waiting != 0)
376 if(verbose) printf("sending request to peer %d\n", i); 404 printf("re-");
405 if (verbose)
406 printf("sending request to peer %d\n", i);
377 setup_request(&req[i]); 407 setup_request(&req[i]);
378 write(socklist[i], &req[i], sizeof(ntp_message)); 408 write(socklist[i], &req[i], sizeof(ntp_message));
379 servers[i].waiting=now_time; 409 servers[i].waiting = now_time;
380 break; 410 break;
381 } 411 }
382 } 412 }
383 413
384 /* quickly poll for any sockets with pending data */ 414 /* quickly poll for any sockets with pending data */
385 servers_readable=poll(ufds, num_hosts, 100); 415 int servers_readable = poll(ufds, num_hosts, 100);
386 if(servers_readable==-1){ 416 if (servers_readable == -1) {
387 perror("polling ntp sockets"); 417 perror("polling ntp sockets");
388 die(STATE_UNKNOWN, "communication errors"); 418 die(STATE_UNKNOWN, "communication errors");
389 } 419 }
390 420
391 /* read from any sockets with pending data */ 421 /* read from any sockets with pending data */
392 for(i=0; servers_readable && i<num_hosts; i++){ 422 for (int i = 0; servers_readable && i < num_hosts; i++) {
393 if(ufds[i].revents&POLLIN && servers[i].num_responses < AVG_NUM){ 423 if (ufds[i].revents & POLLIN && servers[i].num_responses < AVG_NUM) {
394 if(verbose) { 424 if (verbose) {
395 printf("response from peer %d: ", i); 425 printf("response from peer %d: ", i);
396 } 426 }
397 427
398 read(ufds[i].fd, &req[i], sizeof(ntp_message)); 428 read(ufds[i].fd, &req[i], sizeof(ntp_message));
429
430 struct timeval recv_time;
399 gettimeofday(&recv_time, NULL); 431 gettimeofday(&recv_time, NULL);
400 DBG(print_ntp_message(&req[i])); 432 DBG(print_ntp_message(&req[i]));
401 respnum=servers[i].num_responses++; 433 int respnum = servers[i].num_responses++;
402 servers[i].offset[respnum]=calc_offset(&req[i], &recv_time)+time_offset; 434 servers[i].offset[respnum] = calc_offset(&req[i], &recv_time) + time_offset;
403 if(verbose) { 435 if (verbose) {
404 printf("offset %.10g\n", servers[i].offset[respnum]); 436 printf("offset %.10g\n", servers[i].offset[respnum]);
405 } 437 }
406 servers[i].stratum=req[i].stratum; 438 servers[i].stratum = req[i].stratum;
407 servers[i].rtdisp=NTP32asDOUBLE(req[i].rtdisp); 439 servers[i].rtdisp = NTP32asDOUBLE(req[i].rtdisp);
408 servers[i].rtdelay=NTP32asDOUBLE(req[i].rtdelay); 440 servers[i].rtdelay = NTP32asDOUBLE(req[i].rtdelay);
409 servers[i].waiting=0; 441 servers[i].waiting = 0;
410 servers[i].flags=req[i].flags; 442 servers[i].flags = req[i].flags;
411 servers_readable--; 443 servers_readable--;
412 one_read = 1; 444 one_read = true;
413 if(servers[i].num_responses==AVG_NUM) servers_completed++; 445 if (servers[i].num_responses == AVG_NUM)
446 servers_completed++;
414 } 447 }
415 } 448 }
416 /* lather, rinse, repeat. */ 449 /* lather, rinse, repeat. */
417 } 450 }
418 451
419 if (one_read == 0) { 452 if (one_read == false) {
420 die(STATE_CRITICAL, "NTP CRITICAL: No response from NTP server\n"); 453 die(STATE_CRITICAL, "NTP CRITICAL: No response from NTP server\n");
421 } 454 }
422 455
423 /* now, pick the best server from the list */ 456 /* now, pick the best server from the list */
424 best_index=best_offset_server(servers, num_hosts); 457 double avg_offset = 0.;
425 if(best_index < 0){ 458 int best_index = best_offset_server(servers, num_hosts);
426 *status=STATE_UNKNOWN; 459 if (best_index < 0) {
460 *status = STATE_UNKNOWN;
427 } else { 461 } else {
428 /* finally, calculate the average offset */ 462 /* finally, calculate the average offset */
429 for(i=0; i<servers[best_index].num_responses;i++){ 463 for (int i = 0; i < servers[best_index].num_responses; i++) {
430 avg_offset+=servers[best_index].offset[i]; 464 avg_offset += servers[best_index].offset[i];
431 } 465 }
432 avg_offset/=servers[best_index].num_responses; 466 avg_offset /= servers[best_index].num_responses;
433 } 467 }
434 468
435 /* cleanup */ 469 /* cleanup */
436 for(j=0; j<num_hosts; j++){ close(socklist[j]); } 470 for (int j = 0; j < num_hosts; j++) {
471 close(socklist[j]);
472 }
437 free(socklist); 473 free(socklist);
438 free(ufds); 474 free(ufds);
439 free(servers); 475 free(servers);
440 free(req); 476 free(req);
441 freeaddrinfo(ai); 477 freeaddrinfo(ai);
442 478
443 if(verbose) printf("overall average offset: %.10g\n", avg_offset); 479 if (verbose)
480 printf("overall average offset: %.10g\n", avg_offset);
444 return avg_offset; 481 return avg_offset;
445} 482}
446 483
447int process_arguments(int argc, char **argv){ 484int process_arguments(int argc, char **argv) {
448 int c; 485 static struct option longopts[] = {{"version", no_argument, 0, 'V'},
449 int option=0; 486 {"help", no_argument, 0, 'h'},
450 static struct option longopts[] = { 487 {"verbose", no_argument, 0, 'v'},
451 {"version", no_argument, 0, 'V'}, 488 {"use-ipv4", no_argument, 0, '4'},
452 {"help", no_argument, 0, 'h'}, 489 {"use-ipv6", no_argument, 0, '6'},
453 {"verbose", no_argument, 0, 'v'}, 490 {"quiet", no_argument, 0, 'q'},
454 {"use-ipv4", no_argument, 0, '4'}, 491 {"time-offset", optional_argument, 0, 'o'},
455 {"use-ipv6", no_argument, 0, '6'}, 492 {"warning", required_argument, 0, 'w'},
456 {"quiet", no_argument, 0, 'q'}, 493 {"critical", required_argument, 0, 'c'},
457 {"time-offset", optional_argument, 0, 'o'}, 494 {"timeout", required_argument, 0, 't'},
458 {"warning", required_argument, 0, 'w'}, 495 {"hostname", required_argument, 0, 'H'},
459 {"critical", required_argument, 0, 'c'}, 496 {"port", required_argument, 0, 'p'},
460 {"timeout", required_argument, 0, 't'}, 497 {0, 0, 0, 0}};
461 {"hostname", required_argument, 0, 'H'},
462 {"port", required_argument, 0, 'p'},
463 {0, 0, 0, 0}
464 };
465
466 498
467 if (argc < 2) 499 if (argc < 2)
468 usage ("\n"); 500 usage("\n");
469 501
470 while (1) { 502 while (true) {
471 c = getopt_long (argc, argv, "Vhv46qw:c:t:H:p:o:", longopts, &option); 503 int option = 0;
472 if (c == -1 || c == EOF || c == 1) 504 int option_char = getopt_long(argc, argv, "Vhv46qw:c:t:H:p:o:", longopts, &option);
505 if (option_char == -1 || option_char == EOF || option_char == 1)
473 break; 506 break;
474 507
475 switch (c) { 508 switch (option_char) {
476 case 'h': 509 case 'h':
477 print_help(); 510 print_help();
478 exit(STATE_UNKNOWN); 511 exit(STATE_UNKNOWN);
@@ -494,7 +527,7 @@ int process_arguments(int argc, char **argv){
494 ocrit = optarg; 527 ocrit = optarg;
495 break; 528 break;
496 case 'H': 529 case 'H':
497 if(!is_host(optarg)) 530 if (!is_host(optarg))
498 usage2(_("Invalid hostname/address"), optarg); 531 usage2(_("Invalid hostname/address"), optarg);
499 server_address = strdup(optarg); 532 server_address = strdup(optarg);
500 break; 533 break;
@@ -502,11 +535,11 @@ int process_arguments(int argc, char **argv){
502 port = strdup(optarg); 535 port = strdup(optarg);
503 break; 536 break;
504 case 't': 537 case 't':
505 socket_timeout=atoi(optarg); 538 socket_timeout = atoi(optarg);
506 break; 539 break;
507 case 'o': 540 case 'o':
508 time_offset=atoi(optarg); 541 time_offset = atoi(optarg);
509 break; 542 break;
510 case '4': 543 case '4':
511 address_family = AF_INET; 544 address_family = AF_INET;
512 break; 545 break;
@@ -514,77 +547,74 @@ int process_arguments(int argc, char **argv){
514#ifdef USE_IPV6 547#ifdef USE_IPV6
515 address_family = AF_INET6; 548 address_family = AF_INET6;
516#else 549#else
517 usage4 (_("IPv6 support not available")); 550 usage4(_("IPv6 support not available"));
518#endif 551#endif
519 break; 552 break;
520 case '?': 553 case '?':
521 /* print short usage statement if args not parsable */ 554 /* print short usage statement if args not parsable */
522 usage5 (); 555 usage5();
523 break; 556 break;
524 } 557 }
525 } 558 }
526 559
527 if(server_address == NULL){ 560 if (server_address == NULL) {
528 usage4(_("Hostname was not supplied")); 561 usage4(_("Hostname was not supplied"));
529 } 562 }
530 563
531 return 0; 564 return 0;
532} 565}
533 566
534char *perfd_offset (double offset) { 567char *perfd_offset(double offset) {
535 return fperfdata ("offset", offset, "s", 568 return fperfdata("offset", offset, "s", true, offset_thresholds->warning->end, true, offset_thresholds->critical->end, false, 0, false,
536 true, offset_thresholds->warning->end, 569 0);
537 true, offset_thresholds->critical->end,
538 false, 0, false, 0);
539} 570}
540 571
541int main(int argc, char *argv[]){ 572int main(int argc, char *argv[]) {
542 int result, offset_result; 573 setlocale(LC_ALL, "");
543 double offset=0; 574 bindtextdomain(PACKAGE, LOCALEDIR);
544 char *result_line, *perfdata_line; 575 textdomain(PACKAGE);
545
546 setlocale (LC_ALL, "");
547 bindtextdomain (PACKAGE, LOCALEDIR);
548 textdomain (PACKAGE);
549
550 result = offset_result = STATE_OK;
551 576
552 /* Parse extra opts if any */ 577 /* Parse extra opts if any */
553 argv=np_extra_opts (&argc, argv, progname); 578 argv = np_extra_opts(&argc, argv, progname);
554 579
555 if (process_arguments (argc, argv) == ERROR) 580 if (process_arguments(argc, argv) == ERROR)
556 usage4 (_("Could not parse arguments")); 581 usage4(_("Could not parse arguments"));
557 582
558 set_thresholds(&offset_thresholds, owarn, ocrit); 583 set_thresholds(&offset_thresholds, owarn, ocrit);
559 584
560 /* initialize alarm signal handling */ 585 /* initialize alarm signal handling */
561 signal (SIGALRM, socket_timeout_alarm_handler); 586 signal(SIGALRM, socket_timeout_alarm_handler);
562 587
563 /* set socket timeout */ 588 /* set socket timeout */
564 alarm (socket_timeout); 589 alarm(socket_timeout);
565 590
566 offset = offset_request(server_address, &offset_result); 591 int offset_result = STATE_OK;
592 int result = STATE_OK;
593 double offset = offset_request(server_address, &offset_result);
567 if (offset_result == STATE_UNKNOWN) { 594 if (offset_result == STATE_UNKNOWN) {
568 result = ( (!quiet) ? STATE_UNKNOWN : STATE_CRITICAL); 595 result = ((!quiet) ? STATE_UNKNOWN : STATE_CRITICAL);
569 } else { 596 } else {
570 result = get_status(fabs(offset), offset_thresholds); 597 result = get_status(fabs(offset), offset_thresholds);
571 } 598 }
572 599
600 char *result_line;
573 switch (result) { 601 switch (result) {
574 case STATE_CRITICAL : 602 case STATE_CRITICAL:
575 xasprintf(&result_line, _("NTP CRITICAL:")); 603 xasprintf(&result_line, _("NTP CRITICAL:"));
576 break; 604 break;
577 case STATE_WARNING : 605 case STATE_WARNING:
578 xasprintf(&result_line, _("NTP WARNING:")); 606 xasprintf(&result_line, _("NTP WARNING:"));
579 break; 607 break;
580 case STATE_OK : 608 case STATE_OK:
581 xasprintf(&result_line, _("NTP OK:")); 609 xasprintf(&result_line, _("NTP OK:"));
582 break; 610 break;
583 default : 611 default:
584 xasprintf(&result_line, _("NTP UNKNOWN:")); 612 xasprintf(&result_line, _("NTP UNKNOWN:"));
585 break; 613 break;
586 } 614 }
587 if(offset_result == STATE_UNKNOWN){ 615
616 char *perfdata_line;
617 if (offset_result == STATE_UNKNOWN) {
588 xasprintf(&result_line, "%s %s", result_line, _("Offset unknown")); 618 xasprintf(&result_line, "%s %s", result_line, _("Offset unknown"));
589 xasprintf(&perfdata_line, ""); 619 xasprintf(&perfdata_line, "");
590 } else { 620 } else {
@@ -593,35 +623,36 @@ int main(int argc, char *argv[]){
593 } 623 }
594 printf("%s|%s\n", result_line, perfdata_line); 624 printf("%s|%s\n", result_line, perfdata_line);
595 625
596 if(server_address!=NULL) free(server_address); 626 if (server_address != NULL)
627 free(server_address);
597 return result; 628 return result;
598} 629}
599 630
600void print_help(void){ 631void print_help(void) {
601 print_revision(progname, NP_VERSION); 632 print_revision(progname, NP_VERSION);
602 633
603 printf ("Copyright (c) 2006 Sean Finney\n"); 634 printf("Copyright (c) 2006 Sean Finney\n");
604 printf (COPYRIGHT, copyright, email); 635 printf(COPYRIGHT, copyright, email);
605 636
606 printf ("%s\n", _("This plugin checks the clock offset with the ntp server")); 637 printf("%s\n", _("This plugin checks the clock offset with the ntp server"));
607 638
608 printf ("\n\n"); 639 printf("\n\n");
609 640
610 print_usage(); 641 print_usage();
611 printf (UT_HELP_VRSN); 642 printf(UT_HELP_VRSN);
612 printf (UT_EXTRA_OPTS); 643 printf(UT_EXTRA_OPTS);
613 printf (UT_IPv46); 644 printf(UT_IPv46);
614 printf (UT_HOST_PORT, 'p', "123"); 645 printf(UT_HOST_PORT, 'p', "123");
615 printf (" %s\n", "-q, --quiet"); 646 printf(" %s\n", "-q, --quiet");
616 printf (" %s\n", _("Returns UNKNOWN instead of CRITICAL if offset cannot be found")); 647 printf(" %s\n", _("Returns UNKNOWN instead of CRITICAL if offset cannot be found"));
617 printf (" %s\n", "-w, --warning=THRESHOLD"); 648 printf(" %s\n", "-w, --warning=THRESHOLD");
618 printf (" %s\n", _("Offset to result in warning status (seconds)")); 649 printf(" %s\n", _("Offset to result in warning status (seconds)"));
619 printf (" %s\n", "-c, --critical=THRESHOLD"); 650 printf(" %s\n", "-c, --critical=THRESHOLD");
620 printf (" %s\n", _("Offset to result in critical status (seconds)")); 651 printf(" %s\n", _("Offset to result in critical status (seconds)"));
621 printf (" %s\n", "-o, --time_offset=INTEGER"); 652 printf(" %s\n", "-o, --time_offset=INTEGER");
622 printf (" %s\n", _("Expected offset of the ntp server relative to local server (seconds)")); 653 printf(" %s\n", _("Expected offset of the ntp server relative to local server (seconds)"));
623 printf (UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); 654 printf(UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
624 printf (UT_VERBOSE); 655 printf(UT_VERBOSE);
625 656
626 printf("\n"); 657 printf("\n");
627 printf("%s\n", _("This plugin checks the clock offset between the local host and a")); 658 printf("%s\n", _("This plugin checks the clock offset between the local host and a"));
@@ -641,13 +672,10 @@ void print_help(void){
641 printf("%s\n", _("Examples:")); 672 printf("%s\n", _("Examples:"));
642 printf(" %s\n", ("./check_ntp_time -H ntpserv -w 0.5 -c 1")); 673 printf(" %s\n", ("./check_ntp_time -H ntpserv -w 0.5 -c 1"));
643 674
644 printf (UT_SUPPORT); 675 printf(UT_SUPPORT);
645} 676}
646 677
647void 678void print_usage(void) {
648print_usage(void) 679 printf("%s\n", _("Usage:"));
649{
650 printf ("%s\n", _("Usage:"));
651 printf(" %s -H <host> [-4|-6] [-w <warn>] [-c <crit>] [-v verbose] [-o <time offset>]\n", progname); 680 printf(" %s -H <host> [-4|-6] [-w <warn>] [-c <crit>] [-v verbose] [-o <time offset>]\n", progname);
652} 681}
653
diff --git a/plugins/check_nwstat.c b/plugins/check_nwstat.c
index 12a729e0..3af63603 100644
--- a/plugins/check_nwstat.c
+++ b/plugins/check_nwstat.c
@@ -1,36 +1,36 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring check_nwstat plugin 3 * Monitoring check_nwstat plugin
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 2000-2007 Monitoring Plugins Development Team 6 * Copyright (c) 2000-2024 Monitoring Plugins Development Team
7* 7 *
8* Description: 8 * Description:
9* 9 *
10* This file contains the check_nwstat plugin 10 * This file contains the check_nwstat plugin
11* 11 *
12* This plugin attempts to contact the MRTGEXT NLM running on a 12 * This plugin attempts to contact the MRTGEXT NLM running on a
13* Novell server to gather the requested system information. 13 * Novell server to gather the requested system information.
14* 14 *
15* 15 *
16* This program is free software: you can redistribute it and/or modify 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 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 18 * the Free Software Foundation, either version 3 of the License, or
19* (at your option) any later version. 19 * (at your option) any later version.
20* 20 *
21* This program is distributed in the hope that it will be useful, 21 * This program is distributed in the hope that it will be useful,
22* but WITHOUT ANY WARRANTY; without even the implied warranty of 22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24* GNU General Public License for more details. 24 * GNU General Public License for more details.
25* 25 *
26* You should have received a copy of the GNU General Public License 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/>. 27 * along with this program. If not, see <http://www.gnu.org/licenses/>.
28* 28 *
29* 29 *
30*****************************************************************************/ 30 *****************************************************************************/
31 31
32const char *progname = "check_nwstat"; 32const char *progname = "check_nwstat";
33const char *copyright = "2000-2007"; 33const char *copyright = "2000-2024";
34const char *email = "devel@monitoring-plugins.org"; 34const char *email = "devel@monitoring-plugins.org";
35 35
36#include "common.h" 36#include "common.h"
@@ -44,9 +44,10 @@ enum checkvar {
44 LOAD15, /* check 15 minute CPU load */ 44 LOAD15, /* check 15 minute CPU load */
45 CONNS, /* check number of connections */ 45 CONNS, /* check number of connections */
46 VPF, /* check % free space on volume */ 46 VPF, /* check % free space on volume */
47 VMF, /* check MB free space on volume */ 47 VMF, /* check MB free space on volume */
48 VMU, /* check MB used space on volume */ 48 VMU, /* check MB used space on volume */
49 VMP, /* check MB purgeable space on volume */ 49 VPU, /* check % used space on volume */
50 VMP, /* check MB purgeable space on volume */
50 VKF, /* check KB free space on volume */ 51 VKF, /* check KB free space on volume */
51 LTCH, /* check long-term cache hit percentage */ 52 LTCH, /* check long-term cache hit percentage */
52 CBUFF, /* check total cache buffers */ 53 CBUFF, /* check total cache buffers */
@@ -54,7 +55,7 @@ enum checkvar {
54 LRUM, /* check LRU sitting time in minutes */ 55 LRUM, /* check LRU sitting time in minutes */
55 DSDB, /* check to see if DS Database is open */ 56 DSDB, /* check to see if DS Database is open */
56 LOGINS, /* check to see if logins are enabled */ 57 LOGINS, /* check to see if logins are enabled */
57 NRMH, /* check to see NRM Health Status */ 58 NRMH, /* check to see NRM Health Status */
58 PUPRB, /* check % of used packet receive buffers */ 59 PUPRB, /* check % of used packet receive buffers */
59 UPRB, /* check used packet receive buffers */ 60 UPRB, /* check used packet receive buffers */
60 SAPENTRIES, /* check SAP entries */ 61 SAPENTRIES, /* check SAP entries */
@@ -72,8 +73,8 @@ enum checkvar {
72 DSVER, /* check NDS version */ 73 DSVER, /* check NDS version */
73 UPTIME, /* check server uptime */ 74 UPTIME, /* check server uptime */
74 NLM, /* check NLM loaded */ 75 NLM, /* check NLM loaded */
75 NRMP, /* check NRM Process Values */ 76 NRMP, /* check NRM Process Values */
76 NRMM, /* check NRM Memory Values */ 77 NRMM, /* check NRM Memory Values */
77 NRMS, /* check NRM Values */ 78 NRMS, /* check NRM Values */
78 NSS1, /* check Statistics from _Admin:Manage_NSS\GeneralStats.xml */ 79 NSS1, /* check Statistics from _Admin:Manage_NSS\GeneralStats.xml */
79 NSS2, /* check Statistics from _Admin:Manage_NSS\BufferCache.xml */ 80 NSS2, /* check Statistics from _Admin:Manage_NSS\BufferCache.xml */
@@ -88,1600 +89,1439 @@ enum {
88 PORT = 9999 89 PORT = 9999
89}; 90};
90 91
91char *server_address=NULL; 92char *server_address = NULL;
92char *volume_name=NULL; 93char *volume_name = NULL;
93char *nlm_name=NULL; 94char *nlm_name = NULL;
94char *nrmp_name=NULL; 95char *nrmp_name = NULL;
95char *nrmm_name=NULL; 96char *nrmm_name = NULL;
96char *nrms_name=NULL; 97char *nrms_name = NULL;
97char *nss1_name=NULL; 98char *nss1_name = NULL;
98char *nss2_name=NULL; 99char *nss2_name = NULL;
99char *nss3_name=NULL; 100char *nss3_name = NULL;
100char *nss4_name=NULL; 101char *nss4_name = NULL;
101char *nss5_name=NULL; 102char *nss5_name = NULL;
102char *nss6_name=NULL; 103char *nss6_name = NULL;
103char *nss7_name=NULL; 104char *nss7_name = NULL;
104int server_port=PORT; 105int server_port = PORT;
105unsigned long warning_value=0L; 106unsigned long warning_value = 0L;
106unsigned long critical_value=0L; 107unsigned long critical_value = 0L;
107bool check_warning_value = false; 108bool check_warning_value = false;
108bool check_critical_value = false; 109bool check_critical_value = false;
109bool check_netware_version = false; 110bool check_netware_version = false;
110enum checkvar vars_to_check = NONE; 111enum checkvar vars_to_check = NONE;
111int sap_number=-1; 112int sap_number = -1;
112 113
113int process_arguments(int, char **); 114int process_arguments(int, char **);
114void print_help(void); 115void print_help(void);
115void print_usage(void); 116void print_usage(void);
116 117
117 118int main(int argc, char **argv) {
118
119int
120main(int argc, char **argv) {
121 int result = STATE_UNKNOWN; 119 int result = STATE_UNKNOWN;
122 int sd; 120 int sd;
123 char *send_buffer=NULL; 121 char *send_buffer = NULL;
124 char recv_buffer[MAX_INPUT_BUFFER]; 122 char recv_buffer[MAX_INPUT_BUFFER];
125 char *output_message=NULL; 123 char *output_message = NULL;
126 char *temp_buffer=NULL; 124 char *temp_buffer = NULL;
127 char *netware_version=NULL; 125 char *netware_version = NULL;
128 126
129 int time_sync_status=0; 127 int time_sync_status = 0;
130 int nrm_health_status=0; 128 int nrm_health_status = 0;
131 unsigned long total_cache_buffers=0; 129 unsigned long total_cache_buffers = 0;
132 unsigned long dirty_cache_buffers=0; 130 unsigned long dirty_cache_buffers = 0;
133 unsigned long open_files=0; 131 unsigned long open_files = 0;
134 unsigned long abended_threads=0; 132 unsigned long abended_threads = 0;
135 unsigned long max_service_processes=0; 133 unsigned long max_service_processes = 0;
136 unsigned long current_service_processes=0; 134 unsigned long current_service_processes = 0;
137 unsigned long free_disk_space=0L; 135 unsigned long free_disk_space = 0L;
138 unsigned long nrmp_value=0L; 136 unsigned long nrmp_value = 0L;
139 unsigned long nrmm_value=0L; 137 unsigned long nrmm_value = 0L;
140 unsigned long nrms_value=0L; 138 unsigned long nrms_value = 0L;
141 unsigned long nss1_value=0L; 139 unsigned long nss1_value = 0L;
142 unsigned long nss2_value=0L; 140 unsigned long nss2_value = 0L;
143 unsigned long nss3_value=0L; 141 unsigned long nss3_value = 0L;
144 unsigned long nss4_value=0L; 142 unsigned long nss4_value = 0L;
145 unsigned long nss5_value=0L; 143 unsigned long nss5_value = 0L;
146 unsigned long nss6_value=0L; 144 unsigned long nss6_value = 0L;
147 unsigned long nss7_value=0L; 145 unsigned long nss7_value = 0L;
148 unsigned long total_disk_space=0L; 146 unsigned long total_disk_space = 0L;
149 unsigned long purgeable_disk_space=0L; 147 unsigned long used_disk_space = 0L;
150 unsigned long non_purgeable_disk_space=0L; 148 unsigned long percent_used_disk_space = 0L;
151 unsigned long percent_free_space=0; 149 unsigned long purgeable_disk_space = 0L;
152 unsigned long percent_purgeable_space=0; 150 unsigned long non_purgeable_disk_space = 0L;
153 unsigned long percent_non_purgeable_space=0; 151 unsigned long percent_free_space = 0;
154 unsigned long current_connections=0L; 152 unsigned long percent_purgeable_space = 0;
155 unsigned long utilization=0L; 153 unsigned long percent_non_purgeable_space = 0;
156 unsigned long cache_hits=0; 154 unsigned long current_connections = 0L;
157 unsigned long cache_buffers=0L; 155 unsigned long utilization = 0L;
158 unsigned long lru_time=0L; 156 unsigned long cache_hits = 0;
159 unsigned long max_packet_receive_buffers=0; 157 unsigned long cache_buffers = 0L;
160 unsigned long used_packet_receive_buffers=0; 158 unsigned long lru_time = 0L;
161 unsigned long percent_used_packet_receive_buffers=0L; 159 unsigned long max_packet_receive_buffers = 0;
162 unsigned long sap_entries=0; 160 unsigned long used_packet_receive_buffers = 0;
161 unsigned long percent_used_packet_receive_buffers = 0L;
162 unsigned long sap_entries = 0;
163 char uptime[MAX_INPUT_BUFFER]; 163 char uptime[MAX_INPUT_BUFFER];
164 164
165 setlocale (LC_ALL, ""); 165 setlocale(LC_ALL, "");
166 bindtextdomain (PACKAGE, LOCALEDIR); 166 bindtextdomain(PACKAGE, LOCALEDIR);
167 textdomain (PACKAGE); 167 textdomain(PACKAGE);
168 168
169 /* Parse extra opts if any */ 169 /* Parse extra opts if any */
170 argv=np_extra_opts(&argc, argv, progname); 170 argv = np_extra_opts(&argc, argv, progname);
171 171
172 if (process_arguments(argc,argv) == ERROR) 172 if (process_arguments(argc, argv) == ERROR)
173 usage4 (_("Could not parse arguments")); 173 usage4(_("Could not parse arguments"));
174 174
175 /* initialize alarm signal handling */ 175 /* initialize alarm signal handling */
176 signal(SIGALRM,socket_timeout_alarm_handler); 176 signal(SIGALRM, socket_timeout_alarm_handler);
177 177
178 /* set socket timeout */ 178 /* set socket timeout */
179 alarm(socket_timeout); 179 alarm(socket_timeout);
180 180
181 /* open connection */ 181 /* open connection */
182 my_tcp_connect (server_address, server_port, &sd); 182 my_tcp_connect(server_address, server_port, &sd);
183 183
184 /* get OS version string */ 184 /* get OS version string */
185 if (check_netware_version) { 185 if (check_netware_version) {
186 send_buffer = strdup ("S19\r\n"); 186 send_buffer = strdup("S19\r\n");
187 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 187 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
188 if (result!=STATE_OK) 188 if (result != STATE_OK)
189 return result; 189 return result;
190 if (!strcmp(recv_buffer,"-1\n")) 190 if (!strcmp(recv_buffer, "-1\n"))
191 netware_version = strdup(""); 191 netware_version = strdup("");
192 else { 192 else {
193 recv_buffer[strlen(recv_buffer)-1]=0; 193 recv_buffer[strlen(recv_buffer) - 1] = 0;
194 xasprintf (&netware_version,_("NetWare %s: "),recv_buffer); 194 xasprintf(&netware_version, _("NetWare %s: "), recv_buffer);
195 } 195 }
196 } else 196 } else
197 netware_version = strdup(""); 197 netware_version = strdup("");
198 198
199
200 /* check CPU load */ 199 /* check CPU load */
201 if (vars_to_check==LOAD1 || vars_to_check==LOAD5 || vars_to_check==LOAD15) { 200 if (vars_to_check == LOAD1 || vars_to_check == LOAD5 || vars_to_check == LOAD15) {
202 201
203 switch(vars_to_check) { 202 switch (vars_to_check) {
204 case LOAD1: 203 case LOAD1:
205 temp_buffer = strdup ("1"); 204 temp_buffer = strdup("1");
206 break; 205 break;
207 case LOAD5: 206 case LOAD5:
208 temp_buffer = strdup ("5"); 207 temp_buffer = strdup("5");
209 break; 208 break;
210 default: 209 default:
211 temp_buffer = strdup ("15"); 210 temp_buffer = strdup("15");
212 break; 211 break;
213 } 212 }
214 213
215 close(sd); 214 close(sd);
216 my_tcp_connect (server_address, server_port, &sd); 215 my_tcp_connect(server_address, server_port, &sd);
217 216
218 xasprintf (&send_buffer,"UTIL%s\r\n",temp_buffer); 217 xasprintf(&send_buffer, "UTIL%s\r\n", temp_buffer);
219 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 218 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
220 if (result!=STATE_OK) 219 if (result != STATE_OK)
221 return result; 220 return result;
222 utilization=strtoul(recv_buffer,NULL,10); 221 utilization = strtoul(recv_buffer, NULL, 10);
223 222
224 close(sd); 223 close(sd);
225 my_tcp_connect (server_address, server_port, &sd); 224 my_tcp_connect(server_address, server_port, &sd);
226 225
227 send_buffer = strdup ("UPTIME\r\n"); 226 send_buffer = strdup("UPTIME\r\n");
228 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 227 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
229 if (result!=STATE_OK) 228 if (result != STATE_OK)
230 return result; 229 return result;
231 recv_buffer[strlen(recv_buffer)-1]=0; 230 recv_buffer[strlen(recv_buffer) - 1] = 0;
232 sprintf(uptime,_("Up %s,"),recv_buffer); 231 sprintf(uptime, _("Up %s,"), recv_buffer);
233 232
234 if (check_critical_value && utilization >= critical_value) 233 if (check_critical_value && utilization >= critical_value)
235 result=STATE_CRITICAL; 234 result = STATE_CRITICAL;
236 else if (check_warning_value && utilization >= warning_value) 235 else if (check_warning_value && utilization >= warning_value)
237 result=STATE_WARNING; 236 result = STATE_WARNING;
238 237
239 xasprintf (&output_message, 238 xasprintf(&output_message, _("Load %s - %s %s-min load average = %lu%%|load%s=%lu;%lu;%lu;0;100"), state_text(result), uptime,
240 _("Load %s - %s %s-min load average = %lu%%|load%s=%lu;%lu;%lu;0;100"), 239 temp_buffer, utilization, temp_buffer, utilization, warning_value, critical_value);
241 state_text(result),
242 uptime,
243 temp_buffer,
244 utilization,
245 temp_buffer,
246 utilization,
247 warning_value,
248 critical_value);
249 240
250 /* check number of user connections */ 241 /* check number of user connections */
251 } else if (vars_to_check==CONNS) { 242 } else if (vars_to_check == CONNS) {
252 243
253 close(sd); 244 close(sd);
254 my_tcp_connect (server_address, server_port, &sd); 245 my_tcp_connect(server_address, server_port, &sd);
255 246
256 send_buffer = strdup ("CONNECT\r\n"); 247 send_buffer = strdup("CONNECT\r\n");
257 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 248 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
258 if (result!=STATE_OK) 249 if (result != STATE_OK)
259 return result; 250 return result;
260 current_connections=strtoul(recv_buffer,NULL,10); 251 current_connections = strtoul(recv_buffer, NULL, 10);
261 252
262 if (check_critical_value && current_connections >= critical_value) 253 if (check_critical_value && current_connections >= critical_value)
263 result=STATE_CRITICAL; 254 result = STATE_CRITICAL;
264 else if (check_warning_value && current_connections >= warning_value) 255 else if (check_warning_value && current_connections >= warning_value)
265 result=STATE_WARNING; 256 result = STATE_WARNING;
266 257
267 xasprintf (&output_message, 258 xasprintf(&output_message, _("Conns %s - %lu current connections|Conns=%lu;%lu;%lu;;"), state_text(result), current_connections,
268 _("Conns %s - %lu current connections|Conns=%lu;%lu;%lu;;"), 259 current_connections, warning_value, critical_value);
269 state_text(result),
270 current_connections,
271 current_connections,
272 warning_value,
273 critical_value);
274 260
275 /* check % long term cache hits */ 261 /* check % long term cache hits */
276 } else if (vars_to_check==LTCH) { 262 } else if (vars_to_check == LTCH) {
277 263
278 close(sd); 264 close(sd);
279 my_tcp_connect (server_address, server_port, &sd); 265 my_tcp_connect(server_address, server_port, &sd);
280 266
281 send_buffer = strdup ("S1\r\n"); 267 send_buffer = strdup("S1\r\n");
282 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 268 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
283 if (result!=STATE_OK) 269 if (result != STATE_OK)
284 return result; 270 return result;
285 cache_hits=atoi(recv_buffer); 271 cache_hits = atoi(recv_buffer);
286 272
287 if (check_critical_value && cache_hits <= critical_value) 273 if (check_critical_value && cache_hits <= critical_value)
288 result=STATE_CRITICAL; 274 result = STATE_CRITICAL;
289 else if (check_warning_value && cache_hits <= warning_value) 275 else if (check_warning_value && cache_hits <= warning_value)
290 result=STATE_WARNING; 276 result = STATE_WARNING;
291 277
292 xasprintf (&output_message, 278 xasprintf(&output_message, _("%s: Long term cache hits = %lu%%"), state_text(result), cache_hits);
293 _("%s: Long term cache hits = %lu%%"),
294 state_text(result),
295 cache_hits);
296 279
297 /* check cache buffers */ 280 /* check cache buffers */
298 } else if (vars_to_check==CBUFF) { 281 } else if (vars_to_check == CBUFF) {
299 282
300 close(sd); 283 close(sd);
301 my_tcp_connect (server_address, server_port, &sd); 284 my_tcp_connect(server_address, server_port, &sd);
302 285
303 send_buffer = strdup ("S2\r\n"); 286 send_buffer = strdup("S2\r\n");
304 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 287 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
305 if (result!=STATE_OK) 288 if (result != STATE_OK)
306 return result; 289 return result;
307 cache_buffers=strtoul(recv_buffer,NULL,10); 290 cache_buffers = strtoul(recv_buffer, NULL, 10);
308 291
309 if (check_critical_value && cache_buffers <= critical_value) 292 if (check_critical_value && cache_buffers <= critical_value)
310 result=STATE_CRITICAL; 293 result = STATE_CRITICAL;
311 else if (check_warning_value && cache_buffers <= warning_value) 294 else if (check_warning_value && cache_buffers <= warning_value)
312 result=STATE_WARNING; 295 result = STATE_WARNING;
313 296
314 xasprintf (&output_message, 297 xasprintf(&output_message, _("%s: Total cache buffers = %lu|Cachebuffers=%lu;%lu;%lu;;"), state_text(result), cache_buffers,
315 _("%s: Total cache buffers = %lu|Cachebuffers=%lu;%lu;%lu;;"), 298 cache_buffers, warning_value, critical_value);
316 state_text(result),
317 cache_buffers,
318 cache_buffers,
319 warning_value,
320 critical_value);
321 299
322 /* check dirty cache buffers */ 300 /* check dirty cache buffers */
323 } else if (vars_to_check==CDBUFF) { 301 } else if (vars_to_check == CDBUFF) {
324 302
325 close(sd); 303 close(sd);
326 my_tcp_connect (server_address, server_port, &sd); 304 my_tcp_connect(server_address, server_port, &sd);
327 305
328 send_buffer = strdup ("S3\r\n"); 306 send_buffer = strdup("S3\r\n");
329 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 307 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
330 if (result!=STATE_OK) 308 if (result != STATE_OK)
331 return result; 309 return result;
332 cache_buffers=strtoul(recv_buffer,NULL,10); 310 cache_buffers = strtoul(recv_buffer, NULL, 10);
333 311
334 if (check_critical_value && cache_buffers >= critical_value) 312 if (check_critical_value && cache_buffers >= critical_value)
335 result=STATE_CRITICAL; 313 result = STATE_CRITICAL;
336 else if (check_warning_value && cache_buffers >= warning_value) 314 else if (check_warning_value && cache_buffers >= warning_value)
337 result=STATE_WARNING; 315 result = STATE_WARNING;
338 316
339 xasprintf (&output_message, 317 xasprintf(&output_message, _("%s: Dirty cache buffers = %lu|Dirty-Cache-Buffers=%lu;%lu;%lu;;"), state_text(result), cache_buffers,
340 _("%s: Dirty cache buffers = %lu|Dirty-Cache-Buffers=%lu;%lu;%lu;;"), 318 cache_buffers, warning_value, critical_value);
341 state_text(result),
342 cache_buffers,
343 cache_buffers,
344 warning_value,
345 critical_value);
346 319
347 /* check LRU sitting time in minutes */ 320 /* check LRU sitting time in minutes */
348 } else if (vars_to_check==LRUM) { 321 } else if (vars_to_check == LRUM) {
349 322
350 close(sd); 323 close(sd);
351 my_tcp_connect (server_address, server_port, &sd); 324 my_tcp_connect(server_address, server_port, &sd);
352 325
353 send_buffer = strdup ("S5\r\n"); 326 send_buffer = strdup("S5\r\n");
354 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 327 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
355 if (result!=STATE_OK) 328 if (result != STATE_OK)
356 return result; 329 return result;
357 lru_time=strtoul(recv_buffer,NULL,10); 330 lru_time = strtoul(recv_buffer, NULL, 10);
358 331
359 if (check_critical_value && lru_time <= critical_value) 332 if (check_critical_value && lru_time <= critical_value)
360 result=STATE_CRITICAL; 333 result = STATE_CRITICAL;
361 else if (check_warning_value && lru_time <= warning_value) 334 else if (check_warning_value && lru_time <= warning_value)
362 result=STATE_WARNING; 335 result = STATE_WARNING;
363
364 xasprintf (&output_message,
365 _("%s: LRU sitting time = %lu minutes"),
366 state_text(result),
367 lru_time);
368 336
337 xasprintf(&output_message, _("%s: LRU sitting time = %lu minutes"), state_text(result), lru_time);
369 338
370 /* check KB free space on volume */ 339 /* check KB free space on volume */
371 } else if (vars_to_check==VKF) { 340 } else if (vars_to_check == VKF) {
372 341
373 close(sd); 342 close(sd);
374 my_tcp_connect (server_address, server_port, &sd); 343 my_tcp_connect(server_address, server_port, &sd);
375 344
376 xasprintf (&send_buffer,"VKF%s\r\n",volume_name); 345 xasprintf(&send_buffer, "VKF%s\r\n", volume_name);
377 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 346 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
378 if (result!=STATE_OK) 347 if (result != STATE_OK)
379 return result; 348 return result;
380 349
381 if (!strcmp(recv_buffer,"-1\n")) { 350 if (!strcmp(recv_buffer, "-1\n")) {
382 xasprintf (&output_message,_("CRITICAL - Volume '%s' does not exist!"),volume_name); 351 xasprintf(&output_message, _("CRITICAL - Volume '%s' does not exist!"), volume_name);
383 result=STATE_CRITICAL; 352 result = STATE_CRITICAL;
384 } else { 353 } else {
385 free_disk_space=strtoul(recv_buffer,NULL,10); 354 free_disk_space = strtoul(recv_buffer, NULL, 10);
386 if (check_critical_value && free_disk_space <= critical_value) 355 if (check_critical_value && free_disk_space <= critical_value)
387 result=STATE_CRITICAL; 356 result = STATE_CRITICAL;
388 else if (check_warning_value && free_disk_space <= warning_value) 357 else if (check_warning_value && free_disk_space <= warning_value)
389 result=STATE_WARNING; 358 result = STATE_WARNING;
390 xasprintf (&output_message, 359 xasprintf(&output_message, _("%s%lu KB free on volume %s|KBFree%s=%lu;%lu;%lu;;"), (result == STATE_OK) ? "" : _("Only "),
391 _("%s%lu KB free on volume %s|KBFree%s=%lu;%lu;%lu;;"), 360 free_disk_space, volume_name, volume_name, free_disk_space, warning_value, critical_value);
392 (result==STATE_OK)?"":_("Only "),
393 free_disk_space,
394 volume_name,
395 volume_name,
396 free_disk_space,
397 warning_value,
398 critical_value);
399 } 361 }
400 362
401 /* check MB free space on volume */ 363 /* check MB free space on volume */
402 } else if (vars_to_check==VMF) { 364 } else if (vars_to_check == VMF) {
403 365
404 xasprintf (&send_buffer,"VMF%s\r\n",volume_name); 366 xasprintf(&send_buffer, "VMF%s\r\n", volume_name);
405 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 367 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
406 if (result!=STATE_OK) 368 if (result != STATE_OK)
407 return result; 369 return result;
408 370
409 if (!strcmp(recv_buffer,"-1\n")) { 371 if (!strcmp(recv_buffer, "-1\n")) {
410 xasprintf (&output_message,_("CRITICAL - Volume '%s' does not exist!"),volume_name); 372 xasprintf(&output_message, _("CRITICAL - Volume '%s' does not exist!"), volume_name);
411 result=STATE_CRITICAL; 373 result = STATE_CRITICAL;
412 } else { 374 } else {
413 free_disk_space=strtoul(recv_buffer,NULL,10); 375 free_disk_space = strtoul(recv_buffer, NULL, 10);
414 if (check_critical_value && free_disk_space <= critical_value) 376 if (check_critical_value && free_disk_space <= critical_value)
415 result=STATE_CRITICAL; 377 result = STATE_CRITICAL;
416 else if (check_warning_value && free_disk_space <= warning_value) 378 else if (check_warning_value && free_disk_space <= warning_value)
417 result=STATE_WARNING; 379 result = STATE_WARNING;
418 xasprintf (&output_message, 380 xasprintf(&output_message, _("%s%lu MB free on volume %s|MBFree%s=%lu;%lu;%lu;;"), (result == STATE_OK) ? "" : _("Only "),
419 _("%s%lu MB free on volume %s|MBFree%s=%lu;%lu;%lu;;"), 381 free_disk_space, volume_name, volume_name, free_disk_space, warning_value, critical_value);
420 (result==STATE_OK)?"":_("Only "),
421 free_disk_space,
422 volume_name,
423 volume_name,
424 free_disk_space,
425 warning_value,
426 critical_value);
427 } 382 }
428 /* check MB used space on volume */ 383 /* check MB used space on volume */
429 } else if (vars_to_check==VMU) { 384 } else if (vars_to_check == VMU) {
430 385
431 xasprintf (&send_buffer,"VMU%s\r\n",volume_name); 386 xasprintf(&send_buffer, "VMU%s\r\n", volume_name);
432 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 387 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
433 if (result!=STATE_OK) 388 if (result != STATE_OK)
434 return result; 389 return result;
435 390
436 if (!strcmp(recv_buffer,"-1\n")) { 391 if (!strcmp(recv_buffer, "-1\n")) {
437 xasprintf (&output_message,_("CRITICAL - Volume '%s' does not exist!"),volume_name); 392 xasprintf(&output_message, _("CRITICAL - Volume '%s' does not exist!"), volume_name);
438 result=STATE_CRITICAL; 393 result = STATE_CRITICAL;
439 } else { 394 } else {
440 free_disk_space=strtoul(recv_buffer,NULL,10); 395 free_disk_space = strtoul(recv_buffer, NULL, 10);
441 if (check_critical_value && free_disk_space <= critical_value) 396 if (check_critical_value && free_disk_space <= critical_value)
442 result=STATE_CRITICAL; 397 result = STATE_CRITICAL;
443 else if (check_warning_value && free_disk_space <= warning_value) 398 else if (check_warning_value && free_disk_space <= warning_value)
444 result=STATE_WARNING; 399 result = STATE_WARNING;
445 xasprintf (&output_message, 400 xasprintf(&output_message, _("%s%lu MB used on volume %s|MBUsed%s=%lu;%lu;%lu;;"), (result == STATE_OK) ? "" : _("Only "),
446 _("%s%lu MB used on volume %s|MBUsed%s=%lu;%lu;%lu;;"), 401 free_disk_space, volume_name, volume_name, free_disk_space, warning_value, critical_value);
447 (result==STATE_OK)?"":_("Only "),
448 free_disk_space,
449 volume_name,
450 volume_name,
451 free_disk_space,
452 warning_value,
453 critical_value);
454 } 402 }
403 /* check % used space on volume */
404 } else if (vars_to_check == VPU) {
405 close(sd);
406 my_tcp_connect(server_address, server_port, &sd);
407
408 asprintf(&send_buffer, "VMU%s\r\n", volume_name);
409 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
410
411 if (result != STATE_OK)
412 return result;
413
414 if (!strcmp(recv_buffer, "-1\n")) {
415 asprintf(&output_message, _("CRITICAL - Volume '%s' does not exist!"), volume_name);
416 result = STATE_CRITICAL;
455 417
418 } else {
419 used_disk_space = strtoul(recv_buffer, NULL, 10);
420 close(sd);
421 my_tcp_connect(server_address, server_port, &sd);
422 /* get total volume in MB */
423 asprintf(&send_buffer, "VMS%s\r\n", volume_name);
424 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
425 if (result != STATE_OK)
426 return result;
427 total_disk_space = strtoul(recv_buffer, NULL, 10);
428 /* calculate percent used on volume */
429 percent_used_disk_space = (unsigned long)(((double)used_disk_space / (double)total_disk_space) * 100.0);
430
431 if (check_critical_value && percent_used_disk_space >= critical_value)
432 result = STATE_CRITICAL;
433 else if (check_warning_value && percent_used_disk_space >= warning_value)
434 result = STATE_WARNING;
435
436 asprintf(&output_message, _("%lu MB (%lu%%) used on volume %s - total %lu MB|Used space in percent on %s=%lu;%lu;%lu;0;100"),
437 used_disk_space, percent_used_disk_space, volume_name, total_disk_space, volume_name, percent_used_disk_space,
438 warning_value, critical_value);
439 }
456 440
457 /* check % free space on volume */ 441 /* check % free space on volume */
458 } else if (vars_to_check==VPF) { 442 } else if (vars_to_check == VPF) {
459 443
460 close(sd); 444 close(sd);
461 my_tcp_connect (server_address, server_port, &sd); 445 my_tcp_connect(server_address, server_port, &sd);
462 446
463 xasprintf (&send_buffer,"VKF%s\r\n",volume_name); 447 xasprintf(&send_buffer, "VKF%s\r\n", volume_name);
464 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 448 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
465 if (result!=STATE_OK) 449 if (result != STATE_OK)
466 return result; 450 return result;
467 451
468 if (!strcmp(recv_buffer,"-1\n")) { 452 if (!strcmp(recv_buffer, "-1\n")) {
469 453
470 xasprintf (&output_message,_("CRITICAL - Volume '%s' does not exist!"),volume_name); 454 xasprintf(&output_message, _("CRITICAL - Volume '%s' does not exist!"), volume_name);
471 result=STATE_CRITICAL; 455 result = STATE_CRITICAL;
472 456
473 } else { 457 } else {
474 458
475 free_disk_space=strtoul(recv_buffer,NULL,10); 459 free_disk_space = strtoul(recv_buffer, NULL, 10);
476 460
477 close(sd); 461 close(sd);
478 my_tcp_connect (server_address, server_port, &sd); 462 my_tcp_connect(server_address, server_port, &sd);
479 463
480 xasprintf (&send_buffer,"VKS%s\r\n",volume_name); 464 xasprintf(&send_buffer, "VKS%s\r\n", volume_name);
481 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 465 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
482 if (result!=STATE_OK) 466 if (result != STATE_OK)
483 return result; 467 return result;
484 total_disk_space=strtoul(recv_buffer,NULL,10); 468 total_disk_space = strtoul(recv_buffer, NULL, 10);
485 469
486 percent_free_space=(unsigned long)(((double)free_disk_space/(double)total_disk_space)*100.0); 470 percent_free_space = (unsigned long)(((double)free_disk_space / (double)total_disk_space) * 100.0);
487 471
488 if (check_critical_value && percent_free_space <= critical_value) 472 if (check_critical_value && percent_free_space <= critical_value)
489 result=STATE_CRITICAL; 473 result = STATE_CRITICAL;
490 else if (check_warning_value && percent_free_space <= warning_value) 474 else if (check_warning_value && percent_free_space <= warning_value)
491 result=STATE_WARNING; 475 result = STATE_WARNING;
492 free_disk_space/=1024; 476 free_disk_space /= 1024;
493 total_disk_space/=1024; 477 total_disk_space /= 1024;
494 xasprintf (&output_message,_("%lu MB (%lu%%) free on volume %s - total %lu MB|FreeMB%s=%lu;%lu;%lu;0;100"), 478 xasprintf(&output_message, _("%lu MB (%lu%%) free on volume %s - total %lu MB|FreeMB%s=%lu;%lu;%lu;0;100"), free_disk_space,
495 free_disk_space, 479 percent_free_space, volume_name, total_disk_space, volume_name, percent_free_space, warning_value, critical_value);
496 percent_free_space,
497 volume_name,
498 total_disk_space,
499 volume_name,
500 percent_free_space,
501 warning_value,
502 critical_value
503 );
504 } 480 }
505 481
506 /* check to see if DS Database is open or closed */ 482 /* check to see if DS Database is open or closed */
507 } else if (vars_to_check==DSDB) { 483 } else if (vars_to_check == DSDB) {
508 484
509 close(sd); 485 close(sd);
510 my_tcp_connect (server_address, server_port, &sd); 486 my_tcp_connect(server_address, server_port, &sd);
511 487
512 send_buffer = strdup ("S11\r\n"); 488 send_buffer = strdup("S11\r\n");
513 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 489 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
514 if (result!=STATE_OK) 490 if (result != STATE_OK)
515 return result; 491 return result;
516 if (atoi(recv_buffer)==1) 492 if (atoi(recv_buffer) == 1)
517 result=STATE_OK; 493 result = STATE_OK;
518 else 494 else
519 result=STATE_WARNING; 495 result = STATE_WARNING;
520 496
521 close(sd); 497 close(sd);
522 my_tcp_connect (server_address, server_port, &sd); 498 my_tcp_connect(server_address, server_port, &sd);
523 499
524 send_buffer = strdup ("S13\r\n"); 500 send_buffer = strdup("S13\r\n");
525 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 501 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
526 temp_buffer=strtok(recv_buffer,"\r\n"); 502 temp_buffer = strtok(recv_buffer, "\r\n");
527 503
528 xasprintf (&output_message,_("Directory Services Database is %s (DS version %s)"),(result==STATE_OK)?"open":"closed",temp_buffer); 504 xasprintf(&output_message, _("Directory Services Database is %s (DS version %s)"), (result == STATE_OK) ? "open" : "closed",
505 temp_buffer);
529 506
530 /* check to see if logins are enabled */ 507 /* check to see if logins are enabled */
531 } else if (vars_to_check==LOGINS) { 508 } else if (vars_to_check == LOGINS) {
532 509
533 close(sd); 510 close(sd);
534 my_tcp_connect (server_address, server_port, &sd); 511 my_tcp_connect(server_address, server_port, &sd);
535 512
536 send_buffer = strdup ("S12\r\n"); 513 send_buffer = strdup("S12\r\n");
537 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 514 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
538 if (result!=STATE_OK) 515 if (result != STATE_OK)
539 return result; 516 return result;
540 if (atoi(recv_buffer)==1) 517 if (atoi(recv_buffer) == 1)
541 result=STATE_OK; 518 result = STATE_OK;
542 else 519 else
543 result=STATE_WARNING; 520 result = STATE_WARNING;
544
545 xasprintf (&output_message,_("Logins are %s"),(result==STATE_OK)?_("enabled"):_("disabled"));
546 521
522 xasprintf(&output_message, _("Logins are %s"), (result == STATE_OK) ? _("enabled") : _("disabled"));
547 523
548 /* check NRM Health Status Summary*/ 524 /* check NRM Health Status Summary*/
549 } else if (vars_to_check==NRMH) { 525 } else if (vars_to_check == NRMH) {
550 526
551 xasprintf (&send_buffer,"NRMH\r\n"); 527 xasprintf(&send_buffer, "NRMH\r\n");
552 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 528 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
553 if (result!=STATE_OK) 529 if (result != STATE_OK)
554 return result; 530 return result;
555 531
556 nrm_health_status=atoi(recv_buffer); 532 nrm_health_status = atoi(recv_buffer);
557 533
558 if (nrm_health_status==2) { 534 if (nrm_health_status == 2) {
559 result=STATE_OK; 535 result = STATE_OK;
560 xasprintf (&output_message,_("CRITICAL - NRM Status is bad!")); 536 xasprintf(&output_message, _("CRITICAL - NRM Status is bad!"));
561 } 537 } else {
562 else { 538 if (nrm_health_status == 1) {
563 if (nrm_health_status==1) { 539 result = STATE_WARNING;
564 result=STATE_WARNING; 540 xasprintf(&output_message, _("Warning - NRM Status is suspect!"));
565 xasprintf (&output_message,_("Warning - NRM Status is suspect!"));
566 } 541 }
567 542
568 xasprintf (&output_message,_("OK - NRM Status is good!")); 543 xasprintf(&output_message, _("OK - NRM Status is good!"));
569 } 544 }
570 545
571
572
573 /* check packet receive buffers */ 546 /* check packet receive buffers */
574 } else if (vars_to_check==UPRB || vars_to_check==PUPRB) { 547 } else if (vars_to_check == UPRB || vars_to_check == PUPRB) {
575 548
576 close(sd); 549 close(sd);
577 my_tcp_connect (server_address, server_port, &sd); 550 my_tcp_connect(server_address, server_port, &sd);
578 551
579 xasprintf (&send_buffer,"S15\r\n"); 552 xasprintf(&send_buffer, "S15\r\n");
580 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 553 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
581 if (result!=STATE_OK) 554 if (result != STATE_OK)
582 return result; 555 return result;
583 556
584 used_packet_receive_buffers=atoi(recv_buffer); 557 used_packet_receive_buffers = atoi(recv_buffer);
585 558
586 close(sd); 559 close(sd);
587 my_tcp_connect (server_address, server_port, &sd); 560 my_tcp_connect(server_address, server_port, &sd);
588 561
589 xasprintf (&send_buffer,"S16\r\n"); 562 xasprintf(&send_buffer, "S16\r\n");
590 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 563 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
591 if (result!=STATE_OK) 564 if (result != STATE_OK)
592 return result; 565 return result;
593 566
594 max_packet_receive_buffers=atoi(recv_buffer); 567 max_packet_receive_buffers = atoi(recv_buffer);
595 568
596 percent_used_packet_receive_buffers=(unsigned long)(((double)used_packet_receive_buffers/(double)max_packet_receive_buffers)*100.0); 569 percent_used_packet_receive_buffers =
570 (unsigned long)(((double)used_packet_receive_buffers / (double)max_packet_receive_buffers) * 100.0);
597 571
598 if (vars_to_check==UPRB) { 572 if (vars_to_check == UPRB) {
599 if (check_critical_value && used_packet_receive_buffers >= critical_value) 573 if (check_critical_value && used_packet_receive_buffers >= critical_value)
600 result=STATE_CRITICAL; 574 result = STATE_CRITICAL;
601 else if (check_warning_value && used_packet_receive_buffers >= warning_value) 575 else if (check_warning_value && used_packet_receive_buffers >= warning_value)
602 result=STATE_WARNING; 576 result = STATE_WARNING;
603 } else { 577 } else {
604 if (check_critical_value && percent_used_packet_receive_buffers >= critical_value) 578 if (check_critical_value && percent_used_packet_receive_buffers >= critical_value)
605 result=STATE_CRITICAL; 579 result = STATE_CRITICAL;
606 else if (check_warning_value && percent_used_packet_receive_buffers >= warning_value) 580 else if (check_warning_value && percent_used_packet_receive_buffers >= warning_value)
607 result=STATE_WARNING; 581 result = STATE_WARNING;
608 } 582 }
609 583
610 xasprintf (&output_message,_("%lu of %lu (%lu%%) packet receive buffers used"),used_packet_receive_buffers,max_packet_receive_buffers,percent_used_packet_receive_buffers); 584 xasprintf(&output_message, _("%lu of %lu (%lu%%) packet receive buffers used"), used_packet_receive_buffers,
585 max_packet_receive_buffers, percent_used_packet_receive_buffers);
611 586
612 /* check SAP table entries */ 587 /* check SAP table entries */
613 } else if (vars_to_check==SAPENTRIES) { 588 } else if (vars_to_check == SAPENTRIES) {
614 589
615 close(sd); 590 close(sd);
616 my_tcp_connect (server_address, server_port, &sd); 591 my_tcp_connect(server_address, server_port, &sd);
617 592
618 if (sap_number==-1) 593 if (sap_number == -1)
619 xasprintf (&send_buffer,"S9\r\n"); 594 xasprintf(&send_buffer, "S9\r\n");
620 else 595 else
621 xasprintf (&send_buffer,"S9.%d\r\n",sap_number); 596 xasprintf(&send_buffer, "S9.%d\r\n", sap_number);
622 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 597 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
623 if (result!=STATE_OK) 598 if (result != STATE_OK)
624 return result; 599 return result;
625 600
626 sap_entries=atoi(recv_buffer); 601 sap_entries = atoi(recv_buffer);
627 602
628 if (check_critical_value && sap_entries >= critical_value) 603 if (check_critical_value && sap_entries >= critical_value)
629 result=STATE_CRITICAL; 604 result = STATE_CRITICAL;
630 else if (check_warning_value && sap_entries >= warning_value) 605 else if (check_warning_value && sap_entries >= warning_value)
631 result=STATE_WARNING; 606 result = STATE_WARNING;
632 607
633 if (sap_number==-1) 608 if (sap_number == -1)
634 xasprintf (&output_message,_("%lu entries in SAP table"),sap_entries); 609 xasprintf(&output_message, _("%lu entries in SAP table"), sap_entries);
635 else 610 else
636 xasprintf (&output_message,_("%lu entries in SAP table for SAP type %d"),sap_entries,sap_number); 611 xasprintf(&output_message, _("%lu entries in SAP table for SAP type %d"), sap_entries, sap_number);
637 612
638 /* check KB purgeable space on volume */ 613 /* check KB purgeable space on volume */
639 } else if (vars_to_check==VKP) { 614 } else if (vars_to_check == VKP) {
640 615
641 close(sd); 616 close(sd);
642 my_tcp_connect (server_address, server_port, &sd); 617 my_tcp_connect(server_address, server_port, &sd);
643 618
644 xasprintf (&send_buffer,"VKP%s\r\n",volume_name); 619 xasprintf(&send_buffer, "VKP%s\r\n", volume_name);
645 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 620 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
646 if (result!=STATE_OK) 621 if (result != STATE_OK)
647 return result; 622 return result;
648 623
649 if (!strcmp(recv_buffer,"-1\n")) { 624 if (!strcmp(recv_buffer, "-1\n")) {
650 xasprintf (&output_message,_("CRITICAL - Volume '%s' does not exist!"),volume_name); 625 xasprintf(&output_message, _("CRITICAL - Volume '%s' does not exist!"), volume_name);
651 result=STATE_CRITICAL; 626 result = STATE_CRITICAL;
652 } else { 627 } else {
653 purgeable_disk_space=strtoul(recv_buffer,NULL,10); 628 purgeable_disk_space = strtoul(recv_buffer, NULL, 10);
654 if (check_critical_value && purgeable_disk_space >= critical_value) 629 if (check_critical_value && purgeable_disk_space >= critical_value)
655 result=STATE_CRITICAL; 630 result = STATE_CRITICAL;
656 else if (check_warning_value && purgeable_disk_space >= warning_value) 631 else if (check_warning_value && purgeable_disk_space >= warning_value)
657 result=STATE_WARNING; 632 result = STATE_WARNING;
658 xasprintf (&output_message,_("%s%lu KB purgeable on volume %s|Purge%s=%lu;%lu;%lu;;"), 633 xasprintf(&output_message, _("%s%lu KB purgeable on volume %s|Purge%s=%lu;%lu;%lu;;"), (result == STATE_OK) ? "" : _("Only "),
659 (result==STATE_OK)?"":_("Only "), 634 purgeable_disk_space, volume_name, volume_name, purgeable_disk_space, warning_value, critical_value);
660 purgeable_disk_space,
661 volume_name,
662 volume_name,
663 purgeable_disk_space,
664 warning_value,
665 critical_value);
666 } 635 }
667 /* check MB purgeable space on volume */ 636 /* check MB purgeable space on volume */
668 } else if (vars_to_check==VMP) { 637 } else if (vars_to_check == VMP) {
669 638
670 xasprintf (&send_buffer,"VMP%s\r\n",volume_name); 639 xasprintf(&send_buffer, "VMP%s\r\n", volume_name);
671 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 640 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
672 if (result!=STATE_OK) 641 if (result != STATE_OK)
673 return result; 642 return result;
674 643
675 if (!strcmp(recv_buffer,"-1\n")) { 644 if (!strcmp(recv_buffer, "-1\n")) {
676 xasprintf (&output_message,_("CRITICAL - Volume '%s' does not exist!"),volume_name); 645 xasprintf(&output_message, _("CRITICAL - Volume '%s' does not exist!"), volume_name);
677 result=STATE_CRITICAL; 646 result = STATE_CRITICAL;
678 } else { 647 } else {
679 purgeable_disk_space=strtoul(recv_buffer,NULL,10); 648 purgeable_disk_space = strtoul(recv_buffer, NULL, 10);
680 if (check_critical_value && purgeable_disk_space >= critical_value) 649 if (check_critical_value && purgeable_disk_space >= critical_value)
681 result=STATE_CRITICAL; 650 result = STATE_CRITICAL;
682 else if (check_warning_value && purgeable_disk_space >= warning_value) 651 else if (check_warning_value && purgeable_disk_space >= warning_value)
683 result=STATE_WARNING; 652 result = STATE_WARNING;
684 xasprintf (&output_message,_("%s%lu MB purgeable on volume %s|Purge%s=%lu;%lu;%lu;;"), 653 xasprintf(&output_message, _("%s%lu MB purgeable on volume %s|Purge%s=%lu;%lu;%lu;;"), (result == STATE_OK) ? "" : _("Only "),
685 (result==STATE_OK)?"":_("Only "), 654 purgeable_disk_space, volume_name, volume_name, purgeable_disk_space, warning_value, critical_value);
686 purgeable_disk_space,
687 volume_name,
688 volume_name,
689 purgeable_disk_space,
690 warning_value,
691 critical_value);
692 } 655 }
693 656
694 /* check % purgeable space on volume */ 657 /* check % purgeable space on volume */
695 } else if (vars_to_check==VPP) { 658 } else if (vars_to_check == VPP) {
696 659
697 close(sd); 660 close(sd);
698 my_tcp_connect (server_address, server_port, &sd); 661 my_tcp_connect(server_address, server_port, &sd);
699 662
700 xasprintf (&send_buffer,"VKP%s\r\n",volume_name); 663 xasprintf(&send_buffer, "VKP%s\r\n", volume_name);
701 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 664 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
702 if (result!=STATE_OK) 665 if (result != STATE_OK)
703 return result; 666 return result;
704 667
705 if (!strcmp(recv_buffer,"-1\n")) { 668 if (!strcmp(recv_buffer, "-1\n")) {
706 669
707 xasprintf (&output_message,_("CRITICAL - Volume '%s' does not exist!"),volume_name); 670 xasprintf(&output_message, _("CRITICAL - Volume '%s' does not exist!"), volume_name);
708 result=STATE_CRITICAL; 671 result = STATE_CRITICAL;
709 672
710 } else { 673 } else {
711 674
712 purgeable_disk_space=strtoul(recv_buffer,NULL,10); 675 purgeable_disk_space = strtoul(recv_buffer, NULL, 10);
713 676
714 close(sd); 677 close(sd);
715 my_tcp_connect (server_address, server_port, &sd); 678 my_tcp_connect(server_address, server_port, &sd);
716 679
717 xasprintf (&send_buffer,"VKS%s\r\n",volume_name); 680 xasprintf(&send_buffer, "VKS%s\r\n", volume_name);
718 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 681 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
719 if (result!=STATE_OK) 682 if (result != STATE_OK)
720 return result; 683 return result;
721 total_disk_space=strtoul(recv_buffer,NULL,10); 684 total_disk_space = strtoul(recv_buffer, NULL, 10);
722 685
723 percent_purgeable_space=(unsigned long)(((double)purgeable_disk_space/(double)total_disk_space)*100.0); 686 percent_purgeable_space = (unsigned long)(((double)purgeable_disk_space / (double)total_disk_space) * 100.0);
724 687
725 if (check_critical_value && percent_purgeable_space >= critical_value) 688 if (check_critical_value && percent_purgeable_space >= critical_value)
726 result=STATE_CRITICAL; 689 result = STATE_CRITICAL;
727 else if (check_warning_value && percent_purgeable_space >= warning_value) 690 else if (check_warning_value && percent_purgeable_space >= warning_value)
728 result=STATE_WARNING; 691 result = STATE_WARNING;
729 purgeable_disk_space/=1024; 692 purgeable_disk_space /= 1024;
730 xasprintf (&output_message,_("%lu MB (%lu%%) purgeable on volume %s|Purgeable%s=%lu;%lu;%lu;0;100"), 693 xasprintf(&output_message, _("%lu MB (%lu%%) purgeable on volume %s|Purgeable%s=%lu;%lu;%lu;0;100"), purgeable_disk_space,
731 purgeable_disk_space, 694 percent_purgeable_space, volume_name, volume_name, percent_purgeable_space, warning_value, critical_value);
732 percent_purgeable_space,
733 volume_name,
734 volume_name,
735 percent_purgeable_space,
736 warning_value,
737 critical_value
738 );
739 } 695 }
740 696
741 /* check KB not yet purgeable space on volume */ 697 /* check KB not yet purgeable space on volume */
742 } else if (vars_to_check==VKNP) { 698 } else if (vars_to_check == VKNP) {
743 699
744 close(sd); 700 close(sd);
745 my_tcp_connect (server_address, server_port, &sd); 701 my_tcp_connect(server_address, server_port, &sd);
746 702
747 xasprintf (&send_buffer,"VKNP%s\r\n",volume_name); 703 xasprintf(&send_buffer, "VKNP%s\r\n", volume_name);
748 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 704 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
749 if (result!=STATE_OK) 705 if (result != STATE_OK)
750 return result; 706 return result;
751 707
752 if (!strcmp(recv_buffer,"-1\n")) { 708 if (!strcmp(recv_buffer, "-1\n")) {
753 xasprintf (&output_message,_("CRITICAL - Volume '%s' does not exist!"),volume_name); 709 xasprintf(&output_message, _("CRITICAL - Volume '%s' does not exist!"), volume_name);
754 result=STATE_CRITICAL; 710 result = STATE_CRITICAL;
755 } else { 711 } else {
756 non_purgeable_disk_space=strtoul(recv_buffer,NULL,10); 712 non_purgeable_disk_space = strtoul(recv_buffer, NULL, 10);
757 if (check_critical_value && non_purgeable_disk_space >= critical_value) 713 if (check_critical_value && non_purgeable_disk_space >= critical_value)
758 result=STATE_CRITICAL; 714 result = STATE_CRITICAL;
759 else if (check_warning_value && non_purgeable_disk_space >= warning_value) 715 else if (check_warning_value && non_purgeable_disk_space >= warning_value)
760 result=STATE_WARNING; 716 result = STATE_WARNING;
761 xasprintf (&output_message,_("%s%lu KB not yet purgeable on volume %s"),(result==STATE_OK)?"":_("Only "),non_purgeable_disk_space,volume_name); 717 xasprintf(&output_message, _("%s%lu KB not yet purgeable on volume %s"), (result == STATE_OK) ? "" : _("Only "),
718 non_purgeable_disk_space, volume_name);
762 } 719 }
763 720
764 /* check % not yet purgeable space on volume */ 721 /* check % not yet purgeable space on volume */
765 } else if (vars_to_check==VPNP) { 722 } else if (vars_to_check == VPNP) {
766 723
767 close(sd); 724 close(sd);
768 my_tcp_connect (server_address, server_port, &sd); 725 my_tcp_connect(server_address, server_port, &sd);
769 726
770 xasprintf (&send_buffer,"VKNP%s\r\n",volume_name); 727 xasprintf(&send_buffer, "VKNP%s\r\n", volume_name);
771 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 728 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
772 if (result!=STATE_OK) 729 if (result != STATE_OK)
773 return result; 730 return result;
774 731
775 if (!strcmp(recv_buffer,"-1\n")) { 732 if (!strcmp(recv_buffer, "-1\n")) {
776 733
777 xasprintf (&output_message,_("CRITICAL - Volume '%s' does not exist!"),volume_name); 734 xasprintf(&output_message, _("CRITICAL - Volume '%s' does not exist!"), volume_name);
778 result=STATE_CRITICAL; 735 result = STATE_CRITICAL;
779 736
780 } else { 737 } else {
781 738
782 non_purgeable_disk_space=strtoul(recv_buffer,NULL,10); 739 non_purgeable_disk_space = strtoul(recv_buffer, NULL, 10);
783 740
784 close(sd); 741 close(sd);
785 my_tcp_connect (server_address, server_port, &sd); 742 my_tcp_connect(server_address, server_port, &sd);
786 743
787 xasprintf (&send_buffer,"VKS%s\r\n",volume_name); 744 xasprintf(&send_buffer, "VKS%s\r\n", volume_name);
788 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 745 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
789 if (result!=STATE_OK) 746 if (result != STATE_OK)
790 return result; 747 return result;
791 total_disk_space=strtoul(recv_buffer,NULL,10); 748 total_disk_space = strtoul(recv_buffer, NULL, 10);
792 749
793 percent_non_purgeable_space=(unsigned long)(((double)non_purgeable_disk_space/(double)total_disk_space)*100.0); 750 percent_non_purgeable_space = (unsigned long)(((double)non_purgeable_disk_space / (double)total_disk_space) * 100.0);
794 751
795 if (check_critical_value && percent_non_purgeable_space >= critical_value) 752 if (check_critical_value && percent_non_purgeable_space >= critical_value)
796 result=STATE_CRITICAL; 753 result = STATE_CRITICAL;
797 else if (check_warning_value && percent_non_purgeable_space >= warning_value) 754 else if (check_warning_value && percent_non_purgeable_space >= warning_value)
798 result=STATE_WARNING; 755 result = STATE_WARNING;
799 purgeable_disk_space/=1024; 756 purgeable_disk_space /= 1024;
800 xasprintf (&output_message,_("%lu MB (%lu%%) not yet purgeable on volume %s"),non_purgeable_disk_space,percent_non_purgeable_space,volume_name); 757 xasprintf(&output_message, _("%lu MB (%lu%%) not yet purgeable on volume %s"), non_purgeable_disk_space,
758 percent_non_purgeable_space, volume_name);
801 } 759 }
802 760
803 /* check # of open files */ 761 /* check # of open files */
804 } else if (vars_to_check==OFILES) { 762 } else if (vars_to_check == OFILES) {
805 763
806 close(sd); 764 close(sd);
807 my_tcp_connect (server_address, server_port, &sd); 765 my_tcp_connect(server_address, server_port, &sd);
808 766
809 xasprintf (&send_buffer,"S18\r\n"); 767 xasprintf(&send_buffer, "S18\r\n");
810 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 768 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
811 if (result!=STATE_OK) 769 if (result != STATE_OK)
812 return result; 770 return result;
813 771
814 open_files=atoi(recv_buffer); 772 open_files = atoi(recv_buffer);
815 773
816 if (check_critical_value && open_files >= critical_value) 774 if (check_critical_value && open_files >= critical_value)
817 result=STATE_CRITICAL; 775 result = STATE_CRITICAL;
818 else if (check_warning_value && open_files >= warning_value) 776 else if (check_warning_value && open_files >= warning_value)
819 result=STATE_WARNING; 777 result = STATE_WARNING;
820
821 xasprintf (&output_message,_("%lu open files|Openfiles=%lu;%lu;%lu;0,0"),
822 open_files,
823 open_files,
824 warning_value,
825 critical_value);
826 778
779 xasprintf(&output_message, _("%lu open files|Openfiles=%lu;%lu;%lu;0,0"), open_files, open_files, warning_value, critical_value);
827 780
828 /* check # of abended threads (Netware > 5.x only) */ 781 /* check # of abended threads (Netware > 5.x only) */
829 } else if (vars_to_check==ABENDS) { 782 } else if (vars_to_check == ABENDS) {
830 783
831 close(sd); 784 close(sd);
832 my_tcp_connect (server_address, server_port, &sd); 785 my_tcp_connect(server_address, server_port, &sd);
833 786
834 xasprintf (&send_buffer,"S17\r\n"); 787 xasprintf(&send_buffer, "S17\r\n");
835 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 788 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
836 if (result!=STATE_OK) 789 if (result != STATE_OK)
837 return result; 790 return result;
838 791
839 abended_threads=atoi(recv_buffer); 792 abended_threads = atoi(recv_buffer);
840 793
841 if (check_critical_value && abended_threads >= critical_value) 794 if (check_critical_value && abended_threads >= critical_value)
842 result=STATE_CRITICAL; 795 result = STATE_CRITICAL;
843 else if (check_warning_value && abended_threads >= warning_value) 796 else if (check_warning_value && abended_threads >= warning_value)
844 result=STATE_WARNING; 797 result = STATE_WARNING;
845 798
846 xasprintf (&output_message,_("%lu abended threads|Abends=%lu;%lu;%lu;;"), 799 xasprintf(&output_message, _("%lu abended threads|Abends=%lu;%lu;%lu;;"), abended_threads, abended_threads, warning_value,
847 abended_threads, 800 critical_value);
848 abended_threads,
849 warning_value,
850 critical_value);
851 801
852 /* check # of current service processes (Netware 5.x only) */ 802 /* check # of current service processes (Netware 5.x only) */
853 } else if (vars_to_check==CSPROCS) { 803 } else if (vars_to_check == CSPROCS) {
854 804
855 close(sd); 805 close(sd);
856 my_tcp_connect (server_address, server_port, &sd); 806 my_tcp_connect(server_address, server_port, &sd);
857 807
858 xasprintf (&send_buffer,"S20\r\n"); 808 xasprintf(&send_buffer, "S20\r\n");
859 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 809 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
860 if (result!=STATE_OK) 810 if (result != STATE_OK)
861 return result; 811 return result;
862 812
863 max_service_processes=atoi(recv_buffer); 813 max_service_processes = atoi(recv_buffer);
864 814
865 close(sd); 815 close(sd);
866 my_tcp_connect (server_address, server_port, &sd); 816 my_tcp_connect(server_address, server_port, &sd);
867 817
868 xasprintf (&send_buffer,"S21\r\n"); 818 xasprintf(&send_buffer, "S21\r\n");
869 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 819 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
870 if (result!=STATE_OK) 820 if (result != STATE_OK)
871 return result; 821 return result;
872 822
873 current_service_processes=atoi(recv_buffer); 823 current_service_processes = atoi(recv_buffer);
874 824
875 if (check_critical_value && current_service_processes >= critical_value) 825 if (check_critical_value && current_service_processes >= critical_value)
876 result=STATE_CRITICAL; 826 result = STATE_CRITICAL;
877 else if (check_warning_value && current_service_processes >= warning_value) 827 else if (check_warning_value && current_service_processes >= warning_value)
878 result=STATE_WARNING; 828 result = STATE_WARNING;
879 829
880 xasprintf (&output_message, 830 xasprintf(&output_message, _("%lu current service processes (%lu max)|Processes=%lu;%lu;%lu;0;%lu"), current_service_processes,
881 _("%lu current service processes (%lu max)|Processes=%lu;%lu;%lu;0;%lu"), 831 max_service_processes, current_service_processes, warning_value, critical_value, max_service_processes);
882 current_service_processes,
883 max_service_processes,
884 current_service_processes,
885 warning_value,
886 critical_value,
887 max_service_processes);
888 832
889 /* check # Timesync Status */ 833 /* check # Timesync Status */
890 } else if (vars_to_check==TSYNC) { 834 } else if (vars_to_check == TSYNC) {
891 835
892 close(sd); 836 close(sd);
893 my_tcp_connect (server_address, server_port, &sd); 837 my_tcp_connect(server_address, server_port, &sd);
894 838
895 xasprintf (&send_buffer,"S22\r\n"); 839 xasprintf(&send_buffer, "S22\r\n");
896 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 840 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
897 if (result!=STATE_OK) 841 if (result != STATE_OK)
898 return result; 842 return result;
899 843
900 time_sync_status=atoi(recv_buffer); 844 time_sync_status = atoi(recv_buffer);
901 845
902 if (time_sync_status==0) { 846 if (time_sync_status == 0) {
903 result=STATE_CRITICAL; 847 result = STATE_CRITICAL;
904 xasprintf (&output_message,_("CRITICAL - Time not in sync with network!")); 848 xasprintf(&output_message, _("CRITICAL - Time not in sync with network!"));
905 } 849 } else {
906 else { 850 xasprintf(&output_message, _("OK - Time in sync with network!"));
907 xasprintf (&output_message,_("OK - Time in sync with network!"));
908 } 851 }
909 852
910
911
912
913
914 /* check LRU sitting time in secondss */ 853 /* check LRU sitting time in secondss */
915 } else if (vars_to_check==LRUS) { 854 } else if (vars_to_check == LRUS) {
916 855
917 close(sd); 856 close(sd);
918 my_tcp_connect (server_address, server_port, &sd); 857 my_tcp_connect(server_address, server_port, &sd);
919 858
920 send_buffer = strdup ("S4\r\n"); 859 send_buffer = strdup("S4\r\n");
921 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 860 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
922 if (result!=STATE_OK) 861 if (result != STATE_OK)
923 return result; 862 return result;
924 lru_time=strtoul(recv_buffer,NULL,10); 863 lru_time = strtoul(recv_buffer, NULL, 10);
925 864
926 if (check_critical_value && lru_time <= critical_value) 865 if (check_critical_value && lru_time <= critical_value)
927 result=STATE_CRITICAL; 866 result = STATE_CRITICAL;
928 else if (check_warning_value && lru_time <= warning_value) 867 else if (check_warning_value && lru_time <= warning_value)
929 result=STATE_WARNING; 868 result = STATE_WARNING;
930 xasprintf (&output_message,_("LRU sitting time = %lu seconds"),lru_time); 869 xasprintf(&output_message, _("LRU sitting time = %lu seconds"), lru_time);
931
932 870
933 /* check % dirty cacheobuffers as a percentage of the total*/ 871 /* check % dirty cacheobuffers as a percentage of the total*/
934 } else if (vars_to_check==DCB) { 872 } else if (vars_to_check == DCB) {
935 873
936 close(sd); 874 close(sd);
937 my_tcp_connect (server_address, server_port, &sd); 875 my_tcp_connect(server_address, server_port, &sd);
938 876
939 send_buffer = strdup ("S6\r\n"); 877 send_buffer = strdup("S6\r\n");
940 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 878 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
941 if (result!=STATE_OK) 879 if (result != STATE_OK)
942 return result; 880 return result;
943 dirty_cache_buffers=atoi(recv_buffer); 881 dirty_cache_buffers = atoi(recv_buffer);
944 882
945 if (check_critical_value && dirty_cache_buffers <= critical_value) 883 if (check_critical_value && dirty_cache_buffers <= critical_value)
946 result=STATE_CRITICAL; 884 result = STATE_CRITICAL;
947 else if (check_warning_value && dirty_cache_buffers <= warning_value) 885 else if (check_warning_value && dirty_cache_buffers <= warning_value)
948 result=STATE_WARNING; 886 result = STATE_WARNING;
949 xasprintf (&output_message,_("Dirty cache buffers = %lu%% of the total|DCB=%lu;%lu;%lu;0;100"), 887 xasprintf(&output_message, _("Dirty cache buffers = %lu%% of the total|DCB=%lu;%lu;%lu;0;100"), dirty_cache_buffers,
950 dirty_cache_buffers, 888 dirty_cache_buffers, warning_value, critical_value);
951 dirty_cache_buffers,
952 warning_value,
953 critical_value);
954 889
955 /* check % total cache buffers as a percentage of the original*/ 890 /* check % total cache buffers as a percentage of the original*/
956 } else if (vars_to_check==TCB) { 891 } else if (vars_to_check == TCB) {
957 892
958 close(sd); 893 close(sd);
959 my_tcp_connect (server_address, server_port, &sd); 894 my_tcp_connect(server_address, server_port, &sd);
960 895
961 send_buffer = strdup ("S7\r\n"); 896 send_buffer = strdup("S7\r\n");
962 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 897 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
963 if (result!=STATE_OK) 898 if (result != STATE_OK)
964 return result; 899 return result;
965 total_cache_buffers=atoi(recv_buffer); 900 total_cache_buffers = atoi(recv_buffer);
966 901
967 if (check_critical_value && total_cache_buffers <= critical_value) 902 if (check_critical_value && total_cache_buffers <= critical_value)
968 result=STATE_CRITICAL; 903 result = STATE_CRITICAL;
969 else if (check_warning_value && total_cache_buffers <= warning_value) 904 else if (check_warning_value && total_cache_buffers <= warning_value)
970 result=STATE_WARNING; 905 result = STATE_WARNING;
971 xasprintf (&output_message,_("Total cache buffers = %lu%% of the original|TCB=%lu;%lu;%lu;0;100"), 906 xasprintf(&output_message, _("Total cache buffers = %lu%% of the original|TCB=%lu;%lu;%lu;0;100"), total_cache_buffers,
972 total_cache_buffers, 907 total_cache_buffers, warning_value, critical_value);
973 total_cache_buffers,
974 warning_value,
975 critical_value);
976 908
977 } else if (vars_to_check==DSVER) { 909 } else if (vars_to_check == DSVER) {
978 910
979 close(sd); 911 close(sd);
980 my_tcp_connect (server_address, server_port, &sd); 912 my_tcp_connect(server_address, server_port, &sd);
981 913
982 xasprintf (&send_buffer,"S13\r\n"); 914 xasprintf(&send_buffer, "S13\r\n");
983 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 915 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
984 if (result!=STATE_OK) 916 if (result != STATE_OK)
985 return result; 917 return result;
986 918
987 recv_buffer[strlen(recv_buffer)-1]=0; 919 recv_buffer[strlen(recv_buffer) - 1] = 0;
988 920
989 xasprintf (&output_message,_("NDS Version %s"),recv_buffer); 921 xasprintf(&output_message, _("NDS Version %s"), recv_buffer);
990 922
991 } else if (vars_to_check==UPTIME) { 923 } else if (vars_to_check == UPTIME) {
992 924
993 close(sd); 925 close(sd);
994 my_tcp_connect (server_address, server_port, &sd); 926 my_tcp_connect(server_address, server_port, &sd);
995
996 xasprintf (&send_buffer,"UPTIME\r\n");
997 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer));
998 if (result!=STATE_OK)
999 return result;
1000 927
928 xasprintf(&send_buffer, "UPTIME\r\n");
929 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
930 if (result != STATE_OK)
931 return result;
1001 932
1002 recv_buffer[sizeof(recv_buffer)-1]=0; 933 recv_buffer[sizeof(recv_buffer) - 1] = 0;
1003 recv_buffer[strlen(recv_buffer)-1]=0; 934 recv_buffer[strlen(recv_buffer) - 1] = 0;
1004 935
1005 xasprintf (&output_message,_("Up %s"),recv_buffer); 936 xasprintf(&output_message, _("Up %s"), recv_buffer);
1006 937
1007 } else if (vars_to_check==NLM) { 938 } else if (vars_to_check == NLM) {
1008 939
1009 close(sd); 940 close(sd);
1010 my_tcp_connect (server_address, server_port, &sd); 941 my_tcp_connect(server_address, server_port, &sd);
1011 942
1012 xasprintf (&send_buffer,"S24:%s\r\n",nlm_name); 943 xasprintf(&send_buffer, "S24:%s\r\n", nlm_name);
1013 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 944 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
1014 if (result!=STATE_OK) 945 if (result != STATE_OK)
1015 return result; 946 return result;
1016 947
1017 recv_buffer[strlen(recv_buffer)-1]=0; 948 recv_buffer[strlen(recv_buffer) - 1] = 0;
1018 if (strcmp(recv_buffer,"-1")) { 949 if (strcmp(recv_buffer, "-1")) {
1019 xasprintf (&output_message,_("Module %s version %s is loaded"),nlm_name,recv_buffer); 950 xasprintf(&output_message, _("Module %s version %s is loaded"), nlm_name, recv_buffer);
1020 } else { 951 } else {
1021 result=STATE_CRITICAL; 952 result = STATE_CRITICAL;
1022 xasprintf (&output_message,_("Module %s is not loaded"),nlm_name); 953 xasprintf(&output_message, _("Module %s is not loaded"), nlm_name);
1023 954 }
1024 } 955 } else if (vars_to_check == NRMP) {
1025 } else if (vars_to_check==NRMP) {
1026 956
1027 xasprintf (&send_buffer,"NRMP:%s\r\n",nrmp_name); 957 xasprintf(&send_buffer, "NRMP:%s\r\n", nrmp_name);
1028 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 958 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
1029 if (result!=STATE_OK) 959 if (result != STATE_OK)
1030 return result; 960 return result;
1031 961
1032 if (!strcmp(recv_buffer,"-1\n")) { 962 if (!strcmp(recv_buffer, "-1\n")) {
1033 xasprintf (&output_message,_("CRITICAL - Value '%s' does not exist!"),nrmp_name); 963 xasprintf(&output_message, _("CRITICAL - Value '%s' does not exist!"), nrmp_name);
1034 result=STATE_CRITICAL; 964 result = STATE_CRITICAL;
1035 } else { 965 } else {
1036 nrmp_value=strtoul(recv_buffer,NULL,10); 966 nrmp_value = strtoul(recv_buffer, NULL, 10);
1037 if (check_critical_value && nrmp_value <= critical_value) 967 if (check_critical_value && nrmp_value <= critical_value)
1038 result=STATE_CRITICAL; 968 result = STATE_CRITICAL;
1039 else if (check_warning_value && nrmp_value <= warning_value) 969 else if (check_warning_value && nrmp_value <= warning_value)
1040 result=STATE_WARNING; 970 result = STATE_WARNING;
1041 xasprintf (&output_message, 971 xasprintf(&output_message, _("%s is %lu|%s=%lu;%lu;%lu;;"), nrmp_name, nrmp_value, nrmp_name, nrmp_value, warning_value,
1042 _("%s is %lu|%s=%lu;%lu;%lu;;"), 972 critical_value);
1043 nrmp_name,
1044 nrmp_value,
1045 nrmp_name,
1046 nrmp_value,
1047 warning_value,
1048 critical_value);
1049 } 973 }
1050 974
1051 } else if (vars_to_check==NRMM) { 975 } else if (vars_to_check == NRMM) {
1052 976
1053 xasprintf (&send_buffer,"NRMM:%s\r\n",nrmm_name); 977 xasprintf(&send_buffer, "NRMM:%s\r\n", nrmm_name);
1054 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 978 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
1055 if (result!=STATE_OK) 979 if (result != STATE_OK)
1056 return result; 980 return result;
1057 981
1058 if (!strcmp(recv_buffer,"-1\n")) { 982 if (!strcmp(recv_buffer, "-1\n")) {
1059 xasprintf (&output_message,_("CRITICAL - Value '%s' does not exist!"),nrmm_name); 983 xasprintf(&output_message, _("CRITICAL - Value '%s' does not exist!"), nrmm_name);
1060 result=STATE_CRITICAL; 984 result = STATE_CRITICAL;
1061 } else { 985 } else {
1062 nrmm_value=strtoul(recv_buffer,NULL,10); 986 nrmm_value = strtoul(recv_buffer, NULL, 10);
1063 if (check_critical_value && nrmm_value <= critical_value) 987 if (check_critical_value && nrmm_value <= critical_value)
1064 result=STATE_CRITICAL; 988 result = STATE_CRITICAL;
1065 else if (check_warning_value && nrmm_value <= warning_value) 989 else if (check_warning_value && nrmm_value <= warning_value)
1066 result=STATE_WARNING; 990 result = STATE_WARNING;
1067 xasprintf (&output_message, 991 xasprintf(&output_message, _("%s is %lu|%s=%lu;%lu;%lu;;"), nrmm_name, nrmm_value, nrmm_name, nrmm_value, warning_value,
1068 _("%s is %lu|%s=%lu;%lu;%lu;;"), 992 critical_value);
1069 nrmm_name,
1070 nrmm_value,
1071 nrmm_name,
1072 nrmm_value,
1073 warning_value,
1074 critical_value);
1075 } 993 }
1076 994
1077 } else if (vars_to_check==NRMS) { 995 } else if (vars_to_check == NRMS) {
1078 996
1079 xasprintf (&send_buffer,"NRMS:%s\r\n",nrms_name); 997 xasprintf(&send_buffer, "NRMS:%s\r\n", nrms_name);
1080 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 998 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
1081 if (result!=STATE_OK) 999 if (result != STATE_OK)
1082 return result; 1000 return result;
1083 1001
1084 if (!strcmp(recv_buffer,"-1\n")) { 1002 if (!strcmp(recv_buffer, "-1\n")) {
1085 xasprintf (&output_message,_("CRITICAL - Value '%s' does not exist!"),nrms_name); 1003 xasprintf(&output_message, _("CRITICAL - Value '%s' does not exist!"), nrms_name);
1086 result=STATE_CRITICAL; 1004 result = STATE_CRITICAL;
1087 } else { 1005 } else {
1088 nrms_value=strtoul(recv_buffer,NULL,10); 1006 nrms_value = strtoul(recv_buffer, NULL, 10);
1089 if (check_critical_value && nrms_value >= critical_value) 1007 if (check_critical_value && nrms_value >= critical_value)
1090 result=STATE_CRITICAL; 1008 result = STATE_CRITICAL;
1091 else if (check_warning_value && nrms_value >= warning_value) 1009 else if (check_warning_value && nrms_value >= warning_value)
1092 result=STATE_WARNING; 1010 result = STATE_WARNING;
1093 xasprintf (&output_message, 1011 xasprintf(&output_message, _("%s is %lu|%s=%lu;%lu;%lu;;"), nrms_name, nrms_value, nrms_name, nrms_value, warning_value,
1094 _("%s is %lu|%s=%lu;%lu;%lu;;"), 1012 critical_value);
1095 nrms_name,
1096 nrms_value,
1097 nrms_name,
1098 nrms_value,
1099 warning_value,
1100 critical_value);
1101 } 1013 }
1102 1014
1103 } else if (vars_to_check==NSS1) { 1015 } else if (vars_to_check == NSS1) {
1104 1016
1105 xasprintf (&send_buffer,"NSS1:%s\r\n",nss1_name); 1017 xasprintf(&send_buffer, "NSS1:%s\r\n", nss1_name);
1106 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 1018 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
1107 if (result!=STATE_OK) 1019 if (result != STATE_OK)
1108 return result; 1020 return result;
1109 1021
1110 if (!strcmp(recv_buffer,"-1\n")) { 1022 if (!strcmp(recv_buffer, "-1\n")) {
1111 xasprintf (&output_message,_("CRITICAL - Value '%s' does not exist!"),nss1_name); 1023 xasprintf(&output_message, _("CRITICAL - Value '%s' does not exist!"), nss1_name);
1112 result=STATE_CRITICAL; 1024 result = STATE_CRITICAL;
1113 } else { 1025 } else {
1114 nss1_value=strtoul(recv_buffer,NULL,10); 1026 nss1_value = strtoul(recv_buffer, NULL, 10);
1115 if (check_critical_value && nss1_value >= critical_value) 1027 if (check_critical_value && nss1_value >= critical_value)
1116 result=STATE_CRITICAL; 1028 result = STATE_CRITICAL;
1117 else if (check_warning_value && nss1_value >= warning_value) 1029 else if (check_warning_value && nss1_value >= warning_value)
1118 result=STATE_WARNING; 1030 result = STATE_WARNING;
1119 xasprintf (&output_message, 1031 xasprintf(&output_message, _("%s is %lu|%s=%lu;%lu;%lu;;"), nss1_name, nss1_value, nss1_name, nss1_value, warning_value,
1120 _("%s is %lu|%s=%lu;%lu;%lu;;"), 1032 critical_value);
1121 nss1_name,
1122 nss1_value,
1123 nss1_name,
1124 nss1_value,
1125 warning_value,
1126 critical_value);
1127 } 1033 }
1128 1034
1129 } else if (vars_to_check==NSS2) { 1035 } else if (vars_to_check == NSS2) {
1130 1036
1131 xasprintf (&send_buffer,"NSS2:%s\r\n",nss2_name); 1037 xasprintf(&send_buffer, "NSS2:%s\r\n", nss2_name);
1132 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 1038 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
1133 if (result!=STATE_OK) 1039 if (result != STATE_OK)
1134 return result; 1040 return result;
1135 1041
1136 if (!strcmp(recv_buffer,"-1\n")) { 1042 if (!strcmp(recv_buffer, "-1\n")) {
1137 xasprintf (&output_message,_("CRITICAL - Value '%s' does not exist!"),nss2_name); 1043 xasprintf(&output_message, _("CRITICAL - Value '%s' does not exist!"), nss2_name);
1138 result=STATE_CRITICAL; 1044 result = STATE_CRITICAL;
1139 } else { 1045 } else {
1140 nss2_value=strtoul(recv_buffer,NULL,10); 1046 nss2_value = strtoul(recv_buffer, NULL, 10);
1141 if (check_critical_value && nss2_value >= critical_value) 1047 if (check_critical_value && nss2_value >= critical_value)
1142 result=STATE_CRITICAL; 1048 result = STATE_CRITICAL;
1143 else if (check_warning_value && nss2_value >= warning_value) 1049 else if (check_warning_value && nss2_value >= warning_value)
1144 result=STATE_WARNING; 1050 result = STATE_WARNING;
1145 xasprintf (&output_message, 1051 xasprintf(&output_message, _("%s is %lu|%s=%lu;%lu;%lu;;"), nss2_name, nss2_value, nss2_name, nss2_value, warning_value,
1146 _("%s is %lu|%s=%lu;%lu;%lu;;"), 1052 critical_value);
1147 nss2_name,
1148 nss2_value,
1149 nss2_name,
1150 nss2_value,
1151 warning_value,
1152 critical_value);
1153 } 1053 }
1154 1054
1155 } else if (vars_to_check==NSS3) { 1055 } else if (vars_to_check == NSS3) {
1156 1056
1157 xasprintf (&send_buffer,"NSS3:%s\r\n",nss3_name); 1057 xasprintf(&send_buffer, "NSS3:%s\r\n", nss3_name);
1158 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 1058 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
1159 if (result!=STATE_OK) 1059 if (result != STATE_OK)
1160 return result; 1060 return result;
1161 1061
1162 if (!strcmp(recv_buffer,"-1\n")) { 1062 if (!strcmp(recv_buffer, "-1\n")) {
1163 xasprintf (&output_message,_("CRITICAL - Value '%s' does not exist!"),nss3_name); 1063 xasprintf(&output_message, _("CRITICAL - Value '%s' does not exist!"), nss3_name);
1164 result=STATE_CRITICAL; 1064 result = STATE_CRITICAL;
1165 } else { 1065 } else {
1166 nss3_value=strtoul(recv_buffer,NULL,10); 1066 nss3_value = strtoul(recv_buffer, NULL, 10);
1167 if (check_critical_value && nss3_value >= critical_value) 1067 if (check_critical_value && nss3_value >= critical_value)
1168 result=STATE_CRITICAL; 1068 result = STATE_CRITICAL;
1169 else if (check_warning_value && nss3_value >= warning_value) 1069 else if (check_warning_value && nss3_value >= warning_value)
1170 result=STATE_WARNING; 1070 result = STATE_WARNING;
1171 xasprintf (&output_message, 1071 xasprintf(&output_message, _("%s is %lu|%s=%lu;%lu;%lu;;"), nss3_name, nss3_value, nss3_name, nss3_value, warning_value,
1172 _("%s is %lu|%s=%lu;%lu;%lu;;"), 1072 critical_value);
1173 nss3_name,
1174 nss3_value,
1175 nss3_name,
1176 nss3_value,
1177 warning_value,
1178 critical_value);
1179 } 1073 }
1180 1074
1181 } else if (vars_to_check==NSS4) { 1075 } else if (vars_to_check == NSS4) {
1182 1076
1183 xasprintf (&send_buffer,"NSS4:%s\r\n",nss4_name); 1077 xasprintf(&send_buffer, "NSS4:%s\r\n", nss4_name);
1184 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 1078 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
1185 if (result!=STATE_OK) 1079 if (result != STATE_OK)
1186 return result; 1080 return result;
1187 1081
1188 if (!strcmp(recv_buffer,"-1\n")) { 1082 if (!strcmp(recv_buffer, "-1\n")) {
1189 xasprintf (&output_message,_("CRITICAL - Value '%s' does not exist!"),nss4_name); 1083 xasprintf(&output_message, _("CRITICAL - Value '%s' does not exist!"), nss4_name);
1190 result=STATE_CRITICAL; 1084 result = STATE_CRITICAL;
1191 } else { 1085 } else {
1192 nss4_value=strtoul(recv_buffer,NULL,10); 1086 nss4_value = strtoul(recv_buffer, NULL, 10);
1193 if (check_critical_value && nss4_value >= critical_value) 1087 if (check_critical_value && nss4_value >= critical_value)
1194 result=STATE_CRITICAL; 1088 result = STATE_CRITICAL;
1195 else if (check_warning_value && nss4_value >= warning_value) 1089 else if (check_warning_value && nss4_value >= warning_value)
1196 result=STATE_WARNING; 1090 result = STATE_WARNING;
1197 xasprintf (&output_message, 1091 xasprintf(&output_message, _("%s is %lu|%s=%lu;%lu;%lu;;"), nss4_name, nss4_value, nss4_name, nss4_value, warning_value,
1198 _("%s is %lu|%s=%lu;%lu;%lu;;"), 1092 critical_value);
1199 nss4_name,
1200 nss4_value,
1201 nss4_name,
1202 nss4_value,
1203 warning_value,
1204 critical_value);
1205 } 1093 }
1206 1094
1207 } else if (vars_to_check==NSS5) { 1095 } else if (vars_to_check == NSS5) {
1208 1096
1209 xasprintf (&send_buffer,"NSS5:%s\r\n",nss5_name); 1097 xasprintf(&send_buffer, "NSS5:%s\r\n", nss5_name);
1210 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 1098 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
1211 if (result!=STATE_OK) 1099 if (result != STATE_OK)
1212 return result; 1100 return result;
1213 1101
1214 if (!strcmp(recv_buffer,"-1\n")) { 1102 if (!strcmp(recv_buffer, "-1\n")) {
1215 xasprintf (&output_message,_("CRITICAL - Value '%s' does not exist!"),nss5_name); 1103 xasprintf(&output_message, _("CRITICAL - Value '%s' does not exist!"), nss5_name);
1216 result=STATE_CRITICAL; 1104 result = STATE_CRITICAL;
1217 } else { 1105 } else {
1218 nss5_value=strtoul(recv_buffer,NULL,10); 1106 nss5_value = strtoul(recv_buffer, NULL, 10);
1219 if (check_critical_value && nss5_value >= critical_value) 1107 if (check_critical_value && nss5_value >= critical_value)
1220 result=STATE_CRITICAL; 1108 result = STATE_CRITICAL;
1221 else if (check_warning_value && nss5_value >= warning_value) 1109 else if (check_warning_value && nss5_value >= warning_value)
1222 result=STATE_WARNING; 1110 result = STATE_WARNING;
1223 xasprintf (&output_message, 1111 xasprintf(&output_message, _("%s is %lu|%s=%lu;%lu;%lu;;"), nss5_name, nss5_value, nss5_name, nss5_value, warning_value,
1224 _("%s is %lu|%s=%lu;%lu;%lu;;"), 1112 critical_value);
1225 nss5_name,
1226 nss5_value,
1227 nss5_name,
1228 nss5_value,
1229 warning_value,
1230 critical_value);
1231 } 1113 }
1232 1114
1233 } else if (vars_to_check==NSS6) { 1115 } else if (vars_to_check == NSS6) {
1234 1116
1235 xasprintf (&send_buffer,"NSS6:%s\r\n",nss6_name); 1117 xasprintf(&send_buffer, "NSS6:%s\r\n", nss6_name);
1236 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 1118 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
1237 if (result!=STATE_OK) 1119 if (result != STATE_OK)
1238 return result; 1120 return result;
1239 1121
1240 if (!strcmp(recv_buffer,"-1\n")) { 1122 if (!strcmp(recv_buffer, "-1\n")) {
1241 xasprintf (&output_message,_("CRITICAL - Value '%s' does not exist!"),nss6_name); 1123 xasprintf(&output_message, _("CRITICAL - Value '%s' does not exist!"), nss6_name);
1242 result=STATE_CRITICAL; 1124 result = STATE_CRITICAL;
1243 } else { 1125 } else {
1244 nss6_value=strtoul(recv_buffer,NULL,10); 1126 nss6_value = strtoul(recv_buffer, NULL, 10);
1245 if (check_critical_value && nss6_value >= critical_value) 1127 if (check_critical_value && nss6_value >= critical_value)
1246 result=STATE_CRITICAL; 1128 result = STATE_CRITICAL;
1247 else if (check_warning_value && nss6_value >= warning_value) 1129 else if (check_warning_value && nss6_value >= warning_value)
1248 result=STATE_WARNING; 1130 result = STATE_WARNING;
1249 xasprintf (&output_message, 1131 xasprintf(&output_message, _("%s is %lu|%s=%lu;%lu;%lu;;"), nss6_name, nss6_value, nss6_name, nss6_value, warning_value,
1250 _("%s is %lu|%s=%lu;%lu;%lu;;"), 1132 critical_value);
1251 nss6_name,
1252 nss6_value,
1253 nss6_name,
1254 nss6_value,
1255 warning_value,
1256 critical_value);
1257 } 1133 }
1258 1134
1259 } else if (vars_to_check==NSS7) { 1135 } else if (vars_to_check == NSS7) {
1260 1136
1261 xasprintf (&send_buffer,"NSS7:%s\r\n",nss7_name); 1137 xasprintf(&send_buffer, "NSS7:%s\r\n", nss7_name);
1262 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 1138 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
1263 if (result!=STATE_OK) 1139 if (result != STATE_OK)
1264 return result; 1140 return result;
1265 1141
1266 if (!strcmp(recv_buffer,"-1\n")) { 1142 if (!strcmp(recv_buffer, "-1\n")) {
1267 xasprintf (&output_message,_("CRITICAL - Value '%s' does not exist!"),nss7_name); 1143 xasprintf(&output_message, _("CRITICAL - Value '%s' does not exist!"), nss7_name);
1268 result=STATE_CRITICAL; 1144 result = STATE_CRITICAL;
1269 } else { 1145 } else {
1270 nss7_value=strtoul(recv_buffer,NULL,10); 1146 nss7_value = strtoul(recv_buffer, NULL, 10);
1271 if (check_critical_value && nss7_value >= critical_value) 1147 if (check_critical_value && nss7_value >= critical_value)
1272 result=STATE_CRITICAL; 1148 result = STATE_CRITICAL;
1273 else if (check_warning_value && nss7_value >= warning_value) 1149 else if (check_warning_value && nss7_value >= warning_value)
1274 result=STATE_WARNING; 1150 result = STATE_WARNING;
1275 xasprintf (&output_message, 1151 xasprintf(&output_message, _("%s is %lu|%s=%lu;%lu;%lu;;"), nss7_name, nss7_value, nss7_name, nss7_value, warning_value,
1276 _("%s is %lu|%s=%lu;%lu;%lu;;"), 1152 critical_value);
1277 nss7_name,
1278 nss7_value,
1279 nss7_name,
1280 nss7_value,
1281 warning_value,
1282 critical_value);
1283 } 1153 }
1284 1154
1155 } else {
1285 1156
1286} 1157 output_message = strdup(_("Nothing to check!\n"));
1287 else { 1158 result = STATE_UNKNOWN;
1288
1289 output_message = strdup (_("Nothing to check!\n"));
1290 result=STATE_UNKNOWN;
1291
1292 } 1159 }
1293 1160
1294 close (sd); 1161 close(sd);
1295 1162
1296 /* reset timeout */ 1163 /* reset timeout */
1297 alarm(0); 1164 alarm(0);
1298 1165
1299 printf("%s%s\n",netware_version,output_message); 1166 printf("%s%s\n", netware_version, output_message);
1300 1167
1301 return result; 1168 return result;
1302} 1169}
1303 1170
1304
1305
1306/* process command-line arguments */ 1171/* process command-line arguments */
1307int process_arguments(int argc, char **argv) { 1172int process_arguments(int argc, char **argv) {
1308 int c; 1173 int c;
1309 1174
1310 int option = 0; 1175 int option = 0;
1311 static struct option longopts[] = 1176 static struct option longopts[] = {{"port", required_argument, 0, 'p'}, {"timeout", required_argument, 0, 't'},
1312 { 1177 {"critical", required_argument, 0, 'c'}, {"warning", required_argument, 0, 'w'},
1313 {"port", required_argument,0,'p'}, 1178 {"variable", required_argument, 0, 'v'}, {"hostname", required_argument, 0, 'H'},
1314 {"timeout", required_argument,0,'t'}, 1179 {"osversion", no_argument, 0, 'o'}, {"version", no_argument, 0, 'V'},
1315 {"critical", required_argument,0,'c'}, 1180 {"help", no_argument, 0, 'h'}, {0, 0, 0, 0}};
1316 {"warning", required_argument,0,'w'},
1317 {"variable", required_argument,0,'v'},
1318 {"hostname", required_argument,0,'H'},
1319 {"osversion",no_argument, 0,'o'},
1320 {"version", no_argument, 0,'V'},
1321 {"help", no_argument, 0,'h'},
1322 {0,0,0,0}
1323 };
1324 1181
1325 /* no options were supplied */ 1182 /* no options were supplied */
1326 if (argc<2) return ERROR; 1183 if (argc < 2)
1184 return ERROR;
1327 1185
1328 /* backwards compatibility */ 1186 /* backwards compatibility */
1329 if (! is_option(argv[1])) { 1187 if (!is_option(argv[1])) {
1330 server_address=argv[1]; 1188 server_address = argv[1];
1331 argv[1]=argv[0]; 1189 argv[1] = argv[0];
1332 argv=&argv[1]; 1190 argv = &argv[1];
1333 argc--; 1191 argc--;
1334 } 1192 }
1335 1193
1336 for (c=1;c<argc;c++) { 1194 for (c = 1; c < argc; c++) {
1337 if (strcmp("-to",argv[c])==0) 1195 if (strcmp("-to", argv[c]) == 0)
1338 strcpy(argv[c],"-t"); 1196 strcpy(argv[c], "-t");
1339 else if (strcmp("-wv",argv[c])==0) 1197 else if (strcmp("-wv", argv[c]) == 0)
1340 strcpy(argv[c],"-w"); 1198 strcpy(argv[c], "-w");
1341 else if (strcmp("-cv",argv[c])==0) 1199 else if (strcmp("-cv", argv[c]) == 0)
1342 strcpy(argv[c],"-c"); 1200 strcpy(argv[c], "-c");
1343 } 1201 }
1344 1202
1345 while (1) { 1203 while (1) {
1346 c = getopt_long(argc,argv,"+hoVH:t:c:w:p:v:",longopts,&option); 1204 c = getopt_long(argc, argv, "+hoVH:t:c:w:p:v:", longopts, &option);
1347 1205
1348 if (c==-1||c==EOF||c==1) 1206 if (c == -1 || c == EOF || c == 1)
1349 break; 1207 break;
1350 1208
1351 switch (c) 1209 switch (c) {
1352 { 1210 case '?': /* print short usage statement if args not parsable */
1353 case '?': /* print short usage statement if args not parsable */ 1211 usage5();
1354 usage5 (); 1212 case 'h': /* help */
1355 case 'h': /* help */ 1213 print_help();
1356 print_help(); 1214 exit(STATE_UNKNOWN);
1357 exit(STATE_UNKNOWN); 1215 case 'V': /* version */
1358 case 'V': /* version */ 1216 print_revision(progname, NP_VERSION);
1359 print_revision(progname, NP_VERSION); 1217 exit(STATE_UNKNOWN);
1360 exit(STATE_UNKNOWN); 1218 case 'H': /* hostname */
1361 case 'H': /* hostname */ 1219 server_address = optarg;
1362 server_address=optarg; 1220 break;
1363 break; 1221 case 'o': /* display nos version */
1364 case 'o': /* display nos version */ 1222 check_netware_version = true;
1365 check_netware_version = true; 1223 break;
1366 break; 1224 case 'p': /* port */
1367 case 'p': /* port */ 1225 if (is_intnonneg(optarg))
1368 if (is_intnonneg(optarg)) 1226 server_port = atoi(optarg);
1369 server_port=atoi(optarg); 1227 else
1228 die(STATE_UNKNOWN, _("Server port an integer\n"));
1229 break;
1230 case 'v':
1231 if (strlen(optarg) < 3)
1232 return ERROR;
1233 if (!strcmp(optarg, "LOAD1"))
1234 vars_to_check = LOAD1;
1235 else if (!strcmp(optarg, "LOAD5"))
1236 vars_to_check = LOAD5;
1237 else if (!strcmp(optarg, "LOAD15"))
1238 vars_to_check = LOAD15;
1239 else if (!strcmp(optarg, "CONNS"))
1240 vars_to_check = CONNS;
1241 else if (!strcmp(optarg, "LTCH"))
1242 vars_to_check = LTCH;
1243 else if (!strcmp(optarg, "DCB"))
1244 vars_to_check = DCB;
1245 else if (!strcmp(optarg, "TCB"))
1246 vars_to_check = TCB;
1247 else if (!strcmp(optarg, "CBUFF"))
1248 vars_to_check = CBUFF;
1249 else if (!strcmp(optarg, "CDBUFF"))
1250 vars_to_check = CDBUFF;
1251 else if (!strcmp(optarg, "LRUM"))
1252 vars_to_check = LRUM;
1253 else if (!strcmp(optarg, "LRUS"))
1254 vars_to_check = LRUS;
1255 else if (strncmp(optarg, "VPF", 3) == 0) {
1256 vars_to_check = VPF;
1257 volume_name = strdup(optarg + 3);
1258 if (!strcmp(volume_name, ""))
1259 volume_name = strdup("SYS");
1260 } else if (strncmp(optarg, "VKF", 3) == 0) {
1261 vars_to_check = VKF;
1262 volume_name = strdup(optarg + 3);
1263 if (!strcmp(volume_name, ""))
1264 volume_name = strdup("SYS");
1265 } else if (strncmp(optarg, "VMF", 3) == 0) {
1266 vars_to_check = VMF;
1267 volume_name = strdup(optarg + 3);
1268 if (!strcmp(volume_name, ""))
1269 volume_name = strdup("SYS");
1270 } else if (!strcmp(optarg, "DSDB"))
1271 vars_to_check = DSDB;
1272 else if (!strcmp(optarg, "LOGINS"))
1273 vars_to_check = LOGINS;
1274 else if (!strcmp(optarg, "NRMH"))
1275 vars_to_check = NRMH;
1276 else if (!strcmp(optarg, "UPRB"))
1277 vars_to_check = UPRB;
1278 else if (!strcmp(optarg, "PUPRB"))
1279 vars_to_check = PUPRB;
1280 else if (!strncmp(optarg, "SAPENTRIES", 10)) {
1281 vars_to_check = SAPENTRIES;
1282 if (strlen(optarg) > 10)
1283 sap_number = atoi(optarg + 10);
1370 else 1284 else
1371 die(STATE_UNKNOWN,_("Server port an integer\n")); 1285 sap_number = -1;
1372 break; 1286 } else if (!strcmp(optarg, "OFILES"))
1373 case 'v': 1287 vars_to_check = OFILES;
1374 if (strlen(optarg)<3) 1288 else if (strncmp(optarg, "VKP", 3) == 0) {
1375 return ERROR; 1289 vars_to_check = VKP;
1376 if (!strcmp(optarg,"LOAD1")) 1290 volume_name = strdup(optarg + 3);
1377 vars_to_check=LOAD1; 1291 if (!strcmp(volume_name, ""))
1378 else if (!strcmp(optarg,"LOAD5")) 1292 volume_name = strdup("SYS");
1379 vars_to_check=LOAD5; 1293 } else if (strncmp(optarg, "VMP", 3) == 0) {
1380 else if (!strcmp(optarg,"LOAD15")) 1294 vars_to_check = VMP;
1381 vars_to_check=LOAD15; 1295 volume_name = strdup(optarg + 3);
1382 else if (!strcmp(optarg,"CONNS")) 1296 if (!strcmp(volume_name, ""))
1383 vars_to_check=CONNS; 1297 volume_name = strdup("SYS");
1384 else if (!strcmp(optarg,"LTCH")) 1298 } else if (strncmp(optarg, "VMU", 3) == 0) {
1385 vars_to_check=LTCH; 1299 vars_to_check = VMU;
1386 else if (!strcmp(optarg,"DCB")) 1300 volume_name = strdup(optarg + 3);
1387 vars_to_check=DCB; 1301 if (!strcmp(volume_name, ""))
1388 else if (!strcmp(optarg,"TCB")) 1302 volume_name = strdup("SYS");
1389 vars_to_check=TCB; 1303 } else if (strncmp(optarg, "VPU", 3) == 0) {
1390 else if (!strcmp(optarg,"CBUFF")) 1304 vars_to_check = VPU;
1391 vars_to_check=CBUFF; 1305 volume_name = strdup(optarg + 3);
1392 else if (!strcmp(optarg,"CDBUFF")) 1306 if (!strcmp(volume_name, ""))
1393 vars_to_check=CDBUFF; 1307 volume_name = strdup("SYS");
1394 else if (!strcmp(optarg,"LRUM")) 1308 } else if (strncmp(optarg, "VPP", 3) == 0) {
1395 vars_to_check=LRUM; 1309 vars_to_check = VPP;
1396 else if (!strcmp(optarg,"LRUS")) 1310 volume_name = strdup(optarg + 3);
1397 vars_to_check=LRUS; 1311 if (!strcmp(volume_name, ""))
1398 else if (strncmp(optarg,"VPF",3)==0) { 1312 volume_name = strdup("SYS");
1399 vars_to_check=VPF; 1313 } else if (strncmp(optarg, "VKNP", 4) == 0) {
1400 volume_name = strdup (optarg+3); 1314 vars_to_check = VKNP;
1401 if (!strcmp(volume_name,"")) 1315 volume_name = strdup(optarg + 4);
1402 volume_name = strdup ("SYS"); 1316 if (!strcmp(volume_name, ""))
1403 } 1317 volume_name = strdup("SYS");
1404 else if (strncmp(optarg,"VKF",3)==0) { 1318 } else if (strncmp(optarg, "VPNP", 4) == 0) {
1405 vars_to_check=VKF; 1319 vars_to_check = VPNP;
1406 volume_name = strdup (optarg+3); 1320 volume_name = strdup(optarg + 4);
1407 if (!strcmp(volume_name,"")) 1321 if (!strcmp(volume_name, ""))
1408 volume_name = strdup ("SYS"); 1322 volume_name = strdup("SYS");
1409 } 1323 } else if (!strcmp(optarg, "ABENDS"))
1410 else if (strncmp(optarg,"VMF",3)==0) { 1324 vars_to_check = ABENDS;
1411 vars_to_check=VMF; 1325 else if (!strcmp(optarg, "CSPROCS"))
1412 volume_name = strdup (optarg+3); 1326 vars_to_check = CSPROCS;
1413 if (!strcmp(volume_name,"")) 1327 else if (!strcmp(optarg, "TSYNC"))
1414 volume_name = strdup ("SYS"); 1328 vars_to_check = TSYNC;
1415 } 1329 else if (!strcmp(optarg, "DSVER"))
1416 else if (!strcmp(optarg,"DSDB")) 1330 vars_to_check = DSVER;
1417 vars_to_check=DSDB; 1331 else if (!strcmp(optarg, "UPTIME")) {
1418 else if (!strcmp(optarg,"LOGINS")) 1332 vars_to_check = UPTIME;
1419 vars_to_check=LOGINS; 1333 } else if (strncmp(optarg, "NLM:", 4) == 0) {
1420 else if (!strcmp(optarg,"NRMH")) 1334 vars_to_check = NLM;
1421 vars_to_check=NRMH; 1335 nlm_name = strdup(optarg + 4);
1422 else if (!strcmp(optarg,"UPRB")) 1336 } else if (strncmp(optarg, "NRMP", 4) == 0) {
1423 vars_to_check=UPRB; 1337 vars_to_check = NRMP;
1424 else if (!strcmp(optarg,"PUPRB")) 1338 nrmp_name = strdup(optarg + 4);
1425 vars_to_check=PUPRB; 1339 if (!strcmp(nrmp_name, ""))
1426 else if (!strncmp(optarg,"SAPENTRIES",10)) { 1340 nrmp_name = strdup("AVAILABLE_MEMORY");
1427 vars_to_check=SAPENTRIES; 1341 } else if (strncmp(optarg, "NRMM", 4) == 0) {
1428 if (strlen(optarg)>10) 1342 vars_to_check = NRMM;
1429 sap_number=atoi(optarg+10); 1343 nrmm_name = strdup(optarg + 4);
1430 else 1344 if (!strcmp(nrmm_name, ""))
1431 sap_number=-1; 1345 nrmm_name = strdup("AVAILABLE_CACHE_MEMORY");
1432 }
1433 else if (!strcmp(optarg,"OFILES"))
1434 vars_to_check=OFILES;
1435 else if (strncmp(optarg,"VKP",3)==0) {
1436 vars_to_check=VKP;
1437 volume_name = strdup (optarg+3);
1438 if (!strcmp(volume_name,""))
1439 volume_name = strdup ("SYS");
1440 }
1441 else if (strncmp(optarg,"VMP",3)==0) {
1442 vars_to_check=VMP;
1443 volume_name = strdup (optarg+3);
1444 if (!strcmp(volume_name,""))
1445 volume_name = strdup ("SYS");
1446 }
1447 else if (strncmp(optarg,"VMU",3)==0) {
1448 vars_to_check=VMU;
1449 volume_name = strdup (optarg+3);
1450 if (!strcmp(volume_name,""))
1451 volume_name = strdup ("SYS");
1452 }
1453 else if (strncmp(optarg,"VPP",3)==0) {
1454 vars_to_check=VPP;
1455 volume_name = strdup (optarg+3);
1456 if (!strcmp(volume_name,""))
1457 volume_name = strdup ("SYS");
1458 }
1459 else if (strncmp(optarg,"VKNP",4)==0) {
1460 vars_to_check=VKNP;
1461 volume_name = strdup (optarg+4);
1462 if (!strcmp(volume_name,""))
1463 volume_name = strdup ("SYS");
1464 }
1465 else if (strncmp(optarg,"VPNP",4)==0) {
1466 vars_to_check=VPNP;
1467 volume_name = strdup (optarg+4);
1468 if (!strcmp(volume_name,""))
1469 volume_name = strdup("SYS");
1470 }
1471 else if (!strcmp(optarg,"ABENDS"))
1472 vars_to_check=ABENDS;
1473 else if (!strcmp(optarg,"CSPROCS"))
1474 vars_to_check=CSPROCS;
1475 else if (!strcmp(optarg,"TSYNC"))
1476 vars_to_check=TSYNC;
1477 else if (!strcmp(optarg,"DSVER"))
1478 vars_to_check=DSVER;
1479 else if (!strcmp(optarg,"UPTIME")) {
1480 vars_to_check=UPTIME;
1481 }
1482 else if (strncmp(optarg,"NLM:",4)==0) {
1483 vars_to_check=NLM;
1484 nlm_name=strdup (optarg+4);
1485 }
1486 else if (strncmp(optarg,"NRMP",4)==0) {
1487 vars_to_check=NRMP;
1488 nrmp_name = strdup (optarg+4);
1489 if (!strcmp(nrmp_name,""))
1490 nrmp_name = strdup ("AVAILABLE_MEMORY");
1491 }
1492 else if (strncmp(optarg,"NRMM",4)==0) {
1493 vars_to_check=NRMM;
1494 nrmm_name = strdup (optarg+4);
1495 if (!strcmp(nrmm_name,""))
1496 nrmm_name = strdup ("AVAILABLE_CACHE_MEMORY");
1497
1498 }
1499
1500 else if (strncmp(optarg,"NRMS",4)==0) {
1501 vars_to_check=NRMS;
1502 nrms_name = strdup (optarg+4);
1503 if (!strcmp(nrms_name,""))
1504 nrms_name = strdup ("USED_SWAP_SPACE");
1505
1506 }
1507
1508 else if (strncmp(optarg,"NSS1",4)==0) {
1509 vars_to_check=NSS1;
1510 nss1_name = strdup (optarg+4);
1511 if (!strcmp(nss1_name,""))
1512 nss1_name = strdup ("CURRENTBUFFERCACHESIZE");
1513
1514 }
1515
1516 else if (strncmp(optarg,"NSS2",4)==0) {
1517 vars_to_check=NSS2;
1518 nss2_name = strdup (optarg+4);
1519 if (!strcmp(nss2_name,""))
1520 nss2_name = strdup ("CACHEHITS");
1521
1522 }
1523
1524 else if (strncmp(optarg,"NSS3",4)==0) {
1525 vars_to_check=NSS3;
1526 nss3_name = strdup (optarg+4);
1527 if (!strcmp(nss3_name,""))
1528 nss3_name = strdup ("CACHEGITPERCENT");
1529
1530 }
1531
1532 else if (strncmp(optarg,"NSS4",4)==0) {
1533 vars_to_check=NSS4;
1534 nss4_name = strdup (optarg+4);
1535 if (!strcmp(nss4_name,""))
1536 nss4_name = strdup ("CURRENTOPENCOUNT");
1537
1538 }
1539
1540 else if (strncmp(optarg,"NSS5",4)==0) {
1541 vars_to_check=NSS5;
1542 nss5_name = strdup (optarg+4);
1543 if (!strcmp(nss5_name,""))
1544 nss5_name = strdup ("CACHEMISSES");
1545
1546 }
1547
1548
1549 else if (strncmp(optarg,"NSS6",4)==0) {
1550 vars_to_check=NSS6;
1551 nss6_name = strdup (optarg+4);
1552 if (!strcmp(nss6_name,""))
1553 nss6_name = strdup ("PENDINGWORKSCOUNT");
1554
1555 }
1556
1557
1558 else if (strncmp(optarg,"NSS7",4)==0) {
1559 vars_to_check=NSS7;
1560 nss7_name = strdup (optarg+4);
1561 if (!strcmp(nss7_name,""))
1562 nss7_name = strdup ("CACHESIZE");
1563
1564 }
1565 1346
1347 }
1348
1349 else if (strncmp(optarg, "NRMS", 4) == 0) {
1350 vars_to_check = NRMS;
1351 nrms_name = strdup(optarg + 4);
1352 if (!strcmp(nrms_name, ""))
1353 nrms_name = strdup("USED_SWAP_SPACE");
1354
1355 }
1356
1357 else if (strncmp(optarg, "NSS1", 4) == 0) {
1358 vars_to_check = NSS1;
1359 nss1_name = strdup(optarg + 4);
1360 if (!strcmp(nss1_name, ""))
1361 nss1_name = strdup("CURRENTBUFFERCACHESIZE");
1566 1362
1567 else
1568 return ERROR;
1569 break;
1570 case 'w': /* warning threshold */
1571 warning_value=strtoul(optarg,NULL,10);
1572 check_warning_value = true;
1573 break;
1574 case 'c': /* critical threshold */
1575 critical_value=strtoul(optarg,NULL,10);
1576 check_critical_value = true;
1577 break;
1578 case 't': /* timeout */
1579 socket_timeout=atoi(optarg);
1580 if (socket_timeout<=0)
1581 return ERROR;
1582 } 1363 }
1583 1364
1365 else if (strncmp(optarg, "NSS2", 4) == 0) {
1366 vars_to_check = NSS2;
1367 nss2_name = strdup(optarg + 4);
1368 if (!strcmp(nss2_name, ""))
1369 nss2_name = strdup("CACHEHITS");
1370
1371 }
1372
1373 else if (strncmp(optarg, "NSS3", 4) == 0) {
1374 vars_to_check = NSS3;
1375 nss3_name = strdup(optarg + 4);
1376 if (!strcmp(nss3_name, ""))
1377 nss3_name = strdup("CACHEGITPERCENT");
1378
1379 }
1380
1381 else if (strncmp(optarg, "NSS4", 4) == 0) {
1382 vars_to_check = NSS4;
1383 nss4_name = strdup(optarg + 4);
1384 if (!strcmp(nss4_name, ""))
1385 nss4_name = strdup("CURRENTOPENCOUNT");
1386
1387 }
1388
1389 else if (strncmp(optarg, "NSS5", 4) == 0) {
1390 vars_to_check = NSS5;
1391 nss5_name = strdup(optarg + 4);
1392 if (!strcmp(nss5_name, ""))
1393 nss5_name = strdup("CACHEMISSES");
1394
1395 }
1396
1397 else if (strncmp(optarg, "NSS6", 4) == 0) {
1398 vars_to_check = NSS6;
1399 nss6_name = strdup(optarg + 4);
1400 if (!strcmp(nss6_name, ""))
1401 nss6_name = strdup("PENDINGWORKSCOUNT");
1402
1403 }
1404
1405 else if (strncmp(optarg, "NSS7", 4) == 0) {
1406 vars_to_check = NSS7;
1407 nss7_name = strdup(optarg + 4);
1408 if (!strcmp(nss7_name, ""))
1409 nss7_name = strdup("CACHESIZE");
1410
1411 }
1412
1413 else
1414 return ERROR;
1415 break;
1416 case 'w': /* warning threshold */
1417 warning_value = strtoul(optarg, NULL, 10);
1418 check_warning_value = true;
1419 break;
1420 case 'c': /* critical threshold */
1421 critical_value = strtoul(optarg, NULL, 10);
1422 check_critical_value = true;
1423 break;
1424 case 't': /* timeout */
1425 socket_timeout = atoi(optarg);
1426 if (socket_timeout <= 0)
1427 return ERROR;
1428 }
1584 } 1429 }
1585 1430
1586 return OK; 1431 return OK;
1587} 1432}
1588 1433
1589 1434void print_help(void) {
1590
1591void print_help(void)
1592{
1593 char *myport; 1435 char *myport;
1594 xasprintf (&myport, "%d", PORT); 1436 xasprintf(&myport, "%d", PORT);
1595 1437
1596 print_revision (progname, NP_VERSION); 1438 print_revision(progname, NP_VERSION);
1597 1439
1598 printf ("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n"); 1440 printf("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n");
1599 printf (COPYRIGHT, copyright, email); 1441 printf(COPYRIGHT, copyright, email);
1600 1442
1601 printf ("%s\n", _("This plugin attempts to contact the MRTGEXT NLM running on a")); 1443 printf("%s\n", _("This plugin attempts to contact the MRTGEXT NLM running on a"));
1602 printf ("%s\n", _("Novell server to gather the requested system information.")); 1444 printf("%s\n", _("Novell server to gather the requested system information."));
1603 1445
1604 printf ("\n\n"); 1446 printf("\n\n");
1605 1447
1606 print_usage(); 1448 print_usage();
1607 1449
1608 printf (UT_HELP_VRSN); 1450 printf(UT_HELP_VRSN);
1609 printf (UT_EXTRA_OPTS); 1451 printf(UT_EXTRA_OPTS);
1610 1452
1611 printf (UT_HOST_PORT, 'p', myport); 1453 printf(UT_HOST_PORT, 'p', myport);
1612 1454
1613 printf (" %s\n", "-v, --variable=STRING"); 1455 printf(" %s\n", "-v, --variable=STRING");
1614 printf (" %s\n", _("Variable to check. Valid variables include:")); 1456 printf(" %s\n", _("Variable to check. Valid variables include:"));
1615 printf (" %s\n", _("LOAD1 = 1 minute average CPU load")); 1457 printf(" %s\n", _("LOAD1 = 1 minute average CPU load"));
1616 printf (" %s\n", _("LOAD5 = 5 minute average CPU load")); 1458 printf(" %s\n", _("LOAD5 = 5 minute average CPU load"));
1617 printf (" %s\n", _("LOAD15 = 15 minute average CPU load")); 1459 printf(" %s\n", _("LOAD15 = 15 minute average CPU load"));
1618 printf (" %s\n", _("CSPROCS = number of current service processes (NW 5.x only)")); 1460 printf(" %s\n", _("CSPROCS = number of current service processes (NW 5.x only)"));
1619 printf (" %s\n", _("ABENDS = number of abended threads (NW 5.x only)")); 1461 printf(" %s\n", _("ABENDS = number of abended threads (NW 5.x only)"));
1620 printf (" %s\n", _("UPTIME = server uptime")); 1462 printf(" %s\n", _("UPTIME = server uptime"));
1621 printf (" %s\n", _("LTCH = percent long term cache hits")); 1463 printf(" %s\n", _("LTCH = percent long term cache hits"));
1622 printf (" %s\n", _("CBUFF = current number of cache buffers")); 1464 printf(" %s\n", _("CBUFF = current number of cache buffers"));
1623 printf (" %s\n", _("CDBUFF = current number of dirty cache buffers")); 1465 printf(" %s\n", _("CDBUFF = current number of dirty cache buffers"));
1624 printf (" %s\n", _("DCB = dirty cache buffers as a percentage of the total")); 1466 printf(" %s\n", _("DCB = dirty cache buffers as a percentage of the total"));
1625 printf (" %s\n", _("TCB = dirty cache buffers as a percentage of the original")); 1467 printf(" %s\n", _("TCB = dirty cache buffers as a percentage of the original"));
1626 printf (" %s\n", _("OFILES = number of open files")); 1468 printf(" %s\n", _("OFILES = number of open files"));
1627 printf (" %s\n", _(" VMF<vol> = MB of free space on Volume <vol>")); 1469 printf(" %s\n", _(" VMF<vol> = MB of free space on Volume <vol>"));
1628 printf (" %s\n", _(" VMU<vol> = MB used space on Volume <vol>")); 1470 printf(" %s\n", _(" VMU<vol> = MB used space on Volume <vol>"));
1629 printf (" %s\n", _(" VMP<vol> = MB of purgeable space on Volume <vol>")); 1471 printf(" %s\n", _(" VPU<vol> = percent used space on Volume <vol>"));
1630 printf (" %s\n", _(" VPF<vol> = percent free space on volume <vol>")); 1472 printf(" %s\n", _(" VMP<vol> = MB of purgeable space on Volume <vol>"));
1631 printf (" %s\n", _(" VKF<vol> = KB of free space on volume <vol>")); 1473 printf(" %s\n", _(" VPF<vol> = percent free space on volume <vol>"));
1632 printf (" %s\n", _(" VPP<vol> = percent purgeable space on volume <vol>")); 1474 printf(" %s\n", _(" VKF<vol> = KB of free space on volume <vol>"));
1633 printf (" %s\n", _(" VKP<vol> = KB of purgeable space on volume <vol>")); 1475 printf(" %s\n", _(" VPP<vol> = percent purgeable space on volume <vol>"));
1634 printf (" %s\n", _(" VPNP<vol> = percent not yet purgeable space on volume <vol>")); 1476 printf(" %s\n", _(" VKP<vol> = KB of purgeable space on volume <vol>"));
1635 printf (" %s\n", _(" VKNP<vol> = KB of not yet purgeable space on volume <vol>")); 1477 printf(" %s\n", _(" VPNP<vol> = percent not yet purgeable space on volume <vol>"));
1636 printf (" %s\n", _(" LRUM = LRU sitting time in minutes")); 1478 printf(" %s\n", _(" VKNP<vol> = KB of not yet purgeable space on volume <vol>"));
1637 printf (" %s\n", _(" LRUS = LRU sitting time in seconds")); 1479 printf(" %s\n", _(" LRUM = LRU sitting time in minutes"));
1638 printf (" %s\n", _(" DSDB = check to see if DS Database is open")); 1480 printf(" %s\n", _(" LRUS = LRU sitting time in seconds"));
1639 printf (" %s\n", _(" DSVER = NDS version")); 1481 printf(" %s\n", _(" DSDB = check to see if DS Database is open"));
1640 printf (" %s\n", _(" UPRB = used packet receive buffers")); 1482 printf(" %s\n", _(" DSVER = NDS version"));
1641 printf (" %s\n", _(" PUPRB = percent (of max) used packet receive buffers")); 1483 printf(" %s\n", _(" UPRB = used packet receive buffers"));
1642 printf (" %s\n", _(" SAPENTRIES = number of entries in the SAP table")); 1484 printf(" %s\n", _(" PUPRB = percent (of max) used packet receive buffers"));
1643 printf (" %s\n", _(" SAPENTRIES<n> = number of entries in the SAP table for SAP type <n>")); 1485 printf(" %s\n", _(" SAPENTRIES = number of entries in the SAP table"));
1644 printf (" %s\n", _(" TSYNC = timesync status")); 1486 printf(" %s\n", _(" SAPENTRIES<n> = number of entries in the SAP table for SAP type <n>"));
1645 printf (" %s\n", _(" LOGINS = check to see if logins are enabled")); 1487 printf(" %s\n", _(" TSYNC = timesync status"));
1646 printf (" %s\n", _(" CONNS = number of currently licensed connections")); 1488 printf(" %s\n", _(" LOGINS = check to see if logins are enabled"));
1647 printf (" %s\n", _(" NRMH = NRM Summary Status")); 1489 printf(" %s\n", _(" CONNS = number of currently licensed connections"));
1648 printf (" %s\n", _(" NRMP<stat> = Returns the current value for a NRM health item")); 1490 printf(" %s\n", _(" NRMH = NRM Summary Status"));
1649 printf (" %s\n", _(" NRMM<stat> = Returns the current memory stats from NRM")); 1491 printf(" %s\n", _(" NRMP<stat> = Returns the current value for a NRM health item"));
1650 printf (" %s\n", _(" NRMS<stat> = Returns the current Swapfile stats from NRM")); 1492 printf(" %s\n", _(" NRMM<stat> = Returns the current memory stats from NRM"));
1651 printf (" %s\n", _(" NSS1<stat> = Statistics from _Admin:Manage_NSS\\GeneralStats.xml")); 1493 printf(" %s\n", _(" NRMS<stat> = Returns the current Swapfile stats from NRM"));
1652 printf (" %s\n", _(" NSS3<stat> = Statistics from _Admin:Manage_NSS\\NameCache.xml")); 1494 printf(" %s\n", _(" NSS1<stat> = Statistics from _Admin:Manage_NSS\\GeneralStats.xml"));
1653 printf (" %s\n", _(" NSS4<stat> = Statistics from _Admin:Manage_NSS\\FileStats.xml")); 1495 printf(" %s\n", _(" NSS3<stat> = Statistics from _Admin:Manage_NSS\\NameCache.xml"));
1654 printf (" %s\n", _(" NSS5<stat> = Statistics from _Admin:Manage_NSS\\ObjectCache.xml")); 1496 printf(" %s\n", _(" NSS4<stat> = Statistics from _Admin:Manage_NSS\\FileStats.xml"));
1655 printf (" %s\n", _(" NSS6<stat> = Statistics from _Admin:Manage_NSS\\Thread.xml")); 1497 printf(" %s\n", _(" NSS5<stat> = Statistics from _Admin:Manage_NSS\\ObjectCache.xml"));
1656 printf (" %s\n", _(" NSS7<stat> = Statistics from _Admin:Manage_NSS\\AuthorizationCache.xml")); 1498 printf(" %s\n", _(" NSS6<stat> = Statistics from _Admin:Manage_NSS\\Thread.xml"));
1657 printf (" %s\n", _(" NLM:<nlm> = check if NLM is loaded and report version")); 1499 printf(" %s\n", _(" NSS7<stat> = Statistics from _Admin:Manage_NSS\\AuthorizationCache.xml"));
1658 printf (" %s\n", _(" (e.g. NLM:TSANDS.NLM)")); 1500 printf(" %s\n", _(" NLM:<nlm> = check if NLM is loaded and report version"));
1659 printf ("\n"); 1501 printf(" %s\n", _(" (e.g. NLM:TSANDS.NLM)"));
1660 printf (" %s\n", "-w, --warning=INTEGER"); 1502 printf("\n");
1661 printf (" %s\n", _("Threshold which will result in a warning status")); 1503 printf(" %s\n", "-w, --warning=INTEGER");
1662 printf (" %s\n", "-c, --critical=INTEGER"); 1504 printf(" %s\n", _("Threshold which will result in a warning status"));
1663 printf (" %s\n", _("Threshold which will result in a critical status")); 1505 printf(" %s\n", "-c, --critical=INTEGER");
1664 printf (" %s\n", "-o, --osversion"); 1506 printf(" %s\n", _("Threshold which will result in a critical status"));
1665 printf (" %s\n", _("Include server version string in results")); 1507 printf(" %s\n", "-o, --osversion");
1666 1508 printf(" %s\n", _("Include server version string in results"));
1667 printf (UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); 1509
1668 1510 printf(UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
1669 printf ("\n"); 1511
1670 printf ("%s\n", _("Notes:")); 1512 printf("\n");
1671 printf (" %s\n", _("- This plugin requires that the MRTGEXT.NLM file from James Drews' MRTG")); 1513 printf("%s\n", _("Notes:"));
1672 printf (" %s\n", _(" extension for NetWare be loaded on the Novell servers you wish to check.")); 1514 printf(" %s\n", _("- This plugin requires that the MRTGEXT.NLM file from James Drews' MRTG"));
1673 printf (" %s\n", _(" (available from http://www.engr.wisc.edu/~drews/mrtg/)")); 1515 printf(" %s\n", _(" extension for NetWare be loaded on the Novell servers you wish to check."));
1674 printf (" %s\n", _("- Values for critical thresholds should be lower than warning thresholds")); 1516 printf(" %s\n", _(" (available from http://www.engr.wisc.edu/~drews/mrtg/)"));
1675 printf (" %s\n", _(" when the following variables are checked: VPF, VKF, LTCH, CBUFF, DCB, ")); 1517 printf(" %s\n", _("- Values for critical thresholds should be lower than warning thresholds"));
1676 printf (" %s\n", _(" TCB, LRUS and LRUM.")); 1518 printf(" %s\n", _(" when the following variables are checked: VPF, VKF, LTCH, CBUFF, DCB, "));
1677 1519 printf(" %s\n", _(" TCB, LRUS and LRUM."));
1678 printf (UT_SUPPORT); 1520
1521 printf(UT_SUPPORT);
1679} 1522}
1680 1523
1681 1524void print_usage(void) {
1682 1525 printf("%s\n", _("Usage:"));
1683void print_usage(void) 1526 printf("%s -H host [-p port] [-v variable] [-w warning] [-c critical] [-t timeout]\n", progname);
1684{
1685 printf ("%s\n", _("Usage:"));
1686 printf ("%s -H host [-p port] [-v variable] [-w warning] [-c critical] [-t timeout]\n",progname);
1687} 1527}
diff --git a/plugins/check_overcr.c b/plugins/check_overcr.c
index 5165c828..e80d4775 100644
--- a/plugins/check_overcr.c
+++ b/plugins/check_overcr.c
@@ -1,36 +1,36 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring check_overcr plugin 3 * Monitoring check_overcr plugin
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 2000-2007 Monitoring Plugins Development Team 6 * Copyright (c) 2000-2024 Monitoring Plugins Development Team
7* 7 *
8* Description: 8 * Description:
9* 9 *
10* This file contains the check_overcr plugin 10 * This file contains the check_overcr plugin
11* 11 *
12* This plugin attempts to contact the Over-CR collector daemon running on the 12 * This plugin attempts to contact the Over-CR collector daemon running on the
13* remote UNIX server in order to gather the requested system information. 13 * remote UNIX server in order to gather the requested system information.
14* 14 *
15* 15 *
16* This program is free software: you can redistribute it and/or modify 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 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 18 * the Free Software Foundation, either version 3 of the License, or
19* (at your option) any later version. 19 * (at your option) any later version.
20* 20 *
21* This program is distributed in the hope that it will be useful, 21 * This program is distributed in the hope that it will be useful,
22* but WITHOUT ANY WARRANTY; without even the implied warranty of 22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24* GNU General Public License for more details. 24 * GNU General Public License for more details.
25* 25 *
26* You should have received a copy of the GNU General Public License 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/>. 27 * along with this program. If not, see <http://www.gnu.org/licenses/>.
28* 28 *
29* 29 *
30*****************************************************************************/ 30 *****************************************************************************/
31 31
32const char *progname = "check_overcr"; 32const char *progname = "check_overcr";
33const char *copyright = "2000-2007"; 33const char *copyright = "2000-2024";
34const char *email = "devel@monitoring-plugins.org"; 34const char *email = "devel@monitoring-plugins.org";
35 35
36#include "common.h" 36#include "common.h"
@@ -66,13 +66,11 @@ char *disk_name = NULL;
66char *process_name = NULL; 66char *process_name = NULL;
67char send_buffer[MAX_INPUT_BUFFER]; 67char send_buffer[MAX_INPUT_BUFFER];
68 68
69int process_arguments (int, char **); 69int process_arguments(int, char **);
70void print_usage (void); 70void print_usage(void);
71void print_help (void); 71void print_help(void);
72 72
73int 73int main(int argc, char **argv) {
74main (int argc, char **argv)
75{
76 int result = STATE_UNKNOWN; 74 int result = STATE_UNKNOWN;
77 char recv_buffer[MAX_INPUT_BUFFER]; 75 char recv_buffer[MAX_INPUT_BUFFER];
78 char temp_buffer[MAX_INPUT_BUFFER]; 76 char temp_buffer[MAX_INPUT_BUFFER];
@@ -91,66 +89,62 @@ main (int argc, char **argv)
91 int uptime_hours = 0; 89 int uptime_hours = 0;
92 int uptime_minutes = 0; 90 int uptime_minutes = 0;
93 91
94 setlocale (LC_ALL, ""); 92 setlocale(LC_ALL, "");
95 bindtextdomain (PACKAGE, LOCALEDIR); 93 bindtextdomain(PACKAGE, LOCALEDIR);
96 textdomain (PACKAGE); 94 textdomain(PACKAGE);
97 95
98 /* Parse extra opts if any */ 96 /* Parse extra opts if any */
99 argv=np_extra_opts (&argc, argv, progname); 97 argv = np_extra_opts(&argc, argv, progname);
100 98
101 if (process_arguments (argc, argv) == ERROR) 99 if (process_arguments(argc, argv) == ERROR)
102 usage4 (_("Could not parse arguments")); 100 usage4(_("Could not parse arguments"));
103 101
104 /* initialize alarm signal handling */ 102 /* initialize alarm signal handling */
105 signal (SIGALRM, socket_timeout_alarm_handler); 103 signal(SIGALRM, socket_timeout_alarm_handler);
106 104
107 /* set socket timeout */ 105 /* set socket timeout */
108 alarm (socket_timeout); 106 alarm(socket_timeout);
109 107
110 result = process_tcp_request2 (server_address, 108 result = process_tcp_request2(server_address, server_port, send_buffer, recv_buffer, sizeof(recv_buffer));
111 server_port,
112 send_buffer,
113 recv_buffer,
114 sizeof (recv_buffer));
115 109
116 switch (vars_to_check) { 110 switch (vars_to_check) {
117 111
118 case LOAD1: 112 case LOAD1:
119 case LOAD5: 113 case LOAD5:
120 case LOAD15: 114 case LOAD15:
121 115
122 if (result != STATE_OK) 116 if (result != STATE_OK)
123 die (result, _("Unknown error fetching load data\n")); 117 die(result, _("Unknown error fetching load data\n"));
124 118
125 temp_ptr = (char *) strtok (recv_buffer, "\r\n"); 119 temp_ptr = (char *)strtok(recv_buffer, "\r\n");
126 if (temp_ptr == NULL) 120 if (temp_ptr == NULL)
127 die (STATE_CRITICAL, _("Invalid response from server - no load information\n")); 121 die(STATE_CRITICAL, _("Invalid response from server - no load information\n"));
128 else 122 else
129 load_1min = strtod (temp_ptr, NULL); 123 load_1min = strtod(temp_ptr, NULL);
130 124
131 temp_ptr = (char *) strtok (NULL, "\r\n"); 125 temp_ptr = (char *)strtok(NULL, "\r\n");
132 if (temp_ptr == NULL) 126 if (temp_ptr == NULL)
133 die (STATE_CRITICAL, _("Invalid response from server after load 1\n")); 127 die(STATE_CRITICAL, _("Invalid response from server after load 1\n"));
134 else 128 else
135 load_5min = strtod (temp_ptr, NULL); 129 load_5min = strtod(temp_ptr, NULL);
136 130
137 temp_ptr = (char *) strtok (NULL, "\r\n"); 131 temp_ptr = (char *)strtok(NULL, "\r\n");
138 if (temp_ptr == NULL) 132 if (temp_ptr == NULL)
139 die (STATE_CRITICAL, _("Invalid response from server after load 5\n")); 133 die(STATE_CRITICAL, _("Invalid response from server after load 5\n"));
140 else 134 else
141 load_15min = strtod (temp_ptr, NULL); 135 load_15min = strtod(temp_ptr, NULL);
142 136
143 switch (vars_to_check) { 137 switch (vars_to_check) {
144 case LOAD1: 138 case LOAD1:
145 strcpy (temp_buffer, "1"); 139 strcpy(temp_buffer, "1");
146 load = load_1min; 140 load = load_1min;
147 break; 141 break;
148 case LOAD5: 142 case LOAD5:
149 strcpy (temp_buffer, "5"); 143 strcpy(temp_buffer, "5");
150 load = load_5min; 144 load = load_5min;
151 break; 145 break;
152 default: 146 default:
153 strcpy (temp_buffer, "15"); 147 strcpy(temp_buffer, "15");
154 load = load_15min; 148 load = load_15min;
155 break; 149 break;
156 } 150 }
@@ -160,98 +154,82 @@ main (int argc, char **argv)
160 else if (check_warning_value && (load >= warning_value)) 154 else if (check_warning_value && (load >= warning_value))
161 result = STATE_WARNING; 155 result = STATE_WARNING;
162 156
163 die (result, 157 die(result, _("Load %s - %s-min load average = %0.2f"), state_text(result), temp_buffer, load);
164 _("Load %s - %s-min load average = %0.2f"),
165 state_text(result),
166 temp_buffer,
167 load);
168 158
169 break; 159 break;
170 160
171 case DPU: 161 case DPU:
172 162
173 if (result != STATE_OK) 163 if (result != STATE_OK)
174 die (result, _("Unknown error fetching disk data\n")); 164 die(result, _("Unknown error fetching disk data\n"));
175 165
176 for (temp_ptr = (char *) strtok (recv_buffer, " "); 166 for (temp_ptr = (char *)strtok(recv_buffer, " "); temp_ptr != NULL; temp_ptr = (char *)strtok(NULL, " ")) {
177 temp_ptr != NULL;
178 temp_ptr = (char *) strtok (NULL, " ")) {
179 167
180 if (!strcmp (temp_ptr, disk_name)) { 168 if (!strcmp(temp_ptr, disk_name)) {
181 found_disk = true; 169 found_disk = true;
182 temp_ptr = (char *) strtok (NULL, "%"); 170 temp_ptr = (char *)strtok(NULL, "%");
183 if (temp_ptr == NULL) 171 if (temp_ptr == NULL)
184 die (STATE_CRITICAL, _("Invalid response from server\n")); 172 die(STATE_CRITICAL, _("Invalid response from server\n"));
185 else 173 else
186 percent_used_disk_space = strtoul (temp_ptr, NULL, 10); 174 percent_used_disk_space = strtoul(temp_ptr, NULL, 10);
187 break; 175 break;
188 } 176 }
189 177
190 temp_ptr = (char *) strtok (NULL, "\r\n"); 178 temp_ptr = (char *)strtok(NULL, "\r\n");
191 } 179 }
192 180
193 /* error if we couldn't find the info for the disk */ 181 /* error if we couldn't find the info for the disk */
194 if (!found_disk) 182 if (!found_disk)
195 die (STATE_CRITICAL, 183 die(STATE_CRITICAL, "CRITICAL - Disk '%s' non-existent or not mounted", disk_name);
196 "CRITICAL - Disk '%s' non-existent or not mounted",
197 disk_name);
198 184
199 if (check_critical_value && (percent_used_disk_space >= critical_value)) 185 if (check_critical_value && (percent_used_disk_space >= critical_value))
200 result = STATE_CRITICAL; 186 result = STATE_CRITICAL;
201 else if (check_warning_value && (percent_used_disk_space >= warning_value)) 187 else if (check_warning_value && (percent_used_disk_space >= warning_value))
202 result = STATE_WARNING; 188 result = STATE_WARNING;
203 189
204 die (result, "Disk %s - %lu%% used on %s", state_text(result), percent_used_disk_space, disk_name); 190 die(result, "Disk %s - %lu%% used on %s", state_text(result), percent_used_disk_space, disk_name);
205 191
206 break; 192 break;
207 193
208 case NETSTAT: 194 case NETSTAT:
209 195
210 if (result != STATE_OK) 196 if (result != STATE_OK)
211 die (result, _("Unknown error fetching network status\n")); 197 die(result, _("Unknown error fetching network status\n"));
212 else 198 else
213 port_connections = strtod (recv_buffer, NULL); 199 port_connections = strtod(recv_buffer, NULL);
214 200
215 if (check_critical_value && (port_connections >= critical_value)) 201 if (check_critical_value && (port_connections >= critical_value))
216 result = STATE_CRITICAL; 202 result = STATE_CRITICAL;
217 else if (check_warning_value && (port_connections >= warning_value)) 203 else if (check_warning_value && (port_connections >= warning_value))
218 result = STATE_WARNING; 204 result = STATE_WARNING;
219 205
220 die (result, 206 die(result, _("Net %s - %d connection%s on port %d"), state_text(result), port_connections, (port_connections == 1) ? "" : "s",
221 _("Net %s - %d connection%s on port %d"), 207 netstat_port);
222 state_text(result),
223 port_connections,
224 (port_connections == 1) ? "" : "s",
225 netstat_port);
226 208
227 break; 209 break;
228 210
229 case PROCS: 211 case PROCS:
230 212
231 if (result != STATE_OK) 213 if (result != STATE_OK)
232 die (result, _("Unknown error fetching process status\n")); 214 die(result, _("Unknown error fetching process status\n"));
233 215
234 temp_ptr = (char *) strtok (recv_buffer, "("); 216 temp_ptr = (char *)strtok(recv_buffer, "(");
235 if (temp_ptr == NULL) 217 if (temp_ptr == NULL)
236 die (STATE_CRITICAL, _("Invalid response from server\n")); 218 die(STATE_CRITICAL, _("Invalid response from server\n"));
237 219
238 temp_ptr = (char *) strtok (NULL, ")"); 220 temp_ptr = (char *)strtok(NULL, ")");
239 if (temp_ptr == NULL) 221 if (temp_ptr == NULL)
240 die (STATE_CRITICAL, _("Invalid response from server\n")); 222 die(STATE_CRITICAL, _("Invalid response from server\n"));
241 else 223 else
242 processes = strtod (temp_ptr, NULL); 224 processes = strtod(temp_ptr, NULL);
243 225
244 if (check_critical_value && (processes >= critical_value)) 226 if (check_critical_value && (processes >= critical_value))
245 result = STATE_CRITICAL; 227 result = STATE_CRITICAL;
246 else if (check_warning_value && (processes >= warning_value)) 228 else if (check_warning_value && (processes >= warning_value))
247 result = STATE_WARNING; 229 result = STATE_WARNING;
248 230
249 die (result, 231 die(result, _("Process %s - %d instance%s of %s running"), state_text(result), processes, (processes == 1) ? "" : "s",
250 _("Process %s - %d instance%s of %s running"), 232 process_name);
251 state_text(result),
252 processes,
253 (processes == 1) ? "" : "s",
254 process_name);
255 break; 233 break;
256 234
257 case UPTIME: 235 case UPTIME:
@@ -259,8 +237,8 @@ main (int argc, char **argv)
259 if (result != STATE_OK) 237 if (result != STATE_OK)
260 return result; 238 return result;
261 239
262 uptime_raw_hours = strtod (recv_buffer, NULL); 240 uptime_raw_hours = strtod(recv_buffer, NULL);
263 uptime_raw_minutes = (unsigned long) (uptime_raw_hours * 60.0); 241 uptime_raw_minutes = (unsigned long)(uptime_raw_hours * 60.0);
264 242
265 if (check_critical_value && (uptime_raw_minutes <= critical_value)) 243 if (check_critical_value && (uptime_raw_minutes <= critical_value))
266 result = STATE_CRITICAL; 244 result = STATE_CRITICAL;
@@ -273,46 +251,31 @@ main (int argc, char **argv)
273 uptime_raw_minutes %= 60; 251 uptime_raw_minutes %= 60;
274 uptime_minutes = uptime_raw_minutes; 252 uptime_minutes = uptime_raw_minutes;
275 253
276 die (result, 254 die(result, _("Uptime %s - Up %d days %d hours %d minutes"), state_text(result), uptime_days, uptime_hours, uptime_minutes);
277 _("Uptime %s - Up %d days %d hours %d minutes"),
278 state_text(result),
279 uptime_days,
280 uptime_hours,
281 uptime_minutes);
282 break; 255 break;
283 256
284 default: 257 default:
285 die (STATE_UNKNOWN, _("Nothing to check!\n")); 258 die(STATE_UNKNOWN, _("Nothing to check!\n"));
286 break; 259 break;
287 } 260 }
288} 261}
289 262
290
291/* process command-line arguments */ 263/* process command-line arguments */
292int 264int process_arguments(int argc, char **argv) {
293process_arguments (int argc, char **argv)
294{
295 int c; 265 int c;
296 266
297 int option = 0; 267 int option = 0;
298 static struct option longopts[] = { 268 static struct option longopts[] = {
299 {"port", required_argument, 0, 'p'}, 269 {"port", required_argument, 0, 'p'}, {"timeout", required_argument, 0, 't'}, {"critical", required_argument, 0, 'c'},
300 {"timeout", required_argument, 0, 't'}, 270 {"warning", required_argument, 0, 'w'}, {"variable", required_argument, 0, 'v'}, {"hostname", required_argument, 0, 'H'},
301 {"critical", required_argument, 0, 'c'}, 271 {"version", no_argument, 0, 'V'}, {"help", no_argument, 0, 'h'}, {0, 0, 0, 0}};
302 {"warning", required_argument, 0, 'w'},
303 {"variable", required_argument, 0, 'v'},
304 {"hostname", required_argument, 0, 'H'},
305 {"version", no_argument, 0, 'V'},
306 {"help", no_argument, 0, 'h'},
307 {0, 0, 0, 0}
308 };
309 272
310 /* no options were supplied */ 273 /* no options were supplied */
311 if (argc < 2) 274 if (argc < 2)
312 return ERROR; 275 return ERROR;
313 276
314 /* backwards compatibility */ 277 /* backwards compatibility */
315 if (!is_option (argv[1])) { 278 if (!is_option(argv[1])) {
316 server_address = argv[1]; 279 server_address = argv[1];
317 argv[1] = argv[0]; 280 argv[1] = argv[0];
318 argv = &argv[1]; 281 argv = &argv[1];
@@ -320,150 +283,136 @@ process_arguments (int argc, char **argv)
320 } 283 }
321 284
322 for (c = 1; c < argc; c++) { 285 for (c = 1; c < argc; c++) {
323 if (strcmp ("-to", argv[c]) == 0) 286 if (strcmp("-to", argv[c]) == 0)
324 strcpy (argv[c], "-t"); 287 strcpy(argv[c], "-t");
325 else if (strcmp ("-wv", argv[c]) == 0) 288 else if (strcmp("-wv", argv[c]) == 0)
326 strcpy (argv[c], "-w"); 289 strcpy(argv[c], "-w");
327 else if (strcmp ("-cv", argv[c]) == 0) 290 else if (strcmp("-cv", argv[c]) == 0)
328 strcpy (argv[c], "-c"); 291 strcpy(argv[c], "-c");
329 } 292 }
330 293
331 while (1) { 294 while (1) {
332 c = getopt_long (argc, argv, "+hVH:t:c:w:p:v:", longopts, 295 c = getopt_long(argc, argv, "+hVH:t:c:w:p:v:", longopts, &option);
333 &option);
334 296
335 if (c == -1 || c == EOF || c == 1) 297 if (c == -1 || c == EOF || c == 1)
336 break; 298 break;
337 299
338 switch (c) { 300 switch (c) {
339 case '?': /* print short usage statement if args not parsable */ 301 case '?': /* print short usage statement if args not parsable */
340 usage5 (); 302 usage5();
341 case 'h': /* help */ 303 case 'h': /* help */
342 print_help (); 304 print_help();
343 exit (STATE_UNKNOWN); 305 exit(STATE_UNKNOWN);
344 case 'V': /* version */ 306 case 'V': /* version */
345 print_revision (progname, NP_VERSION); 307 print_revision(progname, NP_VERSION);
346 exit (STATE_UNKNOWN); 308 exit(STATE_UNKNOWN);
347 case 'H': /* hostname */ 309 case 'H': /* hostname */
348 server_address = optarg; 310 server_address = optarg;
349 break; 311 break;
350 case 'p': /* port */ 312 case 'p': /* port */
351 if (is_intnonneg (optarg)) 313 if (is_intnonneg(optarg))
352 server_port = atoi (optarg); 314 server_port = atoi(optarg);
353 else 315 else
354 die (STATE_UNKNOWN, 316 die(STATE_UNKNOWN, _("Server port an integer\n"));
355 _("Server port an integer\n"));
356 break; 317 break;
357 case 'v': /* variable */ 318 case 'v': /* variable */
358 if (strcmp (optarg, "LOAD") == 0) { 319 if (strcmp(optarg, "LOAD") == 0) {
359 strcpy (send_buffer, "LOAD\r\nQUIT\r\n"); 320 strcpy(send_buffer, "LOAD\r\nQUIT\r\n");
360 if (strcmp (optarg, "LOAD1") == 0) 321 if (strcmp(optarg, "LOAD1") == 0)
361 vars_to_check = LOAD1; 322 vars_to_check = LOAD1;
362 else if (strcmp (optarg, "LOAD5") == 0) 323 else if (strcmp(optarg, "LOAD5") == 0)
363 vars_to_check = LOAD5; 324 vars_to_check = LOAD5;
364 else if (strcmp (optarg, "LOAD15") == 0) 325 else if (strcmp(optarg, "LOAD15") == 0)
365 vars_to_check = LOAD15; 326 vars_to_check = LOAD15;
366 } 327 } else if (strcmp(optarg, "UPTIME") == 0) {
367 else if (strcmp (optarg, "UPTIME") == 0) {
368 vars_to_check = UPTIME; 328 vars_to_check = UPTIME;
369 strcpy (send_buffer, "UPTIME\r\n"); 329 strcpy(send_buffer, "UPTIME\r\n");
370 } 330 } else if (strstr(optarg, "PROC") == optarg) {
371 else if (strstr (optarg, "PROC") == optarg) {
372 vars_to_check = PROCS; 331 vars_to_check = PROCS;
373 process_name = strscpy (process_name, optarg + 4); 332 process_name = strscpy(process_name, optarg + 4);
374 sprintf (send_buffer, "PROCESS %s\r\n", process_name); 333 sprintf(send_buffer, "PROCESS %s\r\n", process_name);
375 } 334 } else if (strstr(optarg, "NET") == optarg) {
376 else if (strstr (optarg, "NET") == optarg) {
377 vars_to_check = NETSTAT; 335 vars_to_check = NETSTAT;
378 netstat_port = atoi (optarg + 3); 336 netstat_port = atoi(optarg + 3);
379 sprintf (send_buffer, "NETSTAT %d\r\n", netstat_port); 337 sprintf(send_buffer, "NETSTAT %d\r\n", netstat_port);
380 } 338 } else if (strstr(optarg, "DPU") == optarg) {
381 else if (strstr (optarg, "DPU") == optarg) {
382 vars_to_check = DPU; 339 vars_to_check = DPU;
383 strcpy (send_buffer, "DISKSPACE\r\n"); 340 strcpy(send_buffer, "DISKSPACE\r\n");
384 disk_name = strscpy (disk_name, optarg + 3); 341 disk_name = strscpy(disk_name, optarg + 3);
385 } 342 } else
386 else
387 return ERROR; 343 return ERROR;
388 break; 344 break;
389 case 'w': /* warning threshold */ 345 case 'w': /* warning threshold */
390 warning_value = strtoul (optarg, NULL, 10); 346 warning_value = strtoul(optarg, NULL, 10);
391 check_warning_value = true; 347 check_warning_value = true;
392 break; 348 break;
393 case 'c': /* critical threshold */ 349 case 'c': /* critical threshold */
394 critical_value = strtoul (optarg, NULL, 10); 350 critical_value = strtoul(optarg, NULL, 10);
395 check_critical_value = true; 351 check_critical_value = true;
396 break; 352 break;
397 case 't': /* timeout */ 353 case 't': /* timeout */
398 socket_timeout = atoi (optarg); 354 socket_timeout = atoi(optarg);
399 if (socket_timeout <= 0) 355 if (socket_timeout <= 0)
400 return ERROR; 356 return ERROR;
401 } 357 }
402
403 } 358 }
404 return OK; 359 return OK;
405} 360}
406 361
407 362void print_help(void) {
408void
409print_help (void)
410{
411 char *myport; 363 char *myport;
412 xasprintf (&myport, "%d", PORT); 364 xasprintf(&myport, "%d", PORT);
413 365
414 print_revision (progname, NP_VERSION); 366 print_revision(progname, NP_VERSION);
415 367
416 printf ("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n"); 368 printf("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n");
417 printf (COPYRIGHT, copyright, email); 369 printf(COPYRIGHT, copyright, email);
418 370
419 printf ("%s\n", _("This plugin attempts to contact the Over-CR collector daemon running on the")); 371 printf("%s\n", _("This plugin attempts to contact the Over-CR collector daemon running on the"));
420 printf ("%s\n", _("remote UNIX server in order to gather the requested system information.")); 372 printf("%s\n", _("remote UNIX server in order to gather the requested system information."));
421 373
422 printf ("\n\n"); 374 printf("\n\n");
423 375
424 print_usage (); 376 print_usage();
425 377
426 printf (UT_HELP_VRSN); 378 printf(UT_HELP_VRSN);
427 printf (UT_EXTRA_OPTS); 379 printf(UT_EXTRA_OPTS);
428 380
429 printf (UT_HOST_PORT, 'p', myport); 381 printf(UT_HOST_PORT, 'p', myport);
430 382
431 printf (" %s\n", "-w, --warning=INTEGER"); 383 printf(" %s\n", "-w, --warning=INTEGER");
432 printf (" %s\n", _("Threshold which will result in a warning status")); 384 printf(" %s\n", _("Threshold which will result in a warning status"));
433 printf (" %s\n", "-c, --critical=INTEGER"); 385 printf(" %s\n", "-c, --critical=INTEGER");
434 printf (" %s\n", _("Threshold which will result in a critical status")); 386 printf(" %s\n", _("Threshold which will result in a critical status"));
435 printf (" %s\n", "-v, --variable=STRING"); 387 printf(" %s\n", "-v, --variable=STRING");
436 printf (" %s\n", _("Variable to check. Valid variables include:")); 388 printf(" %s\n", _("Variable to check. Valid variables include:"));
437 printf (" %s\n", _("LOAD1 = 1 minute average CPU load")); 389 printf(" %s\n", _("LOAD1 = 1 minute average CPU load"));
438 printf (" %s\n", _("LOAD5 = 5 minute average CPU load")); 390 printf(" %s\n", _("LOAD5 = 5 minute average CPU load"));
439 printf (" %s\n", _("LOAD15 = 15 minute average CPU load")); 391 printf(" %s\n", _("LOAD15 = 15 minute average CPU load"));
440 printf (" %s\n", _("DPU<filesys> = percent used disk space on filesystem <filesys>")); 392 printf(" %s\n", _("DPU<filesys> = percent used disk space on filesystem <filesys>"));
441 printf (" %s\n", _("PROC<process> = number of running processes with name <process>")); 393 printf(" %s\n", _("PROC<process> = number of running processes with name <process>"));
442 printf (" %s\n", _("NET<port> = number of active connections on TCP port <port>")); 394 printf(" %s\n", _("NET<port> = number of active connections on TCP port <port>"));
443 printf (" %s\n", _("UPTIME = system uptime in seconds")); 395 printf(" %s\n", _("UPTIME = system uptime in seconds"));
444 396
445 printf (UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); 397 printf(UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
446 398
447 printf (UT_VERBOSE); 399 printf(UT_VERBOSE);
448 400
449 printf ("\n"); 401 printf("\n");
450 printf ("%s\n", _("This plugin requires that Eric Molitors' Over-CR collector daemon be")); 402 printf("%s\n", _("This plugin requires that Eric Molitors' Over-CR collector daemon be"));
451 printf ("%s\n", _("running on the remote server.")); 403 printf("%s\n", _("running on the remote server."));
452 printf ("%s\n", _("Over-CR can be downloaded from http://www.molitor.org/overcr")); 404 printf("%s\n", _("Over-CR can be downloaded from http://www.molitor.org/overcr"));
453 printf ("%s\n", _("This plugin was tested with version 0.99.53 of the Over-CR collector")); 405 printf("%s\n", _("This plugin was tested with version 0.99.53 of the Over-CR collector"));
454 406
455 printf ("\n"); 407 printf("\n");
456 printf ("%s\n", _("Notes:")); 408 printf("%s\n", _("Notes:"));
457 printf (" %s\n", _("For the available options, the critical threshold value should always be")); 409 printf(" %s\n", _("For the available options, the critical threshold value should always be"));
458 printf (" %s\n", _("higher than the warning threshold value, EXCEPT with the uptime variable")); 410 printf(" %s\n", _("higher than the warning threshold value, EXCEPT with the uptime variable"));
459 411
460 printf (UT_SUPPORT); 412 printf(UT_SUPPORT);
461} 413}
462 414
463 415void print_usage(void) {
464void 416 printf("%s\n", _("Usage:"));
465print_usage (void) 417 printf("%s -H host [-p port] [-v variable] [-w warning] [-c critical] [-t timeout]\n", progname);
466{
467 printf ("%s\n", _("Usage:"));
468 printf ("%s -H host [-p port] [-v variable] [-w warning] [-c critical] [-t timeout]\n", progname);
469} 418}
diff --git a/plugins/check_pgsql.c b/plugins/check_pgsql.c
index 94d589e1..6613634d 100644
--- a/plugins/check_pgsql.c
+++ b/plugins/check_pgsql.c
@@ -1,35 +1,35 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring check_pgsql plugin 3 * Monitoring check_pgsql plugin
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 1999-2011 Monitoring Plugins Development Team 6 * Copyright (c) 1999-2024 Monitoring Plugins Development Team
7* 7 *
8* Description: 8 * Description:
9* 9 *
10* This file contains the check_pgsql plugin 10 * This file contains the check_pgsql plugin
11* 11 *
12* Test whether a PostgreSQL Database is accepting connections. 12 * Test whether a PostgreSQL Database is accepting connections.
13* 13 *
14* 14 *
15* This program is free software: you can redistribute it and/or modify 15 * This program is free software: you can redistribute it and/or modify
16* it under the terms of the GNU General Public License as published by 16 * it under the terms of the GNU General Public License as published by
17* the Free Software Foundation, either version 3 of the License, or 17 * the Free Software Foundation, either version 3 of the License, or
18* (at your option) any later version. 18 * (at your option) any later version.
19* 19 *
20* This program is distributed in the hope that it will be useful, 20 * This program is distributed in the hope that it will be useful,
21* but WITHOUT ANY WARRANTY; without even the implied warranty of 21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23* GNU General Public License for more details. 23 * GNU General Public License for more details.
24* 24 *
25* You should have received a copy of the GNU General Public License 25 * You should have received a copy of the GNU General Public License
26* along with this program. If not, see <http://www.gnu.org/licenses/>. 26 * along with this program. If not, see <http://www.gnu.org/licenses/>.
27* 27 *
28* 28 *
29*****************************************************************************/ 29 *****************************************************************************/
30 30
31const char *progname = "check_pgsql"; 31const char *progname = "check_pgsql";
32const char *copyright = "1999-2011"; 32const char *copyright = "1999-2024";
33const char *email = "devel@monitoring-plugins.org"; 33const char *email = "devel@monitoring-plugins.org";
34 34
35#include "common.h" 35#include "common.h"
@@ -40,22 +40,18 @@ const char *email = "devel@monitoring-plugins.org";
40#include <libpq-fe.h> 40#include <libpq-fe.h>
41#include <pg_config_manual.h> 41#include <pg_config_manual.h>
42 42
43#define DEFAULT_DB "template1" 43#define DEFAULT_DB "template1"
44#define DEFAULT_HOST "127.0.0.1" 44#define DEFAULT_HOST "127.0.0.1"
45 45
46/* return the PSQL server version as a 3-tuple */ 46/* return the PSQL server version as a 3-tuple */
47#define PSQL_SERVER_VERSION3(server_version) \ 47#define PSQL_SERVER_VERSION3(server_version) \
48 (server_version) / 10000, \ 48 (server_version) / 10000, (server_version) / 100 - (int)((server_version) / 10000) * 100, \
49 (server_version) / 100 - (int)((server_version) / 10000) * 100, \ 49 (server_version) - (int)((server_version) / 100) * 100
50 (server_version) - (int)((server_version) / 100) * 100
51/* return true if the given host is a UNIX domain socket */ 50/* return true if the given host is a UNIX domain socket */
52#define PSQL_IS_UNIX_DOMAIN_SOCKET(host) \ 51#define PSQL_IS_UNIX_DOMAIN_SOCKET(host) ((NULL == (host)) || ('\0' == *(host)) || ('/' == *(host)))
53 ((NULL == (host)) || ('\0' == *(host)) || ('/' == *(host)))
54/* return a 3-tuple identifying a host/port independent of the socket type */ 52/* return a 3-tuple identifying a host/port independent of the socket type */
55#define PSQL_SOCKET3(host, port) \ 53#define PSQL_SOCKET3(host, port) \
56 ((NULL == (host)) || ('\0' == *(host))) ? DEFAULT_PGSOCKET_DIR : host, \ 54 ((NULL == (host)) || ('\0' == *(host))) ? DEFAULT_PGSOCKET_DIR : host, PSQL_IS_UNIX_DOMAIN_SOCKET(host) ? "/.s.PGSQL." : ":", port
57 PSQL_IS_UNIX_DOMAIN_SOCKET (host) ? "/.s.PGSQL." : ":", \
58 port
59 55
60enum { 56enum {
61 DEFAULT_PORT = 5432, 57 DEFAULT_PORT = 5432,
@@ -63,33 +59,30 @@ enum {
63 DEFAULT_CRIT = 8 59 DEFAULT_CRIT = 8
64}; 60};
65 61
62static int process_arguments(int /*argc*/, char ** /*argv*/);
63static void print_help(void);
64static bool is_pg_logname(char * /*username*/);
65static int do_query(PGconn * /*conn*/, char * /*query*/);
66void print_usage(void);
67
68static char *pghost = NULL; /* host name of the backend server */
69static char *pgport = NULL; /* port of the backend server */
70static char *pgoptions = NULL;
71static char *pgtty = NULL;
72static char dbName[NAMEDATALEN] = DEFAULT_DB;
73static char *pguser = NULL;
74static char *pgpasswd = NULL;
75static char *pgparams = NULL;
76static double twarn = (double)DEFAULT_WARN;
77static double tcrit = (double)DEFAULT_CRIT;
78static char *pgquery = NULL;
79static char *pgqueryname = NULL;
80static char *query_warning = NULL;
81static char *query_critical = NULL;
82static thresholds *qthresholds = NULL;
83static int verbose = 0;
66 84
67
68int process_arguments (int, char **);
69int validate_arguments (void);
70void print_usage (void);
71void print_help (void);
72bool is_pg_logname (char *);
73int do_query (PGconn *, char *);
74
75char *pghost = NULL; /* host name of the backend server */
76char *pgport = NULL; /* port of the backend server */
77int default_port = DEFAULT_PORT;
78char *pgoptions = NULL;
79char *pgtty = NULL;
80char dbName[NAMEDATALEN] = DEFAULT_DB;
81char *pguser = NULL;
82char *pgpasswd = NULL;
83char *pgparams = NULL;
84double twarn = (double)DEFAULT_WARN;
85double tcrit = (double)DEFAULT_CRIT;
86char *pgquery = NULL;
87#define OPTID_QUERYNAME -1000 85#define OPTID_QUERYNAME -1000
88char *pgqueryname = NULL;
89char *query_warning = NULL;
90char *query_critical = NULL;
91thresholds *qthresholds = NULL;
92int verbose = 0;
93 86
94/****************************************************************************** 87/******************************************************************************
95 88
@@ -141,78 +134,67 @@ Please note that all tags must be lowercase to use the DocBook XML DTD.
141-@@ 134-@@
142******************************************************************************/ 135******************************************************************************/
143 136
144 137int main(int argc, char **argv) {
145 138 setlocale(LC_ALL, "");
146int 139 bindtextdomain(PACKAGE, LOCALEDIR);
147main (int argc, char **argv) 140 textdomain(PACKAGE);
148{
149 PGconn *conn;
150 char *conninfo = NULL;
151
152 struct timeval start_timeval;
153 struct timeval end_timeval;
154 double elapsed_time;
155 int status = STATE_UNKNOWN;
156 int query_status = STATE_UNKNOWN;
157 141
158 /* begin, by setting the parameters for a backend connection if the 142 /* begin, by setting the parameters for a backend connection if the
159 * parameters are null, then the system will try to use reasonable 143 * parameters are null, then the system will try to use reasonable
160 * defaults by looking up environment variables or, failing that, 144 * defaults by looking up environment variables or, failing that,
161 * using hardwired constants */ 145 * using hardwired constants */
162 146
163 pgoptions = NULL; /* special options to start up the backend server */ 147 pgoptions = NULL; /* special options to start up the backend server */
164 pgtty = NULL; /* debugging tty for the backend server */ 148 pgtty = NULL; /* debugging tty for the backend server */
165
166 setlocale (LC_ALL, "");
167 bindtextdomain (PACKAGE, LOCALEDIR);
168 textdomain (PACKAGE);
169 149
170 /* Parse extra opts if any */ 150 /* Parse extra opts if any */
171 argv=np_extra_opts (&argc, argv, progname); 151 argv = np_extra_opts(&argc, argv, progname);
172 152
173 if (process_arguments (argc, argv) == ERROR) 153 if (process_arguments(argc, argv) == ERROR)
174 usage4 (_("Could not parse arguments")); 154 usage4(_("Could not parse arguments"));
175 if (verbose > 2) 155 if (verbose > 2)
176 printf("Arguments initialized\n"); 156 printf("Arguments initialized\n");
177 157
178 /* Set signal handling and alarm */ 158 /* Set signal handling and alarm */
179 if (signal (SIGALRM, timeout_alarm_handler) == SIG_ERR) { 159 if (signal(SIGALRM, timeout_alarm_handler) == SIG_ERR) {
180 usage4 (_("Cannot catch SIGALRM")); 160 usage4(_("Cannot catch SIGALRM"));
181 } 161 }
182 alarm (timeout_interval); 162 alarm(timeout_interval);
183 163
164 char *conninfo = NULL;
184 if (pgparams) 165 if (pgparams)
185 asprintf (&conninfo, "%s ", pgparams); 166 asprintf(&conninfo, "%s ", pgparams);
186 167
187 asprintf (&conninfo, "%sdbname = '%s'", conninfo ? conninfo : "", dbName); 168 asprintf(&conninfo, "%sdbname = '%s'", conninfo ? conninfo : "", dbName);
188 if (pghost) 169 if (pghost)
189 asprintf (&conninfo, "%s host = '%s'", conninfo, pghost); 170 asprintf(&conninfo, "%s host = '%s'", conninfo, pghost);
190 if (pgport) 171 if (pgport)
191 asprintf (&conninfo, "%s port = '%s'", conninfo, pgport); 172 asprintf(&conninfo, "%s port = '%s'", conninfo, pgport);
192 if (pgoptions) 173 if (pgoptions)
193 asprintf (&conninfo, "%s options = '%s'", conninfo, pgoptions); 174 asprintf(&conninfo, "%s options = '%s'", conninfo, pgoptions);
194 /* if (pgtty) -- ignored by PQconnectdb */ 175 /* if (pgtty) -- ignored by PQconnectdb */
195 if (pguser) 176 if (pguser)
196 asprintf (&conninfo, "%s user = '%s'", conninfo, pguser); 177 asprintf(&conninfo, "%s user = '%s'", conninfo, pguser);
197 178
198 if (verbose) /* do not include password (see right below) in output */ 179 if (verbose) /* do not include password (see right below) in output */
199 printf ("Connecting to PostgreSQL using conninfo: %s%s\n", conninfo, 180 printf("Connecting to PostgreSQL using conninfo: %s%s\n", conninfo, pgpasswd ? " password = <hidden>" : "");
200 pgpasswd ? " password = <hidden>" : "");
201 181
202 if (pgpasswd) 182 if (pgpasswd)
203 asprintf (&conninfo, "%s password = '%s'", conninfo, pgpasswd); 183 asprintf(&conninfo, "%s password = '%s'", conninfo, pgpasswd);
204 184
205 /* make a connection to the database */ 185 /* make a connection to the database */
206 gettimeofday (&start_timeval, NULL); 186 struct timeval start_timeval;
207 conn = PQconnectdb (conninfo); 187 gettimeofday(&start_timeval, NULL);
208 gettimeofday (&end_timeval, NULL); 188 PGconn *conn = PQconnectdb(conninfo);
189 struct timeval end_timeval;
190 gettimeofday(&end_timeval, NULL);
209 191
210 while (start_timeval.tv_usec > end_timeval.tv_usec) { 192 while (start_timeval.tv_usec > end_timeval.tv_usec) {
211 --end_timeval.tv_sec; 193 --end_timeval.tv_sec;
212 end_timeval.tv_usec += 1000000; 194 end_timeval.tv_usec += 1000000;
213 } 195 }
214 elapsed_time = (double)(end_timeval.tv_sec - start_timeval.tv_sec) 196 double elapsed_time =
215 + (double)(end_timeval.tv_usec - start_timeval.tv_usec) / 1000000.0; 197 (double)(end_timeval.tv_sec - start_timeval.tv_sec) + (double)(end_timeval.tv_usec - start_timeval.tv_usec) / 1000000.0;
216 198
217 if (verbose) 199 if (verbose)
218 printf("Time elapsed: %f\n", elapsed_time); 200 printf("Time elapsed: %f\n", elapsed_time);
@@ -220,152 +202,139 @@ main (int argc, char **argv)
220 /* check to see that the backend connection was successfully made */ 202 /* check to see that the backend connection was successfully made */
221 if (verbose) 203 if (verbose)
222 printf("Verifying connection\n"); 204 printf("Verifying connection\n");
223 if (PQstatus (conn) == CONNECTION_BAD) { 205 if (PQstatus(conn) == CONNECTION_BAD) {
224 printf (_("CRITICAL - no connection to '%s' (%s).\n"), 206 printf(_("CRITICAL - no connection to '%s' (%s).\n"), dbName, PQerrorMessage(conn));
225 dbName, PQerrorMessage (conn)); 207 PQfinish(conn);
226 PQfinish (conn);
227 return STATE_CRITICAL; 208 return STATE_CRITICAL;
228 } 209 }
229 else if (elapsed_time > tcrit) { 210
211 int status = STATE_UNKNOWN;
212 if (elapsed_time > tcrit) {
230 status = STATE_CRITICAL; 213 status = STATE_CRITICAL;
231 } 214 } else if (elapsed_time > twarn) {
232 else if (elapsed_time > twarn) {
233 status = STATE_WARNING; 215 status = STATE_WARNING;
234 } 216 } else {
235 else {
236 status = STATE_OK; 217 status = STATE_OK;
237 } 218 }
238 219
239 if (verbose) { 220 if (verbose) {
240 char *server_host = PQhost (conn); 221 char *server_host = PQhost(conn);
241 int server_version = PQserverVersion (conn); 222 int server_version = PQserverVersion(conn);
242 223
243 printf ("Successfully connected to database %s (user %s) " 224 printf("Successfully connected to database %s (user %s) "
244 "at server %s%s%s (server version: %d.%d.%d, " 225 "at server %s%s%s (server version: %d.%d.%d, "
245 "protocol version: %d, pid: %d)\n", 226 "protocol version: %d, pid: %d)\n",
246 PQdb (conn), PQuser (conn), 227 PQdb(conn), PQuser(conn), PSQL_SOCKET3(server_host, PQport(conn)), PSQL_SERVER_VERSION3(server_version),
247 PSQL_SOCKET3 (server_host, PQport (conn)), 228 PQprotocolVersion(conn), PQbackendPID(conn));
248 PSQL_SERVER_VERSION3 (server_version),
249 PQprotocolVersion (conn), PQbackendPID (conn));
250 } 229 }
251 230
252 printf (_(" %s - database %s (%f sec.)|%s\n"), 231 printf(_(" %s - database %s (%f sec.)|%s\n"), state_text(status), dbName, elapsed_time,
253 state_text(status), dbName, elapsed_time, 232 fperfdata("time", elapsed_time, "s", !!(twarn > 0.0), twarn, !!(tcrit > 0.0), tcrit, true, 0, false, 0));
254 fperfdata("time", elapsed_time, "s",
255 !!(twarn > 0.0), twarn, !!(tcrit > 0.0), tcrit, true, 0, false,0));
256 233
234 int query_status = STATE_UNKNOWN;
257 if (pgquery) 235 if (pgquery)
258 query_status = do_query (conn, pgquery); 236 query_status = do_query(conn, pgquery);
259 237
260 if (verbose) 238 if (verbose)
261 printf("Closing connection\n"); 239 printf("Closing connection\n");
262 PQfinish (conn); 240 PQfinish(conn);
263 return (pgquery && query_status > status) ? query_status : status; 241 return (pgquery && query_status > status) ? query_status : status;
264} 242}
265 243
266
267
268/* process command-line arguments */ 244/* process command-line arguments */
269int 245int process_arguments(int argc, char **argv) {
270process_arguments (int argc, char **argv) 246 static struct option longopts[] = {{"help", no_argument, 0, 'h'},
271{ 247 {"version", no_argument, 0, 'V'},
272 int c; 248 {"timeout", required_argument, 0, 't'},
273 249 {"critical", required_argument, 0, 'c'},
274 int option = 0; 250 {"warning", required_argument, 0, 'w'},
275 static struct option longopts[] = { 251 {"hostname", required_argument, 0, 'H'},
276 {"help", no_argument, 0, 'h'}, 252 {"logname", required_argument, 0, 'l'},
277 {"version", no_argument, 0, 'V'}, 253 {"password", required_argument, 0, 'p'},
278 {"timeout", required_argument, 0, 't'}, 254 {"authorization", required_argument, 0, 'a'},
279 {"critical", required_argument, 0, 'c'}, 255 {"port", required_argument, 0, 'P'},
280 {"warning", required_argument, 0, 'w'}, 256 {"database", required_argument, 0, 'd'},
281 {"hostname", required_argument, 0, 'H'}, 257 {"option", required_argument, 0, 'o'},
282 {"logname", required_argument, 0, 'l'}, 258 {"query", required_argument, 0, 'q'},
283 {"password", required_argument, 0, 'p'}, 259 {"queryname", required_argument, 0, OPTID_QUERYNAME},
284 {"authorization", required_argument, 0, 'a'}, 260 {"query_critical", required_argument, 0, 'C'},
285 {"port", required_argument, 0, 'P'}, 261 {"query_warning", required_argument, 0, 'W'},
286 {"database", required_argument, 0, 'd'}, 262 {"verbose", no_argument, 0, 'v'},
287 {"option", required_argument, 0, 'o'}, 263 {0, 0, 0, 0}};
288 {"query", required_argument, 0, 'q'}, 264
289 {"queryname", required_argument, 0, OPTID_QUERYNAME}, 265 while (true) {
290 {"query_critical", required_argument, 0, 'C'}, 266 int option = 0;
291 {"query_warning", required_argument, 0, 'W'}, 267 int option_char = getopt_long(argc, argv, "hVt:c:w:H:P:d:l:p:a:o:q:C:W:v", longopts, &option);
292 {"verbose", no_argument, 0, 'v'}, 268
293 {0, 0, 0, 0} 269 if (option_char == EOF)
294 };
295
296 while (1) {
297 c = getopt_long (argc, argv, "hVt:c:w:H:P:d:l:p:a:o:q:C:W:v",
298 longopts, &option);
299
300 if (c == EOF)
301 break; 270 break;
302 271
303 switch (c) { 272 switch (option_char) {
304 case '?': /* usage */ 273 case '?': /* usage */
305 usage5 (); 274 usage5();
306 case 'h': /* help */ 275 case 'h': /* help */
307 print_help (); 276 print_help();
308 exit (STATE_UNKNOWN); 277 exit(STATE_UNKNOWN);
309 case 'V': /* version */ 278 case 'V': /* version */
310 print_revision (progname, NP_VERSION); 279 print_revision(progname, NP_VERSION);
311 exit (STATE_UNKNOWN); 280 exit(STATE_UNKNOWN);
312 case 't': /* timeout period */ 281 case 't': /* timeout period */
313 if (!is_integer (optarg)) 282 if (!is_integer(optarg))
314 usage2 (_("Timeout interval must be a positive integer"), optarg); 283 usage2(_("Timeout interval must be a positive integer"), optarg);
315 else 284 else
316 timeout_interval = atoi (optarg); 285 timeout_interval = atoi(optarg);
317 break; 286 break;
318 case 'c': /* critical time threshold */ 287 case 'c': /* critical time threshold */
319 if (!is_nonnegative (optarg)) 288 if (!is_nonnegative(optarg))
320 usage2 (_("Critical threshold must be a positive integer"), optarg); 289 usage2(_("Critical threshold must be a positive integer"), optarg);
321 else 290 else
322 tcrit = strtod (optarg, NULL); 291 tcrit = strtod(optarg, NULL);
323 break; 292 break;
324 case 'w': /* warning time threshold */ 293 case 'w': /* warning time threshold */
325 if (!is_nonnegative (optarg)) 294 if (!is_nonnegative(optarg))
326 usage2 (_("Warning threshold must be a positive integer"), optarg); 295 usage2(_("Warning threshold must be a positive integer"), optarg);
327 else 296 else
328 twarn = strtod (optarg, NULL); 297 twarn = strtod(optarg, NULL);
329 break; 298 break;
330 case 'C': /* critical query threshold */ 299 case 'C': /* critical query threshold */
331 query_critical = optarg; 300 query_critical = optarg;
332 break; 301 break;
333 case 'W': /* warning query threshold */ 302 case 'W': /* warning query threshold */
334 query_warning = optarg; 303 query_warning = optarg;
335 break; 304 break;
336 case 'H': /* host */ 305 case 'H': /* host */
337 if ((*optarg != '/') && (!is_host (optarg))) 306 if ((*optarg != '/') && (!is_host(optarg)))
338 usage2 (_("Invalid hostname/address"), optarg); 307 usage2(_("Invalid hostname/address"), optarg);
339 else 308 else
340 pghost = optarg; 309 pghost = optarg;
341 break; 310 break;
342 case 'P': /* port */ 311 case 'P': /* port */
343 if (!is_integer (optarg)) 312 if (!is_integer(optarg))
344 usage2 (_("Port must be a positive integer"), optarg); 313 usage2(_("Port must be a positive integer"), optarg);
345 else 314 else
346 pgport = optarg; 315 pgport = optarg;
347 break; 316 break;
348 case 'd': /* database name */ 317 case 'd': /* database name */
349 if (strlen(optarg) >= NAMEDATALEN) { 318 if (strlen(optarg) >= NAMEDATALEN) {
350 usage2 (_("Database name exceeds the maximum length"), optarg); 319 usage2(_("Database name exceeds the maximum length"), optarg);
351 } 320 }
352 snprintf(dbName, NAMEDATALEN, "%s", optarg); 321 snprintf(dbName, NAMEDATALEN, "%s", optarg);
353 break; 322 break;
354 case 'l': /* login name */ 323 case 'l': /* login name */
355 if (!is_pg_logname (optarg)) 324 if (!is_pg_logname(optarg))
356 usage2 (_("User name is not valid"), optarg); 325 usage2(_("User name is not valid"), optarg);
357 else 326 else
358 pguser = optarg; 327 pguser = optarg;
359 break; 328 break;
360 case 'p': /* authentication password */ 329 case 'p': /* authentication password */
361 case 'a': 330 case 'a':
362 pgpasswd = optarg; 331 pgpasswd = optarg;
363 break; 332 break;
364 case 'o': 333 case 'o':
365 if (pgparams) 334 if (pgparams)
366 asprintf (&pgparams, "%s %s", pgparams, optarg); 335 asprintf(&pgparams, "%s %s", pgparams, optarg);
367 else 336 else
368 asprintf (&pgparams, "%s", optarg); 337 asprintf(&pgparams, "%s", optarg);
369 break; 338 break;
370 case 'q': 339 case 'q':
371 pgquery = optarg; 340 pgquery = optarg;
@@ -379,37 +348,8 @@ process_arguments (int argc, char **argv)
379 } 348 }
380 } 349 }
381 350
382 set_thresholds (&qthresholds, query_warning, query_critical); 351 set_thresholds(&qthresholds, query_warning, query_critical);
383
384 return validate_arguments ();
385}
386
387
388/******************************************************************************
389
390@@-
391<sect3>
392<title>validate_arguments</title>
393
394<para>&PROTO_validate_arguments;</para>
395
396<para>Given a database name, this function returns true if the string
397is a valid PostgreSQL database name, and returns false if it is
398not.</para>
399 352
400<para>Valid PostgreSQL database names are less than &NAMEDATALEN;
401characters long and consist of letters, numbers, and underscores. The
402first character cannot be a number, however.</para>
403
404</sect3>
405-@@
406******************************************************************************/
407
408
409
410int
411validate_arguments ()
412{
413 return OK; 353 return OK;
414} 354}
415 355
@@ -437,10 +377,8 @@ should be added.</para>
437-@@ 377-@@
438******************************************************************************/ 378******************************************************************************/
439 379
440 380bool is_pg_logname(char *username) {
441 381 if (strlen(username) > NAMEDATALEN - 1)
442bool is_pg_logname (char *username) {
443 if (strlen (username) > NAMEDATALEN - 1)
444 return (false); 382 return (false);
445 return (true); 383 return (true);
446} 384}
@@ -453,182 +391,155 @@ bool is_pg_logname (char *username) {
453-@@ 391-@@
454******************************************************************************/ 392******************************************************************************/
455 393
456 394void print_help(void) {
457
458void
459print_help (void)
460{
461 char *myport; 395 char *myport;
462 396
463 xasprintf (&myport, "%d", DEFAULT_PORT); 397 xasprintf(&myport, "%d", DEFAULT_PORT);
464 398
465 print_revision (progname, NP_VERSION); 399 print_revision(progname, NP_VERSION);
466 400
467 printf (COPYRIGHT, copyright, email); 401 printf(COPYRIGHT, copyright, email);
468 402
469 printf (_("Test whether a PostgreSQL Database is accepting connections.")); 403 printf(_("Test whether a PostgreSQL Database is accepting connections."));
470 404
471 printf ("\n\n"); 405 printf("\n\n");
472 406
473 print_usage (); 407 print_usage();
474 408
475 printf (UT_HELP_VRSN); 409 printf(UT_HELP_VRSN);
476 printf (UT_EXTRA_OPTS); 410 printf(UT_EXTRA_OPTS);
477 411
478 printf (UT_HOST_PORT, 'P', myport); 412 printf(UT_HOST_PORT, 'P', myport);
479 413
480 printf (" %s\n", "-d, --database=STRING"); 414 printf(" %s\n", "-d, --database=STRING");
481 printf (" %s", _("Database to check ")); 415 printf(" %s", _("Database to check "));
482 printf (_("(default: %s)\n"), DEFAULT_DB); 416 printf(_("(default: %s)\n"), DEFAULT_DB);
483 printf (" %s\n", "-l, --logname = STRING"); 417 printf(" %s\n", "-l, --logname = STRING");
484 printf (" %s\n", _("Login name of user")); 418 printf(" %s\n", _("Login name of user"));
485 printf (" %s\n", "-p, --password = STRING"); 419 printf(" %s\n", "-p, --password = STRING");
486 printf (" %s\n", _("Password (BIG SECURITY ISSUE)")); 420 printf(" %s\n", _("Password (BIG SECURITY ISSUE)"));
487 printf (" %s\n", "-o, --option = STRING"); 421 printf(" %s\n", "-o, --option = STRING");
488 printf (" %s\n", _("Connection parameters (keyword = value), see below")); 422 printf(" %s\n", _("Connection parameters (keyword = value), see below"));
489 423
490 printf (UT_WARN_CRIT); 424 printf(UT_WARN_CRIT);
491 425
492 printf (UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); 426 printf(UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
493 427
494 printf (" %s\n", "-q, --query=STRING"); 428 printf(" %s\n", "-q, --query=STRING");
495 printf (" %s\n", _("SQL query to run. Only first column in first row will be read")); 429 printf(" %s\n", _("SQL query to run. Only first column in first row will be read"));
496 printf (" %s\n", "--queryname=STRING"); 430 printf(" %s\n", "--queryname=STRING");
497 printf (" %s\n", _("A name for the query, this string is used instead of the query")); 431 printf(" %s\n", _("A name for the query, this string is used instead of the query"));
498 printf (" %s\n", _("in the long output of the plugin")); 432 printf(" %s\n", _("in the long output of the plugin"));
499 printf (" %s\n", "-W, --query-warning=RANGE"); 433 printf(" %s\n", "-W, --query-warning=RANGE");
500 printf (" %s\n", _("SQL query value to result in warning status (double)")); 434 printf(" %s\n", _("SQL query value to result in warning status (double)"));
501 printf (" %s\n", "-C, --query-critical=RANGE"); 435 printf(" %s\n", "-C, --query-critical=RANGE");
502 printf (" %s\n", _("SQL query value to result in critical status (double)")); 436 printf(" %s\n", _("SQL query value to result in critical status (double)"));
503 437
504 printf (UT_VERBOSE); 438 printf(UT_VERBOSE);
505 439
506 printf ("\n"); 440 printf("\n");
507 printf (" %s\n", _("All parameters are optional.")); 441 printf(" %s\n", _("All parameters are optional."));
508 printf (" %s\n", _("This plugin tests a PostgreSQL DBMS to determine whether it is active and")); 442 printf(" %s\n", _("This plugin tests a PostgreSQL DBMS to determine whether it is active and"));
509 printf (" %s\n", _("accepting queries. In its current operation, it simply connects to the")); 443 printf(" %s\n", _("accepting queries. In its current operation, it simply connects to the"));
510 printf (" %s\n", _("specified database, and then disconnects. If no database is specified, it")); 444 printf(" %s\n", _("specified database, and then disconnects. If no database is specified, it"));
511 printf (" %s\n", _("connects to the template1 database, which is present in every functioning")); 445 printf(" %s\n", _("connects to the template1 database, which is present in every functioning"));
512 printf (" %s\n\n", _("PostgreSQL DBMS.")); 446 printf(" %s\n\n", _("PostgreSQL DBMS."));
513 447
514 printf (" %s\n", _("If a query is specified using the -q option, it will be executed after")); 448 printf(" %s\n", _("If a query is specified using the -q option, it will be executed after"));
515 printf (" %s\n", _("connecting to the server. The result from the query has to be numeric.")); 449 printf(" %s\n", _("connecting to the server. The result from the query has to be numeric."));
516 printf (" %s\n", _("Multiple SQL commands, separated by semicolon, are allowed but the result ")); 450 printf(" %s\n", _("Multiple SQL commands, separated by semicolon, are allowed but the result "));
517 printf (" %s\n", _("of the last command is taken into account only. The value of the first")); 451 printf(" %s\n", _("of the last command is taken into account only. The value of the first"));
518 printf (" %s\n", _("column in the first row is used as the check result. If a second column is")); 452 printf(" %s\n", _("column in the first row is used as the check result. If a second column is"));
519 printf (" %s\n", _("present in the result set, this is added to the plugin output with a")); 453 printf(" %s\n", _("present in the result set, this is added to the plugin output with a"));
520 printf (" %s\n", _("prefix of \"Extra Info:\". This information can be displayed in the system")); 454 printf(" %s\n", _("prefix of \"Extra Info:\". This information can be displayed in the system"));
521 printf (" %s\n\n", _("executing the plugin.")); 455 printf(" %s\n\n", _("executing the plugin."));
522 456
523 printf (" %s\n", _("See the chapter \"Monitoring Database Activity\" of the PostgreSQL manual")); 457 printf(" %s\n", _("See the chapter \"Monitoring Database Activity\" of the PostgreSQL manual"));
524 printf (" %s\n\n", _("for details about how to access internal statistics of the database server.")); 458 printf(" %s\n\n", _("for details about how to access internal statistics of the database server."));
525 459
526 printf (" %s\n", _("For a list of available connection parameters which may be used with the -o")); 460 printf(" %s\n", _("For a list of available connection parameters which may be used with the -o"));
527 printf (" %s\n", _("command line option, see the documentation for PQconnectdb() in the chapter")); 461 printf(" %s\n", _("command line option, see the documentation for PQconnectdb() in the chapter"));
528 printf (" %s\n", _("\"libpq - C Library\" of the PostgreSQL manual. For example, this may be")); 462 printf(" %s\n", _("\"libpq - C Library\" of the PostgreSQL manual. For example, this may be"));
529 printf (" %s\n", _("used to specify a service name in pg_service.conf to be used for additional")); 463 printf(" %s\n", _("used to specify a service name in pg_service.conf to be used for additional"));
530 printf (" %s\n", _("connection parameters: -o 'service=<name>' or to specify the SSL mode:")); 464 printf(" %s\n", _("connection parameters: -o 'service=<name>' or to specify the SSL mode:"));
531 printf (" %s\n\n", _("-o 'sslmode=require'.")); 465 printf(" %s\n\n", _("-o 'sslmode=require'."));
532 466
533 printf (" %s\n", _("The plugin will connect to a local postmaster if no host is specified. To")); 467 printf(" %s\n", _("The plugin will connect to a local postmaster if no host is specified. To"));
534 printf (" %s\n", _("connect to a remote host, be sure that the remote postmaster accepts TCP/IP")); 468 printf(" %s\n", _("connect to a remote host, be sure that the remote postmaster accepts TCP/IP"));
535 printf (" %s\n\n", _("connections (start the postmaster with the -i option).")); 469 printf(" %s\n\n", _("connections (start the postmaster with the -i option)."));
536 470
537 printf (" %s\n", _("Typically, the monitoring user (unless the --logname option is used) should be")); 471 printf(" %s\n", _("Typically, the monitoring user (unless the --logname option is used) should be"));
538 printf (" %s\n", _("able to connect to the database without a password. The plugin can also send")); 472 printf(" %s\n", _("able to connect to the database without a password. The plugin can also send"));
539 printf (" %s\n", _("a password, but no effort is made to obscure or encrypt the password.")); 473 printf(" %s\n", _("a password, but no effort is made to obscure or encrypt the password."));
540 474
541 printf (UT_SUPPORT); 475 printf(UT_SUPPORT);
542} 476}
543 477
544 478void print_usage(void) {
545 479 printf("%s\n", _("Usage:"));
546void 480 printf("%s [-H <host>] [-P <port>] [-c <critical time>] [-w <warning time>]\n", progname);
547print_usage (void) 481 printf(" [-t <timeout>] [-d <database>] [-l <logname>] [-p <password>]\n"
548{ 482 "[-q <query>] [-C <critical query range>] [-W <warning query range>]\n");
549 printf ("%s\n", _("Usage:"));
550 printf ("%s [-H <host>] [-P <port>] [-c <critical time>] [-w <warning time>]\n", progname);
551 printf (" [-t <timeout>] [-d <database>] [-l <logname>] [-p <password>]\n"
552 "[-q <query>] [-C <critical query range>] [-W <warning query range>]\n");
553} 483}
554 484
555int 485int do_query(PGconn *conn, char *query) {
556do_query (PGconn *conn, char *query)
557{
558 PGresult *res;
559
560 char *val_str;
561 char *extra_info;
562 double value;
563
564 char *endptr = NULL;
565
566 int my_status = STATE_UNKNOWN;
567
568 if (verbose) 486 if (verbose)
569 printf ("Executing SQL query \"%s\".\n", query); 487 printf("Executing SQL query \"%s\".\n", query);
570 res = PQexec (conn, query); 488 PGresult *res = PQexec(conn, query);
571 489
572 if (PGRES_TUPLES_OK != PQresultStatus (res)) { 490 if (PGRES_TUPLES_OK != PQresultStatus(res)) {
573 printf (_("QUERY %s - %s: %s.\n"), _("CRITICAL"), _("Error with query"), 491 printf(_("QUERY %s - %s: %s.\n"), _("CRITICAL"), _("Error with query"), PQerrorMessage(conn));
574 PQerrorMessage (conn));
575 return STATE_CRITICAL; 492 return STATE_CRITICAL;
576 } 493 }
577 494
578 if (PQntuples (res) < 1) { 495 if (PQntuples(res) < 1) {
579 printf ("QUERY %s - %s.\n", _("WARNING"), _("No rows returned")); 496 printf("QUERY %s - %s.\n", _("WARNING"), _("No rows returned"));
580 return STATE_WARNING; 497 return STATE_WARNING;
581 } 498 }
582 499
583 if (PQnfields (res) < 1) { 500 if (PQnfields(res) < 1) {
584 printf ("QUERY %s - %s.\n", _("WARNING"), _("No columns returned")); 501 printf("QUERY %s - %s.\n", _("WARNING"), _("No columns returned"));
585 return STATE_WARNING; 502 return STATE_WARNING;
586 } 503 }
587 504
588 val_str = PQgetvalue (res, 0, 0); 505 char *val_str = PQgetvalue(res, 0, 0);
589 if (! val_str) { 506 if (!val_str) {
590 printf ("QUERY %s - %s.\n", _("CRITICAL"), _("No data returned")); 507 printf("QUERY %s - %s.\n", _("CRITICAL"), _("No data returned"));
591 return STATE_CRITICAL; 508 return STATE_CRITICAL;
592 } 509 }
593 510
594 value = strtod (val_str, &endptr); 511 char *endptr = NULL;
512 double value = strtod(val_str, &endptr);
595 if (verbose) 513 if (verbose)
596 printf ("Query result: %f\n", value); 514 printf("Query result: %f\n", value);
597 515
598 if (endptr == val_str) { 516 if (endptr == val_str) {
599 printf ("QUERY %s - %s: %s\n", _("CRITICAL"), _("Is not a numeric"), val_str); 517 printf("QUERY %s - %s: %s\n", _("CRITICAL"), _("Is not a numeric"), val_str);
600 return STATE_CRITICAL; 518 return STATE_CRITICAL;
601 } 519 }
602 else if ((endptr != NULL) && (*endptr != '\0')) { 520
521 if ((endptr != NULL) && (*endptr != '\0')) {
603 if (verbose) 522 if (verbose)
604 printf ("Garbage after value: %s.\n", endptr); 523 printf("Garbage after value: %s.\n", endptr);
605 } 524 }
606 525
607 my_status = get_status (value, qthresholds); 526 int my_status = get_status(value, qthresholds);
608 printf ("QUERY %s - ", 527 printf("QUERY %s - ", (my_status == STATE_OK) ? _("OK")
609 (my_status == STATE_OK) 528 : (my_status == STATE_WARNING) ? _("WARNING")
610 ? _("OK") 529 : (my_status == STATE_CRITICAL) ? _("CRITICAL")
611 : (my_status == STATE_WARNING) 530 : _("UNKNOWN"));
612 ? _("WARNING") 531 if (pgqueryname) {
613 : (my_status == STATE_CRITICAL) 532 printf(_("%s returned %f"), pgqueryname, value);
614 ? _("CRITICAL") 533 } else {
615 : _("UNKNOWN")); 534 printf(_("'%s' returned %f"), query, value);
616 if(pgqueryname) {
617 printf (_("%s returned %f"), pgqueryname, value);
618 }
619 else {
620 printf (_("'%s' returned %f"), query, value);
621 } 535 }
622 536
623 printf ("|query=%f;%s;%s;;\n", value, 537 printf("|query=%f;%s;%s;;\n", value, query_warning ? query_warning : "", query_critical ? query_critical : "");
624 query_warning ? query_warning : "", 538 if (PQnfields(res) > 1) {
625 query_critical ? query_critical : ""); 539 char *extra_info = PQgetvalue(res, 0, 1);
626 if (PQnfields (res) > 1) {
627 extra_info = PQgetvalue (res, 0, 1);
628 if (extra_info != NULL) { 540 if (extra_info != NULL) {
629 printf ("Extra Info: %s\n", extra_info); 541 printf("Extra Info: %s\n", extra_info);
630 } 542 }
631 } 543 }
632 return my_status; 544 return my_status;
633} 545}
634
diff --git a/plugins/check_ping.c b/plugins/check_ping.c
index 6e162e6a..4aafaf41 100644
--- a/plugins/check_ping.c
+++ b/plugins/check_ping.c
@@ -1,35 +1,35 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring check_ping plugin 3 * Monitoring check_ping plugin
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 2000-2007 Monitoring Plugins Development Team 6 * Copyright (c) 2000-2024 Monitoring Plugins Development Team
7* 7 *
8* Description: 8 * Description:
9* 9 *
10* This file contains the check_ping plugin 10 * This file contains the check_ping plugin
11* 11 *
12* Use the ping program to check connection statistics for a remote host. 12 * Use the ping program to check connection statistics for a remote host.
13* 13 *
14* 14 *
15* This program is free software: you can redistribute it and/or modify 15 * This program is free software: you can redistribute it and/or modify
16* it under the terms of the GNU General Public License as published by 16 * it under the terms of the GNU General Public License as published by
17* the Free Software Foundation, either version 3 of the License, or 17 * the Free Software Foundation, either version 3 of the License, or
18* (at your option) any later version. 18 * (at your option) any later version.
19* 19 *
20* This program is distributed in the hope that it will be useful, 20 * This program is distributed in the hope that it will be useful,
21* but WITHOUT ANY WARRANTY; without even the implied warranty of 21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23* GNU General Public License for more details. 23 * GNU General Public License for more details.
24* 24 *
25* You should have received a copy of the GNU General Public License 25 * You should have received a copy of the GNU General Public License
26* along with this program. If not, see <http://www.gnu.org/licenses/>. 26 * along with this program. If not, see <http://www.gnu.org/licenses/>.
27* 27 *
28* 28 *
29*****************************************************************************/ 29 *****************************************************************************/
30 30
31const char *progname = "check_ping"; 31const char *progname = "check_ping";
32const char *copyright = "2000-2007"; 32const char *copyright = "2000-2024";
33const char *email = "devel@monitoring-plugins.org"; 33const char *email = "devel@monitoring-plugins.org";
34 34
35#include "common.h" 35#include "common.h"
@@ -39,77 +39,73 @@ const char *email = "devel@monitoring-plugins.org";
39 39
40#include <signal.h> 40#include <signal.h>
41 41
42#define WARN_DUPLICATES "DUPLICATES FOUND! " 42#define WARN_DUPLICATES "DUPLICATES FOUND! "
43#define UNKNOWN_TRIP_TIME -1.0 /* -1 seconds */ 43#define UNKNOWN_TRIP_TIME -1.0 /* -1 seconds */
44 44
45enum { 45enum {
46 UNKNOWN_PACKET_LOSS = 200, /* 200% */ 46 UNKNOWN_PACKET_LOSS = 200, /* 200% */
47 DEFAULT_MAX_PACKETS = 5 /* default no. of ICMP ECHO packets */ 47 DEFAULT_MAX_PACKETS = 5 /* default no. of ICMP ECHO packets */
48}; 48};
49 49
50int process_arguments (int, char **); 50static int process_arguments(int /*argc*/, char ** /*argv*/);
51int get_threshold (char *, float *, int *); 51static int get_threshold(char * /*arg*/, float * /*trta*/, int * /*tpl*/);
52int validate_arguments (void); 52static int validate_arguments(void);
53int run_ping (const char *cmd, const char *addr); 53static int run_ping(const char *cmd, const char *addr);
54int error_scan (char buf[MAX_INPUT_BUFFER], const char *addr); 54static int error_scan(char buf[MAX_INPUT_BUFFER], const char *addr);
55void print_usage (void); 55static void print_help(void);
56void print_help (void); 56void print_usage(void);
57 57
58bool display_html = false; 58static bool display_html = false;
59int wpl = UNKNOWN_PACKET_LOSS; 59static int wpl = UNKNOWN_PACKET_LOSS;
60int cpl = UNKNOWN_PACKET_LOSS; 60static int cpl = UNKNOWN_PACKET_LOSS;
61float wrta = UNKNOWN_TRIP_TIME; 61static float wrta = UNKNOWN_TRIP_TIME;
62float crta = UNKNOWN_TRIP_TIME; 62static float crta = UNKNOWN_TRIP_TIME;
63char **addresses = NULL; 63static char **addresses = NULL;
64int n_addresses = 0; 64static int n_addresses = 0;
65int max_addr = 1; 65static int max_addr = 1;
66int max_packets = -1; 66static int max_packets = -1;
67int verbose = 0; 67static int verbose = 0;
68 68
69float rta = UNKNOWN_TRIP_TIME; 69static float rta = UNKNOWN_TRIP_TIME;
70int pl = UNKNOWN_PACKET_LOSS; 70static int pl = UNKNOWN_PACKET_LOSS;
71 71
72char *warn_text; 72static char *warn_text;
73 73
74 74int main(int argc, char **argv) {
75
76int
77main (int argc, char **argv)
78{
79 char *cmd = NULL; 75 char *cmd = NULL;
80 char *rawcmd = NULL; 76 char *rawcmd = NULL;
81 int result = STATE_UNKNOWN; 77 int result = STATE_UNKNOWN;
82 int this_result = STATE_UNKNOWN; 78 int this_result = STATE_UNKNOWN;
83 int i; 79 int i;
84 80
85 setlocale (LC_ALL, ""); 81 setlocale(LC_ALL, "");
86 setlocale (LC_NUMERIC, "C"); 82 setlocale(LC_NUMERIC, "C");
87 bindtextdomain (PACKAGE, LOCALEDIR); 83 bindtextdomain(PACKAGE, LOCALEDIR);
88 textdomain (PACKAGE); 84 textdomain(PACKAGE);
89 85
90 addresses = malloc (sizeof(char*) * max_addr); 86 addresses = malloc(sizeof(char *) * max_addr);
91 addresses[0] = NULL; 87 addresses[0] = NULL;
92 88
93 /* Parse extra opts if any */ 89 /* Parse extra opts if any */
94 argv=np_extra_opts (&argc, argv, progname); 90 argv = np_extra_opts(&argc, argv, progname);
95 91
96 if (process_arguments (argc, argv) == ERROR) 92 if (process_arguments(argc, argv) == ERROR)
97 usage4 (_("Could not parse arguments")); 93 usage4(_("Could not parse arguments"));
98 94
99 /* Set signal handling and alarm */ 95 /* Set signal handling and alarm */
100 if (signal (SIGALRM, popen_timeout_alarm_handler) == SIG_ERR) { 96 if (signal(SIGALRM, popen_timeout_alarm_handler) == SIG_ERR) {
101 usage4 (_("Cannot catch SIGALRM")); 97 usage4(_("Cannot catch SIGALRM"));
102 } 98 }
103 99
104 /* If ./configure finds ping has timeout values, set plugin alarm slightly 100 /* If ./configure finds ping has timeout values, set plugin alarm slightly
105 * higher so that we can use response from command line ping */ 101 * higher so that we can use response from command line ping */
106#if defined(PING_PACKETS_FIRST) && defined(PING_HAS_TIMEOUT) 102#if defined(PING_PACKETS_FIRST) && defined(PING_HAS_TIMEOUT)
107 alarm (timeout_interval + 1); 103 alarm(timeout_interval + 1);
108#else 104#else
109 alarm (timeout_interval); 105 alarm(timeout_interval);
110#endif 106#endif
111 107
112 for (i = 0 ; i < n_addresses ; i++) { 108 for (i = 0; i < n_addresses; i++) {
113 109
114#ifdef PING6_COMMAND 110#ifdef PING6_COMMAND
115 if (address_family != AF_INET && is_inet6_addr(addresses[i])) 111 if (address_family != AF_INET && is_inet6_addr(addresses[i]))
@@ -120,27 +116,26 @@ main (int argc, char **argv)
120 rawcmd = strdup(PING_COMMAND); 116 rawcmd = strdup(PING_COMMAND);
121#endif 117#endif
122 118
123 /* does the host address of number of packets argument come first? */ 119 /* does the host address of number of packets argument come first? */
124#ifdef PING_PACKETS_FIRST 120#ifdef PING_PACKETS_FIRST
125# ifdef PING_HAS_TIMEOUT 121# ifdef PING_HAS_TIMEOUT
126 xasprintf (&cmd, rawcmd, timeout_interval, max_packets, addresses[i]); 122 xasprintf(&cmd, rawcmd, timeout_interval, max_packets, addresses[i]);
127# else 123# else
128 xasprintf (&cmd, rawcmd, max_packets, addresses[i]); 124 xasprintf(&cmd, rawcmd, max_packets, addresses[i]);
129# endif 125# endif
130#else 126#else
131 xasprintf (&cmd, rawcmd, addresses[i], max_packets); 127 xasprintf(&cmd, rawcmd, addresses[i], max_packets);
132#endif 128#endif
133 129
134 if (verbose >= 2) 130 if (verbose >= 2)
135 printf ("CMD: %s\n", cmd); 131 printf("CMD: %s\n", cmd);
136 132
137 /* run the command */ 133 /* run the command */
138 this_result = run_ping (cmd, addresses[i]); 134 this_result = run_ping(cmd, addresses[i]);
139 135
140 if (pl == UNKNOWN_PACKET_LOSS || rta < 0.0) { 136 if (pl == UNKNOWN_PACKET_LOSS || rta < 0.0) {
141 printf ("%s\n", cmd); 137 printf("%s\n", cmd);
142 die (STATE_UNKNOWN, 138 die(STATE_UNKNOWN, _("CRITICAL - Could not interpret output from ping command\n"));
143 _("CRITICAL - Could not interpret output from ping command\n"));
144 } 139 }
145 140
146 if (pl >= cpl || rta >= crta || rta < 0) 141 if (pl >= cpl || rta >= crta || rta < 0)
@@ -148,267 +143,241 @@ main (int argc, char **argv)
148 else if (pl >= wpl || rta >= wrta) 143 else if (pl >= wpl || rta >= wrta)
149 this_result = STATE_WARNING; 144 this_result = STATE_WARNING;
150 else if (pl >= 0 && rta >= 0) 145 else if (pl >= 0 && rta >= 0)
151 this_result = max_state (STATE_OK, this_result); 146 this_result = max_state(STATE_OK, this_result);
152 147
153 if (n_addresses > 1 && this_result != STATE_UNKNOWN) 148 if (n_addresses > 1 && this_result != STATE_UNKNOWN)
154 die (STATE_OK, "%s is alive\n", addresses[i]); 149 die(STATE_OK, "%s is alive\n", addresses[i]);
155 150
156 if (display_html == true) 151 if (display_html == true)
157 printf ("<A HREF='%s/traceroute.cgi?%s'>", CGIURL, addresses[i]); 152 printf("<A HREF='%s/traceroute.cgi?%s'>", CGIURL, addresses[i]);
158 if (pl == 100) 153 if (pl == 100)
159 printf (_("PING %s - %sPacket loss = %d%%"), state_text (this_result), warn_text, 154 printf(_("PING %s - %sPacket loss = %d%%"), state_text(this_result), warn_text, pl);
160 pl);
161 else 155 else
162 printf (_("PING %s - %sPacket loss = %d%%, RTA = %2.2f ms"), 156 printf(_("PING %s - %sPacket loss = %d%%, RTA = %2.2f ms"), state_text(this_result), warn_text, pl, rta);
163 state_text (this_result), warn_text, pl, rta);
164 if (display_html == true) 157 if (display_html == true)
165 printf ("</A>"); 158 printf("</A>");
166 159
167 /* Print performance data */ 160 /* Print performance data */
168 if (pl != 100) { 161 if (pl != 100) {
169 printf("|%s", fperfdata ("rta", (double) rta, "ms", 162 printf("|%s",
170 wrta>0?true:false, wrta, 163 fperfdata("rta", (double)rta, "ms", wrta > 0 ? true : false, wrta, crta > 0 ? true : false, crta, true, 0, false, 0));
171 crta>0?true:false, crta,
172 true, 0, false, 0));
173 } else { 164 } else {
174 printf("| rta=U;%f;%f;;", wrta, crta); 165 printf("| rta=U;%f;%f;;", wrta, crta);
175 } 166 }
176 printf(" %s\n", perfdata ("pl", (long) pl, "%", 167 printf(" %s\n", perfdata("pl", (long)pl, "%", wpl > 0 ? true : false, wpl, cpl > 0 ? true : false, cpl, true, 0, false, 0));
177 wpl>0?true:false, wpl,
178 cpl>0?true:false, cpl,
179 true, 0, false, 0));
180 168
181 if (verbose >= 2) 169 if (verbose >= 2)
182 printf ("%f:%d%% %f:%d%%\n", wrta, wpl, crta, cpl); 170 printf("%f:%d%% %f:%d%%\n", wrta, wpl, crta, cpl);
183 171
184 result = max_state (result, this_result); 172 result = max_state(result, this_result);
185 free (rawcmd); 173 free(rawcmd);
186 free (cmd); 174 free(cmd);
187 } 175 }
188 176
189 return result; 177 return result;
190} 178}
191 179
192
193
194/* process command-line arguments */ 180/* process command-line arguments */
195int 181int process_arguments(int argc, char **argv) {
196process_arguments (int argc, char **argv)
197{
198 int c = 1; 182 int c = 1;
199 char *ptr; 183 char *ptr;
200 184
201 int option = 0; 185 int option = 0;
202 static struct option longopts[] = { 186 static struct option longopts[] = {STD_LONG_OPTS,
203 STD_LONG_OPTS, 187 {"packets", required_argument, 0, 'p'},
204 {"packets", required_argument, 0, 'p'}, 188 {"nohtml", no_argument, 0, 'n'},
205 {"nohtml", no_argument, 0, 'n'}, 189 {"link", no_argument, 0, 'L'},
206 {"link", no_argument, 0, 'L'}, 190 {"use-ipv4", no_argument, 0, '4'},
207 {"use-ipv4", no_argument, 0, '4'}, 191 {"use-ipv6", no_argument, 0, '6'},
208 {"use-ipv6", no_argument, 0, '6'}, 192 {0, 0, 0, 0}};
209 {0, 0, 0, 0}
210 };
211 193
212 if (argc < 2) 194 if (argc < 2)
213 return ERROR; 195 return ERROR;
214 196
215 for (c = 1; c < argc; c++) { 197 for (c = 1; c < argc; c++) {
216 if (strcmp ("-to", argv[c]) == 0) 198 if (strcmp("-to", argv[c]) == 0)
217 strcpy (argv[c], "-t"); 199 strcpy(argv[c], "-t");
218 if (strcmp ("-nohtml", argv[c]) == 0) 200 if (strcmp("-nohtml", argv[c]) == 0)
219 strcpy (argv[c], "-n"); 201 strcpy(argv[c], "-n");
220 } 202 }
221 203
222 while (1) { 204 while (1) {
223 c = getopt_long (argc, argv, "VvhnL46t:c:w:H:p:", longopts, &option); 205 c = getopt_long(argc, argv, "VvhnL46t:c:w:H:p:", longopts, &option);
224 206
225 if (c == -1 || c == EOF) 207 if (c == -1 || c == EOF)
226 break; 208 break;
227 209
228 switch (c) { 210 switch (c) {
229 case '?': /* usage */ 211 case '?': /* usage */
230 usage5 (); 212 usage5();
231 case 'h': /* help */ 213 case 'h': /* help */
232 print_help (); 214 print_help();
233 exit (STATE_UNKNOWN); 215 exit(STATE_UNKNOWN);
234 break; 216 break;
235 case 'V': /* version */ 217 case 'V': /* version */
236 print_revision (progname, NP_VERSION); 218 print_revision(progname, NP_VERSION);
237 exit (STATE_UNKNOWN); 219 exit(STATE_UNKNOWN);
238 break; 220 break;
239 case 't': /* timeout period */ 221 case 't': /* timeout period */
240 timeout_interval = atoi (optarg); 222 timeout_interval = atoi(optarg);
241 break; 223 break;
242 case 'v': /* verbose mode */ 224 case 'v': /* verbose mode */
243 verbose++; 225 verbose++;
244 break; 226 break;
245 case '4': /* IPv4 only */ 227 case '4': /* IPv4 only */
246 address_family = AF_INET; 228 address_family = AF_INET;
247 break; 229 break;
248 case '6': /* IPv6 only */ 230 case '6': /* IPv6 only */
249#ifdef USE_IPV6 231#ifdef USE_IPV6
250 address_family = AF_INET6; 232 address_family = AF_INET6;
251#else 233#else
252 usage (_("IPv6 support not available\n")); 234 usage(_("IPv6 support not available\n"));
253#endif 235#endif
254 break; 236 break;
255 case 'H': /* hostname */ 237 case 'H': /* hostname */
256 ptr=optarg; 238 ptr = optarg;
257 while (1) { 239 while (1) {
258 n_addresses++; 240 n_addresses++;
259 if (n_addresses > max_addr) { 241 if (n_addresses > max_addr) {
260 max_addr *= 2; 242 max_addr *= 2;
261 addresses = realloc (addresses, sizeof(char*) * max_addr); 243 addresses = realloc(addresses, sizeof(char *) * max_addr);
262 if (addresses == NULL) 244 if (addresses == NULL)
263 die (STATE_UNKNOWN, _("Could not realloc() addresses\n")); 245 die(STATE_UNKNOWN, _("Could not realloc() addresses\n"));
264 } 246 }
265 addresses[n_addresses-1] = ptr; 247 addresses[n_addresses - 1] = ptr;
266 if ((ptr = index (ptr, ','))) { 248 if ((ptr = index(ptr, ','))) {
267 strcpy (ptr, ""); 249 strcpy(ptr, "");
268 ptr += sizeof(char); 250 ptr += sizeof(char);
269 } else { 251 } else {
270 break; 252 break;
271 } 253 }
272 } 254 }
273 break; 255 break;
274 case 'p': /* number of packets to send */ 256 case 'p': /* number of packets to send */
275 if (is_intnonneg (optarg)) 257 if (is_intnonneg(optarg))
276 max_packets = atoi (optarg); 258 max_packets = atoi(optarg);
277 else 259 else
278 usage2 (_("<max_packets> (%s) must be a non-negative number\n"), optarg); 260 usage2(_("<max_packets> (%s) must be a non-negative number\n"), optarg);
279 break; 261 break;
280 case 'n': /* no HTML */ 262 case 'n': /* no HTML */
281 display_html = false; 263 display_html = false;
282 break; 264 break;
283 case 'L': /* show HTML */ 265 case 'L': /* show HTML */
284 display_html = true; 266 display_html = true;
285 break; 267 break;
286 case 'c': 268 case 'c':
287 get_threshold (optarg, &crta, &cpl); 269 get_threshold(optarg, &crta, &cpl);
288 break; 270 break;
289 case 'w': 271 case 'w':
290 get_threshold (optarg, &wrta, &wpl); 272 get_threshold(optarg, &wrta, &wpl);
291 break; 273 break;
292 } 274 }
293 } 275 }
294 276
295 c = optind; 277 c = optind;
296 if (c == argc) 278 if (c == argc)
297 return validate_arguments (); 279 return validate_arguments();
298 280
299 if (addresses[0] == NULL) { 281 if (addresses[0] == NULL) {
300 if (!is_host (argv[c])) { 282 if (!is_host(argv[c])) {
301 usage2 (_("Invalid hostname/address"), argv[c]); 283 usage2(_("Invalid hostname/address"), argv[c]);
302 } else { 284 } else {
303 addresses[0] = argv[c++]; 285 addresses[0] = argv[c++];
304 n_addresses++; 286 n_addresses++;
305 if (c == argc) 287 if (c == argc)
306 return validate_arguments (); 288 return validate_arguments();
307 } 289 }
308 } 290 }
309 291
310 if (wpl == UNKNOWN_PACKET_LOSS) { 292 if (wpl == UNKNOWN_PACKET_LOSS) {
311 if (!is_intpercent (argv[c])) { 293 if (!is_intpercent(argv[c])) {
312 printf (_("<wpl> (%s) must be an integer percentage\n"), argv[c]); 294 printf(_("<wpl> (%s) must be an integer percentage\n"), argv[c]);
313 return ERROR; 295 return ERROR;
314 } else { 296 } else {
315 wpl = atoi (argv[c++]); 297 wpl = atoi(argv[c++]);
316 if (c == argc) 298 if (c == argc)
317 return validate_arguments (); 299 return validate_arguments();
318 } 300 }
319 } 301 }
320 302
321 if (cpl == UNKNOWN_PACKET_LOSS) { 303 if (cpl == UNKNOWN_PACKET_LOSS) {
322 if (!is_intpercent (argv[c])) { 304 if (!is_intpercent(argv[c])) {
323 printf (_("<cpl> (%s) must be an integer percentage\n"), argv[c]); 305 printf(_("<cpl> (%s) must be an integer percentage\n"), argv[c]);
324 return ERROR; 306 return ERROR;
325 } else { 307 } else {
326 cpl = atoi (argv[c++]); 308 cpl = atoi(argv[c++]);
327 if (c == argc) 309 if (c == argc)
328 return validate_arguments (); 310 return validate_arguments();
329 } 311 }
330 } 312 }
331 313
332 if (wrta < 0.0) { 314 if (wrta < 0.0) {
333 if (is_negative (argv[c])) { 315 if (is_negative(argv[c])) {
334 printf (_("<wrta> (%s) must be a non-negative number\n"), argv[c]); 316 printf(_("<wrta> (%s) must be a non-negative number\n"), argv[c]);
335 return ERROR; 317 return ERROR;
336 } else { 318 } else {
337 wrta = atof (argv[c++]); 319 wrta = atof(argv[c++]);
338 if (c == argc) 320 if (c == argc)
339 return validate_arguments (); 321 return validate_arguments();
340 } 322 }
341 } 323 }
342 324
343 if (crta < 0.0) { 325 if (crta < 0.0) {
344 if (is_negative (argv[c])) { 326 if (is_negative(argv[c])) {
345 printf (_("<crta> (%s) must be a non-negative number\n"), argv[c]); 327 printf(_("<crta> (%s) must be a non-negative number\n"), argv[c]);
346 return ERROR; 328 return ERROR;
347 } else { 329 } else {
348 crta = atof (argv[c++]); 330 crta = atof(argv[c++]);
349 if (c == argc) 331 if (c == argc)
350 return validate_arguments (); 332 return validate_arguments();
351 } 333 }
352 } 334 }
353 335
354 if (max_packets == -1) { 336 if (max_packets == -1) {
355 if (is_intnonneg (argv[c])) { 337 if (is_intnonneg(argv[c])) {
356 max_packets = atoi (argv[c++]); 338 max_packets = atoi(argv[c++]);
357 } else { 339 } else {
358 printf (_("<max_packets> (%s) must be a non-negative number\n"), argv[c]); 340 printf(_("<max_packets> (%s) must be a non-negative number\n"), argv[c]);
359 return ERROR; 341 return ERROR;
360 } 342 }
361 } 343 }
362 344
363 return validate_arguments (); 345 return validate_arguments();
364} 346}
365 347
366 348int get_threshold(char *arg, float *trta, int *tpl) {
367 349 if (is_intnonneg(arg) && sscanf(arg, "%f", trta) == 1)
368int
369get_threshold (char *arg, float *trta, int *tpl)
370{
371 if (is_intnonneg (arg) && sscanf (arg, "%f", trta) == 1)
372 return OK; 350 return OK;
373 else if (strpbrk (arg, ",:") && strstr (arg, "%") && sscanf (arg, "%f%*[:,]%d%%", trta, tpl) == 2) 351 else if (strpbrk(arg, ",:") && strstr(arg, "%") && sscanf(arg, "%f%*[:,]%d%%", trta, tpl) == 2)
374 return OK; 352 return OK;
375 else if (strstr (arg, "%") && sscanf (arg, "%d%%", tpl) == 1) 353 else if (strstr(arg, "%") && sscanf(arg, "%d%%", tpl) == 1)
376 return OK; 354 return OK;
377 355
378 usage2 (_("%s: Warning threshold must be integer or percentage!\n\n"), arg); 356 usage2(_("%s: Warning threshold must be integer or percentage!\n\n"), arg);
379 return STATE_UNKNOWN; 357 return STATE_UNKNOWN;
380} 358}
381 359
382 360int validate_arguments() {
383
384int
385validate_arguments ()
386{
387 float max_seconds; 361 float max_seconds;
388 int i; 362 int i;
389 363
390 if (wrta < 0.0) { 364 if (wrta < 0.0) {
391 printf (_("<wrta> was not set\n")); 365 printf(_("<wrta> was not set\n"));
392 return ERROR; 366 return ERROR;
393 } 367 } else if (crta < 0.0) {
394 else if (crta < 0.0) { 368 printf(_("<crta> was not set\n"));
395 printf (_("<crta> was not set\n"));
396 return ERROR; 369 return ERROR;
397 } 370 } else if (wpl == UNKNOWN_PACKET_LOSS) {
398 else if (wpl == UNKNOWN_PACKET_LOSS) { 371 printf(_("<wpl> was not set\n"));
399 printf (_("<wpl> was not set\n"));
400 return ERROR; 372 return ERROR;
401 } 373 } else if (cpl == UNKNOWN_PACKET_LOSS) {
402 else if (cpl == UNKNOWN_PACKET_LOSS) { 374 printf(_("<cpl> was not set\n"));
403 printf (_("<cpl> was not set\n"));
404 return ERROR; 375 return ERROR;
405 } 376 } else if (wrta > crta) {
406 else if (wrta > crta) { 377 printf(_("<wrta> (%f) cannot be larger than <crta> (%f)\n"), wrta, crta);
407 printf (_("<wrta> (%f) cannot be larger than <crta> (%f)\n"), wrta, crta);
408 return ERROR; 378 return ERROR;
409 } 379 } else if (wpl > cpl) {
410 else if (wpl > cpl) { 380 printf(_("<wpl> (%d) cannot be larger than <cpl> (%d)\n"), wpl, cpl);
411 printf (_("<wpl> (%d) cannot be larger than <cpl> (%d)\n"), wpl, cpl);
412 return ERROR; 381 return ERROR;
413 } 382 }
414 383
@@ -419,68 +388,61 @@ validate_arguments ()
419 if (max_seconds > timeout_interval) 388 if (max_seconds > timeout_interval)
420 timeout_interval = (int)max_seconds; 389 timeout_interval = (int)max_seconds;
421 390
422 for (i=0; i<n_addresses; i++) { 391 for (i = 0; i < n_addresses; i++) {
423 if (!is_host(addresses[i])) 392 if (!is_host(addresses[i]))
424 usage2 (_("Invalid hostname/address"), addresses[i]); 393 usage2(_("Invalid hostname/address"), addresses[i]);
425 } 394 }
426 395
427 if (n_addresses == 0) { 396 if (n_addresses == 0) {
428 usage (_("You must specify a server address or host name")); 397 usage(_("You must specify a server address or host name"));
429 } 398 }
430 399
431 return OK; 400 return OK;
432} 401}
433 402
434 403int run_ping(const char *cmd, const char *addr) {
435
436int
437run_ping (const char *cmd, const char *addr)
438{
439 char buf[MAX_INPUT_BUFFER]; 404 char buf[MAX_INPUT_BUFFER];
440 int result = STATE_UNKNOWN; 405 int result = STATE_UNKNOWN;
441 int match; 406 int match;
442 407
443 if ((child_process = spopen (cmd)) == NULL) 408 if ((child_process = spopen(cmd)) == NULL)
444 die (STATE_UNKNOWN, _("Could not open pipe: %s\n"), cmd); 409 die(STATE_UNKNOWN, _("Could not open pipe: %s\n"), cmd);
445 410
446 child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r"); 411 child_stderr = fdopen(child_stderr_array[fileno(child_process)], "r");
447 if (child_stderr == NULL) 412 if (child_stderr == NULL)
448 printf (_("Cannot open stderr for %s\n"), cmd); 413 printf(_("Cannot open stderr for %s\n"), cmd);
449 414
450 while (fgets (buf, MAX_INPUT_BUFFER - 1, child_process)) { 415 while (fgets(buf, MAX_INPUT_BUFFER - 1, child_process)) {
451 416
452 if (verbose >= 3) 417 if (verbose >= 3)
453 printf("Output: %s", buf); 418 printf("Output: %s", buf);
454 419
455 result = max_state (result, error_scan (buf, addr)); 420 result = max_state(result, error_scan(buf, addr));
456 421
457 /* get the percent loss statistics */ 422 /* get the percent loss statistics */
458 match = 0; 423 match = 0;
459 if((sscanf(buf,"%*d packets transmitted, %*d packets received, +%*d errors, %d%% packet loss%n",&pl,&match) && match) || 424 if ((sscanf(buf, "%*d packets transmitted, %*d packets received, +%*d errors, %d%% packet loss%n", &pl, &match) && match) ||
460 (sscanf(buf,"%*d packets transmitted, %*d packets received, +%*d duplicates, %d%% packet loss%n",&pl,&match) && match) || 425 (sscanf(buf, "%*d packets transmitted, %*d packets received, +%*d duplicates, %d%% packet loss%n", &pl, &match) && match) ||
461 (sscanf(buf,"%*d packets transmitted, %*d received, +%*d duplicates, %d%% packet loss%n",&pl,&match) && match) || 426 (sscanf(buf, "%*d packets transmitted, %*d received, +%*d duplicates, %d%% packet loss%n", &pl, &match) && match) ||
462 (sscanf(buf,"%*d packets transmitted, %*d packets received, %d%% packet loss%n",&pl,&match) && match) || 427 (sscanf(buf, "%*d packets transmitted, %*d packets received, %d%% packet loss%n", &pl, &match) && match) ||
463 (sscanf(buf,"%*d packets transmitted, %*d packets received, %d%% loss, time%n",&pl,&match) && match) || 428 (sscanf(buf, "%*d packets transmitted, %*d packets received, %d%% loss, time%n", &pl, &match) && match) ||
464 (sscanf(buf,"%*d packets transmitted, %*d received, %d%% loss, time%n",&pl,&match) && match) || 429 (sscanf(buf, "%*d packets transmitted, %*d received, %d%% loss, time%n", &pl, &match) && match) ||
465 (sscanf(buf,"%*d packets transmitted, %*d received, %d%% packet loss, time%n",&pl,&match) && match) || 430 (sscanf(buf, "%*d packets transmitted, %*d received, %d%% packet loss, time%n", &pl, &match) && match) ||
466 (sscanf(buf,"%*d packets transmitted, %*d received, +%*d errors, %d%% packet loss%n",&pl,&match) && match) || 431 (sscanf(buf, "%*d packets transmitted, %*d received, +%*d errors, %d%% packet loss%n", &pl, &match) && match) ||
467 (sscanf(buf,"%*d packets transmitted %*d received, +%*d errors, %d%% packet loss%n",&pl,&match) && match) || 432 (sscanf(buf, "%*d packets transmitted %*d received, +%*d errors, %d%% packet loss%n", &pl, &match) && match) ||
468 (sscanf(buf,"%*[^(](%d%% %*[^)])%n",&pl,&match) && match) 433 (sscanf(buf, "%*[^(](%d%% %*[^)])%n", &pl, &match) && match))
469 )
470 continue; 434 continue;
471 435
472 /* get the round trip average */ 436 /* get the round trip average */
473 else 437 else if ((sscanf(buf, "round-trip min/avg/max = %*f/%f/%*f%n", &rta, &match) && match) ||
474 if((sscanf(buf,"round-trip min/avg/max = %*f/%f/%*f%n",&rta,&match) && match) || 438 (sscanf(buf, "round-trip min/avg/max/mdev = %*f/%f/%*f/%*f%n", &rta, &match) && match) ||
475 (sscanf(buf,"round-trip min/avg/max/mdev = %*f/%f/%*f/%*f%n",&rta,&match) && match) || 439 (sscanf(buf, "round-trip min/avg/max/sdev = %*f/%f/%*f/%*f%n", &rta, &match) && match) ||
476 (sscanf(buf,"round-trip min/avg/max/sdev = %*f/%f/%*f/%*f%n",&rta,&match) && match) || 440 (sscanf(buf, "round-trip min/avg/max/stddev = %*f/%f/%*f/%*f%n", &rta, &match) && match) ||
477 (sscanf(buf,"round-trip min/avg/max/stddev = %*f/%f/%*f/%*f%n",&rta,&match) && match) || 441 (sscanf(buf, "round-trip min/avg/max/std-dev = %*f/%f/%*f/%*f%n", &rta, &match) && match) ||
478 (sscanf(buf,"round-trip min/avg/max/std-dev = %*f/%f/%*f/%*f%n",&rta,&match) && match) || 442 (sscanf(buf, "round-trip (ms) min/avg/max = %*f/%f/%*f%n", &rta, &match) && match) ||
479 (sscanf(buf,"round-trip (ms) min/avg/max = %*f/%f/%*f%n",&rta,&match) && match) || 443 (sscanf(buf, "round-trip (ms) min/avg/max/stddev = %*f/%f/%*f/%*f%n", &rta, &match) && match) ||
480 (sscanf(buf,"round-trip (ms) min/avg/max/stddev = %*f/%f/%*f/%*f%n",&rta,&match) && match) || 444 (sscanf(buf, "rtt min/avg/max/mdev = %*f/%f/%*f/%*f ms%n", &rta, &match) && match) ||
481 (sscanf(buf,"rtt min/avg/max/mdev = %*f/%f/%*f/%*f ms%n",&rta,&match) && match) || 445 (sscanf(buf, "%*[^=] = %*fms, %*[^=] = %*fms, %*[^=] = %fms%n", &rta, &match) && match))
482 (sscanf(buf, "%*[^=] = %*fms, %*[^=] = %*fms, %*[^=] = %fms%n", &rta, &match) && match)
483 )
484 continue; 446 continue;
485 } 447 }
486 448
@@ -490,16 +452,14 @@ run_ping (const char *cmd, const char *addr)
490 452
491 /* check stderr, setting at least WARNING if there is output here */ 453 /* check stderr, setting at least WARNING if there is output here */
492 /* Add warning into warn_text */ 454 /* Add warning into warn_text */
493 while (fgets (buf, MAX_INPUT_BUFFER - 1, child_stderr)) { 455 while (fgets(buf, MAX_INPUT_BUFFER - 1, child_stderr)) {
494 if ( 456 if (!strstr(buf, "WARNING - no SO_TIMESTAMP support, falling back to SIOCGSTAMP") && !strstr(buf, "Warning: time of day goes back")
495 ! strstr(buf,"WARNING - no SO_TIMESTAMP support, falling back to SIOCGSTAMP")
496 && ! strstr(buf,"Warning: time of day goes back")
497 457
498 ) { 458 ) {
499 if (verbose >= 3) { 459 if (verbose >= 3) {
500 printf("Got stderr: %s", buf); 460 printf("Got stderr: %s", buf);
501 } 461 }
502 if ((result=error_scan(buf, addr)) == STATE_OK) { 462 if ((result = error_scan(buf, addr)) == STATE_OK) {
503 result = STATE_WARNING; 463 result = STATE_WARNING;
504 if (warn_text == NULL) { 464 if (warn_text == NULL) {
505 warn_text = strdup(_("System call sent warnings to stderr ")); 465 warn_text = strdup(_("System call sent warnings to stderr "));
@@ -510,10 +470,9 @@ run_ping (const char *cmd, const char *addr)
510 } 470 }
511 } 471 }
512 472
513 (void) fclose (child_stderr); 473 (void)fclose(child_stderr);
514
515 474
516 spclose (child_process); 475 spclose(child_process);
517 476
518 if (warn_text == NULL) 477 if (warn_text == NULL)
519 warn_text = strdup(""); 478 warn_text = strdup("");
@@ -521,100 +480,86 @@ run_ping (const char *cmd, const char *addr)
521 return result; 480 return result;
522} 481}
523 482
524 483int error_scan(char buf[MAX_INPUT_BUFFER], const char *addr) {
525 484 if (strstr(buf, "Network is unreachable") || strstr(buf, "Destination Net Unreachable") || strstr(buf, "No route"))
526int 485 die(STATE_CRITICAL, _("CRITICAL - Network Unreachable (%s)\n"), addr);
527error_scan (char buf[MAX_INPUT_BUFFER], const char *addr) 486 else if (strstr(buf, "Destination Host Unreachable") || strstr(buf, "Address unreachable"))
528{ 487 die(STATE_CRITICAL, _("CRITICAL - Host Unreachable (%s)\n"), addr);
529 if (strstr (buf, "Network is unreachable") || 488 else if (strstr(buf, "Destination Port Unreachable") || strstr(buf, "Port unreachable"))
530 strstr (buf, "Destination Net Unreachable") || 489 die(STATE_CRITICAL, _("CRITICAL - Bogus ICMP: Port Unreachable (%s)\n"), addr);
531 strstr (buf, "No route") 490 else if (strstr(buf, "Destination Protocol Unreachable"))
532 ) 491 die(STATE_CRITICAL, _("CRITICAL - Bogus ICMP: Protocol Unreachable (%s)\n"), addr);
533 die (STATE_CRITICAL, _("CRITICAL - Network Unreachable (%s)\n"), addr); 492 else if (strstr(buf, "Destination Net Prohibited"))
534 else if (strstr (buf, "Destination Host Unreachable") || strstr(buf, "Address unreachable")) 493 die(STATE_CRITICAL, _("CRITICAL - Network Prohibited (%s)\n"), addr);
535 die (STATE_CRITICAL, _("CRITICAL - Host Unreachable (%s)\n"), addr); 494 else if (strstr(buf, "Destination Host Prohibited"))
536 else if (strstr (buf, "Destination Port Unreachable") || strstr(buf, "Port unreachable")) 495 die(STATE_CRITICAL, _("CRITICAL - Host Prohibited (%s)\n"), addr);
537 die (STATE_CRITICAL, _("CRITICAL - Bogus ICMP: Port Unreachable (%s)\n"), addr); 496 else if (strstr(buf, "Packet filtered") || strstr(buf, "Administratively prohibited"))
538 else if (strstr (buf, "Destination Protocol Unreachable")) 497 die(STATE_CRITICAL, _("CRITICAL - Packet Filtered (%s)\n"), addr);
539 die (STATE_CRITICAL, _("CRITICAL - Bogus ICMP: Protocol Unreachable (%s)\n"), addr); 498 else if (strstr(buf, "unknown host"))
540 else if (strstr (buf, "Destination Net Prohibited")) 499 die(STATE_CRITICAL, _("CRITICAL - Host not found (%s)\n"), addr);
541 die (STATE_CRITICAL, _("CRITICAL - Network Prohibited (%s)\n"), addr); 500 else if (strstr(buf, "Time to live exceeded") || strstr(buf, "Time exceeded"))
542 else if (strstr (buf, "Destination Host Prohibited")) 501 die(STATE_CRITICAL, _("CRITICAL - Time to live exceeded (%s)\n"), addr);
543 die (STATE_CRITICAL, _("CRITICAL - Host Prohibited (%s)\n"), addr); 502 else if (strstr(buf, "Destination unreachable: "))
544 else if (strstr (buf, "Packet filtered") || strstr(buf, "Administratively prohibited")) 503 die(STATE_CRITICAL, _("CRITICAL - Destination Unreachable (%s)\n"), addr);
545 die (STATE_CRITICAL, _("CRITICAL - Packet Filtered (%s)\n"), addr); 504
546 else if (strstr (buf, "unknown host" )) 505 if (strstr(buf, "(DUP!)") || strstr(buf, "DUPLICATES FOUND")) {
547 die (STATE_CRITICAL, _("CRITICAL - Host not found (%s)\n"), addr);
548 else if (strstr (buf, "Time to live exceeded") || strstr(buf, "Time exceeded"))
549 die (STATE_CRITICAL, _("CRITICAL - Time to live exceeded (%s)\n"), addr);
550 else if (strstr (buf, "Destination unreachable: "))
551 die (STATE_CRITICAL, _("CRITICAL - Destination Unreachable (%s)\n"), addr);
552
553 if (strstr (buf, "(DUP!)") || strstr (buf, "DUPLICATES FOUND")) {
554 if (warn_text == NULL) 506 if (warn_text == NULL)
555 warn_text = strdup (_(WARN_DUPLICATES)); 507 warn_text = strdup(_(WARN_DUPLICATES));
556 else if (! strstr (warn_text, _(WARN_DUPLICATES)) && 508 else if (!strstr(warn_text, _(WARN_DUPLICATES)) && xasprintf(&warn_text, "%s %s", warn_text, _(WARN_DUPLICATES)) == -1)
557 xasprintf (&warn_text, "%s %s", warn_text, _(WARN_DUPLICATES)) == -1) 509 die(STATE_UNKNOWN, _("Unable to realloc warn_text\n"));
558 die (STATE_UNKNOWN, _("Unable to realloc warn_text\n"));
559 return (STATE_WARNING); 510 return (STATE_WARNING);
560 } 511 }
561 512
562 return (STATE_OK); 513 return (STATE_OK);
563} 514}
564 515
516void print_help(void) {
517 print_revision(progname, NP_VERSION);
565 518
519 printf("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n");
520 printf(COPYRIGHT, copyright, email);
566 521
567void 522 printf(_("Use ping to check connection statistics for a remote host."));
568print_help (void)
569{
570 print_revision (progname, NP_VERSION);
571
572 printf ("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n");
573 printf (COPYRIGHT, copyright, email);
574
575 printf (_("Use ping to check connection statistics for a remote host."));
576 523
577 printf ("\n\n"); 524 printf("\n\n");
578 525
579 print_usage (); 526 print_usage();
580 527
581 printf (UT_HELP_VRSN); 528 printf(UT_HELP_VRSN);
582 printf (UT_EXTRA_OPTS); 529 printf(UT_EXTRA_OPTS);
583 530
584 printf (UT_IPv46); 531 printf(UT_IPv46);
585 532
586 printf (" %s\n", "-H, --hostname=HOST"); 533 printf(" %s\n", "-H, --hostname=HOST");
587 printf (" %s\n", _("host to ping")); 534 printf(" %s\n", _("host to ping"));
588 printf (" %s\n", "-w, --warning=THRESHOLD"); 535 printf(" %s\n", "-w, --warning=THRESHOLD");
589 printf (" %s\n", _("warning threshold pair")); 536 printf(" %s\n", _("warning threshold pair"));
590 printf (" %s\n", "-c, --critical=THRESHOLD"); 537 printf(" %s\n", "-c, --critical=THRESHOLD");
591 printf (" %s\n", _("critical threshold pair")); 538 printf(" %s\n", _("critical threshold pair"));
592 printf (" %s\n", "-p, --packets=INTEGER"); 539 printf(" %s\n", "-p, --packets=INTEGER");
593 printf (" %s ", _("number of ICMP ECHO packets to send")); 540 printf(" %s ", _("number of ICMP ECHO packets to send"));
594 printf (_("(Default: %d)\n"), DEFAULT_MAX_PACKETS); 541 printf(_("(Default: %d)\n"), DEFAULT_MAX_PACKETS);
595 printf (" %s\n", "-L, --link"); 542 printf(" %s\n", "-L, --link");
596 printf (" %s\n", _("show HTML in the plugin output (obsoleted by urlize)")); 543 printf(" %s\n", _("show HTML in the plugin output (obsoleted by urlize)"));
597 544
598 printf (UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); 545 printf(UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
599 546
600 printf ("\n"); 547 printf("\n");
601 printf ("%s\n", _("THRESHOLD is <rta>,<pl>% where <rta> is the round trip average travel")); 548 printf("%s\n", _("THRESHOLD is <rta>,<pl>% where <rta> is the round trip average travel"));
602 printf ("%s\n", _("time (ms) which triggers a WARNING or CRITICAL state, and <pl> is the")); 549 printf("%s\n", _("time (ms) which triggers a WARNING or CRITICAL state, and <pl> is the"));
603 printf ("%s\n", _("percentage of packet loss to trigger an alarm state.")); 550 printf("%s\n", _("percentage of packet loss to trigger an alarm state."));
604 551
605 printf ("\n"); 552 printf("\n");
606 printf ("%s\n", _("This plugin uses the ping command to probe the specified host for packet loss")); 553 printf("%s\n", _("This plugin uses the ping command to probe the specified host for packet loss"));
607 printf ("%s\n", _("(percentage) and round trip average (milliseconds). It can produce HTML output")); 554 printf("%s\n", _("(percentage) and round trip average (milliseconds). It can produce HTML output"));
608 printf ("%s\n", _("linking to a traceroute CGI contributed by Ian Cass. The CGI can be found in")); 555 printf("%s\n", _("linking to a traceroute CGI contributed by Ian Cass. The CGI can be found in"));
609 printf ("%s\n", _("the contrib area of the downloads section at http://www.nagios.org/")); 556 printf("%s\n", _("the contrib area of the downloads section at http://www.nagios.org/"));
610 557
611 printf (UT_SUPPORT); 558 printf(UT_SUPPORT);
612} 559}
613 560
614void 561void print_usage(void) {
615print_usage (void) 562 printf("%s\n", _("Usage:"));
616{ 563 printf("%s -H <host_address> -w <wrta>,<wpl>%% -c <crta>,<cpl>%%\n", progname);
617 printf ("%s\n", _("Usage:")); 564 printf(" [-p packets] [-t timeout] [-4|-6]\n");
618 printf ("%s -H <host_address> -w <wrta>,<wpl>%% -c <crta>,<cpl>%%\n", progname);
619 printf (" [-p packets] [-t timeout] [-4|-6]\n");
620} 565}
diff --git a/plugins/check_procs.c b/plugins/check_procs.c
index 1fcbd981..5777ba07 100644
--- a/plugins/check_procs.c
+++ b/plugins/check_procs.c
@@ -3,7 +3,7 @@
3* Monitoring check_procs plugin 3* Monitoring check_procs plugin
4* 4*
5* License: GPL 5* License: GPL
6* Copyright (c) 2000-2008 Monitoring Plugins Development Team 6* Copyright (c) 2000-2024 Monitoring Plugins Development Team
7* 7*
8* Description: 8* Description:
9* 9*
@@ -36,7 +36,7 @@
36 36
37const char *progname = "check_procs"; 37const char *progname = "check_procs";
38const char *program_name = "check_procs"; /* Required for coreutils libs */ 38const char *program_name = "check_procs"; /* Required for coreutils libs */
39const char *copyright = "2000-2008"; 39const char *copyright = "2000-2024";
40const char *email = "devel@monitoring-plugins.org"; 40const char *email = "devel@monitoring-plugins.org";
41 41
42#include "common.h" 42#include "common.h"
diff --git a/plugins/check_radius.c b/plugins/check_radius.c
index 6b32710a..8ed19e55 100644
--- a/plugins/check_radius.c
+++ b/plugins/check_radius.c
@@ -3,7 +3,7 @@
3* Monitoring check_radius plugin 3* Monitoring check_radius plugin
4* 4*
5* License: GPL 5* License: GPL
6* Copyright (c) 1999-2008 Monitoring Plugins Development Team 6* Copyright (c) 1999-2024 Monitoring Plugins Development Team
7* 7*
8* Description: 8* Description:
9* 9*
@@ -29,7 +29,7 @@
29*****************************************************************************/ 29*****************************************************************************/
30 30
31const char *progname = "check_radius"; 31const char *progname = "check_radius";
32const char *copyright = "2000-2008"; 32const char *copyright = "2000-2024";
33const char *email = "devel@monitoring-plugins.org"; 33const char *email = "devel@monitoring-plugins.org";
34 34
35#include "common.h" 35#include "common.h"
diff --git a/plugins/check_real.c b/plugins/check_real.c
index 15e035b6..369a88b1 100644
--- a/plugins/check_real.c
+++ b/plugins/check_real.c
@@ -1,35 +1,35 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring check_real plugin 3 * Monitoring check_real plugin
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 2000-2007 Monitoring Plugins Development Team 6 * Copyright (c) 2000-2024 Monitoring Plugins Development Team
7* 7 *
8* Description: 8 * Description:
9* 9 *
10* This file contains the check_real plugin 10 * This file contains the check_real plugin
11* 11 *
12* This plugin tests the REAL service on the specified host. 12 * This plugin tests the REAL service on the specified host.
13* 13 *
14* 14 *
15* This program is free software: you can redistribute it and/or modify 15 * This program is free software: you can redistribute it and/or modify
16* it under the terms of the GNU General Public License as published by 16 * it under the terms of the GNU General Public License as published by
17* the Free Software Foundation, either version 3 of the License, or 17 * the Free Software Foundation, either version 3 of the License, or
18* (at your option) any later version. 18 * (at your option) any later version.
19* 19 *
20* This program is distributed in the hope that it will be useful, 20 * This program is distributed in the hope that it will be useful,
21* but WITHOUT ANY WARRANTY; without even the implied warranty of 21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23* GNU General Public License for more details. 23 * GNU General Public License for more details.
24* 24 *
25* You should have received a copy of the GNU General Public License 25 * You should have received a copy of the GNU General Public License
26* along with this program. If not, see <http://www.gnu.org/licenses/>. 26 * along with this program. If not, see <http://www.gnu.org/licenses/>.
27* 27 *
28* 28 *
29*****************************************************************************/ 29 *****************************************************************************/
30 30
31const char *progname = "check_real"; 31const char *progname = "check_real";
32const char *copyright = "2000-2007"; 32const char *copyright = "2000-2024";
33const char *email = "devel@monitoring-plugins.org"; 33const char *email = "devel@monitoring-plugins.org";
34 34
35#include "common.h" 35#include "common.h"
@@ -37,121 +37,111 @@ const char *email = "devel@monitoring-plugins.org";
37#include "utils.h" 37#include "utils.h"
38 38
39enum { 39enum {
40 PORT = 554 40 PORT = 554
41}; 41};
42 42
43#define EXPECT "RTSP/1." 43#define EXPECT "RTSP/1."
44#define URL "" 44#define URL ""
45 45
46int process_arguments (int, char **); 46static int process_arguments(int, char **);
47int validate_arguments (void); 47static void print_help(void);
48void print_help (void); 48void print_usage(void);
49void print_usage (void); 49
50 50static int server_port = PORT;
51int server_port = PORT; 51static char *server_address;
52char *server_address; 52static char *host_name;
53char *host_name; 53static char *server_url = NULL;
54char *server_url = NULL; 54static char *server_expect;
55char *server_expect; 55static int warning_time = 0;
56int warning_time = 0; 56static bool check_warning_time = false;
57bool check_warning_time = false; 57static int critical_time = 0;
58int critical_time = 0; 58static bool check_critical_time = false;
59bool check_critical_time = false; 59static bool verbose = false;
60bool verbose = false; 60
61 61int main(int argc, char **argv) {
62 62 setlocale(LC_ALL, "");
63 63 bindtextdomain(PACKAGE, LOCALEDIR);
64int 64 textdomain(PACKAGE);
65main (int argc, char **argv)
66{
67 int sd;
68 int result = STATE_UNKNOWN;
69 char buffer[MAX_INPUT_BUFFER];
70 char *status_line = NULL;
71
72 setlocale (LC_ALL, "");
73 bindtextdomain (PACKAGE, LOCALEDIR);
74 textdomain (PACKAGE);
75 65
76 /* Parse extra opts if any */ 66 /* Parse extra opts if any */
77 argv=np_extra_opts (&argc, argv, progname); 67 argv = np_extra_opts(&argc, argv, progname);
78 68
79 if (process_arguments (argc, argv) == ERROR) 69 if (process_arguments(argc, argv) == ERROR)
80 usage4 (_("Could not parse arguments")); 70 usage4(_("Could not parse arguments"));
81 71
82 /* initialize alarm signal handling */ 72 /* initialize alarm signal handling */
83 signal (SIGALRM, socket_timeout_alarm_handler); 73 signal(SIGALRM, socket_timeout_alarm_handler);
84 74
85 /* set socket timeout */ 75 /* set socket timeout */
86 alarm (socket_timeout); 76 alarm(socket_timeout);
87 time (&start_time); 77 time(&start_time);
88 78
89 /* try to connect to the host at the given port number */ 79 /* try to connect to the host at the given port number */
90 if (my_tcp_connect (server_address, server_port, &sd) != STATE_OK) 80 int socket;
91 die (STATE_CRITICAL, _("Unable to connect to %s on port %d\n"), 81 if (my_tcp_connect(server_address, server_port, &socket) != STATE_OK)
92 server_address, server_port); 82 die(STATE_CRITICAL, _("Unable to connect to %s on port %d\n"), server_address, server_port);
93 83
94 /* Part I - Server Check */ 84 /* Part I - Server Check */
95 85
96 /* send the OPTIONS request */ 86 /* send the OPTIONS request */
97 sprintf (buffer, "OPTIONS rtsp://%s:%d RTSP/1.0\r\n", host_name, server_port); 87 char buffer[MAX_INPUT_BUFFER];
98 result = send (sd, buffer, strlen (buffer), 0); 88 sprintf(buffer, "OPTIONS rtsp://%s:%d RTSP/1.0\r\n", host_name, server_port);
89 int result = send(socket, buffer, strlen(buffer), 0);
99 90
100 /* send the header sync */ 91 /* send the header sync */
101 sprintf (buffer, "CSeq: 1\r\n"); 92 sprintf(buffer, "CSeq: 1\r\n");
102 result = send (sd, buffer, strlen (buffer), 0); 93 result = send(socket, buffer, strlen(buffer), 0);
103 94
104 /* send a newline so the server knows we're done with the request */ 95 /* send a newline so the server knows we're done with the request */
105 sprintf (buffer, "\r\n"); 96 sprintf(buffer, "\r\n");
106 result = send (sd, buffer, strlen (buffer), 0); 97 result = send(socket, buffer, strlen(buffer), 0);
107 98
108 /* watch for the REAL connection string */ 99 /* watch for the REAL connection string */
109 result = recv (sd, buffer, MAX_INPUT_BUFFER - 1, 0); 100 result = recv(socket, buffer, MAX_INPUT_BUFFER - 1, 0);
110 101
111 /* return a CRITICAL status if we couldn't read any data */ 102 /* return a CRITICAL status if we couldn't read any data */
112 if (result == -1) 103 if (result == -1)
113 die (STATE_CRITICAL, _("No data received from %s\n"), host_name); 104 die(STATE_CRITICAL, _("No data received from %s\n"), host_name);
114 105
106 char *status_line = NULL;
115 /* make sure we find the response we are looking for */ 107 /* make sure we find the response we are looking for */
116 if (!strstr (buffer, server_expect)) { 108 if (!strstr(buffer, server_expect)) {
117 if (server_port == PORT) 109 if (server_port == PORT)
118 printf ("%s\n", _("Invalid REAL response received from host")); 110 printf("%s\n", _("Invalid REAL response received from host"));
119 else 111 else
120 printf (_("Invalid REAL response received from host on port %d\n"), 112 printf(_("Invalid REAL response received from host on port %d\n"), server_port);
121 server_port); 113 } else {
122 }
123 else {
124 /* else we got the REAL string, so check the return code */ 114 /* else we got the REAL string, so check the return code */
125 115
126 time (&end_time); 116 time(&end_time);
127 117
128 result = STATE_OK; 118 result = STATE_OK;
129 119
130 status_line = (char *) strtok (buffer, "\n"); 120 status_line = (char *)strtok(buffer, "\n");
131 121
132 if (strstr (status_line, "200")) 122 if (strstr(status_line, "200"))
133 result = STATE_OK; 123 result = STATE_OK;
134 124
135 /* client errors result in a warning state */ 125 /* client errors result in a warning state */
136 else if (strstr (status_line, "400")) 126 else if (strstr(status_line, "400"))
137 result = STATE_WARNING; 127 result = STATE_WARNING;
138 else if (strstr (status_line, "401")) 128 else if (strstr(status_line, "401"))
139 result = STATE_WARNING; 129 result = STATE_WARNING;
140 else if (strstr (status_line, "402")) 130 else if (strstr(status_line, "402"))
141 result = STATE_WARNING; 131 result = STATE_WARNING;
142 else if (strstr (status_line, "403")) 132 else if (strstr(status_line, "403"))
143 result = STATE_WARNING; 133 result = STATE_WARNING;
144 else if (strstr (status_line, "404")) 134 else if (strstr(status_line, "404"))
145 result = STATE_WARNING; 135 result = STATE_WARNING;
146 136
147 /* server errors result in a critical state */ 137 /* server errors result in a critical state */
148 else if (strstr (status_line, "500")) 138 else if (strstr(status_line, "500"))
149 result = STATE_CRITICAL; 139 result = STATE_CRITICAL;
150 else if (strstr (status_line, "501")) 140 else if (strstr(status_line, "501"))
151 result = STATE_CRITICAL; 141 result = STATE_CRITICAL;
152 else if (strstr (status_line, "502")) 142 else if (strstr(status_line, "502"))
153 result = STATE_CRITICAL; 143 result = STATE_CRITICAL;
154 else if (strstr (status_line, "503")) 144 else if (strstr(status_line, "503"))
155 result = STATE_CRITICAL; 145 result = STATE_CRITICAL;
156 146
157 else 147 else
@@ -159,74 +149,70 @@ main (int argc, char **argv)
159 } 149 }
160 150
161 /* Part II - Check stream exists and is ok */ 151 /* Part II - Check stream exists and is ok */
162 if ((result == STATE_OK )&& (server_url != NULL) ) { 152 if ((result == STATE_OK) && (server_url != NULL)) {
163 153
164 /* Part I - Server Check */ 154 /* Part I - Server Check */
165 155
166 /* send the DESCRIBE request */ 156 /* send the DESCRIBE request */
167 sprintf (buffer, "DESCRIBE rtsp://%s:%d%s RTSP/1.0\r\n", host_name, 157 sprintf(buffer, "DESCRIBE rtsp://%s:%d%s RTSP/1.0\r\n", host_name, server_port, server_url);
168 server_port, server_url); 158 result = send(socket, buffer, strlen(buffer), 0);
169 result = send (sd, buffer, strlen (buffer), 0);
170 159
171 /* send the header sync */ 160 /* send the header sync */
172 sprintf (buffer, "CSeq: 2\r\n"); 161 sprintf(buffer, "CSeq: 2\r\n");
173 result = send (sd, buffer, strlen (buffer), 0); 162 result = send(socket, buffer, strlen(buffer), 0);
174 163
175 /* send a newline so the server knows we're done with the request */ 164 /* send a newline so the server knows we're done with the request */
176 sprintf (buffer, "\r\n"); 165 sprintf(buffer, "\r\n");
177 result = send (sd, buffer, strlen (buffer), 0); 166 result = send(socket, buffer, strlen(buffer), 0);
178 167
179 /* watch for the REAL connection string */ 168 /* watch for the REAL connection string */
180 result = recv (sd, buffer, MAX_INPUT_BUFFER - 1, 0); 169 result = recv(socket, buffer, MAX_INPUT_BUFFER - 1, 0);
181 buffer[result] = '\0'; /* null terminate received buffer */ 170 buffer[result] = '\0'; /* null terminate received buffer */
182 171
183 /* return a CRITICAL status if we couldn't read any data */ 172 /* return a CRITICAL status if we couldn't read any data */
184 if (result == -1) { 173 if (result == -1) {
185 printf (_("No data received from host\n")); 174 printf(_("No data received from host\n"));
186 result = STATE_CRITICAL; 175 result = STATE_CRITICAL;
187 } 176 } else {
188 else {
189 /* make sure we find the response we are looking for */ 177 /* make sure we find the response we are looking for */
190 if (!strstr (buffer, server_expect)) { 178 if (!strstr(buffer, server_expect)) {
191 if (server_port == PORT) 179 if (server_port == PORT)
192 printf ("%s\n", _("Invalid REAL response received from host")); 180 printf("%s\n", _("Invalid REAL response received from host"));
193 else 181 else
194 printf (_("Invalid REAL response received from host on port %d\n"), 182 printf(_("Invalid REAL response received from host on port %d\n"), server_port);
195 server_port); 183 } else {
196 }
197 else {
198 184
199 /* else we got the REAL string, so check the return code */ 185 /* else we got the REAL string, so check the return code */
200 186
201 time (&end_time); 187 time(&end_time);
202 188
203 result = STATE_OK; 189 result = STATE_OK;
204 190
205 status_line = (char *) strtok (buffer, "\n"); 191 status_line = (char *)strtok(buffer, "\n");
206 192
207 if (strstr (status_line, "200")) 193 if (strstr(status_line, "200"))
208 result = STATE_OK; 194 result = STATE_OK;
209 195
210 /* client errors result in a warning state */ 196 /* client errors result in a warning state */
211 else if (strstr (status_line, "400")) 197 else if (strstr(status_line, "400"))
212 result = STATE_WARNING; 198 result = STATE_WARNING;
213 else if (strstr (status_line, "401")) 199 else if (strstr(status_line, "401"))
214 result = STATE_WARNING; 200 result = STATE_WARNING;
215 else if (strstr (status_line, "402")) 201 else if (strstr(status_line, "402"))
216 result = STATE_WARNING; 202 result = STATE_WARNING;
217 else if (strstr (status_line, "403")) 203 else if (strstr(status_line, "403"))
218 result = STATE_WARNING; 204 result = STATE_WARNING;
219 else if (strstr (status_line, "404")) 205 else if (strstr(status_line, "404"))
220 result = STATE_WARNING; 206 result = STATE_WARNING;
221 207
222 /* server errors result in a critical state */ 208 /* server errors result in a critical state */
223 else if (strstr (status_line, "500")) 209 else if (strstr(status_line, "500"))
224 result = STATE_CRITICAL; 210 result = STATE_CRITICAL;
225 else if (strstr (status_line, "501")) 211 else if (strstr(status_line, "501"))
226 result = STATE_CRITICAL; 212 result = STATE_CRITICAL;
227 else if (strstr (status_line, "502")) 213 else if (strstr(status_line, "502"))
228 result = STATE_CRITICAL; 214 result = STATE_CRITICAL;
229 else if (strstr (status_line, "503")) 215 else if (strstr(status_line, "503"))
230 result = STATE_CRITICAL; 216 result = STATE_CRITICAL;
231 217
232 else 218 else
@@ -238,217 +224,177 @@ main (int argc, char **argv)
238 /* Return results */ 224 /* Return results */
239 if (result == STATE_OK) { 225 if (result == STATE_OK) {
240 226
241 if (check_critical_time 227 if (check_critical_time && (end_time - start_time) > critical_time)
242 && (end_time - start_time) > critical_time) result = STATE_CRITICAL; 228 result = STATE_CRITICAL;
243 else if (check_warning_time 229 else if (check_warning_time && (end_time - start_time) > warning_time)
244 && (end_time - start_time) > warning_time) result = 230 result = STATE_WARNING;
245 STATE_WARNING;
246 231
247 /* Put some HTML in here to create a dynamic link */ 232 /* Put some HTML in here to create a dynamic link */
248 printf (_("REAL %s - %d second response time\n"), 233 printf(_("REAL %s - %d second response time\n"), state_text(result), (int)(end_time - start_time));
249 state_text (result), 234 } else
250 (int) (end_time - start_time)); 235 printf("%s\n", status_line);
251 }
252 else
253 printf ("%s\n", status_line);
254 236
255 /* close the connection */ 237 /* close the connection */
256 close (sd); 238 close(socket);
257 239
258 /* reset the alarm */ 240 /* reset the alarm */
259 alarm (0); 241 alarm(0);
260 242
261 return result; 243 return result;
262} 244}
263 245
264
265
266/* process command-line arguments */ 246/* process command-line arguments */
267int 247int process_arguments(int argc, char **argv) {
268process_arguments (int argc, char **argv) 248 static struct option longopts[] = {{"hostname", required_argument, 0, 'H'}, {"IPaddress", required_argument, 0, 'I'},
269{ 249 {"expect", required_argument, 0, 'e'}, {"url", required_argument, 0, 'u'},
270 int c; 250 {"port", required_argument, 0, 'p'}, {"critical", required_argument, 0, 'c'},
271 251 {"warning", required_argument, 0, 'w'}, {"timeout", required_argument, 0, 't'},
272 int option = 0; 252 {"verbose", no_argument, 0, 'v'}, {"version", no_argument, 0, 'V'},
273 static struct option longopts[] = { 253 {"help", no_argument, 0, 'h'}, {0, 0, 0, 0}};
274 {"hostname", required_argument, 0, 'H'},
275 {"IPaddress", required_argument, 0, 'I'},
276 {"expect", required_argument, 0, 'e'},
277 {"url", required_argument, 0, 'u'},
278 {"port", required_argument, 0, 'p'},
279 {"critical", required_argument, 0, 'c'},
280 {"warning", required_argument, 0, 'w'},
281 {"timeout", required_argument, 0, 't'},
282 {"verbose", no_argument, 0, 'v'},
283 {"version", no_argument, 0, 'V'},
284 {"help", no_argument, 0, 'h'},
285 {0, 0, 0, 0}
286 };
287 254
288 if (argc < 2) 255 if (argc < 2)
289 return ERROR; 256 return ERROR;
290 257
291 for (c = 1; c < argc; c++) { 258 for (int i = 1; i < argc; i++) {
292 if (strcmp ("-to", argv[c]) == 0) 259 if (strcmp("-to", argv[i]) == 0)
293 strcpy (argv[c], "-t"); 260 strcpy(argv[i], "-t");
294 else if (strcmp ("-wt", argv[c]) == 0) 261 else if (strcmp("-wt", argv[i]) == 0)
295 strcpy (argv[c], "-w"); 262 strcpy(argv[i], "-w");
296 else if (strcmp ("-ct", argv[c]) == 0) 263 else if (strcmp("-ct", argv[i]) == 0)
297 strcpy (argv[c], "-c"); 264 strcpy(argv[i], "-c");
298 } 265 }
299 266
300 while (1) { 267 int option_char;
301 c = getopt_long (argc, argv, "+hvVI:H:e:u:p:w:c:t:", longopts, 268 while (true) {
302 &option); 269 int option = 0;
270 option_char = getopt_long(argc, argv, "+hvVI:H:e:u:p:w:c:t:", longopts, &option);
303 271
304 if (c == -1 || c == EOF) 272 if (option_char == -1 || option_char == EOF)
305 break; 273 break;
306 274
307 switch (c) { 275 switch (option_char) {
308 case 'I': /* hostname */ 276 case 'I': /* hostname */
309 case 'H': /* hostname */ 277 case 'H': /* hostname */
310 if (server_address) 278 if (server_address)
311 break; 279 break;
312 else if (is_host (optarg)) 280 else if (is_host(optarg))
313 server_address = optarg; 281 server_address = optarg;
314 else 282 else
315 usage2 (_("Invalid hostname/address"), optarg); 283 usage2(_("Invalid hostname/address"), optarg);
316 break; 284 break;
317 case 'e': /* string to expect in response header */ 285 case 'e': /* string to expect in response header */
318 server_expect = optarg; 286 server_expect = optarg;
319 break; 287 break;
320 case 'u': /* server URL */ 288 case 'u': /* server URL */
321 server_url = optarg; 289 server_url = optarg;
322 break; 290 break;
323 case 'p': /* port */ 291 case 'p': /* port */
324 if (is_intpos (optarg)) { 292 if (is_intpos(optarg)) {
325 server_port = atoi (optarg); 293 server_port = atoi(optarg);
326 } 294 } else {
327 else { 295 usage4(_("Port must be a positive integer"));
328 usage4 (_("Port must be a positive integer"));
329 } 296 }
330 break; 297 break;
331 case 'w': /* warning time threshold */ 298 case 'w': /* warning time threshold */
332 if (is_intnonneg (optarg)) { 299 if (is_intnonneg(optarg)) {
333 warning_time = atoi (optarg); 300 warning_time = atoi(optarg);
334 check_warning_time = true; 301 check_warning_time = true;
335 } 302 } else {
336 else { 303 usage4(_("Warning time must be a positive integer"));
337 usage4 (_("Warning time must be a positive integer"));
338 } 304 }
339 break; 305 break;
340 case 'c': /* critical time threshold */ 306 case 'c': /* critical time threshold */
341 if (is_intnonneg (optarg)) { 307 if (is_intnonneg(optarg)) {
342 critical_time = atoi (optarg); 308 critical_time = atoi(optarg);
343 check_critical_time = true; 309 check_critical_time = true;
344 } 310 } else {
345 else { 311 usage4(_("Critical time must be a positive integer"));
346 usage4 (_("Critical time must be a positive integer"));
347 } 312 }
348 break; 313 break;
349 case 'v': /* verbose */ 314 case 'v': /* verbose */
350 verbose = true; 315 verbose = true;
351 break; 316 break;
352 case 't': /* timeout */ 317 case 't': /* timeout */
353 if (is_intnonneg (optarg)) { 318 if (is_intnonneg(optarg)) {
354 socket_timeout = atoi (optarg); 319 socket_timeout = atoi(optarg);
355 } 320 } else {
356 else { 321 usage4(_("Timeout interval must be a positive integer"));
357 usage4 (_("Timeout interval must be a positive integer"));
358 } 322 }
359 break; 323 break;
360 case 'V': /* version */ 324 case 'V': /* version */
361 print_revision (progname, NP_VERSION); 325 print_revision(progname, NP_VERSION);
362 exit (STATE_UNKNOWN); 326 exit(STATE_UNKNOWN);
363 case 'h': /* help */ 327 case 'h': /* help */
364 print_help (); 328 print_help();
365 exit (STATE_UNKNOWN); 329 exit(STATE_UNKNOWN);
366 case '?': /* usage */ 330 case '?': /* usage */
367 usage5 (); 331 usage5();
368 } 332 }
369 } 333 }
370 334
371 c = optind; 335 option_char = optind;
372 if (server_address==NULL && argc>c) { 336 if (server_address == NULL && argc > option_char) {
373 if (is_host (argv[c])) { 337 if (is_host(argv[option_char])) {
374 server_address = argv[c++]; 338 server_address = argv[option_char++];
375 } 339 } else {
376 else { 340 usage2(_("Invalid hostname/address"), argv[option_char]);
377 usage2 (_("Invalid hostname/address"), argv[c]);
378 } 341 }
379 } 342 }
380 343
381 if (server_address==NULL) 344 if (server_address == NULL)
382 usage4 (_("You must provide a server to check")); 345 usage4(_("You must provide a server to check"));
383 346
384 if (host_name==NULL) 347 if (host_name == NULL)
385 host_name = strdup (server_address); 348 host_name = strdup(server_address);
386 349
387 if (server_expect == NULL) 350 if (server_expect == NULL)
388 server_expect = strdup(EXPECT); 351 server_expect = strdup(EXPECT);
389 352
390 return validate_arguments ();
391}
392
393
394
395int
396validate_arguments (void)
397{
398 return OK; 353 return OK;
399} 354}
400 355
401 356void print_help(void) {
402
403void
404print_help (void)
405{
406 char *myport; 357 char *myport;
407 xasprintf (&myport, "%d", PORT); 358 xasprintf(&myport, "%d", PORT);
408 359
409 print_revision (progname, NP_VERSION); 360 print_revision(progname, NP_VERSION);
410 361
411 printf ("Copyright (c) 1999 Pedro Leite <leite@cic.ua.pt>\n"); 362 printf("Copyright (c) 1999 Pedro Leite <leite@cic.ua.pt>\n");
412 printf (COPYRIGHT, copyright, email); 363 printf(COPYRIGHT, copyright, email);
413 364
414 printf ("%s\n", _("This plugin tests the REAL service on the specified host.")); 365 printf("%s\n", _("This plugin tests the REAL service on the specified host."));
415 366
416 printf ("\n\n"); 367 printf("\n\n");
417 368
418 print_usage (); 369 print_usage();
419 370
420 printf (UT_HELP_VRSN); 371 printf(UT_HELP_VRSN);
421 printf (UT_EXTRA_OPTS); 372 printf(UT_EXTRA_OPTS);
422 373
423 printf (UT_HOST_PORT, 'p', myport); 374 printf(UT_HOST_PORT, 'p', myport);
424 375
425 printf (" %s\n", "-u, --url=STRING"); 376 printf(" %s\n", "-u, --url=STRING");
426 printf (" %s\n", _("Connect to this url")); 377 printf(" %s\n", _("Connect to this url"));
427 printf (" %s\n", "-e, --expect=STRING"); 378 printf(" %s\n", "-e, --expect=STRING");
428 printf (_("String to expect in first line of server response (default: %s)\n"), 379 printf(_("String to expect in first line of server response (default: %s)\n"), EXPECT);
429 EXPECT);
430 380
431 printf (UT_WARN_CRIT); 381 printf(UT_WARN_CRIT);
432 382
433 printf (UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); 383 printf(UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
434 384
435 printf (UT_VERBOSE); 385 printf(UT_VERBOSE);
436 386
437 printf ("\n"); 387 printf("\n");
438 printf ("%s\n", _("This plugin will attempt to open an RTSP connection with the host.")); 388 printf("%s\n", _("This plugin will attempt to open an RTSP connection with the host."));
439 printf ("%s\n", _("Successful connects return STATE_OK, refusals and timeouts return")); 389 printf("%s\n", _("Successful connects return STATE_OK, refusals and timeouts return"));
440 printf ("%s\n", _("STATE_CRITICAL, other errors return STATE_UNKNOWN. Successful connects,")); 390 printf("%s\n", _("STATE_CRITICAL, other errors return STATE_UNKNOWN. Successful connects,"));
441 printf ("%s\n", _("but incorrect response messages from the host result in STATE_WARNING return")); 391 printf("%s\n", _("but incorrect response messages from the host result in STATE_WARNING return"));
442 printf ("%s\n", _("values.")); 392 printf("%s\n", _("values."));
443 393
444 printf (UT_SUPPORT); 394 printf(UT_SUPPORT);
445} 395}
446 396
447 397void print_usage(void) {
448 398 printf("%s\n", _("Usage:"));
449void 399 printf("%s -H host [-e expect] [-p port] [-w warn] [-c crit] [-t timeout] [-v]\n", progname);
450print_usage (void)
451{
452 printf ("%s\n", _("Usage:"));
453 printf ("%s -H host [-e expect] [-p port] [-w warn] [-c crit] [-t timeout] [-v]\n", progname);
454} 400}
diff --git a/plugins/check_smtp.c b/plugins/check_smtp.c
index 986c3e18..bc175287 100644
--- a/plugins/check_smtp.c
+++ b/plugins/check_smtp.c
@@ -3,7 +3,7 @@
3* Monitoring check_smtp plugin 3* Monitoring check_smtp plugin
4* 4*
5* License: GPL 5* License: GPL
6* Copyright (c) 2000-2023 Monitoring Plugins Development Team 6* Copyright (c) 2000-2024 Monitoring Plugins Development Team
7* 7*
8* Description: 8* Description:
9* 9*
@@ -29,7 +29,7 @@
29*****************************************************************************/ 29*****************************************************************************/
30 30
31const char *progname = "check_smtp"; 31const char *progname = "check_smtp";
32const char *copyright = "2000-2007"; 32const char *copyright = "2000-2024";
33const char *email = "devel@monitoring-plugins.org"; 33const char *email = "devel@monitoring-plugins.org";
34 34
35#include "common.h" 35#include "common.h"
diff --git a/plugins/check_snmp.c b/plugins/check_snmp.c
index 295aa9b5..c1d8e2dd 100644
--- a/plugins/check_snmp.c
+++ b/plugins/check_snmp.c
@@ -1,35 +1,35 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring check_snmp plugin 3 * Monitoring check_snmp plugin
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 1999-2007 Monitoring Plugins Development Team 6 * Copyright (c) 1999-2024 Monitoring Plugins Development Team
7* 7 *
8* Description: 8 * Description:
9* 9 *
10* This file contains the check_snmp plugin 10 * This file contains the check_snmp plugin
11* 11 *
12* Check status of remote machines and obtain system information via SNMP 12 * Check status of remote machines and obtain system information via SNMP
13* 13 *
14* 14 *
15* This program is free software: you can redistribute it and/or modify 15 * This program is free software: you can redistribute it and/or modify
16* it under the terms of the GNU General Public License as published by 16 * it under the terms of the GNU General Public License as published by
17* the Free Software Foundation, either version 3 of the License, or 17 * the Free Software Foundation, either version 3 of the License, or
18* (at your option) any later version. 18 * (at your option) any later version.
19* 19 *
20* This program is distributed in the hope that it will be useful, 20 * This program is distributed in the hope that it will be useful,
21* but WITHOUT ANY WARRANTY; without even the implied warranty of 21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23* GNU General Public License for more details. 23 * GNU General Public License for more details.
24* 24 *
25* You should have received a copy of the GNU General Public License 25 * You should have received a copy of the GNU General Public License
26* along with this program. If not, see <http://www.gnu.org/licenses/>. 26 * along with this program. If not, see <http://www.gnu.org/licenses/>.
27* 27 *
28* 28 *
29*****************************************************************************/ 29 *****************************************************************************/
30 30
31const char *progname = "check_snmp"; 31const char *progname = "check_snmp";
32const char *copyright = "1999-2007"; 32const char *copyright = "1999-2024";
33const char *email = "devel@monitoring-plugins.org"; 33const char *email = "devel@monitoring-plugins.org";
34 34
35#include "common.h" 35#include "common.h"
@@ -37,136 +37,143 @@ const char *email = "devel@monitoring-plugins.org";
37#include "utils.h" 37#include "utils.h"
38#include "utils_cmd.h" 38#include "utils_cmd.h"
39 39
40#define DEFAULT_COMMUNITY "public" 40#define DEFAULT_COMMUNITY "public"
41#define DEFAULT_PORT "161" 41#define DEFAULT_PORT "161"
42#define DEFAULT_MIBLIST "ALL" 42#define DEFAULT_MIBLIST "ALL"
43#define DEFAULT_PROTOCOL "1" 43#define DEFAULT_PROTOCOL "1"
44#define DEFAULT_RETRIES 5 44#define DEFAULT_RETRIES 5
45#define DEFAULT_AUTH_PROTOCOL "MD5" 45#define DEFAULT_AUTH_PROTOCOL "MD5"
46#define DEFAULT_PRIV_PROTOCOL "DES" 46#define DEFAULT_PRIV_PROTOCOL "DES"
47#define DEFAULT_DELIMITER "=" 47#define DEFAULT_DELIMITER "="
48#define DEFAULT_OUTPUT_DELIMITER " " 48#define DEFAULT_OUTPUT_DELIMITER " "
49#define DEFAULT_BUFFER_SIZE 100 49#define DEFAULT_BUFFER_SIZE 100
50 50
51#define mark(a) ((a)!=0?"*":"") 51#define mark(a) ((a) != 0 ? "*" : "")
52 52
53#define CHECK_UNDEF 0 53#define CHECK_UNDEF 0
54#define CRIT_PRESENT 1 54#define CRIT_PRESENT 1
55#define CRIT_STRING 2 55#define CRIT_STRING 2
56#define CRIT_REGEX 4 56#define CRIT_REGEX 4
57#define WARN_PRESENT 8 57#define WARN_PRESENT 8
58#define WARN_STRING 16
59#define WARN_REGEX 32
60 58
61#define OID_COUNT_STEP 8 59#define OID_COUNT_STEP 8
62 60
63/* Longopts only arguments */ 61/* Longopts only arguments */
64#define L_CALCULATE_RATE CHAR_MAX+1 62#define L_CALCULATE_RATE CHAR_MAX + 1
65#define L_RATE_MULTIPLIER CHAR_MAX+2 63#define L_RATE_MULTIPLIER CHAR_MAX + 2
66#define L_INVERT_SEARCH CHAR_MAX+3 64#define L_INVERT_SEARCH CHAR_MAX + 3
67#define L_OFFSET CHAR_MAX+4 65#define L_OFFSET CHAR_MAX + 4
68#define L_IGNORE_MIB_PARSING_ERRORS CHAR_MAX+5 66#define L_IGNORE_MIB_PARSING_ERRORS CHAR_MAX + 5
69 67
70/* Gobble to string - stop incrementing c when c[0] match one of the 68/* Gobble to string - stop incrementing c when c[0] match one of the
71 * characters in s */ 69 * characters in s */
72#define GOBBLE_TOS(c, s) while(c[0]!='\0' && strchr(s, c[0])==NULL) { c++; } 70#define GOBBLE_TOS(c, s) \
71 while (c[0] != '\0' && strchr(s, c[0]) == NULL) { \
72 c++; \
73 }
73/* Given c, keep track of backslashes (bk) and double-quotes (dq) 74/* Given c, keep track of backslashes (bk) and double-quotes (dq)
74 * from c[0] */ 75 * from c[0] */
75#define COUNT_SEQ(c, bk, dq) switch(c[0]) {\ 76#define COUNT_SEQ(c, bk, dq) \
76 case '\\': \ 77 switch (c[0]) { \
77 if (bk) bk--; \ 78 case '\\': \
78 else bk++; \ 79 if (bk) \
79 break; \ 80 bk--; \
80 case '"': \ 81 else \
81 if (!dq) { dq++; } \ 82 bk++; \
82 else if(!bk) { dq--; } \ 83 break; \
83 else { bk--; } \ 84 case '"': \
84 break; \ 85 if (!dq) { \
86 dq++; \
87 } else if (!bk) { \
88 dq--; \
89 } else { \
90 bk--; \
91 } \
92 break; \
85 } 93 }
86 94
87 95static int process_arguments(int, char **);
88 96static int validate_arguments(void);
89int process_arguments (int, char **); 97static char *thisarg(char *str);
90int validate_arguments (void); 98static char *nextarg(char *str);
91char *thisarg (char *str); 99void print_usage(void);
92char *nextarg (char *str); 100static void print_help(void);
93void print_usage (void); 101static char *multiply(char *str);
94void print_help (void);
95char *multiply (char *str);
96 102
97#include "regex.h" 103#include "regex.h"
98char regex_expect[MAX_INPUT_BUFFER] = ""; 104static char regex_expect[MAX_INPUT_BUFFER] = "";
99regex_t preg; 105static regex_t preg;
100regmatch_t pmatch[10]; 106static regmatch_t pmatch[10];
101char errbuf[MAX_INPUT_BUFFER] = ""; 107static char errbuf[MAX_INPUT_BUFFER] = "";
102char perfstr[MAX_INPUT_BUFFER] = "| "; 108static char perfstr[MAX_INPUT_BUFFER] = "| ";
103int cflags = REG_EXTENDED | REG_NOSUB | REG_NEWLINE; 109static int cflags = REG_EXTENDED | REG_NOSUB | REG_NEWLINE;
104int eflags = 0; 110static int eflags = 0;
105int errcode, excode; 111static int errcode, excode;
106 112
107char *server_address = NULL; 113static char *server_address = NULL;
108char *community = NULL; 114static char *community = NULL;
109char **contextargs = NULL; 115static char **contextargs = NULL;
110char *context = NULL; 116static char *context = NULL;
111char **authpriv = NULL; 117static char **authpriv = NULL;
112char *proto = NULL; 118static char *proto = NULL;
113char *seclevel = NULL; 119static char *seclevel = NULL;
114char *secname = NULL; 120static char *secname = NULL;
115char *authproto = NULL; 121static char *authproto = NULL;
116char *privproto = NULL; 122static char *privproto = NULL;
117char *authpasswd = NULL; 123static char *authpasswd = NULL;
118char *privpasswd = NULL; 124static char *privpasswd = NULL;
119int nulloid = STATE_UNKNOWN; 125static int nulloid = STATE_UNKNOWN;
120char **oids = NULL; 126static char **oids = NULL;
121size_t oids_size = 0; 127static size_t oids_size = 0;
122char *label; 128static char *label;
123char *units; 129static char *units;
124char *port; 130static char *port;
125char *snmpcmd; 131static char *snmpcmd;
126char string_value[MAX_INPUT_BUFFER] = ""; 132static char string_value[MAX_INPUT_BUFFER] = "";
127int invert_search=0; 133static int invert_search = 0;
128char **labels = NULL; 134static char **labels = NULL;
129char **unitv = NULL; 135static char **unitv = NULL;
130size_t nlabels = 0; 136static size_t nlabels = 0;
131size_t labels_size = OID_COUNT_STEP; 137static size_t labels_size = OID_COUNT_STEP;
132size_t nunits = 0; 138static size_t nunits = 0;
133size_t unitv_size = OID_COUNT_STEP; 139static size_t unitv_size = OID_COUNT_STEP;
134size_t numoids = 0; 140static size_t numoids = 0;
135int numauthpriv = 0; 141static int numauthpriv = 0;
136int numcontext = 0; 142static int numcontext = 0;
137int verbose = 0; 143static int verbose = 0;
138bool usesnmpgetnext = false; 144static bool usesnmpgetnext = false;
139char *warning_thresholds = NULL; 145static char *warning_thresholds = NULL;
140char *critical_thresholds = NULL; 146static char *critical_thresholds = NULL;
141thresholds **thlds; 147static thresholds **thlds;
142size_t thlds_size = OID_COUNT_STEP; 148static size_t thlds_size = OID_COUNT_STEP;
143double *response_value; 149static double *response_value;
144size_t response_size = OID_COUNT_STEP; 150static size_t response_size = OID_COUNT_STEP;
145int retries = 0; 151static int retries = 0;
146int *eval_method; 152static int *eval_method;
147size_t eval_size = OID_COUNT_STEP; 153static size_t eval_size = OID_COUNT_STEP;
148char *delimiter; 154static char *delimiter;
149char *output_delim; 155static char *output_delim;
150char *miblist = NULL; 156static char *miblist = NULL;
151bool needmibs = false; 157static bool needmibs = false;
152int calculate_rate = 0; 158static int calculate_rate = 0;
153double offset = 0.0; 159static double offset = 0.0;
154int rate_multiplier = 1; 160static int rate_multiplier = 1;
155state_data *previous_state; 161static state_data *previous_state;
156double *previous_value; 162static double *previous_value;
157size_t previous_size = OID_COUNT_STEP; 163static size_t previous_size = OID_COUNT_STEP;
158int perf_labels = 1; 164static int perf_labels = 1;
159char* ip_version = ""; 165static char *ip_version = "";
160double multiplier = 1.0; 166static double multiplier = 1.0;
161char *fmtstr = ""; 167static char *fmtstr = "";
162bool fmtstr_set = false; 168static bool fmtstr_set = false;
163char buffer[DEFAULT_BUFFER_SIZE]; 169static char buffer[DEFAULT_BUFFER_SIZE];
164bool ignore_mib_parsing_errors = false; 170static bool ignore_mib_parsing_errors = false;
165 171
166static char *fix_snmp_range(char *th) 172static char *fix_snmp_range(char *th) {
167{ 173 double left;
168 double left, right; 174 double right;
169 char *colon, *ret; 175 char *colon;
176 char *ret;
170 177
171 if ((colon = strchr(th, ':')) == NULL || *(colon + 1) == '\0') 178 if ((colon = strchr(th, ':')) == NULL || *(colon + 1) == '\0')
172 return th; 179 return th;
@@ -184,12 +191,12 @@ static char *fix_snmp_range(char *th)
184 return ret; 191 return ret;
185} 192}
186 193
187int 194int main(int argc, char **argv) {
188main (int argc, char **argv) 195 int len;
189{ 196 int total_oids;
190 int len, total_oids;
191 size_t line; 197 size_t line;
192 unsigned int bk_count = 0, dq_count = 0; 198 unsigned int bk_count = 0;
199 unsigned int dq_count = 0;
193 int iresult = STATE_UNKNOWN; 200 int iresult = STATE_UNKNOWN;
194 int result = STATE_UNKNOWN; 201 int result = STATE_UNKNOWN;
195 int return_code = 0; 202 int return_code = 0;
@@ -202,80 +209,83 @@ main (int argc, char **argv)
202 char *outbuff; 209 char *outbuff;
203 char *ptr = NULL; 210 char *ptr = NULL;
204 char *show = NULL; 211 char *show = NULL;
205 char *th_warn=NULL; 212 char *th_warn = NULL;
206 char *th_crit=NULL; 213 char *th_crit = NULL;
207 char type[8] = ""; 214 char type[8] = "";
208 output chld_out, chld_err; 215 output chld_out;
209 char *previous_string=NULL; 216 output chld_err;
210 char *ap=NULL; 217 char *previous_string = NULL;
211 char *state_string=NULL; 218 char *ap = NULL;
212 size_t response_length, current_length, string_length; 219 char *state_string = NULL;
213 char *temp_string=NULL; 220 size_t response_length;
214 char *quote_string=NULL; 221 size_t current_length;
222 size_t string_length;
223 char *temp_string = NULL;
224 char *quote_string = NULL;
215 time_t current_time; 225 time_t current_time;
216 double temp_double; 226 double temp_double;
217 time_t duration; 227 time_t duration;
218 char *conv = "12345678"; 228 char *conv = "12345678";
219 int is_counter=0; 229 int is_counter = 0;
220 230
221 setlocale (LC_ALL, ""); 231 setlocale(LC_ALL, "");
222 bindtextdomain (PACKAGE, LOCALEDIR); 232 bindtextdomain(PACKAGE, LOCALEDIR);
223 textdomain (PACKAGE); 233 textdomain(PACKAGE);
224 234
225 labels = malloc (labels_size * sizeof(*labels)); 235 labels = malloc(labels_size * sizeof(*labels));
226 unitv = malloc (unitv_size * sizeof(*unitv)); 236 unitv = malloc(unitv_size * sizeof(*unitv));
227 thlds = malloc (thlds_size * sizeof(*thlds)); 237 thlds = malloc(thlds_size * sizeof(*thlds));
228 response_value = malloc (response_size * sizeof(*response_value)); 238 response_value = malloc(response_size * sizeof(*response_value));
229 previous_value = malloc (previous_size * sizeof(*previous_value)); 239 previous_value = malloc(previous_size * sizeof(*previous_value));
230 eval_method = calloc (eval_size, sizeof(*eval_method)); 240 eval_method = calloc(eval_size, sizeof(*eval_method));
231 oids = calloc(oids_size, sizeof (char *)); 241 oids = calloc(oids_size, sizeof(char *));
232 242
233 label = strdup ("SNMP"); 243 label = strdup("SNMP");
234 units = strdup (""); 244 units = strdup("");
235 port = strdup (DEFAULT_PORT); 245 port = strdup(DEFAULT_PORT);
236 outbuff = strdup (""); 246 outbuff = strdup("");
237 delimiter = strdup (" = "); 247 delimiter = strdup(" = ");
238 output_delim = strdup (DEFAULT_OUTPUT_DELIMITER); 248 output_delim = strdup(DEFAULT_OUTPUT_DELIMITER);
239 timeout_interval = DEFAULT_SOCKET_TIMEOUT; 249 timeout_interval = DEFAULT_SOCKET_TIMEOUT;
240 retries = DEFAULT_RETRIES; 250 retries = DEFAULT_RETRIES;
241 251
242 np_init( (char *) progname, argc, argv ); 252 np_init((char *)progname, argc, argv);
243 253
244 /* Parse extra opts if any */ 254 /* Parse extra opts if any */
245 argv=np_extra_opts (&argc, argv, progname); 255 argv = np_extra_opts(&argc, argv, progname);
246 256
247 np_set_args(argc, argv); 257 np_set_args(argc, argv);
248 258
249 time(&current_time); 259 time(&current_time);
250 260
251 if (process_arguments (argc, argv) == ERROR) 261 if (process_arguments(argc, argv) == ERROR)
252 usage4 (_("Could not parse arguments")); 262 usage4(_("Could not parse arguments"));
253 263
254 if(calculate_rate) { 264 if (calculate_rate) {
255 if (!strcmp(label, "SNMP")) 265 if (!strcmp(label, "SNMP"))
256 label = strdup("SNMP RATE"); 266 label = strdup("SNMP RATE");
257 267
258 size_t i = 0; 268 size_t i = 0;
259 269
260 previous_state = np_state_read(); 270 previous_state = np_state_read();
261 if(previous_state!=NULL) { 271 if (previous_state != NULL) {
262 /* Split colon separated values */ 272 /* Split colon separated values */
263 previous_string = strdup((char *) previous_state->data); 273 previous_string = strdup((char *)previous_state->data);
264 while((ap = strsep(&previous_string, ":")) != NULL) { 274 while ((ap = strsep(&previous_string, ":")) != NULL) {
265 if(verbose>2) 275 if (verbose > 2)
266 printf("State for %zd=%s\n", i, ap); 276 printf("State for %zd=%s\n", i, ap);
267 while (i >= previous_size) { 277 while (i >= previous_size) {
268 previous_size += OID_COUNT_STEP; 278 previous_size += OID_COUNT_STEP;
269 previous_value = realloc(previous_value, previous_size * sizeof(*previous_value)); 279 previous_value = realloc(previous_value, previous_size * sizeof(*previous_value));
270 } 280 }
271 previous_value[i++]=strtod(ap,NULL); 281 previous_value[i++] = strtod(ap, NULL);
272 } 282 }
273 } 283 }
274 } 284 }
275 285
276 /* Populate the thresholds */ 286 /* Populate the thresholds */
277 th_warn=warning_thresholds; 287 th_warn = warning_thresholds;
278 th_crit=critical_thresholds; 288 th_crit = critical_thresholds;
279 for (size_t i = 0; i < numoids; i++) { 289 for (size_t i = 0; i < numoids; i++) {
280 char *w = th_warn ? strndup(th_warn, strcspn(th_warn, ",")) : NULL; 290 char *w = th_warn ? strndup(th_warn, strcspn(th_warn, ",")) : NULL;
281 char *c = th_crit ? strndup(th_crit, strcspn(th_crit, ",")) : NULL; 291 char *c = th_crit ? strndup(th_crit, strcspn(th_crit, ",")) : NULL;
@@ -289,53 +299,52 @@ main (int argc, char **argv)
289 } 299 }
290 300
291 /* Skip empty thresholds, while avoiding segfault */ 301 /* Skip empty thresholds, while avoiding segfault */
292 set_thresholds(&thlds[i], 302 set_thresholds(&thlds[i], w ? strpbrk(w, NP_THRESHOLDS_CHARS) : NULL, c ? strpbrk(c, NP_THRESHOLDS_CHARS) : NULL);
293 w ? strpbrk(w, NP_THRESHOLDS_CHARS) : NULL,
294 c ? strpbrk(c, NP_THRESHOLDS_CHARS) : NULL);
295 if (w) { 303 if (w) {
296 th_warn=strchr(th_warn, ','); 304 th_warn = strchr(th_warn, ',');
297 if (th_warn) th_warn++; 305 if (th_warn)
306 th_warn++;
298 free(w); 307 free(w);
299 } 308 }
300 if (c) { 309 if (c) {
301 th_crit=strchr(th_crit, ','); 310 th_crit = strchr(th_crit, ',');
302 if (th_crit) th_crit++; 311 if (th_crit)
312 th_crit++;
303 free(c); 313 free(c);
304 } 314 }
305 } 315 }
306 316
307 /* Create the command array to execute */ 317 /* Create the command array to execute */
308 if(usesnmpgetnext) { 318 if (usesnmpgetnext) {
309 snmpcmd = strdup (PATH_TO_SNMPGETNEXT); 319 snmpcmd = strdup(PATH_TO_SNMPGETNEXT);
310 }else{ 320 } else {
311 snmpcmd = strdup (PATH_TO_SNMPGET); 321 snmpcmd = strdup(PATH_TO_SNMPGET);
312 } 322 }
313 323
314 /* 10 arguments to pass before context and authpriv options + 1 for host and numoids. Add one for terminating NULL */ 324 /* 10 arguments to pass before context and authpriv options + 1 for host and numoids. Add one for terminating NULL */
315 325
316 unsigned index = 0; 326 unsigned index = 0;
317 command_line = calloc (11 + numcontext + numauthpriv + 1 + numoids + 1, sizeof (char *)); 327 command_line = calloc(11 + numcontext + numauthpriv + 1 + numoids + 1, sizeof(char *));
318 328
319 command_line[index++] = snmpcmd; 329 command_line[index++] = snmpcmd;
320 command_line[index++] = strdup ("-Le"); 330 command_line[index++] = strdup("-Le");
321 command_line[index++] = strdup ("-t"); 331 command_line[index++] = strdup("-t");
322 xasprintf (&command_line[index++], "%d", timeout_interval); 332 xasprintf(&command_line[index++], "%d", timeout_interval);
323 command_line[index++] = strdup ("-r"); 333 command_line[index++] = strdup("-r");
324 xasprintf (&command_line[index++], "%d", retries); 334 xasprintf(&command_line[index++], "%d", retries);
325 command_line[index++] = strdup ("-m"); 335 command_line[index++] = strdup("-m");
326 command_line[index++] = strdup (miblist); 336 command_line[index++] = strdup(miblist);
327 command_line[index++] = "-v"; 337 command_line[index++] = "-v";
328 command_line[index++] = strdup (proto); 338 command_line[index++] = strdup(proto);
329 339
330 xasprintf(&cl_hidden_auth, "%s -Le -t %d -r %d -m %s -v %s", 340 xasprintf(&cl_hidden_auth, "%s -Le -t %d -r %d -m %s -v %s", snmpcmd, timeout_interval, retries, strlen(miblist) ? miblist : "''",
331 snmpcmd, timeout_interval, retries, strlen(miblist) ? miblist : "''", proto); 341 proto);
332 342
333 if (ignore_mib_parsing_errors) { 343 if (ignore_mib_parsing_errors) {
334 command_line[index++] = "-Pe"; 344 command_line[index++] = "-Pe";
335 xasprintf(&cl_hidden_auth, "%s -Pe", cl_hidden_auth); 345 xasprintf(&cl_hidden_auth, "%s -Pe", cl_hidden_auth);
336 } 346 }
337 347
338
339 for (int i = 0; i < numcontext; i++) { 348 for (int i = 0; i < numcontext; i++) {
340 command_line[index++] = contextargs[i]; 349 command_line[index++] = contextargs[i];
341 } 350 }
@@ -344,12 +353,9 @@ main (int argc, char **argv)
344 command_line[index++] = authpriv[i]; 353 command_line[index++] = authpriv[i];
345 } 354 }
346 355
347 xasprintf (&command_line[index++], "%s:%s", server_address, port); 356 xasprintf(&command_line[index++], "%s:%s", server_address, port);
348 357
349 xasprintf(&cl_hidden_auth, "%s [context] [authpriv] %s:%s", 358 xasprintf(&cl_hidden_auth, "%s [context] [authpriv] %s:%s", cl_hidden_auth, server_address, port);
350 cl_hidden_auth,
351 server_address,
352 port);
353 359
354 for (size_t i = 0; i < numoids; i++) { 360 for (size_t i = 0; i < numoids; i++) {
355 command_line[index++] = oids[i]; 361 command_line[index++] = oids[i];
@@ -359,17 +365,17 @@ main (int argc, char **argv)
359 command_line[index++] = NULL; 365 command_line[index++] = NULL;
360 366
361 if (verbose) { 367 if (verbose) {
362 printf ("%s\n", cl_hidden_auth); 368 printf("%s\n", cl_hidden_auth);
363 } 369 }
364 370
365 /* Set signal handling and alarm */ 371 /* Set signal handling and alarm */
366 if (signal (SIGALRM, runcmd_timeout_alarm_handler) == SIG_ERR) { 372 if (signal(SIGALRM, runcmd_timeout_alarm_handler) == SIG_ERR) {
367 usage4 (_("Cannot catch SIGALRM")); 373 usage4(_("Cannot catch SIGALRM"));
368 } 374 }
369 alarm(timeout_interval * retries + 5); 375 alarm(timeout_interval * retries + 5);
370 376
371 /* Run the command */ 377 /* Run the command */
372 return_code = cmd_run_array (command_line, &chld_out, &chld_err, 0); 378 return_code = cmd_run_array(command_line, &chld_out, &chld_err, 0);
373 379
374 /* disable alarm again */ 380 /* disable alarm again */
375 alarm(0); 381 alarm(0);
@@ -379,80 +385,74 @@ main (int argc, char **argv)
379 Do this way so that if there is stderr, will get added to output, which helps problem diagnosis 385 Do this way so that if there is stderr, will get added to output, which helps problem diagnosis
380 */ 386 */
381 if (return_code != 0) 387 if (return_code != 0)
382 external_error=1; 388 external_error = 1;
383 if (chld_out.lines == 0) 389 if (chld_out.lines == 0)
384 external_error=1; 390 external_error = 1;
385 if (external_error) { 391 if (external_error) {
386 if (chld_err.lines > 0) { 392 if (chld_err.lines > 0) {
387 printf (_("External command error: %s\n"), chld_err.line[0]); 393 printf(_("External command error: %s\n"), chld_err.line[0]);
388 for (size_t i = 1; i < chld_err.lines; i++) { 394 for (size_t i = 1; i < chld_err.lines; i++) {
389 printf ("%s\n", chld_err.line[i]); 395 printf("%s\n", chld_err.line[i]);
390 } 396 }
391 } else { 397 } else {
392 printf(_("External command error with no output (return code: %d)\n"), return_code); 398 printf(_("External command error with no output (return code: %d)\n"), return_code);
393 } 399 }
394 exit (STATE_UNKNOWN); 400 exit(STATE_UNKNOWN);
395 } 401 }
396 402
397 if (verbose) { 403 if (verbose) {
398 for (size_t i = 0; i < chld_out.lines; i++) { 404 for (size_t i = 0; i < chld_out.lines; i++) {
399 printf ("%s\n", chld_out.line[i]); 405 printf("%s\n", chld_out.line[i]);
400 } 406 }
401 } 407 }
402 408
403 line = 0; 409 line = 0;
404 total_oids = 0; 410 total_oids = 0;
405 for (size_t i = 0; line < chld_out.lines && i < numoids ; line++, i++, total_oids++) { 411 for (size_t i = 0; line < chld_out.lines && i < numoids; line++, i++, total_oids++) {
406 if(calculate_rate) 412 if (calculate_rate)
407 conv = "%.10g"; 413 conv = "%.10g";
408 else 414 else
409 conv = "%.0f"; 415 conv = "%.0f";
410 416
411 ptr = chld_out.line[line]; 417 ptr = chld_out.line[line];
412 oidname = strpcpy (oidname, ptr, delimiter); 418 oidname = strpcpy(oidname, ptr, delimiter);
413 response = strstr (ptr, delimiter); 419 response = strstr(ptr, delimiter);
414 if (response == NULL) 420 if (response == NULL)
415 break; 421 break;
416 422
417 if (verbose > 2) { 423 if (verbose > 2) {
418 printf("Processing oid %zi (line %zi)\n oidname: %s\n response: %s\n", i+1, line+1, oidname, response); 424 printf("Processing oid %zi (line %zi)\n oidname: %s\n response: %s\n", i + 1, line + 1, oidname, response);
419 } 425 }
420 426
421 /* Clean up type array - Sol10 does not necessarily zero it out */ 427 /* Clean up type array - Sol10 does not necessarily zero it out */
422 bzero(type, sizeof(type)); 428 bzero(type, sizeof(type));
423 429
424 is_counter=0; 430 is_counter = 0;
425 /* We strip out the datatype indicator for PHBs */ 431 /* We strip out the datatype indicator for PHBs */
426 if (strstr (response, "Gauge: ")) { 432 if (strstr(response, "Gauge: ")) {
427 show = multiply (strstr (response, "Gauge: ") + 7); 433 show = multiply(strstr(response, "Gauge: ") + 7);
428 } 434 } else if (strstr(response, "Gauge32: ")) {
429 else if (strstr (response, "Gauge32: ")) { 435 show = multiply(strstr(response, "Gauge32: ") + 9);
430 show = multiply (strstr (response, "Gauge32: ") + 9); 436 } else if (strstr(response, "Counter32: ")) {
431 } 437 show = strstr(response, "Counter32: ") + 11;
432 else if (strstr (response, "Counter32: ")) { 438 is_counter = 1;
433 show = strstr (response, "Counter32: ") + 11; 439 if (!calculate_rate)
434 is_counter=1;
435 if(!calculate_rate)
436 strcpy(type, "c"); 440 strcpy(type, "c");
437 } 441 } else if (strstr(response, "Counter64: ")) {
438 else if (strstr (response, "Counter64: ")) { 442 show = strstr(response, "Counter64: ") + 11;
439 show = strstr (response, "Counter64: ") + 11; 443 is_counter = 1;
440 is_counter=1; 444 if (!calculate_rate)
441 if(!calculate_rate)
442 strcpy(type, "c"); 445 strcpy(type, "c");
443 } 446 } else if (strstr(response, "INTEGER: ")) {
444 else if (strstr (response, "INTEGER: ")) { 447 show = multiply(strstr(response, "INTEGER: ") + 9);
445 show = multiply (strstr (response, "INTEGER: ") + 9);
446 448
447 if (fmtstr_set) { 449 if (fmtstr_set) {
448 conv = fmtstr; 450 conv = fmtstr;
449 } 451 }
450 } 452 } else if (strstr(response, "OID: ")) {
451 else if (strstr (response, "OID: ")) { 453 show = strstr(response, "OID: ") + 5;
452 show = strstr (response, "OID: ") + 5; 454 } else if (strstr(response, "STRING: ")) {
453 } 455 show = strstr(response, "STRING: ") + 8;
454 else if (strstr (response, "STRING: ")) {
455 show = strstr (response, "STRING: ") + 8;
456 conv = "%.10g"; 456 conv = "%.10g";
457 457
458 /* Get the rest of the string on multi-line strings */ 458 /* Get the rest of the string on multi-line strings */
@@ -466,15 +466,17 @@ main (int argc, char **argv)
466 466
467 if (dq_count) { /* unfinished line */ 467 if (dq_count) { /* unfinished line */
468 /* copy show verbatim first */ 468 /* copy show verbatim first */
469 if (!mult_resp) mult_resp = strdup(""); 469 if (!mult_resp)
470 xasprintf (&mult_resp, "%s%s:\n%s\n", mult_resp, oids[i], show); 470 mult_resp = strdup("");
471 xasprintf(&mult_resp, "%s%s:\n%s\n", mult_resp, oids[i], show);
471 /* then strip out unmatched double-quote from single-line output */ 472 /* then strip out unmatched double-quote from single-line output */
472 if (show[0] == '"') show++; 473 if (show[0] == '"')
474 show++;
473 475
474 /* Keep reading until we match end of double-quoted string */ 476 /* Keep reading until we match end of double-quoted string */
475 for (line++; line < chld_out.lines; line++) { 477 for (line++; line < chld_out.lines; line++) {
476 ptr = chld_out.line[line]; 478 ptr = chld_out.line[line];
477 xasprintf (&mult_resp, "%s%s\n", mult_resp, ptr); 479 xasprintf(&mult_resp, "%s%s\n", mult_resp, ptr);
478 480
479 COUNT_SEQ(ptr, bk_count, dq_count) 481 COUNT_SEQ(ptr, bk_count, dq_count)
480 while (dq_count && ptr[0] != '\n' && ptr[0] != '\0') { 482 while (dq_count && ptr[0] != '\n' && ptr[0] != '\0') {
@@ -483,15 +485,14 @@ main (int argc, char **argv)
483 COUNT_SEQ(ptr, bk_count, dq_count) 485 COUNT_SEQ(ptr, bk_count, dq_count)
484 } 486 }
485 /* Break for loop before next line increment when done */ 487 /* Break for loop before next line increment when done */
486 if (!dq_count) break; 488 if (!dq_count)
489 break;
487 } 490 }
488 } 491 }
489 492
490 } 493 } else if (strstr(response, "Timeticks: ")) {
491 else if (strstr (response, "Timeticks: ")) { 494 show = strstr(response, "Timeticks: ");
492 show = strstr (response, "Timeticks: "); 495 } else
493 }
494 else
495 show = response + 3; 496 show = response + 3;
496 497
497 iresult = STATE_DEPENDENT; 498 iresult = STATE_DEPENDENT;
@@ -502,68 +503,67 @@ main (int argc, char **argv)
502 if (verbose > 2) { 503 if (verbose > 2) {
503 print_thresholds(" thresholds", thlds[i]); 504 print_thresholds(" thresholds", thlds[i]);
504 } 505 }
505 ptr = strpbrk (show, "-0123456789"); 506 ptr = strpbrk(show, "-0123456789");
506 if (ptr == NULL){ 507 if (ptr == NULL) {
507 if (nulloid == 3) 508 if (nulloid == 3)
508 die (STATE_UNKNOWN,_("No valid data returned (%s)\n"), show); 509 die(STATE_UNKNOWN, _("No valid data returned (%s)\n"), show);
509 else if (nulloid == 0) 510 else if (nulloid == 0)
510 die (STATE_OK,_("No valid data returned (%s)\n"), show); 511 die(STATE_OK, _("No valid data returned (%s)\n"), show);
511 else if (nulloid == 1) 512 else if (nulloid == 1)
512 die (STATE_WARNING,_("No valid data returned (%s)\n"), show); 513 die(STATE_WARNING, _("No valid data returned (%s)\n"), show);
513 else if (nulloid == 2) 514 else if (nulloid == 2)
514 die (STATE_CRITICAL,_("No valid data returned (%s)\n"), show); 515 die(STATE_CRITICAL, _("No valid data returned (%s)\n"), show);
515 } 516 }
516 while (i >= response_size) { 517 while (i >= response_size) {
517 response_size += OID_COUNT_STEP; 518 response_size += OID_COUNT_STEP;
518 response_value = realloc(response_value, response_size * sizeof(*response_value)); 519 response_value = realloc(response_value, response_size * sizeof(*response_value));
519 } 520 }
520 response_value[i] = strtod (ptr, NULL) + offset; 521 response_value[i] = strtod(ptr, NULL) + offset;
521 522
522 if(calculate_rate) { 523 if (calculate_rate) {
523 if (previous_state!=NULL) { 524 if (previous_state != NULL) {
524 duration = current_time-previous_state->time; 525 duration = current_time - previous_state->time;
525 if(duration<=0) 526 if (duration <= 0)
526 die(STATE_UNKNOWN,_("Time duration between plugin calls is invalid")); 527 die(STATE_UNKNOWN, _("Time duration between plugin calls is invalid"));
527 temp_double = response_value[i]-previous_value[i]; 528 temp_double = response_value[i] - previous_value[i];
528 /* Simple overflow catcher (same as in rrdtool, rrd_update.c) */ 529 /* Simple overflow catcher (same as in rrdtool, rrd_update.c) */
529 if(is_counter) { 530 if (is_counter) {
530 if(temp_double<(double)0.0) 531 if (temp_double < (double)0.0)
531 temp_double+=(double)4294967296.0; /* 2^32 */ 532 temp_double += (double)4294967296.0; /* 2^32 */
532 if(temp_double<(double)0.0) 533 if (temp_double < (double)0.0)
533 temp_double+=(double)18446744069414584320.0; /* 2^64-2^32 */; 534 temp_double += (double)18446744069414584320.0; /* 2^64-2^32 */
535 ;
534 } 536 }
535 /* Convert to per second, then use multiplier */ 537 /* Convert to per second, then use multiplier */
536 temp_double = temp_double/duration*rate_multiplier; 538 temp_double = temp_double / duration * rate_multiplier;
537 iresult = get_status(temp_double, thlds[i]); 539 iresult = get_status(temp_double, thlds[i]);
538 xasprintf (&show, conv, temp_double); 540 xasprintf(&show, conv, temp_double);
539 } 541 }
540 } else { 542 } else {
541 iresult = get_status(response_value[i], thlds[i]); 543 iresult = get_status(response_value[i], thlds[i]);
542 xasprintf (&show, conv, response_value[i]); 544 xasprintf(&show, conv, response_value[i]);
543 } 545 }
544 } 546 }
545 547
546 /* Process this block for string matching */ 548 /* Process this block for string matching */
547 else if (eval_size > i && eval_method[i] & CRIT_STRING) { 549 else if (eval_size > i && eval_method[i] & CRIT_STRING) {
548 if (strcmp (show, string_value)) 550 if (strcmp(show, string_value))
549 iresult = (invert_search==0) ? STATE_CRITICAL : STATE_OK; 551 iresult = (invert_search == 0) ? STATE_CRITICAL : STATE_OK;
550 else 552 else
551 iresult = (invert_search==0) ? STATE_OK : STATE_CRITICAL; 553 iresult = (invert_search == 0) ? STATE_OK : STATE_CRITICAL;
552 } 554 }
553 555
554 /* Process this block for regex matching */ 556 /* Process this block for regex matching */
555 else if (eval_size > i && eval_method[i] & CRIT_REGEX) { 557 else if (eval_size > i && eval_method[i] & CRIT_REGEX) {
556 excode = regexec (&preg, response, 10, pmatch, eflags); 558 excode = regexec(&preg, response, 10, pmatch, eflags);
557 if (excode == 0) { 559 if (excode == 0) {
558 iresult = (invert_search==0) ? STATE_OK : STATE_CRITICAL; 560 iresult = (invert_search == 0) ? STATE_OK : STATE_CRITICAL;
559 } 561 } else if (excode != REG_NOMATCH) {
560 else if (excode != REG_NOMATCH) { 562 regerror(excode, &preg, errbuf, MAX_INPUT_BUFFER);
561 regerror (excode, &preg, errbuf, MAX_INPUT_BUFFER); 563 printf(_("Execute Error: %s\n"), errbuf);
562 printf (_("Execute Error: %s\n"), errbuf); 564 exit(STATE_CRITICAL);
563 exit (STATE_CRITICAL); 565 } else {
564 } 566 iresult = (invert_search == 0) ? STATE_CRITICAL : STATE_OK;
565 else {
566 iresult = (invert_search==0) ? STATE_CRITICAL : STATE_OK;
567 } 567 }
568 } 568 }
569 569
@@ -579,294 +579,283 @@ main (int argc, char **argv)
579 } 579 }
580 580
581 /* Result is the worst outcome of all the OIDs tested */ 581 /* Result is the worst outcome of all the OIDs tested */
582 result = max_state (result, iresult); 582 result = max_state(result, iresult);
583 583
584 /* Prepend a label for this OID if there is one */ 584 /* Prepend a label for this OID if there is one */
585 if (nlabels >= (size_t)1 && (size_t)i < nlabels && labels[i] != NULL) 585 if (nlabels >= (size_t)1 && (size_t)i < nlabels && labels[i] != NULL)
586 xasprintf (&outbuff, "%s%s%s %s%s%s", outbuff, 586 xasprintf(&outbuff, "%s%s%s %s%s%s", outbuff, (i == 0) ? " " : output_delim, labels[i], mark(iresult), show, mark(iresult));
587 (i == 0) ? " " : output_delim,
588 labels[i], mark (iresult), show, mark (iresult));
589 else 587 else
590 xasprintf (&outbuff, "%s%s%s%s%s", outbuff, (i == 0) ? " " : output_delim, 588 xasprintf(&outbuff, "%s%s%s%s%s", outbuff, (i == 0) ? " " : output_delim, mark(iresult), show, mark(iresult));
591 mark (iresult), show, mark (iresult));
592 589
593 /* Append a unit string for this OID if there is one */ 590 /* Append a unit string for this OID if there is one */
594 if (nunits > (size_t)0 && (size_t)i < nunits && unitv[i] != NULL) 591 if (nunits > (size_t)0 && (size_t)i < nunits && unitv[i] != NULL)
595 xasprintf (&outbuff, "%s %s", outbuff, unitv[i]); 592 xasprintf(&outbuff, "%s %s", outbuff, unitv[i]);
596 593
597 /* Write perfdata with whatever can be parsed by strtod, if possible */ 594 /* Write perfdata with whatever can be parsed by strtod, if possible */
598 ptr = NULL; 595 ptr = NULL;
599 strtod(show, &ptr); 596 strtod(show, &ptr);
600 if (ptr > show) { 597 if (ptr > show) {
601 if (perf_labels && nlabels >= (size_t)1 && (size_t)i < nlabels && labels[i] != NULL) 598 if (perf_labels && nlabels >= (size_t)1 && (size_t)i < nlabels && labels[i] != NULL)
602 temp_string=labels[i]; 599 temp_string = labels[i];
603 else 600 else
604 temp_string=oidname; 601 temp_string = oidname;
605 if (strpbrk (temp_string, " ='\"") == NULL) { 602 if (strpbrk(temp_string, " ='\"") == NULL) {
606 strncat(perfstr, temp_string, sizeof(perfstr)-strlen(perfstr)-1); 603 strncat(perfstr, temp_string, sizeof(perfstr) - strlen(perfstr) - 1);
607 } else { 604 } else {
608 if (strpbrk (temp_string, "'") == NULL) { 605 if (strpbrk(temp_string, "'") == NULL) {
609 quote_string="'"; 606 quote_string = "'";
610 } else { 607 } else {
611 quote_string="\""; 608 quote_string = "\"";
612 } 609 }
613 strncat(perfstr, quote_string, sizeof(perfstr)-strlen(perfstr)-1); 610 strncat(perfstr, quote_string, sizeof(perfstr) - strlen(perfstr) - 1);
614 strncat(perfstr, temp_string, sizeof(perfstr)-strlen(perfstr)-1); 611 strncat(perfstr, temp_string, sizeof(perfstr) - strlen(perfstr) - 1);
615 strncat(perfstr, quote_string, sizeof(perfstr)-strlen(perfstr)-1); 612 strncat(perfstr, quote_string, sizeof(perfstr) - strlen(perfstr) - 1);
616 } 613 }
617 strncat(perfstr, "=", sizeof(perfstr)-strlen(perfstr)-1); 614 strncat(perfstr, "=", sizeof(perfstr) - strlen(perfstr) - 1);
618 len = sizeof(perfstr)-strlen(perfstr)-1; 615 len = sizeof(perfstr) - strlen(perfstr) - 1;
619 strncat(perfstr, show, len>ptr-show ? ptr-show : len); 616 strncat(perfstr, show, len > ptr - show ? ptr - show : len);
620 617
621 if (strcmp(type, "") != 0) { 618 if (strcmp(type, "") != 0) {
622 strncat(perfstr, type, sizeof(perfstr)-strlen(perfstr)-1); 619 strncat(perfstr, type, sizeof(perfstr) - strlen(perfstr) - 1);
623 } 620 }
624 621
625 if (warning_thresholds) { 622 if (warning_thresholds) {
626 strncat(perfstr, ";", sizeof(perfstr)-strlen(perfstr)-1); 623 strncat(perfstr, ";", sizeof(perfstr) - strlen(perfstr) - 1);
627 if(thlds[i]->warning && thlds[i]->warning->text) 624 if (thlds[i]->warning && thlds[i]->warning->text)
628 strncat(perfstr, thlds[i]->warning->text, sizeof(perfstr)-strlen(perfstr)-1); 625 strncat(perfstr, thlds[i]->warning->text, sizeof(perfstr) - strlen(perfstr) - 1);
629 } 626 }
630 627
631 if (critical_thresholds) { 628 if (critical_thresholds) {
632 if (!warning_thresholds) 629 if (!warning_thresholds)
633 strncat(perfstr, ";", sizeof(perfstr)-strlen(perfstr)-1); 630 strncat(perfstr, ";", sizeof(perfstr) - strlen(perfstr) - 1);
634 strncat(perfstr, ";", sizeof(perfstr)-strlen(perfstr)-1); 631 strncat(perfstr, ";", sizeof(perfstr) - strlen(perfstr) - 1);
635 if(thlds[i]->critical && thlds[i]->critical->text) 632 if (thlds[i]->critical && thlds[i]->critical->text)
636 strncat(perfstr, thlds[i]->critical->text, sizeof(perfstr)-strlen(perfstr)-1); 633 strncat(perfstr, thlds[i]->critical->text, sizeof(perfstr) - strlen(perfstr) - 1);
637 } 634 }
638 635
639 strncat(perfstr, " ", sizeof(perfstr)-strlen(perfstr)-1); 636 strncat(perfstr, " ", sizeof(perfstr) - strlen(perfstr) - 1);
640 } 637 }
641 } 638 }
642 639
643 /* Save state data, as all data collected now */ 640 /* Save state data, as all data collected now */
644 if(calculate_rate) { 641 if (calculate_rate) {
645 string_length=1024; 642 string_length = 1024;
646 state_string=malloc(string_length); 643 state_string = malloc(string_length);
647 if(state_string==NULL) 644 if (state_string == NULL)
648 die(STATE_UNKNOWN, _("Cannot malloc")); 645 die(STATE_UNKNOWN, _("Cannot malloc"));
649 646
650 current_length=0; 647 current_length = 0;
651 for(int i = 0; i < total_oids; i++) { 648 for (int i = 0; i < total_oids; i++) {
652 xasprintf(&temp_string,"%.0f",response_value[i]); 649 xasprintf(&temp_string, "%.0f", response_value[i]);
653 if(temp_string==NULL) 650 if (temp_string == NULL)
654 die(STATE_UNKNOWN,_("Cannot asprintf()")); 651 die(STATE_UNKNOWN, _("Cannot asprintf()"));
655 response_length = strlen(temp_string); 652 response_length = strlen(temp_string);
656 if(current_length+response_length>string_length) { 653 if (current_length + response_length > string_length) {
657 string_length=current_length+1024; 654 string_length = current_length + 1024;
658 state_string=realloc(state_string,string_length); 655 state_string = realloc(state_string, string_length);
659 if(state_string==NULL) 656 if (state_string == NULL)
660 die(STATE_UNKNOWN, _("Cannot realloc()")); 657 die(STATE_UNKNOWN, _("Cannot realloc()"));
661 } 658 }
662 strcpy(&state_string[current_length],temp_string); 659 strcpy(&state_string[current_length], temp_string);
663 current_length=current_length+response_length; 660 current_length = current_length + response_length;
664 state_string[current_length]=':'; 661 state_string[current_length] = ':';
665 current_length++; 662 current_length++;
666 free(temp_string); 663 free(temp_string);
667 } 664 }
668 state_string[--current_length]='\0'; 665 state_string[--current_length] = '\0';
669 if (verbose > 2) 666 if (verbose > 2)
670 printf("State string=%s\n",state_string); 667 printf("State string=%s\n", state_string);
671 668
672 /* This is not strictly the same as time now, but any subtle variations will cancel out */ 669 /* This is not strictly the same as time now, but any subtle variations will cancel out */
673 np_state_write_string(current_time, state_string ); 670 np_state_write_string(current_time, state_string);
674 if(previous_state==NULL) { 671 if (previous_state == NULL) {
675 /* Or should this be highest state? */ 672 /* Or should this be highest state? */
676 die( STATE_OK, _("No previous data to calculate rate - assume okay" ) ); 673 die(STATE_OK, _("No previous data to calculate rate - assume okay"));
677 } 674 }
678 } 675 }
679 676
680 printf ("%s %s -%s %s\n", label, state_text (result), outbuff, perfstr); 677 printf("%s %s -%s %s\n", label, state_text(result), outbuff, perfstr);
681 if (mult_resp) printf ("%s", mult_resp); 678 if (mult_resp)
679 printf("%s", mult_resp);
682 680
683 return result; 681 return result;
684} 682}
685 683
686
687
688/* process command-line arguments */ 684/* process command-line arguments */
689int 685int process_arguments(int argc, char **argv) {
690process_arguments (int argc, char **argv) 686 static struct option longopts[] = {STD_LONG_OPTS,
691{ 687 {"community", required_argument, 0, 'C'},
692 char *ptr; 688 {"oid", required_argument, 0, 'o'},
693 int c = 1; 689 {"object", required_argument, 0, 'o'},
694 size_t j = 0, jj = 0; 690 {"delimiter", required_argument, 0, 'd'},
695 691 {"nulloid", required_argument, 0, 'z'},
696 int option = 0; 692 {"output-delimiter", required_argument, 0, 'D'},
697 static struct option longopts[] = { 693 {"string", required_argument, 0, 's'},
698 STD_LONG_OPTS, 694 {"timeout", required_argument, 0, 't'},
699 {"community", required_argument, 0, 'C'}, 695 {"regex", required_argument, 0, 'r'},
700 {"oid", required_argument, 0, 'o'}, 696 {"ereg", required_argument, 0, 'r'},
701 {"object", required_argument, 0, 'o'}, 697 {"eregi", required_argument, 0, 'R'},
702 {"delimiter", required_argument, 0, 'd'}, 698 {"label", required_argument, 0, 'l'},
703 {"nulloid", required_argument, 0, 'z'}, 699 {"units", required_argument, 0, 'u'},
704 {"output-delimiter", required_argument, 0, 'D'}, 700 {"port", required_argument, 0, 'p'},
705 {"string", required_argument, 0, 's'}, 701 {"retries", required_argument, 0, 'e'},
706 {"timeout", required_argument, 0, 't'}, 702 {"miblist", required_argument, 0, 'm'},
707 {"regex", required_argument, 0, 'r'}, 703 {"protocol", required_argument, 0, 'P'},
708 {"ereg", required_argument, 0, 'r'}, 704 {"context", required_argument, 0, 'N'},
709 {"eregi", required_argument, 0, 'R'}, 705 {"seclevel", required_argument, 0, 'L'},
710 {"label", required_argument, 0, 'l'}, 706 {"secname", required_argument, 0, 'U'},
711 {"units", required_argument, 0, 'u'}, 707 {"authproto", required_argument, 0, 'a'},
712 {"port", required_argument, 0, 'p'}, 708 {"privproto", required_argument, 0, 'x'},
713 {"retries", required_argument, 0, 'e'}, 709 {"authpasswd", required_argument, 0, 'A'},
714 {"miblist", required_argument, 0, 'm'}, 710 {"privpasswd", required_argument, 0, 'X'},
715 {"protocol", required_argument, 0, 'P'}, 711 {"next", no_argument, 0, 'n'},
716 {"context", required_argument, 0, 'N'}, 712 {"rate", no_argument, 0, L_CALCULATE_RATE},
717 {"seclevel", required_argument, 0, 'L'}, 713 {"rate-multiplier", required_argument, 0, L_RATE_MULTIPLIER},
718 {"secname", required_argument, 0, 'U'}, 714 {"offset", required_argument, 0, L_OFFSET},
719 {"authproto", required_argument, 0, 'a'}, 715 {"invert-search", no_argument, 0, L_INVERT_SEARCH},
720 {"privproto", required_argument, 0, 'x'}, 716 {"perf-oids", no_argument, 0, 'O'},
721 {"authpasswd", required_argument, 0, 'A'}, 717 {"ipv4", no_argument, 0, '4'},
722 {"privpasswd", required_argument, 0, 'X'}, 718 {"ipv6", no_argument, 0, '6'},
723 {"next", no_argument, 0, 'n'}, 719 {"multiplier", required_argument, 0, 'M'},
724 {"rate", no_argument, 0, L_CALCULATE_RATE}, 720 {"fmtstr", required_argument, 0, 'f'},
725 {"rate-multiplier", required_argument, 0, L_RATE_MULTIPLIER}, 721 {"ignore-mib-parsing-errors", no_argument, false, L_IGNORE_MIB_PARSING_ERRORS},
726 {"offset", required_argument, 0, L_OFFSET}, 722 {0, 0, 0, 0}};
727 {"invert-search", no_argument, 0, L_INVERT_SEARCH},
728 {"perf-oids", no_argument, 0, 'O'},
729 {"ipv4", no_argument, 0, '4'},
730 {"ipv6", no_argument, 0, '6'},
731 {"multiplier", required_argument, 0, 'M'},
732 {"fmtstr", required_argument, 0, 'f'},
733 {"ignore-mib-parsing-errors", no_argument, false, L_IGNORE_MIB_PARSING_ERRORS},
734 {0, 0, 0, 0}
735 };
736 723
737 if (argc < 2) 724 if (argc < 2)
738 return ERROR; 725 return ERROR;
739 726
740 /* reverse compatibility for very old non-POSIX usage forms */ 727 /* reverse compatibility for very old non-POSIX usage forms */
741 for (c = 1; c < argc; c++) { 728 for (int c = 1; c < argc; c++) {
742 if (strcmp ("-to", argv[c]) == 0) 729 if (strcmp("-to", argv[c]) == 0)
743 strcpy (argv[c], "-t"); 730 strcpy(argv[c], "-t");
744 if (strcmp ("-wv", argv[c]) == 0) 731 if (strcmp("-wv", argv[c]) == 0)
745 strcpy (argv[c], "-w"); 732 strcpy(argv[c], "-w");
746 if (strcmp ("-cv", argv[c]) == 0) 733 if (strcmp("-cv", argv[c]) == 0)
747 strcpy (argv[c], "-c"); 734 strcpy(argv[c], "-c");
748 } 735 }
749 736
750 while (1) { 737 size_t j = 0;
751 c = getopt_long (argc, argv, "nhvVO46t:c:w:H:C:o:e:E:d:D:s:t:R:r:l:u:p:m:P:N:L:U:a:x:A:X:M:f:z:", 738 size_t jj = 0;
752 longopts, &option); 739 while (true) {
740 int option = 0;
741 int option_char = getopt_long(argc, argv, "nhvVO46t:c:w:H:C:o:e:E:d:D:s:t:R:r:l:u:p:m:P:N:L:U:a:x:A:X:M:f:z:", longopts, &option);
753 742
754 if (c == -1 || c == EOF) 743 if (option_char == -1 || option_char == EOF)
755 break; 744 break;
756 745
757 switch (c) { 746 switch (option_char) {
758 case '?': /* usage */ 747 case '?': /* usage */
759 usage5 (); 748 usage5();
760 case 'h': /* help */ 749 case 'h': /* help */
761 print_help (); 750 print_help();
762 exit (STATE_UNKNOWN); 751 exit(STATE_UNKNOWN);
763 case 'V': /* version */ 752 case 'V': /* version */
764 print_revision (progname, NP_VERSION); 753 print_revision(progname, NP_VERSION);
765 exit (STATE_UNKNOWN); 754 exit(STATE_UNKNOWN);
766 case 'v': /* verbose */ 755 case 'v': /* verbose */
767 verbose++; 756 verbose++;
768 break; 757 break;
769 758
770 /* Connection info */ 759 /* Connection info */
771 case 'C': /* group or community */ 760 case 'C': /* group or community */
772 community = optarg; 761 community = optarg;
773 break; 762 break;
774 case 'H': /* Host or server */ 763 case 'H': /* Host or server */
775 server_address = optarg; 764 server_address = optarg;
776 break; 765 break;
777 case 'p': /* TCP port number */ 766 case 'p': /* TCP port number */
778 port = optarg; 767 port = optarg;
779 break; 768 break;
780 case 'm': /* List of MIBS */ 769 case 'm': /* List of MIBS */
781 miblist = optarg; 770 miblist = optarg;
782 break; 771 break;
783 case 'n': /* usesnmpgetnext */ 772 case 'n': /* usesnmpgetnext */
784 usesnmpgetnext = true; 773 usesnmpgetnext = true;
785 break; 774 break;
786 case 'P': /* SNMP protocol version */ 775 case 'P': /* SNMP protocol version */
787 proto = optarg; 776 proto = optarg;
788 break; 777 break;
789 case 'N': /* SNMPv3 context */ 778 case 'N': /* SNMPv3 context */
790 context = optarg; 779 context = optarg;
791 break; 780 break;
792 case 'L': /* security level */ 781 case 'L': /* security level */
793 seclevel = optarg; 782 seclevel = optarg;
794 break; 783 break;
795 case 'U': /* security username */ 784 case 'U': /* security username */
796 secname = optarg; 785 secname = optarg;
797 break; 786 break;
798 case 'a': /* auth protocol */ 787 case 'a': /* auth protocol */
799 authproto = optarg; 788 authproto = optarg;
800 break; 789 break;
801 case 'x': /* priv protocol */ 790 case 'x': /* priv protocol */
802 privproto = optarg; 791 privproto = optarg;
803 break; 792 break;
804 case 'A': /* auth passwd */ 793 case 'A': /* auth passwd */
805 authpasswd = optarg; 794 authpasswd = optarg;
806 break; 795 break;
807 case 'X': /* priv passwd */ 796 case 'X': /* priv passwd */
808 privpasswd = optarg; 797 privpasswd = optarg;
809 break; 798 break;
810 case 't': /* timeout period */ 799 case 't': /* timeout period */
811 if (!is_integer (optarg)) 800 if (!is_integer(optarg))
812 usage2 (_("Timeout interval must be a positive integer"), optarg); 801 usage2(_("Timeout interval must be a positive integer"), optarg);
813 else 802 else
814 timeout_interval = atoi (optarg); 803 timeout_interval = atoi(optarg);
815 break; 804 break;
816 805
817 /* Test parameters */ 806 /* Test parameters */
818 case 'c': /* critical threshold */ 807 case 'c': /* critical threshold */
819 critical_thresholds = optarg; 808 critical_thresholds = optarg;
820 break; 809 break;
821 case 'w': /* warning threshold */ 810 case 'w': /* warning threshold */
822 warning_thresholds = optarg; 811 warning_thresholds = optarg;
823 break; 812 break;
824 case 'e': /* PRELIMINARY - may change */ 813 case 'e': /* PRELIMINARY - may change */
825 case 'E': /* PRELIMINARY - may change */ 814 case 'E': /* PRELIMINARY - may change */
826 if (!is_integer (optarg)) 815 if (!is_integer(optarg))
827 usage2 (_("Retries interval must be a positive integer"), optarg); 816 usage2(_("Retries interval must be a positive integer"), optarg);
828 else 817 else
829 retries = atoi(optarg); 818 retries = atoi(optarg);
830 break; 819 break;
831 case 'o': /* object identifier */ 820 case 'o': /* object identifier */
832 if ( strspn( optarg, "0123456789.," ) != strlen( optarg ) ) { 821 if (strspn(optarg, "0123456789.,") != strlen(optarg)) {
833 /* 822 /*
834 * we have something other than digits, periods and comas, 823 * we have something other than digits, periods and comas,
835 * so we have a mib variable, rather than just an SNMP OID, 824 * so we have a mib variable, rather than just an SNMP OID,
836 * so we have to actually read the mib files 825 * so we have to actually read the mib files
837 */ 826 */
838 needmibs = true; 827 needmibs = true;
839 } 828 }
840 for (ptr = strtok(optarg, ", "); ptr != NULL; ptr = strtok(NULL, ", "), j++) { 829 for (char *ptr = strtok(optarg, ", "); ptr != NULL; ptr = strtok(NULL, ", "), j++) {
841 while (j >= oids_size) { 830 while (j >= oids_size) {
842 oids_size += OID_COUNT_STEP; 831 oids_size += OID_COUNT_STEP;
843 oids = realloc(oids, oids_size * sizeof (*oids)); 832 oids = realloc(oids, oids_size * sizeof(*oids));
844 } 833 }
845 oids[j] = strdup(ptr); 834 oids[j] = strdup(ptr);
846 } 835 }
847 numoids = j; 836 numoids = j;
848 if (c == 'E' || c == 'e') { 837 if (option_char == 'E' || option_char == 'e') {
849 jj++; 838 jj++;
850 while (j+1 >= eval_size) { 839 while (j + 1 >= eval_size) {
851 eval_size += OID_COUNT_STEP; 840 eval_size += OID_COUNT_STEP;
852 eval_method = realloc(eval_method, eval_size * sizeof(*eval_method)); 841 eval_method = realloc(eval_method, eval_size * sizeof(*eval_method));
853 memset(eval_method + eval_size - OID_COUNT_STEP, 0, 8); 842 memset(eval_method + eval_size - OID_COUNT_STEP, 0, 8);
854 } 843 }
855 if (c == 'E') 844 if (option_char == 'E')
856 eval_method[j+1] |= WARN_PRESENT; 845 eval_method[j + 1] |= WARN_PRESENT;
857 else if (c == 'e') 846 else if (option_char == 'e')
858 eval_method[j+1] |= CRIT_PRESENT; 847 eval_method[j + 1] |= CRIT_PRESENT;
859 } 848 }
860 break; 849 break;
861 case 'z': /* Null OID Return Check */ 850 case 'z': /* Null OID Return Check */
862 if (!is_integer (optarg)) 851 if (!is_integer(optarg))
863 usage2 (_("Exit status must be a positive integer"), optarg); 852 usage2(_("Exit status must be a positive integer"), optarg);
864 else 853 else
865 nulloid = atoi(optarg); 854 nulloid = atoi(optarg);
866 break; 855 break;
867 case 's': /* string or substring */ 856 case 's': /* string or substring */
868 strncpy (string_value, optarg, sizeof (string_value) - 1); 857 strncpy(string_value, optarg, sizeof(string_value) - 1);
869 string_value[sizeof (string_value) - 1] = 0; 858 string_value[sizeof(string_value) - 1] = 0;
870 while (jj >= eval_size) { 859 while (jj >= eval_size) {
871 eval_size += OID_COUNT_STEP; 860 eval_size += OID_COUNT_STEP;
872 eval_method = realloc(eval_method, eval_size * sizeof(*eval_method)); 861 eval_method = realloc(eval_method, eval_size * sizeof(*eval_method));
@@ -874,17 +863,17 @@ process_arguments (int argc, char **argv)
874 } 863 }
875 eval_method[jj++] = CRIT_STRING; 864 eval_method[jj++] = CRIT_STRING;
876 break; 865 break;
877 case 'R': /* regex */ 866 case 'R': /* regex */
878 cflags = REG_ICASE; 867 cflags = REG_ICASE;
879 // fall through 868 // fall through
880 case 'r': /* regex */ 869 case 'r': /* regex */
881 cflags |= REG_EXTENDED | REG_NOSUB | REG_NEWLINE; 870 cflags |= REG_EXTENDED | REG_NOSUB | REG_NEWLINE;
882 strncpy (regex_expect, optarg, sizeof (regex_expect) - 1); 871 strncpy(regex_expect, optarg, sizeof(regex_expect) - 1);
883 regex_expect[sizeof (regex_expect) - 1] = 0; 872 regex_expect[sizeof(regex_expect) - 1] = 0;
884 errcode = regcomp (&preg, regex_expect, cflags); 873 errcode = regcomp(&preg, regex_expect, cflags);
885 if (errcode != 0) { 874 if (errcode != 0) {
886 regerror (errcode, &preg, errbuf, MAX_INPUT_BUFFER); 875 regerror(errcode, &preg, errbuf, MAX_INPUT_BUFFER);
887 printf (_("Could Not Compile Regular Expression")); 876 printf(_("Could Not Compile Regular Expression"));
888 return ERROR; 877 return ERROR;
889 } 878 }
890 while (jj >= eval_size) { 879 while (jj >= eval_size) {
@@ -895,64 +884,64 @@ process_arguments (int argc, char **argv)
895 eval_method[jj++] = CRIT_REGEX; 884 eval_method[jj++] = CRIT_REGEX;
896 break; 885 break;
897 886
898 /* Format */ 887 /* Format */
899 case 'd': /* delimiter */ 888 case 'd': /* delimiter */
900 delimiter = strscpy (delimiter, optarg); 889 delimiter = strscpy(delimiter, optarg);
901 break; 890 break;
902 case 'D': /* output-delimiter */ 891 case 'D': /* output-delimiter */
903 output_delim = strscpy (output_delim, optarg); 892 output_delim = strscpy(output_delim, optarg);
904 break; 893 break;
905 case 'l': /* label */ 894 case 'l': /* label */
906 nlabels++; 895 nlabels++;
907 if (nlabels > labels_size) { 896 if (nlabels > labels_size) {
908 labels_size += 8; 897 labels_size += 8;
909 labels = realloc (labels, labels_size * sizeof(*labels)); 898 labels = realloc(labels, labels_size * sizeof(*labels));
910 if (labels == NULL) 899 if (labels == NULL)
911 die (STATE_UNKNOWN, _("Could not reallocate labels[%d]"), (int)nlabels); 900 die(STATE_UNKNOWN, _("Could not reallocate labels[%d]"), (int)nlabels);
912 } 901 }
913 labels[nlabels - 1] = optarg; 902 labels[nlabels - 1] = optarg;
914 ptr = thisarg (optarg); 903 char *ptr = thisarg(optarg);
915 labels[nlabels - 1] = ptr; 904 labels[nlabels - 1] = ptr;
916 if (ptr[0] == '\'') 905 if (ptr[0] == '\'')
917 labels[nlabels - 1] = ptr + 1; 906 labels[nlabels - 1] = ptr + 1;
918 while (ptr && (ptr = nextarg (ptr))) { 907 while (ptr && (ptr = nextarg(ptr))) {
919 nlabels++; 908 nlabels++;
920 if (nlabels > labels_size) { 909 if (nlabels > labels_size) {
921 labels_size += 8; 910 labels_size += 8;
922 labels = realloc (labels, labels_size * sizeof(*labels)); 911 labels = realloc(labels, labels_size * sizeof(*labels));
923 if (labels == NULL) 912 if (labels == NULL)
924 die (STATE_UNKNOWN, _("Could not reallocate labels\n")); 913 die(STATE_UNKNOWN, _("Could not reallocate labels\n"));
925 } 914 }
926 ptr = thisarg (ptr); 915 ptr = thisarg(ptr);
927 if (ptr[0] == '\'') 916 if (ptr[0] == '\'')
928 labels[nlabels - 1] = ptr + 1; 917 labels[nlabels - 1] = ptr + 1;
929 else 918 else
930 labels[nlabels - 1] = ptr; 919 labels[nlabels - 1] = ptr;
931 } 920 }
932 break; 921 break;
933 case 'u': /* units */ 922 case 'u': /* units */
934 units = optarg; 923 units = optarg;
935 nunits++; 924 nunits++;
936 if (nunits > unitv_size) { 925 if (nunits > unitv_size) {
937 unitv_size += 8; 926 unitv_size += 8;
938 unitv = realloc (unitv, unitv_size * sizeof(*unitv)); 927 unitv = realloc(unitv, unitv_size * sizeof(*unitv));
939 if (unitv == NULL) 928 if (unitv == NULL)
940 die (STATE_UNKNOWN, _("Could not reallocate units [%d]\n"), (int)nunits); 929 die(STATE_UNKNOWN, _("Could not reallocate units [%d]\n"), (int)nunits);
941 } 930 }
942 unitv[nunits - 1] = optarg; 931 unitv[nunits - 1] = optarg;
943 ptr = thisarg (optarg); 932 ptr = thisarg(optarg);
944 unitv[nunits - 1] = ptr; 933 unitv[nunits - 1] = ptr;
945 if (ptr[0] == '\'') 934 if (ptr[0] == '\'')
946 unitv[nunits - 1] = ptr + 1; 935 unitv[nunits - 1] = ptr + 1;
947 while (ptr && (ptr = nextarg (ptr))) { 936 while (ptr && (ptr = nextarg(ptr))) {
948 if (nunits > unitv_size) { 937 if (nunits > unitv_size) {
949 unitv_size += 8; 938 unitv_size += 8;
950 unitv = realloc (unitv, unitv_size * sizeof(*unitv)); 939 unitv = realloc(unitv, unitv_size * sizeof(*unitv));
951 if (units == NULL) 940 if (units == NULL)
952 die (STATE_UNKNOWN, _("Could not realloc() units\n")); 941 die(STATE_UNKNOWN, _("Could not realloc() units\n"));
953 } 942 }
954 nunits++; 943 nunits++;
955 ptr = thisarg (ptr); 944 ptr = thisarg(ptr);
956 if (ptr[0] == '\'') 945 if (ptr[0] == '\'')
957 unitv[nunits - 1] = ptr + 1; 946 unitv[nunits - 1] = ptr + 1;
958 else 947 else
@@ -960,38 +949,38 @@ process_arguments (int argc, char **argv)
960 } 949 }
961 break; 950 break;
962 case L_CALCULATE_RATE: 951 case L_CALCULATE_RATE:
963 if(calculate_rate==0) 952 if (calculate_rate == 0)
964 np_enable_state(NULL, 1); 953 np_enable_state(NULL, 1);
965 calculate_rate = 1; 954 calculate_rate = 1;
966 break; 955 break;
967 case L_RATE_MULTIPLIER: 956 case L_RATE_MULTIPLIER:
968 if(!is_integer(optarg)||((rate_multiplier=atoi(optarg))<=0)) 957 if (!is_integer(optarg) || ((rate_multiplier = atoi(optarg)) <= 0))
969 usage2(_("Rate multiplier must be a positive integer"),optarg); 958 usage2(_("Rate multiplier must be a positive integer"), optarg);
970 break; 959 break;
971 case L_OFFSET: 960 case L_OFFSET:
972 offset=strtod(optarg,NULL); 961 offset = strtod(optarg, NULL);
973 break; 962 break;
974 case L_INVERT_SEARCH: 963 case L_INVERT_SEARCH:
975 invert_search=1; 964 invert_search = 1;
976 break; 965 break;
977 case 'O': 966 case 'O':
978 perf_labels=0; 967 perf_labels = 0;
979 break; 968 break;
980 case '4': 969 case '4':
981 break; 970 break;
982 case '6': 971 case '6':
983 xasprintf(&ip_version, "udp6:"); 972 xasprintf(&ip_version, "udp6:");
984 if(verbose>2) 973 if (verbose > 2)
985 printf("IPv6 detected! Will pass \"udp6:\" to snmpget.\n"); 974 printf("IPv6 detected! Will pass \"udp6:\" to snmpget.\n");
986 break; 975 break;
987 case 'M': 976 case 'M':
988 if ( strspn( optarg, "0123456789.," ) == strlen( optarg ) ) { 977 if (strspn(optarg, "0123456789.,") == strlen(optarg)) {
989 multiplier=strtod(optarg,NULL); 978 multiplier = strtod(optarg, NULL);
990 } 979 }
991 break; 980 break;
992 case 'f': 981 case 'f':
993 if (multiplier != 1.0) { 982 if (multiplier != 1.0) {
994 fmtstr=optarg; 983 fmtstr = optarg;
995 fmtstr_set = true; 984 fmtstr_set = true;
996 } 985 }
997 break; 986 break;
@@ -1004,12 +993,11 @@ process_arguments (int argc, char **argv)
1004 server_address = argv[optind]; 993 server_address = argv[optind];
1005 994
1006 if (community == NULL) 995 if (community == NULL)
1007 community = strdup (DEFAULT_COMMUNITY); 996 community = strdup(DEFAULT_COMMUNITY);
1008 997
1009 return validate_arguments (); 998 return validate_arguments();
1010} 999}
1011 1000
1012
1013/****************************************************************************** 1001/******************************************************************************
1014 1002
1015@@- 1003@@-
@@ -1028,17 +1016,13 @@ selected.</para>
1028-@@ 1016-@@
1029******************************************************************************/ 1017******************************************************************************/
1030 1018
1031 1019static int validate_arguments() {
1032
1033int
1034validate_arguments ()
1035{
1036 /* check whether to load locally installed MIBS (CPU/disk intensive) */ 1020 /* check whether to load locally installed MIBS (CPU/disk intensive) */
1037 if (miblist == NULL) { 1021 if (miblist == NULL) {
1038 if (needmibs) { 1022 if (needmibs) {
1039 miblist = strdup (DEFAULT_MIBLIST); 1023 miblist = strdup(DEFAULT_MIBLIST);
1040 }else{ 1024 } else {
1041 miblist = ""; /* don't read any mib files for numeric oids */ 1025 miblist = ""; /* don't read any mib files for numeric oids */
1042 } 1026 }
1043 } 1027 }
1044 1028
@@ -1053,18 +1037,17 @@ validate_arguments ()
1053 if (proto == NULL) 1037 if (proto == NULL)
1054 xasprintf(&proto, DEFAULT_PROTOCOL); 1038 xasprintf(&proto, DEFAULT_PROTOCOL);
1055 1039
1056 if ((strcmp(proto,"1") == 0) || (strcmp(proto, "2c")==0)) { /* snmpv1 or snmpv2c */ 1040 if ((strcmp(proto, "1") == 0) || (strcmp(proto, "2c") == 0)) { /* snmpv1 or snmpv2c */
1057 numauthpriv = 2; 1041 numauthpriv = 2;
1058 authpriv = calloc (numauthpriv, sizeof (char *)); 1042 authpriv = calloc(numauthpriv, sizeof(char *));
1059 authpriv[0] = strdup ("-c"); 1043 authpriv[0] = strdup("-c");
1060 authpriv[1] = strdup (community); 1044 authpriv[1] = strdup(community);
1061 } 1045 } else if (strcmp(proto, "3") == 0) { /* snmpv3 args */
1062 else if ( strcmp (proto, "3") == 0 ) { /* snmpv3 args */
1063 if (!(context == NULL)) { 1046 if (!(context == NULL)) {
1064 numcontext = 2; 1047 numcontext = 2;
1065 contextargs = calloc (numcontext, sizeof (char *)); 1048 contextargs = calloc(numcontext, sizeof(char *));
1066 contextargs[0] = strdup ("-n"); 1049 contextargs[0] = strdup("-n");
1067 contextargs[1] = strdup (context); 1050 contextargs[1] = strdup(context);
1068 } 1051 }
1069 1052
1070 if (seclevel == NULL) 1053 if (seclevel == NULL)
@@ -1075,282 +1058,266 @@ validate_arguments ()
1075 1058
1076 if (strcmp(seclevel, "noAuthNoPriv") == 0) { 1059 if (strcmp(seclevel, "noAuthNoPriv") == 0) {
1077 numauthpriv = 4; 1060 numauthpriv = 4;
1078 authpriv = calloc (numauthpriv, sizeof (char *)); 1061 authpriv = calloc(numauthpriv, sizeof(char *));
1079 authpriv[0] = strdup ("-l"); 1062 authpriv[0] = strdup("-l");
1080 authpriv[1] = strdup ("noAuthNoPriv"); 1063 authpriv[1] = strdup("noAuthNoPriv");
1081 authpriv[2] = strdup ("-u"); 1064 authpriv[2] = strdup("-u");
1082 authpriv[3] = strdup (secname); 1065 authpriv[3] = strdup(secname);
1083 } else { 1066 } else {
1084 if (! ( (strcmp(seclevel, "authNoPriv")==0) || (strcmp(seclevel, "authPriv")==0) ) ) { 1067 if (!((strcmp(seclevel, "authNoPriv") == 0) || (strcmp(seclevel, "authPriv") == 0))) {
1085 usage2 (_("Invalid seclevel"), seclevel); 1068 usage2(_("Invalid seclevel"), seclevel);
1086 } 1069 }
1087 1070
1088 if (authproto == NULL ) 1071 if (authproto == NULL)
1089 xasprintf(&authproto, DEFAULT_AUTH_PROTOCOL); 1072 xasprintf(&authproto, DEFAULT_AUTH_PROTOCOL);
1090 1073
1091 if (authpasswd == NULL) 1074 if (authpasswd == NULL)
1092 die(STATE_UNKNOWN, _("Required parameter: %s\n"), "authpasswd"); 1075 die(STATE_UNKNOWN, _("Required parameter: %s\n"), "authpasswd");
1093 1076
1094 if ( strcmp(seclevel, "authNoPriv") == 0 ) { 1077 if (strcmp(seclevel, "authNoPriv") == 0) {
1095 numauthpriv = 8; 1078 numauthpriv = 8;
1096 authpriv = calloc (numauthpriv, sizeof (char *)); 1079 authpriv = calloc(numauthpriv, sizeof(char *));
1097 authpriv[0] = strdup ("-l"); 1080 authpriv[0] = strdup("-l");
1098 authpriv[1] = strdup ("authNoPriv"); 1081 authpriv[1] = strdup("authNoPriv");
1099 authpriv[2] = strdup ("-a"); 1082 authpriv[2] = strdup("-a");
1100 authpriv[3] = strdup (authproto); 1083 authpriv[3] = strdup(authproto);
1101 authpriv[4] = strdup ("-u"); 1084 authpriv[4] = strdup("-u");
1102 authpriv[5] = strdup (secname); 1085 authpriv[5] = strdup(secname);
1103 authpriv[6] = strdup ("-A"); 1086 authpriv[6] = strdup("-A");
1104 authpriv[7] = strdup (authpasswd); 1087 authpriv[7] = strdup(authpasswd);
1105 } else if ( strcmp(seclevel, "authPriv") == 0 ) { 1088 } else if (strcmp(seclevel, "authPriv") == 0) {
1106 if (privproto == NULL ) 1089 if (privproto == NULL)
1107 xasprintf(&privproto, DEFAULT_PRIV_PROTOCOL); 1090 xasprintf(&privproto, DEFAULT_PRIV_PROTOCOL);
1108 1091
1109 if (privpasswd == NULL) 1092 if (privpasswd == NULL)
1110 die(STATE_UNKNOWN, _("Required parameter: %s\n"), "privpasswd"); 1093 die(STATE_UNKNOWN, _("Required parameter: %s\n"), "privpasswd");
1111 1094
1112 numauthpriv = 12; 1095 numauthpriv = 12;
1113 authpriv = calloc (numauthpriv, sizeof (char *)); 1096 authpriv = calloc(numauthpriv, sizeof(char *));
1114 authpriv[0] = strdup ("-l"); 1097 authpriv[0] = strdup("-l");
1115 authpriv[1] = strdup ("authPriv"); 1098 authpriv[1] = strdup("authPriv");
1116 authpriv[2] = strdup ("-a"); 1099 authpriv[2] = strdup("-a");
1117 authpriv[3] = strdup (authproto); 1100 authpriv[3] = strdup(authproto);
1118 authpriv[4] = strdup ("-u"); 1101 authpriv[4] = strdup("-u");
1119 authpriv[5] = strdup (secname); 1102 authpriv[5] = strdup(secname);
1120 authpriv[6] = strdup ("-A"); 1103 authpriv[6] = strdup("-A");
1121 authpriv[7] = strdup (authpasswd); 1104 authpriv[7] = strdup(authpasswd);
1122 authpriv[8] = strdup ("-x"); 1105 authpriv[8] = strdup("-x");
1123 authpriv[9] = strdup (privproto); 1106 authpriv[9] = strdup(privproto);
1124 authpriv[10] = strdup ("-X"); 1107 authpriv[10] = strdup("-X");
1125 authpriv[11] = strdup (privpasswd); 1108 authpriv[11] = strdup(privpasswd);
1126 } 1109 }
1127 } 1110 }
1128 1111
1129 } 1112 } else {
1130 else { 1113 usage2(_("Invalid SNMP version"), proto);
1131 usage2 (_("Invalid SNMP version"), proto);
1132 } 1114 }
1133 1115
1134 return OK; 1116 return OK;
1135} 1117}
1136 1118
1137
1138
1139/* trim leading whitespace 1119/* trim leading whitespace
1140 if there is a leading quote, make sure it balances */ 1120 if there is a leading quote, make sure it balances */
1141 1121
1142char * 1122static char *thisarg(char *str) {
1143thisarg (char *str) 1123 str += strspn(str, " \t\r\n"); /* trim any leading whitespace */
1144{ 1124 if (str[0] == '\'') { /* handle SIMPLE quoted strings */
1145 str += strspn (str, " \t\r\n"); /* trim any leading whitespace */ 1125 if (strlen(str) == 1 || !strstr(str + 1, "'"))
1146 if (str[0] == '\'') { /* handle SIMPLE quoted strings */ 1126 die(STATE_UNKNOWN, _("Unbalanced quotes\n"));
1147 if (strlen (str) == 1 || !strstr (str + 1, "'"))
1148 die (STATE_UNKNOWN, _("Unbalanced quotes\n"));
1149 } 1127 }
1150 return str; 1128 return str;
1151} 1129}
1152 1130
1153
1154
1155/* if there's a leading quote, advance to the trailing quote 1131/* if there's a leading quote, advance to the trailing quote
1156 set the trailing quote to '\x0' 1132 set the trailing quote to '\x0'
1157 if the string continues, advance beyond the comma */ 1133 if the string continues, advance beyond the comma */
1158 1134
1159char * 1135static char *nextarg(char *str) {
1160nextarg (char *str)
1161{
1162 if (str[0] == '\'') { 1136 if (str[0] == '\'') {
1163 str[0] = 0; 1137 str[0] = 0;
1164 if (strlen (str) > 1) { 1138 if (strlen(str) > 1) {
1165 str = strstr (str + 1, "'"); 1139 str = strstr(str + 1, "'");
1166 return (++str); 1140 return (++str);
1167 } 1141 } else {
1168 else {
1169 return NULL; 1142 return NULL;
1170 } 1143 }
1171 } 1144 }
1172 if (str[0] == ',') { 1145 if (str[0] == ',') {
1173 str[0] = 0; 1146 str[0] = 0;
1174 if (strlen (str) > 1) { 1147 if (strlen(str) > 1) {
1175 return (++str); 1148 return (++str);
1176 } 1149 } else {
1177 else {
1178 return NULL; 1150 return NULL;
1179 } 1151 }
1180 } 1152 }
1181 if ((str = strstr (str, ",")) && strlen (str) > 1) { 1153 if ((str = strstr(str, ",")) && strlen(str) > 1) {
1182 str[0] = 0; 1154 str[0] = 0;
1183 return (++str); 1155 return (++str);
1184 } 1156 }
1185 return NULL; 1157 return NULL;
1186} 1158}
1187 1159
1188
1189
1190/* multiply result (values 0 < n < 1 work as divider) */ 1160/* multiply result (values 0 < n < 1 work as divider) */
1191char * 1161static char *multiply(char *str) {
1192multiply (char *str) 1162 if (multiplier == 1)
1193{ 1163 return (str);
1194 char *endptr;
1195 double val;
1196 char *conv = "%f";
1197
1198 if(multiplier == 1)
1199 return(str);
1200 1164
1201 if(verbose>2) 1165 if (verbose > 2)
1202 printf(" multiply input: %s\n", str); 1166 printf(" multiply input: %s\n", str);
1203 1167
1204 val = strtod (str, &endptr); 1168 char *endptr;
1169 double val = strtod(str, &endptr);
1205 if ((val == 0.0) && (endptr == str)) { 1170 if ((val == 0.0) && (endptr == str)) {
1206 die(STATE_UNKNOWN, _("multiplier set (%.1f), but input is not a number: %s"), multiplier, str); 1171 die(STATE_UNKNOWN, _("multiplier set (%.1f), but input is not a number: %s"), multiplier, str);
1207 } 1172 }
1208 1173
1209 if(verbose>2) 1174 if (verbose > 2)
1210 printf(" multiply extracted double: %f\n", val); 1175 printf(" multiply extracted double: %f\n", val);
1176
1211 val *= multiplier; 1177 val *= multiplier;
1178 char *conv = "%f";
1212 if (fmtstr_set) { 1179 if (fmtstr_set) {
1213 conv = fmtstr; 1180 conv = fmtstr;
1214 } 1181 }
1215 if (val == (int)val) { 1182 if (val == (int)val) {
1216 snprintf(buffer, DEFAULT_BUFFER_SIZE, "%.0f", val); 1183 snprintf(buffer, DEFAULT_BUFFER_SIZE, "%.0f", val);
1217 } else { 1184 } else {
1218 if(verbose>2) 1185 if (verbose > 2)
1219 printf(" multiply using format: %s\n", conv); 1186 printf(" multiply using format: %s\n", conv);
1220 snprintf(buffer, DEFAULT_BUFFER_SIZE, conv, val); 1187 snprintf(buffer, DEFAULT_BUFFER_SIZE, conv, val);
1221 } 1188 }
1222 if(verbose>2) 1189 if (verbose > 2)
1223 printf(" multiply result: %s\n", buffer); 1190 printf(" multiply result: %s\n", buffer);
1224 return buffer; 1191 return buffer;
1225} 1192}
1226 1193
1194static void print_help(void) {
1195 print_revision(progname, NP_VERSION);
1227 1196
1228void 1197 printf(COPYRIGHT, copyright, email);
1229print_help (void)
1230{
1231 print_revision (progname, NP_VERSION);
1232
1233 printf (COPYRIGHT, copyright, email);
1234 1198
1235 printf ("%s\n", _("Check status of remote machines and obtain system information via SNMP")); 1199 printf("%s\n", _("Check status of remote machines and obtain system information via SNMP"));
1236 1200
1237 printf ("\n\n"); 1201 printf("\n\n");
1238 1202
1239 print_usage (); 1203 print_usage();
1240 1204
1241 printf (UT_HELP_VRSN); 1205 printf(UT_HELP_VRSN);
1242 printf (UT_EXTRA_OPTS); 1206 printf(UT_EXTRA_OPTS);
1243 printf (UT_IPv46); 1207 printf(UT_IPv46);
1244 1208
1245 printf (UT_HOST_PORT, 'p', DEFAULT_PORT); 1209 printf(UT_HOST_PORT, 'p', DEFAULT_PORT);
1246 1210
1247 /* SNMP and Authentication Protocol */ 1211 /* SNMP and Authentication Protocol */
1248 printf (" %s\n", "-n, --next"); 1212 printf(" %s\n", "-n, --next");
1249 printf (" %s\n", _("Use SNMP GETNEXT instead of SNMP GET")); 1213 printf(" %s\n", _("Use SNMP GETNEXT instead of SNMP GET"));
1250 printf (" %s\n", "-P, --protocol=[1|2c|3]"); 1214 printf(" %s\n", "-P, --protocol=[1|2c|3]");
1251 printf (" %s\n", _("SNMP protocol version")); 1215 printf(" %s\n", _("SNMP protocol version"));
1252 printf (" %s\n", "-N, --context=CONTEXT"); 1216 printf(" %s\n", "-N, --context=CONTEXT");
1253 printf (" %s\n", _("SNMPv3 context")); 1217 printf(" %s\n", _("SNMPv3 context"));
1254 printf (" %s\n", "-L, --seclevel=[noAuthNoPriv|authNoPriv|authPriv]"); 1218 printf(" %s\n", "-L, --seclevel=[noAuthNoPriv|authNoPriv|authPriv]");
1255 printf (" %s\n", _("SNMPv3 securityLevel")); 1219 printf(" %s\n", _("SNMPv3 securityLevel"));
1256 printf (" %s\n", "-a, --authproto=[MD5|SHA]"); 1220 printf(" %s\n", "-a, --authproto=AUTHENTICATION_PROTOCOL");
1257 printf (" %s\n", _("SNMPv3 auth proto")); 1221 printf(" %s\n",
1258 printf (" %s\n", "-x, --privproto=[DES|AES]"); 1222 _("SNMPv3 authentication protocol (default MD5), available options depend on the specific version of the net-snmp tools"));
1259 printf (" %s\n", _("SNMPv3 priv proto (default DES)")); 1223 printf(" %s\n", _("if < 5.8 SHA (1) and MD5 should be available, if >= 5.8 additionally SHA-224, SHA-256, SHA-384 and SHA-512"));
1224 printf(" %s\n", "-x, --privproto=PRIVACY_PROTOCOL");
1225 printf(" %s\n", _("SNMPv3 privacy protocol (default DES), available options depend on the specific version of the net-snmp tools"));
1226 printf(" %s\n", _("if < 5.8 DES and AES should be available, if >= 5.8 additionally AES-192 and AES-256"));
1260 1227
1261 /* Authentication Tokens*/ 1228 /* Authentication Tokens*/
1262 printf (" %s\n", "-C, --community=STRING"); 1229 printf(" %s\n", "-C, --community=STRING");
1263 printf (" %s ", _("Optional community string for SNMP communication")); 1230 printf(" %s ", _("Optional community string for SNMP communication"));
1264 printf ("(%s \"%s\")\n", _("default is") ,DEFAULT_COMMUNITY); 1231 printf("(%s \"%s\")\n", _("default is"), DEFAULT_COMMUNITY);
1265 printf (" %s\n", "-U, --secname=USERNAME"); 1232 printf(" %s\n", "-U, --secname=USERNAME");
1266 printf (" %s\n", _("SNMPv3 username")); 1233 printf(" %s\n", _("SNMPv3 username"));
1267 printf (" %s\n", "-A, --authpasswd=PASSWORD"); 1234 printf(" %s\n", "-A, --authpasswd=PASSWORD");
1268 printf (" %s\n", _("SNMPv3 authentication password")); 1235 printf(" %s\n", _("SNMPv3 authentication password"));
1269 printf (" %s\n", "-X, --privpasswd=PASSWORD"); 1236 printf(" %s\n", "-X, --privpasswd=PASSWORD");
1270 printf (" %s\n", _("SNMPv3 privacy password")); 1237 printf(" %s\n", _("SNMPv3 privacy password"));
1271 1238
1272 /* OID Stuff */ 1239 /* OID Stuff */
1273 printf (" %s\n", "-o, --oid=OID(s)"); 1240 printf(" %s\n", "-o, --oid=OID(s)");
1274 printf (" %s\n", _("Object identifier(s) or SNMP variables whose value you wish to query")); 1241 printf(" %s\n", _("Object identifier(s) or SNMP variables whose value you wish to query"));
1275 printf (" %s\n", "-m, --miblist=STRING"); 1242 printf(" %s\n", "-m, --miblist=STRING");
1276 printf (" %s\n", _("List of MIBS to be loaded (default = none if using numeric OIDs or 'ALL'")); 1243 printf(" %s\n", _("List of MIBS to be loaded (default = none if using numeric OIDs or 'ALL'"));
1277 printf (" %s\n", _("for symbolic OIDs.)")); 1244 printf(" %s\n", _("for symbolic OIDs.)"));
1278 printf (" %s\n", "-d, --delimiter=STRING"); 1245 printf(" %s\n", "-d, --delimiter=STRING");
1279 printf (" %s \"%s\"\n", _("Delimiter to use when parsing returned data. Default is"), DEFAULT_DELIMITER); 1246 printf(" %s \"%s\"\n", _("Delimiter to use when parsing returned data. Default is"), DEFAULT_DELIMITER);
1280 printf (" %s\n", _("Any data on the right hand side of the delimiter is considered")); 1247 printf(" %s\n", _("Any data on the right hand side of the delimiter is considered"));
1281 printf (" %s\n", _("to be the data that should be used in the evaluation.")); 1248 printf(" %s\n", _("to be the data that should be used in the evaluation."));
1282 printf (" %s\n", "-z, --nulloid=#"); 1249 printf(" %s\n", "-z, --nulloid=#");
1283 printf (" %s\n", _("If the check returns a 0 length string or NULL value")); 1250 printf(" %s\n", _("If the check returns a 0 length string or NULL value"));
1284 printf (" %s\n", _("This option allows you to choose what status you want it to exit")); 1251 printf(" %s\n", _("This option allows you to choose what status you want it to exit"));
1285 printf (" %s\n", _("Excluding this option renders the default exit of 3(STATE_UNKNOWN)")); 1252 printf(" %s\n", _("Excluding this option renders the default exit of 3(STATE_UNKNOWN)"));
1286 printf (" %s\n", _("0 = OK")); 1253 printf(" %s\n", _("0 = OK"));
1287 printf (" %s\n", _("1 = WARNING")); 1254 printf(" %s\n", _("1 = WARNING"));
1288 printf (" %s\n", _("2 = CRITICAL")); 1255 printf(" %s\n", _("2 = CRITICAL"));
1289 printf (" %s\n", _("3 = UNKNOWN")); 1256 printf(" %s\n", _("3 = UNKNOWN"));
1290 1257
1291 /* Tests Against Integers */ 1258 /* Tests Against Integers */
1292 printf (" %s\n", "-w, --warning=THRESHOLD(s)"); 1259 printf(" %s\n", "-w, --warning=THRESHOLD(s)");
1293 printf (" %s\n", _("Warning threshold range(s)")); 1260 printf(" %s\n", _("Warning threshold range(s)"));
1294 printf (" %s\n", "-c, --critical=THRESHOLD(s)"); 1261 printf(" %s\n", "-c, --critical=THRESHOLD(s)");
1295 printf (" %s\n", _("Critical threshold range(s)")); 1262 printf(" %s\n", _("Critical threshold range(s)"));
1296 printf (" %s\n", "--rate"); 1263 printf(" %s\n", "--rate");
1297 printf (" %s\n", _("Enable rate calculation. See 'Rate Calculation' below")); 1264 printf(" %s\n", _("Enable rate calculation. See 'Rate Calculation' below"));
1298 printf (" %s\n", "--rate-multiplier"); 1265 printf(" %s\n", "--rate-multiplier");
1299 printf (" %s\n", _("Converts rate per second. For example, set to 60 to convert to per minute")); 1266 printf(" %s\n", _("Converts rate per second. For example, set to 60 to convert to per minute"));
1300 printf (" %s\n", "--offset=OFFSET"); 1267 printf(" %s\n", "--offset=OFFSET");
1301 printf (" %s\n", _("Add/subtract the specified OFFSET to numeric sensor data")); 1268 printf(" %s\n", _("Add/subtract the specified OFFSET to numeric sensor data"));
1302 1269
1303 /* Tests Against Strings */ 1270 /* Tests Against Strings */
1304 printf (" %s\n", "-s, --string=STRING"); 1271 printf(" %s\n", "-s, --string=STRING");
1305 printf (" %s\n", _("Return OK state (for that OID) if STRING is an exact match")); 1272 printf(" %s\n", _("Return OK state (for that OID) if STRING is an exact match"));
1306 printf (" %s\n", "-r, --ereg=REGEX"); 1273 printf(" %s\n", "-r, --ereg=REGEX");
1307 printf (" %s\n", _("Return OK state (for that OID) if extended regular expression REGEX matches")); 1274 printf(" %s\n", _("Return OK state (for that OID) if extended regular expression REGEX matches"));
1308 printf (" %s\n", "-R, --eregi=REGEX"); 1275 printf(" %s\n", "-R, --eregi=REGEX");
1309 printf (" %s\n", _("Return OK state (for that OID) if case-insensitive extended REGEX matches")); 1276 printf(" %s\n", _("Return OK state (for that OID) if case-insensitive extended REGEX matches"));
1310 printf (" %s\n", "--invert-search"); 1277 printf(" %s\n", "--invert-search");
1311 printf (" %s\n", _("Invert search result (CRITICAL if found)")); 1278 printf(" %s\n", _("Invert search result (CRITICAL if found)"));
1312 1279
1313 /* Output Formatting */ 1280 /* Output Formatting */
1314 printf (" %s\n", "-l, --label=STRING"); 1281 printf(" %s\n", "-l, --label=STRING");
1315 printf (" %s\n", _("Prefix label for output from plugin")); 1282 printf(" %s\n", _("Prefix label for output from plugin"));
1316 printf (" %s\n", "-u, --units=STRING"); 1283 printf(" %s\n", "-u, --units=STRING");
1317 printf (" %s\n", _("Units label(s) for output data (e.g., 'sec.').")); 1284 printf(" %s\n", _("Units label(s) for output data (e.g., 'sec.')."));
1318 printf (" %s\n", "-D, --output-delimiter=STRING"); 1285 printf(" %s\n", "-D, --output-delimiter=STRING");
1319 printf (" %s\n", _("Separates output on multiple OID requests")); 1286 printf(" %s\n", _("Separates output on multiple OID requests"));
1320 printf (" %s\n", "-M, --multiplier=FLOAT"); 1287 printf(" %s\n", "-M, --multiplier=FLOAT");
1321 printf (" %s\n", _("Multiplies current value, 0 < n < 1 works as divider, defaults to 1")); 1288 printf(" %s\n", _("Multiplies current value, 0 < n < 1 works as divider, defaults to 1"));
1322 printf (" %s\n", "-f, --fmtstr=STRING"); 1289 printf(" %s\n", "-f, --fmtstr=STRING");
1323 printf (" %s\n", _("C-style format string for float values (see option -M)")); 1290 printf(" %s\n", _("C-style format string for float values (see option -M)"));
1324 1291
1325 printf (UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); 1292 printf(UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
1326 printf (" %s\n", _("NOTE the final timeout value is calculated using this formula: timeout_interval * retries + 5")); 1293 printf(" %s\n", _("NOTE the final timeout value is calculated using this formula: timeout_interval * retries + 5"));
1327 printf (" %s\n", "-e, --retries=INTEGER"); 1294 printf(" %s\n", "-e, --retries=INTEGER");
1328 printf (" %s%i\n", _("Number of retries to be used in the requests, default: "), DEFAULT_RETRIES); 1295 printf(" %s%i\n", _("Number of retries to be used in the requests, default: "), DEFAULT_RETRIES);
1329 1296
1330 printf (" %s\n", "-O, --perf-oids"); 1297 printf(" %s\n", "-O, --perf-oids");
1331 printf (" %s\n", _("Label performance data with OIDs instead of --label's")); 1298 printf(" %s\n", _("Label performance data with OIDs instead of --label's"));
1332 1299
1333 printf (" %s\n", "--ignore-mib-parsing-errors"); 1300 printf(" %s\n", "--ignore-mib-parsing-errors");
1334 printf (" %s\n", _("Tell snmpget to not print errors encountered when parsing MIB files")); 1301 printf(" %s\n", _("Tell snmpget to not print errors encountered when parsing MIB files"));
1335 1302
1336 printf (UT_VERBOSE); 1303 printf(UT_VERBOSE);
1337 1304
1338 printf ("\n"); 1305 printf("\n");
1339 printf ("%s\n", _("This plugin uses the 'snmpget' command included with the NET-SNMP package.")); 1306 printf("%s\n", _("This plugin uses the 'snmpget' command included with the NET-SNMP package."));
1340 printf ("%s\n", _("if you don't have the package installed, you will need to download it from")); 1307 printf("%s\n", _("if you don't have the package installed, you will need to download it from"));
1341 printf ("%s\n", _("http://net-snmp.sourceforge.net before you can use this plugin.")); 1308 printf("%s\n", _("http://net-snmp.sourceforge.net before you can use this plugin."));
1342 1309
1343 printf ("\n"); 1310 printf("\n");
1344 printf ("%s\n", _("Notes:")); 1311 printf("%s\n", _("Notes:"));
1345 printf (" %s\n", _("- Multiple OIDs (and labels) may be indicated by a comma or space-delimited ")); 1312 printf(" %s\n", _("- Multiple OIDs (and labels) may be indicated by a comma or space-delimited "));
1346 printf (" %s\n", _("list (lists with internal spaces must be quoted).")); 1313 printf(" %s\n", _("list (lists with internal spaces must be quoted)."));
1347 1314
1348 printf(" -%s", UT_THRESHOLDS_NOTES); 1315 printf(" -%s", UT_THRESHOLDS_NOTES);
1349 1316
1350 printf (" %s\n", _("- When checking multiple OIDs, separate ranges by commas like '-w 1:10,1:,:20'")); 1317 printf(" %s\n", _("- When checking multiple OIDs, separate ranges by commas like '-w 1:10,1:,:20'"));
1351 printf (" %s\n", _("- Note that only one string and one regex may be checked at present")); 1318 printf(" %s\n", _("- Note that only one string and one regex may be checked at present"));
1352 printf (" %s\n", _("- All evaluation methods other than PR, STR, and SUBSTR expect that the value")); 1319 printf(" %s\n", _("- All evaluation methods other than PR, STR, and SUBSTR expect that the value"));
1353 printf (" %s\n", _("returned from the SNMP query is an unsigned integer.")); 1320 printf(" %s\n", _("returned from the SNMP query is an unsigned integer."));
1354 1321
1355 printf("\n"); 1322 printf("\n");
1356 printf("%s\n", _("Rate Calculation:")); 1323 printf("%s\n", _("Rate Calculation:"));
@@ -1362,19 +1329,15 @@ print_help (void)
1362 printf(" %s\n", _("The state is uniquely determined by the arguments to the plugin, so")); 1329 printf(" %s\n", _("The state is uniquely determined by the arguments to the plugin, so"));
1363 printf(" %s\n", _("changing the arguments will create a new state file.")); 1330 printf(" %s\n", _("changing the arguments will create a new state file."));
1364 1331
1365 printf (UT_SUPPORT); 1332 printf(UT_SUPPORT);
1366} 1333}
1367 1334
1368 1335void print_usage(void) {
1369 1336 printf("%s\n", _("Usage:"));
1370void 1337 printf("%s -H <ip_address> -o <OID> [-w warn_range] [-c crit_range]\n", progname);
1371print_usage (void) 1338 printf("[-C community] [-s string] [-r regex] [-R regexi] [-t timeout] [-e retries]\n");
1372{ 1339 printf("[-l label] [-u units] [-p port-number] [-d delimiter] [-D output-delimiter]\n");
1373 printf ("%s\n", _("Usage:")); 1340 printf("[-m miblist] [-P snmp version] [-N context] [-L seclevel] [-U secname]\n");
1374 printf ("%s -H <ip_address> -o <OID> [-w warn_range] [-c crit_range]\n",progname); 1341 printf("[-a authproto] [-A authpasswd] [-x privproto] [-X privpasswd] [-4|6]\n");
1375 printf ("[-C community] [-s string] [-r regex] [-R regexi] [-t timeout] [-e retries]\n"); 1342 printf("[-M multiplier [-f format]]\n");
1376 printf ("[-l label] [-u units] [-p port-number] [-d delimiter] [-D output-delimiter]\n");
1377 printf ("[-m miblist] [-P snmp version] [-N context] [-L seclevel] [-U secname]\n");
1378 printf ("[-a authproto] [-A authpasswd] [-x privproto] [-X privpasswd] [-4|6]\n");
1379 printf ("[-M multiplier [-f format]]\n");
1380} 1343}
diff --git a/plugins/check_ssh.c b/plugins/check_ssh.c
index 4eb746cb..42a88cf9 100644
--- a/plugins/check_ssh.c
+++ b/plugins/check_ssh.c
@@ -1,144 +1,132 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring check_ssh plugin 3 * Monitoring check_ssh plugin
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 2000-2007 Monitoring Plugins Development Team 6 * Copyright (c) 2000-2024 Monitoring Plugins Development Team
7* 7 *
8* Description: 8 * Description:
9* 9 *
10* This file contains the check_ssh plugin 10 * This file contains the check_ssh plugin
11* 11 *
12* Try to connect to an SSH server at specified server and port 12 * Try to connect to an SSH server at specified server and port
13* 13 *
14* 14 *
15* This program is free software: you can redistribute it and/or modify 15 * This program is free software: you can redistribute it and/or modify
16* it under the terms of the GNU General Public License as published by 16 * it under the terms of the GNU General Public License as published by
17* the Free Software Foundation, either version 3 of the License, or 17 * the Free Software Foundation, either version 3 of the License, or
18* (at your option) any later version. 18 * (at your option) any later version.
19* 19 *
20* This program is distributed in the hope that it will be useful, 20 * This program is distributed in the hope that it will be useful,
21* but WITHOUT ANY WARRANTY; without even the implied warranty of 21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23* GNU General Public License for more details. 23 * GNU General Public License for more details.
24* 24 *
25* You should have received a copy of the GNU General Public License 25 * You should have received a copy of the GNU General Public License
26* along with this program. If not, see <http://www.gnu.org/licenses/>. 26 * along with this program. If not, see <http://www.gnu.org/licenses/>.
27* 27 *
28* 28 *
29*****************************************************************************/ 29 *****************************************************************************/
30 30
31const char *progname = "check_ssh"; 31const char *progname = "check_ssh";
32const char *copyright = "2000-2007"; 32const char *copyright = "2000-2024";
33const char *email = "devel@monitoring-plugins.org"; 33const char *email = "devel@monitoring-plugins.org";
34 34
35#include "common.h" 35#include "./common.h"
36#include "netutils.h" 36#include "./netutils.h"
37#include "utils.h" 37#include "utils.h"
38 38
39#ifndef MSG_DONTWAIT 39#ifndef MSG_DONTWAIT
40#define MSG_DONTWAIT 0 40# define MSG_DONTWAIT 0
41#endif 41#endif
42 42
43#define SSH_DFL_PORT 22 43#define SSH_DFL_PORT 22
44#define BUFF_SZ 256 44#define BUFF_SZ 256
45 45
46int port = -1; 46static int port = -1;
47char *server_name = NULL; 47static char *server_name = NULL;
48char *remote_version = NULL; 48static char *remote_version = NULL;
49char *remote_protocol = NULL; 49static char *remote_protocol = NULL;
50bool verbose = false; 50static bool verbose = false;
51 51
52int process_arguments (int, char **); 52static int process_arguments(int /*argc*/, char ** /*argv*/);
53int validate_arguments (void); 53static int validate_arguments(void);
54void print_help (void); 54static void print_help(void);
55void print_usage (void); 55void print_usage(void);
56 56
57int ssh_connect (char *haddr, int hport, char *remote_version, char *remote_protocol); 57static int ssh_connect(char *haddr, int hport, char *remote_version, char *remote_protocol);
58 58
59 59int main(int argc, char **argv) {
60int 60 setlocale(LC_ALL, "");
61main (int argc, char **argv) 61 bindtextdomain(PACKAGE, LOCALEDIR);
62{ 62 textdomain(PACKAGE);
63 int result = STATE_UNKNOWN;
64
65 setlocale (LC_ALL, "");
66 bindtextdomain (PACKAGE, LOCALEDIR);
67 textdomain (PACKAGE);
68 63
69 /* Parse extra opts if any */ 64 /* Parse extra opts if any */
70 argv=np_extra_opts (&argc, argv, progname); 65 argv = np_extra_opts(&argc, argv, progname);
71 66
72 if (process_arguments (argc, argv) == ERROR) 67 if (process_arguments(argc, argv) == ERROR)
73 usage4 (_("Could not parse arguments")); 68 usage4(_("Could not parse arguments"));
74 69
75 /* initialize alarm signal handling */ 70 /* initialize alarm signal handling */
76 signal (SIGALRM, socket_timeout_alarm_handler); 71 signal(SIGALRM, socket_timeout_alarm_handler);
77 72
78 alarm (socket_timeout); 73 alarm(socket_timeout);
79 74
80 /* ssh_connect exits if error is found */ 75 /* ssh_connect exits if error is found */
81 result = ssh_connect (server_name, port, remote_version, remote_protocol); 76 int result = ssh_connect(server_name, port, remote_version, remote_protocol);
82 77
83 alarm (0); 78 alarm(0);
84 79
85 return (result); 80 return (result);
86} 81}
87 82
88
89
90/* process command-line arguments */ 83/* process command-line arguments */
91int 84int process_arguments(int argc, char **argv) {
92process_arguments (int argc, char **argv) 85 static struct option longopts[] = {{"help", no_argument, 0, 'h'},
93{ 86 {"version", no_argument, 0, 'V'},
94 int c; 87 {"host", required_argument, 0, 'H'}, /* backward compatibility */
95 88 {"hostname", required_argument, 0, 'H'},
96 int option = 0; 89 {"port", required_argument, 0, 'p'},
97 static struct option longopts[] = { 90 {"use-ipv4", no_argument, 0, '4'},
98 {"help", no_argument, 0, 'h'}, 91 {"use-ipv6", no_argument, 0, '6'},
99 {"version", no_argument, 0, 'V'}, 92 {"timeout", required_argument, 0, 't'},
100 {"host", required_argument, 0, 'H'}, /* backward compatibility */ 93 {"verbose", no_argument, 0, 'v'},
101 {"hostname", required_argument, 0, 'H'}, 94 {"remote-version", required_argument, 0, 'r'},
102 {"port", required_argument, 0, 'p'}, 95 {"remote-protocol", required_argument, 0, 'P'},
103 {"use-ipv4", no_argument, 0, '4'}, 96 {0, 0, 0, 0}};
104 {"use-ipv6", no_argument, 0, '6'},
105 {"timeout", required_argument, 0, 't'},
106 {"verbose", no_argument, 0, 'v'},
107 {"remote-version", required_argument, 0, 'r'},
108 {"remote-protcol", required_argument, 0, 'P'},
109 {0, 0, 0, 0}
110 };
111 97
112 if (argc < 2) 98 if (argc < 2)
113 return ERROR; 99 return ERROR;
114 100
115 for (c = 1; c < argc; c++) 101 for (int i = 1; i < argc; i++)
116 if (strcmp ("-to", argv[c]) == 0) 102 if (strcmp("-to", argv[i]) == 0)
117 strcpy (argv[c], "-t"); 103 strcpy(argv[i], "-t");
118 104
119 while (1) { 105 int option_char;
120 c = getopt_long (argc, argv, "+Vhv46t:r:H:p:P:", longopts, &option); 106 while (true) {
107 int option = 0;
108 option_char = getopt_long(argc, argv, "+Vhv46t:r:H:p:P:", longopts, &option);
121 109
122 if (c == -1 || c == EOF) 110 if (option_char == -1 || option_char == EOF)
123 break; 111 break;
124 112
125 switch (c) { 113 switch (option_char) {
126 case '?': /* help */ 114 case '?': /* help */
127 usage5 (); 115 usage5();
128 case 'V': /* version */ 116 case 'V': /* version */
129 print_revision (progname, NP_VERSION); 117 print_revision(progname, NP_VERSION);
130 exit (STATE_UNKNOWN); 118 exit(STATE_UNKNOWN);
131 case 'h': /* help */ 119 case 'h': /* help */
132 print_help (); 120 print_help();
133 exit (STATE_UNKNOWN); 121 exit(STATE_UNKNOWN);
134 case 'v': /* verbose */ 122 case 'v': /* verbose */
135 verbose = true; 123 verbose = true;
136 break; 124 break;
137 case 't': /* timeout period */ 125 case 't': /* timeout period */
138 if (!is_integer (optarg)) 126 if (!is_integer(optarg))
139 usage2 (_("Timeout interval must be a positive integer"), optarg); 127 usage2(_("Timeout interval must be a positive integer"), optarg);
140 else 128 else
141 socket_timeout = atoi (optarg); 129 socket_timeout = atoi(optarg);
142 break; 130 break;
143 case '4': 131 case '4':
144 address_family = AF_INET; 132 address_family = AF_INET;
@@ -147,181 +135,227 @@ process_arguments (int argc, char **argv)
147#ifdef USE_IPV6 135#ifdef USE_IPV6
148 address_family = AF_INET6; 136 address_family = AF_INET6;
149#else 137#else
150 usage4 (_("IPv6 support not available")); 138 usage4(_("IPv6 support not available"));
151#endif 139#endif
152 break; 140 break;
153 case 'r': /* remote version */ 141 case 'r': /* remote version */
154 remote_version = optarg; 142 remote_version = optarg;
155 break; 143 break;
156 case 'P': /* remote version */ 144 case 'P': /* remote version */
157 remote_protocol = optarg; 145 remote_protocol = optarg;
158 break; 146 break;
159 case 'H': /* host */ 147 case 'H': /* host */
160 if (!is_host (optarg)) 148 if (!is_host(optarg))
161 usage2 (_("Invalid hostname/address"), optarg); 149 usage2(_("Invalid hostname/address"), optarg);
162 server_name = optarg; 150 server_name = optarg;
163 break; 151 break;
164 case 'p': /* port */ 152 case 'p': /* port */
165 if (is_intpos (optarg)) { 153 if (is_intpos(optarg)) {
166 port = atoi (optarg); 154 port = atoi(optarg);
167 } 155 } else {
168 else { 156 usage2(_("Port number must be a positive integer"), optarg);
169 usage2 (_("Port number must be a positive integer"), optarg);
170 } 157 }
171 } 158 }
172 } 159 }
173 160
174 c = optind; 161 option_char = optind;
175 if (server_name == NULL && c < argc) { 162 if (server_name == NULL && option_char < argc) {
176 if (is_host (argv[c])) { 163 if (is_host(argv[option_char])) {
177 server_name = argv[c++]; 164 server_name = argv[option_char++];
178 } 165 }
179 } 166 }
180 167
181 if (port == -1 && c < argc) { 168 if (port == -1 && option_char < argc) {
182 if (is_intpos (argv[c])) { 169 if (is_intpos(argv[option_char])) {
183 port = atoi (argv[c++]); 170 port = atoi(argv[option_char++]);
184 } 171 } else {
185 else { 172 print_usage();
186 print_usage (); 173 exit(STATE_UNKNOWN);
187 exit (STATE_UNKNOWN);
188 } 174 }
189 } 175 }
190 176
191 return validate_arguments (); 177 return validate_arguments();
192} 178}
193 179
194int 180int validate_arguments(void) {
195validate_arguments (void)
196{
197 if (server_name == NULL) 181 if (server_name == NULL)
198 return ERROR; 182 return ERROR;
199 if (port == -1) /* funky, but allows -p to override stray integer in args */ 183 if (port == -1) /* funky, but allows -p to override stray integer in args */
200 port = SSH_DFL_PORT; 184 port = SSH_DFL_PORT;
201 return OK; 185 return OK;
202} 186}
203 187
204
205/************************************************************************ 188/************************************************************************
206* 189 *
207* Try to connect to SSH server at specified server and port 190 * Try to connect to SSH server at specified server and port
208* 191 *
209*-----------------------------------------------------------------------*/ 192 *-----------------------------------------------------------------------*/
210
211
212int
213ssh_connect (char *haddr, int hport, char *remote_version, char *remote_protocol)
214{
215 int sd;
216 int result;
217 char *output = NULL;
218 char *buffer = NULL;
219 char *ssh_proto = NULL;
220 char *ssh_server = NULL;
221 static char *rev_no = VERSION;
222 struct timeval tv;
223 double elapsed_time;
224 193
194int ssh_connect(char *haddr, int hport, char *remote_version, char *remote_protocol) {
195 struct timeval tv;
225 gettimeofday(&tv, NULL); 196 gettimeofday(&tv, NULL);
226 197
227 result = my_tcp_connect (haddr, hport, &sd); 198 int socket;
199 int result = my_tcp_connect(haddr, hport, &socket);
228 200
229 if (result != STATE_OK) 201 if (result != STATE_OK)
230 return result; 202 return result;
231 203
232 output = (char *) malloc (BUFF_SZ + 1); 204 char *output = (char *)calloc(BUFF_SZ + 1, sizeof(char));
233 memset (output, 0, BUFF_SZ + 1); 205 char *buffer = NULL;
234 recv (sd, output, BUFF_SZ, 0); 206 ssize_t recv_ret = 0;
235 if (strncmp (output, "SSH", 3)) { 207 char *version_control_string = NULL;
236 printf (_("Server answer: %s"), output); 208 ssize_t byte_offset = 0;
237 close(sd); 209 while ((version_control_string == NULL) && (recv_ret = recv(socket, output + byte_offset, BUFF_SZ - byte_offset, 0) > 0)) {
238 exit (STATE_CRITICAL); 210
239 } 211 if (strchr(output, '\n')) { /* we've got at least one full line, start parsing*/
240 else { 212 byte_offset = 0;
241 strip (output); 213
242 if (verbose) 214 char *index = NULL;
243 printf ("%s\n", output); 215 int len = 0;
244 ssh_proto = output + 4; 216 while ((index = strchr(output + byte_offset, '\n')) != NULL) {
245 ssh_server = ssh_proto + strspn (ssh_proto, "-0123456789. "); 217 /*Partition the buffer so that this line is a separate string,
246 ssh_proto[strspn (ssh_proto, "0123456789. ")] = 0; 218 * by replacing the newline with NUL*/
247 219 output[(index - output)] = '\0';
248 xasprintf (&buffer, "SSH-%s-check_ssh_%s\r\n", ssh_proto, rev_no); 220 len = strlen(output + byte_offset);
249 send (sd, buffer, strlen (buffer), MSG_DONTWAIT); 221
250 if (verbose) 222 if ((len >= 4) && (strncmp(output + byte_offset, "SSH-", 4) == 0)) {
251 printf ("%s\n", buffer); 223 /*if the string starts with SSH-, this _should_ be a valid version control string*/
252 224 version_control_string = output + byte_offset;
253 if (remote_version && strcmp(remote_version, ssh_server)) { 225 break;
254 printf 226 }
255 (_("SSH CRITICAL - %s (protocol %s) version mismatch, expected '%s'\n"), 227
256 ssh_server, ssh_proto, remote_version); 228 /*the start of the next line (if one exists) will be after the current one (+ NUL)*/
257 close(sd); 229 byte_offset += (len + 1);
258 exit (STATE_CRITICAL); 230 }
259 }
260 231
261 if (remote_protocol && strcmp(remote_protocol, ssh_proto)) { 232 if (version_control_string == NULL) {
262 printf 233 /* move unconsumed data to beginning of buffer, null rest */
263 (_("SSH CRITICAL - %s (protocol %s) protocol version mismatch, expected '%s'\n"), 234 memmove((void *)output, (void *)(output + byte_offset + 1), BUFF_SZ - len + 1);
264 ssh_server, ssh_proto, remote_protocol); 235 memset(output + byte_offset + 1, 0, BUFF_SZ - byte_offset + 1);
265 close(sd); 236
266 exit (STATE_CRITICAL); 237 /*start reading from end of current line chunk on next recv*/
238 byte_offset = strlen(output);
239 }
240 } else {
241 byte_offset += recv_ret;
267 } 242 }
243 }
268 244
269 elapsed_time = (double)deltime(tv) / 1.0e6; 245 if (recv_ret < 0) {
246 printf("SSH CRITICAL - %s", strerror(errno));
247 exit(STATE_CRITICAL);
248 }
270 249
271 printf 250 if (version_control_string == NULL) {
272 (_("SSH OK - %s (protocol %s) | %s\n"), 251 printf("SSH CRITICAL - No version control string received");
273 ssh_server, ssh_proto, fperfdata("time", elapsed_time, "s", 252 exit(STATE_CRITICAL);
274 false, 0, false, 0, true, 0, true, (int)socket_timeout));
275 close(sd);
276 exit (STATE_OK);
277 } 253 }
278} 254 /*
255 * "When the connection has been established, both sides MUST send an
256 * identification string. This identification string MUST be
257 *
258 * SSH-protoversion-softwareversion SP comments CR LF"
259 * - RFC 4253:4.2
260 */
261 strip(version_control_string);
262 if (verbose)
263 printf("%s\n", version_control_string);
264
265 char *ssh_proto = version_control_string + 4;
266
267 /*
268 * We assume the protoversion is of the form Major.Minor, although
269 * this is not _strictly_ required. See
270 *
271 * "Both the 'protoversion' and 'softwareversion' strings MUST consist of
272 * printable US-ASCII characters, with the exception of whitespace
273 * characters and the minus sign (-)"
274 * - RFC 4253:4.2
275 * and,
276 *
277 * "As stated earlier, the 'protoversion' specified for this protocol is
278 * "2.0". Earlier versions of this protocol have not been formally
279 * documented, but it is widely known that they use 'protoversion' of
280 * "1.x" (e.g., "1.5" or "1.3")."
281 * - RFC 4253:5
282 */
283 char *ssh_server = ssh_proto + strspn(ssh_proto, "0123456789.") + 1; /* (+1 for the '-' separating protoversion from softwareversion) */
284
285 /* If there's a space in the version string, whatever's after the space is a comment
286 * (which is NOT part of the server name/version)*/
287 char *tmp = strchr(ssh_server, ' ');
288 if (tmp) {
289 ssh_server[tmp - ssh_server] = '\0';
290 }
291 if (strlen(ssh_proto) == 0 || strlen(ssh_server) == 0) {
292 printf(_("SSH CRITICAL - Invalid protocol version control string %s\n"), version_control_string);
293 exit(STATE_CRITICAL);
294 }
295 ssh_proto[strspn(ssh_proto, "0123456789. ")] = 0;
279 296
297 static char *rev_no = VERSION;
298 xasprintf(&buffer, "SSH-%s-check_ssh_%s\r\n", ssh_proto, rev_no);
299 send(socket, buffer, strlen(buffer), MSG_DONTWAIT);
300 if (verbose)
301 printf("%s\n", buffer);
302
303 if (remote_version && strcmp(remote_version, ssh_server)) {
304 printf(_("SSH CRITICAL - %s (protocol %s) version mismatch, expected '%s'\n"), ssh_server, ssh_proto, remote_version);
305 close(socket);
306 exit(STATE_CRITICAL);
307 }
308
309 double elapsed_time = (double)deltime(tv) / 1.0e6;
310 if (remote_protocol && strcmp(remote_protocol, ssh_proto)) {
311 printf(_("SSH CRITICAL - %s (protocol %s) protocol version mismatch, expected '%s' | %s\n"), ssh_server, ssh_proto, remote_protocol,
312 fperfdata("time", elapsed_time, "s", false, 0, false, 0, true, 0, true, (int)socket_timeout));
313 close(socket);
314 exit(STATE_CRITICAL);
315 }
280 316
317 printf(_("SSH OK - %s (protocol %s) | %s\n"), ssh_server, ssh_proto,
318 fperfdata("time", elapsed_time, "s", false, 0, false, 0, true, 0, true, (int)socket_timeout));
319 close(socket);
320 exit(STATE_OK);
321}
281 322
282void 323void print_help(void) {
283print_help (void)
284{
285 char *myport; 324 char *myport;
286 xasprintf (&myport, "%d", SSH_DFL_PORT); 325 xasprintf(&myport, "%d", SSH_DFL_PORT);
287 326
288 print_revision (progname, NP_VERSION); 327 print_revision(progname, NP_VERSION);
289 328
290 printf ("Copyright (c) 1999 Remi Paulmier <remi@sinfomic.fr>\n"); 329 printf("Copyright (c) 1999 Remi Paulmier <remi@sinfomic.fr>\n");
291 printf (COPYRIGHT, copyright, email); 330 printf(COPYRIGHT, copyright, email);
292 331
293 printf ("%s\n", _("Try to connect to an SSH server at specified server and port")); 332 printf("%s\n", _("Try to connect to an SSH server at specified server and port"));
294 333
295 printf ("\n\n"); 334 printf("\n\n");
296 335
297 print_usage (); 336 print_usage();
298 337
299 printf (UT_HELP_VRSN); 338 printf(UT_HELP_VRSN);
300 printf (UT_EXTRA_OPTS); 339 printf(UT_EXTRA_OPTS);
301 340
302 printf (UT_HOST_PORT, 'p', myport); 341 printf(UT_HOST_PORT, 'p', myport);
303 342
304 printf (UT_IPv46); 343 printf(UT_IPv46);
305 344
306 printf (UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); 345 printf(UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
307 346
308 printf (" %s\n", "-r, --remote-version=STRING"); 347 printf(" %s\n", "-r, --remote-version=STRING");
309 printf (" %s\n", _("Alert if string doesn't match expected server version (ex: OpenSSH_3.9p1)")); 348 printf(" %s\n", _("Alert if string doesn't match expected server version (ex: OpenSSH_3.9p1)"));
310 349
311 printf (" %s\n", "-P, --remote-protocol=STRING"); 350 printf(" %s\n", "-P, --remote-protocol=STRING");
312 printf (" %s\n", _("Alert if protocol doesn't match expected protocol version (ex: 2.0)")); 351 printf(" %s\n", _("Alert if protocol doesn't match expected protocol version (ex: 2.0)"));
313 352
314 printf (UT_VERBOSE); 353 printf(UT_VERBOSE);
315 354
316 printf (UT_SUPPORT); 355 printf(UT_SUPPORT);
317} 356}
318 357
319 358void print_usage(void) {
320 359 printf("%s\n", _("Usage:"));
321void 360 printf("%s [-4|-6] [-t <timeout>] [-r <remote version>] [-p <port>] <host>\n", progname);
322print_usage (void)
323{
324 printf ("%s\n", _("Usage:"));
325 printf ("%s [-4|-6] [-t <timeout>] [-r <remote version>] [-p <port>] <host>\n", progname);
326} 361}
327
diff --git a/plugins/check_swap.c b/plugins/check_swap.c
index f34b0514..4e3471b6 100644
--- a/plugins/check_swap.c
+++ b/plugins/check_swap.c
@@ -4,7 +4,7 @@
4 * 4 *
5 * License: GPL 5 * License: GPL
6 * Copyright (c) 2000 Karl DeBisschop (kdebisschop@users.sourceforge.net) 6 * Copyright (c) 2000 Karl DeBisschop (kdebisschop@users.sourceforge.net)
7 * Copyright (c) 2000-2023 Monitoring Plugins Development Team 7 * Copyright (c) 2000-2024 Monitoring Plugins Development Team
8 * 8 *
9 * Description: 9 * Description:
10 * 10 *
@@ -27,21 +27,21 @@
27 * 27 *
28 *****************************************************************************/ 28 *****************************************************************************/
29 29
30#include <stdint.h>
30const char *progname = "check_swap"; 31const char *progname = "check_swap";
31const char *copyright = "2000-2023"; 32const char *copyright = "2000-2024";
32const char *email = "devel@monitoring-plugins.org"; 33const char *email = "devel@monitoring-plugins.org";
33 34
34
35#ifdef HAVE_DECL_SWAPCTL 35#ifdef HAVE_DECL_SWAPCTL
36#ifdef HAVE_SYS_PARAM_H 36# ifdef HAVE_SYS_PARAM_H
37#include <sys/param.h> 37# include <sys/param.h>
38#endif 38# endif
39#ifdef HAVE_SYS_SWAP_H 39# ifdef HAVE_SYS_SWAP_H
40#include <sys/swap.h> 40# include <sys/swap.h>
41#endif 41# endif
42#ifdef HAVE_SYS_STAT_H 42# ifdef HAVE_SYS_STAT_H
43#include <sys/stat.h> 43# include <sys/stat.h>
44#endif 44# endif
45#endif 45#endif
46 46
47#include "./check_swap.d/check_swap.h" 47#include "./check_swap.d/check_swap.h"
@@ -52,11 +52,13 @@ typedef struct {
52 swap_config config; 52 swap_config config;
53} swap_config_wrapper; 53} swap_config_wrapper;
54 54
55swap_config_wrapper process_arguments(swap_config_wrapper config, int argc, 55static swap_config_wrapper process_arguments(int argc, char **argv);
56 char **argv); 56void print_usage(void);
57void print_usage(); 57static void print_help(swap_config /*config*/);
58void print_help(swap_config);
59 58
59static int verbose;
60
61#define HUNDRED_PERCENT 100
60 62
61int main(int argc, char **argv) { 63int main(int argc, char **argv) {
62 setlocale(LC_ALL, ""); 64 setlocale(LC_ALL, "");
@@ -69,11 +71,7 @@ int main(int argc, char **argv) {
69 /* Parse extra opts if any */ 71 /* Parse extra opts if any */
70 argv = np_extra_opts(&argc, argv, progname); 72 argv = np_extra_opts(&argc, argv, progname);
71 73
72 swap_config_wrapper tmp = {.errorcode = OK}; 74 swap_config_wrapper tmp = process_arguments(argc, argv);
73
74 tmp.config = swap_config_init();
75
76 tmp = process_arguments(tmp, argc, argv);
77 75
78 if (tmp.errorcode != OK) { 76 if (tmp.errorcode != OK) {
79 usage4(_("Could not parse arguments")); 77 usage4(_("Could not parse arguments"));
@@ -87,8 +85,7 @@ int main(int argc, char **argv) {
87 85
88 /* if total_swap_mb == 0, let's not divide by 0 */ 86 /* if total_swap_mb == 0, let's not divide by 0 */
89 if (data.metrics.total != 0) { 87 if (data.metrics.total != 0) {
90 percent_used = 88 percent_used = HUNDRED_PERCENT * ((double)data.metrics.used) / ((double)data.metrics.total);
91 100 * ((double)data.metrics.used) / ((double)data.metrics.total);
92 } else { 89 } else {
93 printf(_("SWAP %s - Swap is either disabled, not present, or of zero " 90 printf(_("SWAP %s - Swap is either disabled, not present, or of zero "
94 "size."), 91 "size."),
@@ -96,77 +93,97 @@ int main(int argc, char **argv) {
96 exit(config.no_swap_state); 93 exit(config.no_swap_state);
97 } 94 }
98 95
99 if (config.verbose) { 96 if (verbose) {
100 printf("Computed usage percentage: %g\n", percent_used); 97 printf("Computed usage percentage: %g\n", percent_used);
101 } 98 }
102 99
103 uint64_t warn_print = config.warn.value; 100 uint64_t warn_print = config.warn.value;
104 if (config.warn.is_percentage) { 101 if (config.warn.is_percentage) {
105 warn_print = config.warn.value * (data.metrics.total / 100); 102 warn_print = config.warn.value * (data.metrics.total / HUNDRED_PERCENT);
106 } 103 }
107 104
108 uint64_t crit_print = config.crit.value; 105 uint64_t crit_print = config.crit.value;
109 if (config.crit.is_percentage) { 106 if (config.crit.is_percentage) {
110 crit_print = config.crit.value * (data.metrics.total / 100); 107 crit_print = config.crit.value * (data.metrics.total / HUNDRED_PERCENT);
111 } 108 }
112 109
113 char *perfdata = 110 char *perfdata = perfdata_uint64("swap", data.metrics.free, "B", true, warn_print, true, crit_print, true, 0, true, data.metrics.total);
114 perfdata_uint64("swap", data.metrics.free, "B", true, warn_print, true,
115 crit_print, true, 0, true, (long)data.metrics.total);
116 111
117 if (config.verbose > 1) { 112 if (verbose > 1) {
118 printf("Warn threshold value: %" PRIu64 "\n", config.warn.value); 113 printf("Warn threshold value: %" PRIu64 "\n", config.warn.value);
119 } 114 }
120 115
121 if ((config.warn.is_percentage && 116 if ((config.warn.is_percentage && (percent_used >= (double)(HUNDRED_PERCENT - config.warn.value))) ||
122 (percent_used >= (100 - config.warn.value))) ||
123 config.warn.value >= data.metrics.free) { 117 config.warn.value >= data.metrics.free) {
124 data.statusCode = max_state(data.statusCode, STATE_WARNING); 118 data.statusCode = max_state(data.statusCode, STATE_WARNING);
125 } 119 }
126 120
127 if (config.verbose > 1) { 121 if (verbose > 1) {
128 printf("Crit threshold value: %" PRIu64 "\n", config.crit.value); 122 printf("Crit threshold value: %" PRIu64 "\n", config.crit.value);
129 } 123 }
130 124
131 if ((config.crit.is_percentage && 125 if ((config.crit.is_percentage && (percent_used >= (double)(HUNDRED_PERCENT - config.crit.value))) ||
132 (percent_used >= (100 - config.crit.value))) ||
133 config.crit.value >= data.metrics.free) { 126 config.crit.value >= data.metrics.free) {
134 data.statusCode = max_state(data.statusCode, STATE_CRITICAL); 127 data.statusCode = max_state(data.statusCode, STATE_CRITICAL);
135 } 128 }
136 129
137 printf(_("SWAP %s - %g%% free (%lluMB out of %lluMB) %s|%s\n"), 130 printf(_("SWAP %s - %g%% free (%lluMB out of %lluMB) %s|%s\n"), state_text(data.statusCode), (HUNDRED_PERCENT - percent_used),
138 state_text(data.statusCode), (100 - percent_used), data.metrics.free, 131 data.metrics.free, data.metrics.total, status, perfdata);
139 data.metrics.total, status, perfdata);
140 132
141 exit(data.statusCode); 133 exit(data.statusCode);
142} 134}
143 135
136int check_swap(float free_swap_mb, float total_swap_mb, swap_config config) {
137 if (total_swap_mb == 0) {
138 return config.no_swap_state;
139 }
140
141 uint64_t free_swap = (uint64_t)(free_swap_mb * (1024 * 1024)); /* Convert back to bytes as warn and crit specified in bytes */
142
143 if (!config.crit.is_percentage && config.crit.value >= free_swap) {
144 return STATE_CRITICAL;
145 }
146 if (!config.warn.is_percentage && config.warn.value >= free_swap) {
147 return STATE_WARNING;
148 }
149
150 uint64_t usage_percentage = (uint64_t)((total_swap_mb - free_swap_mb) / total_swap_mb) * HUNDRED_PERCENT;
151
152 if (config.crit.is_percentage && config.crit.value != 0 && usage_percentage >= (HUNDRED_PERCENT - config.crit.value)) {
153 return STATE_CRITICAL;
154 }
155
156 if (config.warn.is_percentage && config.warn.value != 0 && usage_percentage >= (HUNDRED_PERCENT - config.warn.value)) {
157 return STATE_WARNING;
158 }
159
160 return STATE_OK;
161}
162
144/* process command-line arguments */ 163/* process command-line arguments */
145swap_config_wrapper process_arguments(swap_config_wrapper conf_wrapper, 164swap_config_wrapper process_arguments(int argc, char **argv) {
146 int argc, char **argv) { 165 swap_config_wrapper conf_wrapper = {.errorcode = OK};
166 conf_wrapper.config = swap_config_init();
167
147 if (argc < 2) { 168 if (argc < 2) {
148 conf_wrapper.errorcode = ERROR; 169 conf_wrapper.errorcode = ERROR;
149 return conf_wrapper; 170 return conf_wrapper;
150 } 171 }
151 172
152 int option = 0; 173 static struct option longopts[] = {{"warning", required_argument, 0, 'w'}, {"critical", required_argument, 0, 'c'},
153 static struct option longopts[] = {{"warning", required_argument, 0, 'w'}, 174 {"allswaps", no_argument, 0, 'a'}, {"no-swap", required_argument, 0, 'n'},
154 {"critical", required_argument, 0, 'c'}, 175 {"verbose", no_argument, 0, 'v'}, {"version", no_argument, 0, 'V'},
155 {"allswaps", no_argument, 0, 'a'}, 176 {"help", no_argument, 0, 'h'}, {0, 0, 0, 0}};
156 {"no-swap", required_argument, 0, 'n'}, 177
157 {"verbose", no_argument, 0, 'v'},
158 {"version", no_argument, 0, 'V'},
159 {"help", no_argument, 0, 'h'},
160 {0, 0, 0, 0}};
161
162 int c = 0; /* option character */
163 while (true) { 178 while (true) {
164 c = getopt_long(argc, argv, "+?Vvhac:w:n:", longopts, &option); 179 int option = 0;
180 int option_char = getopt_long(argc, argv, "+?Vvhac:w:n:", longopts, &option);
165 181
166 if (c == -1 || c == EOF) 182 if (option_char == -1 || option_char == EOF) {
167 break; 183 break;
184 }
168 185
169 switch (c) { 186 switch (option_char) {
170 case 'w': /* warning size threshold */ 187 case 'w': /* warning size threshold */
171 { 188 {
172 /* 189 /*
@@ -183,22 +200,18 @@ swap_config_wrapper process_arguments(swap_config_wrapper conf_wrapper,
183 conf_wrapper.config.warn.is_percentage = true; 200 conf_wrapper.config.warn.is_percentage = true;
184 optarg[length - 1] = '\0'; 201 optarg[length - 1] = '\0';
185 if (is_uint64(optarg, &conf_wrapper.config.warn.value)) { 202 if (is_uint64(optarg, &conf_wrapper.config.warn.value)) {
186 if (conf_wrapper.config.warn.value > 100) { 203 if (conf_wrapper.config.warn.value > HUNDRED_PERCENT) {
187 usage4( 204 usage4(_("Warning threshold percentage must be <= 100!"));
188 _("Warning threshold percentage must be <= 100!"));
189 } 205 }
190 } 206 }
191 break; 207 break;
192 } else { 208 } /* It's Bytes */
193 /* It's Bytes */ 209 conf_wrapper.config.warn.is_percentage = false;
194 conf_wrapper.config.warn.is_percentage = false; 210 if (is_uint64(optarg, &conf_wrapper.config.warn.value)) {
195 if (is_uint64(optarg, &conf_wrapper.config.warn.value)) { 211 break;
196 break;
197 } else {
198 usage4(_("Warning threshold be positive integer or "
199 "percentage!"));
200 }
201 } 212 }
213 usage4(_("Warning threshold be positive integer or "
214 "percentage!"));
202 } 215 }
203 case 'c': /* critical size threshold */ 216 case 'c': /* critical size threshold */
204 { 217 {
@@ -216,35 +229,30 @@ swap_config_wrapper process_arguments(swap_config_wrapper conf_wrapper,
216 conf_wrapper.config.crit.is_percentage = true; 229 conf_wrapper.config.crit.is_percentage = true;
217 optarg[length - 1] = '\0'; 230 optarg[length - 1] = '\0';
218 if (is_uint64(optarg, &conf_wrapper.config.crit.value)) { 231 if (is_uint64(optarg, &conf_wrapper.config.crit.value)) {
219 if (conf_wrapper.config.crit.value > 100) { 232 if (conf_wrapper.config.crit.value > HUNDRED_PERCENT) {
220 usage4( 233 usage4(_("Critical threshold percentage must be <= 100!"));
221 _("Critical threshold percentage must be <= 100!"));
222 } 234 }
223 } 235 }
224 break; 236 break;
225 } else { 237 } /* It's Bytes */
226 /* It's Bytes */ 238 conf_wrapper.config.crit.is_percentage = false;
227 conf_wrapper.config.crit.is_percentage = false; 239 if (is_uint64(optarg, &conf_wrapper.config.crit.value)) {
228 if (is_uint64(optarg, &conf_wrapper.config.crit.value)) { 240 break;
229 break;
230 } else {
231 usage4(_("Critical threshold be positive integer or "
232 "percentage!"));
233 }
234 } 241 }
242 usage4(_("Critical threshold be positive integer or "
243 "percentage!"));
235 } 244 }
236 case 'a': /* all swap */ 245 case 'a': /* all swap */
237 conf_wrapper.config.allswaps = true; 246 conf_wrapper.config.allswaps = true;
238 break; 247 break;
239 case 'n': 248 case 'n':
240 if ((conf_wrapper.config.no_swap_state = 249 if ((conf_wrapper.config.no_swap_state = mp_translate_state(optarg)) == ERROR) {
241 mp_translate_state(optarg)) == ERROR) {
242 usage4(_("no-swap result must be a valid state name (OK, " 250 usage4(_("no-swap result must be a valid state name (OK, "
243 "WARNING, CRITICAL, UNKNOWN) or integer (0-3).")); 251 "WARNING, CRITICAL, UNKNOWN) or integer (0-3)."));
244 } 252 }
245 break; 253 break;
246 case 'v': /* verbose */ 254 case 'v': /* verbose */
247 conf_wrapper.config.verbose++; 255 verbose++;
248 break; 256 break;
249 case 'V': /* version */ 257 case 'V': /* version */
250 print_revision(progname, NP_VERSION); 258 print_revision(progname, NP_VERSION);
@@ -257,16 +265,12 @@ swap_config_wrapper process_arguments(swap_config_wrapper conf_wrapper,
257 } 265 }
258 } 266 }
259 267
260 c = optind; 268 if (conf_wrapper.config.warn.value == 0 && conf_wrapper.config.crit.value == 0) {
261
262 if (conf_wrapper.config.warn.value == 0 &&
263 conf_wrapper.config.crit.value == 0) {
264 conf_wrapper.errorcode = ERROR; 269 conf_wrapper.errorcode = ERROR;
265 return conf_wrapper; 270 return conf_wrapper;
266 } else if ((conf_wrapper.config.warn.is_percentage == 271 }
267 conf_wrapper.config.crit.is_percentage) && 272 if ((conf_wrapper.config.warn.is_percentage == conf_wrapper.config.crit.is_percentage) &&
268 (conf_wrapper.config.warn.value < 273 (conf_wrapper.config.warn.value < conf_wrapper.config.crit.value)) {
269 conf_wrapper.config.crit.value)) {
270 /* This is NOT triggered if warn and crit are different units, e.g warn 274 /* This is NOT triggered if warn and crit are different units, e.g warn
271 * is percentage and crit is absolute. We cannot determine the condition 275 * is percentage and crit is absolute. We cannot determine the condition
272 * at this point since we dont know the value of total swap yet 276 * at this point since we dont know the value of total swap yet
@@ -304,8 +308,7 @@ void print_help(swap_config config) {
304 printf(" %s\n", _("Exit with CRITICAL status if less than PERCENT of " 308 printf(" %s\n", _("Exit with CRITICAL status if less than PERCENT of "
305 "swap space is free")); 309 "swap space is free"));
306 printf(" %s\n", "-a, --allswaps"); 310 printf(" %s\n", "-a, --allswaps");
307 printf(" %s\n", 311 printf(" %s\n", _("Conduct comparisons for all swap partitions, one by one"));
308 _("Conduct comparisons for all swap partitions, one by one"));
309 printf(" %s\n", "-n, --no-swap=<ok|warning|critical|unknown>"); 312 printf(" %s\n", "-n, --no-swap=<ok|warning|critical|unknown>");
310 printf(" %s %s\n", 313 printf(" %s %s\n",
311 _("Resulting state when there is no swap regardless of thresholds. " 314 _("Resulting state when there is no swap regardless of thresholds. "
@@ -317,14 +320,12 @@ void print_help(swap_config config) {
317 printf("%s\n", _("Notes:")); 320 printf("%s\n", _("Notes:"));
318 printf(" %s\n", _("Both INTEGER and PERCENT thresholds can be specified, " 321 printf(" %s\n", _("Both INTEGER and PERCENT thresholds can be specified, "
319 "they are all checked.")); 322 "they are all checked."));
320 printf( 323 printf(" %s\n", _("On AIX, if -a is specified, uses lsps -a, otherwise uses lsps -s."));
321 " %s\n",
322 _("On AIX, if -a is specified, uses lsps -a, otherwise uses lsps -s."));
323 324
324 printf(UT_SUPPORT); 325 printf(UT_SUPPORT);
325} 326}
326 327
327void print_usage() { 328void print_usage(void) {
328 printf("%s\n", _("Usage:")); 329 printf("%s\n", _("Usage:"));
329 printf(" %s [-av] -w <percent_free>%% -c <percent_free>%%\n", progname); 330 printf(" %s [-av] -w <percent_free>%% -c <percent_free>%%\n", progname);
330 printf(" -w <bytes_free> -c <bytes_free> [-n <state>]\n"); 331 printf(" -w <bytes_free> -c <bytes_free> [-n <state>]\n");
diff --git a/plugins/check_swap.d/check_swap.h b/plugins/check_swap.d/check_swap.h
index bad52917..9e8be75f 100644
--- a/plugins/check_swap.d/check_swap.h
+++ b/plugins/check_swap.d/check_swap.h
@@ -4,7 +4,7 @@
4#include "../common.h" 4#include "../common.h"
5 5
6#ifndef SWAP_CONVERSION 6#ifndef SWAP_CONVERSION
7#define SWAP_CONVERSION 1 7# define SWAP_CONVERSION 1
8#endif 8#endif
9 9
10typedef struct { 10typedef struct {
@@ -25,7 +25,6 @@ typedef struct {
25} swap_result; 25} swap_result;
26 26
27typedef struct { 27typedef struct {
28 int verbose;
29 bool allswaps; 28 bool allswaps;
30 int no_swap_state; 29 int no_swap_state;
31 threshold warn; 30 threshold warn;
@@ -34,10 +33,10 @@ typedef struct {
34 int conversion_factor; 33 int conversion_factor;
35} swap_config; 34} swap_config;
36 35
37swap_config swap_config_init(); 36swap_config swap_config_init(void);
38 37
39swap_result get_swap_data(swap_config config); 38swap_result get_swap_data(swap_config config);
40swap_result getSwapFromProcMeminfo(swap_config config, char path_to_proc_meminfo[]); 39swap_result getSwapFromProcMeminfo(char path_to_proc_meminfo[]);
41swap_result getSwapFromSwapCommand(swap_config config, const char swap_command[], const char swap_format[]); 40swap_result getSwapFromSwapCommand(swap_config config, const char swap_command[], const char swap_format[]);
42swap_result getSwapFromSwapctl_BSD(swap_config config); 41swap_result getSwapFromSwapctl_BSD(swap_config config);
43swap_result getSwapFromSwap_SRV4(swap_config config); 42swap_result getSwapFromSwap_SRV4(swap_config config);
diff --git a/plugins/check_swap.d/swap.c b/plugins/check_swap.d/swap.c
index 50920fa3..d437ba59 100644
--- a/plugins/check_swap.d/swap.c
+++ b/plugins/check_swap.d/swap.c
@@ -2,11 +2,12 @@
2#include "../popen.h" 2#include "../popen.h"
3#include "../utils.h" 3#include "../utils.h"
4 4
5swap_config swap_config_init() { 5extern int verbose;
6
7swap_config swap_config_init(void) {
6 swap_config tmp = {0}; 8 swap_config tmp = {0};
7 tmp.allswaps = false; 9 tmp.allswaps = false;
8 tmp.no_swap_state = STATE_CRITICAL; 10 tmp.no_swap_state = STATE_CRITICAL;
9 tmp.verbose = 0;
10 tmp.conversion_factor = SWAP_CONVERSION; 11 tmp.conversion_factor = SWAP_CONVERSION;
11 12
12#ifdef _AIX 13#ifdef _AIX
@@ -20,14 +21,14 @@ swap_config swap_config_init() {
20 21
21swap_result get_swap_data(swap_config config) { 22swap_result get_swap_data(swap_config config) {
22#ifdef HAVE_PROC_MEMINFO 23#ifdef HAVE_PROC_MEMINFO
23 if (config.verbose >= 3) { 24 if (verbose >= 3) {
24 printf("Reading PROC_MEMINFO at %s\n", PROC_MEMINFO); 25 printf("Reading PROC_MEMINFO at %s\n", PROC_MEMINFO);
25 } 26 }
26 27
27 return getSwapFromProcMeminfo(config, PROC_MEMINFO); 28 return getSwapFromProcMeminfo(PROC_MEMINFO);
28#else 29#else
29#ifdef HAVE_SWAP 30# ifdef HAVE_SWAP
30 if (config.verbose >= 3) { 31 if (verbose >= 3) {
31 printf("Using swap command %s with format: %s\n", SWAP_COMMAND, SWAP_FORMAT); 32 printf("Using swap command %s with format: %s\n", SWAP_COMMAND, SWAP_FORMAT);
32 } 33 }
33 34
@@ -43,21 +44,21 @@ swap_result get_swap_data(swap_config config) {
43 } else { 44 } else {
44 return getSwapFromSwapCommand(config, SWAP_COMMAND, SWAP_FORMAT); 45 return getSwapFromSwapCommand(config, SWAP_COMMAND, SWAP_FORMAT);
45 } 46 }
46#else 47# else
47#ifdef CHECK_SWAP_SWAPCTL_SVR4 48# ifdef CHECK_SWAP_SWAPCTL_SVR4
48 return getSwapFromSwapctl_SRV4(); 49 return getSwapFromSwapctl_SRV4();
49#else 50# else
50#ifdef CHECK_SWAP_SWAPCTL_BSD 51# ifdef CHECK_SWAP_SWAPCTL_BSD
51 return getSwapFromSwapctl_BSD(); 52 return getSwapFromSwapctl_BSD();
52#else 53# else
53#error No way found to retrieve swap 54# error No way found to retrieve swap
54#endif /* CHECK_SWAP_SWAPCTL_BSD */ 55# endif /* CHECK_SWAP_SWAPCTL_BSD */
55#endif /* CHECK_SWAP_SWAPCTL_SVR4 */ 56# endif /* CHECK_SWAP_SWAPCTL_SVR4 */
56#endif /* HAVE_SWAP */ 57# endif /* HAVE_SWAP */
57#endif /* HAVE_PROC_MEMINFO */ 58#endif /* HAVE_PROC_MEMINFO */
58} 59}
59 60
60swap_result getSwapFromProcMeminfo(swap_config config, char proc_meminfo[]) { 61swap_result getSwapFromProcMeminfo(char proc_meminfo[]) {
61 FILE *fp; 62 FILE *fp;
62 fp = fopen(proc_meminfo, "r"); 63 fp = fopen(proc_meminfo, "r");
63 64
@@ -79,8 +80,7 @@ swap_result getSwapFromProcMeminfo(swap_config config, char proc_meminfo[]) {
79 * sscanf anymore, like me 80 * sscanf anymore, like me
80 * Also the units used here are unclear and probably wrong 81 * Also the units used here are unclear and probably wrong
81 */ 82 */
82 if (sscanf(input_buffer, "%*[S]%*[w]%*[a]%*[p]%*[:] %lu %lu %lu", 83 if (sscanf(input_buffer, "%*[S]%*[w]%*[a]%*[p]%*[:] %lu %lu %lu", &swap_total, &swap_used, &swap_free) == 3) {
83 &swap_total, &swap_used, &swap_free) == 3) {
84 84
85 result.metrics.total += swap_total; 85 result.metrics.total += swap_total;
86 result.metrics.used += swap_used; 86 result.metrics.used += swap_used;
@@ -96,7 +96,7 @@ swap_result getSwapFromProcMeminfo(swap_config config, char proc_meminfo[]) {
96 "%*[k]%*[B]", 96 "%*[k]%*[B]",
97 str, &tmp_KB)) { 97 str, &tmp_KB)) {
98 98
99 if (config.verbose >= 3) { 99 if (verbose >= 3) {
100 printf("Got %s with %lu\n", str, tmp_KB); 100 printf("Got %s with %lu\n", str, tmp_KB);
101 } 101 }
102 102
@@ -125,9 +125,9 @@ swap_result getSwapFromSwapCommand(swap_config config, const char swap_command[]
125 125
126 char *temp_buffer; 126 char *temp_buffer;
127 127
128 if (config.verbose >= 2) 128 if (verbose >= 2)
129 printf(_("Command: %s\n"), swap_command); 129 printf(_("Command: %s\n"), swap_command);
130 if (config.verbose >= 3) 130 if (verbose >= 3)
131 printf(_("Format: %s\n"), swap_format); 131 printf(_("Format: %s\n"), swap_format);
132 132
133 child_process = spopen(swap_command); 133 child_process = spopen(swap_command);
@@ -169,16 +169,14 @@ swap_result getSwapFromSwapCommand(swap_config config, const char swap_command[]
169 * If different swap command is used for summary switch, need to read format 169 * If different swap command is used for summary switch, need to read format
170 * differently 170 * differently
171 */ 171 */
172 if (config.on_aix && !config.allswaps) { 172 if (config.on_aix && !config.allswaps) {
173 fgets(input_buffer, MAX_INPUT_BUFFER - 1, 173 fgets(input_buffer, MAX_INPUT_BUFFER - 1, child_process); /* Ignore first line */
174 child_process); /* Ignore first line */
175 sscanf(input_buffer, swap_format, &total_swap_mb, &used_swap_mb); 174 sscanf(input_buffer, swap_format, &total_swap_mb, &used_swap_mb);
176 free_swap_mb = total_swap_mb * (100 - used_swap_mb) / 100; 175 free_swap_mb = total_swap_mb * (100 - used_swap_mb) / 100;
177 used_swap_mb = total_swap_mb - free_swap_mb; 176 used_swap_mb = total_swap_mb - free_swap_mb;
178 177
179 if (config.verbose >= 3) { 178 if (verbose >= 3) {
180 printf(_("total=%.0f, used=%.0f, free=%.0f\n"), total_swap_mb, 179 printf(_("total=%.0f, used=%.0f, free=%.0f\n"), total_swap_mb, used_swap_mb, free_swap_mb);
181 used_swap_mb, free_swap_mb);
182 } 180 }
183 } else { 181 } else {
184 while (fgets(input_buffer, MAX_INPUT_BUFFER - 1, child_process)) { 182 while (fgets(input_buffer, MAX_INPUT_BUFFER - 1, child_process)) {
@@ -193,7 +191,7 @@ swap_result getSwapFromSwapCommand(swap_config config, const char swap_command[]
193 dskfree_mb = dskfree_mb / config.conversion_factor; 191 dskfree_mb = dskfree_mb / config.conversion_factor;
194 } 192 }
195 193
196 if (config.verbose >= 3) 194 if (verbose >= 3)
197 printf(_("total=%.0f, free=%.0f\n"), dsktotal_mb, dskfree_mb); 195 printf(_("total=%.0f, free=%.0f\n"), dsktotal_mb, dskfree_mb);
198 196
199 dskused_mb = dsktotal_mb - dskfree_mb; 197 dskused_mb = dsktotal_mb - dskfree_mb;
@@ -204,8 +202,8 @@ swap_result getSwapFromSwapCommand(swap_config config, const char swap_command[]
204 } 202 }
205 203
206 result.metrics.free = free_swap_mb * 1024 * 1024; 204 result.metrics.free = free_swap_mb * 1024 * 1024;
207 result.metrics.used = used_swap_mb * 1024 * 1024; 205 result.metrics.used = used_swap_mb * 1024 * 1024;
208 result.metrics.total = free_swap_mb * 1024 * 1024; 206 result.metrics.total = free_swap_mb * 1024 * 1024;
209 207
210 /* If we get anything on STDERR, at least set warning */ 208 /* If we get anything on STDERR, at least set warning */
211 while (fgets(input_buffer, MAX_INPUT_BUFFER - 1, child_stderr)) { 209 while (fgets(input_buffer, MAX_INPUT_BUFFER - 1, child_stderr)) {
@@ -226,31 +224,31 @@ swap_result getSwapFromSwapCommand(swap_config config, const char swap_command[]
226} 224}
227 225
228#ifndef CHECK_SWAP_SWAPCTL_BSD 226#ifndef CHECK_SWAP_SWAPCTL_BSD
229#define CHECK_SWAP_SWAPCTL_BSD 227# define CHECK_SWAP_SWAPCTL_BSD
230 228
231// Stub functionality for BSD stuff, so the compiler always sees the following BSD code 229// Stub functionality for BSD stuff, so the compiler always sees the following BSD code
232 230
233#define SWAP_NSWAP 0 231# define SWAP_NSWAP 0
234#define SWAP_STATS 1 232# define SWAP_STATS 1
235 233
236int bsd_swapctl(int cmd, const void *arg, int misc) { 234int bsd_swapctl(int cmd, const void *arg, int misc) {
237 (void) cmd; 235 (void)cmd;
238 (void) arg; 236 (void)arg;
239 (void) misc; 237 (void)misc;
240 return 512; 238 return 512;
241} 239}
242 240
243struct swapent { 241struct swapent {
244 dev_t se_dev; /* device id */ 242 dev_t se_dev; /* device id */
245 int se_flags; /* entry flags */ 243 int se_flags; /* entry flags */
246 int se_nblks; /* total blocks */ 244 int se_nblks; /* total blocks */
247 int se_inuse; /* blocks in use */ 245 int se_inuse; /* blocks in use */
248 int se_priority; /* priority */ 246 int se_priority; /* priority */
249 char se_path[PATH_MAX]; /* path to entry */ 247 char se_path[PATH_MAX]; /* path to entry */
250}; 248};
251 249
252#else 250#else
253#define bsd_swapctl swapctl 251# define bsd_swapctl swapctl
254#endif 252#endif
255 253
256swap_result getSwapFromSwapctl_BSD(swap_config config) { 254swap_result getSwapFromSwapctl_BSD(swap_config config) {
@@ -267,7 +265,6 @@ swap_result getSwapFromSwapctl_BSD(swap_config config) {
267 die(STATE_UNKNOWN, _("Error in swapctl call\n")); 265 die(STATE_UNKNOWN, _("Error in swapctl call\n"));
268 } 266 }
269 267
270
271 double dsktotal_mb = 0.0, dskfree_mb = 0.0, dskused_mb = 0.0; 268 double dsktotal_mb = 0.0, dskfree_mb = 0.0, dskused_mb = 0.0;
272 unsigned long long total_swap_mb = 0, free_swap_mb = 0, used_swap_mb = 0; 269 unsigned long long total_swap_mb = 0, free_swap_mb = 0, used_swap_mb = 0;
273 270
@@ -279,7 +276,7 @@ swap_result getSwapFromSwapctl_BSD(swap_config config) {
279 if (config.allswaps && dsktotal_mb > 0) { 276 if (config.allswaps && dsktotal_mb > 0) {
280 double percent = 100 * (((double)dskused_mb) / ((double)dsktotal_mb)); 277 double percent = 100 * (((double)dskused_mb) / ((double)dsktotal_mb));
281 278
282 if (config.verbose) { 279 if (verbose) {
283 printf("[%.0f (%g%%)]", dskfree_mb, 100 - percent); 280 printf("[%.0f (%g%%)]", dskfree_mb, 100 - percent);
284 } 281 }
285 } 282 }
@@ -297,46 +294,44 @@ swap_result getSwapFromSwapctl_BSD(swap_config config) {
297 result.statusCode = OK; 294 result.statusCode = OK;
298 result.errorcode = OK; 295 result.errorcode = OK;
299 296
300 result.metrics.total = total_swap_mb * 1024 * 1024; 297 result.metrics.total = total_swap_mb * 1024 * 1024;
301 result.metrics.free = free_swap_mb * 1024 * 1024; 298 result.metrics.free = free_swap_mb * 1024 * 1024;
302 result.metrics.used = used_swap_mb * 1024 * 1024; 299 result.metrics.used = used_swap_mb * 1024 * 1024;
303 300
304 return result; 301 return result;
305} 302}
306 303
307
308
309#ifndef CHECK_SWAP_SWAPCTL_SVR4 304#ifndef CHECK_SWAP_SWAPCTL_SVR4
310int srv4_swapctl(int cmd, void *arg) { 305int srv4_swapctl(int cmd, void *arg) {
311 (void) cmd; 306 (void)cmd;
312 (void) arg; 307 (void)arg;
313 return 512; 308 return 512;
314} 309}
315 310
316typedef struct srv4_swapent { 311typedef struct srv4_swapent {
317 char *ste_path; /* name of the swap file */ 312 char *ste_path; /* name of the swap file */
318 off_t ste_start; /* starting block for swapping */ 313 off_t ste_start; /* starting block for swapping */
319 off_t ste_length; /* length of swap area */ 314 off_t ste_length; /* length of swap area */
320 long ste_pages; /* number of pages for swapping */ 315 long ste_pages; /* number of pages for swapping */
321 long ste_free; /* number of ste_pages free */ 316 long ste_free; /* number of ste_pages free */
322 long ste_flags; /* ST_INDEL bit set if swap file */ 317 long ste_flags; /* ST_INDEL bit set if swap file */
323 /* is now being deleted */ 318 /* is now being deleted */
324} swapent_t; 319} swapent_t;
325 320
326typedef struct swaptbl { 321typedef struct swaptbl {
327 int swt_n; /* number of swapents following */ 322 int swt_n; /* number of swapents following */
328 struct srv4_swapent swt_ent[]; /* array of swt_n swapents */ 323 struct srv4_swapent swt_ent[]; /* array of swt_n swapents */
329} swaptbl_t; 324} swaptbl_t;
330 325
331#define SC_LIST 2 326# define SC_LIST 2
332#define SC_GETNSWP 3 327# define SC_GETNSWP 3
333 328
334#ifndef MAXPATHLEN 329# ifndef MAXPATHLEN
335#define MAXPATHLEN 2048 330# define MAXPATHLEN 2048
336#endif 331# endif
337 332
338#else 333#else
339#define srv4_swapctl swapctl 334# define srv4_swapctl swapctl
340#endif 335#endif
341 336
342swap_result getSwapFromSwap_SRV4(swap_config config) { 337swap_result getSwapFromSwap_SRV4(swap_config config) {
@@ -349,7 +344,7 @@ swap_result getSwapFromSwap_SRV4(swap_config config) {
349 if (nswaps == 0) 344 if (nswaps == 0)
350 die(STATE_OK, _("SWAP OK: No swap devices defined\n")); 345 die(STATE_OK, _("SWAP OK: No swap devices defined\n"));
351 346
352 if (config.verbose >= 3) 347 if (verbose >= 3)
353 printf("Found %d swap device(s)\n", nswaps); 348 printf("Found %d swap device(s)\n", nswaps);
354 349
355 /* initialize swap table + entries */ 350 /* initialize swap table + entries */
@@ -362,8 +357,7 @@ swap_result getSwapFromSwap_SRV4(swap_config config) {
362 tbl->swt_n = nswaps; 357 tbl->swt_n = nswaps;
363 358
364 for (int i = 0; i < nswaps; i++) { 359 for (int i = 0; i < nswaps; i++) {
365 if ((tbl->swt_ent[i].ste_path = 360 if ((tbl->swt_ent[i].ste_path = (char *)malloc(sizeof(char) * MAXPATHLEN)) == NULL)
366 (char *)malloc(sizeof(char) * MAXPATHLEN)) == NULL)
367 die(STATE_UNKNOWN, _("malloc() failed!\n")); 361 die(STATE_UNKNOWN, _("malloc() failed!\n"));
368 } 362 }
369 363
@@ -374,22 +368,25 @@ swap_result getSwapFromSwap_SRV4(swap_config config) {
374 die(STATE_UNKNOWN, _("Error in swapctl call\n")); 368 die(STATE_UNKNOWN, _("Error in swapctl call\n"));
375 } 369 }
376 370
377 double dsktotal_mb = 0.0, dskfree_mb = 0.0, dskused_mb = 0.0; 371 double dsktotal_mb = 0.0;
378 unsigned long long total_swap_mb = 0, free_swap_mb = 0, used_swap_mb = 0; 372 double dskfree_mb = 0.0;
373 double dskused_mb = 0.0;
374 unsigned long long total_swap_mb = 0;
375 unsigned long long free_swap_mb = 0;
376 unsigned long long used_swap_mb = 0;
379 377
380 for (int i = 0; i < nswaps; i++) { 378 for (int i = 0; i < nswaps; i++) {
381 dsktotal_mb = (float)tbl->swt_ent[i].ste_pages / SWAP_CONVERSION; 379 dsktotal_mb = (float)tbl->swt_ent[i].ste_pages / SWAP_CONVERSION;
382 dskfree_mb = (float)tbl->swt_ent[i].ste_free / SWAP_CONVERSION; 380 dskfree_mb = (float)tbl->swt_ent[i].ste_free / SWAP_CONVERSION;
383 dskused_mb = (dsktotal_mb - dskfree_mb); 381 dskused_mb = (dsktotal_mb - dskfree_mb);
384 382
385 if (config.verbose >= 3) 383 if (verbose >= 3)
386 printf("dsktotal_mb=%.0f dskfree_mb=%.0f dskused_mb=%.0f\n", 384 printf("dsktotal_mb=%.0f dskfree_mb=%.0f dskused_mb=%.0f\n", dsktotal_mb, dskfree_mb, dskused_mb);
387 dsktotal_mb, dskfree_mb, dskused_mb);
388 385
389 if (config.allswaps && dsktotal_mb > 0) { 386 if (config.allswaps && dsktotal_mb > 0) {
390 double percent = 100 * (((double)dskused_mb) / ((double)dsktotal_mb)); 387 double percent = 100 * (((double)dskused_mb) / ((double)dsktotal_mb));
391 388
392 if (config.verbose) { 389 if (verbose) {
393 printf("[%.0f (%g%%)]", dskfree_mb, 100 - percent); 390 printf("[%.0f (%g%%)]", dskfree_mb, 100 - percent);
394 } 391 }
395 } 392 }
diff --git a/plugins/check_tcp.c b/plugins/check_tcp.c
index 01dd35eb..c13ac767 100644
--- a/plugins/check_tcp.c
+++ b/plugins/check_tcp.c
@@ -1,35 +1,35 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring check_tcp plugin 3 * Monitoring check_tcp plugin
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 1999-2013 Monitoring Plugins Development Team 6 * Copyright (c) 1999-2024 Monitoring Plugins Development Team
7* 7 *
8* Description: 8 * Description:
9* 9 *
10* This file contains the check_tcp plugin 10 * This file contains the check_tcp plugin
11* 11 *
12* 12 *
13* This program is free software: you can redistribute it and/or modify 13 * This program is free software: you can redistribute it and/or modify
14* it under the terms of the GNU General Public License as published by 14 * it under the terms of the GNU General Public License as published by
15* the Free Software Foundation, either version 3 of the License, or 15 * the Free Software Foundation, either version 3 of the License, or
16* (at your option) any later version. 16 * (at your option) any later version.
17* 17 *
18* This program is distributed in the hope that it will be useful, 18 * This program is distributed in the hope that it will be useful,
19* but WITHOUT ANY WARRANTY; without even the implied warranty of 19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21* GNU General Public License for more details. 21 * GNU General Public License for more details.
22* 22 *
23* You should have received a copy of the GNU General Public License 23 * You should have received a copy of the GNU General Public License
24* along with this program. If not, see <http://www.gnu.org/licenses/>. 24 * along with this program. If not, see <http://www.gnu.org/licenses/>.
25* 25 *
26* $Id$ 26 * $Id$
27* 27 *
28*****************************************************************************/ 28 *****************************************************************************/
29 29
30/* progname "check_tcp" changes depending on symlink called */ 30/* progname "check_tcp" changes depending on symlink called */
31char *progname; 31char *progname;
32const char *copyright = "1999-2008"; 32const char *copyright = "1999-2024";
33const char *email = "devel@monitoring-plugins.org"; 33const char *email = "devel@monitoring-plugins.org";
34 34
35#include "common.h" 35#include "common.h"
@@ -43,17 +43,17 @@ const char *email = "devel@monitoring-plugins.org";
43#ifdef HAVE_SSL 43#ifdef HAVE_SSL
44static bool check_cert = false; 44static bool check_cert = false;
45static int days_till_exp_warn, days_till_exp_crit; 45static int days_till_exp_warn, days_till_exp_crit;
46# define my_recv(buf, len) ((flags & FLAG_SSL) ? np_net_ssl_read(buf, len) : read(sd, buf, len)) 46# define my_recv(buf, len) ((flags & FLAG_SSL) ? np_net_ssl_read(buf, len) : read(sd, buf, len))
47# define my_send(buf, len) ((flags & FLAG_SSL) ? np_net_ssl_write(buf, len) : send(sd, buf, len, 0)) 47# define my_send(buf, len) ((flags & FLAG_SSL) ? np_net_ssl_write(buf, len) : send(sd, buf, len, 0))
48#else 48#else
49# define my_recv(buf, len) read(sd, buf, len) 49# define my_recv(buf, len) read(sd, buf, len)
50# define my_send(buf, len) send(sd, buf, len, 0) 50# define my_send(buf, len) send(sd, buf, len, 0)
51#endif 51#endif
52 52
53/* int my_recv(char *, size_t); */ 53/* int my_recv(char *, size_t); */
54static int process_arguments (int, char **); 54static int process_arguments(int /*argc*/, char ** /*argv*/);
55void print_help (void); 55static void print_help(void);
56void print_usage (void); 56void print_usage(void);
57 57
58#define EXPECT server_expect[0] 58#define EXPECT server_expect[0]
59static char *SERVICE = "TCP"; 59static char *SERVICE = "TCP";
@@ -91,38 +91,29 @@ static char *sni = NULL;
91static bool sni_specified = false; 91static bool sni_specified = false;
92#endif 92#endif
93 93
94#define FLAG_SSL 0x01 94#define FLAG_SSL 0x01
95#define FLAG_VERBOSE 0x02 95#define FLAG_VERBOSE 0x02
96#define FLAG_TIME_WARN 0x04 96#define FLAG_TIME_WARN 0x04
97#define FLAG_TIME_CRIT 0x08 97#define FLAG_TIME_CRIT 0x08
98#define FLAG_HIDE_OUTPUT 0x10 98#define FLAG_HIDE_OUTPUT 0x10
99static size_t flags; 99static size_t flags;
100 100
101int 101int main(int argc, char **argv) {
102main (int argc, char **argv) 102 setlocale(LC_ALL, "");
103{ 103 bindtextdomain(PACKAGE, LOCALEDIR);
104 int result = STATE_UNKNOWN; 104 textdomain(PACKAGE);
105 char *status = NULL;
106 struct timeval tv;
107 struct timeval timeout;
108 int match = -1;
109 fd_set rfds;
110
111 FD_ZERO(&rfds);
112
113 setlocale (LC_ALL, "");
114 bindtextdomain (PACKAGE, LOCALEDIR);
115 textdomain (PACKAGE);
116 105
117 /* determine program- and service-name quickly */ 106 /* determine program- and service-name quickly */
118 progname = strrchr(argv[0], '/'); 107 progname = strrchr(argv[0], '/');
119 if(progname != NULL) progname++; 108 if (progname != NULL)
120 else progname = argv[0]; 109 progname++;
110 else
111 progname = argv[0];
121 112
122 size_t prog_name_len = strlen(progname); 113 size_t prog_name_len = strlen(progname);
123 if(prog_name_len > 6 && !memcmp(progname, "check_", 6)) { 114 if (prog_name_len > 6 && !memcmp(progname, "check_", 6)) {
124 SERVICE = strdup(progname + 6); 115 SERVICE = strdup(progname + 6);
125 for(size_t i = 0; i < prog_name_len - 6; i++) 116 for (size_t i = 0; i < prog_name_len - 6; i++)
126 SERVICE[i] = toupper(SERVICE[i]); 117 SERVICE[i] = toupper(SERVICE[i]);
127 } 118 }
128 119
@@ -133,23 +124,19 @@ main (int argc, char **argv)
133 /* determine defaults for this service's protocol */ 124 /* determine defaults for this service's protocol */
134 if (!strncmp(SERVICE, "UDP", 3)) { 125 if (!strncmp(SERVICE, "UDP", 3)) {
135 PROTOCOL = IPPROTO_UDP; 126 PROTOCOL = IPPROTO_UDP;
136 } 127 } else if (!strncmp(SERVICE, "FTP", 3)) {
137 else if (!strncmp(SERVICE, "FTP", 3)) {
138 EXPECT = "220"; 128 EXPECT = "220";
139 QUIT = "QUIT\r\n"; 129 QUIT = "QUIT\r\n";
140 PORT = 21; 130 PORT = 21;
141 } 131 } else if (!strncmp(SERVICE, "POP", 3) || !strncmp(SERVICE, "POP3", 4)) {
142 else if (!strncmp(SERVICE, "POP", 3) || !strncmp(SERVICE, "POP3", 4)) {
143 EXPECT = "+OK"; 132 EXPECT = "+OK";
144 QUIT = "QUIT\r\n"; 133 QUIT = "QUIT\r\n";
145 PORT = 110; 134 PORT = 110;
146 } 135 } else if (!strncmp(SERVICE, "SMTP", 4)) {
147 else if (!strncmp(SERVICE, "SMTP", 4)) {
148 EXPECT = "220"; 136 EXPECT = "220";
149 QUIT = "QUIT\r\n"; 137 QUIT = "QUIT\r\n";
150 PORT = 25; 138 PORT = 25;
151 } 139 } else if (!strncmp(SERVICE, "IMAP", 4)) {
152 else if (!strncmp(SERVICE, "IMAP", 4)) {
153 EXPECT = "* OK"; 140 EXPECT = "* OK";
154 QUIT = "a1 LOGOUT\r\n"; 141 QUIT = "a1 LOGOUT\r\n";
155 PORT = 143; 142 PORT = 143;
@@ -160,27 +147,23 @@ main (int argc, char **argv)
160 QUIT = "a1 LOGOUT\r\n"; 147 QUIT = "a1 LOGOUT\r\n";
161 flags |= FLAG_SSL; 148 flags |= FLAG_SSL;
162 PORT = 993; 149 PORT = 993;
163 } 150 } else if (!strncmp(SERVICE, "SPOP", 4)) {
164 else if (!strncmp(SERVICE, "SPOP", 4)) {
165 EXPECT = "+OK"; 151 EXPECT = "+OK";
166 QUIT = "QUIT\r\n"; 152 QUIT = "QUIT\r\n";
167 flags |= FLAG_SSL; 153 flags |= FLAG_SSL;
168 PORT = 995; 154 PORT = 995;
169 } 155 } else if (!strncmp(SERVICE, "SSMTP", 5)) {
170 else if (!strncmp(SERVICE, "SSMTP", 5)) {
171 EXPECT = "220"; 156 EXPECT = "220";
172 QUIT = "QUIT\r\n"; 157 QUIT = "QUIT\r\n";
173 flags |= FLAG_SSL; 158 flags |= FLAG_SSL;
174 PORT = 465; 159 PORT = 465;
175 } 160 } else if (!strncmp(SERVICE, "JABBER", 6)) {
176 else if (!strncmp(SERVICE, "JABBER", 6)) {
177 SEND = "<stream:stream to=\'host\' xmlns=\'jabber:client\' xmlns:stream=\'http://etherx.jabber.org/streams\'>\n"; 161 SEND = "<stream:stream to=\'host\' xmlns=\'jabber:client\' xmlns:stream=\'http://etherx.jabber.org/streams\'>\n";
178 EXPECT = "<?xml version=\'1.0\'"; 162 EXPECT = "<?xml version=\'1.0\'";
179 QUIT = "</stream:stream>\n"; 163 QUIT = "</stream:stream>\n";
180 flags |= FLAG_HIDE_OUTPUT; 164 flags |= FLAG_HIDE_OUTPUT;
181 PORT = 5222; 165 PORT = 5222;
182 } 166 } else if (!strncmp(SERVICE, "NNTPS", 5)) {
183 else if (!strncmp (SERVICE, "NNTPS", 5)) {
184 server_expect_count = 2; 167 server_expect_count = 2;
185 server_expect[0] = "200"; 168 server_expect[0] = "200";
186 server_expect[1] = "201"; 169 server_expect[1] = "201";
@@ -189,83 +172,86 @@ main (int argc, char **argv)
189 PORT = 563; 172 PORT = 563;
190 } 173 }
191#endif 174#endif
192 else if (!strncmp (SERVICE, "NNTP", 4)) { 175 else if (!strncmp(SERVICE, "NNTP", 4)) {
193 server_expect_count = 2; 176 server_expect_count = 2;
194 server_expect = malloc(sizeof(char *) * server_expect_count); 177 server_expect = malloc(sizeof(char *) * server_expect_count);
195 server_expect[0] = strdup("200"); 178 server_expect[0] = strdup("200");
196 server_expect[1] = strdup("201"); 179 server_expect[1] = strdup("201");
197 QUIT = "QUIT\r\n"; 180 QUIT = "QUIT\r\n";
198 PORT = 119; 181 PORT = 119;
199 } 182 } else if (!strncmp(SERVICE, "CLAMD", 5)) {
200 else if (!strncmp(SERVICE, "CLAMD", 5)) {
201 SEND = "PING"; 183 SEND = "PING";
202 EXPECT = "PONG"; 184 EXPECT = "PONG";
203 QUIT = NULL; 185 QUIT = NULL;
204 PORT = 3310; 186 PORT = 3310;
205 } 187 }
206 /* fallthrough check, so it's supposed to use reverse matching */ 188 /* fallthrough check, so it's supposed to use reverse matching */
207 else if (strcmp (SERVICE, "TCP")) 189 else if (strcmp(SERVICE, "TCP"))
208 usage (_("CRITICAL - Generic check_tcp called with unknown service\n")); 190 usage(_("CRITICAL - Generic check_tcp called with unknown service\n"));
209 191
210 server_address = "127.0.0.1"; 192 server_address = "127.0.0.1";
211 server_port = PORT; 193 server_port = PORT;
212 server_send = SEND; 194 server_send = SEND;
213 server_quit = QUIT; 195 server_quit = QUIT;
214 status = NULL; 196 char *status = NULL;
215 197
216 /* Parse extra opts if any */ 198 /* Parse extra opts if any */
217 argv=np_extra_opts (&argc, argv, progname); 199 argv = np_extra_opts(&argc, argv, progname);
218 200
219 if (process_arguments (argc, argv) == ERROR) 201 if (process_arguments(argc, argv) == ERROR)
220 usage4 (_("Could not parse arguments")); 202 usage4(_("Could not parse arguments"));
221 203
222 if(flags & FLAG_VERBOSE) { 204 if (flags & FLAG_VERBOSE) {
223 printf("Using service %s\n", SERVICE); 205 printf("Using service %s\n", SERVICE);
224 printf("Port: %d\n", server_port); 206 printf("Port: %d\n", server_port);
225 printf("flags: 0x%x\n", (int)flags); 207 printf("flags: 0x%x\n", (int)flags);
226 } 208 }
227 209
228 if(EXPECT && !server_expect_count) 210 if (EXPECT && !server_expect_count)
229 server_expect_count++; 211 server_expect_count++;
230 212
231 if(PROTOCOL==IPPROTO_UDP && !(server_expect_count && server_send)){ 213 if (PROTOCOL == IPPROTO_UDP && !(server_expect_count && server_send)) {
232 usage(_("With UDP checks, a send/expect string must be specified.")); 214 usage(_("With UDP checks, a send/expect string must be specified."));
233 } 215 }
234 216
235 /* set up the timer */ 217 /* set up the timer */
236 signal (SIGALRM, socket_timeout_alarm_handler); 218 signal(SIGALRM, socket_timeout_alarm_handler);
237 alarm (socket_timeout); 219 alarm(socket_timeout);
238 220
239 /* try to connect to the host at the given port number */ 221 /* try to connect to the host at the given port number */
240 gettimeofday (&tv, NULL); 222 struct timeval tv;
223 gettimeofday(&tv, NULL);
241 224
242 result = np_net_connect (server_address, server_port, &sd, PROTOCOL); 225 int result = STATE_UNKNOWN;
243 if (result == STATE_CRITICAL) return econn_refuse_state; 226 result = np_net_connect(server_address, server_port, &sd, PROTOCOL);
227 if (result == STATE_CRITICAL)
228 return econn_refuse_state;
244 229
245#ifdef HAVE_SSL 230#ifdef HAVE_SSL
246 if (flags & FLAG_SSL){ 231 if (flags & FLAG_SSL) {
247 result = np_net_ssl_init_with_hostname(sd, (sni_specified ? sni : NULL)); 232 result = np_net_ssl_init_with_hostname(sd, (sni_specified ? sni : NULL));
248 if (result == STATE_OK && check_cert) { 233 if (result == STATE_OK && check_cert) {
249 result = np_net_ssl_check_cert(days_till_exp_warn, days_till_exp_crit); 234 result = np_net_ssl_check_cert(days_till_exp_warn, days_till_exp_crit);
250 } 235 }
251 } 236 }
252 if(result != STATE_OK){ 237 if (result != STATE_OK) {
253 if(sd) close(sd); 238 if (sd)
239 close(sd);
254 np_net_ssl_cleanup(); 240 np_net_ssl_cleanup();
255 return result; 241 return result;
256 } 242 }
257#endif /* HAVE_SSL */ 243#endif /* HAVE_SSL */
258 244
259 if (server_send != NULL) { /* Something to send? */ 245 if (server_send != NULL) { /* Something to send? */
260 my_send(server_send, strlen(server_send)); 246 my_send(server_send, strlen(server_send));
261 } 247 }
262 248
263 if (delay > 0) { 249 if (delay > 0) {
264 tv.tv_sec += delay; 250 tv.tv_sec += delay;
265 sleep (delay); 251 sleep(delay);
266 } 252 }
267 253
268 if(flags & FLAG_VERBOSE) { 254 if (flags & FLAG_VERBOSE) {
269 if (server_send) { 255 if (server_send) {
270 printf("Send string: %s\n", server_send); 256 printf("Send string: %s\n", server_send);
271 } 257 }
@@ -273,13 +259,17 @@ main (int argc, char **argv)
273 printf("Quit string: %s\n", server_quit); 259 printf("Quit string: %s\n", server_quit);
274 } 260 }
275 printf("server_expect_count: %d\n", (int)server_expect_count); 261 printf("server_expect_count: %d\n", (int)server_expect_count);
276 for(size_t i = 0; i < server_expect_count; i++) 262 for (size_t i = 0; i < server_expect_count; i++)
277 printf("\t%zd: %s\n", i, server_expect[i]); 263 printf("\t%zd: %s\n", i, server_expect[i]);
278 } 264 }
279 265
280 /* if(len) later on, we know we have a non-NULL response */ 266 /* if(len) later on, we know we have a non-NULL response */
281 ssize_t len = 0; 267 ssize_t len = 0;
282 268
269 int match = -1;
270 struct timeval timeout;
271 fd_set rfds;
272 FD_ZERO(&rfds);
283 if (server_expect_count) { 273 if (server_expect_count) {
284 ssize_t received = 0; 274 ssize_t received = 0;
285 275
@@ -294,17 +284,14 @@ main (int argc, char **argv)
294 if (maxbytes && len >= maxbytes) 284 if (maxbytes && len >= maxbytes)
295 break; 285 break;
296 286
297 if ((match = np_expect_match(status, 287 if ((match = np_expect_match(status, server_expect, server_expect_count, match_flags)) != NP_MATCH_RETRY)
298 server_expect,
299 server_expect_count,
300 match_flags)) != NP_MATCH_RETRY)
301 break; 288 break;
302 289
303 /* some protocols wait for further input, so make sure we don't wait forever */ 290 /* some protocols wait for further input, so make sure we don't wait forever */
304 FD_SET(sd, &rfds); 291 FD_SET(sd, &rfds);
305 timeout.tv_sec = READ_TIMEOUT; 292 timeout.tv_sec = READ_TIMEOUT;
306 timeout.tv_usec = 0; 293 timeout.tv_usec = 0;
307 if(select(sd + 1, &rfds, NULL, NULL, &timeout) <= 0) 294 if (select(sd + 1, &rfds, NULL, NULL, &timeout) <= 0)
308 break; 295 break;
309 } 296 }
310 297
@@ -313,26 +300,26 @@ main (int argc, char **argv)
313 300
314 /* no data when expected, so return critical */ 301 /* no data when expected, so return critical */
315 if (len == 0) 302 if (len == 0)
316 die (STATE_CRITICAL, _("No data received from host\n")); 303 die(STATE_CRITICAL, _("No data received from host\n"));
317 304
318 /* print raw output if we're debugging */ 305 /* print raw output if we're debugging */
319 if(flags & FLAG_VERBOSE) 306 if (flags & FLAG_VERBOSE)
320 printf("received %d bytes from host\n#-raw-recv-------#\n%s\n#-raw-recv-------#\n", 307 printf("received %d bytes from host\n#-raw-recv-------#\n%s\n#-raw-recv-------#\n", (int)len + 1, status);
321 (int)len + 1, status);
322 /* strip whitespace from end of output */ 308 /* strip whitespace from end of output */
323 while(--len > 0 && isspace(status[len])) 309 while (--len > 0 && isspace(status[len]))
324 status[len] = '\0'; 310 status[len] = '\0';
325 } 311 }
326 312
327 if (server_quit != NULL) { 313 if (server_quit != NULL) {
328 my_send(server_quit, strlen(server_quit)); 314 my_send(server_quit, strlen(server_quit));
329 } 315 }
330 if (sd) close (sd); 316 if (sd)
317 close(sd);
331#ifdef HAVE_SSL 318#ifdef HAVE_SSL
332 np_net_ssl_cleanup(); 319 np_net_ssl_cleanup();
333#endif 320#endif
334 321
335 microsec = deltime (tv); 322 microsec = deltime(tv);
336 elapsed_time = (double)microsec / 1.0e6; 323 elapsed_time = (double)microsec / 1.0e6;
337 324
338 if (flags & FLAG_TIME_CRIT && elapsed_time > critical_time) 325 if (flags & FLAG_TIME_CRIT && elapsed_time > critical_time)
@@ -341,142 +328,123 @@ main (int argc, char **argv)
341 result = STATE_WARNING; 328 result = STATE_WARNING;
342 329
343 /* did we get the response we hoped? */ 330 /* did we get the response we hoped? */
344 if(match == NP_MATCH_FAILURE && result != STATE_CRITICAL) 331 if (match == NP_MATCH_FAILURE && result != STATE_CRITICAL)
345 result = expect_mismatch_state; 332 result = expect_mismatch_state;
346 333
347 /* reset the alarm */ 334 /* reset the alarm */
348 alarm (0); 335 alarm(0);
349 336
350 /* this is a bit stupid, because we don't want to print the 337 /* this is a bit stupid, because we don't want to print the
351 * response time (which can look ok to the user) if we didn't get 338 * response time (which can look ok to the user) if we didn't get
352 * the response we were looking for. if-else */ 339 * the response we were looking for. if-else */
353 printf("%s %s - ", SERVICE, state_text(result)); 340 printf("%s %s - ", SERVICE, state_text(result));
354 341
355 if(match == NP_MATCH_FAILURE && len && !(flags & FLAG_HIDE_OUTPUT)) 342 if (match == NP_MATCH_FAILURE && len && !(flags & FLAG_HIDE_OUTPUT))
356 printf("Unexpected response from host/socket: %s", status); 343 printf("Unexpected response from host/socket: %s", status);
357 else { 344 else {
358 if(match == NP_MATCH_FAILURE) 345 if (match == NP_MATCH_FAILURE)
359 printf("Unexpected response from host/socket on "); 346 printf("Unexpected response from host/socket on ");
360 else 347 else
361 printf("%.3f second response time on ", elapsed_time); 348 printf("%.3f second response time on ", elapsed_time);
362 if(server_address[0] != '/') { 349 if (server_address[0] != '/') {
363 if (host_specified) 350 if (host_specified)
364 printf("%s port %d", 351 printf("%s port %d", server_address, server_port);
365 server_address, server_port);
366 else 352 else
367 printf("port %d", server_port); 353 printf("port %d", server_port);
368 } 354 } else
369 else
370 printf("socket %s", server_address); 355 printf("socket %s", server_address);
371 } 356 }
372 357
373 if (match != NP_MATCH_FAILURE && !(flags & FLAG_HIDE_OUTPUT) && len) 358 if (match != NP_MATCH_FAILURE && !(flags & FLAG_HIDE_OUTPUT) && len)
374 printf (" [%s]", status); 359 printf(" [%s]", status);
375 360
376 /* perf-data doesn't apply when server doesn't talk properly, 361 /* perf-data doesn't apply when server doesn't talk properly,
377 * so print all zeroes on warn and crit. Use fperfdata since 362 * so print all zeroes on warn and crit. Use fperfdata since
378 * localisation settings can make different outputs */ 363 * localisation settings can make different outputs */
379 if(match == NP_MATCH_FAILURE) 364 if (match == NP_MATCH_FAILURE)
380 printf ("|%s", 365 printf("|%s", fperfdata("time", elapsed_time, "s", (flags & FLAG_TIME_WARN ? true : false), 0,
381 fperfdata ("time", elapsed_time, "s", 366 (flags & FLAG_TIME_CRIT ? true : false), 0, true, 0, true, socket_timeout));
382 (flags & FLAG_TIME_WARN ? true : false), 0,
383 (flags & FLAG_TIME_CRIT ? true : false), 0,
384 true, 0,
385 true, socket_timeout)
386 );
387 else 367 else
388 printf("|%s", 368 printf("|%s", fperfdata("time", elapsed_time, "s", (flags & FLAG_TIME_WARN ? true : false), warning_time,
389 fperfdata ("time", elapsed_time, "s", 369 (flags & FLAG_TIME_CRIT ? true : false), critical_time, true, 0, true, socket_timeout));
390 (flags & FLAG_TIME_WARN ? true : false), warning_time,
391 (flags & FLAG_TIME_CRIT ? true : false), critical_time,
392 true, 0,
393 true, socket_timeout)
394 );
395 370
396 putchar('\n'); 371 putchar('\n');
397 return result; 372 return result;
398} 373}
399 374
400
401
402/* process command-line arguments */ 375/* process command-line arguments */
403static int process_arguments (int argc, char **argv) { 376static int process_arguments(int argc, char **argv) {
404 int c;
405 bool escape = false;
406 char *temp;
407
408 enum { 377 enum {
409 SNI_OPTION = CHAR_MAX + 1 378 SNI_OPTION = CHAR_MAX + 1
410 }; 379 };
411 380
412 int option = 0; 381 static struct option longopts[] = {{"hostname", required_argument, 0, 'H'},
413 static struct option longopts[] = { 382 {"critical", required_argument, 0, 'c'},
414 {"hostname", required_argument, 0, 'H'}, 383 {"warning", required_argument, 0, 'w'},
415 {"critical", required_argument, 0, 'c'}, 384 {"critical-codes", required_argument, 0, 'C'},
416 {"warning", required_argument, 0, 'w'}, 385 {"warning-codes", required_argument, 0, 'W'},
417 {"critical-codes", required_argument, 0, 'C'}, 386 {"timeout", required_argument, 0, 't'},
418 {"warning-codes", required_argument, 0, 'W'}, 387 {"protocol", required_argument, 0, 'P'}, /* FIXME: Unhandled */
419 {"timeout", required_argument, 0, 't'}, 388 {"port", required_argument, 0, 'p'},
420 {"protocol", required_argument, 0, 'P'}, /* FIXME: Unhandled */ 389 {"escape", no_argument, 0, 'E'},
421 {"port", required_argument, 0, 'p'}, 390 {"all", no_argument, 0, 'A'},
422 {"escape", no_argument, 0, 'E'}, 391 {"send", required_argument, 0, 's'},
423 {"all", no_argument, 0, 'A'}, 392 {"expect", required_argument, 0, 'e'},
424 {"send", required_argument, 0, 's'}, 393 {"maxbytes", required_argument, 0, 'm'},
425 {"expect", required_argument, 0, 'e'}, 394 {"quit", required_argument, 0, 'q'},
426 {"maxbytes", required_argument, 0, 'm'}, 395 {"jail", no_argument, 0, 'j'},
427 {"quit", required_argument, 0, 'q'}, 396 {"delay", required_argument, 0, 'd'},
428 {"jail", no_argument, 0, 'j'}, 397 {"refuse", required_argument, 0, 'r'},
429 {"delay", required_argument, 0, 'd'}, 398 {"mismatch", required_argument, 0, 'M'},
430 {"refuse", required_argument, 0, 'r'}, 399 {"use-ipv4", no_argument, 0, '4'},
431 {"mismatch", required_argument, 0, 'M'}, 400 {"use-ipv6", no_argument, 0, '6'},
432 {"use-ipv4", no_argument, 0, '4'}, 401 {"verbose", no_argument, 0, 'v'},
433 {"use-ipv6", no_argument, 0, '6'}, 402 {"version", no_argument, 0, 'V'},
434 {"verbose", no_argument, 0, 'v'}, 403 {"help", no_argument, 0, 'h'},
435 {"version", no_argument, 0, 'V'}, 404 {"ssl", no_argument, 0, 'S'},
436 {"help", no_argument, 0, 'h'}, 405 {"sni", required_argument, 0, SNI_OPTION},
437 {"ssl", no_argument, 0, 'S'}, 406 {"certificate", required_argument, 0, 'D'},
438 {"sni", required_argument, 0, SNI_OPTION}, 407 {0, 0, 0, 0}};
439 {"certificate", required_argument, 0, 'D'},
440 {0, 0, 0, 0}
441 };
442 408
443 if (argc < 2) 409 if (argc < 2)
444 usage4 (_("No arguments found")); 410 usage4(_("No arguments found"));
445 411
446 /* backwards compatibility */ 412 /* backwards compatibility */
447 for (c = 1; c < argc; c++) { 413 for (int i = 1; i < argc; i++) {
448 if (strcmp ("-to", argv[c]) == 0) 414 if (strcmp("-to", argv[i]) == 0)
449 strcpy (argv[c], "-t"); 415 strcpy(argv[i], "-t");
450 else if (strcmp ("-wt", argv[c]) == 0) 416 else if (strcmp("-wt", argv[i]) == 0)
451 strcpy (argv[c], "-w"); 417 strcpy(argv[i], "-w");
452 else if (strcmp ("-ct", argv[c]) == 0) 418 else if (strcmp("-ct", argv[i]) == 0)
453 strcpy (argv[c], "-c"); 419 strcpy(argv[i], "-c");
454 } 420 }
455 421
456 if (!is_option (argv[1])) { 422 if (!is_option(argv[1])) {
457 server_address = argv[1]; 423 server_address = argv[1];
458 argv[1] = argv[0]; 424 argv[1] = argv[0];
459 argv = &argv[1]; 425 argv = &argv[1];
460 argc--; 426 argc--;
461 } 427 }
462 428
463 while (1) { 429 int option_char;
464 c = getopt_long (argc, argv, "+hVv46EAH:s:e:q:m:c:w:t:p:C:W:d:Sr:jD:M:", 430 bool escape = false;
465 longopts, &option); 431 while (true) {
432 int option = 0;
433 option_char = getopt_long(argc, argv, "+hVv46EAH:s:e:q:m:c:w:t:p:C:W:d:Sr:jD:M:", longopts, &option);
466 434
467 if (c == -1 || c == EOF || c == 1) 435 if (option_char == -1 || option_char == EOF || option_char == 1)
468 break; 436 break;
469 437
470 switch (c) { 438 switch (option_char) {
471 case '?': /* print short usage statement if args not parsable */ 439 case '?': /* print short usage statement if args not parsable */
472 usage5 (); 440 usage5();
473 case 'h': /* help */ 441 case 'h': /* help */
474 print_help (); 442 print_help();
475 exit (STATE_UNKNOWN); 443 exit(STATE_UNKNOWN);
476 case 'V': /* version */ 444 case 'V': /* version */
477 print_revision (progname, NP_VERSION); 445 print_revision(progname, NP_VERSION);
478 exit (STATE_UNKNOWN); 446 exit(STATE_UNKNOWN);
479 case 'v': /* verbose mode */ 447 case 'v': /* verbose mode */
480 flags |= FLAG_VERBOSE; 448 flags |= FLAG_VERBOSE;
481 match_flags |= NP_MATCH_VERBOSE; 449 match_flags |= NP_MATCH_VERBOSE;
482 break; 450 break;
@@ -487,43 +455,43 @@ static int process_arguments (int argc, char **argv) {
487#ifdef USE_IPV6 455#ifdef USE_IPV6
488 address_family = AF_INET6; 456 address_family = AF_INET6;
489#else 457#else
490 usage4 (_("IPv6 support not available")); 458 usage4(_("IPv6 support not available"));
491#endif 459#endif
492 break; 460 break;
493 case 'H': /* hostname */ 461 case 'H': /* hostname */
494 host_specified = true; 462 host_specified = true;
495 server_address = optarg; 463 server_address = optarg;
496 break; 464 break;
497 case 'c': /* critical */ 465 case 'c': /* critical */
498 critical_time = strtod (optarg, NULL); 466 critical_time = strtod(optarg, NULL);
499 flags |= FLAG_TIME_CRIT; 467 flags |= FLAG_TIME_CRIT;
500 break; 468 break;
501 case 'j': /* hide output */ 469 case 'j': /* hide output */
502 flags |= FLAG_HIDE_OUTPUT; 470 flags |= FLAG_HIDE_OUTPUT;
503 break; 471 break;
504 case 'w': /* warning */ 472 case 'w': /* warning */
505 warning_time = strtod (optarg, NULL); 473 warning_time = strtod(optarg, NULL);
506 flags |= FLAG_TIME_WARN; 474 flags |= FLAG_TIME_WARN;
507 break; 475 break;
508 case 'C': 476 case 'C':
509 crit_codes = realloc (crit_codes, ++crit_codes_count); 477 crit_codes = realloc(crit_codes, ++crit_codes_count);
510 crit_codes[crit_codes_count - 1] = optarg; 478 crit_codes[crit_codes_count - 1] = optarg;
511 break; 479 break;
512 case 'W': 480 case 'W':
513 warn_codes = realloc (warn_codes, ++warn_codes_count); 481 warn_codes = realloc(warn_codes, ++warn_codes_count);
514 warn_codes[warn_codes_count - 1] = optarg; 482 warn_codes[warn_codes_count - 1] = optarg;
515 break; 483 break;
516 case 't': /* timeout */ 484 case 't': /* timeout */
517 if (!is_intpos (optarg)) 485 if (!is_intpos(optarg))
518 usage4 (_("Timeout interval must be a positive integer")); 486 usage4(_("Timeout interval must be a positive integer"));
519 else 487 else
520 socket_timeout = atoi (optarg); 488 socket_timeout = atoi(optarg);
521 break; 489 break;
522 case 'p': /* port */ 490 case 'p': /* port */
523 if (!is_intpos (optarg)) 491 if (!is_intpos(optarg))
524 usage4 (_("Port must be a positive integer")); 492 usage4(_("Port must be a positive integer"));
525 else 493 else
526 server_port = atoi (optarg); 494 server_port = atoi(optarg);
527 break; 495 break;
528 case 'E': 496 case 'E':
529 escape = true; 497 escape = true;
@@ -537,16 +505,16 @@ static int process_arguments (int argc, char **argv) {
537 case 'e': /* expect string (may be repeated) */ 505 case 'e': /* expect string (may be repeated) */
538 match_flags &= ~NP_MATCH_EXACT; 506 match_flags &= ~NP_MATCH_EXACT;
539 if (server_expect_count == 0) 507 if (server_expect_count == 0)
540 server_expect = malloc (sizeof (char *) * (++server_expect_count)); 508 server_expect = malloc(sizeof(char *) * (++server_expect_count));
541 else 509 else
542 server_expect = realloc (server_expect, sizeof (char *) * (++server_expect_count)); 510 server_expect = realloc(server_expect, sizeof(char *) * (++server_expect_count));
543 server_expect[server_expect_count - 1] = optarg; 511 server_expect[server_expect_count - 1] = optarg;
544 break; 512 break;
545 case 'm': 513 case 'm':
546 if (!is_intpos (optarg)) 514 if (!is_intpos(optarg))
547 usage4 (_("Maxbytes must be a positive integer")); 515 usage4(_("Maxbytes must be a positive integer"));
548 else 516 else
549 maxbytes = strtol (optarg, NULL, 0); 517 maxbytes = strtol(optarg, NULL, 0);
550 break; 518 break;
551 case 'q': 519 case 'q':
552 if (escape) 520 if (escape)
@@ -555,62 +523,62 @@ static int process_arguments (int argc, char **argv) {
555 xasprintf(&server_quit, "%s\r\n", optarg); 523 xasprintf(&server_quit, "%s\r\n", optarg);
556 break; 524 break;
557 case 'r': 525 case 'r':
558 if (!strncmp(optarg,"ok",2)) 526 if (!strncmp(optarg, "ok", 2))
559 econn_refuse_state = STATE_OK; 527 econn_refuse_state = STATE_OK;
560 else if (!strncmp(optarg,"warn",4)) 528 else if (!strncmp(optarg, "warn", 4))
561 econn_refuse_state = STATE_WARNING; 529 econn_refuse_state = STATE_WARNING;
562 else if (!strncmp(optarg,"crit",4)) 530 else if (!strncmp(optarg, "crit", 4))
563 econn_refuse_state = STATE_CRITICAL; 531 econn_refuse_state = STATE_CRITICAL;
564 else 532 else
565 usage4 (_("Refuse must be one of ok, warn, crit")); 533 usage4(_("Refuse must be one of ok, warn, crit"));
566 break; 534 break;
567 case 'M': 535 case 'M':
568 if (!strncmp(optarg,"ok",2)) 536 if (!strncmp(optarg, "ok", 2))
569 expect_mismatch_state = STATE_OK; 537 expect_mismatch_state = STATE_OK;
570 else if (!strncmp(optarg,"warn",4)) 538 else if (!strncmp(optarg, "warn", 4))
571 expect_mismatch_state = STATE_WARNING; 539 expect_mismatch_state = STATE_WARNING;
572 else if (!strncmp(optarg,"crit",4)) 540 else if (!strncmp(optarg, "crit", 4))
573 expect_mismatch_state = STATE_CRITICAL; 541 expect_mismatch_state = STATE_CRITICAL;
574 else 542 else
575 usage4 (_("Mismatch must be one of ok, warn, crit")); 543 usage4(_("Mismatch must be one of ok, warn, crit"));
576 break; 544 break;
577 case 'd': 545 case 'd':
578 if (is_intpos (optarg)) 546 if (is_intpos(optarg))
579 delay = atoi (optarg); 547 delay = atoi(optarg);
580 else 548 else
581 usage4 (_("Delay must be a positive integer")); 549 usage4(_("Delay must be a positive integer"));
582 break; 550 break;
583 case 'D': /* Check SSL cert validity - days 'til certificate expiration */ 551 case 'D': { /* Check SSL cert validity - days 'til certificate expiration */
584#ifdef HAVE_SSL 552#ifdef HAVE_SSL
585# ifdef USE_OPENSSL /* XXX */ 553# ifdef USE_OPENSSL /* XXX */
586 if ((temp=strchr(optarg,','))!=NULL) { 554 char *temp;
587 *temp='\0'; 555 if ((temp = strchr(optarg, ',')) != NULL) {
588 if (!is_intnonneg (optarg)) 556 *temp = '\0';
589 usage2 (_("Invalid certificate expiration period"), optarg); 557 if (!is_intnonneg(optarg))
590 days_till_exp_warn = atoi (optarg); 558 usage2(_("Invalid certificate expiration period"), optarg);
591 *temp=','; 559 days_till_exp_warn = atoi(optarg);
592 temp++; 560 *temp = ',';
593 if (!is_intnonneg (temp)) 561 temp++;
594 usage2 (_("Invalid certificate expiration period"), temp); 562 if (!is_intnonneg(temp))
595 days_till_exp_crit = atoi (temp); 563 usage2(_("Invalid certificate expiration period"), temp);
596 } 564 days_till_exp_crit = atoi(temp);
597 else { 565 } else {
598 days_till_exp_crit=0; 566 days_till_exp_crit = 0;
599 if (!is_intnonneg (optarg)) 567 if (!is_intnonneg(optarg))
600 usage2 (_("Invalid certificate expiration period"), optarg); 568 usage2(_("Invalid certificate expiration period"), optarg);
601 days_till_exp_warn = atoi (optarg); 569 days_till_exp_warn = atoi(optarg);
602 } 570 }
603 check_cert = true; 571 check_cert = true;
604 flags |= FLAG_SSL; 572 flags |= FLAG_SSL;
605 break; 573 } break;
606# endif /* USE_OPENSSL */ 574# endif /* USE_OPENSSL */
607#endif 575#endif
608 /* fallthrough if we don't have ssl */ 576 /* fallthrough if we don't have ssl */
609 case 'S': 577 case 'S':
610#ifdef HAVE_SSL 578#ifdef HAVE_SSL
611 flags |= FLAG_SSL; 579 flags |= FLAG_SSL;
612#else 580#else
613 die (STATE_UNKNOWN, _("Invalid option - SSL is not available")); 581 die(STATE_UNKNOWN, _("Invalid option - SSL is not available"));
614#endif 582#endif
615 break; 583 break;
616 case SNI_OPTION: 584 case SNI_OPTION:
@@ -619,7 +587,7 @@ static int process_arguments (int argc, char **argv) {
619 sni_specified = true; 587 sni_specified = true;
620 sni = optarg; 588 sni = optarg;
621#else 589#else
622 die (STATE_UNKNOWN, _("Invalid option - SSL is not available")); 590 die(STATE_UNKNOWN, _("Invalid option - SSL is not available"));
623#endif 591#endif
624 break; 592 break;
625 case 'A': 593 case 'A':
@@ -628,87 +596,81 @@ static int process_arguments (int argc, char **argv) {
628 } 596 }
629 } 597 }
630 598
631 c = optind; 599 option_char = optind;
632 if(!host_specified && c < argc) 600 if (!host_specified && option_char < argc)
633 server_address = strdup (argv[c++]); 601 server_address = strdup(argv[option_char++]);
634 602
635 if (server_address == NULL) 603 if (server_address == NULL)
636 usage4 (_("You must provide a server address")); 604 usage4(_("You must provide a server address"));
637 else if (server_address[0] != '/' && !is_host(server_address)) 605 else if (server_address[0] != '/' && !is_host(server_address))
638 die (STATE_CRITICAL, "%s %s - %s: %s\n", SERVICE, state_text(STATE_CRITICAL), _("Invalid hostname, address or socket"), server_address); 606 die(STATE_CRITICAL, "%s %s - %s: %s\n", SERVICE, state_text(STATE_CRITICAL), _("Invalid hostname, address or socket"),
607 server_address);
639 608
640 return OK; 609 return OK;
641} 610}
642 611
643 612void print_help(void) {
644void 613 print_revision(progname, NP_VERSION);
645print_help (void) 614
646{ 615 printf("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n");
647 print_revision (progname, NP_VERSION); 616 printf(COPYRIGHT, copyright, email);
648 617
649 printf ("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n"); 618 printf(_("This plugin tests %s connections with the specified host (or unix socket).\n\n"), SERVICE);
650 printf (COPYRIGHT, copyright, email); 619
651 620 print_usage();
652 printf (_("This plugin tests %s connections with the specified host (or unix socket).\n\n"), 621
653 SERVICE); 622 printf(UT_HELP_VRSN);
654 623 printf(UT_EXTRA_OPTS);
655 print_usage (); 624
656 625 printf(UT_HOST_PORT, 'p', "none");
657 printf (UT_HELP_VRSN); 626
658 printf (UT_EXTRA_OPTS); 627 printf(UT_IPv46);
659 628
660 printf (UT_HOST_PORT, 'p', "none"); 629 printf(" %s\n", "-E, --escape");
661 630 printf(" %s\n", _("Can use \\n, \\r, \\t or \\\\ in send or quit string. Must come before send or quit option"));
662 printf (UT_IPv46); 631 printf(" %s\n", _("Default: nothing added to send, \\r\\n added to end of quit"));
663 632 printf(" %s\n", "-s, --send=STRING");
664 printf (" %s\n", "-E, --escape"); 633 printf(" %s\n", _("String to send to the server"));
665 printf (" %s\n", _("Can use \\n, \\r, \\t or \\\\ in send or quit string. Must come before send or quit option")); 634 printf(" %s\n", "-e, --expect=STRING");
666 printf (" %s\n", _("Default: nothing added to send, \\r\\n added to end of quit")); 635 printf(" %s %s\n", _("String to expect in server response"), _("(may be repeated)"));
667 printf (" %s\n", "-s, --send=STRING"); 636 printf(" %s\n", "-A, --all");
668 printf (" %s\n", _("String to send to the server")); 637 printf(" %s\n", _("All expect strings need to occur in server response. Default is any"));
669 printf (" %s\n", "-e, --expect=STRING"); 638 printf(" %s\n", "-q, --quit=STRING");
670 printf (" %s %s\n", _("String to expect in server response"), _("(may be repeated)")); 639 printf(" %s\n", _("String to send server to initiate a clean close of the connection"));
671 printf (" %s\n", "-A, --all"); 640 printf(" %s\n", "-r, --refuse=ok|warn|crit");
672 printf (" %s\n", _("All expect strings need to occur in server response. Default is any")); 641 printf(" %s\n", _("Accept TCP refusals with states ok, warn, crit (default: crit)"));
673 printf (" %s\n", "-q, --quit=STRING"); 642 printf(" %s\n", "-M, --mismatch=ok|warn|crit");
674 printf (" %s\n", _("String to send server to initiate a clean close of the connection")); 643 printf(" %s\n", _("Accept expected string mismatches with states ok, warn, crit (default: warn)"));
675 printf (" %s\n", "-r, --refuse=ok|warn|crit"); 644 printf(" %s\n", "-j, --jail");
676 printf (" %s\n", _("Accept TCP refusals with states ok, warn, crit (default: crit)")); 645 printf(" %s\n", _("Hide output from TCP socket"));
677 printf (" %s\n", "-M, --mismatch=ok|warn|crit"); 646 printf(" %s\n", "-m, --maxbytes=INTEGER");
678 printf (" %s\n", _("Accept expected string mismatches with states ok, warn, crit (default: warn)")); 647 printf(" %s\n", _("Close connection once more than this number of bytes are received"));
679 printf (" %s\n", "-j, --jail"); 648 printf(" %s\n", "-d, --delay=INTEGER");
680 printf (" %s\n", _("Hide output from TCP socket")); 649 printf(" %s\n", _("Seconds to wait between sending string and polling for response"));
681 printf (" %s\n", "-m, --maxbytes=INTEGER");
682 printf (" %s\n", _("Close connection once more than this number of bytes are received"));
683 printf (" %s\n", "-d, --delay=INTEGER");
684 printf (" %s\n", _("Seconds to wait between sending string and polling for response"));
685 650
686#ifdef HAVE_SSL 651#ifdef HAVE_SSL
687 printf (" %s\n", "-D, --certificate=INTEGER[,INTEGER]"); 652 printf(" %s\n", "-D, --certificate=INTEGER[,INTEGER]");
688 printf (" %s\n", _("Minimum number of days a certificate has to be valid.")); 653 printf(" %s\n", _("Minimum number of days a certificate has to be valid."));
689 printf (" %s\n", _("1st is #days for warning, 2nd is critical (if not specified - 0).")); 654 printf(" %s\n", _("1st is #days for warning, 2nd is critical (if not specified - 0)."));
690 printf (" %s\n", "-S, --ssl"); 655 printf(" %s\n", "-S, --ssl");
691 printf (" %s\n", _("Use SSL for the connection.")); 656 printf(" %s\n", _("Use SSL for the connection."));
692 printf (" %s\n", "--sni=STRING"); 657 printf(" %s\n", "--sni=STRING");
693 printf (" %s\n", _("SSL server_name")); 658 printf(" %s\n", _("SSL server_name"));
694#endif 659#endif
695 660
696 printf (UT_WARN_CRIT); 661 printf(UT_WARN_CRIT);
697 662
698 printf (UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); 663 printf(UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
699 664
700 printf (UT_VERBOSE); 665 printf(UT_VERBOSE);
701 666
702 printf (UT_SUPPORT); 667 printf(UT_SUPPORT);
703} 668}
704 669
705 670void print_usage(void) {
706void 671 printf("%s\n", _("Usage:"));
707print_usage (void) 672 printf("%s -H host -p port [-w <warning time>] [-c <critical time>] [-s <send string>]\n", progname);
708{ 673 printf("[-e <expect string>] [-q <quit string>][-m <maximum bytes>] [-d <delay>]\n");
709 printf ("%s\n", _("Usage:")); 674 printf("[-t <timeout seconds>] [-r <refuse state>] [-M <mismatch state>] [-v] [-4|-6] [-j]\n");
710 printf ("%s -H host -p port [-w <warning time>] [-c <critical time>] [-s <send string>]\n",progname); 675 printf("[-D <warn days cert expire>[,<crit days cert expire>]] [-S <use SSL>] [-E]\n");
711 printf ("[-e <expect string>] [-q <quit string>][-m <maximum bytes>] [-d <delay>]\n");
712 printf ("[-t <timeout seconds>] [-r <refuse state>] [-M <mismatch state>] [-v] [-4|-6] [-j]\n");
713 printf ("[-D <warn days cert expire>[,<crit days cert expire>]] [-S <use SSL>] [-E]\n");
714} 676}
diff --git a/plugins/check_time.c b/plugins/check_time.c
index f50ea427..d1f50683 100644
--- a/plugins/check_time.c
+++ b/plugins/check_time.c
@@ -1,35 +1,35 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring check_time plugin 3 * Monitoring check_time plugin
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 1999-2007 Monitoring Plugins Development Team 6 * Copyright (c) 1999-2024 Monitoring Plugins Development Team
7* 7 *
8* Description: 8 * Description:
9* 9 *
10* This file contains the check_time plugin 10 * This file contains the check_time plugin
11* 11 *
12* This plugin will check the time difference with the specified host. 12 * This plugin will check the time difference with the specified host.
13* 13 *
14* 14 *
15* This program is free software: you can redistribute it and/or modify 15 * This program is free software: you can redistribute it and/or modify
16* it under the terms of the GNU General Public License as published by 16 * it under the terms of the GNU General Public License as published by
17* the Free Software Foundation, either version 3 of the License, or 17 * the Free Software Foundation, either version 3 of the License, or
18* (at your option) any later version. 18 * (at your option) any later version.
19* 19 *
20* This program is distributed in the hope that it will be useful, 20 * This program is distributed in the hope that it will be useful,
21* but WITHOUT ANY WARRANTY; without even the implied warranty of 21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23* GNU General Public License for more details. 23 * GNU General Public License for more details.
24* 24 *
25* You should have received a copy of the GNU General Public License 25 * You should have received a copy of the GNU General Public License
26* along with this program. If not, see <http://www.gnu.org/licenses/>. 26 * along with this program. If not, see <http://www.gnu.org/licenses/>.
27* 27 *
28* 28 *
29*****************************************************************************/ 29 *****************************************************************************/
30 30
31const char *progname = "check_time"; 31const char *progname = "check_time";
32const char *copyright = "1999-2007"; 32const char *copyright = "1999-2024";
33const char *email = "devel@monitoring-plugins.org"; 33const char *email = "devel@monitoring-plugins.org";
34 34
35#include "common.h" 35#include "common.h"
@@ -40,55 +40,51 @@ enum {
40 TIME_PORT = 37 40 TIME_PORT = 37
41}; 41};
42 42
43#define UNIX_EPOCH 2208988800UL 43#define UNIX_EPOCH 2208988800UL
44 44
45uint32_t raw_server_time; 45static uint32_t raw_server_time;
46unsigned long server_time, diff_time; 46static unsigned long server_time, diff_time;
47int warning_time = 0; 47static int warning_time = 0;
48bool check_warning_time = false; 48static bool check_warning_time = false;
49int critical_time = 0; 49static int critical_time = 0;
50bool check_critical_time = false; 50static bool check_critical_time = false;
51unsigned long warning_diff = 0; 51static unsigned long warning_diff = 0;
52bool check_warning_diff = false; 52static bool check_warning_diff = false;
53unsigned long critical_diff = 0; 53static unsigned long critical_diff = 0;
54bool check_critical_diff = false; 54static bool check_critical_diff = false;
55int server_port = TIME_PORT; 55static int server_port = TIME_PORT;
56char *server_address = NULL; 56static char *server_address = NULL;
57bool use_udp = false; 57static bool use_udp = false;
58 58
59int process_arguments (int, char **); 59static int process_arguments(int, char **);
60void print_help (void); 60static void print_help(void);
61void print_usage (void); 61void print_usage(void);
62 62
63int 63int main(int argc, char **argv) {
64main (int argc, char **argv) 64 setlocale(LC_ALL, "");
65{ 65 bindtextdomain(PACKAGE, LOCALEDIR);
66 int sd; 66 textdomain(PACKAGE);
67 int result = STATE_UNKNOWN;
68 time_t conntime;
69
70 setlocale (LC_ALL, "");
71 bindtextdomain (PACKAGE, LOCALEDIR);
72 textdomain (PACKAGE);
73 67
74 /* Parse extra opts if any */ 68 /* Parse extra opts if any */
75 argv=np_extra_opts (&argc, argv, progname); 69 argv = np_extra_opts(&argc, argv, progname);
76 70
77 if (process_arguments (argc, argv) == ERROR) 71 if (process_arguments(argc, argv) == ERROR)
78 usage4 (_("Could not parse arguments")); 72 usage4(_("Could not parse arguments"));
79 73
80 /* initialize alarm signal handling */ 74 /* initialize alarm signal handling */
81 signal (SIGALRM, socket_timeout_alarm_handler); 75 signal(SIGALRM, socket_timeout_alarm_handler);
82 76
83 /* set socket timeout */ 77 /* set socket timeout */
84 alarm (socket_timeout); 78 alarm(socket_timeout);
85 time (&start_time); 79 time(&start_time);
86 80
81 int socket;
82 int result = STATE_UNKNOWN;
87 /* try to connect to the host at the given port number */ 83 /* try to connect to the host at the given port number */
88 if (use_udp) { 84 if (use_udp) {
89 result = my_udp_connect (server_address, server_port, &sd); 85 result = my_udp_connect(server_address, server_port, &socket);
90 } else { 86 } else {
91 result = my_tcp_connect (server_address, server_port, &sd); 87 result = my_tcp_connect(server_address, server_port, &socket);
92 } 88 }
93 89
94 if (result != STATE_OK) { 90 if (result != STATE_OK) {
@@ -98,34 +94,30 @@ main (int argc, char **argv)
98 result = STATE_WARNING; 94 result = STATE_WARNING;
99 else 95 else
100 result = STATE_UNKNOWN; 96 result = STATE_UNKNOWN;
101 die (result, 97 die(result, _("TIME UNKNOWN - could not connect to server %s, port %d\n"), server_address, server_port);
102 _("TIME UNKNOWN - could not connect to server %s, port %d\n"),
103 server_address, server_port);
104 } 98 }
105 99
106 if (use_udp) { 100 if (use_udp) {
107 if (send (sd, "", 0, 0) < 0) { 101 if (send(socket, "", 0, 0) < 0) {
108 if (check_critical_time) 102 if (check_critical_time)
109 result = STATE_CRITICAL; 103 result = STATE_CRITICAL;
110 else if (check_warning_time) 104 else if (check_warning_time)
111 result = STATE_WARNING; 105 result = STATE_WARNING;
112 else 106 else
113 result = STATE_UNKNOWN; 107 result = STATE_UNKNOWN;
114 die (result, 108 die(result, _("TIME UNKNOWN - could not send UDP request to server %s, port %d\n"), server_address, server_port);
115 _("TIME UNKNOWN - could not send UDP request to server %s, port %d\n"),
116 server_address, server_port);
117 } 109 }
118 } 110 }
119 111
120 /* watch for the connection string */ 112 /* watch for the connection string */
121 result = recv (sd, (void *)&raw_server_time, sizeof (raw_server_time), 0); 113 result = recv(socket, (void *)&raw_server_time, sizeof(raw_server_time), 0);
122 114
123 /* close the connection */ 115 /* close the connection */
124 close (sd); 116 close(socket);
125 117
126 /* reset the alarm */ 118 /* reset the alarm */
127 time (&end_time); 119 time(&end_time);
128 alarm (0); 120 alarm(0);
129 121
130 /* return a WARNING status if we couldn't read any data */ 122 /* return a WARNING status if we couldn't read any data */
131 if (result <= 0) { 123 if (result <= 0) {
@@ -135,240 +127,205 @@ main (int argc, char **argv)
135 result = STATE_WARNING; 127 result = STATE_WARNING;
136 else 128 else
137 result = STATE_UNKNOWN; 129 result = STATE_UNKNOWN;
138 die (result, 130 die(result, _("TIME UNKNOWN - no data received from server %s, port %d\n"), server_address, server_port);
139 _("TIME UNKNOWN - no data received from server %s, port %d\n"),
140 server_address, server_port);
141 } 131 }
142 132
143 result = STATE_OK; 133 result = STATE_OK;
144 134
145 conntime = (end_time - start_time); 135 time_t conntime = (end_time - start_time);
146 if (check_critical_time&& conntime > critical_time) 136 if (check_critical_time && conntime > critical_time)
147 result = STATE_CRITICAL; 137 result = STATE_CRITICAL;
148 else if (check_warning_time && conntime > warning_time) 138 else if (check_warning_time && conntime > warning_time)
149 result = STATE_WARNING; 139 result = STATE_WARNING;
150 140
151 if (result != STATE_OK) 141 if (result != STATE_OK)
152 die (result, _("TIME %s - %d second response time|%s\n"), 142 die(result, _("TIME %s - %d second response time|%s\n"), state_text(result), (int)conntime,
153 state_text (result), (int)conntime, 143 perfdata("time", (long)conntime, "s", check_warning_time, (long)warning_time, check_critical_time, (long)critical_time, true, 0,
154 perfdata ("time", (long)conntime, "s", 144 false, 0));
155 check_warning_time, (long)warning_time, 145
156 check_critical_time, (long)critical_time, 146 server_time = ntohl(raw_server_time) - UNIX_EPOCH;
157 true, 0, false, 0));
158
159 server_time = ntohl (raw_server_time) - UNIX_EPOCH;
160 if (server_time > (unsigned long)end_time) 147 if (server_time > (unsigned long)end_time)
161 diff_time = server_time - (unsigned long)end_time; 148 diff_time = server_time - (unsigned long)end_time;
162 else 149 else
163 diff_time = (unsigned long)end_time - server_time; 150 diff_time = (unsigned long)end_time - server_time;
164 151
165 if (check_critical_diff&& diff_time > critical_diff) 152 if (check_critical_diff && diff_time > critical_diff)
166 result = STATE_CRITICAL; 153 result = STATE_CRITICAL;
167 else if (check_warning_diff&& diff_time > warning_diff) 154 else if (check_warning_diff && diff_time > warning_diff)
168 result = STATE_WARNING; 155 result = STATE_WARNING;
169 156
170 printf (_("TIME %s - %lu second time difference|%s %s\n"), 157 printf(_("TIME %s - %lu second time difference|%s %s\n"), state_text(result), diff_time,
171 state_text (result), diff_time, 158 perfdata("time", (long)conntime, "s", check_warning_time, (long)warning_time, check_critical_time, (long)critical_time, true, 0,
172 perfdata ("time", (long)conntime, "s", 159 false, 0),
173 check_warning_time, (long)warning_time, 160 perfdata("offset", diff_time, "s", check_warning_diff, warning_diff, check_critical_diff, critical_diff, true, 0, false, 0));
174 check_critical_time, (long)critical_time,
175 true, 0, false, 0),
176 perfdata ("offset", diff_time, "s",
177 check_warning_diff, warning_diff,
178 check_critical_diff, critical_diff,
179 true, 0, false, 0));
180 return result; 161 return result;
181} 162}
182 163
183
184
185/* process command-line arguments */ 164/* process command-line arguments */
186int 165int process_arguments(int argc, char **argv) {
187process_arguments (int argc, char **argv) 166 static struct option longopts[] = {{"hostname", required_argument, 0, 'H'},
188{ 167 {"warning-variance", required_argument, 0, 'w'},
189 int c; 168 {"critical-variance", required_argument, 0, 'c'},
190 169 {"warning-connect", required_argument, 0, 'W'},
191 int option = 0; 170 {"critical-connect", required_argument, 0, 'C'},
192 static struct option longopts[] = { 171 {"port", required_argument, 0, 'p'},
193 {"hostname", required_argument, 0, 'H'}, 172 {"udp", no_argument, 0, 'u'},
194 {"warning-variance", required_argument, 0, 'w'}, 173 {"timeout", required_argument, 0, 't'},
195 {"critical-variance", required_argument, 0, 'c'}, 174 {"version", no_argument, 0, 'V'},
196 {"warning-connect", required_argument, 0, 'W'}, 175 {"help", no_argument, 0, 'h'},
197 {"critical-connect", required_argument, 0, 'C'}, 176 {0, 0, 0, 0}};
198 {"port", required_argument, 0, 'p'},
199 {"udp", no_argument, 0, 'u'},
200 {"timeout", required_argument, 0, 't'},
201 {"version", no_argument, 0, 'V'},
202 {"help", no_argument, 0, 'h'},
203 {0, 0, 0, 0}
204 };
205 177
206 if (argc < 2) 178 if (argc < 2)
207 usage ("\n"); 179 usage("\n");
208 180
209 for (c = 1; c < argc; c++) { 181 for (int i = 1; i < argc; i++) {
210 if (strcmp ("-to", argv[c]) == 0) 182 if (strcmp("-to", argv[i]) == 0)
211 strcpy (argv[c], "-t"); 183 strcpy(argv[i], "-t");
212 else if (strcmp ("-wd", argv[c]) == 0) 184 else if (strcmp("-wd", argv[i]) == 0)
213 strcpy (argv[c], "-w"); 185 strcpy(argv[i], "-w");
214 else if (strcmp ("-cd", argv[c]) == 0) 186 else if (strcmp("-cd", argv[i]) == 0)
215 strcpy (argv[c], "-c"); 187 strcpy(argv[i], "-c");
216 else if (strcmp ("-wt", argv[c]) == 0) 188 else if (strcmp("-wt", argv[i]) == 0)
217 strcpy (argv[c], "-W"); 189 strcpy(argv[i], "-W");
218 else if (strcmp ("-ct", argv[c]) == 0) 190 else if (strcmp("-ct", argv[i]) == 0)
219 strcpy (argv[c], "-C"); 191 strcpy(argv[i], "-C");
220 } 192 }
221 193
194 int option_char;
222 while (true) { 195 while (true) {
223 c = getopt_long (argc, argv, "hVH:w:c:W:C:p:t:u", longopts, 196 int option = 0;
224 &option); 197 option_char = getopt_long(argc, argv, "hVH:w:c:W:C:p:t:u", longopts, &option);
225 198
226 if (c == -1 || c == EOF) 199 if (option_char == -1 || option_char == EOF)
227 break; 200 break;
228 201
229 switch (c) { 202 switch (option_char) {
230 case '?': /* print short usage statement if args not parsable */ 203 case '?': /* print short usage statement if args not parsable */
231 usage5 (); 204 usage5();
232 case 'h': /* help */ 205 case 'h': /* help */
233 print_help (); 206 print_help();
234 exit (STATE_UNKNOWN); 207 exit(STATE_UNKNOWN);
235 case 'V': /* version */ 208 case 'V': /* version */
236 print_revision (progname, NP_VERSION); 209 print_revision(progname, NP_VERSION);
237 exit (STATE_UNKNOWN); 210 exit(STATE_UNKNOWN);
238 case 'H': /* hostname */ 211 case 'H': /* hostname */
239 if (!is_host (optarg)) 212 if (!is_host(optarg))
240 usage2 (_("Invalid hostname/address"), optarg); 213 usage2(_("Invalid hostname/address"), optarg);
241 server_address = optarg; 214 server_address = optarg;
242 break; 215 break;
243 case 'w': /* warning-variance */ 216 case 'w': /* warning-variance */
244 if (is_intnonneg (optarg)) { 217 if (is_intnonneg(optarg)) {
245 warning_diff = strtoul (optarg, NULL, 10); 218 warning_diff = strtoul(optarg, NULL, 10);
246 check_warning_diff = true; 219 check_warning_diff = true;
247 } 220 } else if (strspn(optarg, "0123456789:,") > 0) {
248 else if (strspn (optarg, "0123456789:,") > 0) { 221 if (sscanf(optarg, "%lu%*[:,]%d", &warning_diff, &warning_time) == 2) {
249 if (sscanf (optarg, "%lu%*[:,]%d", &warning_diff, &warning_time) == 2) {
250 check_warning_diff = true; 222 check_warning_diff = true;
251 check_warning_time = true; 223 check_warning_time = true;
224 } else {
225 usage4(_("Warning thresholds must be a positive integer"));
252 } 226 }
253 else { 227 } else {
254 usage4 (_("Warning thresholds must be a positive integer")); 228 usage4(_("Warning threshold must be a positive integer"));
255 }
256 }
257 else {
258 usage4 (_("Warning threshold must be a positive integer"));
259 } 229 }
260 break; 230 break;
261 case 'c': /* critical-variance */ 231 case 'c': /* critical-variance */
262 if (is_intnonneg (optarg)) { 232 if (is_intnonneg(optarg)) {
263 critical_diff = strtoul (optarg, NULL, 10); 233 critical_diff = strtoul(optarg, NULL, 10);
264 check_critical_diff = true; 234 check_critical_diff = true;
265 } 235 } else if (strspn(optarg, "0123456789:,") > 0) {
266 else if (strspn (optarg, "0123456789:,") > 0) { 236 if (sscanf(optarg, "%lu%*[:,]%d", &critical_diff, &critical_time) == 2) {
267 if (sscanf (optarg, "%lu%*[:,]%d", &critical_diff, &critical_time) ==
268 2) {
269 check_critical_diff = true; 237 check_critical_diff = true;
270 check_critical_time = true; 238 check_critical_time = true;
239 } else {
240 usage4(_("Critical thresholds must be a positive integer"));
271 } 241 }
272 else { 242 } else {
273 usage4 (_("Critical thresholds must be a positive integer")); 243 usage4(_("Critical threshold must be a positive integer"));
274 }
275 }
276 else {
277 usage4 (_("Critical threshold must be a positive integer"));
278 } 244 }
279 break; 245 break;
280 case 'W': /* warning-connect */ 246 case 'W': /* warning-connect */
281 if (!is_intnonneg (optarg)) 247 if (!is_intnonneg(optarg))
282 usage4 (_("Warning threshold must be a positive integer")); 248 usage4(_("Warning threshold must be a positive integer"));
283 else 249 else
284 warning_time = atoi (optarg); 250 warning_time = atoi(optarg);
285 check_warning_time = true; 251 check_warning_time = true;
286 break; 252 break;
287 case 'C': /* critical-connect */ 253 case 'C': /* critical-connect */
288 if (!is_intnonneg (optarg)) 254 if (!is_intnonneg(optarg))
289 usage4 (_("Critical threshold must be a positive integer")); 255 usage4(_("Critical threshold must be a positive integer"));
290 else 256 else
291 critical_time = atoi (optarg); 257 critical_time = atoi(optarg);
292 check_critical_time = true; 258 check_critical_time = true;
293 break; 259 break;
294 case 'p': /* port */ 260 case 'p': /* port */
295 if (!is_intnonneg (optarg)) 261 if (!is_intnonneg(optarg))
296 usage4 (_("Port must be a positive integer")); 262 usage4(_("Port must be a positive integer"));
297 else 263 else
298 server_port = atoi (optarg); 264 server_port = atoi(optarg);
299 break; 265 break;
300 case 't': /* timeout */ 266 case 't': /* timeout */
301 if (!is_intnonneg (optarg)) 267 if (!is_intnonneg(optarg))
302 usage2 (_("Timeout interval must be a positive integer"), optarg); 268 usage2(_("Timeout interval must be a positive integer"), optarg);
303 else 269 else
304 socket_timeout = atoi (optarg); 270 socket_timeout = atoi(optarg);
305 break; 271 break;
306 case 'u': /* udp */ 272 case 'u': /* udp */
307 use_udp = true; 273 use_udp = true;
308 } 274 }
309 } 275 }
310 276
311 c = optind; 277 option_char = optind;
312 if (server_address == NULL) { 278 if (server_address == NULL) {
313 if (argc > c) { 279 if (argc > option_char) {
314 if (!is_host (argv[c])) 280 if (!is_host(argv[option_char]))
315 usage2 (_("Invalid hostname/address"), optarg); 281 usage2(_("Invalid hostname/address"), optarg);
316 server_address = argv[c]; 282 server_address = argv[option_char];
317 } 283 } else {
318 else { 284 usage4(_("Hostname was not supplied"));
319 usage4 (_("Hostname was not supplied"));
320 } 285 }
321 } 286 }
322 287
323 return OK; 288 return OK;
324} 289}
325 290
326 291void print_help(void) {
327
328void
329print_help (void)
330{
331 char *myport; 292 char *myport;
332 xasprintf (&myport, "%d", TIME_PORT); 293 xasprintf(&myport, "%d", TIME_PORT);
333 294
334 print_revision (progname, NP_VERSION); 295 print_revision(progname, NP_VERSION);
335 296
336 printf ("Copyright (c) 1999 Ethan Galstad\n"); 297 printf("Copyright (c) 1999 Ethan Galstad\n");
337 printf (COPYRIGHT, copyright, email); 298 printf(COPYRIGHT, copyright, email);
338 299
339 printf ("%s\n", _("This plugin will check the time on the specified host.")); 300 printf("%s\n", _("This plugin will check the time on the specified host."));
340 301
341 printf ("\n\n"); 302 printf("\n\n");
342 303
343 print_usage (); 304 print_usage();
344 305
345 printf (UT_HELP_VRSN); 306 printf(UT_HELP_VRSN);
346 printf (UT_EXTRA_OPTS); 307 printf(UT_EXTRA_OPTS);
347 308
348 printf (UT_HOST_PORT, 'p', myport); 309 printf(UT_HOST_PORT, 'p', myport);
349 310
350 printf (" %s\n", "-u, --udp"); 311 printf(" %s\n", "-u, --udp");
351 printf (" %s\n", _("Use UDP to connect, not TCP")); 312 printf(" %s\n", _("Use UDP to connect, not TCP"));
352 printf (" %s\n", "-w, --warning-variance=INTEGER"); 313 printf(" %s\n", "-w, --warning-variance=INTEGER");
353 printf (" %s\n", _("Time difference (sec.) necessary to result in a warning status")); 314 printf(" %s\n", _("Time difference (sec.) necessary to result in a warning status"));
354 printf (" %s\n", "-c, --critical-variance=INTEGER"); 315 printf(" %s\n", "-c, --critical-variance=INTEGER");
355 printf (" %s\n", _("Time difference (sec.) necessary to result in a critical status")); 316 printf(" %s\n", _("Time difference (sec.) necessary to result in a critical status"));
356 printf (" %s\n", "-W, --warning-connect=INTEGER"); 317 printf(" %s\n", "-W, --warning-connect=INTEGER");
357 printf (" %s\n", _("Response time (sec.) necessary to result in warning status")); 318 printf(" %s\n", _("Response time (sec.) necessary to result in warning status"));
358 printf (" %s\n", "-C, --critical-connect=INTEGER"); 319 printf(" %s\n", "-C, --critical-connect=INTEGER");
359 printf (" %s\n", _("Response time (sec.) necessary to result in critical status")); 320 printf(" %s\n", _("Response time (sec.) necessary to result in critical status"));
360 321
361 printf (UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); 322 printf(UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
362 323
363 printf (UT_SUPPORT); 324 printf(UT_SUPPORT);
364} 325}
365 326
366 327void print_usage(void) {
367 328 printf("%s\n", _("Usage:"));
368void 329 printf("%s -H <host_address> [-p port] [-u] [-w variance] [-c variance]\n", progname);
369print_usage (void) 330 printf(" [-W connect_time] [-C connect_time] [-t timeout]\n");
370{
371 printf ("%s\n", _("Usage:"));
372 printf ("%s -H <host_address> [-p port] [-u] [-w variance] [-c variance]\n",progname);
373 printf (" [-W connect_time] [-C connect_time] [-t timeout]\n");
374} 331}
diff --git a/plugins/check_ups.c b/plugins/check_ups.c
index 2fb04eef..adb7ab81 100644
--- a/plugins/check_ups.c
+++ b/plugins/check_ups.c
@@ -1,39 +1,39 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring check_ups plugin 3 * Monitoring check_ups plugin
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 2000 Tom Shields 6 * Copyright (c) 2000 Tom Shields
7* 2004 Alain Richard <alain.richard@equation.fr> 7 * 2004 Alain Richard <alain.richard@equation.fr>
8* 2004 Arnaud Quette <arnaud.quette@mgeups.com> 8 * 2004 Arnaud Quette <arnaud.quette@mgeups.com>
9* Copyright (c) 2002-2007 Monitoring Plugins Development Team 9 * Copyright (c) 2002-2024 Monitoring Plugins Development Team
10* 10 *
11* Description: 11 * Description:
12* 12 *
13* This file contains Network UPS Tools plugin for Monitoring 13 * This file contains Network UPS Tools plugin for Monitoring
14* 14 *
15* This plugin tests the UPS service on the specified host. Network UPS Tools 15 * This plugin tests the UPS service on the specified host. Network UPS Tools
16* from www.networkupstools.org must be running for this plugin to work. 16 * from www.networkupstools.org must be running for this plugin to work.
17* 17 *
18* 18 *
19* This program is free software: you can redistribute it and/or modify 19 * This program is free software: you can redistribute it and/or modify
20* it under the terms of the GNU General Public License as published by 20 * it under the terms of the GNU General Public License as published by
21* the Free Software Foundation, either version 3 of the License, or 21 * the Free Software Foundation, either version 3 of the License, or
22* (at your option) any later version. 22 * (at your option) any later version.
23* 23 *
24* This program is distributed in the hope that it will be useful, 24 * This program is distributed in the hope that it will be useful,
25* but WITHOUT ANY WARRANTY; without even the implied warranty of 25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27* GNU General Public License for more details. 27 * GNU General Public License for more details.
28* 28 *
29* You should have received a copy of the GNU General Public License 29 * You should have received a copy of the GNU General Public License
30* along with this program. If not, see <http://www.gnu.org/licenses/>. 30 * along with this program. If not, see <http://www.gnu.org/licenses/>.
31* 31 *
32* 32 *
33*****************************************************************************/ 33 *****************************************************************************/
34 34
35const char *progname = "check_ups"; 35const char *progname = "check_ups";
36const char *copyright = "2000-2007"; 36const char *copyright = "2000-2024";
37const char *email = "devel@monitoring-plugins.org"; 37const char *email = "devel@monitoring-plugins.org";
38 38
39#include "common.h" 39#include "common.h"
@@ -44,656 +44,667 @@ enum {
44 PORT = 3493 44 PORT = 3493
45}; 45};
46 46
47#define CHECK_NONE 0 47#define UPS_NONE 0 /* no supported options */
48 48#define UPS_UTILITY 1 /* supports utility line */
49#define UPS_NONE 0 /* no supported options */ 49#define UPS_BATTPCT 2 /* supports percent battery remaining */
50#define UPS_UTILITY 1 /* supports utility line */ 50#define UPS_STATUS 4 /* supports UPS status */
51#define UPS_BATTPCT 2 /* supports percent battery remaining */ 51#define UPS_TEMP 8 /* supports UPS temperature */
52#define UPS_STATUS 4 /* supports UPS status */ 52#define UPS_LOADPCT 16 /* supports load percent */
53#define UPS_TEMP 8 /* supports UPS temperature */
54#define UPS_LOADPCT 16 /* supports load percent */
55#define UPS_REALPOWER 32 /* supports real power */ 53#define UPS_REALPOWER 32 /* supports real power */
56 54
57#define UPSSTATUS_NONE 0 55#define UPSSTATUS_NONE 0
58#define UPSSTATUS_OFF 1 56#define UPSSTATUS_OFF 1
59#define UPSSTATUS_OL 2 57#define UPSSTATUS_OL 2
60#define UPSSTATUS_OB 4 58#define UPSSTATUS_OB 4
61#define UPSSTATUS_LB 8 59#define UPSSTATUS_LB 8
62#define UPSSTATUS_CAL 16 60#define UPSSTATUS_CAL 16
63#define UPSSTATUS_RB 32 /*Replace Battery */ 61#define UPSSTATUS_RB 32 /*Replace Battery */
64#define UPSSTATUS_BYPASS 64 62#define UPSSTATUS_BYPASS 64
65#define UPSSTATUS_OVER 128 63#define UPSSTATUS_OVER 128
66#define UPSSTATUS_TRIM 256 64#define UPSSTATUS_TRIM 256
67#define UPSSTATUS_BOOST 512 65#define UPSSTATUS_BOOST 512
68#define UPSSTATUS_CHRG 1024 66#define UPSSTATUS_CHRG 1024
69#define UPSSTATUS_DISCHRG 2048 67#define UPSSTATUS_DISCHRG 2048
70#define UPSSTATUS_UNKNOWN 4096 68#define UPSSTATUS_UNKNOWN 4096
71 69#define UPSSTATUS_ALARM 8192
72enum { NOSUCHVAR = ERROR-1 }; 70
73 71enum {
74int server_port = PORT; 72 NOSUCHVAR = ERROR - 1
75char *server_address; 73};
76char *ups_name = NULL; 74
77double warning_value = 0.0; 75typedef struct ups_config {
78double critical_value = 0.0; 76 unsigned int server_port;
79bool check_warn = false; 77 char *server_address;
80bool check_crit = false; 78 char *ups_name;
81int check_variable = UPS_NONE; 79 double warning_value;
82int supported_options = UPS_NONE; 80 double critical_value;
83int status = UPSSTATUS_NONE; 81 bool check_warn;
84 82 bool check_crit;
85double ups_utility_voltage = 0.0; 83 int check_variable;
86double ups_battery_percent = 0.0; 84 int status;
87double ups_load_percent = 0.0; 85 bool temp_output_c;
88double ups_temperature = 0.0; 86} ups_config;
89double ups_realpower = 0.0; 87
90char *ups_status; 88ups_config ups_config_init(void) {
91bool temp_output_c = false; 89 ups_config tmp = {0};
92 90 tmp.server_port = PORT;
93int determine_status (void); 91 tmp.server_address = NULL;
94int get_ups_variable (const char *, char *); 92 tmp.ups_name = NULL;
95 93 tmp.check_variable = UPS_NONE;
96int process_arguments (int, char **); 94 tmp.status = UPSSTATUS_NONE;
97int validate_arguments (void); 95
98void print_help (void); 96 return tmp;
99void print_usage (void); 97}
100 98
101int 99// Forward declarations
102main (int argc, char **argv) 100int determine_status(ups_config *, int *supported_options);
103{ 101int get_ups_variable(const char *, char *, const ups_config config);
104 int result = STATE_UNKNOWN; 102
105 char *message; 103int process_arguments(int, char **, ups_config *);
104int validate_arguments(ups_config);
105void print_help(void);
106void print_usage(void);
107
108int main(int argc, char **argv) {
109 setlocale(LC_ALL, "");
110 bindtextdomain(PACKAGE, LOCALEDIR);
111 textdomain(PACKAGE);
112
113 char *ups_status;
114 ups_status = strdup("N/A");
115
106 char *data; 116 char *data;
107 char *tunits; 117 data = strdup("");
108 char temp_buffer[MAX_INPUT_BUFFER];
109 double ups_utility_deviation = 0.0;
110 int res;
111 118
112 setlocale (LC_ALL, ""); 119 char *message;
113 bindtextdomain (PACKAGE, LOCALEDIR); 120 message = strdup("");
114 textdomain (PACKAGE);
115 121
116 ups_status = strdup ("N/A"); 122 // Exit result
117 data = strdup (""); 123 int result = STATE_UNKNOWN;
118 message = strdup ("");
119 124
120 /* Parse extra opts if any */ 125 /* Parse extra opts if any */
121 argv=np_extra_opts (&argc, argv, progname); 126 argv = np_extra_opts(&argc, argv, progname);
127
128 // Config from commandline
129 ups_config config = ups_config_init();
122 130
123 if (process_arguments (argc, argv) == ERROR) 131 if (process_arguments(argc, argv, &config) == ERROR) {
124 usage4 (_("Could not parse arguments")); 132 usage4(_("Could not parse arguments"));
133 }
125 134
126 /* initialize alarm signal handling */ 135 /* initialize alarm signal handling */
127 signal (SIGALRM, socket_timeout_alarm_handler); 136 signal(SIGALRM, socket_timeout_alarm_handler);
128 137
129 /* set socket timeout */ 138 /* set socket timeout */
130 alarm (socket_timeout); 139 alarm(socket_timeout);
140
141 int supported_options = UPS_NONE;
131 142
132 /* get the ups status if possible */ 143 /* get the ups status if possible */
133 if (determine_status () != OK) 144 if (determine_status(&config, &supported_options) != OK) {
134 return STATE_CRITICAL; 145 return STATE_CRITICAL;
146 }
147
135 if (supported_options & UPS_STATUS) { 148 if (supported_options & UPS_STATUS) {
136 149
137 ups_status = strdup (""); 150 ups_status = strdup("");
151
138 result = STATE_OK; 152 result = STATE_OK;
139 153
140 if (status & UPSSTATUS_OFF) { 154 if (config.status & UPSSTATUS_OFF) {
141 xasprintf (&ups_status, "Off"); 155 xasprintf(&ups_status, "Off");
142 result = STATE_CRITICAL; 156 result = STATE_CRITICAL;
143 } 157 } else if ((config.status & (UPSSTATUS_OB | UPSSTATUS_LB)) == (UPSSTATUS_OB | UPSSTATUS_LB)) {
144 else if ((status & (UPSSTATUS_OB | UPSSTATUS_LB)) == 158 xasprintf(&ups_status, _("On Battery, Low Battery"));
145 (UPSSTATUS_OB | UPSSTATUS_LB)) {
146 xasprintf (&ups_status, _("On Battery, Low Battery"));
147 result = STATE_CRITICAL; 159 result = STATE_CRITICAL;
148 } 160 } else {
149 else { 161 if (config.status & UPSSTATUS_OL) {
150 if (status & UPSSTATUS_OL) { 162 xasprintf(&ups_status, "%s%s", ups_status, _("Online"));
151 xasprintf (&ups_status, "%s%s", ups_status, _("Online")); 163 }
164 if (config.status & UPSSTATUS_OB) {
165 xasprintf(&ups_status, "%s%s", ups_status, _("On Battery"));
166 result = max_state(result, STATE_WARNING);
152 } 167 }
153 if (status & UPSSTATUS_OB) { 168 if (config.status & UPSSTATUS_LB) {
154 xasprintf (&ups_status, "%s%s", ups_status, _("On Battery")); 169 xasprintf(&ups_status, "%s%s", ups_status, _(", Low Battery"));
155 result = STATE_WARNING; 170 result = max_state(result, STATE_WARNING);
156 } 171 }
157 if (status & UPSSTATUS_LB) { 172 if (config.status & UPSSTATUS_CAL) {
158 xasprintf (&ups_status, "%s%s", ups_status, _(", Low Battery")); 173 xasprintf(&ups_status, "%s%s", ups_status, _(", Calibrating"));
159 result = STATE_WARNING;
160 } 174 }
161 if (status & UPSSTATUS_CAL) { 175 if (config.status & UPSSTATUS_RB) {
162 xasprintf (&ups_status, "%s%s", ups_status, _(", Calibrating")); 176 xasprintf(&ups_status, "%s%s", ups_status, _(", Replace Battery"));
177 result = max_state(result, STATE_WARNING);
163 } 178 }
164 if (status & UPSSTATUS_RB) { 179 if (config.status & UPSSTATUS_BYPASS) {
165 xasprintf (&ups_status, "%s%s", ups_status, _(", Replace Battery")); 180 xasprintf(&ups_status, "%s%s", ups_status, _(", On Bypass"));
166 result = STATE_WARNING; 181 // Bypassing the battery is likely a bad thing
182 result = STATE_CRITICAL;
167 } 183 }
168 if (status & UPSSTATUS_BYPASS) { 184 if (config.status & UPSSTATUS_OVER) {
169 xasprintf (&ups_status, "%s%s", ups_status, _(", On Bypass")); 185 xasprintf(&ups_status, "%s%s", ups_status, _(", Overload"));
186 result = max_state(result, STATE_WARNING);
170 } 187 }
171 if (status & UPSSTATUS_OVER) { 188 if (config.status & UPSSTATUS_TRIM) {
172 xasprintf (&ups_status, "%s%s", ups_status, _(", Overload")); 189 xasprintf(&ups_status, "%s%s", ups_status, _(", Trimming"));
173 } 190 }
174 if (status & UPSSTATUS_TRIM) { 191 if (config.status & UPSSTATUS_BOOST) {
175 xasprintf (&ups_status, "%s%s", ups_status, _(", Trimming")); 192 xasprintf(&ups_status, "%s%s", ups_status, _(", Boosting"));
176 } 193 }
177 if (status & UPSSTATUS_BOOST) { 194 if (config.status & UPSSTATUS_CHRG) {
178 xasprintf (&ups_status, "%s%s", ups_status, _(", Boosting")); 195 xasprintf(&ups_status, "%s%s", ups_status, _(", Charging"));
179 } 196 }
180 if (status & UPSSTATUS_CHRG) { 197 if (config.status & UPSSTATUS_DISCHRG) {
181 xasprintf (&ups_status, "%s%s", ups_status, _(", Charging")); 198 xasprintf(&ups_status, "%s%s", ups_status, _(", Discharging"));
199 result = max_state(result, STATE_WARNING);
182 } 200 }
183 if (status & UPSSTATUS_DISCHRG) { 201 if (config.status & UPSSTATUS_ALARM) {
184 xasprintf (&ups_status, "%s%s", ups_status, _(", Discharging")); 202 xasprintf(&ups_status, "%s%s", ups_status, _(", ALARM"));
203 result = STATE_CRITICAL;
185 } 204 }
186 if (status & UPSSTATUS_UNKNOWN) { 205 if (config.status & UPSSTATUS_UNKNOWN) {
187 xasprintf (&ups_status, "%s%s", ups_status, _(", Unknown")); 206 xasprintf(&ups_status, "%s%s", ups_status, _(", Unknown"));
188 } 207 }
189 } 208 }
190 xasprintf (&message, "%sStatus=%s ", message, ups_status); 209 xasprintf(&message, "%sStatus=%s ", message, ups_status);
191 } 210 }
192 211
212 int res;
213 char temp_buffer[MAX_INPUT_BUFFER];
214
193 /* get the ups utility voltage if possible */ 215 /* get the ups utility voltage if possible */
194 res=get_ups_variable ("input.voltage", temp_buffer); 216 res = get_ups_variable("input.voltage", temp_buffer, config);
195 if (res == NOSUCHVAR) supported_options &= ~UPS_UTILITY; 217 if (res == NOSUCHVAR) {
196 else if (res != OK) 218 supported_options &= ~UPS_UTILITY;
219 } else if (res != OK) {
197 return STATE_CRITICAL; 220 return STATE_CRITICAL;
198 else { 221 } else {
199 supported_options |= UPS_UTILITY; 222 supported_options |= UPS_UTILITY;
200 223
201 ups_utility_voltage = atof (temp_buffer); 224 double ups_utility_voltage = 0.0;
202 xasprintf (&message, "%sUtility=%3.1fV ", message, ups_utility_voltage); 225 ups_utility_voltage = atof(temp_buffer);
226 xasprintf(&message, "%sUtility=%3.1fV ", message, ups_utility_voltage);
203 227
204 if (ups_utility_voltage > 120.0) 228 double ups_utility_deviation = 0.0;
229
230 if (ups_utility_voltage > 120.0) {
205 ups_utility_deviation = 120.0 - ups_utility_voltage; 231 ups_utility_deviation = 120.0 - ups_utility_voltage;
206 else 232 } else {
207 ups_utility_deviation = ups_utility_voltage - 120.0; 233 ups_utility_deviation = ups_utility_voltage - 120.0;
234 }
208 235
209 if (check_variable == UPS_UTILITY) { 236 if (config.check_variable == UPS_UTILITY) {
210 if (check_crit && ups_utility_deviation>=critical_value) { 237 if (config.check_crit && ups_utility_deviation >= config.critical_value) {
211 result = STATE_CRITICAL; 238 result = STATE_CRITICAL;
239 } else if (config.check_warn && ups_utility_deviation >= config.warning_value) {
240 result = max_state(result, STATE_WARNING);
212 } 241 }
213 else if (check_warn && ups_utility_deviation>=warning_value) { 242 xasprintf(&data, "%s",
214 result = max_state (result, STATE_WARNING); 243 perfdata("voltage", (long)(1000 * ups_utility_voltage), "mV", config.check_warn, (long)(1000 * config.warning_value),
215 } 244 config.check_crit, (long)(1000 * config.critical_value), true, 0, false, 0));
216 xasprintf (&data, "%s",
217 perfdata ("voltage", (long)(1000*ups_utility_voltage), "mV",
218 check_warn, (long)(1000*warning_value),
219 check_crit, (long)(1000*critical_value),
220 true, 0, false, 0));
221 } else { 245 } else {
222 xasprintf (&data, "%s", 246 xasprintf(&data, "%s", perfdata("voltage", (long)(1000 * ups_utility_voltage), "mV", false, 0, false, 0, true, 0, false, 0));
223 perfdata ("voltage", (long)(1000*ups_utility_voltage), "mV",
224 false, 0, false, 0, true, 0, false, 0));
225 } 247 }
226 } 248 }
227 249
228 /* get the ups battery percent if possible */ 250 /* get the ups battery percent if possible */
229 res=get_ups_variable ("battery.charge", temp_buffer); 251 res = get_ups_variable("battery.charge", temp_buffer, config);
230 if (res == NOSUCHVAR) supported_options &= ~UPS_BATTPCT; 252 if (res == NOSUCHVAR) {
231 else if ( res != OK) 253 supported_options &= ~UPS_BATTPCT;
254 } else if (res != OK) {
232 return STATE_CRITICAL; 255 return STATE_CRITICAL;
233 else { 256 } else {
234 supported_options |= UPS_BATTPCT; 257 supported_options |= UPS_BATTPCT;
235 ups_battery_percent = atof (temp_buffer);
236 xasprintf (&message, "%sBatt=%3.1f%% ", message, ups_battery_percent);
237 258
238 if (check_variable == UPS_BATTPCT) { 259 double ups_battery_percent = 0.0;
239 if (check_crit && ups_battery_percent <= critical_value) { 260 ups_battery_percent = atof(temp_buffer);
261 xasprintf(&message, "%sBatt=%3.1f%% ", message, ups_battery_percent);
262
263 if (config.check_variable == UPS_BATTPCT) {
264 if (config.check_crit && ups_battery_percent <= config.critical_value) {
240 result = STATE_CRITICAL; 265 result = STATE_CRITICAL;
266 } else if (config.check_warn && ups_battery_percent <= config.warning_value) {
267 result = max_state(result, STATE_WARNING);
241 } 268 }
242 else if (check_warn && ups_battery_percent<=warning_value) { 269 xasprintf(&data, "%s %s", data,
243 result = max_state (result, STATE_WARNING); 270 perfdata("battery", (long)ups_battery_percent, "%", config.check_warn, (long)(config.warning_value),
244 } 271 config.check_crit, (long)(config.critical_value), true, 0, true, 100));
245 xasprintf (&data, "%s %s", data,
246 perfdata ("battery", (long)ups_battery_percent, "%",
247 check_warn, (long)(warning_value),
248 check_crit, (long)(critical_value),
249 true, 0, true, 100));
250 } else { 272 } else {
251 xasprintf (&data, "%s %s", data, 273 xasprintf(&data, "%s %s", data, perfdata("battery", (long)ups_battery_percent, "%", false, 0, false, 0, true, 0, true, 100));
252 perfdata ("battery", (long)ups_battery_percent, "%",
253 false, 0, false, 0, true, 0, true, 100));
254 } 274 }
255 } 275 }
256 276
257 /* get the ups load percent if possible */ 277 /* get the ups load percent if possible */
258 res=get_ups_variable ("ups.load", temp_buffer); 278 res = get_ups_variable("ups.load", temp_buffer, config);
259 if ( res == NOSUCHVAR ) supported_options &= ~UPS_LOADPCT; 279 if (res == NOSUCHVAR) {
260 else if ( res != OK) 280 supported_options &= ~UPS_LOADPCT;
281 } else if (res != OK) {
261 return STATE_CRITICAL; 282 return STATE_CRITICAL;
262 else { 283 } else {
263 supported_options |= UPS_LOADPCT; 284 supported_options |= UPS_LOADPCT;
264 ups_load_percent = atof (temp_buffer);
265 xasprintf (&message, "%sLoad=%3.1f%% ", message, ups_load_percent);
266 285
267 if (check_variable == UPS_LOADPCT) { 286 double ups_load_percent = 0.0;
268 if (check_crit && ups_load_percent>=critical_value) { 287 ups_load_percent = atof(temp_buffer);
288 xasprintf(&message, "%sLoad=%3.1f%% ", message, ups_load_percent);
289
290 if (config.check_variable == UPS_LOADPCT) {
291 if (config.check_crit && ups_load_percent >= config.critical_value) {
269 result = STATE_CRITICAL; 292 result = STATE_CRITICAL;
293 } else if (config.check_warn && ups_load_percent >= config.warning_value) {
294 result = max_state(result, STATE_WARNING);
270 } 295 }
271 else if (check_warn && ups_load_percent>=warning_value) { 296 xasprintf(&data, "%s %s", data,
272 result = max_state (result, STATE_WARNING); 297 perfdata("load", (long)ups_load_percent, "%", config.check_warn, (long)(config.warning_value), config.check_crit,
273 } 298 (long)(config.critical_value), true, 0, true, 100));
274 xasprintf (&data, "%s %s", data,
275 perfdata ("load", (long)ups_load_percent, "%",
276 check_warn, (long)(warning_value),
277 check_crit, (long)(critical_value),
278 true, 0, true, 100));
279 } else { 299 } else {
280 xasprintf (&data, "%s %s", data, 300 xasprintf(&data, "%s %s", data, perfdata("load", (long)ups_load_percent, "%", false, 0, false, 0, true, 0, true, 100));
281 perfdata ("load", (long)ups_load_percent, "%",
282 false, 0, false, 0, true, 0, true, 100));
283 } 301 }
284 } 302 }
285 303
286 /* get the ups temperature if possible */ 304 /* get the ups temperature if possible */
287 res=get_ups_variable ("ups.temperature", temp_buffer); 305 res = get_ups_variable("ups.temperature", temp_buffer, config);
288 if ( res == NOSUCHVAR ) supported_options &= ~UPS_TEMP; 306 if (res == NOSUCHVAR) {
289 else if ( res != OK) 307 supported_options &= ~UPS_TEMP;
308 } else if (res != OK) {
290 return STATE_CRITICAL; 309 return STATE_CRITICAL;
291 else { 310 } else {
292 supported_options |= UPS_TEMP; 311 supported_options |= UPS_TEMP;
293 if (temp_output_c) { 312
294 tunits="degC"; 313 double ups_temperature = 0.0;
295 ups_temperature = atof (temp_buffer); 314 char *tunits;
296 xasprintf (&message, "%sTemp=%3.1fC", message, ups_temperature); 315
297 } 316 if (config.temp_output_c) {
298 else { 317 tunits = "degC";
299 tunits="degF"; 318 ups_temperature = atof(temp_buffer);
300 ups_temperature = (atof (temp_buffer) * 1.8) + 32; 319 xasprintf(&message, "%sTemp=%3.1fC", message, ups_temperature);
301 xasprintf (&message, "%sTemp=%3.1fF", message, ups_temperature); 320 } else {
321 tunits = "degF";
322 ups_temperature = (atof(temp_buffer) * 1.8) + 32;
323 xasprintf(&message, "%sTemp=%3.1fF", message, ups_temperature);
302 } 324 }
303 325
304 if (check_variable == UPS_TEMP) { 326 if (config.check_variable == UPS_TEMP) {
305 if (check_crit && ups_temperature>=critical_value) { 327 if (config.check_crit && ups_temperature >= config.critical_value) {
306 result = STATE_CRITICAL; 328 result = STATE_CRITICAL;
329 } else if (config.check_warn && ups_temperature >= config.warning_value) {
330 result = max_state(result, STATE_WARNING);
307 } 331 }
308 else if (check_warn && ups_temperature>=warning_value) { 332 xasprintf(&data, "%s %s", data,
309 result = max_state (result, STATE_WARNING); 333 perfdata("temp", (long)ups_temperature, tunits, config.check_warn, (long)(config.warning_value), config.check_crit,
310 } 334 (long)(config.critical_value), true, 0, false, 0));
311 xasprintf (&data, "%s %s", data,
312 perfdata ("temp", (long)ups_temperature, tunits,
313 check_warn, (long)(warning_value),
314 check_crit, (long)(critical_value),
315 true, 0, false, 0));
316 } else { 335 } else {
317 xasprintf (&data, "%s %s", data, 336 xasprintf(&data, "%s %s", data, perfdata("temp", (long)ups_temperature, tunits, false, 0, false, 0, true, 0, false, 0));
318 perfdata ("temp", (long)ups_temperature, tunits,
319 false, 0, false, 0, true, 0, false, 0));
320 } 337 }
321 } 338 }
322 339
323 /* get the ups real power if possible */ 340 /* get the ups real power if possible */
324 res=get_ups_variable ("ups.realpower", temp_buffer); 341 res = get_ups_variable("ups.realpower", temp_buffer, config);
325 if ( res == NOSUCHVAR ) supported_options &= ~UPS_REALPOWER; 342 if (res == NOSUCHVAR) {
326 else if ( res != OK) 343 supported_options &= ~UPS_REALPOWER;
344 } else if (res != OK) {
327 return STATE_CRITICAL; 345 return STATE_CRITICAL;
328 else { 346 } else {
329 supported_options |= UPS_REALPOWER; 347 supported_options |= UPS_REALPOWER;
330 ups_realpower = atof (temp_buffer); 348 double ups_realpower = 0.0;
331 xasprintf (&message, "%sReal power=%3.1fW ", message, ups_realpower); 349 ups_realpower = atof(temp_buffer);
350 xasprintf(&message, "%sReal power=%3.1fW ", message, ups_realpower);
332 351
333 if (check_variable == UPS_REALPOWER) { 352 if (config.check_variable == UPS_REALPOWER) {
334 if (check_crit && ups_realpower>=critical_value) { 353 if (config.check_crit && ups_realpower >= config.critical_value) {
335 result = STATE_CRITICAL; 354 result = STATE_CRITICAL;
355 } else if (config.check_warn && ups_realpower >= config.warning_value) {
356 result = max_state(result, STATE_WARNING);
336 } 357 }
337 else if (check_warn && ups_realpower>=warning_value) { 358 xasprintf(&data, "%s %s", data,
338 result = max_state (result, STATE_WARNING); 359 perfdata("realpower", (long)ups_realpower, "W", config.check_warn, (long)(config.warning_value), config.check_crit,
339 } 360 (long)(config.critical_value), true, 0, false, 0));
340 xasprintf (&data, "%s %s", data,
341 perfdata ("realpower", (long)ups_realpower, "W",
342 check_warn, (long)(warning_value),
343 check_crit, (long)(critical_value),
344 true, 0, false, 0));
345 } else { 361 } else {
346 xasprintf (&data, "%s %s", data, 362 xasprintf(&data, "%s %s", data, perfdata("realpower", (long)ups_realpower, "W", false, 0, false, 0, true, 0, false, 0));
347 perfdata ("realpower", (long)ups_realpower, "W",
348 false, 0, false, 0, true, 0, false, 0));
349 } 363 }
350 } 364 }
351 365
352 /* if the UPS does not support any options we are looking for, report an error */ 366 /* if the UPS does not support any options we are looking for, report an
367 * error */
353 if (supported_options == UPS_NONE) { 368 if (supported_options == UPS_NONE) {
354 result = STATE_CRITICAL; 369 result = STATE_CRITICAL;
355 xasprintf (&message, _("UPS does not support any available options\n")); 370 xasprintf(&message, _("UPS does not support any available options\n"));
356 } 371 }
357 372
358 /* reset timeout */ 373 /* reset timeout */
359 alarm (0); 374 alarm(0);
360 375
361 printf ("UPS %s - %s|%s\n", state_text(result), message, data); 376 printf("UPS %s - %s|%s\n", state_text(result), message, data);
362 return result; 377 return result;
363} 378}
364 379
365
366
367/* determines what options are supported by the UPS */ 380/* determines what options are supported by the UPS */
368int 381int determine_status(ups_config *config, int *supported_options) {
369determine_status (void)
370{
371 char recv_buffer[MAX_INPUT_BUFFER]; 382 char recv_buffer[MAX_INPUT_BUFFER];
372 char temp_buffer[MAX_INPUT_BUFFER];
373 char *ptr;
374 int res;
375 383
376 res=get_ups_variable ("ups.status", recv_buffer); 384 int res = get_ups_variable("ups.status", recv_buffer, *config);
377 if (res == NOSUCHVAR) return OK; 385 if (res == NOSUCHVAR) {
386 return OK;
387 }
388
378 if (res != STATE_OK) { 389 if (res != STATE_OK) {
379 printf ("%s\n", _("Invalid response received from host")); 390 printf("%s\n", _("Invalid response received from host"));
380 return ERROR; 391 return ERROR;
381 } 392 }
382 393
383 supported_options |= UPS_STATUS; 394 *supported_options |= UPS_STATUS;
384 395
385 strcpy (temp_buffer, recv_buffer); 396 char temp_buffer[MAX_INPUT_BUFFER];
386 for (ptr = (char *) strtok (temp_buffer, " "); ptr != NULL; 397
387 ptr = (char *) strtok (NULL, " ")) { 398 strcpy(temp_buffer, recv_buffer);
388 if (!strcmp (ptr, "OFF")) 399 for (char *ptr = (char *)strtok(temp_buffer, " "); ptr != NULL; ptr = (char *)strtok(NULL, " ")) {
389 status |= UPSSTATUS_OFF; 400 if (!strcmp(ptr, "OFF")) {
390 else if (!strcmp (ptr, "OL")) 401 config->status |= UPSSTATUS_OFF;
391 status |= UPSSTATUS_OL; 402 } else if (!strcmp(ptr, "OL")) {
392 else if (!strcmp (ptr, "OB")) 403 config->status |= UPSSTATUS_OL;
393 status |= UPSSTATUS_OB; 404 } else if (!strcmp(ptr, "OB")) {
394 else if (!strcmp (ptr, "LB")) 405 config->status |= UPSSTATUS_OB;
395 status |= UPSSTATUS_LB; 406 } else if (!strcmp(ptr, "LB")) {
396 else if (!strcmp (ptr, "CAL")) 407 config->status |= UPSSTATUS_LB;
397 status |= UPSSTATUS_CAL; 408 } else if (!strcmp(ptr, "CAL")) {
398 else if (!strcmp (ptr, "RB")) 409 config->status |= UPSSTATUS_CAL;
399 status |= UPSSTATUS_RB; 410 } else if (!strcmp(ptr, "RB")) {
400 else if (!strcmp (ptr, "BYPASS")) 411 config->status |= UPSSTATUS_RB;
401 status |= UPSSTATUS_BYPASS; 412 } else if (!strcmp(ptr, "BYPASS")) {
402 else if (!strcmp (ptr, "OVER")) 413 config->status |= UPSSTATUS_BYPASS;
403 status |= UPSSTATUS_OVER; 414 } else if (!strcmp(ptr, "OVER")) {
404 else if (!strcmp (ptr, "TRIM")) 415 config->status |= UPSSTATUS_OVER;
405 status |= UPSSTATUS_TRIM; 416 } else if (!strcmp(ptr, "TRIM")) {
406 else if (!strcmp (ptr, "BOOST")) 417 config->status |= UPSSTATUS_TRIM;
407 status |= UPSSTATUS_BOOST; 418 } else if (!strcmp(ptr, "BOOST")) {
408 else if (!strcmp (ptr, "CHRG")) 419 config->status |= UPSSTATUS_BOOST;
409 status |= UPSSTATUS_CHRG; 420 } else if (!strcmp(ptr, "CHRG")) {
410 else if (!strcmp (ptr, "DISCHRG")) 421 config->status |= UPSSTATUS_CHRG;
411 status |= UPSSTATUS_DISCHRG; 422 } else if (!strcmp(ptr, "DISCHRG")) {
412 else 423 config->status |= UPSSTATUS_DISCHRG;
413 status |= UPSSTATUS_UNKNOWN; 424 } else if (!strcmp(ptr, "ALARM")) {
425 config->status |= UPSSTATUS_ALARM;
426 } else {
427 config->status |= UPSSTATUS_UNKNOWN;
428 }
414 } 429 }
415 430
416 return OK; 431 return OK;
417} 432}
418 433
419
420/* gets a variable value for a specific UPS */ 434/* gets a variable value for a specific UPS */
421int 435int get_ups_variable(const char *varname, char *buf, const ups_config config) {
422get_ups_variable (const char *varname, char *buf)
423{
424 /* char command[MAX_INPUT_BUFFER]; */
425 char temp_buffer[MAX_INPUT_BUFFER];
426 char send_buffer[MAX_INPUT_BUFFER]; 436 char send_buffer[MAX_INPUT_BUFFER];
427 char *ptr;
428 char *logout = "OK Goodbye\n";
429 int logout_len = strlen(logout);
430 int len;
431
432 *buf=0;
433 437
434 /* create the command string to send to the UPS daemon */ 438 /* create the command string to send to the UPS daemon */
435 /* Add LOGOUT to avoid read failure logs */ 439 /* Add LOGOUT to avoid read failure logs */
436 int res = snprintf (send_buffer, sizeof(send_buffer), "GET VAR %s %s\nLOGOUT\n", ups_name, varname); 440 int res = snprintf(send_buffer, sizeof(send_buffer), "GET VAR %s %s\nLOGOUT\n", config.ups_name, varname);
437 if ( (res > 0) && ((size_t)res >= sizeof(send_buffer))) { 441 if ((res > 0) && ((size_t)res >= sizeof(send_buffer))) {
438 printf("%s\n", _("UPS name to long for buffer")); 442 printf("%s\n", _("UPS name to long for buffer"));
439 return ERROR; 443 return ERROR;
440 } 444 }
441 445
446 char temp_buffer[MAX_INPUT_BUFFER];
447
442 /* send the command to the daemon and get a response back */ 448 /* send the command to the daemon and get a response back */
443 if (process_tcp_request 449 if (process_tcp_request(config.server_address, config.server_port, send_buffer, temp_buffer, sizeof(temp_buffer)) != STATE_OK) {
444 (server_address, server_port, send_buffer, temp_buffer, 450 printf("%s\n", _("Invalid response received from host"));
445 sizeof (temp_buffer)) != STATE_OK) {
446 printf ("%s\n", _("Invalid response received from host"));
447 return ERROR; 451 return ERROR;
448 } 452 }
449 453
450 ptr = temp_buffer; 454 char *ptr = temp_buffer;
451 len = strlen(ptr); 455 int len = strlen(ptr);
452 if (len > logout_len && strcmp (ptr + len - logout_len, logout) == 0) len -= logout_len; 456 const char *logout = "OK Goodbye\n";
453 if (len > 0 && ptr[len-1] == '\n') ptr[len-1]=0; 457 const int logout_len = strlen(logout);
454 if (strcmp (ptr, "ERR UNKNOWN-UPS") == 0) { 458
455 printf (_("CRITICAL - no such UPS '%s' on that host\n"), ups_name); 459 if (len > logout_len && strcmp(ptr + len - logout_len, logout) == 0) {
460 len -= logout_len;
461 }
462 if (len > 0 && ptr[len - 1] == '\n') {
463 ptr[len - 1] = 0;
464 }
465 if (strcmp(ptr, "ERR UNKNOWN-UPS") == 0) {
466 printf(_("CRITICAL - no such UPS '%s' on that host\n"), config.ups_name);
456 return ERROR; 467 return ERROR;
457 } 468 }
458 469
459 if (strcmp (ptr, "ERR VAR-NOT-SUPPORTED") == 0) { 470 if (strcmp(ptr, "ERR VAR-NOT-SUPPORTED") == 0) {
460 /*printf ("Error: Variable '%s' is not supported\n", varname);*/ 471 /*printf ("Error: Variable '%s' is not supported\n", varname);*/
461 return NOSUCHVAR; 472 return NOSUCHVAR;
462 } 473 }
463 474
464 if (strcmp (ptr, "ERR DATA-STALE") == 0) { 475 if (strcmp(ptr, "ERR DATA-STALE") == 0) {
465 printf ("%s\n", _("CRITICAL - UPS data is stale")); 476 printf("%s\n", _("CRITICAL - UPS data is stale"));
466 return ERROR; 477 return ERROR;
467 } 478 }
468 479
469 if (strncmp (ptr, "ERR", 3) == 0) { 480 if (strncmp(ptr, "ERR", 3) == 0) {
470 printf (_("Unknown error: %s\n"), ptr); 481 printf(_("Unknown error: %s\n"), ptr);
471 return ERROR; 482 return ERROR;
472 } 483 }
473 484
474 ptr = temp_buffer + strlen (varname) + strlen (ups_name) + 6; 485 ptr = temp_buffer + strlen(varname) + strlen(config.ups_name) + 6;
475 len = strlen(ptr); 486 len = strlen(ptr);
476 if (len < 2 || ptr[0] != '"' || ptr[len-1] != '"') { 487 if (len < 2 || ptr[0] != '"' || ptr[len - 1] != '"') {
477 printf ("%s\n", _("Error: unable to parse variable")); 488 printf("%s\n", _("Error: unable to parse variable"));
478 return ERROR; 489 return ERROR;
479 } 490 }
480 strncpy (buf, ptr+1, len - 2); 491
492 *buf = 0;
493 strncpy(buf, ptr + 1, len - 2);
481 buf[len - 2] = 0; 494 buf[len - 2] = 0;
482 495
483 return OK; 496 return OK;
484} 497}
485 498
486
487/* Command line: CHECK_UPS -H <host_address> -u ups [-p port] [-v variable] 499/* Command line: CHECK_UPS -H <host_address> -u ups [-p port] [-v variable]
488 [-wv warn_value] [-cv crit_value] [-to to_sec] */ 500 [-wv warn_value] [-cv crit_value] [-to to_sec] */
489 501
490
491/* process command-line arguments */ 502/* process command-line arguments */
492int 503int process_arguments(int argc, char **argv, ups_config *config) {
493process_arguments (int argc, char **argv) 504
494{ 505 static struct option longopts[] = {{"hostname", required_argument, 0, 'H'},
495 int c; 506 {"ups", required_argument, 0, 'u'},
496 507 {"port", required_argument, 0, 'p'},
497 int option = 0; 508 {"critical", required_argument, 0, 'c'},
498 static struct option longopts[] = { 509 {"warning", required_argument, 0, 'w'},
499 {"hostname", required_argument, 0, 'H'}, 510 {"timeout", required_argument, 0, 't'},
500 {"ups", required_argument, 0, 'u'}, 511 {"temperature", no_argument, 0, 'T'},
501 {"port", required_argument, 0, 'p'}, 512 {"variable", required_argument, 0, 'v'},
502 {"critical", required_argument, 0, 'c'}, 513 {"version", no_argument, 0, 'V'},
503 {"warning", required_argument, 0, 'w'}, 514 {"help", no_argument, 0, 'h'},
504 {"timeout", required_argument, 0, 't'}, 515 {0, 0, 0, 0}};
505 {"temperature", no_argument, 0, 'T'}, 516
506 {"variable", required_argument, 0, 'v'}, 517 if (argc < 2) {
507 {"version", no_argument, 0, 'V'},
508 {"help", no_argument, 0, 'h'},
509 {0, 0, 0, 0}
510 };
511
512 if (argc < 2)
513 return ERROR; 518 return ERROR;
519 }
514 520
521 int c;
515 for (c = 1; c < argc; c++) { 522 for (c = 1; c < argc; c++) {
516 if (strcmp ("-to", argv[c]) == 0) 523 if (strcmp("-to", argv[c]) == 0) {
517 strcpy (argv[c], "-t"); 524 strcpy(argv[c], "-t");
518 else if (strcmp ("-wt", argv[c]) == 0) 525 } else if (strcmp("-wt", argv[c]) == 0) {
519 strcpy (argv[c], "-w"); 526 strcpy(argv[c], "-w");
520 else if (strcmp ("-ct", argv[c]) == 0) 527 } else if (strcmp("-ct", argv[c]) == 0) {
521 strcpy (argv[c], "-c"); 528 strcpy(argv[c], "-c");
529 }
522 } 530 }
523 531
532 int option = 0;
524 while (1) { 533 while (1) {
525 c = getopt_long (argc, argv, "hVTH:u:p:v:c:w:t:", longopts, 534 c = getopt_long(argc, argv, "hVTH:u:p:v:c:w:t:", longopts, &option);
526 &option);
527 535
528 if (c == -1 || c == EOF) 536 if (c == -1 || c == EOF) {
529 break; 537 break;
538 }
530 539
531 switch (c) { 540 switch (c) {
532 case '?': /* help */ 541 case '?': /* help */
533 usage5 (); 542 usage5();
534 case 'H': /* hostname */ 543 case 'H': /* hostname */
535 if (is_host (optarg)) { 544 if (is_host(optarg)) {
536 server_address = optarg; 545 config->server_address = optarg;
537 } 546 } else {
538 else { 547 usage2(_("Invalid hostname/address"), optarg);
539 usage2 (_("Invalid hostname/address"), optarg);
540 } 548 }
541 break; 549 break;
542 case 'T': /* FIXME: to be improved (ie "-T C" for Celsius or "-T F" for Fahrenheit) */ 550 case 'T': /* FIXME: to be improved (ie "-T C" for Celsius or "-T F" for
543 temp_output_c = true; 551 Fahrenheit) */
552 config->temp_output_c = true;
544 break; 553 break;
545 case 'u': /* ups name */ 554 case 'u': /* ups name */
546 ups_name = optarg; 555 config->ups_name = optarg;
547 break; 556 break;
548 case 'p': /* port */ 557 case 'p': /* port */
549 if (is_intpos (optarg)) { 558 if (is_intpos(optarg)) {
550 server_port = atoi (optarg); 559 config->server_port = atoi(optarg);
551 } 560 } else {
552 else { 561 usage2(_("Port must be a positive integer"), optarg);
553 usage2 (_("Port must be a positive integer"), optarg);
554 } 562 }
555 break; 563 break;
556 case 'c': /* critical time threshold */ 564 case 'c': /* critical time threshold */
557 if (is_intnonneg (optarg)) { 565 if (is_intnonneg(optarg)) {
558 critical_value = atoi (optarg); 566 config->critical_value = atoi(optarg);
559 check_crit = true; 567 config->check_crit = true;
560 } 568 } else {
561 else { 569 usage2(_("Critical time must be a positive integer"), optarg);
562 usage2 (_("Critical time must be a positive integer"), optarg);
563 } 570 }
564 break; 571 break;
565 case 'w': /* warning time threshold */ 572 case 'w': /* warning time threshold */
566 if (is_intnonneg (optarg)) { 573 if (is_intnonneg(optarg)) {
567 warning_value = atoi (optarg); 574 config->warning_value = atoi(optarg);
568 check_warn = true; 575 config->check_warn = true;
569 } 576 } else {
570 else { 577 usage2(_("Warning time must be a positive integer"), optarg);
571 usage2 (_("Warning time must be a positive integer"), optarg);
572 } 578 }
573 break; 579 break;
574 case 'v': /* variable */ 580 case 'v': /* variable */
575 if (!strcmp (optarg, "LINE")) 581 if (!strcmp(optarg, "LINE")) {
576 check_variable = UPS_UTILITY; 582 config->check_variable = UPS_UTILITY;
577 else if (!strcmp (optarg, "TEMP")) 583 } else if (!strcmp(optarg, "TEMP")) {
578 check_variable = UPS_TEMP; 584 config->check_variable = UPS_TEMP;
579 else if (!strcmp (optarg, "BATTPCT")) 585 } else if (!strcmp(optarg, "BATTPCT")) {
580 check_variable = UPS_BATTPCT; 586 config->check_variable = UPS_BATTPCT;
581 else if (!strcmp (optarg, "LOADPCT")) 587 } else if (!strcmp(optarg, "LOADPCT")) {
582 check_variable = UPS_LOADPCT; 588 config->check_variable = UPS_LOADPCT;
583 else if (!strcmp (optarg, "REALPOWER")) 589 } else if (!strcmp(optarg, "REALPOWER")) {
584 check_variable = UPS_REALPOWER; 590 config->check_variable = UPS_REALPOWER;
585 else 591 } else {
586 usage2 (_("Unrecognized UPS variable"), optarg); 592 usage2(_("Unrecognized UPS variable"), optarg);
587 break;
588 case 't': /* timeout */
589 if (is_intnonneg (optarg)) {
590 socket_timeout = atoi (optarg);
591 } 593 }
592 else { 594 break;
593 usage4 (_("Timeout interval must be a positive integer")); 595 case 't': /* timeout */
596 if (is_intnonneg(optarg)) {
597 socket_timeout = atoi(optarg);
598 } else {
599 usage4(_("Timeout interval must be a positive integer"));
594 } 600 }
595 break; 601 break;
596 case 'V': /* version */ 602 case 'V': /* version */
597 print_revision (progname, NP_VERSION); 603 print_revision(progname, NP_VERSION);
598 exit (STATE_UNKNOWN); 604 exit(STATE_UNKNOWN);
599 case 'h': /* help */ 605 case 'h': /* help */
600 print_help (); 606 print_help();
601 exit (STATE_UNKNOWN); 607 exit(STATE_UNKNOWN);
602 } 608 }
603 } 609 }
604 610
605 611 if (config->server_address == NULL && argc > optind) {
606 if (server_address == NULL && argc > optind) { 612 if (is_host(argv[optind])) {
607 if (is_host (argv[optind])) 613 config->server_address = argv[optind++];
608 server_address = argv[optind++]; 614 } else {
609 else 615 usage2(_("Invalid hostname/address"), optarg);
610 usage2 (_("Invalid hostname/address"), optarg); 616 }
611 } 617 }
612 618
613 if (server_address == NULL) 619 if (config->server_address == NULL) {
614 server_address = strdup("127.0.0.1"); 620 config->server_address = strdup("127.0.0.1");
621 }
615 622
616 return validate_arguments(); 623 return validate_arguments(*config);
617} 624}
618 625
619 626int validate_arguments(ups_config config) {
620int 627 if (!config.ups_name) {
621validate_arguments (void) 628 printf("%s\n", _("Error : no UPS indicated"));
622{
623 if (! ups_name) {
624 printf ("%s\n", _("Error : no UPS indicated"));
625 return ERROR; 629 return ERROR;
626 } 630 }
627 return OK; 631 return OK;
628} 632}
629 633
634void print_help(void) {
635 print_revision(progname, NP_VERSION);
630 636
631void 637 printf("Copyright (c) 2000 Tom Shields\n");
632print_help (void) 638 printf("Copyright (c) 2004 Alain Richard <alain.richard@equation.fr>\n");
633{ 639 printf("Copyright (c) 2004 Arnaud Quette <arnaud.quette@mgeups.com>\n");
634 char *myport; 640 printf(COPYRIGHT, copyright, email);
635 xasprintf (&myport, "%d", PORT);
636
637 print_revision (progname, NP_VERSION);
638
639 printf ("Copyright (c) 2000 Tom Shields\n");
640 printf ("Copyright (c) 2004 Alain Richard <alain.richard@equation.fr>\n");
641 printf ("Copyright (c) 2004 Arnaud Quette <arnaud.quette@mgeups.com>\n");
642 printf (COPYRIGHT, copyright, email);
643
644 printf ("%s\n", _("This plugin tests the UPS service on the specified host. Network UPS Tools"));
645 printf ("%s\n", _("from www.networkupstools.org must be running for this plugin to work."));
646
647 printf ("\n\n");
648
649 print_usage ();
650 641
651 printf (UT_HELP_VRSN); 642 printf("%s\n", _("This plugin tests the UPS service on the specified host. "
652 printf (UT_EXTRA_OPTS); 643 "Network UPS Tools"));
644 printf("%s\n", _("from www.networkupstools.org must be running for this "
645 "plugin to work."));
653 646
654 printf (UT_HOST_PORT, 'p', myport); 647 printf("\n\n");
655 648
656 printf (" %s\n", "-u, --ups=STRING"); 649 print_usage();
657 printf (" %s\n", _("Name of UPS"));
658 printf (" %s\n", "-T, --temperature");
659 printf (" %s\n", _("Output of temperatures in Celsius"));
660 printf (" %s\n", "-v, --variable=STRING");
661 printf (" %s %s\n", _("Valid values for STRING are"), "LINE, TEMP, BATTPCT, LOADPCT or REALPOWER");
662 650
663 printf (UT_WARN_CRIT); 651 printf(UT_HELP_VRSN);
652 printf(UT_EXTRA_OPTS);
664 653
665 printf (UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); 654 char *myport;
666 655 xasprintf(&myport, "%d", PORT);
667/* TODO: -v clashing with -v/-variable. Commenting out help text since verbose 656 printf(UT_HOST_PORT, 'p', myport);
668 is unused up to now */ 657
669/* printf (UT_VERBOSE); */ 658 printf(" %s\n", "-u, --ups=STRING");
670 659 printf(" %s\n", _("Name of UPS"));
671 printf ("\n"); 660 printf(" %s\n", "-T, --temperature");
672 printf ("%s\n", _("This plugin attempts to determine the status of a UPS (Uninterruptible Power")); 661 printf(" %s\n", _("Output of temperatures in Celsius"));
673 printf ("%s\n", _("Supply) on a local or remote host. If the UPS is online or calibrating, the")); 662 printf(" %s\n", "-v, --variable=STRING");
674 printf ("%s\n", _("plugin will return an OK state. If the battery is on it will return a WARNING")); 663 printf(" %s %s\n", _("Valid values for STRING are"), "LINE, TEMP, BATTPCT, LOADPCT or REALPOWER");
675 printf ("%s\n", _("state. If the UPS is off or has a low battery the plugin will return a CRITICAL")); 664
676 printf ("%s\n", _("state.")); 665 printf(UT_WARN_CRIT);
677 666
678 printf ("\n"); 667 printf(UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
679 printf ("%s\n", _("Notes:")); 668
680 printf (" %s\n", _("You may also specify a variable to check (such as temperature, utility voltage,")); 669 /* TODO: -v clashing with -v/-variable. Commenting out help text since
681 printf (" %s\n", _("battery load, etc.) as well as warning and critical thresholds for the value")); 670 verbose is unused up to now */
682 printf (" %s\n", _("of that variable. If the remote host has multiple UPS that are being monitored")); 671 /* printf (UT_VERBOSE); */
683 printf (" %s\n", _("you will have to use the --ups option to specify which UPS to check.")); 672
684 printf ("\n"); 673 printf("\n");
685 printf (" %s\n", _("This plugin requires that the UPSD daemon distributed with Russell Kroll's")); 674 printf("%s\n", _("This plugin attempts to determine the status of a UPS "
686 printf (" %s\n", _("Network UPS Tools be installed on the remote host. If you do not have the")); 675 "(Uninterruptible Power"));
687 printf (" %s\n", _("package installed on your system, you can download it from")); 676 printf("%s\n", _("Supply) on a local or remote host. If the UPS is online "
688 printf (" %s\n", _("http://www.networkupstools.org")); 677 "or calibrating, the"));
689 678 printf("%s\n", _("plugin will return an OK state. If the battery is on it "
690 printf (UT_SUPPORT); 679 "will return a WARNING"));
680 printf("%s\n", _("state. If the UPS is off or has a low battery the plugin "
681 "will return a CRITICAL"));
682 printf("%s\n", _("state."));
683
684 printf("\n");
685 printf("%s\n", _("Notes:"));
686 printf(" %s\n", _("You may also specify a variable to check (such as "
687 "temperature, utility voltage,"));
688 printf(" %s\n", _("battery load, etc.) as well as warning and critical "
689 "thresholds for the value"));
690 printf(" %s\n", _("of that variable. If the remote host has multiple UPS "
691 "that are being monitored"));
692 printf(" %s\n", _("you will have to use the --ups option to specify which "
693 "UPS to check."));
694 printf("\n");
695 printf(" %s\n", _("This plugin requires that the UPSD daemon distributed "
696 "with Russell Kroll's"));
697 printf(" %s\n", _("Network UPS Tools be installed on the remote host. If "
698 "you do not have the"));
699 printf(" %s\n", _("package installed on your system, you can download it from"));
700 printf(" %s\n", _("http://www.networkupstools.org"));
701
702 printf(UT_SUPPORT);
691} 703}
692 704
693 705void print_usage(void) {
694void 706 printf("%s\n", _("Usage:"));
695print_usage (void) 707 printf("%s -H host -u ups [-p port] [-v variable] [-w warn_value] [-c "
696{ 708 "crit_value] [-to to_sec] [-T]\n",
697 printf ("%s\n", _("Usage:")); 709 progname);
698 printf ("%s -H host -u ups [-p port] [-v variable] [-w warn_value] [-c crit_value] [-to to_sec] [-T]\n", progname);
699} 710}
diff --git a/plugins/check_users.c b/plugins/check_users.c
index 89b95369..f1e1c39d 100644
--- a/plugins/check_users.c
+++ b/plugins/check_users.c
@@ -1,71 +1,69 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring check_users plugin 3 * Monitoring check_users plugin
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 2000-2012 Monitoring Plugins Development Team 6 * Copyright (c) 2000-2024 Monitoring Plugins Development Team
7* 7 *
8* Description: 8 * Description:
9* 9 *
10* This file contains the check_users plugin 10 * This file contains the check_users plugin
11* 11 *
12* This plugin checks the number of users currently logged in on the local 12 * This plugin checks the number of users currently logged in on the local
13* system and generates an error if the number exceeds the thresholds 13 * system and generates an error if the number exceeds the thresholds
14* specified. 14 * specified.
15* 15 *
16* 16 *
17* This program is free software: you can redistribute it and/or modify 17 * This program is free software: you can redistribute it and/or modify
18* it under the terms of the GNU General Public License as published by 18 * it under the terms of the GNU General Public License as published by
19* the Free Software Foundation, either version 3 of the License, or 19 * the Free Software Foundation, either version 3 of the License, or
20* (at your option) any later version. 20 * (at your option) any later version.
21* 21 *
22* This program is distributed in the hope that it will be useful, 22 * This program is distributed in the hope that it will be useful,
23* but WITHOUT ANY WARRANTY; without even the implied warranty of 23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25* GNU General Public License for more details. 25 * GNU General Public License for more details.
26* 26 *
27* You should have received a copy of the GNU General Public License 27 * You should have received a copy of the GNU General Public License
28* along with this program. If not, see <http://www.gnu.org/licenses/>. 28 * along with this program. If not, see <http://www.gnu.org/licenses/>.
29* 29 *
30* 30 *
31*****************************************************************************/ 31 *****************************************************************************/
32 32
33const char *progname = "check_users"; 33const char *progname = "check_users";
34const char *copyright = "2000-2007"; 34const char *copyright = "2000-2024";
35const char *email = "devel@monitoring-plugins.org"; 35const char *email = "devel@monitoring-plugins.org";
36 36
37#include "common.h" 37#include "common.h"
38#include "utils.h" 38#include "utils.h"
39 39
40#if HAVE_WTSAPI32_H 40#if HAVE_WTSAPI32_H
41# include <windows.h> 41# include <windows.h>
42# include <wtsapi32.h> 42# include <wtsapi32.h>
43# undef ERROR 43# undef ERROR
44# define ERROR -1 44# define ERROR -1
45#elif HAVE_UTMPX_H 45#elif HAVE_UTMPX_H
46# include <utmpx.h> 46# include <utmpx.h>
47#else 47#else
48# include "popen.h" 48# include "popen.h"
49#endif 49#endif
50 50
51#ifdef HAVE_LIBSYSTEMD 51#ifdef HAVE_LIBSYSTEMD
52#include <systemd/sd-daemon.h> 52# include <systemd/sd-daemon.h>
53#include <systemd/sd-login.h> 53# include <systemd/sd-login.h>
54#endif 54#endif
55 55
56#define possibly_set(a,b) ((a) == 0 ? (b) : 0) 56#define possibly_set(a, b) ((a) == 0 ? (b) : 0)
57 57
58int process_arguments (int, char **); 58static int process_arguments(int, char **);
59void print_help (void); 59static void print_help(void);
60void print_usage (void); 60void print_usage(void);
61 61
62char *warning_range = NULL; 62static char *warning_range = NULL;
63char *critical_range = NULL; 63static char *critical_range = NULL;
64thresholds *thlds = NULL; 64static thresholds *thlds = NULL;
65 65
66int 66int main(int argc, char **argv) {
67main (int argc, char **argv)
68{
69 int users = -1; 67 int users = -1;
70 int result = STATE_UNKNOWN; 68 int result = STATE_UNKNOWN;
71#if HAVE_WTSAPI32_H 69#if HAVE_WTSAPI32_H
@@ -78,74 +76,71 @@ main (int argc, char **argv)
78 char input_buffer[MAX_INPUT_BUFFER]; 76 char input_buffer[MAX_INPUT_BUFFER];
79#endif 77#endif
80 78
81 setlocale (LC_ALL, ""); 79 setlocale(LC_ALL, "");
82 bindtextdomain (PACKAGE, LOCALEDIR); 80 bindtextdomain(PACKAGE, LOCALEDIR);
83 textdomain (PACKAGE); 81 textdomain(PACKAGE);
84 82
85 /* Parse extra opts if any */ 83 /* Parse extra opts if any */
86 argv = np_extra_opts (&argc, argv, progname); 84 argv = np_extra_opts(&argc, argv, progname);
87 85
88 if (process_arguments (argc, argv) == ERROR) 86 if (process_arguments(argc, argv) == ERROR)
89 usage4 (_("Could not parse arguments")); 87 usage4(_("Could not parse arguments"));
90 88
91 users = 0; 89 users = 0;
92 90
93#ifdef HAVE_LIBSYSTEMD 91#ifdef HAVE_LIBSYSTEMD
94 if (sd_booted () > 0) 92 if (sd_booted() > 0)
95 users = sd_get_sessions (NULL); 93 users = sd_get_sessions(NULL);
96 else { 94 else {
97#endif 95#endif
98#if HAVE_WTSAPI32_H 96#if HAVE_WTSAPI32_H
99 if (!WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 97 if (!WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, &wtsinfo, &wtscount)) {
100 0, 1, &wtsinfo, &wtscount)) { 98 printf(_("Could not enumerate RD sessions: %d\n"), GetLastError());
101 printf(_("Could not enumerate RD sessions: %d\n"), GetLastError()); 99 return STATE_UNKNOWN;
102 return STATE_UNKNOWN; 100 }
103 }
104 101
105 for (index = 0; index < wtscount; index++) { 102 for (index = 0; index < wtscount; index++) {
106 LPTSTR username; 103 LPTSTR username;
107 DWORD size; 104 DWORD size;
108 int len; 105 int len;
109 106
110 if (!WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, 107 if (!WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, wtsinfo[index].SessionId, WTSUserName, &username, &size))
111 wtsinfo[index].SessionId, WTSUserName, &username, &size)) 108 continue;
112 continue;
113 109
114 len = lstrlen(username); 110 len = lstrlen(username);
115 111
116 WTSFreeMemory(username); 112 WTSFreeMemory(username);
117 113
118 if (len == 0) 114 if (len == 0)
119 continue; 115 continue;
120 116
121 if (wtsinfo[index].State == WTSActive || 117 if (wtsinfo[index].State == WTSActive || wtsinfo[index].State == WTSDisconnected)
122 wtsinfo[index].State == WTSDisconnected) 118 users++;
123 users++; 119 }
124 }
125 120
126 WTSFreeMemory(wtsinfo); 121 WTSFreeMemory(wtsinfo);
127#elif HAVE_UTMPX_H 122#elif HAVE_UTMPX_H
128 /* get currently logged users from utmpx */ 123 /* get currently logged users from utmpx */
129 setutxent (); 124 setutxent();
130 125
131 while ((putmpx = getutxent ()) != NULL) 126 while ((putmpx = getutxent()) != NULL)
132 if (putmpx->ut_type == USER_PROCESS) 127 if (putmpx->ut_type == USER_PROCESS)
133 users++; 128 users++;
134 129
135 endutxent (); 130 endutxent();
136#else 131#else
137 /* run the command */ 132 /* run the command */
138 child_process = spopen (WHO_COMMAND); 133 child_process = spopen(WHO_COMMAND);
139 if (child_process == NULL) { 134 if (child_process == NULL) {
140 printf (_("Could not open pipe: %s\n"), WHO_COMMAND); 135 printf(_("Could not open pipe: %s\n"), WHO_COMMAND);
141 return STATE_UNKNOWN; 136 return STATE_UNKNOWN;
142 } 137 }
143 138
144 child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r"); 139 child_stderr = fdopen(child_stderr_array[fileno(child_process)], "r");
145 if (child_stderr == NULL) 140 if (child_stderr == NULL)
146 printf (_("Could not open stderr for %s\n"), WHO_COMMAND); 141 printf(_("Could not open stderr for %s\n"), WHO_COMMAND);
147 142
148 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) { 143 while (fgets(input_buffer, MAX_INPUT_BUFFER - 1, child_process)) {
149 /* increment 'users' on all lines except total user count */ 144 /* increment 'users' on all lines except total user count */
150 if (input_buffer[0] != '#') { 145 if (input_buffer[0] != '#') {
151 users++; 146 users++;
@@ -153,18 +148,18 @@ main (int argc, char **argv)
153 } 148 }
154 149
155 /* get total logged in users */ 150 /* get total logged in users */
156 if (sscanf (input_buffer, _("# users=%d"), &users) == 1) 151 if (sscanf(input_buffer, _("# users=%d"), &users) == 1)
157 break; 152 break;
158 } 153 }
159 154
160 /* check STDERR */ 155 /* check STDERR */
161 if (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr)) 156 if (fgets(input_buffer, MAX_INPUT_BUFFER - 1, child_stderr))
162 result = possibly_set (result, STATE_UNKNOWN); 157 result = possibly_set(result, STATE_UNKNOWN);
163 (void) fclose (child_stderr); 158 (void)fclose(child_stderr);
164 159
165 /* close the pipe */ 160 /* close the pipe */
166 if (spclose (child_process)) 161 if (spclose(child_process))
167 result = possibly_set (result, STATE_UNKNOWN); 162 result = possibly_set(result, STATE_UNKNOWN);
168#endif 163#endif
169#ifdef HAVE_LIBSYSTEMD 164#ifdef HAVE_LIBSYSTEMD
170 } 165 }
@@ -174,109 +169,99 @@ main (int argc, char **argv)
174 result = get_status((double)users, thlds); 169 result = get_status((double)users, thlds);
175 170
176 if (result == STATE_UNKNOWN) 171 if (result == STATE_UNKNOWN)
177 printf ("%s\n", _("Unable to read output")); 172 printf("%s\n", _("Unable to read output"));
178 else { 173 else {
179 printf (_("USERS %s - %d users currently logged in |%s\n"), 174 printf(_("USERS %s - %d users currently logged in |%s\n"), state_text(result), users,
180 state_text(result), users, 175 sperfdata_int("users", users, "", warning_range, critical_range, true, 0, false, 0));
181 sperfdata_int("users", users, "", warning_range,
182 critical_range, true, 0, false, 0));
183 } 176 }
184 177
185 return result; 178 return result;
186} 179}
187 180
188/* process command-line arguments */ 181/* process command-line arguments */
189int 182int process_arguments(int argc, char **argv) {
190process_arguments (int argc, char **argv) 183 static struct option longopts[] = {{"critical", required_argument, 0, 'c'},
191{ 184 {"warning", required_argument, 0, 'w'},
192 int c; 185 {"version", no_argument, 0, 'V'},
193 int option = 0; 186 {"help", no_argument, 0, 'h'},
194 static struct option longopts[] = { 187 {0, 0, 0, 0}};
195 {"critical", required_argument, 0, 'c'},
196 {"warning", required_argument, 0, 'w'},
197 {"version", no_argument, 0, 'V'},
198 {"help", no_argument, 0, 'h'},
199 {0, 0, 0, 0}
200 };
201 188
202 if (argc < 2) 189 if (argc < 2)
203 usage ("\n"); 190 usage("\n");
204 191
192 int option_char;
205 while (true) { 193 while (true) {
206 c = getopt_long (argc, argv, "+hVvc:w:", longopts, &option); 194 int option = 0;
195 option_char = getopt_long(argc, argv, "+hVvc:w:", longopts, &option);
207 196
208 if (c == -1 || c == EOF || c == 1) 197 if (option_char == -1 || option_char == EOF || option_char == 1)
209 break; 198 break;
210 199
211 switch (c) { 200 switch (option_char) {
212 case '?': /* print short usage statement if args not parsable */ 201 case '?': /* print short usage statement if args not parsable */
213 usage5 (); 202 usage5();
214 case 'h': /* help */ 203 case 'h': /* help */
215 print_help (); 204 print_help();
216 exit (STATE_UNKNOWN); 205 exit(STATE_UNKNOWN);
217 case 'V': /* version */ 206 case 'V': /* version */
218 print_revision (progname, NP_VERSION); 207 print_revision(progname, NP_VERSION);
219 exit (STATE_UNKNOWN); 208 exit(STATE_UNKNOWN);
220 case 'c': /* critical */ 209 case 'c': /* critical */
221 critical_range = optarg; 210 critical_range = optarg;
222 break; 211 break;
223 case 'w': /* warning */ 212 case 'w': /* warning */
224 warning_range = optarg; 213 warning_range = optarg;
225 break; 214 break;
226 } 215 }
227 } 216 }
228 217
229 c = optind; 218 option_char = optind;
230 219
231 if (warning_range == NULL && argc > c) 220 if (warning_range == NULL && argc > option_char)
232 warning_range = argv[c++]; 221 warning_range = argv[option_char++];
233 222
234 if (critical_range == NULL && argc > c) 223 if (critical_range == NULL && argc > option_char)
235 critical_range = argv[c++]; 224 critical_range = argv[option_char++];
236 225
237 /* this will abort in case of invalid ranges */ 226 /* this will abort in case of invalid ranges */
238 set_thresholds (&thlds, warning_range, critical_range); 227 set_thresholds(&thlds, warning_range, critical_range);
239 228
240 if (!thlds->warning) { 229 if (!thlds->warning) {
241 usage4 (_("Warning threshold must be a valid range expression")); 230 usage4(_("Warning threshold must be a valid range expression"));
242 } 231 }
243 232
244 if (!thlds->critical) { 233 if (!thlds->critical) {
245 usage4 (_("Critical threshold must be a valid range expression")); 234 usage4(_("Critical threshold must be a valid range expression"));
246 } 235 }
247 236
248 return OK; 237 return OK;
249} 238}
250 239
251void 240void print_help(void) {
252print_help (void) 241 print_revision(progname, NP_VERSION);
253{
254 print_revision (progname, NP_VERSION);
255 242
256 printf ("Copyright (c) 1999 Ethan Galstad\n"); 243 printf("Copyright (c) 1999 Ethan Galstad\n");
257 printf (COPYRIGHT, copyright, email); 244 printf(COPYRIGHT, copyright, email);
258 245
259 printf ("%s\n", _("This plugin checks the number of users currently logged in on the local")); 246 printf("%s\n", _("This plugin checks the number of users currently logged in on the local"));
260 printf ("%s\n", _("system and generates an error if the number exceeds the thresholds specified.")); 247 printf("%s\n", _("system and generates an error if the number exceeds the thresholds specified."));
261 248
262 printf ("\n\n"); 249 printf("\n\n");
263 250
264 print_usage (); 251 print_usage();
265 252
266 printf (UT_HELP_VRSN); 253 printf(UT_HELP_VRSN);
267 printf (UT_EXTRA_OPTS); 254 printf(UT_EXTRA_OPTS);
268 255
269 printf (" %s\n", "-w, --warning=RANGE_EXPRESSION"); 256 printf(" %s\n", "-w, --warning=RANGE_EXPRESSION");
270 printf (" %s\n", _("Set WARNING status if number of logged in users violates RANGE_EXPRESSION")); 257 printf(" %s\n", _("Set WARNING status if number of logged in users violates RANGE_EXPRESSION"));
271 printf (" %s\n", "-c, --critical=RANGE_EXPRESSION"); 258 printf(" %s\n", "-c, --critical=RANGE_EXPRESSION");
272 printf (" %s\n", _("Set CRITICAL status if number of logged in users violates RANGE_EXPRESSION")); 259 printf(" %s\n", _("Set CRITICAL status if number of logged in users violates RANGE_EXPRESSION"));
273 260
274 printf (UT_SUPPORT); 261 printf(UT_SUPPORT);
275} 262}
276 263
277void 264void print_usage(void) {
278print_usage (void) 265 printf("%s\n", _("Usage:"));
279{ 266 printf("%s -w <users> -c <users>\n", progname);
280 printf ("%s\n", _("Usage:"));
281 printf ("%s -w <users> -c <users>\n", progname);
282} 267}
diff --git a/plugins/negate.c b/plugins/negate.c
index 745c12ac..7e52fe67 100644
--- a/plugins/negate.c
+++ b/plugins/negate.c
@@ -1,36 +1,36 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring negate plugin 3 * Monitoring negate plugin
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 2002-2008 Monitoring Plugins Development Team 6 * Copyright (c) 2002-2024 Monitoring Plugins Development Team
7* 7 *
8* Description: 8 * Description:
9* 9 *
10* This file contains the negate plugin 10 * This file contains the negate plugin
11* 11 *
12* Negates the status of a plugin (returns OK for CRITICAL, and vice-versa). 12 * Negates the status of a plugin (returns OK for CRITICAL, and vice-versa).
13* Can also perform custom state switching. 13 * Can also perform custom state switching.
14* 14 *
15* 15 *
16* This program is free software: you can redistribute it and/or modify 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 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 18 * the Free Software Foundation, either version 3 of the License, or
19* (at your option) any later version. 19 * (at your option) any later version.
20* 20 *
21* This program is distributed in the hope that it will be useful, 21 * This program is distributed in the hope that it will be useful,
22* but WITHOUT ANY WARRANTY; without even the implied warranty of 22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24* GNU General Public License for more details. 24 * GNU General Public License for more details.
25* 25 *
26* You should have received a copy of the GNU General Public License 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/>. 27 * along with this program. If not, see <http://www.gnu.org/licenses/>.
28* 28 *
29* 29 *
30*****************************************************************************/ 30 *****************************************************************************/
31 31
32const char *progname = "negate"; 32const char *progname = "negate";
33const char *copyright = "2002-2008"; 33const char *copyright = "2002-2024";
34const char *email = "devel@monitoring-plugins.org"; 34const char *email = "devel@monitoring-plugins.org";
35 35
36#define DEFAULT_TIMEOUT 11 36#define DEFAULT_TIMEOUT 11
@@ -41,13 +41,11 @@ const char *email = "devel@monitoring-plugins.org";
41 41
42#include <ctype.h> 42#include <ctype.h>
43 43
44/* char *command_line; */ 44static const char **process_arguments(int /*argc*/, char ** /*argv*/);
45 45static void validate_arguments(char ** /*command_line*/);
46static const char **process_arguments (int, char **); 46static void print_help(void);
47void validate_arguments (char **); 47void print_usage(void);
48void print_help (void); 48static bool subst_text = false;
49void print_usage (void);
50bool subst_text = false;
51 49
52static int state[4] = { 50static int state[4] = {
53 STATE_OK, 51 STATE_OK,
@@ -56,183 +54,165 @@ static int state[4] = {
56 STATE_UNKNOWN, 54 STATE_UNKNOWN,
57}; 55};
58 56
59int 57int main(int argc, char **argv) {
60main (int argc, char **argv) 58 setlocale(LC_ALL, "");
61{ 59 bindtextdomain(PACKAGE, LOCALEDIR);
62 int result = STATE_UNKNOWN; 60 textdomain(PACKAGE);
63 char *sub;
64 char **command_line;
65 output chld_out, chld_err;
66
67 setlocale (LC_ALL, "");
68 bindtextdomain (PACKAGE, LOCALEDIR);
69 textdomain (PACKAGE);
70 61
71 timeout_interval = DEFAULT_TIMEOUT; 62 timeout_interval = DEFAULT_TIMEOUT;
72 63
73 command_line = (char **) process_arguments (argc, argv); 64 char **command_line = (char **)process_arguments(argc, argv);
74 65
75 /* Set signal handling and alarm */ 66 /* Set signal handling and alarm */
76 if (signal (SIGALRM, timeout_alarm_handler) == SIG_ERR) 67 if (signal(SIGALRM, timeout_alarm_handler) == SIG_ERR)
77 die (STATE_UNKNOWN, _("Cannot catch SIGALRM")); 68 die(STATE_UNKNOWN, _("Cannot catch SIGALRM"));
78 69
79 (void) alarm ((unsigned) timeout_interval); 70 (void)alarm((unsigned)timeout_interval);
71
72 int result = STATE_UNKNOWN;
73 output chld_out;
74 output chld_err;
80 75
81 /* catch when the command is quoted */ 76 /* catch when the command is quoted */
82 if(command_line[1] == NULL) { 77 if (command_line[1] == NULL) {
83 result = cmd_run (command_line[0], &chld_out, &chld_err, 0); 78 result = cmd_run(command_line[0], &chld_out, &chld_err, 0);
84 } else { 79 } else {
85 result = cmd_run_array (command_line, &chld_out, &chld_err, 0); 80 result = cmd_run_array(command_line, &chld_out, &chld_err, 0);
86 } 81 }
87 if (chld_err.lines > 0) { 82 if (chld_err.lines > 0) {
88 for (size_t i = 0; i < chld_err.lines; i++) { 83 for (size_t i = 0; i < chld_err.lines; i++) {
89 fprintf (stderr, "%s\n", chld_err.line[i]); 84 fprintf(stderr, "%s\n", chld_err.line[i]);
90 } 85 }
91 } 86 }
92 87
93 /* Return UNKNOWN or worse if no output is returned */ 88 /* Return UNKNOWN or worse if no output is returned */
94 if (chld_out.lines == 0) 89 if (chld_out.lines == 0)
95 die (max_state_alt (result, STATE_UNKNOWN), _("No data returned from command\n")); 90 die(max_state_alt(result, STATE_UNKNOWN), _("No data returned from command\n"));
96 91
92 char *sub;
97 for (size_t i = 0; i < chld_out.lines; i++) { 93 for (size_t i = 0; i < chld_out.lines; i++) {
98 if (subst_text && result >= 0 && result <= 4 && result != state[result]) { 94 if (subst_text && result >= 0 && result <= 4 && result != state[result]) {
99 /* Loop over each match found */ 95 /* Loop over each match found */
100 while ((sub = strstr (chld_out.line[i], state_text (result)))) { 96 while ((sub = strstr(chld_out.line[i], state_text(result)))) {
101 /* Terminate the first part and skip over the string we'll substitute */ 97 /* Terminate the first part and skip over the string we'll substitute */
102 *sub = '\0'; 98 *sub = '\0';
103 sub += strlen (state_text (result)); 99 sub += strlen(state_text(result));
104 /* then put everything back together */ 100 /* then put everything back together */
105 xasprintf (&chld_out.line[i], "%s%s%s", chld_out.line[i], state_text (state[result]), sub); 101 xasprintf(&chld_out.line[i], "%s%s%s", chld_out.line[i], state_text(state[result]), sub);
106 } 102 }
107 } 103 }
108 printf ("%s\n", chld_out.line[i]); 104 printf("%s\n", chld_out.line[i]);
109 } 105 }
110 106
111 if (result >= 0 && result <= 4) { 107 if (result >= 0 && result <= 4) {
112 exit (state[result]); 108 exit(state[result]);
113 } else { 109 } else {
114 exit (result); 110 exit(result);
115 } 111 }
116} 112}
117 113
118
119/* process command-line arguments */ 114/* process command-line arguments */
120static const char ** 115static const char **process_arguments(int argc, char **argv) {
121process_arguments (int argc, char **argv) 116 static struct option longopts[] = {{"help", no_argument, 0, 'h'}, {"version", no_argument, 0, 'V'},
122{ 117 {"timeout", required_argument, 0, 't'}, {"timeout-result", required_argument, 0, 'T'},
123 int c; 118 {"ok", required_argument, 0, 'o'}, {"warning", required_argument, 0, 'w'},
119 {"critical", required_argument, 0, 'c'}, {"unknown", required_argument, 0, 'u'},
120 {"substitute", no_argument, 0, 's'}, {0, 0, 0, 0}};
121
124 bool permute = true; 122 bool permute = true;
123 while (true) {
124 int option = 0;
125 int option_char = getopt_long(argc, argv, "+hVt:T:o:w:c:u:s", longopts, &option);
125 126
126 int option = 0; 127 if (option_char == -1 || option_char == EOF)
127 static struct option longopts[] = {
128 {"help", no_argument, 0, 'h'},
129 {"version", no_argument, 0, 'V'},
130 {"timeout", required_argument, 0, 't'},
131 {"timeout-result", required_argument, 0, 'T'},
132 {"ok", required_argument, 0, 'o'},
133 {"warning", required_argument, 0, 'w'},
134 {"critical", required_argument, 0, 'c'},
135 {"unknown", required_argument, 0, 'u'},
136 {"substitute", no_argument, 0, 's'},
137 {0, 0, 0, 0}
138 };
139
140 while (1) {
141 c = getopt_long (argc, argv, "+hVt:T:o:w:c:u:s", longopts, &option);
142
143 if (c == -1 || c == EOF)
144 break; 128 break;
145 129
146 switch (c) { 130 switch (option_char) {
147 case '?': /* help */ 131 case '?': /* help */
148 usage5 (); 132 usage5();
149 break; 133 break;
150 case 'h': /* help */ 134 case 'h': /* help */
151 print_help (); 135 print_help();
152 exit (EXIT_SUCCESS); 136 exit(EXIT_SUCCESS);
153 break; 137 break;
154 case 'V': /* version */ 138 case 'V': /* version */
155 print_revision (progname, NP_VERSION); 139 print_revision(progname, NP_VERSION);
156 exit (EXIT_SUCCESS); 140 exit(EXIT_SUCCESS);
157 case 't': /* timeout period */ 141 case 't': /* timeout period */
158 if (!is_integer (optarg)) 142 if (!is_integer(optarg))
159 usage2 (_("Timeout interval must be a positive integer"), optarg); 143 usage2(_("Timeout interval must be a positive integer"), optarg);
160 else 144 else
161 timeout_interval = atoi (optarg); 145 timeout_interval = atoi(optarg);
162 break; 146 break;
163 case 'T': /* Result to return on timeouts */ 147 case 'T': /* Result to return on timeouts */
164 if ((timeout_state = mp_translate_state(optarg)) == ERROR) 148 if ((timeout_state = mp_translate_state(optarg)) == ERROR)
165 usage4 (_("Timeout result must be a valid state name (OK, WARNING, CRITICAL, UNKNOWN) or integer (0-3).")); 149 usage4(_("Timeout result must be a valid state name (OK, WARNING, CRITICAL, UNKNOWN) or integer (0-3)."));
166 break; 150 break;
167 case 'o': /* replacement for OK */ 151 case 'o': /* replacement for OK */
168 if ((state[STATE_OK] = mp_translate_state(optarg)) == ERROR) 152 if ((state[STATE_OK] = mp_translate_state(optarg)) == ERROR)
169 usage4 (_("Ok must be a valid state name (OK, WARNING, CRITICAL, UNKNOWN) or integer (0-3).")); 153 usage4(_("Ok must be a valid state name (OK, WARNING, CRITICAL, UNKNOWN) or integer (0-3)."));
170 permute = false; 154 permute = false;
171 break; 155 break;
172 156
173 case 'w': /* replacement for WARNING */ 157 case 'w': /* replacement for WARNING */
174 if ((state[STATE_WARNING] = mp_translate_state(optarg)) == ERROR) 158 if ((state[STATE_WARNING] = mp_translate_state(optarg)) == ERROR)
175 usage4 (_("Warning must be a valid state name (OK, WARNING, CRITICAL, UNKNOWN) or integer (0-3).")); 159 usage4(_("Warning must be a valid state name (OK, WARNING, CRITICAL, UNKNOWN) or integer (0-3)."));
176 permute = false; 160 permute = false;
177 break; 161 break;
178 case 'c': /* replacement for CRITICAL */ 162 case 'c': /* replacement for CRITICAL */
179 if ((state[STATE_CRITICAL] = mp_translate_state(optarg)) == ERROR) 163 if ((state[STATE_CRITICAL] = mp_translate_state(optarg)) == ERROR)
180 usage4 (_("Critical must be a valid state name (OK, WARNING, CRITICAL, UNKNOWN) or integer (0-3).")); 164 usage4(_("Critical must be a valid state name (OK, WARNING, CRITICAL, UNKNOWN) or integer (0-3)."));
181 permute = false; 165 permute = false;
182 break; 166 break;
183 case 'u': /* replacement for UNKNOWN */ 167 case 'u': /* replacement for UNKNOWN */
184 if ((state[STATE_UNKNOWN] = mp_translate_state(optarg)) == ERROR) 168 if ((state[STATE_UNKNOWN] = mp_translate_state(optarg)) == ERROR)
185 usage4 (_("Unknown must be a valid state name (OK, WARNING, CRITICAL, UNKNOWN) or integer (0-3).")); 169 usage4(_("Unknown must be a valid state name (OK, WARNING, CRITICAL, UNKNOWN) or integer (0-3)."));
186 permute = false; 170 permute = false;
187 break; 171 break;
188 case 's': /* Substitute status text */ 172 case 's': /* Substitute status text */
189 subst_text = true; 173 subst_text = true;
190 break; 174 break;
191 } 175 }
192 } 176 }
193 177
194 validate_arguments (&argv[optind]); 178 validate_arguments(&argv[optind]);
195 179
196 if (permute) { /* No [owcu] switch specified, default to this */ 180 if (permute) { /* No [owcu] switch specified, default to this */
197 state[STATE_OK] = STATE_CRITICAL; 181 state[STATE_OK] = STATE_CRITICAL;
198 state[STATE_CRITICAL] = STATE_OK; 182 state[STATE_CRITICAL] = STATE_OK;
199 } 183 }
200 184
201 return (const char **) &argv[optind]; 185 return (const char **)&argv[optind];
202} 186}
203 187
204 188void validate_arguments(char **command_line) {
205void
206validate_arguments (char **command_line)
207{
208 if (command_line[0] == NULL) 189 if (command_line[0] == NULL)
209 usage4 (_("Could not parse arguments")); 190 usage4(_("Could not parse arguments"));
210 191
211 if (strncmp(command_line[0],"/",1) != 0 && strncmp(command_line[0],"./",2) != 0) 192 if (strncmp(command_line[0], "/", 1) != 0 && strncmp(command_line[0], "./", 2) != 0)
212 usage4 (_("Require path to command")); 193 usage4(_("Require path to command"));
213} 194}
214 195
196void print_help(void) {
197 print_revision(progname, NP_VERSION);
215 198
216void 199 printf(COPYRIGHT, copyright, email);
217print_help (void)
218{
219 print_revision (progname, NP_VERSION);
220 200
221 printf (COPYRIGHT, copyright, email); 201 printf("%s\n", _("Negates only the return code of a plugin (returns OK for CRITICAL and vice-versa) by default."));
202 printf("%s\n", _("Additional switches can be used to control:\n"));
203 printf("\t - which state becomes what\n");
204 printf("\t - changing the plugin output text to match the return code");
222 205
223 printf ("%s\n", _("Negates the status of a plugin (returns OK for CRITICAL and vice-versa).")); 206 printf("\n\n");
224 printf ("%s\n", _("Additional switches can be used to control which state becomes what."));
225 207
226 printf ("\n\n"); 208 print_usage();
227 209
228 print_usage (); 210 printf(UT_HELP_VRSN);
229 211
230 printf (UT_HELP_VRSN); 212 printf(UT_PLUG_TIMEOUT, timeout_interval);
231 213 printf(" %s\n", _("Keep timeout longer than the plugin timeout to retain CRITICAL status."));
232 printf (UT_PLUG_TIMEOUT, timeout_interval); 214 printf(" -T, --timeout-result=STATUS\n");
233 printf (" %s\n", _("Keep timeout longer than the plugin timeout to retain CRITICAL status.")); 215 printf(" %s\n", _("Custom result on Negate timeouts; see below for STATUS definition\n"));
234 printf (" -T, --timeout-result=STATUS\n");
235 printf (" %s\n", _("Custom result on Negate timeouts; see below for STATUS definition\n"));
236 216
237 printf(" -o, --ok=STATUS\n"); 217 printf(" -o, --ok=STATUS\n");
238 printf(" -w, --warning=STATUS\n"); 218 printf(" -w, --warning=STATUS\n");
@@ -244,31 +224,27 @@ print_help (void)
244 printf(" -s, --substitute\n"); 224 printf(" -s, --substitute\n");
245 printf(_(" Substitute output text as well. Will only substitute text in CAPITALS\n")); 225 printf(_(" Substitute output text as well. Will only substitute text in CAPITALS\n"));
246 226
247 printf ("\n"); 227 printf("\n");
248 printf ("%s\n", _("Examples:")); 228 printf("%s\n", _("Examples:"));
249 printf (" %s\n", "negate /usr/local/nagios/libexec/check_ping -H host"); 229 printf(" %s\n", "negate /usr/local/nagios/libexec/check_ping -H host");
250 printf (" %s\n", _("Run check_ping and invert result. Must use full path to plugin")); 230 printf(" %s\n", _("Run check_ping and invert result. Must use full path to plugin"));
251 printf (" %s\n", "negate -w OK -c UNKNOWN /usr/local/nagios/libexec/check_procs -a 'vi negate.c'"); 231 printf(" %s\n", "negate -w OK -c UNKNOWN /usr/local/nagios/libexec/check_procs -a 'vi negate.c'");
252 printf (" %s\n", _("This will return OK instead of WARNING and UNKNOWN instead of CRITICAL")); 232 printf(" %s\n", _("This will return OK instead of WARNING and UNKNOWN instead of CRITICAL"));
253 printf ("\n"); 233 printf("\n");
254 printf ("%s\n", _("Notes:")); 234 printf("%s\n", _("Notes:"));
255 printf (" %s\n", _("This plugin is a wrapper to take the output of another plugin and invert it.")); 235 printf(" %s\n", _("This plugin is a wrapper to take the output of another plugin and invert it."));
256 printf (" %s\n", _("The full path of the plugin must be provided.")); 236 printf(" %s\n", _("The full path of the plugin must be provided."));
257 printf (" %s\n", _("If the wrapped plugin returns OK, the wrapper will return CRITICAL.")); 237 printf(" %s\n", _("If the wrapped plugin returns OK, the wrapper will return CRITICAL."));
258 printf (" %s\n", _("If the wrapped plugin returns CRITICAL, the wrapper will return OK.")); 238 printf(" %s\n", _("If the wrapped plugin returns CRITICAL, the wrapper will return OK."));
259 printf (" %s\n", _("Otherwise, the output state of the wrapped plugin is unchanged.")); 239 printf(" %s\n", _("Otherwise, the output state of the wrapped plugin is unchanged."));
260 printf ("\n"); 240 printf("\n");
261 printf (" %s\n", _("Using timeout-result, it is possible to override the timeout behaviour or a")); 241 printf(" %s\n", _("Using timeout-result, it is possible to override the timeout behaviour or a"));
262 printf (" %s\n", _("plugin by setting the negate timeout a bit lower.")); 242 printf(" %s\n", _("plugin by setting the negate timeout a bit lower."));
263 243
264 printf (UT_SUPPORT); 244 printf(UT_SUPPORT);
265} 245}
266 246
267 247void print_usage(void) {
268 248 printf("%s\n", _("Usage:"));
269void 249 printf("%s [-t timeout] [-Towcu STATE] [-s] <definition of wrapped plugin>\n", progname);
270print_usage (void)
271{
272 printf ("%s\n", _("Usage:"));
273 printf ("%s [-t timeout] [-Towcu STATE] [-s] <definition of wrapped plugin>\n", progname);
274} 250}
diff --git a/plugins/netutils.c b/plugins/netutils.c
index c6af248e..ee81912a 100644
--- a/plugins/netutils.c
+++ b/plugins/netutils.c
@@ -1,31 +1,31 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring Plugins network utilities 3 * Monitoring Plugins network utilities
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 1999 Ethan Galstad (nagios@nagios.org) 6 * Copyright (c) 1999 Ethan Galstad (nagios@nagios.org)
7* Copyright (c) 2003-2008 Monitoring Plugins Development Team 7 * Copyright (c) 2003-2024 Monitoring Plugins Development Team
8* 8 *
9* Description: 9 * Description:
10* 10 *
11* This file contains commons functions used in many of the plugins. 11 * This file contains commons functions used in many of the plugins.
12* 12 *
13* 13 *
14* This program is free software: you can redistribute it and/or modify 14 * This program is free software: you can redistribute it and/or modify
15* it under the terms of the GNU General Public License as published by 15 * it under the terms of the GNU General Public License as published by
16* the Free Software Foundation, either version 3 of the License, or 16 * the Free Software Foundation, either version 3 of the License, or
17* (at your option) any later version. 17 * (at your option) any later version.
18* 18 *
19* This program is distributed in the hope that it will be useful, 19 * This program is distributed in the hope that it will be useful,
20* but WITHOUT ANY WARRANTY; without even the implied warranty of 20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22* GNU General Public License for more details. 22 * GNU General Public License for more details.
23* 23 *
24* You should have received a copy of the GNU General Public License 24 * You should have received a copy of the GNU General Public License
25* along with this program. If not, see <http://www.gnu.org/licenses/>. 25 * along with this program. If not, see <http://www.gnu.org/licenses/>.
26* 26 *
27* 27 *
28*****************************************************************************/ 28 *****************************************************************************/
29 29
30#include "common.h" 30#include "common.h"
31#include "netutils.h" 31#include "netutils.h"
@@ -42,25 +42,19 @@ int address_family = AF_INET;
42#endif 42#endif
43 43
44/* handles socket timeouts */ 44/* handles socket timeouts */
45void 45void socket_timeout_alarm_handler(int sig) {
46socket_timeout_alarm_handler (int sig)
47{
48 if (sig == SIGALRM) 46 if (sig == SIGALRM)
49 printf (_("%s - Socket timeout after %d seconds\n"), state_text(socket_timeout_state), socket_timeout); 47 printf(_("%s - Socket timeout after %d seconds\n"), state_text(socket_timeout_state), socket_timeout);
50 else 48 else
51 printf (_("%s - Abnormal timeout after %d seconds\n"), state_text(socket_timeout_state), socket_timeout); 49 printf(_("%s - Abnormal timeout after %d seconds\n"), state_text(socket_timeout_state), socket_timeout);
52 50
53 exit (socket_timeout_state); 51 exit(socket_timeout_state);
54} 52}
55 53
56
57/* connects to a host on a specified tcp port, sends a string, and gets a 54/* connects to a host on a specified tcp port, sends a string, and gets a
58 response. loops on select-recv until timeout or eof to get all of a 55 response. loops on select-recv until timeout or eof to get all of a
59 multi-packet answer */ 56 multi-packet answer */
60int 57int process_tcp_request2(const char *server_address, int server_port, const char *send_buffer, char *recv_buffer, int recv_size) {
61process_tcp_request2 (const char *server_address, int server_port,
62 const char *send_buffer, char *recv_buffer, int recv_size)
63{
64 58
65 int result; 59 int result;
66 int send_result; 60 int send_result;
@@ -70,13 +64,13 @@ process_tcp_request2 (const char *server_address, int server_port,
70 fd_set readfds; 64 fd_set readfds;
71 int recv_length = 0; 65 int recv_length = 0;
72 66
73 result = np_net_connect (server_address, server_port, &sd, IPPROTO_TCP); 67 result = np_net_connect(server_address, server_port, &sd, IPPROTO_TCP);
74 if (result != STATE_OK) 68 if (result != STATE_OK)
75 return STATE_CRITICAL; 69 return STATE_CRITICAL;
76 70
77 send_result = send (sd, send_buffer, strlen (send_buffer), 0); 71 send_result = send(sd, send_buffer, strlen(send_buffer), 0);
78 if (send_result<0 || (size_t)send_result!=strlen(send_buffer)) { 72 if (send_result < 0 || (size_t)send_result != strlen(send_buffer)) {
79 printf ("%s\n", _("Send failed")); 73 printf("%s\n", _("Send failed"));
80 result = STATE_WARNING; 74 result = STATE_WARNING;
81 } 75 }
82 76
@@ -85,38 +79,32 @@ process_tcp_request2 (const char *server_address, int server_port,
85 minus one for data from the host */ 79 minus one for data from the host */
86 tv.tv_sec = socket_timeout - 1; 80 tv.tv_sec = socket_timeout - 1;
87 tv.tv_usec = 0; 81 tv.tv_usec = 0;
88 FD_ZERO (&readfds); 82 FD_ZERO(&readfds);
89 FD_SET (sd, &readfds); 83 FD_SET(sd, &readfds);
90 select (sd + 1, &readfds, NULL, NULL, &tv); 84 select(sd + 1, &readfds, NULL, NULL, &tv);
91 85
92 /* make sure some data has arrived */ 86 /* make sure some data has arrived */
93 if (!FD_ISSET (sd, &readfds)) { /* it hasn't */ 87 if (!FD_ISSET(sd, &readfds)) { /* it hasn't */
94 if (!recv_length) { 88 if (!recv_length) {
95 strcpy (recv_buffer, ""); 89 strcpy(recv_buffer, "");
96 printf ("%s\n", _("No data was received from host!")); 90 printf("%s\n", _("No data was received from host!"));
97 result = STATE_WARNING; 91 result = STATE_WARNING;
98 } 92 } else { /* this one failed, but previous ones worked */
99 else { /* this one failed, but previous ones worked */
100 recv_buffer[recv_length] = 0; 93 recv_buffer[recv_length] = 0;
101 } 94 }
102 break; 95 break;
103 } 96 } else { /* it has */
104 else { /* it has */ 97 recv_result = recv(sd, recv_buffer + recv_length, (size_t)recv_size - recv_length - 1, 0);
105 recv_result =
106 recv (sd, recv_buffer + recv_length,
107 (size_t)recv_size - recv_length - 1, 0);
108 if (recv_result == -1) { 98 if (recv_result == -1) {
109 /* recv failed, bail out */ 99 /* recv failed, bail out */
110 strcpy (recv_buffer + recv_length, ""); 100 strcpy(recv_buffer + recv_length, "");
111 result = STATE_WARNING; 101 result = STATE_WARNING;
112 break; 102 break;
113 } 103 } else if (recv_result == 0) {
114 else if (recv_result == 0) {
115 /* end of file ? */ 104 /* end of file ? */
116 recv_buffer[recv_length] = 0; 105 recv_buffer[recv_length] = 0;
117 break; 106 break;
118 } 107 } else { /* we got data! */
119 else { /* we got data! */
120 recv_length += recv_result; 108 recv_length += recv_result;
121 if (recv_length >= recv_size - 1) { 109 if (recv_length >= recv_size - 1) {
122 /* buffer full, we're done */ 110 /* buffer full, we're done */
@@ -129,42 +117,35 @@ process_tcp_request2 (const char *server_address, int server_port,
129 } 117 }
130 /* end while(1) */ 118 /* end while(1) */
131 119
132 close (sd); 120 close(sd);
133 return result; 121 return result;
134} 122}
135 123
136
137/* connects to a host on a specified port, sends a string, and gets a 124/* connects to a host on a specified port, sends a string, and gets a
138 response */ 125 response */
139int 126int process_request(const char *server_address, int server_port, int proto, const char *send_buffer, char *recv_buffer, int recv_size) {
140process_request (const char *server_address, int server_port, int proto,
141 const char *send_buffer, char *recv_buffer, int recv_size)
142{
143 int result; 127 int result;
144 int sd; 128 int sd;
145 129
146 result = STATE_OK; 130 result = STATE_OK;
147 131
148 result = np_net_connect (server_address, server_port, &sd, proto); 132 result = np_net_connect(server_address, server_port, &sd, proto);
149 if (result != STATE_OK) 133 if (result != STATE_OK)
150 return STATE_CRITICAL; 134 return STATE_CRITICAL;
151 135
152 result = send_request (sd, proto, send_buffer, recv_buffer, recv_size); 136 result = send_request(sd, proto, send_buffer, recv_buffer, recv_size);
153 137
154 close (sd); 138 close(sd);
155 139
156 return result; 140 return result;
157} 141}
158 142
159
160/* opens a tcp or udp connection to a remote host or local socket */ 143/* opens a tcp or udp connection to a remote host or local socket */
161int 144int np_net_connect(const char *host_name, int port, int *sd, int proto) {
162np_net_connect (const char *host_name, int port, int *sd, int proto) 145 /* send back STATE_UNKOWN if there's an error
163{ 146 send back STATE_OK if we connect
164 /* send back STATE_UNKOWN if there's an error 147 send back STATE_CRITICAL if we can't connect.
165 send back STATE_OK if we connect 148 Let upstream figure out what to send to the user. */
166 send back STATE_CRITICAL if we can't connect.
167 Let upstream figure out what to send to the user. */
168 struct addrinfo hints; 149 struct addrinfo hints;
169 struct addrinfo *r, *res; 150 struct addrinfo *r, *res;
170 struct sockaddr_un su; 151 struct sockaddr_un su;
@@ -176,13 +157,13 @@ np_net_connect (const char *host_name, int port, int *sd, int proto)
176 socktype = (proto == IPPROTO_UDP) ? SOCK_DGRAM : SOCK_STREAM; 157 socktype = (proto == IPPROTO_UDP) ? SOCK_DGRAM : SOCK_STREAM;
177 158
178 /* as long as it doesn't start with a '/', it's assumed a host or ip */ 159 /* as long as it doesn't start with a '/', it's assumed a host or ip */
179 if (!is_socket){ 160 if (!is_socket) {
180 memset (&hints, 0, sizeof (hints)); 161 memset(&hints, 0, sizeof(hints));
181 hints.ai_family = address_family; 162 hints.ai_family = address_family;
182 hints.ai_protocol = proto; 163 hints.ai_protocol = proto;
183 hints.ai_socktype = socktype; 164 hints.ai_socktype = socktype;
184 165
185 len = strlen (host_name); 166 len = strlen(host_name);
186 /* check for an [IPv6] address (and strip the brackets) */ 167 /* check for an [IPv6] address (and strip the brackets) */
187 if (len >= 2 && host_name[0] == '[' && host_name[len - 1] == ']') { 168 if (len >= 2 && host_name[0] == '[' && host_name[len - 1] == ']') {
188 host_name++; 169 host_name++;
@@ -190,29 +171,29 @@ np_net_connect (const char *host_name, int port, int *sd, int proto)
190 } 171 }
191 if (len >= sizeof(host)) 172 if (len >= sizeof(host))
192 return STATE_UNKNOWN; 173 return STATE_UNKNOWN;
193 memcpy (host, host_name, len); 174 memcpy(host, host_name, len);
194 host[len] = '\0'; 175 host[len] = '\0';
195 snprintf (port_str, sizeof (port_str), "%d", port); 176 snprintf(port_str, sizeof(port_str), "%d", port);
196 result = getaddrinfo (host, port_str, &hints, &res); 177 result = getaddrinfo(host, port_str, &hints, &res);
197 178
198 if (result != 0) { 179 if (result != 0) {
199 printf ("%s\n", gai_strerror (result)); 180 printf("%s\n", gai_strerror(result));
200 return STATE_UNKNOWN; 181 return STATE_UNKNOWN;
201 } 182 }
202 183
203 r = res; 184 r = res;
204 while (r) { 185 while (r) {
205 /* attempt to create a socket */ 186 /* attempt to create a socket */
206 *sd = socket (r->ai_family, socktype, r->ai_protocol); 187 *sd = socket(r->ai_family, socktype, r->ai_protocol);
207 188
208 if (*sd < 0) { 189 if (*sd < 0) {
209 printf ("%s\n", _("Socket creation failed")); 190 printf("%s\n", _("Socket creation failed"));
210 freeaddrinfo (r); 191 freeaddrinfo(r);
211 return STATE_UNKNOWN; 192 return STATE_UNKNOWN;
212 } 193 }
213 194
214 /* attempt to open a connection */ 195 /* attempt to open a connection */
215 result = connect (*sd, r->ai_addr, r->ai_addrlen); 196 result = connect(*sd, r->ai_addr, r->ai_addrlen);
216 197
217 if (result == 0) { 198 if (result == 0) {
218 was_refused = false; 199 was_refused = false;
@@ -227,21 +208,21 @@ np_net_connect (const char *host_name, int port, int *sd, int proto)
227 } 208 }
228 } 209 }
229 210
230 close (*sd); 211 close(*sd);
231 r = r->ai_next; 212 r = r->ai_next;
232 } 213 }
233 freeaddrinfo (res); 214 freeaddrinfo(res);
234 } 215 }
235 /* else the hostname is interpreted as a path to a unix socket */ 216 /* else the hostname is interpreted as a path to a unix socket */
236 else { 217 else {
237 if(strlen(host_name) >= UNIX_PATH_MAX){ 218 if (strlen(host_name) >= UNIX_PATH_MAX) {
238 die(STATE_UNKNOWN, _("Supplied path too long unix domain socket")); 219 die(STATE_UNKNOWN, _("Supplied path too long unix domain socket"));
239 } 220 }
240 memset(&su, 0, sizeof(su)); 221 memset(&su, 0, sizeof(su));
241 su.sun_family = AF_UNIX; 222 su.sun_family = AF_UNIX;
242 strncpy(su.sun_path, host_name, UNIX_PATH_MAX); 223 strncpy(su.sun_path, host_name, UNIX_PATH_MAX);
243 *sd = socket(PF_UNIX, SOCK_STREAM, 0); 224 *sd = socket(PF_UNIX, SOCK_STREAM, 0);
244 if(*sd < 0){ 225 if (*sd < 0) {
245 die(STATE_UNKNOWN, _("Socket creation failed")); 226 die(STATE_UNKNOWN, _("Socket creation failed"));
246 } 227 }
247 result = connect(*sd, (struct sockaddr *)&su, sizeof(su)); 228 result = connect(*sd, (struct sockaddr *)&su, sizeof(su));
@@ -259,37 +240,32 @@ np_net_connect (const char *host_name, int port, int *sd, int proto)
259 if (is_socket) 240 if (is_socket)
260 printf("connect to file socket %s: %s\n", host_name, strerror(errno)); 241 printf("connect to file socket %s: %s\n", host_name, strerror(errno));
261 else 242 else
262 printf("connect to address %s and port %d: %s\n", 243 printf("connect to address %s and port %d: %s\n", host_name, port, strerror(errno));
263 host_name, port, strerror(errno));
264 return STATE_CRITICAL; 244 return STATE_CRITICAL;
265 break; 245 break;
266 default: /* it's a logic error if we do not end up in STATE_(OK|WARNING|CRITICAL) */ 246 default: /* it's a logic error if we do not end up in STATE_(OK|WARNING|CRITICAL) */
267 return STATE_UNKNOWN; 247 return STATE_UNKNOWN;
268 break; 248 break;
269 } 249 }
270 } 250 } else {
271 else {
272 if (is_socket) 251 if (is_socket)
273 printf("connect to file socket %s: %s\n", host_name, strerror(errno)); 252 printf("connect to file socket %s: %s\n", host_name, strerror(errno));
274 else 253 else
275 printf("connect to address %s and port %d: %s\n", 254 printf("connect to address %s and port %d: %s\n", host_name, port, strerror(errno));
276 host_name, port, strerror(errno));
277 return STATE_CRITICAL; 255 return STATE_CRITICAL;
278 } 256 }
279} 257}
280 258
281int 259int send_request(int sd, int proto, const char *send_buffer, char *recv_buffer, int recv_size) {
282send_request (int sd, int proto, const char *send_buffer, char *recv_buffer, int recv_size)
283{
284 int result = STATE_OK; 260 int result = STATE_OK;
285 int send_result; 261 int send_result;
286 int recv_result; 262 int recv_result;
287 struct timeval tv; 263 struct timeval tv;
288 fd_set readfds; 264 fd_set readfds;
289 265
290 send_result = send (sd, send_buffer, strlen (send_buffer), 0); 266 send_result = send(sd, send_buffer, strlen(send_buffer), 0);
291 if (send_result<0 || (size_t)send_result!=strlen(send_buffer)) { 267 if (send_result < 0 || (size_t)send_result != strlen(send_buffer)) {
292 printf ("%s\n", _("Send failed")); 268 printf("%s\n", _("Send failed"));
293 result = STATE_WARNING; 269 result = STATE_WARNING;
294 } 270 }
295 271
@@ -297,26 +273,25 @@ send_request (int sd, int proto, const char *send_buffer, char *recv_buffer, int
297 for data from the host */ 273 for data from the host */
298 tv.tv_sec = socket_timeout - 1; 274 tv.tv_sec = socket_timeout - 1;
299 tv.tv_usec = 0; 275 tv.tv_usec = 0;
300 FD_ZERO (&readfds); 276 FD_ZERO(&readfds);
301 FD_SET (sd, &readfds); 277 FD_SET(sd, &readfds);
302 select (sd + 1, &readfds, NULL, NULL, &tv); 278 select(sd + 1, &readfds, NULL, NULL, &tv);
303 279
304 /* make sure some data has arrived */ 280 /* make sure some data has arrived */
305 if (!FD_ISSET (sd, &readfds)) { 281 if (!FD_ISSET(sd, &readfds)) {
306 strcpy (recv_buffer, ""); 282 strcpy(recv_buffer, "");
307 printf ("%s\n", _("No data was received from host!")); 283 printf("%s\n", _("No data was received from host!"));
308 result = STATE_WARNING; 284 result = STATE_WARNING;
309 } 285 }
310 286
311 else { 287 else {
312 recv_result = recv (sd, recv_buffer, (size_t)recv_size - 1, 0); 288 recv_result = recv(sd, recv_buffer, (size_t)recv_size - 1, 0);
313 if (recv_result == -1) { 289 if (recv_result == -1) {
314 strcpy (recv_buffer, ""); 290 strcpy(recv_buffer, "");
315 if (proto != IPPROTO_TCP) 291 if (proto != IPPROTO_TCP)
316 printf ("%s\n", _("Receive failed")); 292 printf("%s\n", _("Receive failed"));
317 result = STATE_WARNING; 293 result = STATE_WARNING;
318 } 294 } else
319 else
320 recv_buffer[recv_result] = 0; 295 recv_buffer[recv_result] = 0;
321 296
322 /* die returned string */ 297 /* die returned string */
@@ -325,51 +300,46 @@ send_request (int sd, int proto, const char *send_buffer, char *recv_buffer, int
325 return result; 300 return result;
326} 301}
327 302
328 303bool is_host(const char *address) {
329bool is_host (const char *address) { 304 if (is_addr(address) || is_hostname(address))
330 if (is_addr (address) || is_hostname (address))
331 return (true); 305 return (true);
332 306
333 return (false); 307 return (false);
334} 308}
335 309
336void 310void host_or_die(const char *str) {
337host_or_die(const char *str) 311 if (!str || (!is_addr(str) && !is_hostname(str)))
338{
339 if(!str || (!is_addr(str) && !is_hostname(str)))
340 usage_va(_("Invalid hostname/address - %s"), str); 312 usage_va(_("Invalid hostname/address - %s"), str);
341} 313}
342 314
343bool is_addr (const char *address) { 315bool is_addr(const char *address) {
344#ifdef USE_IPV6 316#ifdef USE_IPV6
345 if (address_family == AF_INET && is_inet_addr (address)) 317 if (address_family == AF_INET && is_inet_addr(address))
346 return true; 318 return true;
347 else if (address_family == AF_INET6 && is_inet6_addr (address)) 319 else if (address_family == AF_INET6 && is_inet6_addr(address))
348 return true; 320 return true;
349#else 321#else
350 if (is_inet_addr (address)) 322 if (is_inet_addr(address))
351 return (true); 323 return (true);
352#endif 324#endif
353 325
354 return (false); 326 return (false);
355} 327}
356 328
357int 329int dns_lookup(const char *in, struct sockaddr_storage *ss, int family) {
358dns_lookup (const char *in, struct sockaddr_storage *ss, int family)
359{
360 struct addrinfo hints; 330 struct addrinfo hints;
361 struct addrinfo *res; 331 struct addrinfo *res;
362 int retval; 332 int retval;
363 333
364 memset (&hints, 0, sizeof(struct addrinfo)); 334 memset(&hints, 0, sizeof(struct addrinfo));
365 hints.ai_family = family; 335 hints.ai_family = family;
366 336
367 retval = getaddrinfo (in, NULL, &hints, &res); 337 retval = getaddrinfo(in, NULL, &hints, &res);
368 if (retval != 0) 338 if (retval != 0)
369 return false; 339 return false;
370 340
371 if (ss != NULL) 341 if (ss != NULL)
372 memcpy (ss, res->ai_addr, res->ai_addrlen); 342 memcpy(ss, res->ai_addr, res->ai_addrlen);
373 freeaddrinfo (res); 343 freeaddrinfo(res);
374 return true; 344 return true;
375} 345}
diff --git a/plugins/picohttpparser/picohttpparser.c b/plugins/picohttpparser/picohttpparser.c
index d0bfac62..2ae92d66 100644
--- a/plugins/picohttpparser/picohttpparser.c
+++ b/plugins/picohttpparser/picohttpparser.c
@@ -28,623 +28,610 @@
28#include <stddef.h> 28#include <stddef.h>
29#include <string.h> 29#include <string.h>
30#ifdef __SSE4_2__ 30#ifdef __SSE4_2__
31#ifdef _MSC_VER 31# ifdef _MSC_VER
32#include <nmmintrin.h> 32# include <nmmintrin.h>
33#else 33# else
34#include <x86intrin.h> 34# include <x86intrin.h>
35#endif 35# endif
36#endif 36#endif
37#include "picohttpparser.h" 37#include "picohttpparser.h"
38 38
39#if __GNUC__ >= 3 39#if __GNUC__ >= 3
40#define likely(x) __builtin_expect(!!(x), 1) 40# define likely(x) __builtin_expect(!!(x), 1)
41#define unlikely(x) __builtin_expect(!!(x), 0) 41# define unlikely(x) __builtin_expect(!!(x), 0)
42#else 42#else
43#define likely(x) (x) 43# define likely(x) (x)
44#define unlikely(x) (x) 44# define unlikely(x) (x)
45#endif 45#endif
46 46
47#ifdef _MSC_VER 47#ifdef _MSC_VER
48#define ALIGNED(n) _declspec(align(n)) 48# define ALIGNED(n) _declspec(align(n))
49#else 49#else
50#define ALIGNED(n) __attribute__((aligned(n))) 50# define ALIGNED(n) __attribute__((aligned(n)))
51#endif 51#endif
52 52
53#define IS_PRINTABLE_ASCII(c) ((unsigned char)(c)-040u < 0137u) 53#define IS_PRINTABLE_ASCII(c) ((unsigned char)(c)-040u < 0137u)
54 54
55#define CHECK_EOF() \ 55#define CHECK_EOF() \
56 if (buf == buf_end) { \ 56 if (buf == buf_end) { \
57 *ret = -2; \ 57 *ret = -2; \
58 return NULL; \ 58 return NULL; \
59 } 59 }
60 60
61#define EXPECT_CHAR_NO_CHECK(ch) \ 61#define EXPECT_CHAR_NO_CHECK(ch) \
62 if (*buf++ != ch) { \ 62 if (*buf++ != ch) { \
63 *ret = -1; \ 63 *ret = -1; \
64 return NULL; \ 64 return NULL; \
65 } 65 }
66 66
67#define EXPECT_CHAR(ch) \ 67#define EXPECT_CHAR(ch) \
68 CHECK_EOF(); \ 68 CHECK_EOF(); \
69 EXPECT_CHAR_NO_CHECK(ch); 69 EXPECT_CHAR_NO_CHECK(ch);
70 70
71#define ADVANCE_TOKEN(tok, toklen) \ 71#define ADVANCE_TOKEN(tok, toklen) \
72 do { \ 72 do { \
73 const char *tok_start = buf; \ 73 const char *tok_start = buf; \
74 static const char ALIGNED(16) ranges2[16] = "\000\040\177\177"; \ 74 static const char ALIGNED(16) ranges2[16] = "\000\040\177\177"; \
75 int found2; \ 75 int found2; \
76 buf = findchar_fast(buf, buf_end, ranges2, 4, &found2); \ 76 buf = findchar_fast(buf, buf_end, ranges2, 4, &found2); \
77 if (!found2) { \ 77 if (!found2) { \
78 CHECK_EOF(); \ 78 CHECK_EOF(); \
79 } \ 79 } \
80 while (1) { \ 80 while (1) { \
81 if (*buf == ' ') { \ 81 if (*buf == ' ') { \
82 break; \ 82 break; \
83 } else if (unlikely(!IS_PRINTABLE_ASCII(*buf))) { \ 83 } else if (unlikely(!IS_PRINTABLE_ASCII(*buf))) { \
84 if ((unsigned char)*buf < '\040' || *buf == '\177') { \ 84 if ((unsigned char)*buf < '\040' || *buf == '\177') { \
85 *ret = -1; \ 85 *ret = -1; \
86 return NULL; \ 86 return NULL; \
87 } \ 87 } \
88 } \ 88 } \
89 ++buf; \ 89 ++buf; \
90 CHECK_EOF(); \ 90 CHECK_EOF(); \
91 } \ 91 } \
92 tok = tok_start; \ 92 tok = tok_start; \
93 toklen = buf - tok_start; \ 93 toklen = buf - tok_start; \
94 } while (0) 94 } while (0)
95 95
96static const char *token_char_map = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" 96static const char *token_char_map = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
97 "\0\1\0\1\1\1\1\1\0\0\1\1\0\1\1\0\1\1\1\1\1\1\1\1\1\1\0\0\0\0\0\0" 97 "\0\1\0\1\1\1\1\1\0\0\1\1\0\1\1\0\1\1\1\1\1\1\1\1\1\1\0\0\0\0\0\0"
98 "\0\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\0\0\0\1\1" 98 "\0\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\0\0\0\1\1"
99 "\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\0\1\0\1\0" 99 "\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\0\1\0\1\0"
100 "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" 100 "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
101 "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" 101 "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
102 "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" 102 "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
103 "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; 103 "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
104 104
105static const char *findchar_fast(const char *buf, const char *buf_end, const char *ranges, size_t ranges_size, int *found) 105static const char *findchar_fast(const char *buf, const char *buf_end, const char *ranges, size_t ranges_size, int *found) {
106{ 106 *found = 0;
107 *found = 0;
108#if __SSE4_2__ 107#if __SSE4_2__
109 if (likely(buf_end - buf >= 16)) { 108 if (likely(buf_end - buf >= 16)) {
110 __m128i ranges16 = _mm_loadu_si128((const __m128i *)ranges); 109 __m128i ranges16 = _mm_loadu_si128((const __m128i *)ranges);
111 110
112 size_t left = (buf_end - buf) & ~15; 111 size_t left = (buf_end - buf) & ~15;
113 do { 112 do {
114 __m128i b16 = _mm_loadu_si128((const __m128i *)buf); 113 __m128i b16 = _mm_loadu_si128((const __m128i *)buf);
115 int r = _mm_cmpestri(ranges16, ranges_size, b16, 16, _SIDD_LEAST_SIGNIFICANT | _SIDD_CMP_RANGES | _SIDD_UBYTE_OPS); 114 int r = _mm_cmpestri(ranges16, ranges_size, b16, 16, _SIDD_LEAST_SIGNIFICANT | _SIDD_CMP_RANGES | _SIDD_UBYTE_OPS);
116 if (unlikely(r != 16)) { 115 if (unlikely(r != 16)) {
117 buf += r; 116 buf += r;
118 *found = 1; 117 *found = 1;
119 break; 118 break;
120 } 119 }
121 buf += 16; 120 buf += 16;
122 left -= 16; 121 left -= 16;
123 } while (likely(left != 0)); 122 } while (likely(left != 0));
124 } 123 }
125#else 124#else
126 /* suppress unused parameter warning */ 125 /* suppress unused parameter warning */
127 (void)buf_end; 126 (void)buf_end;
128 (void)ranges; 127 (void)ranges;
129 (void)ranges_size; 128 (void)ranges_size;
130#endif 129#endif
131 return buf; 130 return buf;
132} 131}
133 132
134static const char *get_token_to_eol(const char *buf, const char *buf_end, const char **token, size_t *token_len, int *ret) 133static const char *get_token_to_eol(const char *buf, const char *buf_end, const char **token, size_t *token_len, int *ret) {
135{ 134 const char *token_start = buf;
136 const char *token_start = buf;
137 135
138#ifdef __SSE4_2__ 136#ifdef __SSE4_2__
139 static const char ALIGNED(16) ranges1[16] = "\0\010" /* allow HT */ 137 static const char ALIGNED(16) ranges1[16] = "\0\010" /* allow HT */
140 "\012\037" /* allow SP and up to but not including DEL */ 138 "\012\037" /* allow SP and up to but not including DEL */
141 "\177\177"; /* allow chars w. MSB set */ 139 "\177\177"; /* allow chars w. MSB set */
142 int found; 140 int found;
143 buf = findchar_fast(buf, buf_end, ranges1, 6, &found); 141 buf = findchar_fast(buf, buf_end, ranges1, 6, &found);
144 if (found) 142 if (found)
145 goto FOUND_CTL; 143 goto FOUND_CTL;
146#else 144#else
147 /* find non-printable char within the next 8 bytes, this is the hottest code; manually inlined */ 145 /* find non-printable char within the next 8 bytes, this is the hottest code; manually inlined */
148 while (likely(buf_end - buf >= 8)) { 146 while (likely(buf_end - buf >= 8)) {
149#define DOIT() \ 147# define DOIT() \
150 do { \ 148 do { \
151 if (unlikely(!IS_PRINTABLE_ASCII(*buf))) \ 149 if (unlikely(!IS_PRINTABLE_ASCII(*buf))) \
152 goto NonPrintable; \ 150 goto NonPrintable; \
153 ++buf; \ 151 ++buf; \
154 } while (0) 152 } while (0)
155 DOIT(); 153 DOIT();
156 DOIT(); 154 DOIT();
157 DOIT(); 155 DOIT();
158 DOIT(); 156 DOIT();
159 DOIT(); 157 DOIT();
160 DOIT(); 158 DOIT();
161 DOIT(); 159 DOIT();
162 DOIT(); 160 DOIT();
163#undef DOIT 161# undef DOIT
164 continue; 162 continue;
165 NonPrintable: 163 NonPrintable:
166 if ((likely((unsigned char)*buf < '\040') && likely(*buf != '\011')) || unlikely(*buf == '\177')) { 164 if ((likely((unsigned char)*buf < '\040') && likely(*buf != '\011')) || unlikely(*buf == '\177')) {
167 goto FOUND_CTL; 165 goto FOUND_CTL;
168 } 166 }
169 ++buf; 167 ++buf;
170 } 168 }
171#endif 169#endif
172 for (;; ++buf) { 170 for (;; ++buf) {
173 CHECK_EOF(); 171 CHECK_EOF();
174 if (unlikely(!IS_PRINTABLE_ASCII(*buf))) { 172 if (unlikely(!IS_PRINTABLE_ASCII(*buf))) {
175 if ((likely((unsigned char)*buf < '\040') && likely(*buf != '\011')) || unlikely(*buf == '\177')) { 173 if ((likely((unsigned char)*buf < '\040') && likely(*buf != '\011')) || unlikely(*buf == '\177')) {
176 goto FOUND_CTL; 174 goto FOUND_CTL;
177 } 175 }
178 } 176 }
179 } 177 }
180FOUND_CTL: 178FOUND_CTL:
181 if (likely(*buf == '\015')) { 179 if (likely(*buf == '\015')) {
182 ++buf; 180 ++buf;
183 EXPECT_CHAR('\012'); 181 EXPECT_CHAR('\012');
184 *token_len = buf - 2 - token_start; 182 *token_len = buf - 2 - token_start;
185 } else if (*buf == '\012') { 183 } else if (*buf == '\012') {
186 *token_len = buf - token_start; 184 *token_len = buf - token_start;
187 ++buf; 185 ++buf;
188 } else { 186 } else {
189 *ret = -1; 187 *ret = -1;
190 return NULL; 188 return NULL;
191 } 189 }
192 *token = token_start; 190 *token = token_start;
193 191
194 return buf; 192 return buf;
195} 193}
196 194
197static const char *is_complete(const char *buf, const char *buf_end, size_t last_len, int *ret) 195static const char *is_complete(const char *buf, const char *buf_end, size_t last_len, int *ret) {
198{ 196 int ret_cnt = 0;
199 int ret_cnt = 0; 197 buf = last_len < 3 ? buf : buf + last_len - 3;
200 buf = last_len < 3 ? buf : buf + last_len - 3; 198
201 199 while (1) {
202 while (1) { 200 CHECK_EOF();
203 CHECK_EOF(); 201 if (*buf == '\015') {
204 if (*buf == '\015') { 202 ++buf;
205 ++buf; 203 CHECK_EOF();
206 CHECK_EOF(); 204 EXPECT_CHAR('\012');
207 EXPECT_CHAR('\012'); 205 ++ret_cnt;
208 ++ret_cnt; 206 } else if (*buf == '\012') {
209 } else if (*buf == '\012') { 207 ++buf;
210 ++buf; 208 ++ret_cnt;
211 ++ret_cnt; 209 } else {
212 } else { 210 ++buf;
213 ++buf; 211 ret_cnt = 0;
214 ret_cnt = 0; 212 }
215 } 213 if (ret_cnt == 2) {
216 if (ret_cnt == 2) { 214 return buf;
217 return buf; 215 }
218 } 216 }
219 } 217
220 218 *ret = -2;
221 *ret = -2; 219 return NULL;
222 return NULL;
223} 220}
224 221
225#define PARSE_INT(valp_, mul_) \ 222#define PARSE_INT(valp_, mul_) \
226 if (*buf < '0' || '9' < *buf) { \ 223 if (*buf < '0' || '9' < *buf) { \
227 buf++; \ 224 buf++; \
228 *ret = -1; \ 225 *ret = -1; \
229 return NULL; \ 226 return NULL; \
230 } \ 227 } \
231 *(valp_) = (mul_) * (*buf++ - '0'); 228 *(valp_) = (mul_) * (*buf++ - '0');
232 229
233#define PARSE_INT_3(valp_) \ 230#define PARSE_INT_3(valp_) \
234 do { \ 231 do { \
235 int res_ = 0; \ 232 int res_ = 0; \
236 PARSE_INT(&res_, 100) \ 233 PARSE_INT(&res_, 100) \
237 *valp_ = res_; \ 234 *valp_ = res_; \
238 PARSE_INT(&res_, 10) \ 235 PARSE_INT(&res_, 10) \
239 *valp_ += res_; \ 236 *valp_ += res_; \
240 PARSE_INT(&res_, 1) \ 237 PARSE_INT(&res_, 1) \
241 *valp_ += res_; \ 238 *valp_ += res_; \
242 } while (0) 239 } while (0)
243 240
244/* returned pointer is always within [buf, buf_end), or null */ 241/* returned pointer is always within [buf, buf_end), or null */
245static const char *parse_http_version(const char *buf, const char *buf_end, int *major_version, int *minor_version, int *ret) 242static const char *parse_http_version(const char *buf, const char *buf_end, int *major_version, int *minor_version, int *ret) {
246{ 243 /* we want at least [HTTP/1.<two chars>] to try to parse */
247 /* we want at least [HTTP/1.<two chars>] to try to parse */ 244 if (buf_end - buf < 9) {
248 if (buf_end - buf < 9) { 245 *ret = -2;
249 *ret = -2; 246 return NULL;
250 return NULL; 247 }
251 } 248 EXPECT_CHAR_NO_CHECK('H');
252 EXPECT_CHAR_NO_CHECK('H'); 249 EXPECT_CHAR_NO_CHECK('T');
253 EXPECT_CHAR_NO_CHECK('T'); 250 EXPECT_CHAR_NO_CHECK('T');
254 EXPECT_CHAR_NO_CHECK('T'); 251 EXPECT_CHAR_NO_CHECK('P');
255 EXPECT_CHAR_NO_CHECK('P'); 252 EXPECT_CHAR_NO_CHECK('/');
256 EXPECT_CHAR_NO_CHECK('/'); 253 PARSE_INT(major_version, 1);
257 PARSE_INT(major_version, 1); 254 if (*major_version == 1) {
258 if (*major_version == 1) { 255 EXPECT_CHAR_NO_CHECK('.');
259 EXPECT_CHAR_NO_CHECK('.'); 256 PARSE_INT(minor_version, 1);
260 PARSE_INT(minor_version, 1); 257 } else {
261 } else { 258 *minor_version = 0;
262 *minor_version = 0; 259 }
263 } 260 return buf;
264 return buf;
265} 261}
266 262
267static const char *parse_headers(const char *buf, const char *buf_end, struct phr_header *headers, size_t *num_headers, 263static const char *parse_headers(const char *buf, const char *buf_end, struct phr_header *headers, size_t *num_headers, size_t max_headers,
268 size_t max_headers, int *ret) 264 int *ret) {
269{ 265 for (;; ++*num_headers) {
270 for (;; ++*num_headers) { 266 CHECK_EOF();
271 CHECK_EOF(); 267 if (*buf == '\015') {
272 if (*buf == '\015') { 268 ++buf;
273 ++buf; 269 EXPECT_CHAR('\012');
274 EXPECT_CHAR('\012'); 270 break;
275 break; 271 } else if (*buf == '\012') {
276 } else if (*buf == '\012') { 272 ++buf;
277 ++buf; 273 break;
278 break; 274 }
279 } 275 if (*num_headers == max_headers) {
280 if (*num_headers == max_headers) { 276 *ret = -1;
281 *ret = -1; 277 return NULL;
282 return NULL; 278 }
283 } 279 if (!(*num_headers != 0 && (*buf == ' ' || *buf == '\t'))) {
284 if (!(*num_headers != 0 && (*buf == ' ' || *buf == '\t'))) { 280 /* parsing name, but do not discard SP before colon, see
285 /* parsing name, but do not discard SP before colon, see 281 * http://www.mozilla.org/security/announce/2006/mfsa2006-33.html */
286 * http://www.mozilla.org/security/announce/2006/mfsa2006-33.html */ 282 headers[*num_headers].name = buf;
287 headers[*num_headers].name = buf; 283 static const char ALIGNED(16) ranges1[] = "\x00 " /* control chars and up to SP */
288 static const char ALIGNED(16) ranges1[] = "\x00 " /* control chars and up to SP */ 284 "\"\"" /* 0x22 */
289 "\"\"" /* 0x22 */ 285 "()" /* 0x28,0x29 */
290 "()" /* 0x28,0x29 */ 286 ",," /* 0x2c */
291 ",," /* 0x2c */ 287 "//" /* 0x2f */
292 "//" /* 0x2f */ 288 ":@" /* 0x3a-0x40 */
293 ":@" /* 0x3a-0x40 */ 289 "[]" /* 0x5b-0x5d */
294 "[]" /* 0x5b-0x5d */ 290 "{\377"; /* 0x7b-0xff */
295 "{\377"; /* 0x7b-0xff */ 291 int found;
296 int found; 292 buf = findchar_fast(buf, buf_end, ranges1, sizeof(ranges1) - 1, &found);
297 buf = findchar_fast(buf, buf_end, ranges1, sizeof(ranges1) - 1, &found); 293 if (!found) {
298 if (!found) { 294 CHECK_EOF();
299 CHECK_EOF(); 295 }
300 } 296 while (1) {
301 while (1) { 297 if (*buf == ':') {
302 if (*buf == ':') { 298 break;
303 break; 299 } else if (!token_char_map[(unsigned char)*buf]) {
304 } else if (!token_char_map[(unsigned char)*buf]) { 300 *ret = -1;
305 *ret = -1; 301 return NULL;
306 return NULL; 302 }
307 } 303 ++buf;
308 ++buf; 304 CHECK_EOF();
309 CHECK_EOF(); 305 }
310 } 306 if ((headers[*num_headers].name_len = buf - headers[*num_headers].name) == 0) {
311 if ((headers[*num_headers].name_len = buf - headers[*num_headers].name) == 0) { 307 *ret = -1;
312 *ret = -1; 308 return NULL;
313 return NULL; 309 }
314 } 310 ++buf;
315 ++buf; 311 for (;; ++buf) {
316 for (;; ++buf) { 312 CHECK_EOF();
317 CHECK_EOF(); 313 if (!(*buf == ' ' || *buf == '\t')) {
318 if (!(*buf == ' ' || *buf == '\t')) { 314 break;
319 break; 315 }
320 } 316 }
321 } 317 } else {
322 } else { 318 headers[*num_headers].name = NULL;
323 headers[*num_headers].name = NULL; 319 headers[*num_headers].name_len = 0;
324 headers[*num_headers].name_len = 0; 320 }
325 } 321 const char *value;
326 const char *value; 322 size_t value_len;
327 size_t value_len; 323 if ((buf = get_token_to_eol(buf, buf_end, &value, &value_len, ret)) == NULL) {
328 if ((buf = get_token_to_eol(buf, buf_end, &value, &value_len, ret)) == NULL) { 324 return NULL;
329 return NULL; 325 }
330 } 326 /* remove trailing SPs and HTABs */
331 /* remove trailing SPs and HTABs */ 327 const char *value_end = value + value_len;
332 const char *value_end = value + value_len; 328 for (; value_end != value; --value_end) {
333 for (; value_end != value; --value_end) { 329 const char c = *(value_end - 1);
334 const char c = *(value_end - 1); 330 if (!(c == ' ' || c == '\t')) {
335 if (!(c == ' ' || c == '\t')) { 331 break;
336 break; 332 }
337 } 333 }
338 } 334 headers[*num_headers].value = value;
339 headers[*num_headers].value = value; 335 headers[*num_headers].value_len = value_end - value;
340 headers[*num_headers].value_len = value_end - value; 336 }
341 } 337 return buf;
342 return buf;
343} 338}
344 339
345static const char *parse_request(const char *buf, const char *buf_end, const char **method, size_t *method_len, const char **path, 340static const char *parse_request(const char *buf, const char *buf_end, const char **method, size_t *method_len, const char **path,
346 size_t *path_len, int *major_version, int *minor_version, struct phr_header *headers, size_t *num_headers, 341 size_t *path_len, int *major_version, int *minor_version, struct phr_header *headers, size_t *num_headers,
347 size_t max_headers, int *ret) 342 size_t max_headers, int *ret) {
348{ 343 /* skip first empty line (some clients add CRLF after POST content) */
349 /* skip first empty line (some clients add CRLF after POST content) */ 344 CHECK_EOF();
350 CHECK_EOF(); 345 if (*buf == '\015') {
351 if (*buf == '\015') { 346 ++buf;
352 ++buf; 347 EXPECT_CHAR('\012');
353 EXPECT_CHAR('\012'); 348 } else if (*buf == '\012') {
354 } else if (*buf == '\012') { 349 ++buf;
355 ++buf; 350 }
356 } 351
357 352 /* parse request line */
358 /* parse request line */ 353 ADVANCE_TOKEN(*method, *method_len);
359 ADVANCE_TOKEN(*method, *method_len); 354 do {
360 do { 355 ++buf;
361 ++buf; 356 } while (*buf == ' ');
362 } while (*buf == ' '); 357 ADVANCE_TOKEN(*path, *path_len);
363 ADVANCE_TOKEN(*path, *path_len); 358 do {
364 do { 359 ++buf;
365 ++buf; 360 } while (*buf == ' ');
366 } while (*buf == ' '); 361 if (*method_len == 0 || *path_len == 0) {
367 if (*method_len == 0 || *path_len == 0) { 362 *ret = -1;
368 *ret = -1; 363 return NULL;
369 return NULL; 364 }
370 } 365 if ((buf = parse_http_version(buf, buf_end, major_version, minor_version, ret)) == NULL) {
371 if ((buf = parse_http_version(buf, buf_end, major_version, minor_version, ret)) == NULL) { 366 return NULL;
372 return NULL; 367 }
373 } 368 if (*buf == '\015') {
374 if (*buf == '\015') { 369 ++buf;
375 ++buf; 370 EXPECT_CHAR('\012');
376 EXPECT_CHAR('\012'); 371 } else if (*buf == '\012') {
377 } else if (*buf == '\012') { 372 ++buf;
378 ++buf; 373 } else {
379 } else { 374 *ret = -1;
380 *ret = -1; 375 return NULL;
381 return NULL; 376 }
382 } 377
383 378 return parse_headers(buf, buf_end, headers, num_headers, max_headers, ret);
384 return parse_headers(buf, buf_end, headers, num_headers, max_headers, ret);
385} 379}
386 380
387int phr_parse_request(const char *buf_start, size_t len, const char **method, size_t *method_len, const char **path, 381int phr_parse_request(const char *buf_start, size_t len, const char **method, size_t *method_len, const char **path, size_t *path_len,
388 size_t *path_len, int *major_version, int *minor_version, struct phr_header *headers, size_t *num_headers, size_t last_len) 382 int *major_version, int *minor_version, struct phr_header *headers, size_t *num_headers, size_t last_len) {
389{ 383 const char *buf = buf_start, *buf_end = buf_start + len;
390 const char *buf = buf_start, *buf_end = buf_start + len; 384 size_t max_headers = *num_headers;
391 size_t max_headers = *num_headers; 385 int r;
392 int r; 386
393 387 *method = NULL;
394 *method = NULL; 388 *method_len = 0;
395 *method_len = 0; 389 *path = NULL;
396 *path = NULL; 390 *path_len = 0;
397 *path_len = 0; 391 *major_version = -1;
398 *major_version = -1; 392 *minor_version = -1;
399 *minor_version = -1; 393 *num_headers = 0;
400 *num_headers = 0; 394
401 395 /* if last_len != 0, check if the request is complete (a fast countermeasure
402 /* if last_len != 0, check if the request is complete (a fast countermeasure 396 against slowloris */
403 against slowloris */ 397 if (last_len != 0 && is_complete(buf, buf_end, last_len, &r) == NULL) {
404 if (last_len != 0 && is_complete(buf, buf_end, last_len, &r) == NULL) { 398 return r;
405 return r; 399 }
406 } 400
407 401 if ((buf = parse_request(buf, buf_end, method, method_len, path, path_len, major_version, minor_version, headers, num_headers,
408 if ((buf = parse_request(buf, buf_end, method, method_len, path, path_len, major_version, minor_version, headers, num_headers, max_headers, 402 max_headers, &r)) == NULL) {
409 &r)) == NULL) { 403 return r;
410 return r; 404 }
411 } 405
412 406 return (int)(buf - buf_start);
413 return (int)(buf - buf_start);
414} 407}
415 408
416static const char *parse_response(const char *buf, const char *buf_end, int *major_version, int *minor_version, int *status, const char **msg, 409static const char *parse_response(const char *buf, const char *buf_end, int *major_version, int *minor_version, int *status,
417 size_t *msg_len, struct phr_header *headers, size_t *num_headers, size_t max_headers, int *ret) 410 const char **msg, size_t *msg_len, struct phr_header *headers, size_t *num_headers, size_t max_headers,
418{ 411 int *ret) {
419 /* parse "HTTP/1.x" */ 412 /* parse "HTTP/1.x" */
420 if ((buf = parse_http_version(buf, buf_end, major_version, minor_version, ret)) == NULL) { 413 if ((buf = parse_http_version(buf, buf_end, major_version, minor_version, ret)) == NULL) {
421 return NULL; 414 return NULL;
422 } 415 }
423 /* skip space */ 416 /* skip space */
424 if (*buf != ' ') { 417 if (*buf != ' ') {
425 *ret = -1; 418 *ret = -1;
426 return NULL; 419 return NULL;
427 } 420 }
428 do { 421 do {
429 ++buf; 422 ++buf;
430 } while (*buf == ' '); 423 } while (*buf == ' ');
431 /* parse status code, we want at least [:digit:][:digit:][:digit:]<other char> to try to parse */ 424 /* parse status code, we want at least [:digit:][:digit:][:digit:]<other char> to try to parse */
432 if (buf_end - buf < 4) { 425 if (buf_end - buf < 4) {
433 *ret = -2; 426 *ret = -2;
434 return NULL; 427 return NULL;
435 } 428 }
436 PARSE_INT_3(status); 429 PARSE_INT_3(status);
437 430
438 /* get message including preceding space */ 431 /* get message including preceding space */
439 if ((buf = get_token_to_eol(buf, buf_end, msg, msg_len, ret)) == NULL) { 432 if ((buf = get_token_to_eol(buf, buf_end, msg, msg_len, ret)) == NULL) {
440 return NULL; 433 return NULL;
441 } 434 }
442 if (*msg_len == 0) { 435 if (*msg_len == 0) {
443 /* ok */ 436 /* ok */
444 } else if (**msg == ' ') { 437 } else if (**msg == ' ') {
445 /* remove preceding space */ 438 /* remove preceding space */
446 do { 439 do {
447 ++*msg; 440 ++*msg;
448 --*msg_len; 441 --*msg_len;
449 } while (**msg == ' '); 442 } while (**msg == ' ');
450 } else { 443 } else {
451 /* garbage found after status code */ 444 /* garbage found after status code */
452 *ret = -1; 445 *ret = -1;
453 return NULL; 446 return NULL;
454 } 447 }
455 448
456 return parse_headers(buf, buf_end, headers, num_headers, max_headers, ret); 449 return parse_headers(buf, buf_end, headers, num_headers, max_headers, ret);
457} 450}
458 451
459int phr_parse_response(const char *buf_start, size_t len, int *major_version, int *minor_version, int *status, const char **msg, size_t *msg_len, 452int phr_parse_response(const char *buf_start, size_t len, int *major_version, int *minor_version, int *status, const char **msg,
460 struct phr_header *headers, size_t *num_headers, size_t last_len) 453 size_t *msg_len, struct phr_header *headers, size_t *num_headers, size_t last_len) {
461{ 454 const char *buf = buf_start, *buf_end = buf + len;
462 const char *buf = buf_start, *buf_end = buf + len; 455 size_t max_headers = *num_headers;
463 size_t max_headers = *num_headers; 456 int r;
464 int r; 457
465 458 *major_version = -1;
466 *major_version = -1; 459 *minor_version = -1;
467 *minor_version = -1; 460 *status = 0;
468 *status = 0; 461 *msg = NULL;
469 *msg = NULL; 462 *msg_len = 0;
470 *msg_len = 0; 463 *num_headers = 0;
471 *num_headers = 0; 464
472 465 /* if last_len != 0, check if the response is complete (a fast countermeasure
473 /* if last_len != 0, check if the response is complete (a fast countermeasure 466 against slowloris */
474 against slowloris */ 467 if (last_len != 0 && is_complete(buf, buf_end, last_len, &r) == NULL) {
475 if (last_len != 0 && is_complete(buf, buf_end, last_len, &r) == NULL) { 468 return r;
476 return r; 469 }
477 } 470
478 471 if ((buf = parse_response(buf, buf_end, major_version, minor_version, status, msg, msg_len, headers, num_headers, max_headers, &r)) ==
479 if ((buf = parse_response(buf, buf_end, major_version, minor_version, status, msg, msg_len, headers, num_headers, max_headers, &r)) == NULL) { 472 NULL) {
480 return r; 473 return r;
481 } 474 }
482 475
483 return (int)(buf - buf_start); 476 return (int)(buf - buf_start);
484} 477}
485 478
486int phr_parse_headers(const char *buf_start, size_t len, struct phr_header *headers, size_t *num_headers, size_t last_len) 479int phr_parse_headers(const char *buf_start, size_t len, struct phr_header *headers, size_t *num_headers, size_t last_len) {
487{ 480 const char *buf = buf_start, *buf_end = buf + len;
488 const char *buf = buf_start, *buf_end = buf + len; 481 size_t max_headers = *num_headers;
489 size_t max_headers = *num_headers; 482 int r;
490 int r;
491 483
492 *num_headers = 0; 484 *num_headers = 0;
493 485
494 /* if last_len != 0, check if the response is complete (a fast countermeasure 486 /* if last_len != 0, check if the response is complete (a fast countermeasure
495 against slowloris */ 487 against slowloris */
496 if (last_len != 0 && is_complete(buf, buf_end, last_len, &r) == NULL) { 488 if (last_len != 0 && is_complete(buf, buf_end, last_len, &r) == NULL) {
497 return r; 489 return r;
498 } 490 }
499 491
500 if ((buf = parse_headers(buf, buf_end, headers, num_headers, max_headers, &r)) == NULL) { 492 if ((buf = parse_headers(buf, buf_end, headers, num_headers, max_headers, &r)) == NULL) {
501 return r; 493 return r;
502 } 494 }
503 495
504 return (int)(buf - buf_start); 496 return (int)(buf - buf_start);
505} 497}
506 498
507enum { 499enum {
508 CHUNKED_IN_CHUNK_SIZE, 500 CHUNKED_IN_CHUNK_SIZE,
509 CHUNKED_IN_CHUNK_EXT, 501 CHUNKED_IN_CHUNK_EXT,
510 CHUNKED_IN_CHUNK_DATA, 502 CHUNKED_IN_CHUNK_DATA,
511 CHUNKED_IN_CHUNK_CRLF, 503 CHUNKED_IN_CHUNK_CRLF,
512 CHUNKED_IN_TRAILERS_LINE_HEAD, 504 CHUNKED_IN_TRAILERS_LINE_HEAD,
513 CHUNKED_IN_TRAILERS_LINE_MIDDLE 505 CHUNKED_IN_TRAILERS_LINE_MIDDLE
514}; 506};
515 507
516static int decode_hex(int ch) 508static int decode_hex(int ch) {
517{ 509 if ('0' <= ch && ch <= '9') {
518 if ('0' <= ch && ch <= '9') { 510 return ch - '0';
519 return ch - '0'; 511 } else if ('A' <= ch && ch <= 'F') {
520 } else if ('A' <= ch && ch <= 'F') { 512 return ch - 'A' + 0xa;
521 return ch - 'A' + 0xa; 513 } else if ('a' <= ch && ch <= 'f') {
522 } else if ('a' <= ch && ch <= 'f') { 514 return ch - 'a' + 0xa;
523 return ch - 'a' + 0xa; 515 } else {
524 } else { 516 return -1;
525 return -1; 517 }
526 }
527} 518}
528 519
529ssize_t phr_decode_chunked(struct phr_chunked_decoder *decoder, char *buf, size_t *_bufsz) 520ssize_t phr_decode_chunked(struct phr_chunked_decoder *decoder, char *buf, size_t *_bufsz) {
530{ 521 size_t dst = 0, src = 0, bufsz = *_bufsz;
531 size_t dst = 0, src = 0, bufsz = *_bufsz; 522 ssize_t ret = -2; /* incomplete */
532 ssize_t ret = -2; /* incomplete */ 523
533 524 while (1) {
534 while (1) { 525 switch (decoder->_state) {
535 switch (decoder->_state) { 526 case CHUNKED_IN_CHUNK_SIZE:
536 case CHUNKED_IN_CHUNK_SIZE: 527 for (;; ++src) {
537 for (;; ++src) { 528 int v;
538 int v; 529 if (src == bufsz)
539 if (src == bufsz) 530 goto Exit;
540 goto Exit; 531 if ((v = decode_hex(buf[src])) == -1) {
541 if ((v = decode_hex(buf[src])) == -1) { 532 if (decoder->_hex_count == 0) {
542 if (decoder->_hex_count == 0) { 533 ret = -1;
543 ret = -1; 534 goto Exit;
544 goto Exit; 535 }
545 } 536 break;
546 break; 537 }
547 } 538 if (decoder->_hex_count == sizeof(size_t) * 2) {
548 if (decoder->_hex_count == sizeof(size_t) * 2) { 539 ret = -1;
549 ret = -1; 540 goto Exit;
550 goto Exit; 541 }
551 } 542 decoder->bytes_left_in_chunk = decoder->bytes_left_in_chunk * 16 + v;
552 decoder->bytes_left_in_chunk = decoder->bytes_left_in_chunk * 16 + v; 543 ++decoder->_hex_count;
553 ++decoder->_hex_count; 544 }
554 } 545 decoder->_hex_count = 0;
555 decoder->_hex_count = 0; 546 decoder->_state = CHUNKED_IN_CHUNK_EXT;
556 decoder->_state = CHUNKED_IN_CHUNK_EXT; 547 /* fallthru */
557 /* fallthru */ 548 case CHUNKED_IN_CHUNK_EXT:
558 case CHUNKED_IN_CHUNK_EXT: 549 /* RFC 7230 A.2 "Line folding in chunk extensions is disallowed" */
559 /* RFC 7230 A.2 "Line folding in chunk extensions is disallowed" */ 550 for (;; ++src) {
560 for (;; ++src) { 551 if (src == bufsz)
561 if (src == bufsz) 552 goto Exit;
562 goto Exit; 553 if (buf[src] == '\012')
563 if (buf[src] == '\012') 554 break;
564 break; 555 }
565 } 556 ++src;
566 ++src; 557 if (decoder->bytes_left_in_chunk == 0) {
567 if (decoder->bytes_left_in_chunk == 0) { 558 if (decoder->consume_trailer) {
568 if (decoder->consume_trailer) { 559 decoder->_state = CHUNKED_IN_TRAILERS_LINE_HEAD;
569 decoder->_state = CHUNKED_IN_TRAILERS_LINE_HEAD; 560 break;
570 break; 561 } else {
571 } else { 562 goto Complete;
572 goto Complete; 563 }
573 } 564 }
574 } 565 decoder->_state = CHUNKED_IN_CHUNK_DATA;
575 decoder->_state = CHUNKED_IN_CHUNK_DATA; 566 /* fallthru */
576 /* fallthru */ 567 case CHUNKED_IN_CHUNK_DATA: {
577 case CHUNKED_IN_CHUNK_DATA: { 568 size_t avail = bufsz - src;
578 size_t avail = bufsz - src; 569 if (avail < decoder->bytes_left_in_chunk) {
579 if (avail < decoder->bytes_left_in_chunk) { 570 if (dst != src)
580 if (dst != src) 571 memmove(buf + dst, buf + src, avail);
581 memmove(buf + dst, buf + src, avail); 572 src += avail;
582 src += avail; 573 dst += avail;
583 dst += avail; 574 decoder->bytes_left_in_chunk -= avail;
584 decoder->bytes_left_in_chunk -= avail; 575 goto Exit;
585 goto Exit; 576 }
586 } 577 if (dst != src)
587 if (dst != src) 578 memmove(buf + dst, buf + src, decoder->bytes_left_in_chunk);
588 memmove(buf + dst, buf + src, decoder->bytes_left_in_chunk); 579 src += decoder->bytes_left_in_chunk;
589 src += decoder->bytes_left_in_chunk; 580 dst += decoder->bytes_left_in_chunk;
590 dst += decoder->bytes_left_in_chunk; 581 decoder->bytes_left_in_chunk = 0;
591 decoder->bytes_left_in_chunk = 0; 582 decoder->_state = CHUNKED_IN_CHUNK_CRLF;
592 decoder->_state = CHUNKED_IN_CHUNK_CRLF; 583 }
593 } 584 /* fallthru */
594 /* fallthru */ 585 case CHUNKED_IN_CHUNK_CRLF:
595 case CHUNKED_IN_CHUNK_CRLF: 586 for (;; ++src) {
596 for (;; ++src) { 587 if (src == bufsz)
597 if (src == bufsz) 588 goto Exit;
598 goto Exit; 589 if (buf[src] != '\015')
599 if (buf[src] != '\015') 590 break;
600 break; 591 }
601 } 592 if (buf[src] != '\012') {
602 if (buf[src] != '\012') { 593 ret = -1;
603 ret = -1; 594 goto Exit;
604 goto Exit; 595 }
605 } 596 ++src;
606 ++src; 597 decoder->_state = CHUNKED_IN_CHUNK_SIZE;
607 decoder->_state = CHUNKED_IN_CHUNK_SIZE; 598 break;
608 break; 599 case CHUNKED_IN_TRAILERS_LINE_HEAD:
609 case CHUNKED_IN_TRAILERS_LINE_HEAD: 600 for (;; ++src) {
610 for (;; ++src) { 601 if (src == bufsz)
611 if (src == bufsz) 602 goto Exit;
612 goto Exit; 603 if (buf[src] != '\015')
613 if (buf[src] != '\015') 604 break;
614 break; 605 }
615 } 606 if (buf[src++] == '\012')
616 if (buf[src++] == '\012') 607 goto Complete;
617 goto Complete; 608 decoder->_state = CHUNKED_IN_TRAILERS_LINE_MIDDLE;
618 decoder->_state = CHUNKED_IN_TRAILERS_LINE_MIDDLE; 609 /* fallthru */
619 /* fallthru */ 610 case CHUNKED_IN_TRAILERS_LINE_MIDDLE:
620 case CHUNKED_IN_TRAILERS_LINE_MIDDLE: 611 for (;; ++src) {
621 for (;; ++src) { 612 if (src == bufsz)
622 if (src == bufsz) 613 goto Exit;
623 goto Exit; 614 if (buf[src] == '\012')
624 if (buf[src] == '\012') 615 break;
625 break; 616 }
626 } 617 ++src;
627 ++src; 618 decoder->_state = CHUNKED_IN_TRAILERS_LINE_HEAD;
628 decoder->_state = CHUNKED_IN_TRAILERS_LINE_HEAD; 619 break;
629 break; 620 default:
630 default: 621 assert(!"decoder is corrupt");
631 assert(!"decoder is corrupt"); 622 }
632 } 623 }
633 }
634 624
635Complete: 625Complete:
636 ret = bufsz - src; 626 ret = bufsz - src;
637Exit: 627Exit:
638 if (dst != src) 628 if (dst != src)
639 memmove(buf + dst, buf + src, bufsz - src); 629 memmove(buf + dst, buf + src, bufsz - src);
640 *_bufsz = dst; 630 *_bufsz = dst;
641 return ret; 631 return ret;
642} 632}
643 633
644int phr_decode_chunked_is_in_data(struct phr_chunked_decoder *decoder) 634int phr_decode_chunked_is_in_data(struct phr_chunked_decoder *decoder) { return decoder->_state == CHUNKED_IN_CHUNK_DATA; }
645{
646 return decoder->_state == CHUNKED_IN_CHUNK_DATA;
647}
648 635
649#undef CHECK_EOF 636#undef CHECK_EOF
650#undef EXPECT_CHAR 637#undef EXPECT_CHAR
diff --git a/plugins/popen.c b/plugins/popen.c
index 54e63bc5..2b9824bc 100644
--- a/plugins/popen.c
+++ b/plugins/popen.c
@@ -1,42 +1,42 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring Plugins popen 3 * Monitoring Plugins popen
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 2005-2007 Monitoring Plugins Development Team 6 * Copyright (c) 2005-2024 Monitoring Plugins Development Team
7* 7 *
8* Description: 8 * Description:
9* 9 *
10* A safe alternative to popen 10 * A safe alternative to popen
11* 11 *
12* Provides spopen and spclose 12 * Provides spopen and spclose
13* 13 *
14* FILE * spopen(const char *); 14 * FILE * spopen(const char *);
15* int spclose(FILE *); 15 * int spclose(FILE *);
16* 16 *
17* Code taken with little modification from "Advanced Programming for the Unix 17 * Code taken with little modification from "Advanced Programming for the Unix
18* Environment" by W. Richard Stevens 18 * Environment" by W. Richard Stevens
19* 19 *
20* This is considered safe in that no shell is spawned, and the environment 20 * This is considered safe in that no shell is spawned, and the environment
21* and path passed to the exec'd program are essentially empty. (popen create 21 * and path passed to the exec'd program are essentially empty. (popen create
22* a shell and passes the environment to it). 22 * a shell and passes the environment to it).
23* 23 *
24* 24 *
25* This program is free software: you can redistribute it and/or modify 25 * This program is free software: you can redistribute it and/or modify
26* it under the terms of the GNU General Public License as published by 26 * it under the terms of the GNU General Public License as published by
27* the Free Software Foundation, either version 3 of the License, or 27 * the Free Software Foundation, either version 3 of the License, or
28* (at your option) any later version. 28 * (at your option) any later version.
29* 29 *
30* This program is distributed in the hope that it will be useful, 30 * This program is distributed in the hope that it will be useful,
31* but WITHOUT ANY WARRANTY; without even the implied warranty of 31 * but WITHOUT ANY WARRANTY; without even the implied warranty of
32* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 32 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
33* GNU General Public License for more details. 33 * GNU General Public License for more details.
34* 34 *
35* You should have received a copy of the GNU General Public License 35 * You should have received a copy of the GNU General Public License
36* along with this program. If not, see <http://www.gnu.org/licenses/>. 36 * along with this program. If not, see <http://www.gnu.org/licenses/>.
37* 37 *
38* 38 *
39*****************************************************************************/ 39 *****************************************************************************/
40 40
41#include "./common.h" 41#include "./common.h"
42#include "./utils.h" 42#include "./utils.h"
@@ -47,63 +47,52 @@ extern pid_t *childpid;
47extern int *child_stderr_array; 47extern int *child_stderr_array;
48extern FILE *child_process; 48extern FILE *child_process;
49 49
50FILE *spopen (const char *); 50FILE *spopen(const char * /*cmdstring*/);
51int spclose (FILE *); 51int spclose(FILE * /*fp*/);
52#ifdef REDHAT_SPOPEN_ERROR 52#ifdef REDHAT_SPOPEN_ERROR
53void popen_sigchld_handler (int); 53void popen_sigchld_handler(int);
54#endif 54#endif
55void popen_timeout_alarm_handler (int); 55void popen_timeout_alarm_handler(int /*signo*/);
56 56
57#include <stdarg.h> /* ANSI C header file */ 57#include <stdarg.h> /* ANSI C header file */
58#include <fcntl.h> 58#include <fcntl.h>
59 59
60#include <limits.h> 60#include <limits.h>
61#include <sys/resource.h> 61#include <sys/resource.h>
62 62
63#ifdef HAVE_SYS_WAIT_H 63#ifdef HAVE_SYS_WAIT_H
64#include <sys/wait.h> 64# include <sys/wait.h>
65#endif 65#endif
66 66
67#ifndef WEXITSTATUS 67#ifndef WEXITSTATUS
68# define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8) 68# define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
69#endif 69#endif
70 70
71#ifndef WIFEXITED 71#ifndef WIFEXITED
72# define WIFEXITED(stat_val) (((stat_val) & 255) == 0) 72# define WIFEXITED(stat_val) (((stat_val)&255) == 0)
73#endif 73#endif
74 74
75/* 4.3BSD Reno <signal.h> doesn't define SIG_ERR */ 75/* 4.3BSD Reno <signal.h> doesn't define SIG_ERR */
76#if defined(SIG_IGN) && !defined(SIG_ERR) 76#if defined(SIG_IGN) && !defined(SIG_ERR)
77#define SIG_ERR ((Sigfunc *)-1) 77# define SIG_ERR ((Sigfunc *)-1)
78#endif 78#endif
79 79
80 80char *pname = NULL; /* caller can set this from argv[0] */
81char *pname = NULL; /* caller can set this from argv[0] */
82 81
83#ifdef REDHAT_SPOPEN_ERROR 82#ifdef REDHAT_SPOPEN_ERROR
84static volatile int childtermd = 0; 83static volatile int childtermd = 0;
85#endif 84#endif
86 85
87FILE * 86FILE *spopen(const char *cmdstring) {
88spopen (const char *cmdstring) 87#ifdef RLIMIT_CORE
89{
90 char *env[2];
91 char *cmd = NULL;
92 char **argv = NULL;
93 char *str, *tmp;
94 int argc;
95
96 int i = 0, pfd[2], pfderr[2];
97 pid_t pid;
98
99#ifdef RLIMIT_CORE
100 /* do not leave core files */ 88 /* do not leave core files */
101 struct rlimit limit; 89 struct rlimit limit;
102 getrlimit (RLIMIT_CORE, &limit); 90 getrlimit(RLIMIT_CORE, &limit);
103 limit.rlim_cur = 0; 91 limit.rlim_cur = 0;
104 setrlimit (RLIMIT_CORE, &limit); 92 setrlimit(RLIMIT_CORE, &limit);
105#endif 93#endif
106 94
95 char *env[2];
107 env[0] = strdup("LC_ALL=C"); 96 env[0] = strdup("LC_ALL=C");
108 env[1] = NULL; 97 env[1] = NULL;
109 98
@@ -111,184 +100,182 @@ spopen (const char *cmdstring)
111 if (cmdstring == NULL) 100 if (cmdstring == NULL)
112 return (NULL); 101 return (NULL);
113 102
103 char *cmd = NULL;
114 /* make copy of command string so strtok() doesn't silently modify it */ 104 /* make copy of command string so strtok() doesn't silently modify it */
115 /* (the calling program may want to access it later) */ 105 /* (the calling program may want to access it later) */
116 cmd = malloc (strlen (cmdstring) + 1); 106 cmd = malloc(strlen(cmdstring) + 1);
117 if (cmd == NULL) 107 if (cmd == NULL)
118 return NULL; 108 return NULL;
119 strcpy (cmd, cmdstring); 109 strcpy(cmd, cmdstring);
120 110
121 /* This is not a shell, so we don't handle "???" */ 111 /* This is not a shell, so we don't handle "???" */
122 if (strstr (cmdstring, "\"")) 112 if (strstr(cmdstring, "\""))
123 return NULL; 113 return NULL;
124 114
125 /* allow single quotes, but only if non-whitesapce doesn't occur on both sides */ 115 /* allow single quotes, but only if non-whitesapce doesn't occur on both sides */
126 if (strstr (cmdstring, " ' ") || strstr (cmdstring, "'''")) 116 if (strstr(cmdstring, " ' ") || strstr(cmdstring, "'''"))
127 return NULL; 117 return NULL;
128 118
119 int argc;
120 char **argv = NULL;
129 /* there cannot be more args than characters */ 121 /* there cannot be more args than characters */
130 argc = strlen (cmdstring) + 1; /* add 1 for NULL termination */ 122 argc = strlen(cmdstring) + 1; /* add 1 for NULL termination */
131 argv = malloc (sizeof(char*)*argc); 123 argv = malloc(sizeof(char *) * argc);
132 124
133 if (argv == NULL) { 125 if (argv == NULL) {
134 printf ("%s\n", _("Could not malloc argv array in popen()")); 126 printf("%s\n", _("Could not malloc argv array in popen()"));
135 return NULL; 127 return NULL;
136 } 128 }
137 129
130 int i = 0;
131 char *str;
138 /* loop to get arguments to command */ 132 /* loop to get arguments to command */
139 while (cmd) { 133 while (cmd) {
140 str = cmd; 134 str = cmd;
141 str += strspn (str, " \t\r\n"); /* trim any leading whitespace */ 135 str += strspn(str, " \t\r\n"); /* trim any leading whitespace */
142 136
143 if (i >= argc - 2) { 137 if (i >= argc - 2) {
144 printf ("%s\n",_("CRITICAL - You need more args!!!")); 138 printf("%s\n", _("CRITICAL - You need more args!!!"));
145 return (NULL); 139 return (NULL);
146 } 140 }
147 141
148 if (strstr (str, "'") == str) { /* handle SIMPLE quoted strings */ 142 if (strstr(str, "'") == str) { /* handle SIMPLE quoted strings */
149 str++; 143 str++;
150 if (!strstr (str, "'")) 144 if (!strstr(str, "'"))
151 return NULL; /* balanced? */ 145 return NULL; /* balanced? */
152 cmd = 1 + strstr (str, "'"); 146 cmd = 1 + strstr(str, "'");
153 str[strcspn (str, "'")] = 0; 147 str[strcspn(str, "'")] = 0;
154 } 148 } else if (strcspn(str, "'") < strcspn(str, " \t\r\n")) {
155 else if (strcspn(str,"'") < strcspn (str, " \t\r\n")) { 149 /* handle --option='foo bar' strings */
156 /* handle --option='foo bar' strings */ 150 char *tmp = str + strcspn(str, "'") + 1;
157 tmp = str + strcspn(str, "'") + 1; 151 if (!strstr(tmp, "'"))
158 if (!strstr (tmp, "'")) 152 return NULL; /* balanced? */
159 return NULL; /* balanced? */ 153 tmp += strcspn(tmp, "'") + 1;
160 tmp += strcspn(tmp,"'") + 1;
161 *tmp = 0; 154 *tmp = 0;
162 cmd = tmp + 1; 155 cmd = tmp + 1;
163 } else { 156 } else {
164 if (strpbrk (str, " \t\r\n")) { 157 if (strpbrk(str, " \t\r\n")) {
165 cmd = 1 + strpbrk (str, " \t\r\n"); 158 cmd = 1 + strpbrk(str, " \t\r\n");
166 str[strcspn (str, " \t\r\n")] = 0; 159 str[strcspn(str, " \t\r\n")] = 0;
167 } 160 } else {
168 else {
169 cmd = NULL; 161 cmd = NULL;
170 } 162 }
171 } 163 }
172 164
173 if (cmd && strlen (cmd) == strspn (cmd, " \t\r\n")) 165 if (cmd && strlen(cmd) == strspn(cmd, " \t\r\n"))
174 cmd = NULL; 166 cmd = NULL;
175 167
176 argv[i++] = str; 168 argv[i++] = str;
177
178 } 169 }
179 argv[i] = NULL; 170 argv[i] = NULL;
180 171
181 long maxfd = mp_open_max(); 172 long maxfd = mp_open_max();
182 173
183 if (childpid == NULL) { /* first time through */ 174 if (childpid == NULL) { /* first time through */
184 if ((childpid = calloc ((size_t)maxfd, sizeof (pid_t))) == NULL) 175 if ((childpid = calloc((size_t)maxfd, sizeof(pid_t))) == NULL)
185 return (NULL); 176 return (NULL);
186 } 177 }
187 178
188 if (child_stderr_array == NULL) { /* first time through */ 179 if (child_stderr_array == NULL) { /* first time through */
189 if ((child_stderr_array = calloc ((size_t)maxfd, sizeof (int))) == NULL) 180 if ((child_stderr_array = calloc((size_t)maxfd, sizeof(int))) == NULL)
190 return (NULL); 181 return (NULL);
191 } 182 }
192 183
193 if (pipe (pfd) < 0) 184 int pfd[2];
194 return (NULL); /* errno set by pipe() */ 185 if (pipe(pfd) < 0)
186 return (NULL); /* errno set by pipe() */
195 187
196 if (pipe (pfderr) < 0) 188 int pfderr[2];
197 return (NULL); /* errno set by pipe() */ 189 if (pipe(pfderr) < 0)
190 return (NULL); /* errno set by pipe() */
198 191
199#ifdef REDHAT_SPOPEN_ERROR 192#ifdef REDHAT_SPOPEN_ERROR
200 if (signal (SIGCHLD, popen_sigchld_handler) == SIG_ERR) { 193 if (signal(SIGCHLD, popen_sigchld_handler) == SIG_ERR) {
201 usage4 (_("Cannot catch SIGCHLD")); 194 usage4(_("Cannot catch SIGCHLD"));
202 } 195 }
203#endif 196#endif
204 197
205 if ((pid = fork ()) < 0) 198 pid_t pid;
206 return (NULL); /* errno set by fork() */ 199 if ((pid = fork()) < 0)
207 else if (pid == 0) { /* child */ 200 return (NULL); /* errno set by fork() */
208 close (pfd[0]); 201
202 if (pid == 0) { /* child */
203 close(pfd[0]);
209 if (pfd[1] != STDOUT_FILENO) { 204 if (pfd[1] != STDOUT_FILENO) {
210 dup2 (pfd[1], STDOUT_FILENO); 205 dup2(pfd[1], STDOUT_FILENO);
211 close (pfd[1]); 206 close(pfd[1]);
212 } 207 }
213 close (pfderr[0]); 208 close(pfderr[0]);
214 if (pfderr[1] != STDERR_FILENO) { 209 if (pfderr[1] != STDERR_FILENO) {
215 dup2 (pfderr[1], STDERR_FILENO); 210 dup2(pfderr[1], STDERR_FILENO);
216 close (pfderr[1]); 211 close(pfderr[1]);
217 } 212 }
218 /* close all descriptors in childpid[] */ 213 /* close all descriptors in childpid[] */
219 for (i = 0; i < maxfd; i++) 214 for (i = 0; i < maxfd; i++)
220 if (childpid[i] > 0) 215 if (childpid[i] > 0)
221 close (i); 216 close(i);
222 217
223 execve (argv[0], argv, env); 218 execve(argv[0], argv, env);
224 _exit (0); 219 _exit(0);
225 } 220 }
226 221
227 close (pfd[1]); /* parent */ 222 close(pfd[1]); /* parent */
228 if ((child_process = fdopen (pfd[0], "r")) == NULL) 223 if ((child_process = fdopen(pfd[0], "r")) == NULL)
229 return (NULL); 224 return (NULL);
230 close (pfderr[1]); 225 close(pfderr[1]);
231 226
232 childpid[fileno (child_process)] = pid; /* remember child pid for this fd */ 227 childpid[fileno(child_process)] = pid; /* remember child pid for this fd */
233 child_stderr_array[fileno (child_process)] = pfderr[0]; /* remember STDERR */ 228 child_stderr_array[fileno(child_process)] = pfderr[0]; /* remember STDERR */
234 return (child_process); 229 return (child_process);
235} 230}
236 231
237int 232int spclose(FILE *fp) {
238spclose (FILE * fp)
239{
240 int fd, status;
241 pid_t pid;
242
243 if (childpid == NULL) 233 if (childpid == NULL)
244 return (1); /* popen() has never been called */ 234 return (1); /* popen() has never been called */
245 235
246 fd = fileno (fp); 236 pid_t pid;
237 int fd = fileno(fp);
247 if ((pid = childpid[fd]) == 0) 238 if ((pid = childpid[fd]) == 0)
248 return (1); /* fp wasn't opened by popen() */ 239 return (1); /* fp wasn't opened by popen() */
249 240
250 childpid[fd] = 0; 241 childpid[fd] = 0;
251 if (fclose (fp) == EOF) 242 if (fclose(fp) == EOF)
252 return (1); 243 return (1);
253 244
254#ifdef REDHAT_SPOPEN_ERROR 245#ifdef REDHAT_SPOPEN_ERROR
255 while (!childtermd); /* wait until SIGCHLD */ 246 while (!childtermd)
247 ; /* wait until SIGCHLD */
256#endif 248#endif
257 249
258 while (waitpid (pid, &status, 0) < 0) 250 int status;
251 while (waitpid(pid, &status, 0) < 0)
259 if (errno != EINTR) 252 if (errno != EINTR)
260 return (1); /* error other than EINTR from waitpid() */ 253 return (1); /* error other than EINTR from waitpid() */
261 254
262 if (WIFEXITED (status)) 255 if (WIFEXITED(status))
263 return (WEXITSTATUS (status)); /* return child's termination status */ 256 return (WEXITSTATUS(status)); /* return child's termination status */
264 257
265 return (1); 258 return (1);
266} 259}
267 260
268#ifdef REDHAT_SPOPEN_ERROR 261#ifdef REDHAT_SPOPEN_ERROR
269void 262void popen_sigchld_handler(int signo) {
270popen_sigchld_handler (int signo)
271{
272 if (signo == SIGCHLD) 263 if (signo == SIGCHLD)
273 childtermd = 1; 264 childtermd = 1;
274} 265}
275#endif 266#endif
276 267
277void 268void popen_timeout_alarm_handler(int signo) {
278popen_timeout_alarm_handler (int signo)
279{
280 int fh;
281 if (signo == SIGALRM) { 269 if (signo == SIGALRM) {
282 if (child_process != NULL) { 270 if (child_process != NULL) {
283 fh=fileno (child_process); 271 int fh = fileno(child_process);
284 if(fh >= 0){ 272 if (fh >= 0) {
285 kill (childpid[fh], SIGKILL); 273 kill(childpid[fh], SIGKILL);
286 } 274 }
287 printf (_("CRITICAL - Plugin timed out after %d seconds\n"), 275 printf(_("CRITICAL - Plugin timed out after %d seconds\n"), timeout_interval);
288 timeout_interval);
289 } else { 276 } else {
290 printf ("%s\n", _("CRITICAL - popen timeout received, but no child process")); 277 printf("%s\n", _("CRITICAL - popen timeout received, but no child process"));
291 } 278 }
292 exit (STATE_CRITICAL); 279 exit(STATE_CRITICAL);
293 } 280 }
294} 281}
diff --git a/plugins/runcmd.c b/plugins/runcmd.c
index ed49bb99..2e53dc0b 100644
--- a/plugins/runcmd.c
+++ b/plugins/runcmd.c
@@ -1,63 +1,63 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring run command utilities 3 * Monitoring run command utilities
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 2005-2006 Monitoring Plugins Development Team 6 * Copyright (c) 2005-2024 Monitoring Plugins Development Team
7* 7 *
8* Description : 8 * Description :
9* 9 *
10* A simple interface to executing programs from other programs, using an 10 * A simple interface to executing programs from other programs, using an
11* optimized and safe popen()-like implementation. It is considered safe 11 * optimized and safe popen()-like implementation. It is considered safe
12* in that no shell needs to be spawned and the environment passed to the 12 * in that no shell needs to be spawned and the environment passed to the
13* execve()'d program is essentially empty. 13 * execve()'d program is essentially empty.
14* 14 *
15* The code in this file is a derivative of popen.c which in turn was taken 15 * The code in this file is a derivative of popen.c which in turn was taken
16* from "Advanced Programming for the Unix Environment" by W. Richard Stevens. 16 * from "Advanced Programming for the Unix Environment" by W. Richard Stevens.
17* 17 *
18* Care has been taken to make sure the functions are async-safe. The one 18 * Care has been taken to make sure the functions are async-safe. The one
19* function which isn't is np_runcmd_init() which it doesn't make sense to 19 * function which isn't is np_runcmd_init() which it doesn't make sense to
20* call twice anyway, so the api as a whole should be considered async-safe. 20 * call twice anyway, so the api as a whole should be considered async-safe.
21* 21 *
22* 22 *
23* This program is free software: you can redistribute it and/or modify 23 * This program is free software: you can redistribute it and/or modify
24* it under the terms of the GNU General Public License as published by 24 * it under the terms of the GNU General Public License as published by
25* the Free Software Foundation, either version 3 of the License, or 25 * the Free Software Foundation, either version 3 of the License, or
26* (at your option) any later version. 26 * (at your option) any later version.
27* 27 *
28* This program is distributed in the hope that it will be useful, 28 * This program is distributed in the hope that it will be useful,
29* but WITHOUT ANY WARRANTY; without even the implied warranty of 29 * but WITHOUT ANY WARRANTY; without even the implied warranty of
30* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 30 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31* GNU General Public License for more details. 31 * GNU General Public License for more details.
32* 32 *
33* You should have received a copy of the GNU General Public License 33 * You should have received a copy of the GNU General Public License
34* along with this program. If not, see <http://www.gnu.org/licenses/>. 34 * along with this program. If not, see <http://www.gnu.org/licenses/>.
35* 35 *
36* 36 *
37*****************************************************************************/ 37 *****************************************************************************/
38 38
39#define NAGIOSPLUG_API_C 1 39#define NAGIOSPLUG_API_C 1
40 40
41/** includes **/ 41/** includes **/
42#include "runcmd.h" 42#include "runcmd.h"
43#ifdef HAVE_SYS_WAIT_H 43#ifdef HAVE_SYS_WAIT_H
44# include <sys/wait.h> 44# include <sys/wait.h>
45#endif 45#endif
46 46
47#include "./utils.h" 47#include "./utils.h"
48 48
49/** macros **/ 49/** macros **/
50#ifndef WEXITSTATUS 50#ifndef WEXITSTATUS
51# define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8) 51# define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
52#endif 52#endif
53 53
54#ifndef WIFEXITED 54#ifndef WIFEXITED
55# define WIFEXITED(stat_val) (((stat_val) & 255) == 0) 55# define WIFEXITED(stat_val) (((stat_val)&255) == 0)
56#endif 56#endif
57 57
58/* 4.3BSD Reno <signal.h> doesn't define SIG_ERR */ 58/* 4.3BSD Reno <signal.h> doesn't define SIG_ERR */
59#if defined(SIG_IGN) && !defined(SIG_ERR) 59#if defined(SIG_IGN) && !defined(SIG_ERR)
60# define SIG_ERR ((Sigfunc *)-1) 60# define SIG_ERR ((Sigfunc *)-1)
61#endif 61#endif
62 62
63#include "../lib/maxfd.h" 63#include "../lib/maxfd.h"
@@ -72,33 +72,26 @@
72static pid_t *np_pids = NULL; 72static pid_t *np_pids = NULL;
73 73
74/** prototypes **/ 74/** prototypes **/
75static int np_runcmd_open(const char *, int *, int *) 75static int np_runcmd_open(const char *, int *, int *) __attribute__((__nonnull__(1, 2, 3)));
76 __attribute__((__nonnull__(1, 2, 3)));
77 76
78static int np_fetch_output(int, output *, int) 77static int np_fetch_output(int, output *, int) __attribute__((__nonnull__(2)));
79 __attribute__((__nonnull__(2)));
80 78
81static int np_runcmd_close(int); 79static int np_runcmd_close(int);
82 80
83/* prototype imported from utils.h */ 81/* prototype imported from utils.h */
84extern void die (int, const char *, ...) 82extern void die(int, const char *, ...) __attribute__((__noreturn__, __format__(__printf__, 2, 3)));
85 __attribute__((__noreturn__,__format__(__printf__, 2, 3)));
86
87 83
88/* this function is NOT async-safe. It is exported so multithreaded 84/* this function is NOT async-safe. It is exported so multithreaded
89 * plugins (or other apps) can call it prior to running any commands 85 * plugins (or other apps) can call it prior to running any commands
90 * through this api and thus achieve async-safeness throughout the api */ 86 * through this api and thus achieve async-safeness throughout the api */
91void np_runcmd_init(void) 87void np_runcmd_init(void) {
92{ 88 long maxfd = mp_open_max();
93 long maxfd = mp_open_max(); 89 if (!np_pids)
94 if(!np_pids) np_pids = calloc(maxfd, sizeof(pid_t)); 90 np_pids = calloc(maxfd, sizeof(pid_t));
95} 91}
96 92
97
98/* Start running a command */ 93/* Start running a command */
99static int 94static int np_runcmd_open(const char *cmdstring, int *pfd, int *pfderr) {
100np_runcmd_open(const char *cmdstring, int *pfd, int *pfderr)
101{
102 char *env[2]; 95 char *env[2];
103 char *cmd = NULL; 96 char *cmd = NULL;
104 char **argv = NULL; 97 char **argv = NULL;
@@ -112,7 +105,8 @@ np_runcmd_open(const char *cmdstring, int *pfd, int *pfderr)
112 105
113 int i = 0; 106 int i = 0;
114 107
115 if(!np_pids) NP_RUNCMD_INIT; 108 if (!np_pids)
109 NP_RUNCMD_INIT;
116 110
117 env[0] = strdup("LC_ALL=C"); 111 env[0] = strdup("LC_ALL=C");
118 env[1] = NULL; 112 env[1] = NULL;
@@ -120,15 +114,17 @@ np_runcmd_open(const char *cmdstring, int *pfd, int *pfderr)
120 /* make copy of command string so strtok() doesn't silently modify it */ 114 /* make copy of command string so strtok() doesn't silently modify it */
121 /* (the calling program may want to access it later) */ 115 /* (the calling program may want to access it later) */
122 cmdlen = strlen(cmdstring); 116 cmdlen = strlen(cmdstring);
123 if((cmd = malloc(cmdlen + 1)) == NULL) return -1; 117 if ((cmd = malloc(cmdlen + 1)) == NULL)
118 return -1;
124 memcpy(cmd, cmdstring, cmdlen); 119 memcpy(cmd, cmdstring, cmdlen);
125 cmd[cmdlen] = '\0'; 120 cmd[cmdlen] = '\0';
126 121
127 /* This is not a shell, so we don't handle "???" */ 122 /* This is not a shell, so we don't handle "???" */
128 if (strstr (cmdstring, "\"")) return -1; 123 if (strstr(cmdstring, "\""))
124 return -1;
129 125
130 /* allow single quotes, but only if non-whitesapce doesn't occur on both sides */ 126 /* allow single quotes, but only if non-whitesapce doesn't occur on both sides */
131 if (strstr (cmdstring, " ' ") || strstr (cmdstring, "'''")) 127 if (strstr(cmdstring, " ' ") || strstr(cmdstring, "'''"))
132 return -1; 128 return -1;
133 129
134 /* each arg must be whitespace-separated, so args can be a maximum 130 /* each arg must be whitespace-separated, so args can be a maximum
@@ -137,32 +133,31 @@ np_runcmd_open(const char *cmdstring, int *pfd, int *pfderr)
137 argv = calloc(sizeof(char *), argc); 133 argv = calloc(sizeof(char *), argc);
138 134
139 if (argv == NULL) { 135 if (argv == NULL) {
140 printf ("%s\n", _("Could not malloc argv array in popen()")); 136 printf("%s\n", _("Could not malloc argv array in popen()"));
141 return -1; 137 return -1;
142 } 138 }
143 139
144 /* get command arguments (stupidly, but fairly quickly) */ 140 /* get command arguments (stupidly, but fairly quickly) */
145 while (cmd) { 141 while (cmd) {
146 str = cmd; 142 str = cmd;
147 str += strspn (str, " \t\r\n"); /* trim any leading whitespace */ 143 str += strspn(str, " \t\r\n"); /* trim any leading whitespace */
148 144
149 if (strstr (str, "'") == str) { /* handle SIMPLE quoted strings */ 145 if (strstr(str, "'") == str) { /* handle SIMPLE quoted strings */
150 str++; 146 str++;
151 if (!strstr (str, "'")) return -1; /* balanced? */ 147 if (!strstr(str, "'"))
152 cmd = 1 + strstr (str, "'"); 148 return -1; /* balanced? */
153 str[strcspn (str, "'")] = 0; 149 cmd = 1 + strstr(str, "'");
154 } 150 str[strcspn(str, "'")] = 0;
155 else { 151 } else {
156 if (strpbrk (str, " \t\r\n")) { 152 if (strpbrk(str, " \t\r\n")) {
157 cmd = 1 + strpbrk (str, " \t\r\n"); 153 cmd = 1 + strpbrk(str, " \t\r\n");
158 str[strcspn (str, " \t\r\n")] = 0; 154 str[strcspn(str, " \t\r\n")] = 0;
159 } 155 } else {
160 else {
161 cmd = NULL; 156 cmd = NULL;
162 } 157 }
163 } 158 }
164 159
165 if (cmd && strlen (cmd) == strspn (cmd, " \t\r\n")) 160 if (cmd && strlen(cmd) == strspn(cmd, " \t\r\n"))
166 cmd = NULL; 161 cmd = NULL;
167 162
168 argv[i++] = str; 163 argv[i++] = str;
@@ -173,33 +168,33 @@ np_runcmd_open(const char *cmdstring, int *pfd, int *pfderr)
173 168
174 /* child runs exceve() and _exit. */ 169 /* child runs exceve() and _exit. */
175 if (pid == 0) { 170 if (pid == 0) {
176#ifdef RLIMIT_CORE 171#ifdef RLIMIT_CORE
177 /* the program we execve shouldn't leave core files */ 172 /* the program we execve shouldn't leave core files */
178 getrlimit (RLIMIT_CORE, &limit); 173 getrlimit(RLIMIT_CORE, &limit);
179 limit.rlim_cur = 0; 174 limit.rlim_cur = 0;
180 setrlimit (RLIMIT_CORE, &limit); 175 setrlimit(RLIMIT_CORE, &limit);
181#endif 176#endif
182 close (pfd[0]); 177 close(pfd[0]);
183 if (pfd[1] != STDOUT_FILENO) { 178 if (pfd[1] != STDOUT_FILENO) {
184 dup2 (pfd[1], STDOUT_FILENO); 179 dup2(pfd[1], STDOUT_FILENO);
185 close (pfd[1]); 180 close(pfd[1]);
186 } 181 }
187 close (pfderr[0]); 182 close(pfderr[0]);
188 if (pfderr[1] != STDERR_FILENO) { 183 if (pfderr[1] != STDERR_FILENO) {
189 dup2 (pfderr[1], STDERR_FILENO); 184 dup2(pfderr[1], STDERR_FILENO);
190 close (pfderr[1]); 185 close(pfderr[1]);
191 } 186 }
192 187
193 /* close all descriptors in np_pids[] 188 /* close all descriptors in np_pids[]
194 * This is executed in a separate address space (pure child), 189 * This is executed in a separate address space (pure child),
195 * so we don't have to worry about async safety */ 190 * so we don't have to worry about async safety */
196 long maxfd = mp_open_max(); 191 long maxfd = mp_open_max();
197 for (i = 0; i < maxfd; i++) 192 for (i = 0; i < maxfd; i++)
198 if(np_pids[i] > 0) 193 if (np_pids[i] > 0)
199 close (i); 194 close(i);
200 195
201 execve (argv[0], argv, env); 196 execve(argv[0], argv, env);
202 _exit (STATE_UNKNOWN); 197 _exit(STATE_UNKNOWN);
203 } 198 }
204 199
205 /* parent picks up execution here */ 200 /* parent picks up execution here */
@@ -213,49 +208,44 @@ np_runcmd_open(const char *cmdstring, int *pfd, int *pfderr)
213 return pfd[0]; 208 return pfd[0];
214} 209}
215 210
216 211static int np_runcmd_close(int fd) {
217static int
218np_runcmd_close(int fd)
219{
220 int status; 212 int status;
221 pid_t pid; 213 pid_t pid;
222 214
223 /* make sure this fd was opened by popen() */ 215 /* make sure this fd was opened by popen() */
224 long maxfd = mp_open_max(); 216 long maxfd = mp_open_max();
225 if(fd < 0 || fd > maxfd || !np_pids || (pid = np_pids[fd]) == 0) 217 if (fd < 0 || fd > maxfd || !np_pids || (pid = np_pids[fd]) == 0)
226 return -1; 218 return -1;
227 219
228 np_pids[fd] = 0; 220 np_pids[fd] = 0;
229 if (close (fd) == -1) return -1; 221 if (close(fd) == -1)
222 return -1;
230 223
231 /* EINTR is ok (sort of), everything else is bad */ 224 /* EINTR is ok (sort of), everything else is bad */
232 while (waitpid (pid, &status, 0) < 0) 225 while (waitpid(pid, &status, 0) < 0)
233 if (errno != EINTR) return -1; 226 if (errno != EINTR)
227 return -1;
234 228
235 /* return child's termination status */ 229 /* return child's termination status */
236 return (WIFEXITED(status)) ? WEXITSTATUS(status) : -1; 230 return (WIFEXITED(status)) ? WEXITSTATUS(status) : -1;
237} 231}
238 232
239 233void runcmd_timeout_alarm_handler(int signo) {
240void
241runcmd_timeout_alarm_handler (int signo)
242{
243 234
244 if (signo == SIGALRM) 235 if (signo == SIGALRM)
245 puts(_("CRITICAL - Plugin timed out while executing system call")); 236 puts(_("CRITICAL - Plugin timed out while executing system call"));
246 237
247 long maxfd = mp_open_max(); 238 long maxfd = mp_open_max();
248 if(np_pids) for(long int i = 0; i < maxfd; i++) { 239 if (np_pids)
249 if(np_pids[i] != 0) kill(np_pids[i], SIGKILL); 240 for (long int i = 0; i < maxfd; i++) {
250 } 241 if (np_pids[i] != 0)
242 kill(np_pids[i], SIGKILL);
243 }
251 244
252 exit (STATE_CRITICAL); 245 exit(STATE_CRITICAL);
253} 246}
254 247
255 248static int np_fetch_output(int fd, output *op, int flags) {
256static int
257np_fetch_output(int fd, output *op, int flags)
258{
259 size_t len = 0, i = 0, lineno = 0; 249 size_t len = 0, i = 0, lineno = 0;
260 size_t rsf = 6, ary_size = 0; /* rsf = right shift factor, dec'ed uncond once */ 250 size_t rsf = 6, ary_size = 0; /* rsf = right shift factor, dec'ed uncond once */
261 char *buf = NULL; 251 char *buf = NULL;
@@ -264,7 +254,7 @@ np_fetch_output(int fd, output *op, int flags)
264 254
265 op->buf = NULL; 255 op->buf = NULL;
266 op->buflen = 0; 256 op->buflen = 0;
267 while((ret = read(fd, tmpbuf, sizeof(tmpbuf))) > 0) { 257 while ((ret = read(fd, tmpbuf, sizeof(tmpbuf))) > 0) {
268 len = (size_t)ret; 258 len = (size_t)ret;
269 op->buf = realloc(op->buf, op->buflen + len + 1); 259 op->buf = realloc(op->buf, op->buflen + len + 1);
270 memcpy(op->buf + op->buflen, tmpbuf, len); 260 memcpy(op->buf + op->buflen, tmpbuf, len);
@@ -272,33 +262,33 @@ np_fetch_output(int fd, output *op, int flags)
272 i++; 262 i++;
273 } 263 }
274 264
275 if(ret < 0) { 265 if (ret < 0) {
276 printf("read() returned %d: %s\n", ret, strerror(errno)); 266 printf("read() returned %d: %s\n", ret, strerror(errno));
277 return ret; 267 return ret;
278 } 268 }
279 269
280 /* some plugins may want to keep output unbroken, and some commands 270 /* some plugins may want to keep output unbroken, and some commands
281 * will yield no output, so return here for those */ 271 * will yield no output, so return here for those */
282 if(flags & RUNCMD_NO_ARRAYS || !op->buf || !op->buflen) 272 if (flags & RUNCMD_NO_ARRAYS || !op->buf || !op->buflen)
283 return op->buflen; 273 return op->buflen;
284 274
285 /* and some may want both */ 275 /* and some may want both */
286 if(flags & RUNCMD_NO_ASSOC) { 276 if (flags & RUNCMD_NO_ASSOC) {
287 buf = malloc(op->buflen); 277 buf = malloc(op->buflen);
288 memcpy(buf, op->buf, op->buflen); 278 memcpy(buf, op->buf, op->buflen);
289 } 279 } else
290 else buf = op->buf; 280 buf = op->buf;
291 281
292 op->line = NULL; 282 op->line = NULL;
293 op->lens = NULL; 283 op->lens = NULL;
294 i = 0; 284 i = 0;
295 while(i < op->buflen) { 285 while (i < op->buflen) {
296 /* make sure we have enough memory */ 286 /* make sure we have enough memory */
297 if(lineno >= ary_size) { 287 if (lineno >= ary_size) {
298 /* ary_size must never be zero */ 288 /* ary_size must never be zero */
299 do { 289 do {
300 ary_size = op->buflen >> --rsf; 290 ary_size = op->buflen >> --rsf;
301 } while(!ary_size); 291 } while (!ary_size);
302 292
303 op->line = realloc(op->line, ary_size * sizeof(char *)); 293 op->line = realloc(op->line, ary_size * sizeof(char *));
304 op->lens = realloc(op->lens, ary_size * sizeof(size_t)); 294 op->lens = realloc(op->lens, ary_size * sizeof(size_t));
@@ -308,7 +298,8 @@ np_fetch_output(int fd, output *op, int flags)
308 op->line[lineno] = &buf[i]; 298 op->line[lineno] = &buf[i];
309 299
310 /* hop to next newline or end of buffer */ 300 /* hop to next newline or end of buffer */
311 while(buf[i] != '\n' && i < op->buflen) i++; 301 while (buf[i] != '\n' && i < op->buflen)
302 i++;
312 buf[i] = '\0'; 303 buf[i] = '\0';
313 304
314 /* calculate the string length using pointer difference */ 305 /* calculate the string length using pointer difference */
@@ -321,21 +312,22 @@ np_fetch_output(int fd, output *op, int flags)
321 return lineno; 312 return lineno;
322} 313}
323 314
324 315int np_runcmd(const char *cmd, output *out, output *err, int flags) {
325int
326np_runcmd(const char *cmd, output *out, output *err, int flags)
327{
328 int fd, pfd_out[2], pfd_err[2]; 316 int fd, pfd_out[2], pfd_err[2];
329 317
330 /* initialize the structs */ 318 /* initialize the structs */
331 if(out) memset(out, 0, sizeof(output)); 319 if (out)
332 if(err) memset(err, 0, sizeof(output)); 320 memset(out, 0, sizeof(output));
333 321 if (err)
334 if((fd = np_runcmd_open(cmd, pfd_out, pfd_err)) == -1) 322 memset(err, 0, sizeof(output));
335 die (STATE_UNKNOWN, _("Could not open pipe: %s\n"), cmd); 323
336 324 if ((fd = np_runcmd_open(cmd, pfd_out, pfd_err)) == -1)
337 if(out) out->lines = np_fetch_output(pfd_out[0], out, flags); 325 die(STATE_UNKNOWN, _("Could not open pipe: %s\n"), cmd);
338 if(err) err->lines = np_fetch_output(pfd_err[0], err, flags); 326
327 if (out)
328 out->lines = np_fetch_output(pfd_out[0], out, flags);
329 if (err)
330 err->lines = np_fetch_output(pfd_err[0], err, flags);
339 331
340 return np_runcmd_close(fd); 332 return np_runcmd_close(fd);
341} 333}
diff --git a/plugins/sslutils.c b/plugins/sslutils.c
index 6bc0ba81..3c928413 100644
--- a/plugins/sslutils.c
+++ b/plugins/sslutils.c
@@ -1,46 +1,42 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring Plugins SSL utilities 3 * Monitoring Plugins SSL utilities
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 2005-2010 Monitoring Plugins Development Team 6 * Copyright (c) 2005-2024 Monitoring Plugins Development Team
7* 7 *
8* Description: 8 * Description:
9* 9 *
10* This file contains common functions for plugins that require SSL. 10 * This file contains common functions for plugins that require SSL.
11* 11 *
12* 12 *
13* This program is free software: you can redistribute it and/or modify 13 * This program is free software: you can redistribute it and/or modify
14* it under the terms of the GNU General Public License as published by 14 * it under the terms of the GNU General Public License as published by
15* the Free Software Foundation, either version 3 of the License, or 15 * the Free Software Foundation, either version 3 of the License, or
16* (at your option) any later version. 16 * (at your option) any later version.
17* 17 *
18* This program is distributed in the hope that it will be useful, 18 * This program is distributed in the hope that it will be useful,
19* but WITHOUT ANY WARRANTY; without even the implied warranty of 19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21* GNU General Public License for more details. 21 * GNU General Public License for more details.
22* 22 *
23* You should have received a copy of the GNU General Public License 23 * You should have received a copy of the GNU General Public License
24* along with this program. If not, see <http://www.gnu.org/licenses/>. 24 * along with this program. If not, see <http://www.gnu.org/licenses/>.
25* 25 *
26* 26 *
27*****************************************************************************/ 27 *****************************************************************************/
28 28
29#define MAX_CN_LENGTH 256 29#define MAX_CN_LENGTH 256
30#include "common.h" 30#include "common.h"
31#include "netutils.h" 31#include "netutils.h"
32 32
33#ifdef HAVE_SSL 33#ifdef HAVE_SSL
34static SSL_CTX *ctx=NULL; 34static SSL_CTX *ctx = NULL;
35static SSL *s=NULL; 35static SSL *s = NULL;
36 36
37int np_net_ssl_init(int sd) { 37int np_net_ssl_init(int sd) { return np_net_ssl_init_with_hostname(sd, NULL); }
38 return np_net_ssl_init_with_hostname(sd, NULL);
39}
40 38
41int np_net_ssl_init_with_hostname(int sd, char *host_name) { 39int np_net_ssl_init_with_hostname(int sd, char *host_name) { return np_net_ssl_init_with_hostname_and_version(sd, host_name, 0); }
42 return np_net_ssl_init_with_hostname_and_version(sd, host_name, 0);
43}
44 40
45int np_net_ssl_init_with_hostname_and_version(int sd, char *host_name, int version) { 41int np_net_ssl_init_with_hostname_and_version(int sd, char *host_name, int version) {
46 return np_net_ssl_init_with_hostname_version_and_cert(sd, host_name, version, NULL, NULL); 42 return np_net_ssl_init_with_hostname_version_and_cert(sd, host_name, version, NULL, NULL);
@@ -59,145 +55,141 @@ int np_net_ssl_init_with_hostname_version_and_cert(int sd, char *host_name, int
59 printf("%s\n", _("UNKNOWN - SSL protocol version 2 is not supported by your SSL library.")); 55 printf("%s\n", _("UNKNOWN - SSL protocol version 2 is not supported by your SSL library."));
60 return STATE_UNKNOWN; 56 return STATE_UNKNOWN;
61 case MP_SSLv3: /* SSLv3 protocol */ 57 case MP_SSLv3: /* SSLv3 protocol */
62#if defined(OPENSSL_NO_SSL3) 58# if defined(OPENSSL_NO_SSL3)
63 printf("%s\n", _("UNKNOWN - SSL protocol version 3 is not supported by your SSL library.")); 59 printf("%s\n", _("UNKNOWN - SSL protocol version 3 is not supported by your SSL library."));
64 return STATE_UNKNOWN; 60 return STATE_UNKNOWN;
65#else 61# else
66 SSL_CTX_set_min_proto_version(ctx, SSL3_VERSION); 62 SSL_CTX_set_min_proto_version(ctx, SSL3_VERSION);
67 SSL_CTX_set_max_proto_version(ctx, SSL3_VERSION); 63 SSL_CTX_set_max_proto_version(ctx, SSL3_VERSION);
68 break; 64 break;
69#endif 65# endif
70 case MP_TLSv1: /* TLSv1 protocol */ 66 case MP_TLSv1: /* TLSv1 protocol */
71#if defined(OPENSSL_NO_TLS1) 67# if defined(OPENSSL_NO_TLS1)
72 printf("%s\n", _("UNKNOWN - TLS protocol version 1 is not supported by your SSL library.")); 68 printf("%s\n", _("UNKNOWN - TLS protocol version 1 is not supported by your SSL library."));
73 return STATE_UNKNOWN; 69 return STATE_UNKNOWN;
74#else 70# else
75 SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION); 71 SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION);
76 SSL_CTX_set_max_proto_version(ctx, TLS1_VERSION); 72 SSL_CTX_set_max_proto_version(ctx, TLS1_VERSION);
77 break; 73 break;
78#endif 74# endif
79 case MP_TLSv1_1: /* TLSv1.1 protocol */ 75 case MP_TLSv1_1: /* TLSv1.1 protocol */
80#if !defined(SSL_OP_NO_TLSv1_1) 76# if !defined(SSL_OP_NO_TLSv1_1)
81 printf("%s\n", _("UNKNOWN - TLS protocol version 1.1 is not supported by your SSL library.")); 77 printf("%s\n", _("UNKNOWN - TLS protocol version 1.1 is not supported by your SSL library."));
82 return STATE_UNKNOWN; 78 return STATE_UNKNOWN;
83#else 79# else
84 SSL_CTX_set_min_proto_version(ctx, TLS1_1_VERSION); 80 SSL_CTX_set_min_proto_version(ctx, TLS1_1_VERSION);
85 SSL_CTX_set_max_proto_version(ctx, TLS1_1_VERSION); 81 SSL_CTX_set_max_proto_version(ctx, TLS1_1_VERSION);
86 break; 82 break;
87#endif 83# endif
88 case MP_TLSv1_2: /* TLSv1.2 protocol */ 84 case MP_TLSv1_2: /* TLSv1.2 protocol */
89#if !defined(SSL_OP_NO_TLSv1_2) 85# if !defined(SSL_OP_NO_TLSv1_2)
90 printf("%s\n", _("UNKNOWN - TLS protocol version 1.2 is not supported by your SSL library.")); 86 printf("%s\n", _("UNKNOWN - TLS protocol version 1.2 is not supported by your SSL library."));
91 return STATE_UNKNOWN; 87 return STATE_UNKNOWN;
92#else 88# else
93 SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION); 89 SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION);
94 SSL_CTX_set_max_proto_version(ctx, TLS1_2_VERSION); 90 SSL_CTX_set_max_proto_version(ctx, TLS1_2_VERSION);
95 break; 91 break;
96#endif 92# endif
97 case MP_TLSv1_2_OR_NEWER: 93 case MP_TLSv1_2_OR_NEWER:
98#if !defined(SSL_OP_NO_TLSv1_1) 94# if !defined(SSL_OP_NO_TLSv1_1)
99 printf("%s\n", _("UNKNOWN - Disabling TLSv1.1 is not supported by your SSL library.")); 95 printf("%s\n", _("UNKNOWN - Disabling TLSv1.1 is not supported by your SSL library."));
100 return STATE_UNKNOWN; 96 return STATE_UNKNOWN;
101#else 97# else
102 SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION); 98 SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION);
103 break; 99 break;
104#endif 100# endif
105 case MP_TLSv1_1_OR_NEWER: 101 case MP_TLSv1_1_OR_NEWER:
106#if !defined(SSL_OP_NO_TLSv1) 102# if !defined(SSL_OP_NO_TLSv1)
107 printf("%s\n", _("UNKNOWN - Disabling TLSv1 is not supported by your SSL library.")); 103 printf("%s\n", _("UNKNOWN - Disabling TLSv1 is not supported by your SSL library."));
108 return STATE_UNKNOWN; 104 return STATE_UNKNOWN;
109#else 105# else
110 SSL_CTX_set_min_proto_version(ctx, TLS1_1_VERSION); 106 SSL_CTX_set_min_proto_version(ctx, TLS1_1_VERSION);
111 break; 107 break;
112#endif 108# endif
113 case MP_TLSv1_OR_NEWER: 109 case MP_TLSv1_OR_NEWER:
114#if defined(SSL_OP_NO_SSLv3) 110# if defined(SSL_OP_NO_SSLv3)
115 SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION); 111 SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION);
116 break; 112 break;
117#endif 113# endif
118 case MP_SSLv3_OR_NEWER: 114 case MP_SSLv3_OR_NEWER:
119#if defined(SSL_OP_NO_SSLv2) 115# if defined(SSL_OP_NO_SSLv2)
120 SSL_CTX_set_min_proto_version(ctx, SSL3_VERSION); 116 SSL_CTX_set_min_proto_version(ctx, SSL3_VERSION);
121 break; 117 break;
122#endif 118# endif
123 } 119 }
124 120
125 if (cert && privkey) { 121 if (cert && privkey) {
126#ifdef USE_OPENSSL 122# ifdef USE_OPENSSL
127 if (!SSL_CTX_use_certificate_chain_file(ctx, cert)) { 123 if (!SSL_CTX_use_certificate_chain_file(ctx, cert)) {
128#elif USE_GNUTLS 124# elif USE_GNUTLS
129 if (!SSL_CTX_use_certificate_file(ctx, cert, SSL_FILETYPE_PEM)) { 125 if (!SSL_CTX_use_certificate_file(ctx, cert, SSL_FILETYPE_PEM)) {
130#else 126# else
131#error Unported for unknown SSL library 127# error Unported for unknown SSL library
132#endif 128# endif
133 printf ("%s\n", _("CRITICAL - Unable to open certificate chain file!\n")); 129 printf("%s\n", _("CRITICAL - Unable to open certificate chain file!\n"));
134 return STATE_CRITICAL; 130 return STATE_CRITICAL;
135 } 131 }
136 SSL_CTX_use_PrivateKey_file(ctx, privkey, SSL_FILETYPE_PEM); 132 SSL_CTX_use_PrivateKey_file(ctx, privkey, SSL_FILETYPE_PEM);
137#ifdef USE_OPENSSL 133# ifdef USE_OPENSSL
138 if (!SSL_CTX_check_private_key(ctx)) { 134 if (!SSL_CTX_check_private_key(ctx)) {
139 printf ("%s\n", _("CRITICAL - Private key does not seem to match certificate!\n")); 135 printf("%s\n", _("CRITICAL - Private key does not seem to match certificate!\n"));
140 return STATE_CRITICAL; 136 return STATE_CRITICAL;
141 } 137 }
142#endif 138# endif
143 } 139 }
144#ifdef SSL_OP_NO_TICKET 140# ifdef SSL_OP_NO_TICKET
145 options |= SSL_OP_NO_TICKET; 141 options |= SSL_OP_NO_TICKET;
146#endif 142# endif
147 SSL_CTX_set_options(ctx, options); 143 SSL_CTX_set_options(ctx, options);
148 SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY); 144 SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY);
149 if ((s = SSL_new(ctx)) != NULL) { 145 if ((s = SSL_new(ctx)) != NULL) {
150#ifdef SSL_set_tlsext_host_name 146# ifdef SSL_set_tlsext_host_name
151 if (host_name != NULL) 147 if (host_name != NULL)
152 SSL_set_tlsext_host_name(s, host_name); 148 SSL_set_tlsext_host_name(s, host_name);
153#endif 149# endif
154 SSL_set_fd(s, sd); 150 SSL_set_fd(s, sd);
155 if (SSL_connect(s) == 1) { 151 if (SSL_connect(s) == 1) {
156 return OK; 152 return OK;
157 } else { 153 } else {
158 printf("%s\n", _("CRITICAL - Cannot make SSL connection.")); 154 printf("%s\n", _("CRITICAL - Cannot make SSL connection."));
159# ifdef USE_OPENSSL /* XXX look into ERR_error_string */ 155# ifdef USE_OPENSSL /* XXX look into ERR_error_string */
160 ERR_print_errors_fp(stdout); 156 ERR_print_errors_fp(stdout);
161# endif /* USE_OPENSSL */ 157# endif /* USE_OPENSSL */
162 } 158 }
163 } else { 159 } else {
164 printf("%s\n", _("CRITICAL - Cannot initiate SSL handshake.")); 160 printf("%s\n", _("CRITICAL - Cannot initiate SSL handshake."));
165 } 161 }
166 return STATE_CRITICAL; 162 return STATE_CRITICAL;
167} 163}
168 164
169void np_net_ssl_cleanup() { 165void np_net_ssl_cleanup() {
170 if (s) { 166 if (s) {
171#ifdef SSL_set_tlsext_host_name 167# ifdef SSL_set_tlsext_host_name
172 SSL_set_tlsext_host_name(s, NULL); 168 SSL_set_tlsext_host_name(s, NULL);
173#endif 169# endif
174 SSL_shutdown(s); 170 SSL_shutdown(s);
175 SSL_free(s); 171 SSL_free(s);
176 if (ctx) { 172 if (ctx) {
177 SSL_CTX_free(ctx); 173 SSL_CTX_free(ctx);
178 ctx=NULL; 174 ctx = NULL;
179 } 175 }
180 s=NULL; 176 s = NULL;
181 } 177 }
182} 178}
183 179
184int np_net_ssl_write(const void *buf, int num) { 180int np_net_ssl_write(const void *buf, int num) { return SSL_write(s, buf, num); }
185 return SSL_write(s, buf, num);
186}
187 181
188int np_net_ssl_read(void *buf, int num) { 182int np_net_ssl_read(void *buf, int num) { return SSL_read(s, buf, num); }
189 return SSL_read(s, buf, num);
190}
191 183
192int np_net_ssl_check_certificate(X509 *certificate, int days_till_exp_warn, int days_till_exp_crit){ 184int np_net_ssl_check_certificate(X509 *certificate, int days_till_exp_warn, int days_till_exp_crit) {
193# ifdef USE_OPENSSL 185# ifdef USE_OPENSSL
194 X509_NAME *subj=NULL; 186 X509_NAME *subj = NULL;
195 char timestamp[50] = ""; 187 char timestamp[50] = "";
196 char cn[MAX_CN_LENGTH]= ""; 188 char cn[MAX_CN_LENGTH] = "";
197 char *tz; 189 char *tz;
198 190
199 int cnlen =-1; 191 int cnlen = -1;
200 int status=STATE_UNKNOWN; 192 int status = STATE_UNKNOWN;
201 193
202 ASN1_STRING *tm; 194 ASN1_STRING *tm;
203 int offset; 195 int offset;
@@ -208,15 +200,15 @@ int np_net_ssl_check_certificate(X509 *certificate, int days_till_exp_warn, int
208 time_t tm_t; 200 time_t tm_t;
209 201
210 if (!certificate) { 202 if (!certificate) {
211 printf("%s\n",_("CRITICAL - Cannot retrieve server certificate.")); 203 printf("%s\n", _("CRITICAL - Cannot retrieve server certificate."));
212 return STATE_CRITICAL; 204 return STATE_CRITICAL;
213 } 205 }
214 206
215 /* Extract CN from certificate subject */ 207 /* Extract CN from certificate subject */
216 subj=X509_get_subject_name(certificate); 208 subj = X509_get_subject_name(certificate);
217 209
218 if (!subj) { 210 if (!subj) {
219 printf("%s\n",_("CRITICAL - Cannot retrieve certificate subject.")); 211 printf("%s\n", _("CRITICAL - Cannot retrieve certificate subject."));
220 return STATE_CRITICAL; 212 return STATE_CRITICAL;
221 } 213 }
222 cnlen = X509_NAME_get_text_by_NID(subj, NID_commonName, cn, sizeof(cn)); 214 cnlen = X509_NAME_get_text_by_NID(subj, NID_commonName, cn, sizeof(cn));
@@ -242,23 +234,16 @@ int np_net_ssl_check_certificate(X509 *certificate, int days_till_exp_warn, int
242 printf("%s\n", _("CRITICAL - Wrong time format in certificate.")); 234 printf("%s\n", _("CRITICAL - Wrong time format in certificate."));
243 return STATE_CRITICAL; 235 return STATE_CRITICAL;
244 } else { 236 } else {
245 stamp.tm_year = 237 stamp.tm_year = (tm->data[0] - '0') * 1000 + (tm->data[1] - '0') * 100 + (tm->data[2] - '0') * 10 + (tm->data[3] - '0');
246 (tm->data[0] - '0') * 1000 + (tm->data[1] - '0') * 100 +
247 (tm->data[2] - '0') * 10 + (tm->data[3] - '0');
248 stamp.tm_year -= 1900; 238 stamp.tm_year -= 1900;
249 offset = 2; 239 offset = 2;
250 } 240 }
251 } 241 }
252 stamp.tm_mon = 242 stamp.tm_mon = (tm->data[2 + offset] - '0') * 10 + (tm->data[3 + offset] - '0') - 1;
253 (tm->data[2 + offset] - '0') * 10 + (tm->data[3 + offset] - '0') - 1; 243 stamp.tm_mday = (tm->data[4 + offset] - '0') * 10 + (tm->data[5 + offset] - '0');
254 stamp.tm_mday = 244 stamp.tm_hour = (tm->data[6 + offset] - '0') * 10 + (tm->data[7 + offset] - '0');
255 (tm->data[4 + offset] - '0') * 10 + (tm->data[5 + offset] - '0'); 245 stamp.tm_min = (tm->data[8 + offset] - '0') * 10 + (tm->data[9 + offset] - '0');
256 stamp.tm_hour = 246 stamp.tm_sec = (tm->data[10 + offset] - '0') * 10 + (tm->data[11 + offset] - '0');
257 (tm->data[6 + offset] - '0') * 10 + (tm->data[7 + offset] - '0');
258 stamp.tm_min =
259 (tm->data[8 + offset] - '0') * 10 + (tm->data[9 + offset] - '0');
260 stamp.tm_sec =
261 (tm->data[10 + offset] - '0') * 10 + (tm->data[11 + offset] - '0');
262 stamp.tm_isdst = -1; 247 stamp.tm_isdst = -1;
263 248
264 tm_t = timegm(&stamp); 249 tm_t = timegm(&stamp);
@@ -275,30 +260,30 @@ int np_net_ssl_check_certificate(X509 *certificate, int days_till_exp_warn, int
275 tzset(); 260 tzset();
276 261
277 if (days_left > 0 && days_left <= days_till_exp_warn) { 262 if (days_left > 0 && days_left <= days_till_exp_warn) {
278 printf (_("%s - Certificate '%s' expires in %d day(s) (%s).\n"), (days_left>days_till_exp_crit)?"WARNING":"CRITICAL", cn, days_left, timestamp); 263 printf(_("%s - Certificate '%s' expires in %d day(s) (%s).\n"), (days_left > days_till_exp_crit) ? "WARNING" : "CRITICAL", cn,
264 days_left, timestamp);
279 if (days_left > days_till_exp_crit) 265 if (days_left > days_till_exp_crit)
280 status = STATE_WARNING; 266 status = STATE_WARNING;
281 else 267 else
282 status = STATE_CRITICAL; 268 status = STATE_CRITICAL;
283 } else if (days_left == 0 && time_left > 0) { 269 } else if (days_left == 0 && time_left > 0) {
284 if (time_left >= 3600) 270 if (time_left >= 3600)
285 time_remaining = (int) time_left / 3600; 271 time_remaining = (int)time_left / 3600;
286 else 272 else
287 time_remaining = (int) time_left / 60; 273 time_remaining = (int)time_left / 60;
288 274
289 printf (_("%s - Certificate '%s' expires in %u %s (%s)\n"), 275 printf(_("%s - Certificate '%s' expires in %u %s (%s)\n"), (days_left > days_till_exp_crit) ? "WARNING" : "CRITICAL", cn,
290 (days_left>days_till_exp_crit) ? "WARNING" : "CRITICAL", cn, time_remaining, 276 time_remaining, time_left >= 3600 ? "hours" : "minutes", timestamp);
291 time_left >= 3600 ? "hours" : "minutes", timestamp);
292 277
293 if ( days_left > days_till_exp_crit) 278 if (days_left > days_till_exp_crit)
294 status = STATE_WARNING; 279 status = STATE_WARNING;
295 else 280 else
296 status = STATE_CRITICAL; 281 status = STATE_CRITICAL;
297 } else if (time_left < 0) { 282 } else if (time_left < 0) {
298 printf(_("CRITICAL - Certificate '%s' expired on %s.\n"), cn, timestamp); 283 printf(_("CRITICAL - Certificate '%s' expired on %s.\n"), cn, timestamp);
299 status=STATE_CRITICAL; 284 status = STATE_CRITICAL;
300 } else if (days_left == 0) { 285 } else if (days_left == 0) {
301 printf (_("%s - Certificate '%s' just expired (%s).\n"), (days_left>days_till_exp_crit)?"WARNING":"CRITICAL", cn, timestamp); 286 printf(_("%s - Certificate '%s' just expired (%s).\n"), (days_left > days_till_exp_crit) ? "WARNING" : "CRITICAL", cn, timestamp);
302 if (days_left > days_till_exp_crit) 287 if (days_left > days_till_exp_crit)
303 status = STATE_WARNING; 288 status = STATE_WARNING;
304 else 289 else
@@ -309,22 +294,21 @@ int np_net_ssl_check_certificate(X509 *certificate, int days_till_exp_warn, int
309 } 294 }
310 X509_free(certificate); 295 X509_free(certificate);
311 return status; 296 return status;
312# else /* ifndef USE_OPENSSL */ 297# else /* ifndef USE_OPENSSL */
313 printf("%s\n", _("WARNING - Plugin does not support checking certificates.")); 298 printf("%s\n", _("WARNING - Plugin does not support checking certificates."));
314 return STATE_WARNING; 299 return STATE_WARNING;
315# endif /* USE_OPENSSL */ 300# endif /* USE_OPENSSL */
316} 301}
317 302
318int np_net_ssl_check_cert(int days_till_exp_warn, int days_till_exp_crit){ 303int np_net_ssl_check_cert(int days_till_exp_warn, int days_till_exp_crit) {
319# ifdef USE_OPENSSL 304# ifdef USE_OPENSSL
320 X509 *certificate = NULL; 305 X509 *certificate = NULL;
321 certificate=SSL_get_peer_certificate(s); 306 certificate = SSL_get_peer_certificate(s);
322 return(np_net_ssl_check_certificate(certificate, days_till_exp_warn, days_till_exp_crit)); 307 return (np_net_ssl_check_certificate(certificate, days_till_exp_warn, days_till_exp_crit));
323# else /* ifndef USE_OPENSSL */ 308# else /* ifndef USE_OPENSSL */
324 printf("%s\n", _("WARNING - Plugin does not support checking certificates.")); 309 printf("%s\n", _("WARNING - Plugin does not support checking certificates."));
325 return STATE_WARNING; 310 return STATE_WARNING;
326# endif /* USE_OPENSSL */ 311# endif /* USE_OPENSSL */
327} 312}
328 313
329
330#endif /* HAVE_SSL */ 314#endif /* HAVE_SSL */
diff --git a/plugins/t/check_curl.t b/plugins/t/check_curl.t
index eae98cc1..7a930a4e 100644
--- a/plugins/t/check_curl.t
+++ b/plugins/t/check_curl.t
@@ -205,9 +205,9 @@ SKIP: {
205 like ( $res->output, '/time_connect=[\d\.]+/', 'Extended Performance Data Output OK' ); 205 like ( $res->output, '/time_connect=[\d\.]+/', 'Extended Performance Data Output OK' );
206 like ( $res->output, '/time_ssl=[\d\.]+/', 'Extended Performance Data SSL Output OK' ); 206 like ( $res->output, '/time_ssl=[\d\.]+/', 'Extended Performance Data SSL Output OK' );
207 207
208 $res = NPTest->testCmd( "./$plugin -H www.mozilla.com -u /firefox -f curl" ); 208 $res = NPTest->testCmd( "./$plugin -H monitoring-plugins.org -u /download.html -f follow" );
209 is( $res->return_code, 0, "Redirection based on location is okay"); 209 is( $res->return_code, 0, "Redirection based on location is okay");
210 210
211 $res = NPTest->testCmd( "./$plugin -H www.mozilla.com --extended-perfdata" ); 211 $res = NPTest->testCmd( "./$plugin -H monitoring-plugins.org --extended-perfdata" );
212 like ( $res->output, '/time_connect=[\d\.]+/', 'Extended Performance Data Output OK' ); 212 like ( $res->output, '/time_connect=[\d\.]+/', 'Extended Performance Data Output OK' );
213} 213}
diff --git a/plugins/t/check_disk.t b/plugins/t/check_disk.t
index bf8dd362..9eb77ce4 100644
--- a/plugins/t/check_disk.t
+++ b/plugins/t/check_disk.t
@@ -44,7 +44,7 @@ my @perf_data = sort(split(/ /, $result->perf_output));
44# Calculate avg_free free on mountpoint1 and mountpoint2 44# Calculate avg_free free on mountpoint1 and mountpoint2
45# because if you check in the middle, you should get different errors 45# because if you check in the middle, you should get different errors
46$_ = $result->output; 46$_ = $result->output;
47my ($free_on_mp1, $free_on_mp2) = (m/\((\d+)%.*\((\d+)%/); 47my ($free_on_mp1, $free_on_mp2) = (m/\((\d+\.\d+)%.*\((\d+\.\d+)%/);
48die "Cannot parse output: $_" unless ($free_on_mp1 && $free_on_mp2); 48die "Cannot parse output: $_" unless ($free_on_mp1 && $free_on_mp2);
49my $avg_free = ceil(($free_on_mp1+$free_on_mp2)/2); 49my $avg_free = ceil(($free_on_mp1+$free_on_mp2)/2);
50my ($more_free, $less_free); 50my ($more_free, $less_free);
@@ -119,8 +119,12 @@ like ( $result->only_output, qr/$more_free/, "Have disk name in text");
119 119
120$result = NPTest->testCmd( "./check_disk -w 1 -c 1 -p $more_free -p $less_free" ); 120$result = NPTest->testCmd( "./check_disk -w 1 -c 1 -p $more_free -p $less_free" );
121cmp_ok( $result->return_code, '==', 0, "At least 1 MB available on $more_free and $less_free"); 121cmp_ok( $result->return_code, '==', 0, "At least 1 MB available on $more_free and $less_free");
122
122$_ = $result->output; 123$_ = $result->output;
124
123my ($free_mb_on_mp1, $free_mb_on_mp2) = (m/(\d+)MiB .* (\d+)MiB /g); 125my ($free_mb_on_mp1, $free_mb_on_mp2) = (m/(\d+)MiB .* (\d+)MiB /g);
126die "Cannot parse output: $_" unless ($free_mb_on_mp1 && $free_mb_on_mp2);
127
124my $free_mb_on_all = $free_mb_on_mp1 + $free_mb_on_mp2; 128my $free_mb_on_all = $free_mb_on_mp1 + $free_mb_on_mp2;
125 129
126 130
@@ -311,8 +315,8 @@ $result = NPTest->testCmd( "./check_disk -w 0% -c 0% -C -w 0% -c 0% -p $mountpoi
311like( $result->output, '/;.*;\|/', "-C selects partitions if -p is not given"); 315like( $result->output, '/;.*;\|/', "-C selects partitions if -p is not given");
312 316
313# grouping: exit crit if the sum of free megs on mp1+mp2 is less than warn/crit 317# grouping: exit crit if the sum of free megs on mp1+mp2 is less than warn/crit
314$result = NPTest->testCmd( "./check_disk -w ". ($free_mb_on_all + 1) ." -c ". ($free_mb_on_all + 1) ."-g group -p $mountpoint_valid -p $mountpoint2_valid" ); 318$result = NPTest->testCmd( "./check_disk -w ". ($free_mb_on_all + 1) ." -c ". ($free_mb_on_all + 1) ." -g group -p $mountpoint_valid -p $mountpoint2_valid" );
315cmp_ok( $result->return_code, '==', 2, "grouping: exit crit if the sum of free megs on mp1+mp2 is less than warn/crit"); 319cmp_ok( $result->return_code, '==', 2, "grouping: exit crit if the sum of free megs on mp1+mp2 is less than warn/crit\nInstead received: " . $result->output);
316 320
317# grouping: exit warning if the sum of free megs on mp1+mp2 is between -w and -c 321# grouping: exit warning if the sum of free megs on mp1+mp2 is between -w and -c
318$result = NPTest->testCmd( "./check_disk -w ". ($free_mb_on_all + 1) ." -c ". ($free_mb_on_all - 1) ." -g group -p $mountpoint_valid -p $mountpoint2_valid" ); 322$result = NPTest->testCmd( "./check_disk -w ". ($free_mb_on_all + 1) ." -c ". ($free_mb_on_all - 1) ." -g group -p $mountpoint_valid -p $mountpoint2_valid" );
diff --git a/plugins/t/check_http.t b/plugins/t/check_http.t
index 1f2fbdfd..6ab4a5b6 100644
--- a/plugins/t/check_http.t
+++ b/plugins/t/check_http.t
@@ -166,10 +166,10 @@ SKIP: {
166 like ( $res->output, '/time_connect=[\d\.]+/', 'Extended Performance Data Output OK' ); 166 like ( $res->output, '/time_connect=[\d\.]+/', 'Extended Performance Data Output OK' );
167 like ( $res->output, '/time_ssl=[\d\.]+/', 'Extended Performance Data SSL Output OK' ); 167 like ( $res->output, '/time_ssl=[\d\.]+/', 'Extended Performance Data SSL Output OK' );
168 168
169 $res = NPTest->testCmd( "./$plugin -H www.mozilla.com -u /firefox -f follow" ); 169 $res = NPTest->testCmd( "./$plugin -H monitoring-plugins.org -u /download.html -f follow" );
170 is( $res->return_code, 0, "Redirection based on location is okay"); 170 is( $res->return_code, 0, "Redirection based on location is okay");
171 171
172 $res = NPTest->testCmd( "./$plugin -H www.mozilla.com --extended-perfdata" ); 172 $res = NPTest->testCmd( "./$plugin -H monitoring-plugins.org --extended-perfdata" );
173 like ( $res->output, '/time_connect=[\d\.]+/', 'Extended Performance Data Output OK' ); 173 like ( $res->output, '/time_connect=[\d\.]+/', 'Extended Performance Data Output OK' );
174} 174}
175 175
diff --git a/plugins/t/check_ssh.t b/plugins/t/check_ssh.t
index a5cd23ce..907d33a8 100644
--- a/plugins/t/check_ssh.t
+++ b/plugins/t/check_ssh.t
@@ -8,34 +8,116 @@ use strict;
8use Test::More; 8use Test::More;
9use NPTest; 9use NPTest;
10 10
11my $res;
12
11# Required parameters 13# Required parameters
12my $ssh_host = getTestParameter("NP_SSH_HOST", "A host providing SSH service", "localhost"); 14my $ssh_host = getTestParameter("NP_SSH_HOST",
13my $host_nonresponsive = getTestParameter("NP_HOST_NONRESPONSIVE", "The hostname of system not responsive to network requests", "10.0.0.1" ); 15 "A host providing SSH service",
14my $hostname_invalid = getTestParameter("NP_HOSTNAME_INVALID", "An invalid (not known to DNS) hostname", "nosuchhost" ); 16 "localhost");
17
18my $host_nonresponsive = getTestParameter("NP_HOST_NONRESPONSIVE",
19 "The hostname of system not responsive to network requests",
20 "10.0.0.1" );
21
22my $hostname_invalid = getTestParameter("NP_HOSTNAME_INVALID",
23 "An invalid (not known to DNS) hostname",
24 "nosuchhost" );
25
26
27plan tests => 14 + 6;
28
29SKIP: {
30 skip "SSH_HOST must be defined", 6 unless $ssh_host;
31 my $result = NPTest->testCmd(
32 "./check_ssh -H $ssh_host"
33 );
34 cmp_ok($result->return_code, '==', 0, "Exit with return code 0 (OK)");
35 like($result->output, '/^SSH OK - /', "Status text if command returned none (OK)");
36
37
38 $result = NPTest->testCmd(
39 "./check_ssh -H $host_nonresponsive -t 2"
40 );
41 cmp_ok($result->return_code, '==', 2, "Exit with return code 0 (OK)");
42 like($result->output, '/^CRITICAL - Socket timeout after 2 seconds/', "Status text if command returned none (OK)");
43
44
45
46 $result = NPTest->testCmd(
47 "./check_ssh -H $hostname_invalid -t 2"
48 );
49 cmp_ok($result->return_code, '==', 3, "Exit with return code 0 (OK)");
50 like($result->output, '/^check_ssh: Invalid hostname/', "Status text if command returned none (OK)");
51
15 52
53}
54SKIP: {
16 55
17plan skip_all => "SSH_HOST must be defined" unless $ssh_host; 56 skip "No netcat available", 14 unless (system("which nc > /dev/null") == 0);
18plan tests => 6;
19 57
58 # netcat on linux (on debian) will just keep the socket open if not advised otherwise
59 # therefore we add -q to close it after two seconds after receiving the EOF from input
60 my $nc_flags = "-l 5003 -N";
61 #A valid protocol version control string has the form
62 # SSH-protoversion-softwareversion SP comments CR LF
63 #
64 # where `comments` is optional, protoversion is the SSH protocol version and
65 # softwareversion is an arbitrary string representing the server software version
66 open(NC, "echo 'SSH-2.0-nagiosplug.ssh.0.1' | nc ${nc_flags}|");
67 sleep 0.1;
68 $res = NPTest->testCmd( "./check_ssh -H localhost -p 5003" );
69 cmp_ok( $res->return_code, '==', 0, "Got SSH protocol version control string");
70 like( $res->output, '/^SSH OK - nagiosplug.ssh.0.1 \(protocol 2.0\)/', "Output OK");
71 close NC;
20 72
21my $result = NPTest->testCmd( 73 open(NC, "echo 'SSH-2.0-3.2.9.1' | nc ${nc_flags}|");
22 "./check_ssh -H $ssh_host" 74 sleep 0.1;
23 ); 75 $res = NPTest->testCmd( "./check_ssh -H localhost -p 5003" );
24cmp_ok($result->return_code, '==', 0, "Exit with return code 0 (OK)"); 76 cmp_ok( $res->return_code, "==", 0, "Got SSH protocol version control string with non-alpha softwareversion string");
25like($result->output, '/^SSH OK - /', "Status text if command returned none (OK)"); 77 like( $res->output, '/^SSH OK - 3.2.9.1 \(protocol 2.0\)/', "Output OK for non-alpha softwareversion string");
78 close NC;
26 79
80 open(NC, "echo 'SSH-2.0-nagiosplug.ssh.0.1 this is a comment' | nc ${nc_flags} |");
81 sleep 0.1;
82 $res = NPTest->testCmd( "./check_ssh -H localhost -p 5003 -r nagiosplug.ssh.0.1" );
83 cmp_ok( $res->return_code, '==', 0, "Got SSH protocol version control string, and parsed comment appropriately");
84 like( $res->output, '/^SSH OK - nagiosplug.ssh.0.1 \(protocol 2.0\)/', "Output OK");
85 close NC;
27 86
28$result = NPTest->testCmd( 87 open(NC, "echo 'SSH-' | nc ${nc_flags}|");
29 "./check_ssh -H $host_nonresponsive -t 2" 88 sleep 0.1;
30 ); 89 $res = NPTest->testCmd( "./check_ssh -H localhost -p 5003" );
31cmp_ok($result->return_code, '==', 2, "Exit with return code 0 (OK)"); 90 cmp_ok( $res->return_code, '==', 2, "Got invalid SSH protocol version control string");
32like($result->output, '/^CRITICAL - Socket timeout after 2 seconds/', "Status text if command returned none (OK)"); 91 like( $res->output, '/^SSH CRITICAL/', "Output OK");
92 close NC;
33 93
94 open(NC, "echo '' | nc ${nc_flags}|");
95 sleep 0.1;
96 $res = NPTest->testCmd( "./check_ssh -H localhost -p 5003" );
97 cmp_ok( $res->return_code, '==', 2, "No version control string received");
98 like( $res->output, '/^SSH CRITICAL - No version control string received/', "Output OK");
99 close NC;
34 100
101 open(NC, "echo 'Not a version control string' | nc ${nc_flags}|");
102 sleep 0.1;
103 $res = NPTest->testCmd( "./check_ssh -H localhost -p 5003" );
104 cmp_ok( $res->return_code, '==', 2, "No version control string received");
105 like( $res->output, '/^SSH CRITICAL - No version control string received/', "Output OK");
106 close NC;
35 107
36$result = NPTest->testCmd(
37 "./check_ssh -H $hostname_invalid -t 2"
38 );
39cmp_ok($result->return_code, '==', 3, "Exit with return code 0 (OK)");
40like($result->output, '/^check_ssh: Invalid hostname/', "Status text if command returned none (OK)");
41 108
109 #RFC 4253 permits servers to send any number of data lines prior to sending the protocol version control string
110 open(NC, "{ echo 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'; sleep 0.5;
111 echo 'BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB'; sleep 0.5;
112 echo 'CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC'; sleep 0.2;
113 echo 'DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD'; sleep 0.3;
114 printf 'EEEEEEEEEEEEEEEEEE'; sleep 0.2;
115 printf 'EEEEEEEEEEEEEEEEEE\n'; sleep 0.2;
116 echo 'Some\nPrepended\nData\nLines\n'; sleep 0.2;
117 echo 'SSH-2.0-nagiosplug.ssh.0.2';} | nc ${nc_flags}|");
118 sleep 0.1;
119 $res = NPTest->testCmd( "./check_ssh -H localhost -p 5003" );
120 cmp_ok( $res->return_code, '==', 0, "Got delayed SSH protocol version control string");
121 like( $res->output, '/^SSH OK - nagiosplug.ssh.0.2 \(protocol 2.0\)/', "Output OK");
122 close NC;
123}
diff --git a/plugins/t/check_swap.t b/plugins/t/check_swap.t
index de9e0f05..18780386 100644
--- a/plugins/t/check_swap.t
+++ b/plugins/t/check_swap.t
@@ -5,7 +5,7 @@
5# 5#
6 6
7use strict; 7use strict;
8use Test::More tests => 8; 8use Test::More tests => 14;
9use NPTest; 9use NPTest;
10 10
11my $successOutput = '/^SWAP OK - [0-9]+\% free \([0-9]+MB out of [0-9]+MB\)/'; 11my $successOutput = '/^SWAP OK - [0-9]+\% free \([0-9]+MB out of [0-9]+MB\)/';
@@ -14,6 +14,10 @@ my $warnOutput = '/^SWAP WARNING - [0-9]+\% free \([0-9]+MB out of [0-9]+MB\)
14 14
15my $result; 15my $result;
16 16
17$result = NPTest->testCmd( "./check_swap" ); # Always OK
18cmp_ok( $result->return_code, "==", 0, "Always OK" );
19like( $result->output, $successOutput, "Right output" );
20
17$result = NPTest->testCmd( "./check_swap -w 1048576 -c 1048576" ); # 1 MB free 21$result = NPTest->testCmd( "./check_swap -w 1048576 -c 1048576" ); # 1 MB free
18cmp_ok( $result->return_code, "==", 0, "At least 1MB free" ); 22cmp_ok( $result->return_code, "==", 0, "At least 1MB free" );
19like( $result->output, $successOutput, "Right output" ); 23like( $result->output, $successOutput, "Right output" );
@@ -29,3 +33,11 @@ like( $result->output, $failureOutput, "Right output" );
29$result = NPTest->testCmd( "./check_swap -w 100% -c 1%" ); # 100% (always warn) 33$result = NPTest->testCmd( "./check_swap -w 100% -c 1%" ); # 100% (always warn)
30cmp_ok( $result->return_code, "==", 1, 'Get warning because not 100% free' ); 34cmp_ok( $result->return_code, "==", 1, 'Get warning because not 100% free' );
31like( $result->output, $warnOutput, "Right output" ); 35like( $result->output, $warnOutput, "Right output" );
36
37$result = NPTest->testCmd( "./check_swap -w 100%" ); # 100% (single threshold, always warn)
38cmp_ok( $result->return_code, "==", 1, 'Get warning because not 100% free' );
39like( $result->output, $warnOutput, "Right output" );
40
41$result = NPTest->testCmd( "./check_swap -c 100%" ); # 100% (single threshold, always critical)
42cmp_ok( $result->return_code, "==", 2, 'Get critical because not 100% free' );
43like( $result->output, $failureOutput, "Right output" );
diff --git a/plugins/tests/check_curl.t b/plugins/tests/check_curl.t
index 3c914830..eaa9f518 100755
--- a/plugins/tests/check_curl.t
+++ b/plugins/tests/check_curl.t
@@ -21,7 +21,7 @@ use FindBin qw($Bin);
21 21
22$ENV{'LC_TIME'} = "C"; 22$ENV{'LC_TIME'} = "C";
23 23
24my $common_tests = 73; 24my $common_tests = 75;
25my $ssl_only_tests = 8; 25my $ssl_only_tests = 8;
26# Check that all dependent modules are available 26# Check that all dependent modules are available
27eval "use HTTP::Daemon 6.01;"; 27eval "use HTTP::Daemon 6.01;";
@@ -178,6 +178,11 @@ sub run_server {
178 $c->send_basic_header; 178 $c->send_basic_header;
179 $c->send_crlf; 179 $c->send_crlf;
180 $c->send_response(HTTP::Response->new( 200, 'OK', undef, 'redirected' )); 180 $c->send_response(HTTP::Response->new( 200, 'OK', undef, 'redirected' ));
181 } elsif ($r->url->path eq "/redirect_rel") {
182 $c->send_basic_header(302);
183 $c->send_header("Location", "/redirect2" );
184 $c->send_crlf;
185 $c->send_response('moved to /redirect2');
181 } elsif ($r->url->path eq "/redir_timeout") { 186 } elsif ($r->url->path eq "/redir_timeout") {
182 $c->send_redirect( "/timeout" ); 187 $c->send_redirect( "/timeout" );
183 } elsif ($r->url->path eq "/timeout") { 188 } elsif ($r->url->path eq "/timeout") {
@@ -471,9 +476,12 @@ sub run_common_tests {
471 is( $result->return_code, 0, $cmd); 476 is( $result->return_code, 0, $cmd);
472 like( $result->output, '/^HTTP OK: HTTP/1.1 200 OK - \d+ bytes in [\d\.]+ second/', "Output correct: ".$result->output ); 477 like( $result->output, '/^HTTP OK: HTTP/1.1 200 OK - \d+ bytes in [\d\.]+ second/', "Output correct: ".$result->output );
473 478
474 # These tests may block 479 $cmd = "$command -f follow -u /redirect_rel -s redirected";
475 print "ALRM\n"; 480 $result = NPTest->testCmd( $cmd );
481 is( $result->return_code, 0, $cmd);
482 like( $result->output, '/^HTTP OK: HTTP/1.1 200 OK - \d+ bytes in [\d\.]+ second/', "Output correct: ".$result->output );
476 483
484 # These tests may block
477 # stickyport - on full urlS port is set back to 80 otherwise 485 # stickyport - on full urlS port is set back to 80 otherwise
478 $cmd = "$command -f stickyport -u /redir_external -t 5 -s redirected"; 486 $cmd = "$command -f stickyport -u /redir_external -t 5 -s redirected";
479 eval { 487 eval {
diff --git a/plugins/tests/check_http.t b/plugins/tests/check_http.t
index 6078b274..6eaf85b2 100755
--- a/plugins/tests/check_http.t
+++ b/plugins/tests/check_http.t
@@ -13,7 +13,7 @@ use IO::Socket::INET;
13 13
14$ENV{'LC_TIME'} = "C"; 14$ENV{'LC_TIME'} = "C";
15 15
16my $common_tests = 71; 16my $common_tests = 73;
17my $virtual_port_tests = 8; 17my $virtual_port_tests = 8;
18my $ssl_only_tests = 12; 18my $ssl_only_tests = 12;
19my $chunked_encoding_special_tests = 1; 19my $chunked_encoding_special_tests = 1;
@@ -199,6 +199,11 @@ sub run_server {
199 $c->send_basic_header; 199 $c->send_basic_header;
200 $c->send_crlf; 200 $c->send_crlf;
201 $c->send_response(HTTP::Response->new( 200, 'OK', undef, 'redirected' )); 201 $c->send_response(HTTP::Response->new( 200, 'OK', undef, 'redirected' ));
202 } elsif ($r->url->path eq "/redirect_rel") {
203 $c->send_basic_header(302);
204 $c->send_header("Location", "/redirect2" );
205 $c->send_crlf;
206 $c->send_response('moved to /redirect2');
202 } elsif ($r->url->path eq "/redir_timeout") { 207 } elsif ($r->url->path eq "/redir_timeout") {
203 $c->send_redirect( "/timeout" ); 208 $c->send_redirect( "/timeout" );
204 } elsif ($r->url->path eq "/timeout") { 209 } elsif ($r->url->path eq "/timeout") {
@@ -515,6 +520,11 @@ sub run_common_tests {
515 is( $result->return_code, 0, $cmd); 520 is( $result->return_code, 0, $cmd);
516 like( $result->output, '/^HTTP OK: HTTP/1.1 200 OK - \d+ bytes in [\d\.]+ second/', "Output correct: ".$result->output ); 521 like( $result->output, '/^HTTP OK: HTTP/1.1 200 OK - \d+ bytes in [\d\.]+ second/', "Output correct: ".$result->output );
517 522
523 $cmd = "$command -f follow -u /redirect_rel -s redirected";
524 $result = NPTest->testCmd( $cmd );
525 is( $result->return_code, 0, $cmd);
526 like( $result->output, '/^HTTP OK: HTTP/1.1 200 OK - \d+ bytes in [\d\.]+ second/', "Output correct: ".$result->output );
527
518 # These tests may block 528 # These tests may block
519 print "ALRM\n"; 529 print "ALRM\n";
520 530
diff --git a/plugins/urlize.c b/plugins/urlize.c
index 6fda72d1..1aa4e425 100644
--- a/plugins/urlize.c
+++ b/plugins/urlize.c
@@ -1,51 +1,49 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring urlize plugin 3 * Monitoring urlize plugin
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 2000-2007 Monitoring Plugins Development Team 6 * Copyright (c) 2000-2024 Monitoring Plugins Development Team
7* 7 *
8* Description: 8 * Description:
9* 9 *
10* This file contains the urlize plugin 10 * This file contains the urlize plugin
11* 11 *
12* This plugin wraps the text output of another command (plugin) in HTML <A> 12 * This plugin wraps the text output of another command (plugin) in HTML <A>
13* tags. This plugin returns the status of the invoked plugin. 13 * tags. This plugin returns the status of the invoked plugin.
14* 14 *
15* 15 *
16* This program is free software: you can redistribute it and/or modify 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 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 18 * the Free Software Foundation, either version 3 of the License, or
19* (at your option) any later version. 19 * (at your option) any later version.
20* 20 *
21* This program is distributed in the hope that it will be useful, 21 * This program is distributed in the hope that it will be useful,
22* but WITHOUT ANY WARRANTY; without even the implied warranty of 22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24* GNU General Public License for more details. 24 * GNU General Public License for more details.
25* 25 *
26* You should have received a copy of the GNU General Public License 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/>. 27 * along with this program. If not, see <http://www.gnu.org/licenses/>.
28* 28 *
29* 29 *
30*****************************************************************************/ 30 *****************************************************************************/
31 31
32const char *progname = "urlize"; 32const char *progname = "urlize";
33const char *copyright = "2000-2006"; 33const char *copyright = "2000-2024";
34const char *email = "devel@monitoring-plugins.org"; 34const char *email = "devel@monitoring-plugins.org";
35 35
36#include "common.h" 36#include "common.h"
37#include "utils.h" 37#include "utils.h"
38#include "popen.h" 38#include "popen.h"
39 39
40#define PERF_CHARACTER "|" 40#define PERF_CHARACTER "|"
41#define NEWLINE_CHARACTER '\n' 41#define NEWLINE_CHARACTER '\n'
42 42
43void print_help (void); 43void print_help(void);
44void print_usage (void); 44void print_usage(void);
45 45
46int 46int main(int argc, char **argv) {
47main (int argc, char **argv)
48{
49 int found = 0, result = STATE_UNKNOWN; 47 int found = 0, result = STATE_UNKNOWN;
50 char *url = NULL; 48 char *url = NULL;
51 char *cmd; 49 char *cmd;
@@ -56,79 +54,72 @@ main (int argc, char **argv)
56 int c; 54 int c;
57 int option = 0; 55 int option = 0;
58 static struct option longopts[] = { 56 static struct option longopts[] = {
59 {"help", no_argument, 0, 'h'}, 57 {"help", no_argument, 0, 'h'}, {"version", no_argument, 0, 'V'}, {"url", required_argument, 0, 'u'}, {0, 0, 0, 0}};
60 {"version", no_argument, 0, 'V'},
61 {"url", required_argument, 0, 'u'},
62 {0, 0, 0, 0}
63 };
64 58
65 setlocale (LC_ALL, ""); 59 setlocale(LC_ALL, "");
66 bindtextdomain (PACKAGE, LOCALEDIR); 60 bindtextdomain(PACKAGE, LOCALEDIR);
67 textdomain (PACKAGE); 61 textdomain(PACKAGE);
68 62
69 /* Need at least 2 args */ 63 /* Need at least 2 args */
70 if (argc < 3) { 64 if (argc < 3) {
71 print_help(); 65 print_help();
72 exit (STATE_UNKNOWN); 66 exit(STATE_UNKNOWN);
73 } 67 }
74 68
75 while (1) { 69 while (1) {
76 c = getopt_long (argc, argv, "+hVu:", longopts, &option); 70 c = getopt_long(argc, argv, "+hVu:", longopts, &option);
77 71
78 if (c == -1 || c == EOF) 72 if (c == -1 || c == EOF)
79 break; 73 break;
80 74
81 switch (c) { 75 switch (c) {
82 case 'h': /* help */ 76 case 'h': /* help */
83 print_help (); 77 print_help();
84 exit (EXIT_SUCCESS); 78 exit(EXIT_SUCCESS);
85 break; 79 break;
86 case 'V': /* version */ 80 case 'V': /* version */
87 print_revision (progname, NP_VERSION); 81 print_revision(progname, NP_VERSION);
88 exit (EXIT_SUCCESS); 82 exit(EXIT_SUCCESS);
89 break; 83 break;
90 case 'u': 84 case 'u':
91 url = strdup (argv[optind]); 85 url = strdup(argv[optind]);
92 break; 86 break;
93 case '?': 87 case '?':
94 default: 88 default:
95 usage5 (); 89 usage5();
96 } 90 }
97 } 91 }
98 92
99 if (url == NULL) 93 if (url == NULL)
100 url = strdup (argv[optind++]); 94 url = strdup(argv[optind++]);
101 95
102 cmd = strdup (argv[optind++]); 96 cmd = strdup(argv[optind++]);
103 for (c = optind; c < argc; c++) { 97 for (c = optind; c < argc; c++) {
104 xasprintf (&cmd, "%s %s", cmd, argv[c]); 98 xasprintf(&cmd, "%s %s", cmd, argv[c]);
105 } 99 }
106 100
107 child_process = spopen (cmd); 101 child_process = spopen(cmd);
108 if (child_process == NULL) { 102 if (child_process == NULL) {
109 printf (_("Could not open pipe: %s\n"), cmd); 103 printf(_("Could not open pipe: %s\n"), cmd);
110 exit (STATE_UNKNOWN); 104 exit(STATE_UNKNOWN);
111 } 105 }
112 106
113 child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r"); 107 child_stderr = fdopen(child_stderr_array[fileno(child_process)], "r");
114 if (child_stderr == NULL) { 108 if (child_stderr == NULL) {
115 printf (_("Could not open stderr for %s\n"), cmd); 109 printf(_("Could not open stderr for %s\n"), cmd);
116 } 110 }
117 111
118 bzero(tstr, sizeof(tstr)); 112 bzero(tstr, sizeof(tstr));
119 buf = malloc(MAX_INPUT_BUFFER); 113 buf = malloc(MAX_INPUT_BUFFER);
120 printf ("<A href=\"%s\">", argv[1]); 114 printf("<A href=\"%s\">", argv[1]);
121 while (fgets (buf, MAX_INPUT_BUFFER - 1, child_process)) { 115 while (fgets(buf, MAX_INPUT_BUFFER - 1, child_process)) {
122 found++; 116 found++;
123 /* Collect the string in temp str so we can tokenize */ 117 /* Collect the string in temp str so we can tokenize */
124 strcat(tstr, buf); 118 strcat(tstr, buf);
125 } 119 }
126 120
127 if (!found) 121 if (!found)
128 die (STATE_UNKNOWN, 122 die(STATE_UNKNOWN, _("%s UNKNOWN - No data received from host\nCMD: %s</A>\n"), argv[0], cmd);
129 _("%s UNKNOWN - No data received from host\nCMD: %s</A>\n"),
130 argv[0], cmd);
131
132 123
133 /* chop the newline character */ 124 /* chop the newline character */
134 if ((nstr = strchr(tstr, NEWLINE_CHARACTER)) != NULL) 125 if ((nstr = strchr(tstr, NEWLINE_CHARACTER)) != NULL)
@@ -136,63 +127,55 @@ main (int argc, char **argv)
136 127
137 /* tokenize the string for Perfdata if there is some */ 128 /* tokenize the string for Perfdata if there is some */
138 nstr = strtok(tstr, PERF_CHARACTER); 129 nstr = strtok(tstr, PERF_CHARACTER);
139 printf ("%s", nstr); 130 printf("%s", nstr);
140 printf ("</A>"); 131 printf("</A>");
141 nstr = strtok(NULL, PERF_CHARACTER); 132 nstr = strtok(NULL, PERF_CHARACTER);
142 if (nstr != NULL) 133 if (nstr != NULL)
143 printf (" | %s", nstr); 134 printf(" | %s", nstr);
144 135
145 /* close the pipe */ 136 /* close the pipe */
146 result = spclose (child_process); 137 result = spclose(child_process);
147 138
148 /* WARNING if output found on stderr */ 139 /* WARNING if output found on stderr */
149 if (fgets (buf, MAX_INPUT_BUFFER - 1, child_stderr)) 140 if (fgets(buf, MAX_INPUT_BUFFER - 1, child_stderr))
150 result = max_state (result, STATE_WARNING); 141 result = max_state(result, STATE_WARNING);
151 142
152 /* close stderr */ 143 /* close stderr */
153 (void) fclose (child_stderr); 144 (void)fclose(child_stderr);
154 145
155 return result; 146 return result;
156} 147}
157 148
149void print_help(void) {
150 print_revision(progname, NP_VERSION);
158 151
152 printf("Copyright (c) 2000 Karl DeBisschop <kdebisschop@users.sourceforge.net>\n");
153 printf(COPYRIGHT, copyright, email);
159 154
160void 155 printf("%s\n", _("This plugin wraps the text output of another command (plugin) in HTML <A>"));
161print_help (void) 156 printf("%s\n", _("tags, thus displaying the child plugin's output as a clickable link in compatible"));
162{ 157 printf("%s\n", _("monitoring status screen. This plugin returns the status of the invoked plugin."));
163 print_revision (progname, NP_VERSION);
164
165 printf ("Copyright (c) 2000 Karl DeBisschop <kdebisschop@users.sourceforge.net>\n");
166 printf (COPYRIGHT, copyright, email);
167
168 printf ("%s\n", _("This plugin wraps the text output of another command (plugin) in HTML <A>"));
169 printf ("%s\n", _("tags, thus displaying the child plugin's output as a clickable link in compatible"));
170 printf ("%s\n", _("monitoring status screen. This plugin returns the status of the invoked plugin."));
171 158
172 printf ("\n\n"); 159 printf("\n\n");
173 160
174 print_usage (); 161 print_usage();
175 162
176 printf (UT_HELP_VRSN); 163 printf(UT_HELP_VRSN);
177 164
178 printf ("\n"); 165 printf("\n");
179 printf ("%s\n", _("Examples:")); 166 printf("%s\n", _("Examples:"));
180 printf ("%s\n", _("Pay close attention to quoting to ensure that the shell passes the expected")); 167 printf("%s\n", _("Pay close attention to quoting to ensure that the shell passes the expected"));
181 printf ("%s\n\n", _("data to the plugin. For example, in:")); 168 printf("%s\n\n", _("data to the plugin. For example, in:"));
182 printf (" %s\n\n", _("urlize http://example.com/ check_http -H example.com -r 'two words'")); 169 printf(" %s\n\n", _("urlize http://example.com/ check_http -H example.com -r 'two words'"));
183 printf (" %s\n", _("the shell will remove the single quotes and urlize will see:")); 170 printf(" %s\n", _("the shell will remove the single quotes and urlize will see:"));
184 printf (" %s\n\n", _("urlize http://example.com/ check_http -H example.com -r two words")); 171 printf(" %s\n\n", _("urlize http://example.com/ check_http -H example.com -r two words"));
185 printf (" %s\n\n", _("You probably want:")); 172 printf(" %s\n\n", _("You probably want:"));
186 printf (" %s\n", _("urlize http://example.com/ \"check_http -H example.com -r 'two words'\"")); 173 printf(" %s\n", _("urlize http://example.com/ \"check_http -H example.com -r 'two words'\""));
187 174
188 printf (UT_SUPPORT); 175 printf(UT_SUPPORT);
189} 176}
190 177
191 178void print_usage(void) {
192 179 printf("%s\n", _("Usage:"));
193void 180 printf("%s <url> <plugin> <arg1> ... <argN>\n", progname);
194print_usage (void)
195{
196 printf ("%s\n", _("Usage:"));
197 printf ("%s <url> <plugin> <arg1> ... <argN>\n", progname);
198} 181}
diff --git a/plugins/utils.c b/plugins/utils.c
index aff17906..f11db731 100644
--- a/plugins/utils.c
+++ b/plugins/utils.c
@@ -1,38 +1,40 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Library of useful functions for plugins 3 * Library of useful functions for plugins
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 2000 Karl DeBisschop (karl@debisschop.net) 6 * Copyright (c) 2000 Karl DeBisschop (karl@debisschop.net)
7* Copyright (c) 2002-2007 Monitoring Plugins Development Team 7 * Copyright (c) 2002-2024 Monitoring Plugins Development Team
8* 8 *
9* This program is free software: you can redistribute it and/or modify 9 * This program is free software: you can redistribute it and/or modify
10* it under the terms of the GNU General Public License as published by 10 * it under the terms of the GNU General Public License as published by
11* the Free Software Foundation, either version 3 of the License, or 11 * the Free Software Foundation, either version 3 of the License, or
12* (at your option) any later version. 12 * (at your option) any later version.
13* 13 *
14* This program is distributed in the hope that it will be useful, 14 * This program is distributed in the hope that it will be useful,
15* but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17* GNU General Public License for more details. 17 * GNU General Public License for more details.
18* 18 *
19* You should have received a copy of the GNU General Public License 19 * You should have received a copy of the GNU General Public License
20* along with this program. If not, see <http://www.gnu.org/licenses/>. 20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21* 21 *
22* 22 *
23*****************************************************************************/ 23 *****************************************************************************/
24 24
25#include "common.h" 25#include "common.h"
26#include "utils.h" 26#include "./utils.h"
27#include "utils_base.h" 27#include "utils_base.h"
28#include <stdarg.h> 28#include <stdarg.h>
29#include <limits.h> 29#include <limits.h>
30#include <string.h> 30#include <string.h>
31#include <errno.h> 31#include <errno.h>
32 32
33#include <stdbool.h>
34
33#include <arpa/inet.h> 35#include <arpa/inet.h>
34 36
35extern void print_usage (void); 37extern void print_usage(void);
36extern const char *progname; 38extern const char *progname;
37 39
38#define STRLEN 64 40#define STRLEN 64
@@ -48,9 +50,7 @@ time_t start_time, end_time;
48 * Note that numerically the above does not hold 50 * Note that numerically the above does not hold
49 ****************************************************************************/ 51 ****************************************************************************/
50 52
51int 53int max_state(int a, int b) {
52max_state (int a, int b)
53{
54 if (a == STATE_CRITICAL || b == STATE_CRITICAL) 54 if (a == STATE_CRITICAL || b == STATE_CRITICAL)
55 return STATE_CRITICAL; 55 return STATE_CRITICAL;
56 else if (a == STATE_WARNING || b == STATE_WARNING) 56 else if (a == STATE_WARNING || b == STATE_WARNING)
@@ -62,7 +62,7 @@ max_state (int a, int b)
62 else if (a == STATE_DEPENDENT || b == STATE_DEPENDENT) 62 else if (a == STATE_DEPENDENT || b == STATE_DEPENDENT)
63 return STATE_DEPENDENT; 63 return STATE_DEPENDENT;
64 else 64 else
65 return max (a, b); 65 return max(a, b);
66} 66}
67 67
68/* ************************************************************************** 68/* **************************************************************************
@@ -75,9 +75,7 @@ max_state (int a, int b)
75 * non-OK state. 75 * non-OK state.
76 ****************************************************************************/ 76 ****************************************************************************/
77 77
78int 78int max_state_alt(int a, int b) {
79max_state_alt (int a, int b)
80{
81 if (a == STATE_CRITICAL || b == STATE_CRITICAL) 79 if (a == STATE_CRITICAL || b == STATE_CRITICAL)
82 return STATE_CRITICAL; 80 return STATE_CRITICAL;
83 else if (a == STATE_WARNING || b == STATE_WARNING) 81 else if (a == STATE_WARNING || b == STATE_WARNING)
@@ -89,112 +87,127 @@ max_state_alt (int a, int b)
89 else if (a == STATE_OK || b == STATE_OK) 87 else if (a == STATE_OK || b == STATE_OK)
90 return STATE_OK; 88 return STATE_OK;
91 else 89 else
92 return max (a, b); 90 return max(a, b);
93} 91}
94 92
95void usage (const char *msg) 93void usage(const char *msg) {
96{ 94 printf("%s\n", msg);
97 printf ("%s\n", msg); 95 print_usage();
98 print_usage (); 96 exit(STATE_UNKNOWN);
99 exit (STATE_UNKNOWN);
100} 97}
101 98
102void usage_va (const char *fmt, ...) 99void usage_va(const char *fmt, ...) {
103{
104 va_list ap; 100 va_list ap;
105 printf("%s: ", progname); 101 printf("%s: ", progname);
106 va_start(ap, fmt); 102 va_start(ap, fmt);
107 vprintf(fmt, ap); 103 vprintf(fmt, ap);
108 va_end(ap); 104 va_end(ap);
109 printf("\n"); 105 printf("\n");
110 exit (STATE_UNKNOWN); 106 exit(STATE_UNKNOWN);
111} 107}
112 108
113void usage2(const char *msg, const char *arg) 109void usage2(const char *msg, const char *arg) {
114{ 110 printf("%s: %s - %s\n", progname, msg, arg ? arg : "(null)");
115 printf ("%s: %s - %s\n", progname, msg, arg?arg:"(null)" ); 111 print_usage();
116 print_usage (); 112 exit(STATE_UNKNOWN);
117 exit (STATE_UNKNOWN);
118} 113}
119 114
120void 115void usage3(const char *msg, int arg) {
121usage3 (const char *msg, int arg) 116 printf("%s: %s - %c\n", progname, msg, arg);
122{
123 printf ("%s: %s - %c\n", progname, msg, arg);
124 print_usage(); 117 print_usage();
125 exit (STATE_UNKNOWN); 118 exit(STATE_UNKNOWN);
126} 119}
127 120
128void 121void usage4(const char *msg) {
129usage4 (const char *msg) 122 printf("%s: %s\n", progname, msg);
130{
131 printf ("%s: %s\n", progname, msg);
132 print_usage(); 123 print_usage();
133 exit (STATE_UNKNOWN); 124 exit(STATE_UNKNOWN);
134} 125}
135 126
136void 127void usage5(void) {
137usage5 (void)
138{
139 print_usage(); 128 print_usage();
140 exit (STATE_UNKNOWN); 129 exit(STATE_UNKNOWN);
141} 130}
142 131
143void 132void print_revision(const char *command_name, const char *revision) {
144print_revision (const char *command_name, const char *revision) 133 printf("%s v%s (%s %s)\n", command_name, revision, PACKAGE, VERSION);
145{
146 printf ("%s v%s (%s %s)\n",
147 command_name, revision, PACKAGE, VERSION);
148} 134}
149 135
150bool is_numeric (char *number) { 136bool is_numeric(char *number) {
151 char tmp[1]; 137 char tmp[1];
152 float x; 138 float x;
153 139
154 if (!number) 140 if (!number)
155 return false; 141 return false;
156 else if (sscanf (number, "%f%c", &x, tmp) == 1) 142 else if (sscanf(number, "%f%c", &x, tmp) == 1)
157 return true; 143 return true;
158 else 144 else
159 return false; 145 return false;
160} 146}
161 147
162bool is_positive (char *number) { 148bool is_positive(char *number) {
163 if (is_numeric (number) && atof (number) > 0.0) 149 if (is_numeric(number) && atof(number) > 0.0)
164 return true; 150 return true;
165 else 151 else
166 return false; 152 return false;
167} 153}
168 154
169bool is_negative (char *number) { 155bool is_negative(char *number) {
170 if (is_numeric (number) && atof (number) < 0.0) 156 if (is_numeric(number) && atof(number) < 0.0)
171 return true; 157 return true;
172 else 158 else
173 return false; 159 return false;
174} 160}
175 161
176bool is_nonnegative (char *number) { 162bool is_nonnegative(char *number) {
177 if (is_numeric (number) && atof (number) >= 0.0) 163 if (is_numeric(number) && atof(number) >= 0.0)
178 return true; 164 return true;
179 else 165 else
180 return false; 166 return false;
181} 167}
182 168
183bool is_percentage (char *number) { 169bool is_percentage(char *number) {
184 int x; 170 int x;
185 if (is_numeric (number) && (x = atof (number)) >= 0 && x <= 100) 171 if (is_numeric(number) && (x = atof(number)) >= 0 && x <= 100)
186 return true; 172 return true;
187 else 173 else
188 return false; 174 return false;
189} 175}
190 176
191bool is_integer (char *number) { 177bool is_percentage_expression(const char str[]) {
178 if (!str) {
179 return false;
180 }
181
182 size_t len = strlen(str);
183
184 if (str[len - 1] != '%') {
185 return false;
186 }
187
188 char *foo = calloc(sizeof(char), len + 1);
189
190 if (!foo) {
191 die(STATE_UNKNOWN, _("calloc failed \n"));
192 }
193
194 strcpy(foo, str);
195 foo[len - 1] = '\0';
196
197 bool result = is_numeric(foo);
198
199 free(foo);
200
201 return result;
202}
203
204bool is_integer(char *number) {
192 long int n; 205 long int n;
193 206
194 if (!number || (strspn (number, "-0123456789 ") != strlen (number))) 207 if (!number || (strspn(number, "-0123456789 ") != strlen(number)))
195 return false; 208 return false;
196 209
197 n = strtol (number, NULL, 10); 210 n = strtol(number, NULL, 10);
198 211
199 if (errno != ERANGE && n >= INT_MIN && n <= INT_MAX) 212 if (errno != ERANGE && n >= INT_MIN && n <= INT_MAX)
200 return true; 213 return true;
@@ -202,22 +215,22 @@ bool is_integer (char *number) {
202 return false; 215 return false;
203} 216}
204 217
205bool is_intpos (char *number) { 218bool is_intpos(char *number) {
206 if (is_integer (number) && atoi (number) > 0) 219 if (is_integer(number) && atoi(number) > 0)
207 return true; 220 return true;
208 else 221 else
209 return false; 222 return false;
210} 223}
211 224
212bool is_intneg (char *number) { 225bool is_intneg(char *number) {
213 if (is_integer (number) && atoi (number) < 0) 226 if (is_integer(number) && atoi(number) < 0)
214 return true; 227 return true;
215 else 228 else
216 return false; 229 return false;
217} 230}
218 231
219bool is_intnonneg (char *number) { 232bool is_intnonneg(char *number) {
220 if (is_integer (number) && atoi (number) >= 0) 233 if (is_integer(number) && atoi(number) >= 0)
221 return true; 234 return true;
222 else 235 else
223 return false; 236 return false;
@@ -230,7 +243,7 @@ bool is_intnonneg (char *number) {
230 */ 243 */
231bool is_int64(char *number, int64_t *target) { 244bool is_int64(char *number, int64_t *target) {
232 errno = 0; 245 errno = 0;
233 char *endptr = { 0 }; 246 char *endptr = {0};
234 247
235 int64_t tmp = strtoll(number, &endptr, 10); 248 int64_t tmp = strtoll(number, &endptr, 10);
236 if (errno != 0) { 249 if (errno != 0) {
@@ -258,7 +271,7 @@ bool is_int64(char *number, int64_t *target) {
258 */ 271 */
259bool is_uint64(char *number, uint64_t *target) { 272bool is_uint64(char *number, uint64_t *target) {
260 errno = 0; 273 errno = 0;
261 char *endptr = { 0 }; 274 char *endptr = {0};
262 unsigned long long tmp = strtoull(number, &endptr, 10); 275 unsigned long long tmp = strtoull(number, &endptr, 10);
263 276
264 if (errno != 0) { 277 if (errno != 0) {
@@ -280,66 +293,50 @@ bool is_uint64(char *number, uint64_t *target) {
280 return true; 293 return true;
281} 294}
282 295
283bool is_intpercent (char *number) { 296bool is_intpercent(char *number) {
284 int i; 297 int i;
285 if (is_integer (number) && (i = atoi (number)) >= 0 && i <= 100) 298 if (is_integer(number) && (i = atoi(number)) >= 0 && i <= 100)
286 return true; 299 return true;
287 else 300 else
288 return false; 301 return false;
289} 302}
290 303
291bool is_option (char *str) { 304bool is_option(char *str) {
292 if (!str) 305 if (!str)
293 return false; 306 return false;
294 else if (strspn (str, "-") == 1 || strspn (str, "-") == 2) 307 else if (strspn(str, "-") == 1 || strspn(str, "-") == 2)
295 return true; 308 return true;
296 else 309 else
297 return false; 310 return false;
298} 311}
299 312
300#ifdef NEED_GETTIMEOFDAY 313#ifdef NEED_GETTIMEOFDAY
301int 314int gettimeofday(struct timeval *tv, struct timezone *tz) {
302gettimeofday (struct timeval *tv, struct timezone *tz)
303{
304 tv->tv_usec = 0; 315 tv->tv_usec = 0;
305 tv->tv_sec = (long) time ((time_t) 0); 316 tv->tv_sec = (long)time((time_t)0);
306} 317}
307#endif 318#endif
308 319
309 320double delta_time(struct timeval tv) {
310
311double
312delta_time (struct timeval tv)
313{
314 struct timeval now; 321 struct timeval now;
315 322
316 gettimeofday (&now, NULL); 323 gettimeofday(&now, NULL);
317 return ((double)(now.tv_sec - tv.tv_sec) + (double)(now.tv_usec - tv.tv_usec) / (double)1000000); 324 return ((double)(now.tv_sec - tv.tv_sec) + (double)(now.tv_usec - tv.tv_usec) / (double)1000000);
318} 325}
319 326
320 327long deltime(struct timeval tv) {
321
322long
323deltime (struct timeval tv)
324{
325 struct timeval now; 328 struct timeval now;
326 gettimeofday (&now, NULL); 329 gettimeofday(&now, NULL);
327 return (now.tv_sec - tv.tv_sec)*1000000 + now.tv_usec - tv.tv_usec; 330 return (now.tv_sec - tv.tv_sec) * 1000000 + now.tv_usec - tv.tv_usec;
328} 331}
329 332
330 333void strip(char *buffer) {
331
332
333void
334strip (char *buffer)
335{
336 size_t x; 334 size_t x;
337 int i; 335 int i;
338 336
339 for (x = strlen (buffer); x >= 1; x--) { 337 for (x = strlen(buffer); x >= 1; x--) {
340 i = x - 1; 338 i = x - 1;
341 if (buffer[i] == ' ' || 339 if (buffer[i] == ' ' || buffer[i] == '\r' || buffer[i] == '\n' || buffer[i] == '\t')
342 buffer[i] == '\r' || buffer[i] == '\n' || buffer[i] == '\t')
343 buffer[i] = '\0'; 340 buffer[i] = '\0';
344 else 341 else
345 break; 342 break;
@@ -347,7 +344,6 @@ strip (char *buffer)
347 return; 344 return;
348} 345}
349 346
350
351/****************************************************************************** 347/******************************************************************************
352 * 348 *
353 * Copies one string to another. Any previously existing data in 349 * Copies one string to another. Any previously existing data in
@@ -360,19 +356,15 @@ strip (char *buffer)
360 * 356 *
361 *****************************************************************************/ 357 *****************************************************************************/
362 358
363char * 359char *strscpy(char *dest, const char *src) {
364strscpy (char *dest, const char *src)
365{
366 if (src == NULL) 360 if (src == NULL)
367 return NULL; 361 return NULL;
368 362
369 xasprintf (&dest, "%s", src); 363 xasprintf(&dest, "%s", src);
370 364
371 return dest; 365 return dest;
372} 366}
373 367
374
375
376/****************************************************************************** 368/******************************************************************************
377 * 369 *
378 * Returns a pointer to the next line of a multiline string buffer 370 * Returns a pointer to the next line of a multiline string buffer
@@ -389,7 +381,7 @@ strscpy (char *dest, const char *src)
389 * This 381 * This
390 * is 382 * is
391 * a 383 * a
392 * 384 *
393 * multiline string buffer 385 * multiline string buffer
394 * ============================== 386 * ==============================
395 * 387 *
@@ -402,7 +394,7 @@ strscpy (char *dest, const char *src)
402 * printf("%d %s",i++,firstword(ptr)); 394 * printf("%d %s",i++,firstword(ptr));
403 * ptr = strnl(ptr); 395 * ptr = strnl(ptr);
404 * } 396 * }
405 * 397 *
406 * Produces the following: 398 * Produces the following:
407 * 399 *
408 * 1 This 400 * 1 This
@@ -423,25 +415,22 @@ strscpy (char *dest, const char *src)
423 * 415 *
424 *****************************************************************************/ 416 *****************************************************************************/
425 417
426char * 418char *strnl(char *str) {
427strnl (char *str)
428{
429 size_t len; 419 size_t len;
430 if (str == NULL) 420 if (str == NULL)
431 return NULL; 421 return NULL;
432 str = strpbrk (str, "\r\n"); 422 str = strpbrk(str, "\r\n");
433 if (str == NULL) 423 if (str == NULL)
434 return NULL; 424 return NULL;
435 len = strspn (str, "\r\n"); 425 len = strspn(str, "\r\n");
436 if (str[len] == '\0') 426 if (str[len] == '\0')
437 return NULL; 427 return NULL;
438 str += len; 428 str += len;
439 if (strlen (str) == 0) 429 if (strlen(str) == 0)
440 return NULL; 430 return NULL;
441 return str; 431 return str;
442} 432}
443 433
444
445/****************************************************************************** 434/******************************************************************************
446 * 435 *
447 * Like strscpy, except only the portion of the source string up to 436 * Like strscpy, except only the portion of the source string up to
@@ -458,29 +447,25 @@ strnl (char *str)
458 * 447 *
459 *****************************************************************************/ 448 *****************************************************************************/
460 449
461char * 450char *strpcpy(char *dest, const char *src, const char *str) {
462strpcpy (char *dest, const char *src, const char *str)
463{
464 size_t len; 451 size_t len;
465 452
466 if (src) 453 if (src)
467 len = strcspn (src, str); 454 len = strcspn(src, str);
468 else 455 else
469 return NULL; 456 return NULL;
470 457
471 if (dest == NULL || strlen (dest) < len) 458 if (dest == NULL || strlen(dest) < len)
472 dest = realloc (dest, len + 1); 459 dest = realloc(dest, len + 1);
473 if (dest == NULL) 460 if (dest == NULL)
474 die (STATE_UNKNOWN, _("failed realloc in strpcpy\n")); 461 die(STATE_UNKNOWN, _("failed realloc in strpcpy\n"));
475 462
476 strncpy (dest, src, len); 463 strncpy(dest, src, len);
477 dest[len] = '\0'; 464 dest[len] = '\0';
478 465
479 return dest; 466 return dest;
480} 467}
481 468
482
483
484/****************************************************************************** 469/******************************************************************************
485 * 470 *
486 * Like strscat, except only the portion of the source string up to 471 * Like strscat, except only the portion of the source string up to
@@ -489,62 +474,54 @@ strpcpy (char *dest, const char *src, const char *str)
489 * str = strpcpy(str,"This is a line of text with no trailing newline","x"); 474 * str = strpcpy(str,"This is a line of text with no trailing newline","x");
490 * str = strpcat(str,"This is a line of text with no trailing newline","x"); 475 * str = strpcat(str,"This is a line of text with no trailing newline","x");
491 * printf("%s\n",str); 476 * printf("%s\n",str);
492 * 477 *
493 *This is a line of texThis is a line of tex 478 *This is a line of texThis is a line of tex
494 * 479 *
495 *****************************************************************************/ 480 *****************************************************************************/
496 481
497char * 482char *strpcat(char *dest, const char *src, const char *str) {
498strpcat (char *dest, const char *src, const char *str)
499{
500 size_t len, l2; 483 size_t len, l2;
501 484
502 if (dest) 485 if (dest)
503 len = strlen (dest); 486 len = strlen(dest);
504 else 487 else
505 len = 0; 488 len = 0;
506 489
507 if (src) { 490 if (src) {
508 l2 = strcspn (src, str); 491 l2 = strcspn(src, str);
509 } 492 } else {
510 else {
511 return dest; 493 return dest;
512 } 494 }
513 495
514 dest = realloc (dest, len + l2 + 1); 496 dest = realloc(dest, len + l2 + 1);
515 if (dest == NULL) 497 if (dest == NULL)
516 die (STATE_UNKNOWN, _("failed malloc in strscat\n")); 498 die(STATE_UNKNOWN, _("failed malloc in strscat\n"));
517 499
518 strncpy (dest + len, src, l2); 500 strncpy(dest + len, src, l2);
519 dest[len + l2] = '\0'; 501 dest[len + l2] = '\0';
520 502
521 return dest; 503 return dest;
522} 504}
523 505
524
525/****************************************************************************** 506/******************************************************************************
526 * 507 *
527 * asprintf, but die on failure 508 * asprintf, but die on failure
528 * 509 *
529 ******************************************************************************/ 510 ******************************************************************************/
530 511
531int 512int xvasprintf(char **strp, const char *fmt, va_list ap) {
532xvasprintf (char **strp, const char *fmt, va_list ap) 513 int result = vasprintf(strp, fmt, ap);
533{
534 int result = vasprintf (strp, fmt, ap);
535 if (result == -1 || *strp == NULL) 514 if (result == -1 || *strp == NULL)
536 die (STATE_UNKNOWN, _("failed malloc in xvasprintf\n")); 515 die(STATE_UNKNOWN, _("failed malloc in xvasprintf\n"));
537 return result; 516 return result;
538} 517}
539 518
540int 519int xasprintf(char **strp, const char *fmt, ...) {
541xasprintf (char **strp, const char *fmt, ...)
542{
543 va_list ap; 520 va_list ap;
544 int result; 521 int result;
545 va_start (ap, fmt); 522 va_start(ap, fmt);
546 result = xvasprintf (strp, fmt, ap); 523 result = xvasprintf(strp, fmt, ap);
547 va_end (ap); 524 va_end(ap);
548 return result; 525 return result;
549} 526}
550 527
@@ -554,247 +531,192 @@ xasprintf (char **strp, const char *fmt, ...)
554 * 531 *
555 ******************************************************************************/ 532 ******************************************************************************/
556 533
557char *perfdata (const char *label, 534char *perfdata(const char *label, long int val, const char *uom, int warnp, long int warn, int critp, long int crit, int minp,
558 long int val, 535 long int minv, int maxp, long int maxv) {
559 const char *uom,
560 int warnp,
561 long int warn,
562 int critp,
563 long int crit,
564 int minp,
565 long int minv,
566 int maxp,
567 long int maxv)
568{
569 char *data = NULL; 536 char *data = NULL;
570 537
571 if (strpbrk (label, "'= ")) 538 if (strpbrk(label, "'= "))
572 xasprintf (&data, "'%s'=%ld%s;", label, val, uom); 539 xasprintf(&data, "'%s'=%ld%s;", label, val, uom);
573 else 540 else
574 xasprintf (&data, "%s=%ld%s;", label, val, uom); 541 xasprintf(&data, "%s=%ld%s;", label, val, uom);
575 542
576 if (warnp) 543 if (warnp)
577 xasprintf (&data, "%s%ld;", data, warn); 544 xasprintf(&data, "%s%ld;", data, warn);
578 else 545 else
579 xasprintf (&data, "%s;", data); 546 xasprintf(&data, "%s;", data);
580 547
581 if (critp) 548 if (critp)
582 xasprintf (&data, "%s%ld;", data, crit); 549 xasprintf(&data, "%s%ld;", data, crit);
583 else 550 else
584 xasprintf (&data, "%s;", data); 551 xasprintf(&data, "%s;", data);
585 552
586 if (minp) 553 if (minp)
587 xasprintf (&data, "%s%ld;", data, minv); 554 xasprintf(&data, "%s%ld;", data, minv);
588 else 555 else
589 xasprintf (&data, "%s;", data); 556 xasprintf(&data, "%s;", data);
590 557
591 if (maxp) 558 if (maxp)
592 xasprintf (&data, "%s%ld", data, maxv); 559 xasprintf(&data, "%s%ld", data, maxv);
593 560
594 return data; 561 return data;
595} 562}
596 563
597 564char *perfdata_uint64(const char *label, uint64_t val, const char *uom, int warnp, /* Warning present */
598char *perfdata_uint64 (const char *label, 565 uint64_t warn, int critp, /* Critical present */
599 uint64_t val, 566 uint64_t crit, int minp, /* Minimum present */
600 const char *uom, 567 uint64_t minv, int maxp, /* Maximum present */
601 int warnp, /* Warning present */ 568 uint64_t maxv) {
602 uint64_t warn,
603 int critp, /* Critical present */
604 uint64_t crit,
605 int minp, /* Minimum present */
606 uint64_t minv,
607 int maxp, /* Maximum present */
608 uint64_t maxv)
609{
610 char *data = NULL; 569 char *data = NULL;
611 570
612 if (strpbrk (label, "'= ")) 571 if (strpbrk(label, "'= "))
613 xasprintf (&data, "'%s'=%" PRIu64 "%s;", label, val, uom); 572 xasprintf(&data, "'%s'=%" PRIu64 "%s;", label, val, uom);
614 else 573 else
615 xasprintf (&data, "%s=%" PRIu64 "%s;", label, val, uom); 574 xasprintf(&data, "%s=%" PRIu64 "%s;", label, val, uom);
616 575
617 if (warnp) 576 if (warnp)
618 xasprintf (&data, "%s%" PRIu64 ";", data, warn); 577 xasprintf(&data, "%s%" PRIu64 ";", data, warn);
619 else 578 else
620 xasprintf (&data, "%s;", data); 579 xasprintf(&data, "%s;", data);
621 580
622 if (critp) 581 if (critp)
623 xasprintf (&data, "%s%" PRIu64 ";", data, crit); 582 xasprintf(&data, "%s%" PRIu64 ";", data, crit);
624 else 583 else
625 xasprintf (&data, "%s;", data); 584 xasprintf(&data, "%s;", data);
626 585
627 if (minp) 586 if (minp)
628 xasprintf (&data, "%s%" PRIu64 ";", data, minv); 587 xasprintf(&data, "%s%" PRIu64 ";", data, minv);
629 else 588 else
630 xasprintf (&data, "%s;", data); 589 xasprintf(&data, "%s;", data);
631 590
632 if (maxp) 591 if (maxp)
633 xasprintf (&data, "%s%" PRIu64, data, maxv); 592 xasprintf(&data, "%s%" PRIu64, data, maxv);
634 593
635 return data; 594 return data;
636} 595}
637 596
638 597char *perfdata_int64(const char *label, int64_t val, const char *uom, int warnp, /* Warning present */
639char *perfdata_int64 (const char *label, 598 int64_t warn, int critp, /* Critical present */
640 int64_t val, 599 int64_t crit, int minp, /* Minimum present */
641 const char *uom, 600 int64_t minv, int maxp, /* Maximum present */
642 int warnp, /* Warning present */ 601 int64_t maxv) {
643 int64_t warn,
644 int critp, /* Critical present */
645 int64_t crit,
646 int minp, /* Minimum present */
647 int64_t minv,
648 int maxp, /* Maximum present */
649 int64_t maxv)
650{
651 char *data = NULL; 602 char *data = NULL;
652 603
653 if (strpbrk (label, "'= ")) 604 if (strpbrk(label, "'= "))
654 xasprintf (&data, "'%s'=%" PRId64 "%s;", label, val, uom); 605 xasprintf(&data, "'%s'=%" PRId64 "%s;", label, val, uom);
655 else 606 else
656 xasprintf (&data, "%s=%" PRId64 "%s;", label, val, uom); 607 xasprintf(&data, "%s=%" PRId64 "%s;", label, val, uom);
657 608
658 if (warnp) 609 if (warnp)
659 xasprintf (&data, "%s%" PRId64 ";", data, warn); 610 xasprintf(&data, "%s%" PRId64 ";", data, warn);
660 else 611 else
661 xasprintf (&data, "%s;", data); 612 xasprintf(&data, "%s;", data);
662 613
663 if (critp) 614 if (critp)
664 xasprintf (&data, "%s%" PRId64 ";", data, crit); 615 xasprintf(&data, "%s%" PRId64 ";", data, crit);
665 else 616 else
666 xasprintf (&data, "%s;", data); 617 xasprintf(&data, "%s;", data);
667 618
668 if (minp) 619 if (minp)
669 xasprintf (&data, "%s%" PRId64 ";", data, minv); 620 xasprintf(&data, "%s%" PRId64 ";", data, minv);
670 else 621 else
671 xasprintf (&data, "%s;", data); 622 xasprintf(&data, "%s;", data);
672 623
673 if (maxp) 624 if (maxp)
674 xasprintf (&data, "%s%" PRId64, data, maxv); 625 xasprintf(&data, "%s%" PRId64, data, maxv);
675 626
676 return data; 627 return data;
677} 628}
678 629
679 630char *fperfdata(const char *label, double val, const char *uom, int warnp, double warn, int critp, double crit, int minp, double minv,
680char *fperfdata (const char *label, 631 int maxp, double maxv) {
681 double val,
682 const char *uom,
683 int warnp,
684 double warn,
685 int critp,
686 double crit,
687 int minp,
688 double minv,
689 int maxp,
690 double maxv)
691{
692 char *data = NULL; 632 char *data = NULL;
693 633
694 if (strpbrk (label, "'= ")) 634 if (strpbrk(label, "'= "))
695 xasprintf (&data, "'%s'=", label); 635 xasprintf(&data, "'%s'=", label);
696 else 636 else
697 xasprintf (&data, "%s=", label); 637 xasprintf(&data, "%s=", label);
698 638
699 xasprintf (&data, "%s%f", data, val); 639 xasprintf(&data, "%s%f", data, val);
700 xasprintf (&data, "%s%s;", data, uom); 640 xasprintf(&data, "%s%s;", data, uom);
701 641
702 if (warnp) 642 if (warnp)
703 xasprintf (&data, "%s%f", data, warn); 643 xasprintf(&data, "%s%f", data, warn);
704 644
705 xasprintf (&data, "%s;", data); 645 xasprintf(&data, "%s;", data);
706 646
707 if (critp) 647 if (critp)
708 xasprintf (&data, "%s%f", data, crit); 648 xasprintf(&data, "%s%f", data, crit);
709 649
710 xasprintf (&data, "%s;", data); 650 xasprintf(&data, "%s;", data);
711 651
712 if (minp) 652 if (minp)
713 xasprintf (&data, "%s%f", data, minv); 653 xasprintf(&data, "%s%f", data, minv);
714 654
715 if (maxp) { 655 if (maxp) {
716 xasprintf (&data, "%s;", data); 656 xasprintf(&data, "%s;", data);
717 xasprintf (&data, "%s%f", data, maxv); 657 xasprintf(&data, "%s%f", data, maxv);
718 } 658 }
719 659
720 return data; 660 return data;
721} 661}
722 662
723char *sperfdata (const char *label, 663char *sperfdata(const char *label, double val, const char *uom, char *warn, char *crit, int minp, double minv, int maxp, double maxv) {
724 double val,
725 const char *uom,
726 char *warn,
727 char *crit,
728 int minp,
729 double minv,
730 int maxp,
731 double maxv)
732{
733 char *data = NULL; 664 char *data = NULL;
734 if (strpbrk (label, "'= ")) 665 if (strpbrk(label, "'= "))
735 xasprintf (&data, "'%s'=", label); 666 xasprintf(&data, "'%s'=", label);
736 else 667 else
737 xasprintf (&data, "%s=", label); 668 xasprintf(&data, "%s=", label);
738 669
739 xasprintf (&data, "%s%f", data, val); 670 xasprintf(&data, "%s%f", data, val);
740 xasprintf (&data, "%s%s;", data, uom); 671 xasprintf(&data, "%s%s;", data, uom);
741 672
742 if (warn!=NULL) 673 if (warn != NULL)
743 xasprintf (&data, "%s%s", data, warn); 674 xasprintf(&data, "%s%s", data, warn);
744 675
745 xasprintf (&data, "%s;", data); 676 xasprintf(&data, "%s;", data);
746 677
747 if (crit!=NULL) 678 if (crit != NULL)
748 xasprintf (&data, "%s%s", data, crit); 679 xasprintf(&data, "%s%s", data, crit);
749 680
750 xasprintf (&data, "%s;", data); 681 xasprintf(&data, "%s;", data);
751 682
752 if (minp) 683 if (minp)
753 xasprintf (&data, "%s%f", data, minv); 684 xasprintf(&data, "%s%f", data, minv);
754 685
755 if (maxp) { 686 if (maxp) {
756 xasprintf (&data, "%s;", data); 687 xasprintf(&data, "%s;", data);
757 xasprintf (&data, "%s%f", data, maxv); 688 xasprintf(&data, "%s%f", data, maxv);
758 } 689 }
759 690
760 return data; 691 return data;
761} 692}
762 693
763char *sperfdata_int (const char *label, 694char *sperfdata_int(const char *label, int val, const char *uom, char *warn, char *crit, int minp, int minv, int maxp, int maxv) {
764 int val,
765 const char *uom,
766 char *warn,
767 char *crit,
768 int minp,
769 int minv,
770 int maxp,
771 int maxv)
772{
773 char *data = NULL; 695 char *data = NULL;
774 if (strpbrk (label, "'= ")) 696 if (strpbrk(label, "'= "))
775 xasprintf (&data, "'%s'=", label); 697 xasprintf(&data, "'%s'=", label);
776 else 698 else
777 xasprintf (&data, "%s=", label); 699 xasprintf(&data, "%s=", label);
778 700
779 xasprintf (&data, "%s%d", data, val); 701 xasprintf(&data, "%s%d", data, val);
780 xasprintf (&data, "%s%s;", data, uom); 702 xasprintf(&data, "%s%s;", data, uom);
781 703
782 if (warn!=NULL) 704 if (warn != NULL)
783 xasprintf (&data, "%s%s", data, warn); 705 xasprintf(&data, "%s%s", data, warn);
784 706
785 xasprintf (&data, "%s;", data); 707 xasprintf(&data, "%s;", data);
786 708
787 if (crit!=NULL) 709 if (crit != NULL)
788 xasprintf (&data, "%s%s", data, crit); 710 xasprintf(&data, "%s%s", data, crit);
789 711
790 xasprintf (&data, "%s;", data); 712 xasprintf(&data, "%s;", data);
791 713
792 if (minp) 714 if (minp)
793 xasprintf (&data, "%s%d", data, minv); 715 xasprintf(&data, "%s%d", data, minv);
794 716
795 if (maxp) { 717 if (maxp) {
796 xasprintf (&data, "%s;", data); 718 xasprintf(&data, "%s;", data);
797 xasprintf (&data, "%s%d", data, maxv); 719 xasprintf(&data, "%s%d", data, maxv);
798 } 720 }
799 721
800 return data; 722 return data;
diff --git a/plugins/utils.h b/plugins/utils.h
index 62e489be..f939e337 100644
--- a/plugins/utils.h
+++ b/plugins/utils.h
@@ -49,6 +49,7 @@ bool is_positive (char *);
49bool is_negative (char *); 49bool is_negative (char *);
50bool is_nonnegative (char *); 50bool is_nonnegative (char *);
51bool is_percentage (char *); 51bool is_percentage (char *);
52bool is_percentage_expression (const char[]);
52 53
53bool is_option (char *); 54bool is_option (char *);
54 55