summaryrefslogtreecommitdiffstats
path: root/plugins
diff options
context:
space:
mode:
authorLorenz Kästle <12514511+RincewindsHat@users.noreply.github.com>2024-10-31 13:57:43 (GMT)
committerGitHub <noreply@github.com>2024-10-31 13:57:43 (GMT)
commitb1d260a821b7d4916d6bf1a026fbc9b4f2b268ae (patch)
tree84a3fc6b26b181a1ed10d7ca55c32ac9170efbd4 /plugins
parentb4c5956591e9741ce9b190210e7b10940a6adbdd (diff)
parent8955f56de355403941bc8f02a4edb2bc72d1397a (diff)
downloadmonitoring-plugins-b1d260a821b7d4916d6bf1a026fbc9b4f2b268ae.tar.gz
Merge pull request #2035 from RincewindsHat/cleanup/rest-of-plugins
Cleanup for some more plugins
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.c4596
-rw-r--r--plugins/check_dbi.c827
-rw-r--r--plugins/check_dig.c650
-rw-r--r--plugins/check_disk.c1971
-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.c4
-rw-r--r--plugins/check_ide_smart.c496
-rw-r--r--plugins/check_ldap.c4
-rw-r--r--plugins/check_mrtg.c456
-rw-r--r--plugins/check_mrtgtraf.c457
-rw-r--r--plugins/check_mysql.c4
-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.c2137
-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.c1265
-rw-r--r--plugins/check_ssh.c4
-rw-r--r--plugins/check_tcp.c598
-rw-r--r--plugins/check_time.c431
-rw-r--r--plugins/check_ups.c8
-rw-r--r--plugins/check_users.c291
-rw-r--r--plugins/negate.c298
-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/urlize.c195
-rw-r--r--plugins/utils.c509
46 files changed, 12417 insertions, 13914 deletions
diff --git a/plugins/check_apt.c b/plugins/check_apt.c
index 5c0f6e2..5e4021b 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 2a23b39..905b239 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 e1ede9f..b40c38c 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 d3bddac..1d27da2 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,1107 +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;
137int state_regex = STATE_CRITICAL; 137static int state_regex = STATE_CRITICAL;
138 138
139char *server_address = NULL; 139static char *server_address = NULL;
140char *host_name = NULL; 140static char *host_name = NULL;
141char *server_url = 0; 141static char *server_url = 0;
142char server_ip[DEFAULT_BUFFER_SIZE]; 142static struct curl_slist *server_ips = NULL;
143struct curl_slist *server_ips = NULL; 143static bool specify_port = false;
144bool specify_port = false; 144static unsigned short server_port = HTTP_PORT;
145unsigned short server_port = HTTP_PORT; 145static unsigned short virtual_port = 0;
146unsigned short virtual_port = 0; 146static int host_name_length;
147int host_name_length; 147static char output_header_search[30] = "";
148char output_header_search[30] = ""; 148static char output_string_search[30] = "";
149char output_string_search[30] = ""; 149static char *warning_thresholds = NULL;
150char *warning_thresholds = NULL; 150static char *critical_thresholds = NULL;
151char *critical_thresholds = NULL; 151static int days_till_exp_warn, days_till_exp_crit;
152int days_till_exp_warn, days_till_exp_crit; 152static thresholds *thlds;
153thresholds *thlds; 153static char user_agent[DEFAULT_BUFFER_SIZE];
154char user_agent[DEFAULT_BUFFER_SIZE]; 154static int verbose = 0;
155int verbose = 0; 155static bool show_extended_perfdata = false;
156bool show_extended_perfdata = false; 156static bool show_body = false;
157bool show_body = false; 157static int min_page_len = 0;
158int min_page_len = 0; 158static int max_page_len = 0;
159int max_page_len = 0; 159static int redir_depth = 0;
160int redir_depth = 0; 160static int max_depth = DEFAULT_MAX_REDIRS;
161int max_depth = DEFAULT_MAX_REDIRS; 161static char *http_method = NULL;
162char *http_method = NULL; 162static char *http_post_data = NULL;
163char *http_post_data = NULL; 163static char *http_content_type = NULL;
164char *http_content_type = NULL; 164static CURL *curl;
165CURL *curl; 165static bool curl_global_initialized = false;
166bool curl_global_initialized = false; 166static bool curl_easy_initialized = false;
167bool curl_easy_initialized = false; 167static struct curl_slist *header_list = NULL;
168struct curl_slist *header_list = NULL; 168static bool body_buf_initialized = false;
169bool body_buf_initialized = false; 169static curlhelp_write_curlbuf body_buf;
170curlhelp_write_curlbuf body_buf; 170static bool header_buf_initialized = false;
171bool header_buf_initialized = false; 171static curlhelp_write_curlbuf header_buf;
172curlhelp_write_curlbuf header_buf; 172static bool status_line_initialized = false;
173bool status_line_initialized = false; 173static curlhelp_statusline status_line;
174curlhelp_statusline status_line; 174static bool put_buf_initialized = false;
175bool put_buf_initialized = false; 175static curlhelp_read_curlbuf put_buf;
176curlhelp_read_curlbuf put_buf; 176static char http_header[DEFAULT_BUFFER_SIZE];
177char http_header[DEFAULT_BUFFER_SIZE]; 177static long code;
178long code; 178static long socket_timeout = DEFAULT_SOCKET_TIMEOUT;
179long socket_timeout = DEFAULT_SOCKET_TIMEOUT; 179static double total_time;
180double total_time; 180static double time_connect;
181double time_connect; 181static double time_appconnect;
182double time_appconnect; 182static double time_headers;
183double time_headers; 183static double time_firstbyte;
184double time_firstbyte; 184static char errbuf[MAX_INPUT_BUFFER];
185char errbuf[MAX_INPUT_BUFFER]; 185static CURLcode res;
186CURLcode res; 186static char url[DEFAULT_BUFFER_SIZE];
187char url[DEFAULT_BUFFER_SIZE]; 187static char msg[DEFAULT_BUFFER_SIZE];
188char msg[DEFAULT_BUFFER_SIZE]; 188static char perfstring[DEFAULT_BUFFER_SIZE];
189char perfstring[DEFAULT_BUFFER_SIZE]; 189static char header_expect[MAX_INPUT_BUFFER] = "";
190char header_expect[MAX_INPUT_BUFFER] = ""; 190static char string_expect[MAX_INPUT_BUFFER] = "";
191char string_expect[MAX_INPUT_BUFFER] = ""; 191static char server_expect[MAX_INPUT_BUFFER] = HTTP_EXPECT;
192char server_expect[MAX_INPUT_BUFFER] = HTTP_EXPECT; 192static int server_expect_yn = 0;
193int server_expect_yn = 0; 193static char user_auth[MAX_INPUT_BUFFER] = "";
194char user_auth[MAX_INPUT_BUFFER] = ""; 194static char proxy_auth[MAX_INPUT_BUFFER] = "";
195char proxy_auth[MAX_INPUT_BUFFER] = ""; 195static char **http_opt_headers;
196char **http_opt_headers; 196static int http_opt_headers_count = 0;
197int http_opt_headers_count = 0; 197static bool display_html = false;
198bool display_html = false; 198static int onredirect = STATE_OK;
199int onredirect = STATE_OK; 199static int followmethod = FOLLOW_HTTP_CURL;
200int followmethod = FOLLOW_HTTP_CURL; 200static int followsticky = STICKY_NONE;
201int followsticky = STICKY_NONE; 201static bool use_ssl = false;
202bool use_ssl = false; 202static bool check_cert = false;
203bool use_sni = true; 203static bool continue_after_check_cert = false;
204bool check_cert = false;
205bool continue_after_check_cert = false;
206typedef union { 204typedef union {
207 struct curl_slist* to_info; 205 struct curl_slist *to_info;
208 struct curl_certinfo* to_certinfo; 206 struct curl_certinfo *to_certinfo;
209} cert_ptr_union; 207} cert_ptr_union;
210cert_ptr_union cert_ptr; 208static cert_ptr_union cert_ptr;
211int ssl_version = CURL_SSLVERSION_DEFAULT; 209static int ssl_version = CURL_SSLVERSION_DEFAULT;
212char *client_cert = NULL; 210static char *client_cert = NULL;
213char *client_privkey = NULL; 211static char *client_privkey = NULL;
214char *ca_cert = NULL; 212static char *ca_cert = NULL;
215bool verify_peer_and_host = false; 213static bool verify_peer_and_host = false;
216bool is_openssl_callback = false; 214static bool is_openssl_callback = false;
217bool add_sslctx_verify_fun = false; 215static bool add_sslctx_verify_fun = false;
218#if defined(HAVE_SSL) && defined(USE_OPENSSL) 216#if defined(HAVE_SSL) && defined(USE_OPENSSL)
219X509 *cert = NULL; 217static X509 *cert = NULL;
220#endif /* defined(HAVE_SSL) && defined(USE_OPENSSL) */ 218#endif /* defined(HAVE_SSL) && defined(USE_OPENSSL) */
221bool no_body = false; 219static bool no_body = false;
222int maximum_age = -1; 220static int maximum_age = -1;
223int address_family = AF_UNSPEC; 221static int address_family = AF_UNSPEC;
224curlhelp_ssl_library ssl_library = CURLHELP_SSL_LIBRARY_UNKNOWN; 222static curlhelp_ssl_library ssl_library = CURLHELP_SSL_LIBRARY_UNKNOWN;
225int curl_http_version = CURL_HTTP_VERSION_NONE; 223static int curl_http_version = CURL_HTTP_VERSION_NONE;
226bool automatic_decompression = false; 224static bool automatic_decompression = false;
227char *cookie_jar_file = NULL; 225static char *cookie_jar_file = NULL;
228bool haproxy_protocol = false; 226static bool haproxy_protocol = false;
229 227
230bool process_arguments (int, char**); 228static bool process_arguments(int /*argc*/, char ** /*argv*/);
231void handle_curl_option_return_code (CURLcode res, const char* option); 229static void handle_curl_option_return_code(CURLcode res, const char *option);
232int check_http (void); 230static int check_http(void);
233void redir (curlhelp_write_curlbuf*); 231static void redir(curlhelp_write_curlbuf * /*header_buf*/);
234char *perfd_time (double microsec); 232static char *perfd_time(double elapsed_time);
235char *perfd_time_connect (double microsec); 233static char *perfd_time_connect(double elapsed_time_connect);
236char *perfd_time_ssl (double microsec); 234static char *perfd_time_ssl(double elapsed_time_ssl);
237char *perfd_time_firstbyte (double microsec); 235static char *perfd_time_firstbyte(double elapsed_time_firstbyte);
238char *perfd_time_headers (double microsec); 236static char *perfd_time_headers(double elapsed_time_headers);
239char *perfd_time_transfer (double microsec); 237static char *perfd_time_transfer(double elapsed_time_transfer);
240char *perfd_size (int page_len); 238static char *perfd_size(int page_len);
241void print_help (void); 239static void print_help(void);
242void print_usage (void); 240void print_usage(void);
243void print_curl_version (void); 241static void print_curl_version(void);
244int curlhelp_initwritebuffer (curlhelp_write_curlbuf*); 242static int curlhelp_initwritebuffer(curlhelp_write_curlbuf * /*buf*/);
245size_t curlhelp_buffer_write_callback(void*, size_t , size_t , void*); 243static size_t curlhelp_buffer_write_callback(void * /*buffer*/, size_t /*size*/, size_t /*nmemb*/, void * /*stream*/);
246void curlhelp_freewritebuffer (curlhelp_write_curlbuf*); 244static void curlhelp_freewritebuffer(curlhelp_write_curlbuf * /*buf*/);
247int curlhelp_initreadbuffer (curlhelp_read_curlbuf *, const char *, size_t); 245static int curlhelp_initreadbuffer(curlhelp_read_curlbuf * /*buf*/, const char * /*data*/, size_t /*datalen*/);
248size_t curlhelp_buffer_read_callback(void *, size_t , size_t , void *); 246static size_t curlhelp_buffer_read_callback(void * /*buffer*/, size_t /*size*/, size_t /*nmemb*/, void * /*stream*/);
249void curlhelp_freereadbuffer (curlhelp_read_curlbuf *); 247static void curlhelp_freereadbuffer(curlhelp_read_curlbuf * /*buf*/);
250curlhelp_ssl_library curlhelp_get_ssl_library (); 248static curlhelp_ssl_library curlhelp_get_ssl_library(void);
251const char* curlhelp_get_ssl_library_string (curlhelp_ssl_library); 249static const char *curlhelp_get_ssl_library_string(curlhelp_ssl_library /*ssl_library*/);
252int net_noopenssl_check_certificate (cert_ptr_union*, int, int); 250int net_noopenssl_check_certificate(cert_ptr_union *, int, int);
253 251
254int curlhelp_parse_statusline (const char*, curlhelp_statusline *); 252static int curlhelp_parse_statusline(const char * /*buf*/, curlhelp_statusline * /*status_line*/);
255void curlhelp_free_statusline (curlhelp_statusline *); 253static void curlhelp_free_statusline(curlhelp_statusline * /*status_line*/);
256char *get_header_value (const struct phr_header* headers, const size_t nof_headers, const char* header); 254static char *get_header_value(const struct phr_header *headers, size_t nof_headers, const char *header);
257int check_document_dates (const curlhelp_write_curlbuf *, char (*msg)[DEFAULT_BUFFER_SIZE]); 255static int check_document_dates(const curlhelp_write_curlbuf * /*header_buf*/, char (*msg)[DEFAULT_BUFFER_SIZE]);
258int get_content_length (const curlhelp_write_curlbuf* header_buf, const curlhelp_write_curlbuf* body_buf); 256static int get_content_length(const curlhelp_write_curlbuf *header_buf, const curlhelp_write_curlbuf *body_buf);
259 257
260#if defined(HAVE_SSL) && defined(USE_OPENSSL) 258#if defined(HAVE_SSL) && defined(USE_OPENSSL)
261int 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);
262#endif /* defined(HAVE_SSL) && defined(USE_OPENSSL) */ 260#endif /* defined(HAVE_SSL) && defined(USE_OPENSSL) */
263 261
264void remove_newlines (char *); 262static void test_file(char * /*path*/);
265void test_file (char *);
266 263
267int 264int main(int argc, char **argv) {
268main (int argc, char **argv) 265 int result = STATE_UNKNOWN;
269{
270 int result = STATE_UNKNOWN;
271 266
272 setlocale (LC_ALL, ""); 267 setlocale(LC_ALL, "");
273 bindtextdomain (PACKAGE, LOCALEDIR); 268 bindtextdomain(PACKAGE, LOCALEDIR);
274 textdomain (PACKAGE); 269 textdomain(PACKAGE);
275 270
276 /* Parse extra opts if any */ 271 /* Parse extra opts if any */
277 argv = np_extra_opts (&argc, argv, progname); 272 argv = np_extra_opts(&argc, argv, progname);
278 273
279 /* set defaults */ 274 /* set defaults */
280 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());
281 progname, NP_VERSION, VERSION, curl_version());
282 276
283 /* parse arguments */ 277 /* parse arguments */
284 if (process_arguments (argc, argv) == false) 278 if (process_arguments(argc, argv) == false)
285 usage4 (_("Could not parse arguments")); 279 usage4(_("Could not parse arguments"));
286 280
287 if (display_html) 281 if (display_html)
288 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,
289 use_ssl ? "https" : "http", 283 virtual_port ? virtual_port : server_port, server_url);
290 host_name ? host_name : server_address,
291 virtual_port ? virtual_port : server_port,
292 server_url);
293 284
294 result = check_http (); 285 result = check_http();
295 return result; 286 return result;
296} 287}
297 288
298#ifdef HAVE_SSL 289#ifdef HAVE_SSL
299#ifdef USE_OPENSSL 290# ifdef USE_OPENSSL
300 291
301int verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx) 292int verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx) {
302{ 293 (void)preverify_ok;
303 (void) preverify_ok; 294 /* TODO: we get all certificates of the chain, so which ones
304 /* TODO: we get all certificates of the chain, so which ones 295 * should we test?
305 * should we test? 296 * TODO: is the last certificate always the server certificate?
306 * TODO: is the last certificate always the server certificate? 297 */
307 */ 298 cert = X509_STORE_CTX_get_current_cert(x509_ctx);
308 cert = X509_STORE_CTX_get_current_cert(x509_ctx); 299# if OPENSSL_VERSION_NUMBER >= 0x10100000L
309#if OPENSSL_VERSION_NUMBER >= 0x10100000L 300 X509_up_ref(cert);
310 X509_up_ref(cert); 301# endif
311#endif 302 if (verbose >= 2) {
312 if (verbose>=2) { 303 puts("* SSL verify callback with certificate:");
313 puts("* SSL verify callback with certificate:"); 304 X509_NAME *subject;
314 X509_NAME *subject, *issuer; 305 X509_NAME *issuer;
315 printf("* issuer:\n"); 306 printf("* issuer:\n");
316 issuer = X509_get_issuer_name( cert ); 307 issuer = X509_get_issuer_name(cert);
317 X509_NAME_print_ex_fp(stdout, issuer, 5, XN_FLAG_MULTILINE); 308 X509_NAME_print_ex_fp(stdout, issuer, 5, XN_FLAG_MULTILINE);
318 printf("* curl verify_callback:\n* subject:\n"); 309 printf("* curl verify_callback:\n* subject:\n");
319 subject = X509_get_subject_name( cert ); 310 subject = X509_get_subject_name(cert);
320 X509_NAME_print_ex_fp(stdout, subject, 5, XN_FLAG_MULTILINE); 311 X509_NAME_print_ex_fp(stdout, subject, 5, XN_FLAG_MULTILINE);
321 puts(""); 312 puts("");
322 } 313 }
323 return 1; 314 return 1;
324} 315}
325 316
326CURLcode sslctxfun(CURL *curl, SSL_CTX *sslctx, void *parm) 317CURLcode sslctxfun(CURL *curl, SSL_CTX *sslctx, void *parm) {
327{ 318 (void)curl; // ignore unused parameter
328 (void) curl; // ignore unused parameter 319 (void)parm; // ignore unused parameter
329 (void) parm; // ignore unused parameter 320 if (add_sslctx_verify_fun) {
330 if(add_sslctx_verify_fun) { 321 SSL_CTX_set_verify(sslctx, SSL_VERIFY_PEER, verify_callback);
331 SSL_CTX_set_verify(sslctx, SSL_VERIFY_PEER, verify_callback); 322 }
332 } 323
333 324 // workaround for issue:
334 // workaround for issue: 325 // OpenSSL SSL_read: error:0A000126:SSL routines::unexpected eof while reading, errno 0
335 // OpenSSL SSL_read: error:0A000126:SSL routines::unexpected eof while reading, errno 0 326 // see discussion https://github.com/openssl/openssl/discussions/22690
336 // see discussion https://github.com/openssl/openssl/discussions/22690 327# ifdef SSL_OP_IGNORE_UNEXPECTED_EOF
337#ifdef SSL_OP_IGNORE_UNEXPECTED_EOF 328 SSL_CTX_set_options(sslctx, SSL_OP_IGNORE_UNEXPECTED_EOF);
338 SSL_CTX_set_options(sslctx, SSL_OP_IGNORE_UNEXPECTED_EOF); 329# endif
339#endif
340 330
341 return CURLE_OK; 331 return CURLE_OK;
342} 332}
343 333
344#endif /* USE_OPENSSL */ 334# endif /* USE_OPENSSL */
345#endif /* HAVE_SSL */ 335#endif /* HAVE_SSL */
346 336
347/* returns a string "HTTP/1.x" or "HTTP/2" */ 337/* returns a string "HTTP/1.x" or "HTTP/2" */
348static char *string_statuscode (int major, int minor) 338static char *string_statuscode(int major, int minor) {
349{ 339 static char buf[10];
350 static char buf[10]; 340
351 341 switch (major) {
352 switch (major) { 342 case 1:
353 case 1: 343 snprintf(buf, sizeof(buf), "HTTP/%d.%d", major, minor);
354 snprintf (buf, sizeof (buf), "HTTP/%d.%d", major, minor); 344 break;
355 break; 345 case 2:
356 case 2: 346 case 3:
357 case 3: 347 snprintf(buf, sizeof(buf), "HTTP/%d", major);
358 snprintf (buf, sizeof (buf), "HTTP/%d", major); 348 break;
359 break; 349 default:
360 default: 350 /* assuming here HTTP/N with N>=4 */
361 /* assuming here HTTP/N with N>=4 */ 351 snprintf(buf, sizeof(buf), "HTTP/%d", major);
362 snprintf (buf, sizeof (buf), "HTTP/%d", major); 352 break;
363 break; 353 }
364 } 354
365 355 return buf;
366 return buf;
367} 356}
368 357
369/* Checks if the server 'reply' is one of the expected 'statuscodes' */ 358/* Checks if the server 'reply' is one of the expected 'statuscodes' */
370static int 359static int expected_statuscode(const char *reply, const char *statuscodes) {
371expected_statuscode (const char *reply, const char *statuscodes) 360 char *expected;
372{ 361 char *code;
373 char *expected, *code; 362 int result = 0;
374 int result = 0; 363
375 364 if ((expected = strdup(statuscodes)) == NULL)
376 if ((expected = strdup (statuscodes)) == NULL) 365 die(STATE_UNKNOWN, _("HTTP UNKNOWN - Memory allocation error\n"));
377 die (STATE_UNKNOWN, _("HTTP UNKNOWN - Memory allocation error\n")); 366
378 367 for (code = strtok(expected, ","); code != NULL; code = strtok(NULL, ","))
379 for (code = strtok (expected, ","); code != NULL; code = strtok (NULL, ",")) 368 if (strstr(reply, code) != NULL) {
380 if (strstr (reply, code) != NULL) { 369 result = 1;
381 result = 1; 370 break;
382 break; 371 }
383 } 372
384 373 free(expected);
385 free (expected); 374 return result;
386 return result;
387} 375}
388 376
389void 377void handle_curl_option_return_code(CURLcode res, const char *option) {
390handle_curl_option_return_code (CURLcode res, const char* option) 378 if (res != CURLE_OK) {
391{ 379 snprintf(msg, DEFAULT_BUFFER_SIZE, _("Error while setting cURL option '%s': cURL returned %d - %s"), option, res,
392 if (res != CURLE_OK) { 380 curl_easy_strerror(res));
393 snprintf (msg, 381 die(STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg);
394 DEFAULT_BUFFER_SIZE, 382 }
395 _("Error while setting cURL option '%s': cURL returned %d - %s"),
396 option,
397 res,
398 curl_easy_strerror(res));
399 die (STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg);
400 }
401} 383}
402 384
403int 385int lookup_host(const char *host, char *buf, size_t buflen) {
404lookup_host (const char *host, char *buf, size_t buflen) 386 struct addrinfo hints, *res, *result;
405{ 387 char addrstr[100];
406 struct addrinfo hints, *res, *result; 388 size_t addrstr_len;
407 char addrstr[100]; 389 int errcode;
408 size_t addrstr_len; 390 void *ptr = {0};
409 int errcode; 391 size_t buflen_remaining = buflen - 1;
410 void *ptr = { 0 }; 392
411 size_t buflen_remaining = buflen - 1; 393 memset(&hints, 0, sizeof(hints));
412 394 hints.ai_family = address_family;
413 memset (&hints, 0, sizeof (hints)); 395 hints.ai_socktype = SOCK_STREAM;
414 hints.ai_family = address_family; 396 hints.ai_flags |= AI_CANONNAME;
415 hints.ai_socktype = SOCK_STREAM; 397
416 hints.ai_flags |= AI_CANONNAME; 398 errcode = getaddrinfo(host, NULL, &hints, &result);
417 399 if (errcode != 0)
418 errcode = getaddrinfo (host, NULL, &hints, &result); 400 return errcode;
419 if (errcode != 0) 401
420 return errcode; 402 strcpy(buf, "");
421 403 res = result;
422 strcpy(buf, ""); 404
423 res = result; 405 while (res) {
424 406 switch (res->ai_family) {
425 while (res) { 407 case AF_INET:
426 switch (res->ai_family) { 408 ptr = &((struct sockaddr_in *)res->ai_addr)->sin_addr;
427 case AF_INET: 409 break;
428 ptr = &((struct sockaddr_in *) res->ai_addr)->sin_addr; 410 case AF_INET6:
429 break; 411 ptr = &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr;
430 case AF_INET6: 412 break;
431 ptr = &((struct sockaddr_in6 *) res->ai_addr)->sin6_addr; 413 }
432 break; 414
433 } 415 inet_ntop(res->ai_family, ptr, addrstr, 100);
434 416 if (verbose >= 1) {
435 inet_ntop (res->ai_family, ptr, addrstr, 100); 417 printf("* getaddrinfo IPv%d address: %s\n", res->ai_family == PF_INET6 ? 6 : 4, addrstr);
436 if (verbose >= 1) { 418 }
437 printf ("* getaddrinfo IPv%d address: %s\n", 419
438 res->ai_family == PF_INET6 ? 6 : 4, addrstr); 420 // Append all IPs to buf as a comma-separated string
439 } 421 addrstr_len = strlen(addrstr);
440 422 if (buflen_remaining > addrstr_len + 1) {
441 // Append all IPs to buf as a comma-separated string 423 if (buf[0] != '\0') {
442 addrstr_len = strlen(addrstr); 424 strncat(buf, ",", buflen_remaining);
443 if (buflen_remaining > addrstr_len + 1) { 425 buflen_remaining -= 1;
444 if (buf[0] != '\0') { 426 }
445 strncat(buf, ",", buflen_remaining); 427 strncat(buf, addrstr, buflen_remaining);
446 buflen_remaining -= 1; 428 buflen_remaining -= addrstr_len;
447 } 429 }
448 strncat(buf, addrstr, buflen_remaining); 430
449 buflen_remaining -= addrstr_len; 431 res = res->ai_next;
450 } 432 }
451 433
452 res = res->ai_next; 434 freeaddrinfo(result);
453 } 435
454 436 return 0;
455 freeaddrinfo(result);
456
457 return 0;
458} 437}
459 438
460static void 439static void cleanup(void) {
461cleanup (void) 440 if (status_line_initialized)
462{ 441 curlhelp_free_statusline(&status_line);
463 if (status_line_initialized) curlhelp_free_statusline(&status_line); 442 status_line_initialized = false;
464 status_line_initialized = false; 443 if (curl_easy_initialized)
465 if (curl_easy_initialized) curl_easy_cleanup (curl); 444 curl_easy_cleanup(curl);
466 curl_easy_initialized = false; 445 curl_easy_initialized = false;
467 if (curl_global_initialized) curl_global_cleanup (); 446 if (curl_global_initialized)
468 curl_global_initialized = false; 447 curl_global_cleanup();
469 if (body_buf_initialized) curlhelp_freewritebuffer (&body_buf); 448 curl_global_initialized = false;
470 body_buf_initialized = false; 449 if (body_buf_initialized)
471 if (header_buf_initialized) curlhelp_freewritebuffer (&header_buf); 450 curlhelp_freewritebuffer(&body_buf);
472 header_buf_initialized = false; 451 body_buf_initialized = false;
473 if (put_buf_initialized) curlhelp_freereadbuffer (&put_buf); 452 if (header_buf_initialized)
474 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;
475} 458}
476 459
477int 460int check_http(void) {
478check_http (void) 461 int result = STATE_OK;
479{ 462 int result_ssl = STATE_OK;
480 int result = STATE_OK; 463 int page_len = 0;
481 int result_ssl = STATE_OK; 464 int i;
482 int page_len = 0; 465 char *force_host_header = NULL;
483 int i; 466 struct curl_slist *host = NULL;
484 char *force_host_header = NULL; 467 char addrstr[DEFAULT_BUFFER_SIZE / 2];
485 struct curl_slist *host = NULL; 468 char dnscache[DEFAULT_BUFFER_SIZE];
486 char addrstr[DEFAULT_BUFFER_SIZE/2]; 469
487 char dnscache[DEFAULT_BUFFER_SIZE]; 470 /* initialize curl */
488 471 if (curl_global_init(CURL_GLOBAL_DEFAULT) != CURLE_OK)
489 /* initialize curl */ 472 die(STATE_UNKNOWN, "HTTP UNKNOWN - curl_global_init failed\n");
490 if (curl_global_init (CURL_GLOBAL_DEFAULT) != CURLE_OK) 473 curl_global_initialized = true;
491 die (STATE_UNKNOWN, "HTTP UNKNOWN - curl_global_init failed\n"); 474
492 curl_global_initialized = true; 475 if ((curl = curl_easy_init()) == NULL) {
493 476 die(STATE_UNKNOWN, "HTTP UNKNOWN - curl_easy_init failed\n");
494 if ((curl = curl_easy_init()) == NULL) { 477 }
495 die (STATE_UNKNOWN, "HTTP UNKNOWN - curl_easy_init failed\n"); 478 curl_easy_initialized = true;
496 } 479
497 curl_easy_initialized = true; 480 /* register cleanup function to shut down libcurl properly */
498 481 atexit(cleanup);
499 /* register cleanup function to shut down libcurl properly */ 482
500 atexit (cleanup); 483 if (verbose >= 1)
501 484 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_VERBOSE, 1), "CURLOPT_VERBOSE");
502 if (verbose >= 1) 485
503 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_VERBOSE, 1), "CURLOPT_VERBOSE"); 486 /* print everything on stdout like check_http would do */
504 487 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_STDERR, stdout), "CURLOPT_STDERR");
505 /* print everything on stdout like check_http would do */ 488
506 handle_curl_option_return_code (curl_easy_setopt(curl, CURLOPT_STDERR, stdout), "CURLOPT_STDERR"); 489 if (automatic_decompression)
507
508 if (automatic_decompression)
509#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 21, 6) 490#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 21, 6)
510 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");
511#else 492#else
512 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");
513#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 21, 6) */ 494#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 21, 6) */
514 495
515 /* initialize buffer for body of the answer */ 496 /* initialize buffer for body of the answer */
516 if (curlhelp_initwritebuffer(&body_buf) < 0) 497 if (curlhelp_initwritebuffer(&body_buf) < 0)
517 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");
518 body_buf_initialized = true; 499 body_buf_initialized = true;
519 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),
520 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_WRITEDATA, (void *)&body_buf), "CURLOPT_WRITEDATA"); 501 "CURLOPT_WRITEFUNCTION");
521 502 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&body_buf), "CURLOPT_WRITEDATA");
522 /* initialize buffer for header of the answer */ 503
523 if (curlhelp_initwritebuffer( &header_buf ) < 0) 504 /* initialize buffer for header of the answer */
524 die (STATE_UNKNOWN, "HTTP CRITICAL - out of memory allocating buffer for header\n" ); 505 if (curlhelp_initwritebuffer(&header_buf) < 0)
525 header_buf_initialized = true; 506 die(STATE_UNKNOWN, "HTTP CRITICAL - out of memory allocating buffer for header\n");
526 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;
527 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),
528 509 "CURLOPT_HEADERFUNCTION");
529 /* set the error buffer */ 510 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_WRITEHEADER, (void *)&header_buf), "CURLOPT_WRITEHEADER");
530 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_ERRORBUFFER, errbuf), "CURLOPT_ERRORBUFFER"); 511
531 512 /* set the error buffer */
532 /* set timeouts */ 513 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errbuf), "CURLOPT_ERRORBUFFER");
533 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_CONNECTTIMEOUT, socket_timeout), "CURLOPT_CONNECTTIMEOUT"); 514
534 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_TIMEOUT, socket_timeout), "CURLOPT_TIMEOUT"); 515 /* set timeouts */
535 516 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, socket_timeout), "CURLOPT_CONNECTTIMEOUT");
536 /* enable haproxy protocol */ 517 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_TIMEOUT, socket_timeout), "CURLOPT_TIMEOUT");
537 if (haproxy_protocol) { 518
538 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_HAPROXYPROTOCOL, 1L), "CURLOPT_HAPROXYPROTOCOL"); 519 /* enable haproxy protocol */
539 } 520 if (haproxy_protocol) {
540 521 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_HAPROXYPROTOCOL, 1L), "CURLOPT_HAPROXYPROTOCOL");
541 // 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 522 }
542 if(use_ssl && host_name != NULL) { 523
543 if ( (res=lookup_host (server_address, addrstr, DEFAULT_BUFFER_SIZE/2)) != 0) { 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
544 snprintf (msg, 525 // use the host_name later on to make SNI happy
545 DEFAULT_BUFFER_SIZE, 526 if (use_ssl && host_name != NULL) {
546 _("Unable to lookup IP address for '%s': getaddrinfo returned %d - %s"), 527 if ((res = lookup_host(server_address, addrstr, DEFAULT_BUFFER_SIZE / 2)) != 0) {
547 server_address, 528 snprintf(msg, DEFAULT_BUFFER_SIZE, _("Unable to lookup IP address for '%s': getaddrinfo returned %d - %d"), server_address, res,
548 res, 529 gai_strerror(res));
549 gai_strerror (res)); 530 die(STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg);
550 die (STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg); 531 }
551 } 532 snprintf(dnscache, DEFAULT_BUFFER_SIZE, "%s:%d:%s", host_name, server_port, addrstr);
552 snprintf (dnscache, DEFAULT_BUFFER_SIZE, "%s:%d:%s", host_name, server_port, addrstr); 533 host = curl_slist_append(NULL, dnscache);
553 host = curl_slist_append(NULL, dnscache); 534 curl_easy_setopt(curl, CURLOPT_RESOLVE, host);
554 curl_easy_setopt(curl, CURLOPT_RESOLVE, host); 535 if (verbose >= 1)
555 if (verbose>=1) 536 printf("* curl CURLOPT_RESOLVE: %s\n", dnscache);
556 printf ("* curl CURLOPT_RESOLVE: %s\n", dnscache); 537 }
557 } 538
558 539 // If server_address is an IPv6 address it must be surround by square brackets
559 // If server_address is an IPv6 address it must be surround by square brackets 540 struct in6_addr tmp_in_addr;
560 struct in6_addr tmp_in_addr; 541 if (inet_pton(AF_INET6, server_address, &tmp_in_addr) == 1) {
561 if (inet_pton(AF_INET6, server_address, &tmp_in_addr) == 1) { 542 char *new_server_address = malloc(strlen(server_address) + 3);
562 char *new_server_address = malloc(strlen(server_address) + 3); 543 if (new_server_address == NULL) {
563 if (new_server_address == NULL) { 544 die(STATE_UNKNOWN, "HTTP UNKNOWN - Unable to allocate memory\n");
564 die(STATE_UNKNOWN, "HTTP UNKNOWN - Unable to allocate memory\n"); 545 }
565 } 546 snprintf(new_server_address, strlen(server_address) + 3, "[%s]", server_address);
566 snprintf(new_server_address, strlen(server_address)+3, "[%s]", server_address); 547 free(server_address);
567 free(server_address); 548 server_address = new_server_address;
568 server_address = new_server_address; 549 }
569 } 550
570 551 /* compose URL: use the address we want to connect to, set Host: header later */
571 /* compose URL: use the address we want to connect to, set Host: header later */ 552 snprintf(url, DEFAULT_BUFFER_SIZE, "%s://%s:%d%s", use_ssl ? "https" : "http",
572 snprintf (url, DEFAULT_BUFFER_SIZE, "%s://%s:%d%s", 553 (use_ssl & (host_name != NULL)) ? host_name : server_address, server_port, server_url);
573 use_ssl ? "https" : "http", 554
574 ( use_ssl & ( host_name != NULL ) ) ? host_name : server_address, 555 if (verbose >= 1)
575 server_port, 556 printf("* curl CURLOPT_URL: %s\n", url);
576 server_url 557 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_URL, url), "CURLOPT_URL");
577 ); 558
578 559 /* extract proxy information for legacy proxy https requests */
579 if (verbose>=1) 560 if (!strcmp(http_method, "CONNECT") || strstr(server_url, "http") == server_url) {
580 printf ("* curl CURLOPT_URL: %s\n", url); 561 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_PROXY, server_address), "CURLOPT_PROXY");
581 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_URL, url), "CURLOPT_URL"); 562 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_PROXYPORT, (long)server_port), "CURLOPT_PROXYPORT");
582 563 if (verbose >= 2)
583 /* extract proxy information for legacy proxy https requests */ 564 printf("* curl CURLOPT_PROXY: %s:%d\n", server_address, server_port);
584 if (!strcmp(http_method, "CONNECT") || strstr(server_url, "http") == server_url) { 565 http_method = "GET";
585 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_PROXY, server_address), "CURLOPT_PROXY"); 566 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_URL, server_url), "CURLOPT_URL");
586 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_PROXYPORT, (long)server_port), "CURLOPT_PROXYPORT"); 567 }
587 if (verbose>=2) 568
588 printf ("* curl CURLOPT_PROXY: %s:%d\n", server_address, server_port); 569 /* disable body for HEAD request */
589 http_method = "GET"; 570 if (http_method && !strcmp(http_method, "HEAD")) {
590 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_URL, server_url), "CURLOPT_URL"); 571 no_body = true;
591 } 572 }
592 573
593 /* disable body for HEAD request */ 574 /* set HTTP protocol version */
594 if (http_method && !strcmp (http_method, "HEAD" )) { 575 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, curl_http_version), "CURLOPT_HTTP_VERSION");
595 no_body = true; 576
596 } 577 /* set HTTP method */
597 578 if (http_method) {
598 /* set HTTP protocol version */ 579 if (!strcmp(http_method, "POST"))
599 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_HTTP_VERSION, curl_http_version), "CURLOPT_HTTP_VERSION"); 580 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_POST, 1), "CURLOPT_POST");
600 581 else if (!strcmp(http_method, "PUT"))
601 /* set HTTP method */ 582 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_UPLOAD, 1), "CURLOPT_UPLOAD");
602 if (http_method) { 583 else
603 if (!strcmp(http_method, "POST")) 584 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, http_method), "CURLOPT_CUSTOMREQUEST");
604 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_POST, 1), "CURLOPT_POST"); 585 }
605 else if (!strcmp(http_method, "PUT")) 586
606 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_UPLOAD, 1), "CURLOPT_UPLOAD"); 587 /* check if Host header is explicitly set in options */
607 else 588 if (http_opt_headers_count) {
608 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_CUSTOMREQUEST, http_method), "CURLOPT_CUSTOMREQUEST"); 589 for (i = 0; i < http_opt_headers_count; i++) {
609 } 590 if (strncmp(http_opt_headers[i], "Host:", 5) == 0) {
610 591 force_host_header = http_opt_headers[i];
611 /* check if Host header is explicitly set in options */ 592 }
612 if (http_opt_headers_count) { 593 }
613 for (i = 0; i < http_opt_headers_count ; i++) { 594 }
614 if (strncmp(http_opt_headers[i], "Host:", 5) == 0) { 595
615 force_host_header = http_opt_headers[i]; 596 /* set hostname (virtual hosts), not needed if CURLOPT_CONNECT_TO is used, but left in anyway */
616 } 597 if (host_name != NULL && force_host_header == NULL) {
617 } 598 if ((virtual_port != HTTP_PORT && !use_ssl) || (virtual_port != HTTPS_PORT && use_ssl)) {
618 } 599 snprintf(http_header, DEFAULT_BUFFER_SIZE, "Host: %s:%d", host_name, virtual_port);
619 600 } else {
620 /* set hostname (virtual hosts), not needed if CURLOPT_CONNECT_TO is used, but left in anyway */ 601 snprintf(http_header, DEFAULT_BUFFER_SIZE, "Host: %s", host_name);
621 if(host_name != NULL && force_host_header == NULL) { 602 }
622 if((virtual_port != HTTP_PORT && !use_ssl) || (virtual_port != HTTPS_PORT && use_ssl)) { 603 header_list = curl_slist_append(header_list, http_header);
623 snprintf(http_header, DEFAULT_BUFFER_SIZE, "Host: %s:%d", host_name, virtual_port); 604 }
624 } else { 605
625 snprintf(http_header, DEFAULT_BUFFER_SIZE, "Host: %s", host_name); 606 /* always close connection, be nice to servers */
626 } 607 snprintf(http_header, DEFAULT_BUFFER_SIZE, "Connection: close");
627 header_list = curl_slist_append (header_list, http_header); 608 header_list = curl_slist_append(header_list, http_header);
628 } 609
629 610 /* attach additional headers supplied by the user */
630 /* always close connection, be nice to servers */ 611 /* optionally send any other header tag */
631 snprintf (http_header, DEFAULT_BUFFER_SIZE, "Connection: close"); 612 if (http_opt_headers_count) {
632 header_list = curl_slist_append (header_list, http_header); 613 for (i = 0; i < http_opt_headers_count; i++) {
633 614 header_list = curl_slist_append(header_list, http_opt_headers[i]);
634 /* attach additional headers supplied by the user */ 615 }
635 /* optionally send any other header tag */ 616 /* This cannot be free'd here because a redirection will then try to access this and segfault */
636 if (http_opt_headers_count) { 617 /* Covered in a testcase in tests/check_http.t */
637 for (i = 0; i < http_opt_headers_count ; i++) { 618 /* free(http_opt_headers); */
638 header_list = curl_slist_append (header_list, http_opt_headers[i]); 619 }
639 } 620
640 /* This cannot be free'd here because a redirection will then try to access this and segfault */ 621 /* set HTTP headers */
641 /* Covered in a testcase in tests/check_http.t */ 622 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header_list), "CURLOPT_HTTPHEADER");
642 /* free(http_opt_headers); */
643 }
644
645 /* set HTTP headers */
646 handle_curl_option_return_code (curl_easy_setopt( curl, CURLOPT_HTTPHEADER, header_list ), "CURLOPT_HTTPHEADER");
647 623
648#ifdef LIBCURL_FEATURE_SSL 624#ifdef LIBCURL_FEATURE_SSL
649 625
650 /* set SSL version, warn about insecure or unsupported versions */ 626 /* set SSL version, warn about insecure or unsupported versions */
651 if (use_ssl) { 627 if (use_ssl) {
652 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");
653 } 629 }
654 630
655 /* client certificate and key to present to server (SSL) */ 631 /* client certificate and key to present to server (SSL) */
656 if (client_cert) 632 if (client_cert)
657 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");
658 if (client_privkey) 634 if (client_privkey)
659 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");
660 if (ca_cert) { 636 if (ca_cert) {
661 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");
662 } 638 }
663 if (ca_cert || verify_peer_and_host) { 639 if (ca_cert || verify_peer_and_host) {
664 /* 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
665 * hostname in the certificate, can be switched off later */ 641 * hostname in the certificate, can be switched off later */
666 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");
667 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");
668 } else { 644 } else {
669 /* backward-compatible behaviour, be tolerant in checks 645 /* backward-compatible behaviour, be tolerant in checks
670 * TODO: depending on more options have aspects we want 646 * TODO: depending on more options have aspects we want
671 * to be less tolerant about ssl verfications 647 * to be less tolerant about ssl verfications
672 */ 648 */
673 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");
674 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");
675 } 651 }
676 652
677 /* detect SSL library used by libcurl */ 653 /* detect SSL library used by libcurl */
678 ssl_library = curlhelp_get_ssl_library (); 654 ssl_library = curlhelp_get_ssl_library();
679 655
680 /* try hard to get a stack of certificates to verify against */ 656 /* try hard to get a stack of certificates to verify against */
681 if (check_cert) { 657 if (check_cert) {
682#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 19, 1) 658# if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 19, 1)
683 /* inform curl to report back certificates */ 659 /* inform curl to report back certificates */
684 switch (ssl_library) { 660 switch (ssl_library) {
685 case CURLHELP_SSL_LIBRARY_OPENSSL: 661 case CURLHELP_SSL_LIBRARY_OPENSSL:
686 case CURLHELP_SSL_LIBRARY_LIBRESSL: 662 case CURLHELP_SSL_LIBRARY_LIBRESSL:
687 /* set callback to extract certificate with OpenSSL context function (works with 663 /* set callback to extract certificate with OpenSSL context function (works with
688 * OpenSSL-style libraries only!) */ 664 * OpenSSL-style libraries only!) */
689#ifdef USE_OPENSSL 665# ifdef USE_OPENSSL
690 /* libcurl and monitoring plugins built with OpenSSL, good */ 666 /* libcurl and monitoring plugins built with OpenSSL, good */
691 add_sslctx_verify_fun = true; 667 add_sslctx_verify_fun = true;
692 is_openssl_callback = true; 668 is_openssl_callback = true;
693#endif /* USE_OPENSSL */ 669# endif /* USE_OPENSSL */
694 /* libcurl is built with OpenSSL, monitoring plugins, so falling 670 /* libcurl is built with OpenSSL, monitoring plugins, so falling
695 * back to manually extracting certificate information */ 671 * back to manually extracting certificate information */
696 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_CERTINFO, 1L), "CURLOPT_CERTINFO"); 672 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_CERTINFO, 1L), "CURLOPT_CERTINFO");
697 break; 673 break;
698 674
699 case CURLHELP_SSL_LIBRARY_NSS: 675 case CURLHELP_SSL_LIBRARY_NSS:
700#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) 676# if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0)
701 /* NSS: support for CERTINFO is implemented since 7.34.0 */ 677 /* NSS: support for CERTINFO is implemented since 7.34.0 */
702 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_CERTINFO, 1L), "CURLOPT_CERTINFO"); 678 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_CERTINFO, 1L), "CURLOPT_CERTINFO");
703#else /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) */ 679# else /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) */
704 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)); 680 die(STATE_CRITICAL, "HTTP CRITICAL - Cannot retrieve certificates (libcurl linked with SSL library '%s' is too old)\n",
705#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) */ 681 curlhelp_get_ssl_library_string(ssl_library));
706 break; 682# endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) */
707 683 break;
708 case CURLHELP_SSL_LIBRARY_GNUTLS: 684
709#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 42, 0) 685 case CURLHELP_SSL_LIBRARY_GNUTLS:
710 /* GnuTLS: support for CERTINFO is implemented since 7.42.0 */ 686# if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 42, 0)
711 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_CERTINFO, 1L), "CURLOPT_CERTINFO"); 687 /* GnuTLS: support for CERTINFO is implemented since 7.42.0 */
712#else /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 42, 0) */ 688 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_CERTINFO, 1L), "CURLOPT_CERTINFO");
713 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)); 689# else /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 42, 0) */
714#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 42, 0) */ 690 die(STATE_CRITICAL, "HTTP CRITICAL - Cannot retrieve certificates (libcurl linked with SSL library '%s' is too old)\n",
715 break; 691 curlhelp_get_ssl_library_string(ssl_library));
716 692# endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 42, 0) */
717 case CURLHELP_SSL_LIBRARY_UNKNOWN: 693 break;
718 default: 694
719 die (STATE_CRITICAL, "HTTP CRITICAL - Cannot retrieve certificates (unknown SSL library '%s', must implement first)\n", curlhelp_get_ssl_library_string (ssl_library)); 695 case CURLHELP_SSL_LIBRARY_UNKNOWN:
720 break; 696 default:
721 } 697 die(STATE_CRITICAL, "HTTP CRITICAL - Cannot retrieve certificates (unknown SSL library '%s', must implement first)\n",
722#else /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 19, 1) */ 698 curlhelp_get_ssl_library_string(ssl_library));
723 /* old libcurl, our only hope is OpenSSL, otherwise we are out of luck */ 699 break;
724 if (ssl_library == CURLHELP_SSL_LIBRARY_OPENSSL || ssl_library == CURLHELP_SSL_LIBRARY_LIBRESSL) 700 }
725 add_sslctx_verify_fun = true; 701# else /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 19, 1) */
726 else 702 /* old libcurl, our only hope is OpenSSL, otherwise we are out of luck */
727 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"); 703 if (ssl_library == CURLHELP_SSL_LIBRARY_OPENSSL || ssl_library == CURLHELP_SSL_LIBRARY_LIBRESSL)
728#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 19, 1) */ 704 add_sslctx_verify_fun = true;
729 } 705 else
730 706 die(STATE_CRITICAL, "HTTP CRITICAL - Cannot retrieve certificates (no CURLOPT_SSL_CTX_FUNCTION, no OpenSSL library or libcurl "
731#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 10, 6) /* required for CURLOPT_SSL_CTX_FUNCTION */ 707 "too old and has no CURLOPT_CERTINFO)\n");
732 // ssl ctx function is not available with all ssl backends 708# endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 19, 1) */
733 if (curl_easy_setopt(curl, CURLOPT_SSL_CTX_FUNCTION, NULL) != CURLE_UNKNOWN_OPTION) 709 }
734 handle_curl_option_return_code (curl_easy_setopt(curl, CURLOPT_SSL_CTX_FUNCTION, sslctxfun), "CURLOPT_SSL_CTX_FUNCTION"); 710
735#endif 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
736 716
737#endif /* LIBCURL_FEATURE_SSL */ 717#endif /* LIBCURL_FEATURE_SSL */
738 718
739 /* set default or user-given user agent identification */ 719 /* set default or user-given user agent identification */
740 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");
741 721
742 /* proxy-authentication */ 722 /* proxy-authentication */
743 if (strcmp(proxy_auth, "")) 723 if (strcmp(proxy_auth, ""))
744 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");
745 725
746 /* authentication */ 726 /* authentication */
747 if (strcmp(user_auth, "")) 727 if (strcmp(user_auth, ""))
748 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");
749 729
750 /* TODO: parameter auth method, bitfield of following methods: 730 /* TODO: parameter auth method, bitfield of following methods:
751 * CURLAUTH_BASIC (default) 731 * CURLAUTH_BASIC (default)
752 * CURLAUTH_DIGEST 732 * CURLAUTH_DIGEST
753 * CURLAUTH_DIGEST_IE 733 * CURLAUTH_DIGEST_IE
754 * CURLAUTH_NEGOTIATE 734 * CURLAUTH_NEGOTIATE
755 * CURLAUTH_NTLM 735 * CURLAUTH_NTLM
756 * CURLAUTH_NTLM_WB 736 * CURLAUTH_NTLM_WB
757 * 737 *
758 * convenience tokens for typical sets of methods: 738 * convenience tokens for typical sets of methods:
759 * CURLAUTH_ANYSAFE: most secure, without BASIC 739 * CURLAUTH_ANYSAFE: most secure, without BASIC
760 * or CURLAUTH_ANY: most secure, even BASIC if necessary 740 * or CURLAUTH_ANY: most secure, even BASIC if necessary
761 * 741 *
762 * 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");
763 */ 743 */
764 744
765 /* handle redirections */ 745 /* handle redirections */
766 if (onredirect == STATE_DEPENDENT) { 746 if (onredirect == STATE_DEPENDENT) {
767 if( followmethod == FOLLOW_LIBCURL ) { 747 if (followmethod == FOLLOW_LIBCURL) {
768 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");
769 749
770 /* default -1 is infinite, not good, could lead to zombie plugins! 750 /* default -1 is infinite, not good, could lead to zombie plugins!
771 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
772 */ 752 */
773 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");
774 754
775 /* 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) */
776#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 85, 0) 756#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 85, 0)
777 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");
778#elif LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 19, 4) 759#elif LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 19, 4)
779 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");
780#endif 762#endif
781 763
782 /* TODO: handle the following aspects of redirection, make them 764 /* TODO: handle the following aspects of redirection, make them
783 * command line options too later: 765 * command line options too later:
784 CURLOPT_POSTREDIR: method switch 766 CURLOPT_POSTREDIR: method switch
785 CURLINFO_REDIRECT_URL: custom redirect option 767 CURLINFO_REDIRECT_URL: custom redirect option
786 CURLOPT_REDIRECT_PROTOCOLS: allow people to step outside safe protocols 768 CURLOPT_REDIRECT_PROTOCOLS: allow people to step outside safe protocols
787 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?
788 */ 770 */
789 } else { 771 } else {
790 /* old style redirection is handled below */ 772 /* old style redirection is handled below */
791 } 773 }
792 } 774 }
793 775
794 /* no-body */ 776 /* no-body */
795 if (no_body) 777 if (no_body)
796 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");
797 779
798 /* IPv4 or IPv6 forced DNS resolution */ 780 /* IPv4 or IPv6 forced DNS resolution */
799 if (address_family == AF_UNSPEC) 781 if (address_family == AF_UNSPEC)
800 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),
801 else if (address_family == AF_INET) 783 "CURLOPT_IPRESOLVE(CURL_IPRESOLVE_WHATEVER)");
802 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)
803#if defined (USE_IPV6) && defined (LIBCURL_FEATURE_IPV6) 785 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4),
804 else if (address_family == AF_INET6) 786 "CURLOPT_IPRESOLVE(CURL_IPRESOLVE_V4)");
805 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)");
806#endif 791#endif
807 792
808 /* either send http POST data (any data, not only POST)*/ 793 /* either send http POST data (any data, not only POST)*/
809 if (!strcmp(http_method, "POST") ||!strcmp(http_method, "PUT")) { 794 if (!strcmp(http_method, "POST") || !strcmp(http_method, "PUT")) {
810 /* set content of payload for POST and PUT */ 795 /* set content of payload for POST and PUT */
811 if (http_content_type) { 796 if (http_content_type) {
812 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);
813 header_list = curl_slist_append (header_list, http_header); 798 header_list = curl_slist_append(header_list, http_header);
814 } 799 }
815 /* NULL indicates "HTTP Continue" in libcurl, provide an empty string 800 /* NULL indicates "HTTP Continue" in libcurl, provide an empty string
816 * in case of no POST/PUT data */ 801 * in case of no POST/PUT data */
817 if (!http_post_data) 802 if (!http_post_data)
818 http_post_data = ""; 803 http_post_data = "";
819 if (!strcmp(http_method, "POST")) { 804 if (!strcmp(http_method, "POST")) {
820 /* POST method, set payload with CURLOPT_POSTFIELDS */ 805 /* POST method, set payload with CURLOPT_POSTFIELDS */
821 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");
822 } else if (!strcmp(http_method, "PUT")) { 807 } else if (!strcmp(http_method, "PUT")) {
823 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),
824 if (curlhelp_initreadbuffer (&put_buf, http_post_data, strlen (http_post_data)) < 0) 809 "CURLOPT_READFUNCTION");
825 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)
826 put_buf_initialized = true; 811 die(STATE_UNKNOWN, "HTTP CRITICAL - out of memory allocating read buffer for PUT\n");
827 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_READDATA, (void *)&put_buf), "CURLOPT_READDATA"); 812 put_buf_initialized = true;
828 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");
829 } 814 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_INFILESIZE, (curl_off_t)strlen(http_post_data)),
830 } 815 "CURLOPT_INFILESIZE");
831 816 }
832 /* cookie handling */ 817 }
833 if (cookie_jar_file != NULL) { 818
834 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_COOKIEJAR, cookie_jar_file), "CURLOPT_COOKIEJAR"); 819 /* cookie handling */
835 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_COOKIEFILE, cookie_jar_file), "CURLOPT_COOKIEFILE"); 820 if (cookie_jar_file != NULL) {
836 } 821 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_COOKIEJAR, cookie_jar_file), "CURLOPT_COOKIEJAR");
837 822 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_COOKIEFILE, cookie_jar_file), "CURLOPT_COOKIEFILE");
838 /* do the request */ 823 }
839 res = curl_easy_perform(curl); 824
840 825 /* do the request */
841 if (verbose>=2 && http_post_data) 826 res = curl_easy_perform(curl);
842 printf ("**** REQUEST CONTENT ****\n%s\n", http_post_data); 827
843 828 if (verbose >= 2 && http_post_data)
844 /* free header and server IP resolve lists, we don't need it anymore */ 829 printf("**** REQUEST CONTENT ****\n%s\n", http_post_data);
845 curl_slist_free_all (header_list); header_list = NULL; 830
846 curl_slist_free_all (server_ips); server_ips = NULL; 831 /* free header and server IP resolve lists, we don't need it anymore */
847 if (host) { 832 curl_slist_free_all(header_list);
848 curl_slist_free_all (host); host = NULL; 833 header_list = NULL;
849 } 834 curl_slist_free_all(server_ips);
850 835 server_ips = NULL;
851 /* Curl errors, result in critical Nagios state */ 836 if (host) {
852 if (res != CURLE_OK) { 837 curl_slist_free_all(host);
853 snprintf (msg, 838 host = NULL;
854 DEFAULT_BUFFER_SIZE, 839 }
855 _("Invalid HTTP response received from host on port %d: cURL returned %d - %s"), 840
856 server_port, 841 /* Curl errors, result in critical Nagios state */
857 res, 842 if (res != CURLE_OK) {
858 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,
859 die (STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg); 844 res, errbuf[0] ? errbuf : curl_easy_strerror(res));
860 } 845 die(STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg);
861 846 }
862 /* certificate checks */ 847
848 /* certificate checks */
863#ifdef LIBCURL_FEATURE_SSL 849#ifdef LIBCURL_FEATURE_SSL
864 if (use_ssl) { 850 if (use_ssl) {
865 if (check_cert) { 851 if (check_cert) {
866 if (is_openssl_callback) { 852 if (is_openssl_callback) {
867#ifdef USE_OPENSSL 853# ifdef USE_OPENSSL
868 /* check certificate with OpenSSL functions, curl has been built against OpenSSL 854 /* check certificate with OpenSSL functions, curl has been built against OpenSSL
869 * and we actually have OpenSSL in the monitoring tools 855 * and we actually have OpenSSL in the monitoring tools
870 */ 856 */
871 result_ssl = 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);
872 if (!continue_after_check_cert) { 858 if (!continue_after_check_cert) {
873 return result_ssl; 859 return result_ssl;
874 } 860 }
875#else /* USE_OPENSSL */ 861# else /* USE_OPENSSL */
876 die (STATE_CRITICAL, "HTTP CRITICAL - Cannot retrieve certificates - OpenSSL callback used and not linked against OpenSSL\n"); 862 die(STATE_CRITICAL,
877#endif /* USE_OPENSSL */ 863 "HTTP CRITICAL - Cannot retrieve certificates - OpenSSL callback used and not linked against OpenSSL\n");
878 } else { 864# endif /* USE_OPENSSL */
879 int i; 865 } else {
880 struct curl_slist *slist; 866 int i;
881 867 struct curl_slist *slist;
882 cert_ptr.to_info = NULL; 868
883 res = curl_easy_getinfo (curl, CURLINFO_CERTINFO, &cert_ptr.to_info); 869 cert_ptr.to_info = NULL;
884 if (!res && cert_ptr.to_info) { 870 res = curl_easy_getinfo(curl, CURLINFO_CERTINFO, &cert_ptr.to_info);
885#ifdef USE_OPENSSL 871 if (!res && cert_ptr.to_info) {
886 /* We have no OpenSSL in libcurl, but we can use OpenSSL for X509 cert parsing 872# ifdef USE_OPENSSL
887 * 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
888 */ 874 * We only check the first certificate and assume it's the one of the server
889 const char* raw_cert = NULL; 875 */
890 for (i = 0; i < cert_ptr.to_certinfo->num_of_certs; i++) { 876 const char *raw_cert = NULL;
891 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++) {
892 if (verbose >= 2) 878 for (slist = cert_ptr.to_certinfo->certinfo[i]; slist; slist = slist->next) {
893 printf ("%d ** %s\n", i, slist->data); 879 if (verbose >= 2)
894 if (strncmp (slist->data, "Cert:", 5) == 0) { 880 printf("%d ** %s\n", i, slist->data);
895 raw_cert = &slist->data[5]; 881 if (strncmp(slist->data, "Cert:", 5) == 0) {
896 goto GOT_FIRST_CERT; 882 raw_cert = &slist->data[5];
897 } 883 goto GOT_FIRST_CERT;
898 } 884 }
899 } 885 }
900GOT_FIRST_CERT: 886 }
901 if (!raw_cert) { 887 GOT_FIRST_CERT:
902 snprintf (msg, 888 if (!raw_cert) {
903 DEFAULT_BUFFER_SIZE, 889 snprintf(msg, DEFAULT_BUFFER_SIZE,
904 _("Cannot retrieve certificates from CERTINFO information - certificate data was empty")); 890 _("Cannot retrieve certificates from CERTINFO information - certificate data was empty"));
905 die (STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg); 891 die(STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg);
906 } 892 }
907 BIO* cert_BIO = BIO_new (BIO_s_mem()); 893 BIO *cert_BIO = BIO_new(BIO_s_mem());
908 BIO_write (cert_BIO, raw_cert, strlen(raw_cert)); 894 BIO_write(cert_BIO, raw_cert, strlen(raw_cert));
909 cert = PEM_read_bio_X509 (cert_BIO, NULL, NULL, NULL); 895 cert = PEM_read_bio_X509(cert_BIO, NULL, NULL, NULL);
910 if (!cert) { 896 if (!cert) {
911 snprintf (msg, 897 snprintf(msg, DEFAULT_BUFFER_SIZE, _("Cannot read certificate from CERTINFO information - BIO error"));
912 DEFAULT_BUFFER_SIZE, 898 die(STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg);
913 _("Cannot read certificate from CERTINFO information - BIO error")); 899 }
914 die (STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg); 900 BIO_free(cert_BIO);
915 } 901 result_ssl = np_net_ssl_check_certificate(cert, days_till_exp_warn, days_till_exp_crit);
916 BIO_free (cert_BIO); 902 if (!continue_after_check_cert) {
917 result_ssl = np_net_ssl_check_certificate(cert, days_till_exp_warn, days_till_exp_crit); 903 return result_ssl;
918 if (!continue_after_check_cert) { 904 }
919 return result_ssl; 905# else /* USE_OPENSSL */
920 } 906 /* We assume we don't have OpenSSL and np_net_ssl_check_certificate at our disposal,
921#else /* USE_OPENSSL */ 907 * so we use the libcurl CURLINFO data
922 /* We assume we don't have OpenSSL and np_net_ssl_check_certificate at our disposal, 908 */
923 * so we use the libcurl CURLINFO data 909 result_ssl = net_noopenssl_check_certificate(&cert_ptr, days_till_exp_warn, days_till_exp_crit);
924 */ 910 if (!continue_after_check_cert) {
925 result_ssl = net_noopenssl_check_certificate(&cert_ptr, days_till_exp_warn, days_till_exp_crit); 911 return result_ssl;
926 if (!continue_after_check_cert) { 912 }
927 return result_ssl; 913# endif /* USE_OPENSSL */
928 } 914 } else {
929#endif /* USE_OPENSSL */ 915 snprintf(msg, DEFAULT_BUFFER_SIZE, _("Cannot retrieve certificates - cURL returned %d - %s"), res,
930 } else { 916 curl_easy_strerror(res));
931 snprintf (msg, 917 die(STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg);
932 DEFAULT_BUFFER_SIZE, 918 }
933 _("Cannot retrieve certificates - cURL returned %d - %s"), 919 }
934 res, 920 }
935 curl_easy_strerror(res)); 921 }
936 die (STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg);
937 }
938 }
939 }
940 }
941#endif /* LIBCURL_FEATURE_SSL */ 922#endif /* LIBCURL_FEATURE_SSL */
942 923
943 /* 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
944 * performance data to the answer always 925 * performance data to the answer always
945 */ 926 */
946 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");
947 page_len = get_content_length(&header_buf, &body_buf); 928 page_len = get_content_length(&header_buf, &body_buf);
948 if(show_extended_perfdata) { 929 if (show_extended_perfdata) {
949 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");
950 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");
951 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");
952 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),
953 snprintf(perfstring, DEFAULT_BUFFER_SIZE, "%s %s %s %s %s %s %s", 934 "CURLINFO_STARTTRANSFER_TIME");
954 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),
955 perfd_size(page_len), 936 perfd_time_connect(time_connect), use_ssl ? perfd_time_ssl(time_appconnect - time_connect) : "",
956 perfd_time_connect(time_connect), 937 perfd_time_headers(time_headers - time_appconnect), perfd_time_firstbyte(time_firstbyte - time_headers),
957 use_ssl ? perfd_time_ssl (time_appconnect-time_connect) : "", 938 perfd_time_transfer(total_time - time_firstbyte));
958 perfd_time_headers(time_headers - time_appconnect), 939 } else {
959 perfd_time_firstbyte(time_firstbyte - time_headers), 940 snprintf(perfstring, DEFAULT_BUFFER_SIZE, "%s %s", perfd_time(total_time), perfd_size(page_len));
960 perfd_time_transfer(total_time-time_firstbyte) 941 }
961 );
962 } else {
963 snprintf(perfstring, DEFAULT_BUFFER_SIZE, "%s %s",
964 perfd_time(total_time),
965 perfd_size(page_len)
966 );
967 }
968
969 /* return a CRITICAL status if we couldn't read any data */
970 if (strlen(header_buf.buf) == 0 && strlen(body_buf.buf) == 0)
971 die (STATE_CRITICAL, _("HTTP CRITICAL - No header received from host\n"));
972
973 /* get status line of answer, check sanity of HTTP code */
974 if (curlhelp_parse_statusline (header_buf.buf, &status_line) < 0) {
975 snprintf (msg,
976 DEFAULT_BUFFER_SIZE,
977 "Unparsable status line in %.3g seconds response time|%s\n",
978 total_time,
979 perfstring);
980 /* we cannot know the major/minor version here for sure as we cannot parse the first line */
981 die (STATE_CRITICAL, "HTTP CRITICAL HTTP/x.x %ld unknown - %s", code, msg);
982 }
983 status_line_initialized = true;
984
985 /* get result code from cURL */
986 handle_curl_option_return_code (curl_easy_getinfo (curl, CURLINFO_RESPONSE_CODE, &code), "CURLINFO_RESPONSE_CODE");
987 if (verbose>=2)
988 printf ("* curl CURLINFO_RESPONSE_CODE is %ld\n", code);
989
990 /* print status line, header, body if verbose */
991 if (verbose >= 2) {
992 printf ("**** HEADER ****\n%s\n**** CONTENT ****\n%s\n", header_buf.buf,
993 (no_body ? " [[ skipped ]]" : body_buf.buf));
994 }
995
996 /* make sure the status line matches the response we are looking for */
997 if (!expected_statuscode(status_line.first_line, server_expect)) {
998 if (server_port == HTTP_PORT)
999 snprintf(msg,
1000 DEFAULT_BUFFER_SIZE,
1001 _("Invalid HTTP response received from host: %s\n"),
1002 status_line.first_line);
1003 else
1004 snprintf(msg,
1005 DEFAULT_BUFFER_SIZE,
1006 _("Invalid HTTP response received from host on port %d: %s\n"),
1007 server_port,
1008 status_line.first_line);
1009 die (STATE_CRITICAL, "HTTP CRITICAL - %s%s%s", msg,
1010 show_body ? "\n" : "",
1011 show_body ? body_buf.buf : "");
1012 }
1013
1014 if( server_expect_yn ) {
1015 snprintf(msg, DEFAULT_BUFFER_SIZE, _("Status line output matched \"%s\" - "), server_expect);
1016 if (verbose)
1017 printf ("%s\n",msg);
1018 result = STATE_OK;
1019 }
1020 else {
1021 /* illegal return codes result in a critical state */
1022 if (code >= 600 || code < 100) {
1023 die (STATE_CRITICAL, _("HTTP CRITICAL: Invalid Status (%d, %.40s)\n"), status_line.http_code, status_line.msg);
1024 /* server errors result in a critical state */
1025 } else if (code >= 500) {
1026 result = STATE_CRITICAL;
1027 /* client errors result in a warning state */
1028 } else if (code >= 400) {
1029 result = STATE_WARNING;
1030 /* check redirected page if specified */
1031 } else if (code >= 300) {
1032 if (onredirect == STATE_DEPENDENT) {
1033 if( followmethod == FOLLOW_LIBCURL ) {
1034 code = status_line.http_code;
1035 } else {
1036 /* old check_http style redirection, if we come
1037 * back here, we are in the same status as with
1038 * the libcurl method
1039 */
1040 redir (&header_buf);
1041 }
1042 } else {
1043 /* this is a specific code in the command line to
1044 * be returned when a redirection is encountered
1045 */
1046 }
1047 result = max_state_alt (onredirect, result);
1048 /* all other codes are considered ok */
1049 } else {
1050 result = STATE_OK;
1051 }
1052 }
1053
1054 /* libcurl redirection internally, handle error states here */
1055 if( followmethod == FOLLOW_LIBCURL ) {
1056 handle_curl_option_return_code (curl_easy_getinfo (curl, CURLINFO_REDIRECT_COUNT, &redir_depth), "CURLINFO_REDIRECT_COUNT");
1057 if (verbose >= 2)
1058 printf(_("* curl LIBINFO_REDIRECT_COUNT is %d\n"), redir_depth);
1059 if (redir_depth > max_depth) {
1060 snprintf (msg, DEFAULT_BUFFER_SIZE, "maximum redirection depth %d exceeded in libcurl",
1061 max_depth);
1062 die (STATE_WARNING, "HTTP WARNING - %s", msg);
1063 }
1064 }
1065
1066 /* check status codes, set exit status accordingly */
1067 if( status_line.http_code != code ) {
1068 die (STATE_CRITICAL, _("HTTP CRITICAL %s %d %s - different HTTP codes (cUrl has %ld)\n"),
1069 string_statuscode (status_line.http_major, status_line.http_minor),
1070 status_line.http_code, status_line.msg, code);
1071 }
1072
1073 if (maximum_age >= 0) {
1074 result = max_state_alt(check_document_dates(&header_buf, &msg), result);
1075 }
1076
1077 /* Page and Header content checks go here */
1078
1079 if (strlen (header_expect)) {
1080 if (!strstr (header_buf.buf, header_expect)) {
1081
1082 strncpy(&output_header_search[0],header_expect,sizeof(output_header_search));
1083
1084 if(output_header_search[sizeof(output_header_search)-1]!='\0') {
1085 bcopy("...",&output_header_search[sizeof(output_header_search)-4],4);
1086 }
1087 942
1088 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"));
1089 946
1090 snprintf (tmp, 947 /* get status line of answer, check sanity of HTTP code */
1091 DEFAULT_BUFFER_SIZE, 948 if (curlhelp_parse_statusline(header_buf.buf, &status_line) < 0) {
1092 _("%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);
1093 msg, 950 /* we cannot know the major/minor version here for sure as we cannot parse the first line */
1094 output_header_search, 951 die(STATE_CRITICAL, "HTTP CRITICAL HTTP/x.x %ld unknown - %s", code, msg);
1095 use_ssl ? "https" : "http", 952 }
1096 host_name ? host_name : server_address, 953 status_line_initialized = true;
1097 server_port,
1098 server_url);
1099 954
1100 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);
1101 959
1102 result = STATE_CRITICAL; 960 /* print status line, header, body if verbose */
1103 } 961 if (verbose >= 2) {
1104 } 962 printf("**** HEADER ****\n%s\n**** CONTENT ****\n%s\n", header_buf.buf, (no_body ? " [[ skipped ]]" : body_buf.buf));
963 }
1105 964
1106 if (strlen (string_expect)) { 965 /* make sure the status line matches the response we are looking for */
1107 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 }
1108 974
1109 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 }
1110 1013
1111 if(output_string_search[sizeof(output_string_search)-1]!='\0') { 1014 /* libcurl redirection internally, handle error states here */
1112 bcopy("...",&output_string_search[sizeof(output_string_search)-4],4); 1015 if (followmethod == FOLLOW_LIBCURL) {
1113 } 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 }
1114 1065
1115 char tmp[DEFAULT_BUFFER_SIZE]; 1066 char tmp[DEFAULT_BUFFER_SIZE];
1116 1067
1117 snprintf (tmp, 1068 snprintf(tmp, DEFAULT_BUFFER_SIZE, _("%sstring '%s' not found on '%s://%s:%d%s', "), msg, output_string_search,
1118 DEFAULT_BUFFER_SIZE, 1069 use_ssl ? "https" : "http", host_name ? host_name : server_address, server_port, server_url);
1119 _("%sstring '%s' not found on '%s://%s:%d%s', "),
1120 msg,
1121 output_string_search,
1122 use_ssl ? "https" : "http",
1123 host_name ? host_name : server_address,
1124 server_port,
1125 server_url);
1126 1070
1127 strcpy(msg, tmp); 1071 strcpy(msg, tmp);
1128 1072
1129 result = STATE_CRITICAL; 1073 result = STATE_CRITICAL;
1130 } 1074 }
1131 } 1075 }
1132 1076
1133 if (strlen (regexp)) { 1077 if (strlen(regexp)) {
1134 errcode = regexec (&preg, body_buf.buf, REGS, pmatch, 0); 1078 errcode = regexec(&preg, body_buf.buf, REGS, pmatch, 0);
1135 if ((errcode == 0 && !invert_regex) || (errcode == REG_NOMATCH && invert_regex)) { 1079 if ((errcode == 0 && !invert_regex) || (errcode == REG_NOMATCH && invert_regex)) {
1136 /* OK - No-op to avoid changing the logic around it */ 1080 /* OK - No-op to avoid changing the logic around it */
1137 result = max_state_alt(STATE_OK, result); 1081 result = max_state_alt(STATE_OK, result);
1138 } 1082 } else if ((errcode == REG_NOMATCH && !invert_regex) || (errcode == 0 && invert_regex)) {
1139 else if ((errcode == REG_NOMATCH && !invert_regex) || (errcode == 0 && invert_regex)) {
1140 if (!invert_regex) { 1083 if (!invert_regex) {
1141 char tmp[DEFAULT_BUFFER_SIZE]; 1084 char tmp[DEFAULT_BUFFER_SIZE];
1142 1085
1143 snprintf (tmp, DEFAULT_BUFFER_SIZE, _("%spattern not found, "), msg); 1086 snprintf(tmp, DEFAULT_BUFFER_SIZE, _("%spattern not found, "), msg);
1144 strcpy(msg, tmp); 1087 strcpy(msg, tmp);
1145 1088
1146 } else { 1089 } else {
1147 char tmp[DEFAULT_BUFFER_SIZE]; 1090 char tmp[DEFAULT_BUFFER_SIZE];
1148 1091
1149 snprintf (tmp, DEFAULT_BUFFER_SIZE, _("%spattern found, "), msg); 1092 snprintf(tmp, DEFAULT_BUFFER_SIZE, _("%spattern found, "), msg);
1150 strcpy(msg, tmp); 1093 strcpy(msg, tmp);
1151
1152 } 1094 }
1153 result = state_regex; 1095 result = state_regex;
1154 } else { 1096 } else {
1155 regerror (errcode, &preg, errbuf, MAX_INPUT_BUFFER); 1097 regerror(errcode, &preg, errbuf, MAX_INPUT_BUFFER);
1156 1098
1157 char tmp[DEFAULT_BUFFER_SIZE]; 1099 char tmp[DEFAULT_BUFFER_SIZE];
1158 1100
1159 snprintf (tmp, DEFAULT_BUFFER_SIZE, _("%sExecute Error: %s, "), msg, errbuf); 1101 snprintf(tmp, DEFAULT_BUFFER_SIZE, _("%sExecute Error: %s, "), msg, errbuf);
1160 strcpy(msg, tmp); 1102 strcpy(msg, tmp);
1161 result = STATE_UNKNOWN; 1103 result = STATE_UNKNOWN;
1162 } 1104 }
1163 } 1105 }
1164 1106
1165 /* make sure the page is of an appropriate size */ 1107 /* make sure the page is of an appropriate size */
1166 if ((max_page_len > 0) && (page_len > max_page_len)) { 1108 if ((max_page_len > 0) && (page_len > max_page_len)) {
1167 char tmp[DEFAULT_BUFFER_SIZE]; 1109 char tmp[DEFAULT_BUFFER_SIZE];
1168 1110
1169 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);
1170 1112
1171 strcpy(msg, tmp); 1113 strcpy(msg, tmp);
1172 1114
@@ -1175,1281 +1117,1230 @@ GOT_FIRST_CERT:
1175 } else if ((min_page_len > 0) && (page_len < min_page_len)) { 1117 } else if ((min_page_len > 0) && (page_len < min_page_len)) {
1176 char tmp[DEFAULT_BUFFER_SIZE]; 1118 char tmp[DEFAULT_BUFFER_SIZE];
1177 1119
1178 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);
1179 strcpy(msg, tmp); 1121 strcpy(msg, tmp);
1180 result = max_state_alt(STATE_WARNING, result); 1122 result = max_state_alt(STATE_WARNING, result);
1181 } 1123 }
1182 1124
1183 /* -w, -c: check warning and critical level */ 1125 /* -w, -c: check warning and critical level */
1184 result = max_state_alt(get_status(total_time, thlds), result); 1126 result = max_state_alt(get_status(total_time, thlds), result);
1185 1127
1186 /* Cut-off trailing characters */ 1128 /* Cut-off trailing characters */
1187 if (strlen(msg) >= 2) { 1129 if (strlen(msg) >= 2) {
1188 if(msg[strlen(msg)-2] == ',') 1130 if (msg[strlen(msg) - 2] == ',')
1189 msg[strlen(msg)-2] = '\0'; 1131 msg[strlen(msg) - 2] = '\0';
1190 else 1132 else
1191 msg[strlen(msg)-3] = '\0'; 1133 msg[strlen(msg) - 3] = '\0';
1192 } 1134 }
1193 1135
1194 /* 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); */
1195 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", 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),
1196 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,
1197 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 : ""),
1198 strlen(msg) > 0 ? " - " : "", 1140 (show_body ? "\n" : ""));
1199 msg, page_len, total_time, 1141
1200 (display_html ? "</A>" : ""), 1142 return max_state_alt(result, result_ssl);
1201 perfstring,
1202 (show_body ? body_buf.buf : ""),
1203 (show_body ? "\n" : "") );
1204
1205 return max_state_alt(result, result_ssl);
1206} 1143}
1207 1144
1208int 1145int uri_strcmp(const UriTextRangeA range, const char *s) {
1209uri_strcmp (const UriTextRangeA range, const char* s) 1146 if (!range.first)
1210{ 1147 return -1;
1211 if (!range.first) return -1; 1148 if ((size_t)(range.afterLast - range.first) < strlen(s))
1212 if ( (size_t)(range.afterLast - range.first) < strlen (s) ) return -1; 1149 return -1;
1213 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)));
1214} 1151}
1215 1152
1216char* 1153char *uri_string(const UriTextRangeA range, char *buf, size_t buflen) {
1217uri_string (const UriTextRangeA range, char* buf, size_t buflen) 1154 if (!range.first)
1218{ 1155 return "(null)";
1219 if (!range.first) return "(null)"; 1156 strncpy(buf, range.first, max(buflen - 1, (size_t)(range.afterLast - range.first)));
1220 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';
1221 buf[max (buflen-1, (size_t)(range.afterLast - range.first))] = '\0'; 1158 buf[range.afterLast - range.first] = '\0';
1222 buf[range.afterLast - range.first] = '\0'; 1159 return buf;
1223 return buf;
1224} 1160}
1225 1161
1226void 1162void redir(curlhelp_write_curlbuf *header_buf) {
1227redir (curlhelp_write_curlbuf* header_buf) 1163 char *location = NULL;
1228{ 1164 curlhelp_statusline status_line;
1229 char *location = NULL; 1165 struct phr_header headers[255];
1230 curlhelp_statusline status_line; 1166 size_t nof_headers = 255;
1231 struct phr_header headers[255]; 1167 size_t msglen;
1232 size_t nof_headers = 255; 1168 char buf[DEFAULT_BUFFER_SIZE];
1233 size_t msglen; 1169 char ipstr[INET_ADDR_MAX_SIZE];
1234 char buf[DEFAULT_BUFFER_SIZE]; 1170 int new_port;
1235 char ipstr[INET_ADDR_MAX_SIZE]; 1171 char *new_host;
1236 int new_port; 1172 char *new_url;
1237 char *new_host; 1173
1238 char *new_url; 1174 int res = phr_parse_response(header_buf->buf, header_buf->buflen, &status_line.http_major, &status_line.http_minor,
1239 1175 &status_line.http_code, &status_line.msg, &msglen, headers, &nof_headers, 0);
1240 int res = phr_parse_response (header_buf->buf, header_buf->buflen,
1241 &status_line.http_major, &status_line.http_minor, &status_line.http_code, &status_line.msg, &msglen,
1242 headers, &nof_headers, 0);
1243 1176
1244 if (res == -1) { 1177 if (res == -1) {
1245 die (STATE_UNKNOWN, _("HTTP UNKNOWN - Failed to parse Response\n")); 1178 die(STATE_UNKNOWN, _("HTTP UNKNOWN - Failed to parse Response\n"));
1246 } 1179 }
1247 1180
1248 location = get_header_value (headers, nof_headers, "location"); 1181 location = get_header_value(headers, nof_headers, "location");
1249 1182
1250 if (verbose >= 2) 1183 if (verbose >= 2)
1251 printf(_("* Seen redirect location %s\n"), location); 1184 printf(_("* Seen redirect location %s\n"), location);
1252 1185
1253 if (++redir_depth > max_depth) 1186 if (++redir_depth > max_depth)
1254 die (STATE_WARNING, 1187 die(STATE_WARNING, _("HTTP WARNING - maximum redirection depth %d exceeded - %s%s\n"), max_depth, location,
1255 _("HTTP WARNING - maximum redirection depth %d exceeded - %s%s\n"), 1188 (display_html ? "</A>" : ""));
1256 max_depth, location, (display_html ? "</A>" : "")); 1189
1257 1190 UriParserStateA state;
1258 UriParserStateA state; 1191 UriUriA uri;
1259 UriUriA uri; 1192 state.uri = &uri;
1260 state.uri = &uri; 1193 if (uriParseUriA(&state, location) != URI_SUCCESS) {
1261 if (uriParseUriA (&state, location) != URI_SUCCESS) { 1194 if (state.errorCode == URI_ERROR_SYNTAX) {
1262 if (state.errorCode == URI_ERROR_SYNTAX) { 1195 die(STATE_UNKNOWN, _("HTTP UNKNOWN - Could not parse redirect location '%s'%s\n"), location, (display_html ? "</A>" : ""));
1263 die (STATE_UNKNOWN, 1196 } else if (state.errorCode == URI_ERROR_MALLOC) {
1264 _("HTTP UNKNOWN - Could not parse redirect location '%s'%s\n"), 1197 die(STATE_UNKNOWN, _("HTTP UNKNOWN - Could not allocate URL\n"));
1265 location, (display_html ? "</A>" : "")); 1198 }
1266 } else if (state.errorCode == URI_ERROR_MALLOC) { 1199 }
1267 die (STATE_UNKNOWN, _("HTTP UNKNOWN - Could not allocate URL\n")); 1200
1268 } 1201 if (verbose >= 2) {
1269 } 1202 printf(_("** scheme: %s\n"), uri_string(uri.scheme, buf, DEFAULT_BUFFER_SIZE));
1270 1203 printf(_("** host: %s\n"), uri_string(uri.hostText, buf, DEFAULT_BUFFER_SIZE));
1271 if (verbose >= 2) { 1204 printf(_("** port: %s\n"), uri_string(uri.portText, buf, DEFAULT_BUFFER_SIZE));
1272 printf (_("** scheme: %s\n"), 1205 if (uri.hostData.ip4) {
1273 uri_string (uri.scheme, buf, DEFAULT_BUFFER_SIZE)); 1206 inet_ntop(AF_INET, uri.hostData.ip4->data, ipstr, sizeof(ipstr));
1274 printf (_("** host: %s\n"), 1207 printf(_("** IPv4: %s\n"), ipstr);
1275 uri_string (uri.hostText, buf, DEFAULT_BUFFER_SIZE)); 1208 }
1276 printf (_("** port: %s\n"), 1209 if (uri.hostData.ip6) {
1277 uri_string (uri.portText, buf, DEFAULT_BUFFER_SIZE)); 1210 inet_ntop(AF_INET, uri.hostData.ip6->data, ipstr, sizeof(ipstr));
1278 if (uri.hostData.ip4) { 1211 printf(_("** IPv6: %s\n"), ipstr);
1279 inet_ntop (AF_INET, uri.hostData.ip4->data, ipstr, sizeof (ipstr)); 1212 }
1280 printf (_("** IPv4: %s\n"), ipstr); 1213 if (uri.pathHead) {
1281 } 1214 printf(_("** path: "));
1282 if (uri.hostData.ip6) { 1215 const UriPathSegmentA *p = uri.pathHead;
1283 inet_ntop (AF_INET, uri.hostData.ip6->data, ipstr, sizeof (ipstr)); 1216 for (; p; p = p->next) {
1284 printf (_("** IPv6: %s\n"), ipstr); 1217 printf("/%s", uri_string(p->text, buf, DEFAULT_BUFFER_SIZE));
1285 } 1218 }
1286 if (uri.pathHead) { 1219 puts("");
1287 printf (_("** path: ")); 1220 }
1288 const UriPathSegmentA* p = uri.pathHead; 1221 if (uri.query.first) {
1289 for (; p; p = p->next) { 1222 printf(_("** query: %s\n"), uri_string(uri.query, buf, DEFAULT_BUFFER_SIZE));
1290 printf ("/%s", uri_string (p->text, buf, DEFAULT_BUFFER_SIZE)); 1223 }
1291 } 1224 if (uri.fragment.first) {
1292 puts (""); 1225 printf(_("** fragment: %s\n"), uri_string(uri.fragment, buf, DEFAULT_BUFFER_SIZE));
1293 } 1226 }
1294 if (uri.query.first) { 1227 }
1295 printf (_("** query: %s\n"), 1228
1296 uri_string (uri.query, buf, DEFAULT_BUFFER_SIZE)); 1229 if (uri.scheme.first) {
1297 } 1230 if (!uri_strcmp(uri.scheme, "https"))
1298 if (uri.fragment.first) { 1231 use_ssl = true;
1299 printf (_("** fragment: %s\n"), 1232 else
1300 uri_string (uri.fragment, buf, DEFAULT_BUFFER_SIZE)); 1233 use_ssl = false;
1301 } 1234 }
1302 } 1235
1303 1236 /* we do a sloppy test here only, because uriparser would have failed
1304 if (uri.scheme.first) { 1237 * above, if the port would be invalid, we just check for MAX_PORT
1305 if (!uri_strcmp (uri.scheme, "https")) 1238 */
1306 use_ssl = true; 1239 if (uri.portText.first) {
1307 else 1240 new_port = atoi(uri_string(uri.portText, buf, DEFAULT_BUFFER_SIZE));
1308 use_ssl = false; 1241 } else {
1309 } 1242 new_port = HTTP_PORT;
1310 1243 if (use_ssl)
1311 /* we do a sloppy test here only, because uriparser would have failed 1244 new_port = HTTPS_PORT;
1312 * above, if the port would be invalid, we just check for MAX_PORT 1245 }
1313 */ 1246 if (new_port > MAX_PORT)
1314 if (uri.portText.first) { 1247 die(STATE_UNKNOWN, _("HTTP UNKNOWN - Redirection to port above %d - %s%s\n"), MAX_PORT, location, display_html ? "</A>" : "");
1315 new_port = atoi (uri_string (uri.portText, buf, DEFAULT_BUFFER_SIZE)); 1248
1316 } else { 1249 /* by RFC 7231 relative URLs in Location should be taken relative to
1317 new_port = HTTP_PORT; 1250 * the original URL, so we try to form a new absolute URL here
1318 if (use_ssl) 1251 */
1319 new_port = HTTPS_PORT; 1252 if (!uri.scheme.first && !uri.hostText.first) {
1320 } 1253 new_host = strdup(host_name ? host_name : server_address);
1321 if (new_port > MAX_PORT) 1254 new_port = server_port;
1322 die (STATE_UNKNOWN, 1255 if (use_ssl)
1323 _("HTTP UNKNOWN - Redirection to port above %d - %s%s\n"), 1256 uri_string(uri.scheme, "https", DEFAULT_BUFFER_SIZE);
1324 MAX_PORT, location, display_html ? "</A>" : ""); 1257 } else {
1325 1258 new_host = strdup(uri_string(uri.hostText, buf, DEFAULT_BUFFER_SIZE));
1326 /* by RFC 7231 relative URLs in Location should be taken relative to 1259 }
1327 * the original URL, so we try to form a new absolute URL here 1260
1328 */ 1261 /* compose new path */
1329 if (!uri.scheme.first && !uri.hostText.first) { 1262 /* TODO: handle fragments and query part of URL */
1330 new_host = strdup (host_name ? host_name : server_address); 1263 new_url = (char *)calloc(1, DEFAULT_BUFFER_SIZE);
1331 new_port = server_port; 1264 if (uri.pathHead) {
1332 if(use_ssl) 1265 const UriPathSegmentA *p = uri.pathHead;
1333 uri_string (uri.scheme, "https", DEFAULT_BUFFER_SIZE); 1266 for (; p; p = p->next) {
1334 } else { 1267 strncat(new_url, "/", DEFAULT_BUFFER_SIZE);
1335 new_host = strdup (uri_string (uri.hostText, buf, DEFAULT_BUFFER_SIZE)); 1268 strncat(new_url, uri_string(p->text, buf, DEFAULT_BUFFER_SIZE), DEFAULT_BUFFER_SIZE - 1);
1336 } 1269 }
1337 1270 }
1338 /* compose new path */ 1271
1339 /* TODO: handle fragments and query part of URL */ 1272 if (server_port == new_port && !strncmp(server_address, new_host, MAX_IPV4_HOSTLENGTH) &&
1340 new_url = (char *)calloc( 1, DEFAULT_BUFFER_SIZE); 1273 (host_name && !strncmp(host_name, new_host, MAX_IPV4_HOSTLENGTH)) && !strcmp(server_url, new_url))
1341 if (uri.pathHead) { 1274 die(STATE_CRITICAL, _("HTTP CRITICAL - redirection creates an infinite loop - %s://%s:%d%s%s\n"), use_ssl ? "https" : "http",
1342 const UriPathSegmentA* p = uri.pathHead; 1275 new_host, new_port, new_url, (display_html ? "</A>" : ""));
1343 for (; p; p = p->next) { 1276
1344 strncat (new_url, "/", DEFAULT_BUFFER_SIZE); 1277 /* set new values for redirected request */
1345 strncat (new_url, uri_string (p->text, buf, DEFAULT_BUFFER_SIZE), DEFAULT_BUFFER_SIZE-1); 1278
1346 } 1279 if (!(followsticky & STICKY_HOST)) {
1347 } 1280 free(server_address);
1348 1281 server_address = strndup(new_host, MAX_IPV4_HOSTLENGTH);
1349 if (server_port==new_port && 1282 }
1350 !strncmp(server_address, new_host, MAX_IPV4_HOSTLENGTH) && 1283 if (!(followsticky & STICKY_PORT)) {
1351 (host_name && !strncmp(host_name, new_host, MAX_IPV4_HOSTLENGTH)) && 1284 server_port = (unsigned short)new_port;
1352 !strcmp(server_url, new_url)) 1285 }
1353 die (STATE_CRITICAL, 1286
1354 _("HTTP CRITICAL - redirection creates an infinite loop - %s://%s:%d%s%s\n"), 1287 free(host_name);
1355 use_ssl ? "https" : "http", new_host, new_port, new_url, (display_html ? "</A>" : "")); 1288 host_name = strndup(new_host, MAX_IPV4_HOSTLENGTH);
1356 1289
1357 /* set new values for redirected request */ 1290 /* reset virtual port */
1358 1291 virtual_port = server_port;
1359 if (!(followsticky & STICKY_HOST)) { 1292
1360 free (server_address); 1293 free(new_host);
1361 server_address = strndup (new_host, MAX_IPV4_HOSTLENGTH); 1294 free(server_url);
1362 } 1295 server_url = new_url;
1363 if (!(followsticky & STICKY_PORT)) { 1296
1364 server_port = (unsigned short)new_port; 1297 uriFreeUriMembersA(&uri);
1365 } 1298
1366 1299 if (verbose)
1367 free (host_name); 1300 printf(_("Redirection to %s://%s:%d%s\n"), use_ssl ? "https" : "http", host_name ? host_name : server_address, server_port,
1368 host_name = strndup (new_host, MAX_IPV4_HOSTLENGTH); 1301 server_url);
1369 1302
1370 /* reset virtual port */ 1303 /* TODO: the hash component MUST be taken from the original URL and
1371 virtual_port = server_port; 1304 * attached to the URL in Location
1372 1305 */
1373 free(new_host); 1306
1374 free (server_url); 1307 cleanup();
1375 server_url = new_url; 1308 check_http();
1376
1377 uriFreeUriMembersA (&uri);
1378
1379 if (verbose)
1380 printf (_("Redirection to %s://%s:%d%s\n"), use_ssl ? "https" : "http",
1381 host_name ? host_name : server_address, server_port, server_url);
1382
1383 /* TODO: the hash component MUST be taken from the original URL and
1384 * attached to the URL in Location
1385 */
1386
1387 cleanup ();
1388 check_http ();
1389} 1309}
1390 1310
1391/* check whether a file exists */ 1311/* check whether a file exists */
1392void 1312void test_file(char *path) {
1393test_file (char *path) 1313 if (access(path, R_OK) == 0)
1394{ 1314 return;
1395 if (access(path, R_OK) == 0) 1315 usage2(_("file does not exist or is not readable"), path);
1396 return;
1397 usage2 (_("file does not exist or is not readable"), path);
1398} 1316}
1399 1317
1400bool 1318bool process_arguments(int argc, char **argv) {
1401process_arguments (int argc, char **argv) 1319 char *p;
1402{ 1320 int c = 1;
1403 char *p; 1321 char *temp;
1404 int c = 1; 1322
1405 char *temp; 1323 enum {
1406 1324 INVERT_REGEX = CHAR_MAX + 1,
1407 enum { 1325 SNI_OPTION,
1408 INVERT_REGEX = CHAR_MAX + 1, 1326 MAX_REDIRS_OPTION,
1409 SNI_OPTION, 1327 CONTINUE_AFTER_CHECK_CERT,
1410 MAX_REDIRS_OPTION, 1328 CA_CERT_OPTION,
1411 CONTINUE_AFTER_CHECK_CERT, 1329 HTTP_VERSION_OPTION,
1412 CA_CERT_OPTION, 1330 AUTOMATIC_DECOMPRESSION,
1413 HTTP_VERSION_OPTION, 1331 COOKIE_JAR,
1414 AUTOMATIC_DECOMPRESSION, 1332 HAPROXY_PROTOCOL,
1415 COOKIE_JAR, 1333 STATE_REGEX
1416 HAPROXY_PROTOCOL, 1334 };
1417 STATE_REGEX 1335
1418 }; 1336 int option = 0;
1419 1337 int got_plus = 0;
1420 int option = 0; 1338 static struct option longopts[] = {STD_LONG_OPTS,
1421 int got_plus = 0; 1339 {"link", no_argument, 0, 'L'},
1422 static struct option longopts[] = { 1340 {"nohtml", no_argument, 0, 'n'},
1423 STD_LONG_OPTS, 1341 {"ssl", optional_argument, 0, 'S'},
1424 {"link", no_argument, 0, 'L'}, 1342 {"sni", no_argument, 0, SNI_OPTION},
1425 {"nohtml", no_argument, 0, 'n'}, 1343 {"post", required_argument, 0, 'P'},
1426 {"ssl", optional_argument, 0, 'S'}, 1344 {"method", required_argument, 0, 'j'},
1427 {"sni", no_argument, 0, SNI_OPTION}, 1345 {"IP-address", required_argument, 0, 'I'},
1428 {"post", required_argument, 0, 'P'}, 1346 {"url", required_argument, 0, 'u'},
1429 {"method", required_argument, 0, 'j'}, 1347 {"port", required_argument, 0, 'p'},
1430 {"IP-address", required_argument, 0, 'I'}, 1348 {"authorization", required_argument, 0, 'a'},
1431 {"url", required_argument, 0, 'u'}, 1349 {"proxy-authorization", required_argument, 0, 'b'},
1432 {"port", required_argument, 0, 'p'}, 1350 {"header-string", required_argument, 0, 'd'},
1433 {"authorization", required_argument, 0, 'a'}, 1351 {"string", required_argument, 0, 's'},
1434 {"proxy-authorization", required_argument, 0, 'b'}, 1352 {"expect", required_argument, 0, 'e'},
1435 {"header-string", required_argument, 0, 'd'}, 1353 {"regex", required_argument, 0, 'r'},
1436 {"string", required_argument, 0, 's'}, 1354 {"ereg", required_argument, 0, 'r'},
1437 {"expect", required_argument, 0, 'e'}, 1355 {"eregi", required_argument, 0, 'R'},
1438 {"regex", required_argument, 0, 'r'}, 1356 {"linespan", no_argument, 0, 'l'},
1439 {"ereg", required_argument, 0, 'r'}, 1357 {"onredirect", required_argument, 0, 'f'},
1440 {"eregi", required_argument, 0, 'R'}, 1358 {"certificate", required_argument, 0, 'C'},
1441 {"linespan", no_argument, 0, 'l'}, 1359 {"client-cert", required_argument, 0, 'J'},
1442 {"onredirect", required_argument, 0, 'f'}, 1360 {"private-key", required_argument, 0, 'K'},
1443 {"certificate", required_argument, 0, 'C'}, 1361 {"ca-cert", required_argument, 0, CA_CERT_OPTION},
1444 {"client-cert", required_argument, 0, 'J'}, 1362 {"verify-cert", no_argument, 0, 'D'},
1445 {"private-key", required_argument, 0, 'K'}, 1363 {"continue-after-certificate", no_argument, 0, CONTINUE_AFTER_CHECK_CERT},
1446 {"ca-cert", required_argument, 0, CA_CERT_OPTION}, 1364 {"useragent", required_argument, 0, 'A'},
1447 {"verify-cert", no_argument, 0, 'D'}, 1365 {"header", required_argument, 0, 'k'},
1448 {"continue-after-certificate", no_argument, 0, CONTINUE_AFTER_CHECK_CERT}, 1366 {"no-body", no_argument, 0, 'N'},
1449 {"useragent", required_argument, 0, 'A'}, 1367 {"max-age", required_argument, 0, 'M'},
1450 {"header", required_argument, 0, 'k'}, 1368 {"content-type", required_argument, 0, 'T'},
1451 {"no-body", no_argument, 0, 'N'}, 1369 {"pagesize", required_argument, 0, 'm'},
1452 {"max-age", required_argument, 0, 'M'}, 1370 {"invert-regex", no_argument, NULL, INVERT_REGEX},
1453 {"content-type", required_argument, 0, 'T'}, 1371 {"state-regex", required_argument, 0, STATE_REGEX},
1454 {"pagesize", required_argument, 0, 'm'}, 1372 {"use-ipv4", no_argument, 0, '4'},
1455 {"invert-regex", no_argument, NULL, INVERT_REGEX}, 1373 {"use-ipv6", no_argument, 0, '6'},
1456 {"state-regex", required_argument, 0, STATE_REGEX}, 1374 {"extended-perfdata", no_argument, 0, 'E'},
1457 {"use-ipv4", no_argument, 0, '4'}, 1375 {"show-body", no_argument, 0, 'B'},
1458 {"use-ipv6", no_argument, 0, '6'}, 1376 {"max-redirs", required_argument, 0, MAX_REDIRS_OPTION},
1459 {"extended-perfdata", no_argument, 0, 'E'}, 1377 {"http-version", required_argument, 0, HTTP_VERSION_OPTION},
1460 {"show-body", no_argument, 0, 'B'}, 1378 {"enable-automatic-decompression", no_argument, 0, AUTOMATIC_DECOMPRESSION},
1461 {"max-redirs", required_argument, 0, MAX_REDIRS_OPTION}, 1379 {"cookie-jar", required_argument, 0, COOKIE_JAR},
1462 {"http-version", required_argument, 0, HTTP_VERSION_OPTION}, 1380 {"haproxy-protocol", no_argument, 0, HAPROXY_PROTOCOL},
1463 {"enable-automatic-decompression", no_argument, 0, AUTOMATIC_DECOMPRESSION}, 1381 {0, 0, 0, 0}};
1464 {"cookie-jar", required_argument, 0, COOKIE_JAR}, 1382
1465 {"haproxy-protocol", no_argument, 0, HAPROXY_PROTOCOL}, 1383 if (argc < 2)
1466 {0, 0, 0, 0} 1384 return false;
1467 }; 1385
1468 1386 /* support check_http compatible arguments */
1469 if (argc < 2) 1387 for (c = 1; c < argc; c++) {
1470 return false; 1388 if (strcmp("-to", argv[c]) == 0)
1471 1389 strcpy(argv[c], "-t");
1472 /* support check_http compatible arguments */ 1390 if (strcmp("-hn", argv[c]) == 0)
1473 for (c = 1; c < argc; c++) { 1391 strcpy(argv[c], "-H");
1474 if (strcmp ("-to", argv[c]) == 0) 1392 if (strcmp("-wt", argv[c]) == 0)
1475 strcpy (argv[c], "-t"); 1393 strcpy(argv[c], "-w");
1476 if (strcmp ("-hn", argv[c]) == 0) 1394 if (strcmp("-ct", argv[c]) == 0)
1477 strcpy (argv[c], "-H"); 1395 strcpy(argv[c], "-c");
1478 if (strcmp ("-wt", argv[c]) == 0) 1396 if (strcmp("-nohtml", argv[c]) == 0)
1479 strcpy (argv[c], "-w"); 1397 strcpy(argv[c], "-n");
1480 if (strcmp ("-ct", argv[c]) == 0) 1398 }
1481 strcpy (argv[c], "-c"); 1399
1482 if (strcmp ("-nohtml", argv[c]) == 0) 1400 server_url = strdup(DEFAULT_SERVER_URL);
1483 strcpy (argv[c], "-n"); 1401
1484 } 1402 while (1) {
1485 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);
1486 server_url = strdup(DEFAULT_SERVER_URL); 1404 if (c == -1 || c == EOF || c == 1)
1487 1405 break;
1488 while (1) { 1406
1489 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); 1407 switch (c) {
1490 if (c == -1 || c == EOF || c == 1) 1408 case 'h':
1491 break; 1409 print_help();
1492 1410 exit(STATE_UNKNOWN);
1493 switch (c) { 1411 break;
1494 case 'h': 1412 case 'V':
1495 print_help(); 1413 print_revision(progname, NP_VERSION);
1496 exit(STATE_UNKNOWN); 1414 print_curl_version();
1497 break; 1415 exit(STATE_UNKNOWN);
1498 case 'V': 1416 break;
1499 print_revision(progname, NP_VERSION); 1417 case 'v':
1500 print_curl_version(); 1418 verbose++;
1501 exit(STATE_UNKNOWN); 1419 break;
1502 break; 1420 case 't': /* timeout period */
1503 case 'v': 1421 if (!is_intnonneg(optarg))
1504 verbose++; 1422 usage2(_("Timeout interval must be a positive integer"), optarg);
1505 break; 1423 else
1506 case 't': /* timeout period */ 1424 socket_timeout = (int)strtol(optarg, NULL, 10);
1507 if (!is_intnonneg (optarg)) 1425 break;
1508 usage2 (_("Timeout interval must be a positive integer"), optarg); 1426 case 'c': /* critical time threshold */
1509 else 1427 critical_thresholds = optarg;
1510 socket_timeout = (int)strtol (optarg, NULL, 10); 1428 break;
1511 break; 1429 case 'w': /* warning time threshold */
1512 case 'c': /* critical time threshold */ 1430 warning_thresholds = optarg;
1513 critical_thresholds = optarg; 1431 break;
1514 break; 1432 case 'H': /* virtual host */
1515 case 'w': /* warning time threshold */ 1433 host_name = strdup(optarg);
1516 warning_thresholds = optarg; 1434 if (host_name[0] == '[') {
1517 break; 1435 if ((p = strstr(host_name, "]:")) != NULL) { /* [IPv6]:port */
1518 case 'H': /* virtual host */ 1436 virtual_port = atoi(p + 2);
1519 host_name = strdup (optarg); 1437 /* cut off the port */
1520 if (host_name[0] == '[') { 1438 host_name_length = strlen(host_name) - strlen(p) - 1;
1521 if ((p = strstr (host_name, "]:")) != NULL) { /* [IPv6]:port */ 1439 free(host_name);
1522 virtual_port = atoi (p + 2); 1440 host_name = strndup(optarg, host_name_length);
1523 /* cut off the port */ 1441 }
1524 host_name_length = strlen (host_name) - strlen (p) - 1; 1442 } else if ((p = strchr(host_name, ':')) != NULL && strchr(++p, ':') == NULL) { /* IPv4:port or host:port */
1525 free (host_name); 1443 virtual_port = atoi(p);
1526 host_name = strndup (optarg, host_name_length); 1444 /* cut off the port */
1527 } 1445 host_name_length = strlen(host_name) - strlen(p) - 1;
1528 } else if ((p = strchr (host_name, ':')) != NULL 1446 free(host_name);
1529 && strchr (++p, ':') == NULL) { /* IPv4:port or host:port */ 1447 host_name = strndup(optarg, host_name_length);
1530 virtual_port = atoi (p); 1448 }
1531 /* cut off the port */ 1449 break;
1532 host_name_length = strlen (host_name) - strlen (p) - 1; 1450 case 'I': /* internet address */
1533 free (host_name); 1451 server_address = strdup(optarg);
1534 host_name = strndup (optarg, host_name_length); 1452 break;
1535 } 1453 case 'u': /* URL path */
1536 break; 1454 server_url = strdup(optarg);
1537 case 'I': /* internet address */ 1455 break;
1538 server_address = strdup (optarg); 1456 case 'p': /* Server port */
1539 break; 1457 if (!is_intnonneg(optarg))
1540 case 'u': /* URL path */ 1458 usage2(_("Invalid port number, expecting a non-negative number"), optarg);
1541 server_url = strdup (optarg); 1459 else {
1542 break; 1460 if (strtol(optarg, NULL, 10) > MAX_PORT)
1543 case 'p': /* Server port */ 1461 usage2(_("Invalid port number, supplied port number is too big"), optarg);
1544 if (!is_intnonneg (optarg)) 1462 server_port = (unsigned short)strtol(optarg, NULL, 10);
1545 usage2 (_("Invalid port number, expecting a non-negative number"), optarg); 1463 specify_port = true;
1546 else { 1464 }
1547 if( strtol(optarg, NULL, 10) > MAX_PORT) 1465 break;
1548 usage2 (_("Invalid port number, supplied port number is too big"), optarg); 1466 case 'a': /* authorization info */
1549 server_port = (unsigned short)strtol(optarg, NULL, 10); 1467 strncpy(user_auth, optarg, MAX_INPUT_BUFFER - 1);
1550 specify_port = true; 1468 user_auth[MAX_INPUT_BUFFER - 1] = 0;
1551 } 1469 break;
1552 break; 1470 case 'b': /* proxy-authorization info */
1553 case 'a': /* authorization info */ 1471 strncpy(proxy_auth, optarg, MAX_INPUT_BUFFER - 1);
1554 strncpy (user_auth, optarg, MAX_INPUT_BUFFER - 1); 1472 proxy_auth[MAX_INPUT_BUFFER - 1] = 0;
1555 user_auth[MAX_INPUT_BUFFER - 1] = 0; 1473 break;
1556 break; 1474 case 'P': /* HTTP POST data in URL encoded format; ignored if settings already */
1557 case 'b': /* proxy-authorization info */ 1475 if (!http_post_data)
1558 strncpy (proxy_auth, optarg, MAX_INPUT_BUFFER - 1); 1476 http_post_data = strdup(optarg);
1559 proxy_auth[MAX_INPUT_BUFFER - 1] = 0; 1477 if (!http_method)
1560 break; 1478 http_method = strdup("POST");
1561 case 'P': /* HTTP POST data in URL encoded format; ignored if settings already */ 1479 break;
1562 if (! http_post_data) 1480 case 'j': /* Set HTTP method */
1563 http_post_data = strdup (optarg); 1481 if (http_method)
1564 if (! http_method) 1482 free(http_method);
1565 http_method = strdup("POST"); 1483 http_method = strdup(optarg);
1566 break; 1484 break;
1567 case 'j': /* Set HTTP method */ 1485 case 'A': /* useragent */
1568 if (http_method) 1486 strncpy(user_agent, optarg, DEFAULT_BUFFER_SIZE);
1569 free(http_method); 1487 user_agent[DEFAULT_BUFFER_SIZE - 1] = '\0';
1570 http_method = strdup (optarg); 1488 break;
1571 break; 1489 case 'k': /* Additional headers */
1572 case 'A': /* useragent */ 1490 if (http_opt_headers_count == 0)
1573 strncpy (user_agent, optarg, DEFAULT_BUFFER_SIZE); 1491 http_opt_headers = malloc(sizeof(char *) * (++http_opt_headers_count));
1574 user_agent[DEFAULT_BUFFER_SIZE-1] = '\0'; 1492 else
1575 break; 1493 http_opt_headers = realloc(http_opt_headers, sizeof(char *) * (++http_opt_headers_count));
1576 case 'k': /* Additional headers */ 1494 http_opt_headers[http_opt_headers_count - 1] = optarg;
1577 if (http_opt_headers_count == 0) 1495 break;
1578 http_opt_headers = malloc (sizeof (char *) * (++http_opt_headers_count)); 1496 case 'L': /* show html link */
1579 else 1497 display_html = true;
1580 http_opt_headers = realloc (http_opt_headers, sizeof (char *) * (++http_opt_headers_count)); 1498 break;
1581 http_opt_headers[http_opt_headers_count - 1] = optarg; 1499 case 'n': /* do not show html link */
1582 break; 1500 display_html = false;
1583 case 'L': /* show html link */ 1501 break;
1584 display_html = true; 1502 case 'C': /* Check SSL cert validity */
1585 break;
1586 case 'n': /* do not show html link */
1587 display_html = false;
1588 break;
1589 case 'C': /* Check SSL cert validity */
1590#ifdef LIBCURL_FEATURE_SSL 1503#ifdef LIBCURL_FEATURE_SSL
1591 if ((temp=strchr(optarg,','))!=NULL) { 1504 if ((temp = strchr(optarg, ',')) != NULL) {
1592 *temp='\0'; 1505 *temp = '\0';
1593 if (!is_intnonneg (optarg)) 1506 if (!is_intnonneg(optarg))
1594 usage2 (_("Invalid certificate expiration period"), optarg); 1507 usage2(_("Invalid certificate expiration period"), optarg);
1595 days_till_exp_warn = atoi(optarg); 1508 days_till_exp_warn = atoi(optarg);
1596 *temp=','; 1509 *temp = ',';
1597 temp++; 1510 temp++;
1598 if (!is_intnonneg (temp)) 1511 if (!is_intnonneg(temp))
1599 usage2 (_("Invalid certificate expiration period"), temp); 1512 usage2(_("Invalid certificate expiration period"), temp);
1600 days_till_exp_crit = atoi (temp); 1513 days_till_exp_crit = atoi(temp);
1601 } 1514 } else {
1602 else { 1515 days_till_exp_crit = 0;
1603 days_till_exp_crit=0; 1516 if (!is_intnonneg(optarg))
1604 if (!is_intnonneg (optarg)) 1517 usage2(_("Invalid certificate expiration period"), optarg);
1605 usage2 (_("Invalid certificate expiration period"), optarg); 1518 days_till_exp_warn = atoi(optarg);
1606 days_till_exp_warn = atoi (optarg); 1519 }
1607 } 1520 check_cert = true;
1608 check_cert = true; 1521 goto enable_ssl;
1609 goto enable_ssl;
1610#endif 1522#endif
1611 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 */
1612#ifdef HAVE_SSL 1524#ifdef HAVE_SSL
1613 continue_after_check_cert = true; 1525 continue_after_check_cert = true;
1614 break; 1526 break;
1615#endif 1527#endif
1616 case 'J': /* use client certificate */ 1528 case 'J': /* use client certificate */
1617#ifdef LIBCURL_FEATURE_SSL 1529#ifdef LIBCURL_FEATURE_SSL
1618 test_file(optarg); 1530 test_file(optarg);
1619 client_cert = optarg; 1531 client_cert = optarg;
1620 goto enable_ssl; 1532 goto enable_ssl;
1621#endif 1533#endif
1622 case 'K': /* use client private key */ 1534 case 'K': /* use client private key */
1623#ifdef LIBCURL_FEATURE_SSL 1535#ifdef LIBCURL_FEATURE_SSL
1624 test_file(optarg); 1536 test_file(optarg);
1625 client_privkey = optarg; 1537 client_privkey = optarg;
1626 goto enable_ssl; 1538 goto enable_ssl;
1627#endif 1539#endif
1628#ifdef LIBCURL_FEATURE_SSL 1540#ifdef LIBCURL_FEATURE_SSL
1629 case CA_CERT_OPTION: /* use CA chain file */ 1541 case CA_CERT_OPTION: /* use CA chain file */
1630 test_file(optarg); 1542 test_file(optarg);
1631 ca_cert = optarg; 1543 ca_cert = optarg;
1632 goto enable_ssl; 1544 goto enable_ssl;
1633#endif 1545#endif
1634#ifdef LIBCURL_FEATURE_SSL 1546#ifdef LIBCURL_FEATURE_SSL
1635 case 'D': /* verify peer certificate & host */ 1547 case 'D': /* verify peer certificate & host */
1636 verify_peer_and_host = true; 1548 verify_peer_and_host = true;
1637 break; 1549 break;
1638#endif 1550#endif
1639 case 'S': /* use SSL */ 1551 case 'S': /* use SSL */
1640#ifdef LIBCURL_FEATURE_SSL 1552#ifdef LIBCURL_FEATURE_SSL
1641 enable_ssl: 1553 enable_ssl:
1642 use_ssl = true; 1554 use_ssl = true;
1643 /* ssl_version initialized to CURL_SSLVERSION_DEFAULT as a default. 1555 /* ssl_version initialized to CURL_SSLVERSION_DEFAULT as a default.
1644 * 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
1645 * parameters, like -S and -C combinations */ 1557 * parameters, like -S and -C combinations */
1646 ssl_version = CURL_SSLVERSION_DEFAULT; 1558 ssl_version = CURL_SSLVERSION_DEFAULT;
1647 if (c=='S' && optarg != NULL) { 1559 if (c == 'S' && optarg != NULL) {
1648 char *plus_ptr = strchr(optarg, '+'); 1560 char *plus_ptr = strchr(optarg, '+');
1649 if (plus_ptr) { 1561 if (plus_ptr) {
1650 got_plus = 1; 1562 got_plus = 1;
1651 *plus_ptr = '\0'; 1563 *plus_ptr = '\0';
1652 } 1564 }
1653 1565
1654 if (optarg[0] == '2') 1566 if (optarg[0] == '2')
1655 ssl_version = CURL_SSLVERSION_SSLv2; 1567 ssl_version = CURL_SSLVERSION_SSLv2;
1656 else if (optarg[0] == '3') 1568 else if (optarg[0] == '3')
1657 ssl_version = CURL_SSLVERSION_SSLv3; 1569 ssl_version = CURL_SSLVERSION_SSLv3;
1658 else if (!strcmp (optarg, "1") || !strcmp (optarg, "1.0")) 1570 else if (!strcmp(optarg, "1") || !strcmp(optarg, "1.0"))
1659#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) 1571# if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0)
1660 ssl_version = CURL_SSLVERSION_TLSv1_0; 1572 ssl_version = CURL_SSLVERSION_TLSv1_0;
1661#else 1573# else
1662 ssl_version = CURL_SSLVERSION_DEFAULT; 1574 ssl_version = CURL_SSLVERSION_DEFAULT;
1663#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) */ 1575# endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) */
1664 else if (!strcmp (optarg, "1.1")) 1576 else if (!strcmp(optarg, "1.1"))
1665#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) 1577# if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0)
1666 ssl_version = CURL_SSLVERSION_TLSv1_1; 1578 ssl_version = CURL_SSLVERSION_TLSv1_1;
1667#else 1579# else
1668 ssl_version = CURL_SSLVERSION_DEFAULT; 1580 ssl_version = CURL_SSLVERSION_DEFAULT;
1669#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) */ 1581# endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) */
1670 else if (!strcmp (optarg, "1.2")) 1582 else if (!strcmp(optarg, "1.2"))
1671#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) 1583# if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0)
1672 ssl_version = CURL_SSLVERSION_TLSv1_2; 1584 ssl_version = CURL_SSLVERSION_TLSv1_2;
1673#else 1585# else
1674 ssl_version = CURL_SSLVERSION_DEFAULT; 1586 ssl_version = CURL_SSLVERSION_DEFAULT;
1675#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) */ 1587# endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) */
1676 else if (!strcmp (optarg, "1.3")) 1588 else if (!strcmp(optarg, "1.3"))
1677#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 52, 0) 1589# if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 52, 0)
1678 ssl_version = CURL_SSLVERSION_TLSv1_3; 1590 ssl_version = CURL_SSLVERSION_TLSv1_3;
1679#else 1591# else
1680 ssl_version = CURL_SSLVERSION_DEFAULT; 1592 ssl_version = CURL_SSLVERSION_DEFAULT;
1681#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 52, 0) */ 1593# endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 52, 0) */
1682 else 1594 else
1683 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)"));
1684 } 1596 }
1685#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 54, 0) 1597# if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 54, 0)
1686 if (got_plus) { 1598 if (got_plus) {
1687 switch (ssl_version) { 1599 switch (ssl_version) {
1688 case CURL_SSLVERSION_TLSv1_3: 1600 case CURL_SSLVERSION_TLSv1_3:
1689 ssl_version |= CURL_SSLVERSION_MAX_TLSv1_3; 1601 ssl_version |= CURL_SSLVERSION_MAX_TLSv1_3;
1690 break; 1602 break;
1691 case CURL_SSLVERSION_TLSv1_2: 1603 case CURL_SSLVERSION_TLSv1_2:
1692 case CURL_SSLVERSION_TLSv1_1: 1604 case CURL_SSLVERSION_TLSv1_1:
1693 case CURL_SSLVERSION_TLSv1_0: 1605 case CURL_SSLVERSION_TLSv1_0:
1694 ssl_version |= CURL_SSLVERSION_MAX_DEFAULT; 1606 ssl_version |= CURL_SSLVERSION_MAX_DEFAULT;
1695 break; 1607 break;
1696 } 1608 }
1697 } else { 1609 } else {
1698 switch (ssl_version) { 1610 switch (ssl_version) {
1699 case CURL_SSLVERSION_TLSv1_3: 1611 case CURL_SSLVERSION_TLSv1_3:
1700 ssl_version |= CURL_SSLVERSION_MAX_TLSv1_3; 1612 ssl_version |= CURL_SSLVERSION_MAX_TLSv1_3;
1701 break; 1613 break;
1702 case CURL_SSLVERSION_TLSv1_2: 1614 case CURL_SSLVERSION_TLSv1_2:
1703 ssl_version |= CURL_SSLVERSION_MAX_TLSv1_2; 1615 ssl_version |= CURL_SSLVERSION_MAX_TLSv1_2;
1704 break; 1616 break;
1705 case CURL_SSLVERSION_TLSv1_1: 1617 case CURL_SSLVERSION_TLSv1_1:
1706 ssl_version |= CURL_SSLVERSION_MAX_TLSv1_1; 1618 ssl_version |= CURL_SSLVERSION_MAX_TLSv1_1;
1707 break; 1619 break;
1708 case CURL_SSLVERSION_TLSv1_0: 1620 case CURL_SSLVERSION_TLSv1_0:
1709 ssl_version |= CURL_SSLVERSION_MAX_TLSv1_0; 1621 ssl_version |= CURL_SSLVERSION_MAX_TLSv1_0;
1710 break; 1622 break;
1711 } 1623 }
1712 } 1624 }
1713#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 54, 0) */ 1625# endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 54, 0) */
1714 if (verbose >= 2) 1626 if (verbose >= 2)
1715 printf(_("* Set SSL/TLS version to %d\n"), ssl_version); 1627 printf(_("* Set SSL/TLS version to %d\n"), ssl_version);
1716 if (!specify_port) 1628 if (!specify_port)
1717 server_port = HTTPS_PORT; 1629 server_port = HTTPS_PORT;
1718 break; 1630 break;
1719#else /* LIBCURL_FEATURE_SSL */ 1631#else /* LIBCURL_FEATURE_SSL */
1720 /* -C -J and -K fall through to here without SSL */ 1632 /* -C -J and -K fall through to here without SSL */
1721 usage4 (_("Invalid option - SSL is not available")); 1633 usage4(_("Invalid option - SSL is not available"));
1722 break; 1634 break;
1723 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 */
1724 use_sni = true; 1636 use_sni = true;
1725 break; 1637 break;
1726#endif /* LIBCURL_FEATURE_SSL */ 1638#endif /* LIBCURL_FEATURE_SSL */
1727 case MAX_REDIRS_OPTION: 1639 case MAX_REDIRS_OPTION:
1728 if (!is_intnonneg (optarg)) 1640 if (!is_intnonneg(optarg))
1729 usage2 (_("Invalid max_redirs count"), optarg); 1641 usage2(_("Invalid max_redirs count"), optarg);
1730 else { 1642 else {
1731 max_depth = atoi (optarg); 1643 max_depth = atoi(optarg);
1732 } 1644 }
1733 break; 1645 break;
1734 case 'f': /* onredirect */ 1646 case 'f': /* onredirect */
1735 if (!strcmp (optarg, "ok")) 1647 if (!strcmp(optarg, "ok"))
1736 onredirect = STATE_OK; 1648 onredirect = STATE_OK;
1737 else if (!strcmp (optarg, "warning")) 1649 else if (!strcmp(optarg, "warning"))
1738 onredirect = STATE_WARNING; 1650 onredirect = STATE_WARNING;
1739 else if (!strcmp (optarg, "critical")) 1651 else if (!strcmp(optarg, "critical"))
1740 onredirect = STATE_CRITICAL; 1652 onredirect = STATE_CRITICAL;
1741 else if (!strcmp (optarg, "unknown")) 1653 else if (!strcmp(optarg, "unknown"))
1742 onredirect = STATE_UNKNOWN; 1654 onredirect = STATE_UNKNOWN;
1743 else if (!strcmp (optarg, "follow")) 1655 else if (!strcmp(optarg, "follow"))
1744 onredirect = STATE_DEPENDENT; 1656 onredirect = STATE_DEPENDENT;
1745 else if (!strcmp (optarg, "stickyport")) 1657 else if (!strcmp(optarg, "stickyport"))
1746 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;
1747 else if (!strcmp (optarg, "sticky")) 1659 else if (!strcmp(optarg, "sticky"))
1748 onredirect = STATE_DEPENDENT, followmethod = FOLLOW_HTTP_CURL, followsticky = STICKY_HOST; 1660 onredirect = STATE_DEPENDENT, followmethod = FOLLOW_HTTP_CURL, followsticky = STICKY_HOST;
1749 else if (!strcmp (optarg, "follow")) 1661 else if (!strcmp(optarg, "follow"))
1750 onredirect = STATE_DEPENDENT, followmethod = FOLLOW_HTTP_CURL, followsticky = STICKY_NONE; 1662 onredirect = STATE_DEPENDENT, followmethod = FOLLOW_HTTP_CURL, followsticky = STICKY_NONE;
1751 else if (!strcmp (optarg, "curl")) 1663 else if (!strcmp(optarg, "curl"))
1752 onredirect = STATE_DEPENDENT, followmethod = FOLLOW_LIBCURL; 1664 onredirect = STATE_DEPENDENT, followmethod = FOLLOW_LIBCURL;
1753 else usage2 (_("Invalid onredirect option"), optarg); 1665 else
1754 if (verbose >= 2) 1666 usage2(_("Invalid onredirect option"), optarg);
1755 printf(_("* Following redirects set to %s\n"), state_text(onredirect)); 1667 if (verbose >= 2)
1756 break; 1668 printf(_("* Following redirects set to %s\n"), state_text(onredirect));
1757 case 'd': /* string or substring */ 1669 break;
1758 strncpy (header_expect, optarg, MAX_INPUT_BUFFER - 1); 1670 case 'd': /* string or substring */
1759 header_expect[MAX_INPUT_BUFFER - 1] = 0; 1671 strncpy(header_expect, optarg, MAX_INPUT_BUFFER - 1);
1760 break; 1672 header_expect[MAX_INPUT_BUFFER - 1] = 0;
1761 case 's': /* string or substring */ 1673 break;
1762 strncpy (string_expect, optarg, MAX_INPUT_BUFFER - 1); 1674 case 's': /* string or substring */
1763 string_expect[MAX_INPUT_BUFFER - 1] = 0; 1675 strncpy(string_expect, optarg, MAX_INPUT_BUFFER - 1);
1764 break; 1676 string_expect[MAX_INPUT_BUFFER - 1] = 0;
1765 case 'e': /* string or substring */ 1677 break;
1766 strncpy (server_expect, optarg, MAX_INPUT_BUFFER - 1); 1678 case 'e': /* string or substring */
1767 server_expect[MAX_INPUT_BUFFER - 1] = 0; 1679 strncpy(server_expect, optarg, MAX_INPUT_BUFFER - 1);
1768 server_expect_yn = 1; 1680 server_expect[MAX_INPUT_BUFFER - 1] = 0;
1769 break; 1681 server_expect_yn = 1;
1770 case 'T': /* Content-type */ 1682 break;
1771 http_content_type = strdup (optarg); 1683 case 'T': /* Content-type */
1772 break; 1684 http_content_type = strdup(optarg);
1773 case 'l': /* linespan */ 1685 break;
1774 cflags &= ~REG_NEWLINE; 1686 case 'l': /* linespan */
1775 break; 1687 cflags &= ~REG_NEWLINE;
1776 case 'R': /* regex */ 1688 break;
1777 cflags |= REG_ICASE; 1689 case 'R': /* regex */
1690 cflags |= REG_ICASE;
1778 // fall through 1691 // fall through
1779 case 'r': /* regex */ 1692 case 'r': /* regex */
1780 strncpy (regexp, optarg, MAX_RE_SIZE - 1); 1693 strncpy(regexp, optarg, MAX_RE_SIZE - 1);
1781 regexp[MAX_RE_SIZE - 1] = 0; 1694 regexp[MAX_RE_SIZE - 1] = 0;
1782 errcode = regcomp (&preg, regexp, cflags); 1695 errcode = regcomp(&preg, regexp, cflags);
1783 if (errcode != 0) { 1696 if (errcode != 0) {
1784 (void) regerror (errcode, &preg, errbuf, MAX_INPUT_BUFFER); 1697 (void)regerror(errcode, &preg, errbuf, MAX_INPUT_BUFFER);
1785 printf (_("Could Not Compile Regular Expression: %s"), errbuf); 1698 printf(_("Could Not Compile Regular Expression: %s"), errbuf);
1786 return false; 1699 return false;
1787 } 1700 }
1788 break; 1701 break;
1789 case INVERT_REGEX: 1702 case INVERT_REGEX:
1790 invert_regex = true; 1703 invert_regex = true;
1791 break; 1704 break;
1792 case STATE_REGEX: 1705 case STATE_REGEX:
1793 if (!strcasecmp (optarg, "critical")) 1706 if (!strcasecmp(optarg, "critical"))
1794 state_regex = STATE_CRITICAL; 1707 state_regex = STATE_CRITICAL;
1795 else if (!strcasecmp (optarg, "warning")) 1708 else if (!strcasecmp(optarg, "warning"))
1796 state_regex = STATE_WARNING; 1709 state_regex = STATE_WARNING;
1797 else usage2 (_("Invalid state-regex option"), optarg); 1710 else
1798 break; 1711 usage2(_("Invalid state-regex option"), optarg);
1799 case '4': 1712 break;
1800 address_family = AF_INET; 1713 case '4':
1801 break; 1714 address_family = AF_INET;
1802 case '6': 1715 break;
1803#if defined (USE_IPV6) && defined (LIBCURL_FEATURE_IPV6) 1716 case '6':
1804 address_family = AF_INET6; 1717#if defined(USE_IPV6) && defined(LIBCURL_FEATURE_IPV6)
1718 address_family = AF_INET6;
1805#else 1719#else
1806 usage4 (_("IPv6 support not available")); 1720 usage4(_("IPv6 support not available"));
1807#endif 1721#endif
1808 break; 1722 break;
1809 case 'm': /* min_page_length */ 1723 case 'm': /* min_page_length */
1810 { 1724 {
1811 char *tmp; 1725 char *tmp;
1812 if (strchr(optarg, ':') != (char *)NULL) { 1726 if (strchr(optarg, ':') != (char *)NULL) {
1813 /* range, so get two values, min:max */ 1727 /* range, so get two values, min:max */
1814 tmp = strtok(optarg, ":"); 1728 tmp = strtok(optarg, ":");
1815 if (tmp == NULL) { 1729 if (tmp == NULL) {
1816 printf("Bad format: try \"-m min:max\"\n"); 1730 printf("Bad format: try \"-m min:max\"\n");
1817 exit (STATE_WARNING); 1731 exit(STATE_WARNING);
1818 } else 1732 } else
1819 min_page_len = atoi(tmp); 1733 min_page_len = atoi(tmp);
1820 1734
1821 tmp = strtok(NULL, ":"); 1735 tmp = strtok(NULL, ":");
1822 if (tmp == NULL) { 1736 if (tmp == NULL) {
1823 printf("Bad format: try \"-m min:max\"\n"); 1737 printf("Bad format: try \"-m min:max\"\n");
1824 exit (STATE_WARNING); 1738 exit(STATE_WARNING);
1825 } else 1739 } else
1826 max_page_len = atoi(tmp); 1740 max_page_len = atoi(tmp);
1827 } else 1741 } else
1828 min_page_len = atoi (optarg); 1742 min_page_len = atoi(optarg);
1829 break; 1743 break;
1830 } 1744 }
1831 case 'N': /* no-body */ 1745 case 'N': /* no-body */
1832 no_body = true; 1746 no_body = true;
1833 break; 1747 break;
1834 case 'M': /* max-age */ 1748 case 'M': /* max-age */
1835 { 1749 {
1836 int L = strlen(optarg); 1750 int L = strlen(optarg);
1837 if (L && optarg[L-1] == 'm') 1751 if (L && optarg[L - 1] == 'm')
1838 maximum_age = atoi (optarg) * 60; 1752 maximum_age = atoi(optarg) * 60;
1839 else if (L && optarg[L-1] == 'h') 1753 else if (L && optarg[L - 1] == 'h')
1840 maximum_age = atoi (optarg) * 60 * 60; 1754 maximum_age = atoi(optarg) * 60 * 60;
1841 else if (L && optarg[L-1] == 'd') 1755 else if (L && optarg[L - 1] == 'd')
1842 maximum_age = atoi (optarg) * 60 * 60 * 24; 1756 maximum_age = atoi(optarg) * 60 * 60 * 24;
1843 else if (L && (optarg[L-1] == 's' || 1757 else if (L && (optarg[L - 1] == 's' || isdigit(optarg[L - 1])))
1844 isdigit (optarg[L-1]))) 1758 maximum_age = atoi(optarg);
1845 maximum_age = atoi (optarg); 1759 else {
1846 else { 1760 fprintf(stderr, "unparsable max-age: %s\n", optarg);
1847 fprintf (stderr, "unparsable max-age: %s\n", optarg); 1761 exit(STATE_WARNING);
1848 exit (STATE_WARNING); 1762 }
1849 } 1763 if (verbose >= 2)
1850 if (verbose >= 2) 1764 printf("* Maximal age of document set to %d seconds\n", maximum_age);
1851 printf ("* Maximal age of document set to %d seconds\n", maximum_age); 1765 } break;
1852 } 1766 case 'E': /* show extended perfdata */
1853 break; 1767 show_extended_perfdata = true;
1854 case 'E': /* show extended perfdata */ 1768 break;
1855 show_extended_perfdata = true; 1769 case 'B': /* print body content after status line */
1856 break; 1770 show_body = true;
1857 case 'B': /* print body content after status line */ 1771 break;
1858 show_body = true; 1772 case HTTP_VERSION_OPTION:
1859 break; 1773 curl_http_version = CURL_HTTP_VERSION_NONE;
1860 case HTTP_VERSION_OPTION: 1774 if (strcmp(optarg, "1.0") == 0) {
1861 curl_http_version = CURL_HTTP_VERSION_NONE; 1775 curl_http_version = CURL_HTTP_VERSION_1_0;
1862 if (strcmp (optarg, "1.0") == 0) { 1776 } else if (strcmp(optarg, "1.1") == 0) {
1863 curl_http_version = CURL_HTTP_VERSION_1_0; 1777 curl_http_version = CURL_HTTP_VERSION_1_1;
1864 } else if (strcmp (optarg, "1.1") == 0) { 1778 } else if ((strcmp(optarg, "2.0") == 0) || (strcmp(optarg, "2") == 0)) {
1865 curl_http_version = CURL_HTTP_VERSION_1_1;
1866 } else if ((strcmp (optarg, "2.0") == 0) || (strcmp (optarg, "2") == 0)) {
1867#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 33, 0) 1779#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 33, 0)
1868 curl_http_version = CURL_HTTP_VERSION_2_0; 1780 curl_http_version = CURL_HTTP_VERSION_2_0;
1869#else 1781#else
1870 curl_http_version = CURL_HTTP_VERSION_NONE; 1782 curl_http_version = CURL_HTTP_VERSION_NONE;
1871#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 33, 0) */ 1783#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 33, 0) */
1872 } else { 1784 } else {
1873 fprintf (stderr, "unknown http-version parameter: %s\n", optarg); 1785 fprintf(stderr, "unknown http-version parameter: %s\n", optarg);
1874 exit (STATE_WARNING); 1786 exit(STATE_WARNING);
1875 } 1787 }
1876 break; 1788 break;
1877 case AUTOMATIC_DECOMPRESSION: 1789 case AUTOMATIC_DECOMPRESSION:
1878 automatic_decompression = true; 1790 automatic_decompression = true;
1879 break; 1791 break;
1880 case COOKIE_JAR: 1792 case COOKIE_JAR:
1881 cookie_jar_file = optarg; 1793 cookie_jar_file = optarg;
1882 break; 1794 break;
1883 case HAPROXY_PROTOCOL: 1795 case HAPROXY_PROTOCOL:
1884 haproxy_protocol = true; 1796 haproxy_protocol = true;
1885 break; 1797 break;
1886 case '?': 1798 case '?':
1887 /* print short usage statement if args not parsable */ 1799 /* print short usage statement if args not parsable */
1888 usage5 (); 1800 usage5();
1889 break; 1801 break;
1890 } 1802 }
1891 } 1803 }
1892 1804
1893 c = optind; 1805 c = optind;
1894 1806
1895 if (server_address == NULL && c < argc) 1807 if (server_address == NULL && c < argc)
1896 server_address = strdup (argv[c++]); 1808 server_address = strdup(argv[c++]);
1897 1809
1898 if (host_name == NULL && c < argc) 1810 if (host_name == NULL && c < argc)
1899 host_name = strdup (argv[c++]); 1811 host_name = strdup(argv[c++]);
1900 1812
1901 if (server_address == NULL) { 1813 if (server_address == NULL) {
1902 if (host_name == NULL) 1814 if (host_name == NULL)
1903 usage4 (_("You must specify a server address or host name")); 1815 usage4(_("You must specify a server address or host name"));
1904 else 1816 else
1905 server_address = strdup (host_name); 1817 server_address = strdup(host_name);
1906 } 1818 }
1907 1819
1908 set_thresholds(&thlds, warning_thresholds, critical_thresholds); 1820 set_thresholds(&thlds, warning_thresholds, critical_thresholds);
1909 1821
1910 if (critical_thresholds && thlds->critical->end>(double)socket_timeout) 1822 if (critical_thresholds && thlds->critical->end > (double)socket_timeout)
1911 socket_timeout = (int)thlds->critical->end + 1; 1823 socket_timeout = (int)thlds->critical->end + 1;
1912 if (verbose >= 2) 1824 if (verbose >= 2)
1913 printf ("* Socket timeout set to %ld seconds\n", socket_timeout); 1825 printf("* Socket timeout set to %ld seconds\n", socket_timeout);
1914 1826
1915 if (http_method == NULL) 1827 if (http_method == NULL)
1916 http_method = strdup ("GET"); 1828 http_method = strdup("GET");
1917 1829
1918 if (client_cert && !client_privkey) 1830 if (client_cert && !client_privkey)
1919 usage4 (_("If you use a client certificate you must also specify a private key file")); 1831 usage4(_("If you use a client certificate you must also specify a private key file"));
1920 1832
1921 if (virtual_port == 0) 1833 if (virtual_port == 0)
1922 virtual_port = server_port; 1834 virtual_port = server_port;
1923 else { 1835 else {
1924 if ((use_ssl && server_port == HTTPS_PORT) || (!use_ssl && server_port == HTTP_PORT)) 1836 if ((use_ssl && server_port == HTTPS_PORT) || (!use_ssl && server_port == HTTP_PORT))
1925 if(!specify_port) 1837 if (!specify_port)
1926 server_port = virtual_port; 1838 server_port = virtual_port;
1927 } 1839 }
1928 1840
1929 return true; 1841 return true;
1930} 1842}
1931 1843
1932char *perfd_time (double elapsed_time) 1844char *perfd_time(double elapsed_time) {
1933{ 1845 return fperfdata("time", elapsed_time, "s", thlds->warning ? true : false, thlds->warning ? thlds->warning->end : 0,
1934 return fperfdata ("time", elapsed_time, "s", 1846 thlds->critical ? true : false, thlds->critical ? thlds->critical->end : 0, true, 0, true, socket_timeout);
1935 thlds->warning?true:false, thlds->warning?thlds->warning->end:0,
1936 thlds->critical?true:false, thlds->critical?thlds->critical->end:0,
1937 true, 0, true, socket_timeout);
1938} 1847}
1939 1848
1940char *perfd_time_connect (double elapsed_time_connect) 1849char *perfd_time_connect(double elapsed_time_connect) {
1941{ 1850 return fperfdata("time_connect", elapsed_time_connect, "s", false, 0, false, 0, false, 0, true, socket_timeout);
1942 return fperfdata ("time_connect", elapsed_time_connect, "s", false, 0, false, 0, false, 0, true, socket_timeout);
1943} 1851}
1944 1852
1945char *perfd_time_ssl (double elapsed_time_ssl) 1853char *perfd_time_ssl(double elapsed_time_ssl) {
1946{ 1854 return fperfdata("time_ssl", elapsed_time_ssl, "s", false, 0, false, 0, false, 0, true, socket_timeout);
1947 return fperfdata ("time_ssl", elapsed_time_ssl, "s", false, 0, false, 0, false, 0, true, socket_timeout);
1948} 1855}
1949 1856
1950char *perfd_time_headers (double elapsed_time_headers) 1857char *perfd_time_headers(double elapsed_time_headers) {
1951{ 1858 return fperfdata("time_headers", elapsed_time_headers, "s", false, 0, false, 0, false, 0, true, socket_timeout);
1952 return fperfdata ("time_headers", elapsed_time_headers, "s", false, 0, false, 0, false, 0, true, socket_timeout);
1953} 1859}
1954 1860
1955char *perfd_time_firstbyte (double elapsed_time_firstbyte) 1861char *perfd_time_firstbyte(double elapsed_time_firstbyte) {
1956{ 1862 return fperfdata("time_firstbyte", elapsed_time_firstbyte, "s", false, 0, false, 0, false, 0, true, socket_timeout);
1957 return fperfdata ("time_firstbyte", elapsed_time_firstbyte, "s", false, 0, false, 0, false, 0, true, socket_timeout);
1958} 1863}
1959 1864
1960char *perfd_time_transfer (double elapsed_time_transfer) 1865char *perfd_time_transfer(double elapsed_time_transfer) {
1961{ 1866 return fperfdata("time_transfer", elapsed_time_transfer, "s", false, 0, false, 0, false, 0, true, socket_timeout);
1962 return fperfdata ("time_transfer", elapsed_time_transfer, "s", false, 0, false, 0, false, 0, true, socket_timeout);
1963} 1867}
1964 1868
1965char *perfd_size (int page_len) 1869char *perfd_size(int page_len) {
1966{ 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,
1967 return perfdata ("size", page_len, "B", 1871 false, 0);
1968 (min_page_len>0?true:false), min_page_len,
1969 (min_page_len>0?true:false), 0,
1970 true, 0, false, 0);
1971} 1872}
1972 1873
1973void 1874void print_help(void) {
1974print_help (void) 1875 print_revision(progname, NP_VERSION);
1975{
1976 print_revision (progname, NP_VERSION);
1977 1876
1978 printf ("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n"); 1877 printf("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n");
1979 printf (COPYRIGHT, copyright, email); 1878 printf(COPYRIGHT, copyright, email);
1980 1879
1981 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"));
1982 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"));
1983 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"));
1984 printf ("%s\n", _("certificate expiration times.")); 1883 printf("%s\n", _("certificate expiration times."));
1985 printf ("\n"); 1884 printf("\n");
1986 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"));
1987 printf ("%s\n", _("as possible.")); 1886 printf("%s\n", _("as possible."));
1988 1887
1989 printf ("\n\n"); 1888 printf("\n\n");
1990 1889
1991 print_usage (); 1890 print_usage();
1992 1891
1993 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"));
1994 1893
1995 printf ("\n"); 1894 printf("\n");
1996 1895
1997 printf (UT_HELP_VRSN); 1896 printf(UT_HELP_VRSN);
1998 printf (UT_EXTRA_OPTS); 1897 printf(UT_EXTRA_OPTS);
1999 1898
2000 printf (" %s\n", "-H, --hostname=ADDRESS"); 1899 printf(" %s\n", "-H, --hostname=ADDRESS");
2001 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)"));
2002 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)"));
2003 printf (" %s\n", "-I, --IP-address=ADDRESS"); 1902 printf(" %s\n", "-I, --IP-address=ADDRESS");
2004 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)."));
2005 printf (" %s\n", "-p, --port=INTEGER"); 1904 printf(" %s\n", "-p, --port=INTEGER");
2006 printf (" %s", _("Port number (default: ")); 1905 printf(" %s", _("Port number (default: "));
2007 printf ("%d)\n", HTTP_PORT); 1906 printf("%d)\n", HTTP_PORT);
2008 1907
2009 printf (UT_IPv46); 1908 printf(UT_IPv46);
2010 1909
2011#ifdef LIBCURL_FEATURE_SSL 1910#ifdef LIBCURL_FEATURE_SSL
2012 printf (" %s\n", "-S, --ssl=VERSION[+]"); 1911 printf(" %s\n", "-S, --ssl=VERSION[+]");
2013 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"));
2014 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,"));
2015 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."));
2016 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"));
2017 printf (" %s\n", "--sni"); 1916 printf(" %s\n", "--sni");
2018 printf (" %s\n", _("Enable SSL/TLS hostname extension support (SNI)")); 1917 printf(" %s\n", _("Enable SSL/TLS hostname extension support (SNI)"));
2019#if LIBCURL_VERSION_NUM >= 0x071801 1918# if LIBCURL_VERSION_NUM >= 0x071801
2020 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"));
2021 printf (" %s\n", _(" SNI only really works since TLSv1.0")); 1920 printf(" %s\n", _(" SNI only really works since TLSv1.0"));
2022#else 1921# else
2023 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"));
2024#endif 1923# endif
2025 printf (" %s\n", "-C, --certificate=INTEGER[,INTEGER]"); 1924 printf(" %s\n", "-C, --certificate=INTEGER[,INTEGER]");
2026 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."));
2027 printf (" %s\n", _("A STATE_WARNING is returned if the certificate has a validity less than the")); 1926 printf(" %s\n", _("A STATE_WARNING is returned if the certificate has a validity less than the"));
2028 printf (" %s\n", _("first agument's value. If there is a second argument and the certificate's")); 1927 printf(" %s\n", _("first agument's value. If there is a second argument and the certificate's"));
2029 printf (" %s\n", _("validity is less than its value, a STATE_CRITICAL is returned.")); 1928 printf(" %s\n", _("validity is less than its value, a STATE_CRITICAL is returned."));
2030 printf (" %s\n", _("(When this option is used the URL is not checked by default. You can use")); 1929 printf(" %s\n", _("(When this option is used the URL is not checked by default. You can use"));
2031 printf (" %s\n", _(" --continue-after-certificate to override this behavior)")); 1930 printf(" %s\n", _(" --continue-after-certificate to override this behavior)"));
2032 printf (" %s\n", "--continue-after-certificate"); 1931 printf(" %s\n", "--continue-after-certificate");
2033 printf (" %s\n", _("Allows the HTTP check to continue after performing the certificate check.")); 1932 printf(" %s\n", _("Allows the HTTP check to continue after performing the certificate check."));
2034 printf (" %s\n", _("Does nothing unless -C is used.")); 1933 printf(" %s\n", _("Does nothing unless -C is used."));
2035 printf (" %s\n", "-J, --client-cert=FILE"); 1934 printf(" %s\n", "-J, --client-cert=FILE");
2036 printf (" %s\n", _("Name of file that contains the client certificate (PEM format)")); 1935 printf(" %s\n", _("Name of file that contains the client certificate (PEM format)"));
2037 printf (" %s\n", _("to be used in establishing the SSL session")); 1936 printf(" %s\n", _("to be used in establishing the SSL session"));
2038 printf (" %s\n", "-K, --private-key=FILE"); 1937 printf(" %s\n", "-K, --private-key=FILE");
2039 printf (" %s\n", _("Name of file containing the private key (PEM format)")); 1938 printf(" %s\n", _("Name of file containing the private key (PEM format)"));
2040 printf (" %s\n", _("matching the client certificate")); 1939 printf(" %s\n", _("matching the client certificate"));
2041 printf (" %s\n", "--ca-cert=FILE"); 1940 printf(" %s\n", "--ca-cert=FILE");
2042 printf (" %s\n", _("CA certificate file to verify peer against")); 1941 printf(" %s\n", _("CA certificate file to verify peer against"));
2043 printf (" %s\n", "-D, --verify-cert"); 1942 printf(" %s\n", "-D, --verify-cert");
2044 printf (" %s\n", _("Verify the peer's SSL certificate and hostname")); 1943 printf(" %s\n", _("Verify the peer's SSL certificate and hostname"));
2045#endif 1944#endif
2046 1945
2047 printf (" %s\n", "-e, --expect=STRING"); 1946 printf(" %s\n", "-e, --expect=STRING");
2048 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"));
2049 printf (" %s", _("the first (status) line of the server response (default: ")); 1948 printf(" %s", _("the first (status) line of the server response (default: "));
2050 printf ("%s)\n", HTTP_EXPECT); 1949 printf("%s)\n", HTTP_EXPECT);
2051 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)"));
2052 printf (" %s\n", "-d, --header-string=STRING"); 1951 printf(" %s\n", "-d, --header-string=STRING");
2053 printf (" %s\n", _("String to expect in the response headers")); 1952 printf(" %s\n", _("String to expect in the response headers"));
2054 printf (" %s\n", "-s, --string=STRING"); 1953 printf(" %s\n", "-s, --string=STRING");
2055 printf (" %s\n", _("String to expect in the content")); 1954 printf(" %s\n", _("String to expect in the content"));
2056 printf (" %s\n", "-u, --url=PATH"); 1955 printf(" %s\n", "-u, --url=PATH");
2057 printf (" %s\n", _("URL to GET or POST (default: /)")); 1956 printf(" %s\n", _("URL to GET or POST (default: /)"));
2058 printf (" %s\n", "-P, --post=STRING"); 1957 printf(" %s\n", "-P, --post=STRING");
2059 printf (" %s\n", _("URL decoded http POST data")); 1958 printf(" %s\n", _("URL decoded http POST data"));
2060 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)");
2061 printf (" %s\n", _("Set HTTP method.")); 1960 printf(" %s\n", _("Set HTTP method."));
2062 printf (" %s\n", "-N, --no-body"); 1961 printf(" %s\n", "-N, --no-body");
2063 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."));
2064 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.)"));
2065 printf (" %s\n", "-M, --max-age=SECONDS"); 1964 printf(" %s\n", "-M, --max-age=SECONDS");
2066 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"));
2067 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."));
2068 printf (" %s\n", "-T, --content-type=STRING"); 1967 printf(" %s\n", "-T, --content-type=STRING");
2069 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"));
2070 printf (" %s\n", "-l, --linespan"); 1969 printf(" %s\n", "-l, --linespan");
2071 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)"));
2072 printf (" %s\n", "-r, --regex, --ereg=STRING"); 1971 printf(" %s\n", "-r, --regex, --ereg=STRING");
2073 printf (" %s\n", _("Search page for regex STRING")); 1972 printf(" %s\n", _("Search page for regex STRING"));
2074 printf (" %s\n", "-R, --eregi=STRING"); 1973 printf(" %s\n", "-R, --eregi=STRING");
2075 printf (" %s\n", _("Search page for case-insensitive regex STRING")); 1974 printf(" %s\n", _("Search page for case-insensitive regex STRING"));
2076 printf (" %s\n", "--invert-regex"); 1975 printf(" %s\n", "--invert-regex");
2077 printf (" %s\n", _("Return STATE if found, OK if not (STATE is CRITICAL, per default)")); 1976 printf(" %s\n", _("Return STATE if found, OK if not (STATE is CRITICAL, per default)"));
2078 printf (" %s\n", _("can be changed with --state--regex)")); 1977 printf(" %s\n", _("can be changed with --state--regex)"));
2079 printf (" %s\n", "--state-regex=STATE"); 1978 printf(" %s\n", "--state-regex=STATE");
2080 printf (" %s\n", _("Return STATE if regex is found, OK if not. STATE can be one of \"critical\",\"warning\"")); 1979 printf(" %s\n", _("Return STATE if regex is found, OK if not. STATE can be one of \"critical\",\"warning\""));
2081 printf (" %s\n", "-a, --authorization=AUTH_PAIR"); 1980 printf(" %s\n", "-a, --authorization=AUTH_PAIR");
2082 printf (" %s\n", _("Username:password on sites with basic authentication")); 1981 printf(" %s\n", _("Username:password on sites with basic authentication"));
2083 printf (" %s\n", "-b, --proxy-authorization=AUTH_PAIR"); 1982 printf(" %s\n", "-b, --proxy-authorization=AUTH_PAIR");
2084 printf (" %s\n", _("Username:password on proxy-servers with basic authentication")); 1983 printf(" %s\n", _("Username:password on proxy-servers with basic authentication"));
2085 printf (" %s\n", "-A, --useragent=STRING"); 1984 printf(" %s\n", "-A, --useragent=STRING");
2086 printf (" %s\n", _("String to be sent in http header as \"User Agent\"")); 1985 printf(" %s\n", _("String to be sent in http header as \"User Agent\""));
2087 printf (" %s\n", "-k, --header=STRING"); 1986 printf(" %s\n", "-k, --header=STRING");
2088 printf (" %s\n", _("Any other tags to be sent in http header. Use multiple times for additional headers")); 1987 printf(" %s\n", _("Any other tags to be sent in http header. Use multiple times for additional headers"));
2089 printf (" %s\n", "-E, --extended-perfdata"); 1988 printf(" %s\n", "-E, --extended-perfdata");
2090 printf (" %s\n", _("Print additional performance data")); 1989 printf(" %s\n", _("Print additional performance data"));
2091 printf (" %s\n", "-B, --show-body"); 1990 printf(" %s\n", "-B, --show-body");
2092 printf (" %s\n", _("Print body content below status line")); 1991 printf(" %s\n", _("Print body content below status line"));
2093 printf (" %s\n", "-L, --link"); 1992 printf(" %s\n", "-L, --link");
2094 printf (" %s\n", _("Wrap output in HTML link (obsoleted by urlize)")); 1993 printf(" %s\n", _("Wrap output in HTML link (obsoleted by urlize)"));
2095 printf (" %s\n", "-f, --onredirect=<ok|warning|critical|follow|sticky|stickyport|curl>"); 1994 printf(" %s\n", "-f, --onredirect=<ok|warning|critical|follow|sticky|stickyport|curl>");
2096 printf (" %s\n", _("How to handle redirected pages. sticky is like follow but stick to the")); 1995 printf(" %s\n", _("How to handle redirected pages. sticky is like follow but stick to the"));
2097 printf (" %s\n", _("specified IP address. stickyport also ensures port stays the same.")); 1996 printf(" %s\n", _("specified IP address. stickyport also ensures port stays the same."));
2098 printf (" %s\n", _("follow uses the old redirection algorithm of check_http.")); 1997 printf(" %s\n", _("follow uses the old redirection algorithm of check_http."));
2099 printf (" %s\n", _("curl uses CURL_FOLLOWLOCATION built into libcurl.")); 1998 printf(" %s\n", _("curl uses CURL_FOLLOWLOCATION built into libcurl."));
2100 printf (" %s\n", "--max-redirs=INTEGER"); 1999 printf(" %s\n", "--max-redirs=INTEGER");
2101 printf (" %s", _("Maximal number of redirects (default: ")); 2000 printf(" %s", _("Maximal number of redirects (default: "));
2102 printf ("%d)\n", DEFAULT_MAX_REDIRS); 2001 printf("%d)\n", DEFAULT_MAX_REDIRS);
2103 printf (" %s\n", "-m, --pagesize=INTEGER<:INTEGER>"); 2002 printf(" %s\n", "-m, --pagesize=INTEGER<:INTEGER>");
2104 printf (" %s\n", _("Minimum page size required (bytes) : Maximum page size required (bytes)")); 2003 printf(" %s\n", _("Minimum page size required (bytes) : Maximum page size required (bytes)"));
2105 printf ("\n"); 2004 printf("\n");
2106 printf (" %s\n", "--http-version=VERSION"); 2005 printf(" %s\n", "--http-version=VERSION");
2107 printf (" %s\n", _("Connect via specific HTTP protocol.")); 2006 printf(" %s\n", _("Connect via specific HTTP protocol."));
2108 printf (" %s\n", _("1.0 = HTTP/1.0, 1.1 = HTTP/1.1, 2.0 = HTTP/2 (HTTP/2 will fail without -S)")); 2007 printf(" %s\n", _("1.0 = HTTP/1.0, 1.1 = HTTP/1.1, 2.0 = HTTP/2 (HTTP/2 will fail without -S)"));
2109 printf (" %s\n", "--enable-automatic-decompression"); 2008 printf(" %s\n", "--enable-automatic-decompression");
2110 printf (" %s\n", _("Enable automatic decompression of body (CURLOPT_ACCEPT_ENCODING).")); 2009 printf(" %s\n", _("Enable automatic decompression of body (CURLOPT_ACCEPT_ENCODING)."));
2111 printf(" %s\n", "--haproxy-protocol"); 2010 printf(" %s\n", "--haproxy-protocol");
2112 printf(" %s\n", _("Send HAProxy proxy protocol v1 header (CURLOPT_HAPROXYPROTOCOL).")); 2011 printf(" %s\n", _("Send HAProxy proxy protocol v1 header (CURLOPT_HAPROXYPROTOCOL)."));
2113 printf (" %s\n", "--cookie-jar=FILE"); 2012 printf(" %s\n", "--cookie-jar=FILE");
2114 printf (" %s\n", _("Store cookies in the cookie jar and send them out when requested.")); 2013 printf(" %s\n", _("Store cookies in the cookie jar and send them out when requested."));
2115 printf ("\n"); 2014 printf("\n");
2116 2015
2117 printf (UT_WARN_CRIT); 2016 printf(UT_WARN_CRIT);
2118 2017
2119 printf (UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); 2018 printf(UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
2120 2019
2121 printf (UT_VERBOSE); 2020 printf(UT_VERBOSE);
2122 2021
2123 printf ("\n"); 2022 printf("\n");
2124 printf ("%s\n", _("Notes:")); 2023 printf("%s\n", _("Notes:"));
2125 printf (" %s\n", _("This plugin will attempt to open an HTTP connection with the host.")); 2024 printf(" %s\n", _("This plugin will attempt to open an HTTP connection with the host."));
2126 printf (" %s\n", _("Successful connects return STATE_OK, refusals and timeouts return STATE_CRITICAL")); 2025 printf(" %s\n", _("Successful connects return STATE_OK, refusals and timeouts return STATE_CRITICAL"));
2127 printf (" %s\n", _("other errors return STATE_UNKNOWN. Successful connects, but incorrect response")); 2026 printf(" %s\n", _("other errors return STATE_UNKNOWN. Successful connects, but incorrect response"));
2128 printf (" %s\n", _("messages from the host result in STATE_WARNING return values. If you are")); 2027 printf(" %s\n", _("messages from the host result in STATE_WARNING return values. If you are"));
2129 printf (" %s\n", _("checking a virtual server that uses 'host headers' you must supply the FQDN")); 2028 printf(" %s\n", _("checking a virtual server that uses 'host headers' you must supply the FQDN"));
2130 printf (" %s\n", _("(fully qualified domain name) as the [host_name] argument.")); 2029 printf(" %s\n", _("(fully qualified domain name) as the [host_name] argument."));
2131 2030
2132#ifdef LIBCURL_FEATURE_SSL 2031#ifdef LIBCURL_FEATURE_SSL
2133 printf ("\n"); 2032 printf("\n");
2134 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"));
2135 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 "));
2136 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."));
2137 printf ("\n"); 2036 printf("\n");
2138 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"));
2139 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"));
2140 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."));
2141 printf ("\n"); 2040 printf("\n");
2142 printf ("%s\n", _("Examples:")); 2041 printf("%s\n", _("Examples:"));
2143 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");
2144 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,"));
2145 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"));
2146 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,"));
2147 printf (" %s\n", _("a STATE_CRITICAL will be returned.")); 2046 printf(" %s\n", _("a STATE_CRITICAL will be returned."));
2148 printf ("\n"); 2047 printf("\n");
2149 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");
2150 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,"));
2151 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"));
2152 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"));
2153 printf (" %s\n\n", _("the certificate is expired.")); 2052 printf(" %s\n\n", _("the certificate is expired."));
2154 printf ("\n"); 2053 printf("\n");
2155 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");
2156 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,"));
2157 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"));
2158 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."));
2159 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"));
2160#endif 2059#endif
2161 2060
2162 printf ("\n %s\n", "CHECK WEBSERVER CONTENT VIA PROXY:"); 2061 printf("\n %s\n", "CHECK WEBSERVER CONTENT VIA PROXY:");
2163 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:"));
2164 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"));
2165 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:"));
2166 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"));
2167 2066
2168#ifdef LIBCURL_FEATURE_SSL 2067#ifdef LIBCURL_FEATURE_SSL
2169 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: ");
2170 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:"));
2171 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"));
2172 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:"));
2173 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 "));
2174 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>"));
2175 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"));
2176 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,"));
2177 printf (" %s\n", _("a STATE_CRITICAL will be returned.")); 2076 printf(" %s\n", _("a STATE_CRITICAL will be returned."));
2178 2077
2179#endif 2078#endif
2180 2079
2181 printf (UT_SUPPORT); 2080 printf(UT_SUPPORT);
2182
2183} 2081}
2184 2082
2185 2083void print_usage(void) {
2186 2084 printf("%s\n", _("Usage:"));
2187void 2085 printf(" %s -H <vhost> | -I <IP-address> [-u <uri>] [-p <port>]\n", progname);
2188print_usage (void) 2086 printf(" [-J <client certificate file>] [-K <private key>] [--ca-cert <CA certificate file>] [-D]\n");
2189{ 2087 printf(" [-w <warn time>] [-c <critical time>] [-t <timeout>] [-L] [-E] [-a auth]\n");
2190 printf ("%s\n", _("Usage:")); 2088 printf(" [-b proxy_auth] [-f <ok|warning|critical|follow|sticky|stickyport|curl>]\n");
2191 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");
2192 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");
2193 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");
2194 printf (" [-b proxy_auth] [-f <ok|warning|critical|follow|sticky|stickyport|curl>]\n"); 2092 printf(" [-T <content-type>] [-j method]\n");
2195 printf (" [-e <expect>] [-d string] [-s string] [-l] [-r <regex> | -R <case-insensitive regex>]\n"); 2093 printf(" [--http-version=<version>] [--enable-automatic-decompression]\n");
2196 printf (" [-P string] [-m <min_pg_size>:<max_pg_size>] [-4|-6] [-N] [-M <age>]\n"); 2094 printf(" [--cookie-jar=<cookie jar file>\n");
2197 printf (" [-A string] [-k string] [-S <version>] [--sni] [--haproxy-protocol]\n"); 2095 printf(" %s -H <vhost> | -I <IP-address> -C <warn_age>[,<crit_age>]\n", progname);
2198 printf (" [-T <content-type>] [-j method]\n"); 2096 printf(" [-p <port>] [-t <timeout>] [-4|-6] [--sni]\n");
2199 printf (" [--http-version=<version>] [--enable-automatic-decompression]\n"); 2097 printf("\n");
2200 printf (" [--cookie-jar=<cookie jar file>\n");
2201 printf (" %s -H <vhost> | -I <IP-address> -C <warn_age>[,<crit_age>]\n",progname);
2202 printf (" [-p <port>] [-t <timeout>] [-4|-6] [--sni]\n");
2203 printf ("\n");
2204#ifdef LIBCURL_FEATURE_SSL 2098#ifdef LIBCURL_FEATURE_SSL
2205 printf ("%s\n", _("In the first form, make an HTTP request.")); 2099 printf("%s\n", _("In the first form, make an HTTP request."));
2206 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."));
2207#endif 2101#endif
2208} 2102}
2209 2103
2210void 2104void print_curl_version(void) { printf("%s\n", curl_version()); }
2211print_curl_version (void)
2212{
2213 printf( "%s\n", curl_version());
2214}
2215 2105
2216int 2106int curlhelp_initwritebuffer(curlhelp_write_curlbuf *buf) {
2217curlhelp_initwritebuffer (curlhelp_write_curlbuf *buf) 2107 buf->bufsize = DEFAULT_BUFFER_SIZE;
2218{ 2108 buf->buflen = 0;
2219 buf->bufsize = DEFAULT_BUFFER_SIZE; 2109 buf->buf = (char *)malloc((size_t)buf->bufsize);
2220 buf->buflen = 0; 2110 if (buf->buf == NULL)
2221 buf->buf = (char *)malloc ((size_t)buf->bufsize); 2111 return -1;
2222 if (buf->buf == NULL) return -1; 2112 return 0;
2223 return 0;
2224} 2113}
2225 2114
2226size_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) {
2227{ 2116 curlhelp_write_curlbuf *buf = (curlhelp_write_curlbuf *)stream;
2228 curlhelp_write_curlbuf *buf = (curlhelp_write_curlbuf *)stream;
2229 2117
2230 while (buf->bufsize < buf->buflen + size * nmemb + 1) { 2118 while (buf->bufsize < buf->buflen + size * nmemb + 1) {
2231 buf->bufsize = buf->bufsize * 2; 2119 buf->bufsize = buf->bufsize * 2;
2232 buf->buf = (char *)realloc (buf->buf, buf->bufsize); 2120 buf->buf = (char *)realloc(buf->buf, buf->bufsize);
2233 if (buf->buf == NULL) { 2121 if (buf->buf == NULL) {
2234 fprintf(stderr, "malloc failed (%d) %s\n", errno, strerror(errno)); 2122 fprintf(stderr, "malloc failed (%d) %s\n", errno, strerror(errno));
2235 return -1; 2123 return -1;
2236 } 2124 }
2237 } 2125 }
2238 2126
2239 memcpy (buf->buf + buf->buflen, buffer, size * nmemb); 2127 memcpy(buf->buf + buf->buflen, buffer, size * nmemb);
2240 buf->buflen += size * nmemb; 2128 buf->buflen += size * nmemb;
2241 buf->buf[buf->buflen] = '\0'; 2129 buf->buf[buf->buflen] = '\0';
2242 2130
2243 return (int)(size * nmemb); 2131 return (int)(size * nmemb);
2244} 2132}
2245 2133
2246size_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) {
2247{ 2135 curlhelp_read_curlbuf *buf = (curlhelp_read_curlbuf *)stream;
2248 curlhelp_read_curlbuf *buf = (curlhelp_read_curlbuf *)stream;
2249 2136
2250 size_t n = min (nmemb * size, buf->buflen - buf->pos); 2137 size_t n = min(nmemb * size, buf->buflen - buf->pos);
2251 2138
2252 memcpy (buffer, buf->buf + buf->pos, n); 2139 memcpy(buffer, buf->buf + buf->pos, n);
2253 buf->pos += n; 2140 buf->pos += n;
2254 2141
2255 return (int)n; 2142 return (int)n;
2256} 2143}
2257 2144
2258void 2145void curlhelp_freewritebuffer(curlhelp_write_curlbuf *buf) {
2259curlhelp_freewritebuffer (curlhelp_write_curlbuf *buf) 2146 free(buf->buf);
2260{ 2147 buf->buf = NULL;
2261 free (buf->buf);
2262 buf->buf = NULL;
2263} 2148}
2264 2149
2265int 2150int curlhelp_initreadbuffer(curlhelp_read_curlbuf *buf, const char *data, size_t datalen) {
2266curlhelp_initreadbuffer (curlhelp_read_curlbuf *buf, const char *data, size_t datalen) 2151 buf->buflen = datalen;
2267{ 2152 buf->buf = (char *)malloc((size_t)buf->buflen);
2268 buf->buflen = datalen; 2153 if (buf->buf == NULL)
2269 buf->buf = (char *)malloc ((size_t)buf->buflen); 2154 return -1;
2270 if (buf->buf == NULL) return -1; 2155 memcpy(buf->buf, data, datalen);
2271 memcpy (buf->buf, data, datalen); 2156 buf->pos = 0;
2272 buf->pos = 0; 2157 return 0;
2273 return 0;
2274} 2158}
2275 2159
2276void 2160void curlhelp_freereadbuffer(curlhelp_read_curlbuf *buf) {
2277curlhelp_freereadbuffer (curlhelp_read_curlbuf *buf) 2161 free(buf->buf);
2278{ 2162 buf->buf = NULL;
2279 free (buf->buf);
2280 buf->buf = NULL;
2281} 2163}
2282 2164
2283/* 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)?
2284 */ 2166 */
2285const char* 2167const char *strrstr2(const char *haystack, const char *needle) {
2286strrstr2(const char *haystack, const char *needle) 2168 int counter;
2287{ 2169 size_t len;
2288 int counter; 2170 const char *prev_pos;
2289 size_t len; 2171 const char *pos;
2290 const char *prev_pos; 2172
2291 const char *pos; 2173 if (haystack == NULL || needle == NULL)
2292 2174 return NULL;
2293 if (haystack == NULL || needle == NULL) 2175
2294 return NULL; 2176 if (haystack[0] == '\0' || needle[0] == '\0')
2295 2177 return NULL;
2296 if (haystack[0] == '\0' || needle[0] == '\0') 2178
2297 return NULL; 2179 counter = 0;
2298 2180 prev_pos = NULL;
2299 counter = 0; 2181 pos = haystack;
2300 prev_pos = NULL; 2182 len = strlen(needle);
2301 pos = haystack; 2183 for (;;) {
2302 len = strlen (needle); 2184 pos = strstr(pos, needle);
2303 for (;;) { 2185 if (pos == NULL) {
2304 pos = strstr (pos, needle); 2186 if (counter == 0)
2305 if (pos == NULL) { 2187 return NULL;
2306 if (counter == 0) 2188 return prev_pos;
2307 return NULL; 2189 }
2308 else 2190 counter++;
2309 return prev_pos; 2191 prev_pos = pos;
2310 } 2192 pos += len;
2311 counter++; 2193 if (*pos == '\0')
2312 prev_pos = pos; 2194 return prev_pos;
2313 pos += len; 2195 }
2314 if (*pos == '\0') return prev_pos;
2315 }
2316} 2196}
2317 2197
2318int 2198int curlhelp_parse_statusline(const char *buf, curlhelp_statusline *status_line) {
2319curlhelp_parse_statusline (const char *buf, curlhelp_statusline *status_line) 2199 char *first_line_end;
2320{ 2200 char *p;
2321 char *first_line_end; 2201 size_t first_line_len;
2322 char *p; 2202 char *pp;
2323 size_t first_line_len; 2203 const char *start;
2324 char *pp; 2204 char *first_line_buf;
2325 const char *start; 2205
2326 char *first_line_buf; 2206 /* find last start of a new header */
2327 2207 start = strrstr2(buf, "\r\nHTTP/");
2328 /* find last start of a new header */ 2208 if (start != NULL) {
2329 start = strrstr2 (buf, "\r\nHTTP/"); 2209 start += 2;
2330 if (start != NULL) { 2210 buf = start;
2331 start += 2; 2211 }
2332 buf = start;
2333 }
2334
2335 first_line_end = strstr(buf, "\r\n");
2336 if (first_line_end == NULL) return -1;
2337
2338 first_line_len = (size_t)(first_line_end - buf);
2339 status_line->first_line = (char *)malloc (first_line_len + 1);
2340 if (status_line->first_line == NULL) return -1;
2341 memcpy (status_line->first_line, buf, first_line_len);
2342 status_line->first_line[first_line_len] = '\0';
2343 first_line_buf = strdup( status_line->first_line );
2344
2345 /* protocol and version: "HTTP/x.x" SP or "HTTP/2" SP */
2346
2347 p = strtok(first_line_buf, "/");
2348 if( p == NULL ) { free( first_line_buf ); return -1; }
2349 if( strcmp( p, "HTTP" ) != 0 ) { free( first_line_buf ); return -1; }
2350
2351 p = strtok( NULL, " " );
2352 if( p == NULL ) { free( first_line_buf ); return -1; }
2353 if( strchr( p, '.' ) != NULL ) {
2354
2355 /* HTTP 1.x case */
2356 strtok( p, "." );
2357 status_line->http_major = (int)strtol( p, &pp, 10 );
2358 if( *pp != '\0' ) { free( first_line_buf ); return -1; }
2359 strtok( NULL, " " );
2360 status_line->http_minor = (int)strtol( p, &pp, 10 );
2361 if( *pp != '\0' ) { free( first_line_buf ); return -1; }
2362 p += 4; /* 1.x SP */
2363 } else {
2364 /* HTTP 2 case */
2365 status_line->http_major = (int)strtol( p, &pp, 10 );
2366 status_line->http_minor = 0;
2367 p += 2; /* 2 SP */
2368 }
2369
2370 /* status code: "404" or "404.1", then SP */
2371
2372 p = strtok( p, " " );
2373 if( p == NULL ) { free( first_line_buf ); return -1; }
2374 if( strchr( p, '.' ) != NULL ) {
2375 char *ppp;
2376 ppp = strtok( p, "." );
2377 status_line->http_code = (int)strtol( ppp, &pp, 10 );
2378 if( *pp != '\0' ) { free( first_line_buf ); return -1; }
2379 ppp = strtok( NULL, "" );
2380 status_line->http_subcode = (int)strtol( ppp, &pp, 10 );
2381 if( *pp != '\0' ) { free( first_line_buf ); return -1; }
2382 p += 6; /* 400.1 SP */
2383 } else {
2384 status_line->http_code = (int)strtol( p, &pp, 10 );
2385 status_line->http_subcode = -1;
2386 if( *pp != '\0' ) { free( first_line_buf ); return -1; }
2387 p += 4; /* 400 SP */
2388 }
2389
2390 /* Human readable message: "Not Found" CRLF */
2391
2392 p = strtok( p, "" );
2393 if( p == NULL ) { status_line->msg = ""; return 0; }
2394 status_line->msg = status_line->first_line + ( p - first_line_buf );
2395 free( first_line_buf );
2396
2397 return 0;
2398}
2399 2212
2400void 2213 first_line_end = strstr(buf, "\r\n");
2401curlhelp_free_statusline (curlhelp_statusline *status_line) 2214 if (first_line_end == NULL)
2402{ 2215 return -1;
2403 free (status_line->first_line); 2216
2404} 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 }
2405 2264
2406void 2265 /* status code: "404" or "404.1", then SP */
2407remove_newlines (char *s)
2408{
2409 char *p;
2410 2266
2411 for (p = s; *p != '\0'; p++) 2267 p = strtok(p, " ");
2412 if (*p == '\r' || *p == '\n') 2268 if (p == NULL) {
2413 *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;
2414} 2308}
2415 2309
2416char * 2310void curlhelp_free_statusline(curlhelp_statusline *status_line) { free(status_line->first_line); }
2417get_header_value (const struct phr_header* headers, const size_t nof_headers, const char* header) 2311
2418{ 2312char *get_header_value(const struct phr_header *headers, const size_t nof_headers, const char *header) {
2419 for(size_t i = 0; i < nof_headers; i++ ) { 2313 for (size_t i = 0; i < nof_headers; i++) {
2420 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) {
2421 return strndup( headers[i].value, headers[i].value_len ); 2315 return strndup(headers[i].value, headers[i].value_len);
2422 } 2316 }
2423 } 2317 }
2424 return NULL; 2318 return NULL;
2425} 2319}
2426 2320
2427int 2321int check_document_dates(const curlhelp_write_curlbuf *header_buf, char (*msg)[DEFAULT_BUFFER_SIZE]) {
2428check_document_dates (const curlhelp_write_curlbuf *header_buf, char (*msg)[DEFAULT_BUFFER_SIZE]) 2322 char *server_date = NULL;
2429{ 2323 char *document_date = NULL;
2430 char *server_date = NULL; 2324 int date_result = STATE_OK;
2431 char *document_date = NULL; 2325 curlhelp_statusline status_line;
2432 int date_result = STATE_OK; 2326 struct phr_header headers[255];
2433 curlhelp_statusline status_line; 2327 size_t nof_headers = 255;
2434 struct phr_header headers[255]; 2328 size_t msglen;
2435 size_t nof_headers = 255; 2329
2436 size_t msglen; 2330 int res = phr_parse_response(header_buf->buf, header_buf->buflen, &status_line.http_major, &status_line.http_minor,
2437 2331 &status_line.http_code, &status_line.msg, &msglen, headers, &nof_headers, 0);
2438 int res = phr_parse_response (header_buf->buf, header_buf->buflen,
2439 &status_line.http_major, &status_line.http_minor, &status_line.http_code, &status_line.msg, &msglen,
2440 headers, &nof_headers, 0);
2441 2332
2442 if (res == -1) { 2333 if (res == -1) {
2443 die (STATE_UNKNOWN, _("HTTP UNKNOWN - Failed to parse Response\n")); 2334 die(STATE_UNKNOWN, _("HTTP UNKNOWN - Failed to parse Response\n"));
2444 } 2335 }
2445 2336
2446 server_date = get_header_value (headers, nof_headers, "date"); 2337 server_date = get_header_value(headers, nof_headers, "date");
2447 document_date = get_header_value (headers, nof_headers, "last-modified"); 2338 document_date = get_header_value(headers, nof_headers, "last-modified");
2448 2339
2449 if (!server_date || !*server_date) { 2340 if (!server_date || !*server_date) {
2450 char tmp[DEFAULT_BUFFER_SIZE]; 2341 char tmp[DEFAULT_BUFFER_SIZE];
2451 2342
2452 snprintf (tmp, DEFAULT_BUFFER_SIZE, _("%sServer date unknown, "), *msg); 2343 snprintf(tmp, DEFAULT_BUFFER_SIZE, _("%sServer date unknown, "), *msg);
2453 strcpy(*msg, tmp); 2344 strcpy(*msg, tmp);
2454 2345
2455 date_result = max_state_alt(STATE_UNKNOWN, date_result); 2346 date_result = max_state_alt(STATE_UNKNOWN, date_result);
@@ -2457,34 +2348,34 @@ check_document_dates (const curlhelp_write_curlbuf *header_buf, char (*msg)[DEFA
2457 } else if (!document_date || !*document_date) { 2348 } else if (!document_date || !*document_date) {
2458 char tmp[DEFAULT_BUFFER_SIZE]; 2349 char tmp[DEFAULT_BUFFER_SIZE];
2459 2350
2460 snprintf (tmp, DEFAULT_BUFFER_SIZE, _("%sDocument modification date unknown, "), *msg); 2351 snprintf(tmp, DEFAULT_BUFFER_SIZE, _("%sDocument modification date unknown, "), *msg);
2461 strcpy(*msg, tmp); 2352 strcpy(*msg, tmp);
2462 2353
2463 date_result = max_state_alt(STATE_CRITICAL, date_result); 2354 date_result = max_state_alt(STATE_CRITICAL, date_result);
2464 2355
2465 } else { 2356 } else {
2466 time_t srv_data = curl_getdate (server_date, NULL); 2357 time_t srv_data = curl_getdate(server_date, NULL);
2467 time_t doc_data = curl_getdate (document_date, NULL); 2358 time_t doc_data = curl_getdate(document_date, NULL);
2468 if (verbose >= 2) 2359 if (verbose >= 2)
2469 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);
2470 if (srv_data <= 0) { 2361 if (srv_data <= 0) {
2471 char tmp[DEFAULT_BUFFER_SIZE]; 2362 char tmp[DEFAULT_BUFFER_SIZE];
2472 2363
2473 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);
2474 strcpy(*msg, tmp); 2365 strcpy(*msg, tmp);
2475 2366
2476 date_result = max_state_alt(STATE_CRITICAL, date_result); 2367 date_result = max_state_alt(STATE_CRITICAL, date_result);
2477 } else if (doc_data <= 0) { 2368 } else if (doc_data <= 0) {
2478 char tmp[DEFAULT_BUFFER_SIZE]; 2369 char tmp[DEFAULT_BUFFER_SIZE];
2479 2370
2480 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);
2481 strcpy(*msg, tmp); 2372 strcpy(*msg, tmp);
2482 2373
2483 date_result = max_state_alt(STATE_CRITICAL, date_result); 2374 date_result = max_state_alt(STATE_CRITICAL, date_result);
2484 } else if (doc_data > srv_data + 30) { 2375 } else if (doc_data > srv_data + 30) {
2485 char tmp[DEFAULT_BUFFER_SIZE]; 2376 char tmp[DEFAULT_BUFFER_SIZE];
2486 2377
2487 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);
2488 strcpy(*msg, tmp); 2379 strcpy(*msg, tmp);
2489 2380
2490 date_result = max_state_alt(STATE_CRITICAL, date_result); 2381 date_result = max_state_alt(STATE_CRITICAL, date_result);
@@ -2493,14 +2384,14 @@ check_document_dates (const curlhelp_write_curlbuf *header_buf, char (*msg)[DEFA
2493 if (n > (60 * 60 * 24 * 2)) { 2384 if (n > (60 * 60 * 24 * 2)) {
2494 char tmp[DEFAULT_BUFFER_SIZE]; 2385 char tmp[DEFAULT_BUFFER_SIZE];
2495 2386
2496 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));
2497 strcpy(*msg, tmp); 2388 strcpy(*msg, tmp);
2498 2389
2499 date_result = max_state_alt(STATE_CRITICAL, date_result); 2390 date_result = max_state_alt(STATE_CRITICAL, date_result);
2500 } else { 2391 } else {
2501 char tmp[DEFAULT_BUFFER_SIZE]; 2392 char tmp[DEFAULT_BUFFER_SIZE];
2502 2393
2503 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);
2504 strcpy(*msg, tmp); 2395 strcpy(*msg, tmp);
2505 2396
2506 date_result = max_state_alt(STATE_CRITICAL, date_result); 2397 date_result = max_state_alt(STATE_CRITICAL, date_result);
@@ -2508,132 +2399,128 @@ check_document_dates (const curlhelp_write_curlbuf *header_buf, char (*msg)[DEFA
2508 } 2399 }
2509 } 2400 }
2510 2401
2511 if (server_date) free (server_date); 2402 if (server_date)
2512 if (document_date) free (document_date); 2403 free(server_date);
2404 if (document_date)
2405 free(document_date);
2513 2406
2514 return date_result; 2407 return date_result;
2515} 2408}
2516 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;
2517 2417
2518int 2418 int res = phr_parse_response(header_buf->buf, header_buf->buflen, &status_line.http_major, &status_line.http_minor,
2519get_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);
2520{
2521 size_t content_length = 0;
2522 struct phr_header headers[255];
2523 size_t nof_headers = 255;
2524 size_t msglen;
2525 char *content_length_s = NULL;
2526 curlhelp_statusline status_line;
2527
2528 int res = phr_parse_response (header_buf->buf, header_buf->buflen,
2529 &status_line.http_major, &status_line.http_minor, &status_line.http_code, &status_line.msg, &msglen,
2530 headers, &nof_headers, 0);
2531 2420
2532 if (res == -1) { 2421 if (res == -1) {
2533 die (STATE_UNKNOWN, _("HTTP UNKNOWN - Failed to parse Response\n")); 2422 die(STATE_UNKNOWN, _("HTTP UNKNOWN - Failed to parse Response\n"));
2534 } 2423 }
2535 2424
2536 content_length_s = get_header_value (headers, nof_headers, "content-length"); 2425 content_length_s = get_header_value(headers, nof_headers, "content-length");
2537 if (!content_length_s) { 2426 if (!content_length_s) {
2538 return header_buf->buflen + body_buf->buflen; 2427 return header_buf->buflen + body_buf->buflen;
2539 } 2428 }
2540 content_length_s += strspn (content_length_s, " \t"); 2429 content_length_s += strspn(content_length_s, " \t");
2541 content_length = atoi (content_length_s); 2430 content_length = atoi(content_length_s);
2542 if (content_length != body_buf->buflen) { 2431 if (content_length != body_buf->buflen) {
2543 /* 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? */
2544 } 2433 }
2545 2434
2546 if (content_length_s) free (content_length_s); 2435 if (content_length_s)
2436 free(content_length_s);
2547 2437
2548 return header_buf->buflen + body_buf->buflen; 2438 return header_buf->buflen + body_buf->buflen;
2549} 2439}
2550 2440
2551/* 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? */
2552curlhelp_ssl_library 2442curlhelp_ssl_library curlhelp_get_ssl_library(void) {
2553curlhelp_get_ssl_library () 2443 curl_version_info_data *version_data;
2554{ 2444 char *ssl_version;
2555 curl_version_info_data* version_data; 2445 char *library;
2556 char *ssl_version; 2446 curlhelp_ssl_library ssl_library = CURLHELP_SSL_LIBRARY_UNKNOWN;
2557 char *library; 2447
2558 curlhelp_ssl_library ssl_library = CURLHELP_SSL_LIBRARY_UNKNOWN; 2448 version_data = curl_version_info(CURLVERSION_NOW);
2559 2449 if (version_data == NULL)
2560 version_data = curl_version_info (CURLVERSION_NOW); 2450 return CURLHELP_SSL_LIBRARY_UNKNOWN;
2561 if (version_data == NULL) return CURLHELP_SSL_LIBRARY_UNKNOWN; 2451
2562 2452 ssl_version = strdup(version_data->ssl_version);
2563 ssl_version = strdup (version_data->ssl_version); 2453 if (ssl_version == NULL)
2564 if (ssl_version == NULL ) return CURLHELP_SSL_LIBRARY_UNKNOWN; 2454 return CURLHELP_SSL_LIBRARY_UNKNOWN;
2565 2455
2566 library = strtok (ssl_version, "/"); 2456 library = strtok(ssl_version, "/");
2567 if (library == NULL) return CURLHELP_SSL_LIBRARY_UNKNOWN; 2457 if (library == NULL)
2568 2458 return CURLHELP_SSL_LIBRARY_UNKNOWN;
2569 if (strcmp (library, "OpenSSL") == 0) 2459
2570 ssl_library = CURLHELP_SSL_LIBRARY_OPENSSL; 2460 if (strcmp(library, "OpenSSL") == 0)
2571 else if (strcmp (library, "LibreSSL") == 0) 2461 ssl_library = CURLHELP_SSL_LIBRARY_OPENSSL;
2572 ssl_library = CURLHELP_SSL_LIBRARY_LIBRESSL; 2462 else if (strcmp(library, "LibreSSL") == 0)
2573 else if (strcmp (library, "GnuTLS") == 0) 2463 ssl_library = CURLHELP_SSL_LIBRARY_LIBRESSL;
2574 ssl_library = CURLHELP_SSL_LIBRARY_GNUTLS; 2464 else if (strcmp(library, "GnuTLS") == 0)
2575 else if (strcmp (library, "NSS") == 0) 2465 ssl_library = CURLHELP_SSL_LIBRARY_GNUTLS;
2576 ssl_library = CURLHELP_SSL_LIBRARY_NSS; 2466 else if (strcmp(library, "NSS") == 0)
2577 2467 ssl_library = CURLHELP_SSL_LIBRARY_NSS;
2578 if (verbose >= 2) 2468
2579 printf ("* SSL library string is : %s %s (%d)\n", version_data->ssl_version, library, ssl_library); 2469 if (verbose >= 2)
2580 2470 printf("* SSL library string is : %s %s (%d)\n", version_data->ssl_version, library, ssl_library);
2581 free (ssl_version); 2471
2582 2472 free(ssl_version);
2583 return ssl_library; 2473
2474 return ssl_library;
2584} 2475}
2585 2476
2586const char* 2477const char *curlhelp_get_ssl_library_string(curlhelp_ssl_library ssl_library) {
2587curlhelp_get_ssl_library_string (curlhelp_ssl_library ssl_library) 2478 switch (ssl_library) {
2588{ 2479 case CURLHELP_SSL_LIBRARY_OPENSSL:
2589 switch (ssl_library) { 2480 return "OpenSSL";
2590 case CURLHELP_SSL_LIBRARY_OPENSSL: 2481 case CURLHELP_SSL_LIBRARY_LIBRESSL:
2591 return "OpenSSL"; 2482 return "LibreSSL";
2592 case CURLHELP_SSL_LIBRARY_LIBRESSL: 2483 case CURLHELP_SSL_LIBRARY_GNUTLS:
2593 return "LibreSSL"; 2484 return "GnuTLS";
2594 case CURLHELP_SSL_LIBRARY_GNUTLS: 2485 case CURLHELP_SSL_LIBRARY_NSS:
2595 return "GnuTLS"; 2486 return "NSS";
2596 case CURLHELP_SSL_LIBRARY_NSS: 2487 case CURLHELP_SSL_LIBRARY_UNKNOWN:
2597 return "NSS"; 2488 default:
2598 case CURLHELP_SSL_LIBRARY_UNKNOWN: 2489 return "unknown";
2599 default: 2490 }
2600 return "unknown";
2601 }
2602} 2491}
2603 2492
2604#ifdef LIBCURL_FEATURE_SSL 2493#ifdef LIBCURL_FEATURE_SSL
2605#ifndef USE_OPENSSL 2494# ifndef USE_OPENSSL
2606time_t 2495time_t parse_cert_date(const char *s) {
2607parse_cert_date (const char *s) 2496 struct tm tm;
2608{ 2497 time_t date;
2609 struct tm tm; 2498 char *res;
2610 time_t date; 2499
2611 char *res; 2500 if (!s)
2612 2501 return -1;
2613 if (!s) return -1; 2502
2614 2503 /* Jan 17 14:25:12 2020 GMT */
2615 /* Jan 17 14:25:12 2020 GMT */ 2504 res = strptime(s, "%Y-%m-%d %H:%M:%S GMT", &tm);
2616 res = strptime (s, "%Y-%m-%d %H:%M:%S GMT", &tm); 2505 /* Sep 11 12:00:00 2020 GMT */
2617 /* Sep 11 12:00:00 2020 GMT */ 2506 if (res == NULL)
2618 if (res == NULL) strptime (s, "%Y %m %d %H:%M:%S GMT", &tm); 2507 strptime(s, "%Y %m %d %H:%M:%S GMT", &tm);
2619 date = mktime (&tm); 2508 date = mktime(&tm);
2620 2509
2621 return date; 2510 return date;
2622} 2511}
2623 2512
2624/* 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
2625 * OpenSSL could be this function 2514 * OpenSSL could be this function
2626 */ 2515 */
2627int 2516int net_noopenssl_check_certificate(cert_ptr_union *cert_ptr, int days_till_exp_warn, int days_till_exp_crit) {
2628net_noopenssl_check_certificate (cert_ptr_union* cert_ptr, int days_till_exp_warn, int days_till_exp_crit) 2517 int i;
2629{ 2518 struct curl_slist *slist;
2630 int i; 2519 int cname_found = 0;
2631 struct curl_slist* slist; 2520 char *start_date_str = NULL;
2632 int cname_found = 0; 2521 char *end_date_str = NULL;
2633 char* start_date_str = NULL; 2522 time_t start_date;
2634 char* end_date_str = NULL; 2523 time_t end_date;
2635 time_t start_date;
2636 time_t end_date;
2637 char *tz; 2524 char *tz;
2638 float time_left; 2525 float time_left;
2639 int days_left; 2526 int days_left;
@@ -2641,66 +2528,64 @@ net_noopenssl_check_certificate (cert_ptr_union* cert_ptr, int days_till_exp_war
2641 char timestamp[50] = ""; 2528 char timestamp[50] = "";
2642 int status = STATE_UNKNOWN; 2529 int status = STATE_UNKNOWN;
2643 2530
2644 if (verbose >= 2) 2531 if (verbose >= 2)
2645 printf ("**** REQUEST CERTIFICATES ****\n"); 2532 printf("**** REQUEST CERTIFICATES ****\n");
2646 2533
2647 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++) {
2648 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) {
2649 /* find first common name in subject, 2536 /* find first common name in subject,
2650 * TODO: check alternative subjects for 2537 * TODO: check alternative subjects for
2651 * TODO: have a decent parser here and not a hack 2538 * TODO: have a decent parser here and not a hack
2652 * multi-host certificate, check wildcards 2539 * multi-host certificate, check wildcards
2653 */ 2540 */
2654 if (strncasecmp (slist->data, "Subject:", 8) == 0) { 2541 if (strncasecmp(slist->data, "Subject:", 8) == 0) {
2655 int d = 3; 2542 int d = 3;
2656 char* p = strstr (slist->data, "CN="); 2543 char *p = strstr(slist->data, "CN=");
2657 if (p == NULL) { 2544 if (p == NULL) {
2658 d = 5; 2545 d = 5;
2659 p = strstr (slist->data, "CN = "); 2546 p = strstr(slist->data, "CN = ");
2660 } 2547 }
2661 if (p != NULL) { 2548 if (p != NULL) {
2662 if (strncmp (host_name, p+d, strlen (host_name)) == 0) { 2549 if (strncmp(host_name, p + d, strlen(host_name)) == 0) {
2663 cname_found = 1; 2550 cname_found = 1;
2664 } 2551 }
2665 } 2552 }
2666 } else if (strncasecmp (slist->data, "Start Date:", 11) == 0) { 2553 } else if (strncasecmp(slist->data, "Start Date:", 11) == 0) {
2667 start_date_str = &slist->data[11]; 2554 start_date_str = &slist->data[11];
2668 } else if (strncasecmp (slist->data, "Expire Date:", 12) == 0) { 2555 } else if (strncasecmp(slist->data, "Expire Date:", 12) == 0) {
2669 end_date_str = &slist->data[12]; 2556 end_date_str = &slist->data[12];
2670 } else if (strncasecmp (slist->data, "Cert:", 5) == 0) { 2557 } else if (strncasecmp(slist->data, "Cert:", 5) == 0) {
2671 goto HAVE_FIRST_CERT; 2558 goto HAVE_FIRST_CERT;
2672 } 2559 }
2673 if (verbose >= 2) 2560 if (verbose >= 2)
2674 printf ("%d ** %s\n", i, slist->data); 2561 printf("%d ** %s\n", i, slist->data);
2675 } 2562 }
2676 } 2563 }
2677HAVE_FIRST_CERT: 2564HAVE_FIRST_CERT:
2678 2565
2679 if (verbose >= 2) 2566 if (verbose >= 2)
2680 printf ("**** REQUEST CERTIFICATES ****\n"); 2567 printf("**** REQUEST CERTIFICATES ****\n");
2681 2568
2682 if (!cname_found) { 2569 if (!cname_found) {
2683 printf("%s\n",_("CRITICAL - Cannot retrieve certificate subject.")); 2570 printf("%s\n", _("CRITICAL - Cannot retrieve certificate subject."));
2684 return STATE_CRITICAL; 2571 return STATE_CRITICAL;
2685 } 2572 }
2686 2573
2687 start_date = parse_cert_date (start_date_str); 2574 start_date = parse_cert_date(start_date_str);
2688 if (start_date <= 0) { 2575 if (start_date <= 0) {
2689 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);
2690 start_date_str); 2577 puts(msg);
2691 puts (msg); 2578 return STATE_WARNING;
2692 return STATE_WARNING; 2579 }
2693 } 2580
2694 2581 end_date = parse_cert_date(end_date_str);
2695 end_date = parse_cert_date (end_date_str); 2582 if (end_date <= 0) {
2696 if (end_date <= 0) { 2583 snprintf(msg, DEFAULT_BUFFER_SIZE, _("WARNING - Unparsable 'Expire Date' in certificate: '%s'"), start_date_str);
2697 snprintf (msg, DEFAULT_BUFFER_SIZE, _("WARNING - Unparsable 'Expire Date' in certificate: '%s'"), 2584 puts(msg);
2698 start_date_str); 2585 return STATE_WARNING;
2699 puts (msg); 2586 }
2700 return STATE_WARNING; 2587
2701 } 2588 time_left = difftime(end_date, time(NULL));
2702
2703 time_left = difftime (end_date, time(NULL));
2704 days_left = time_left / 86400; 2589 days_left = time_left / 86400;
2705 tz = getenv("TZ"); 2590 tz = getenv("TZ");
2706 setenv("TZ", "GMT", 1); 2591 setenv("TZ", "GMT", 1);
@@ -2713,30 +2598,31 @@ HAVE_FIRST_CERT:
2713 tzset(); 2598 tzset();
2714 2599
2715 if (days_left > 0 && days_left <= days_till_exp_warn) { 2600 if (days_left > 0 && days_left <= days_till_exp_warn) {
2716 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);
2717 if (days_left > days_till_exp_crit) 2603 if (days_left > days_till_exp_crit)
2718 status = STATE_WARNING; 2604 status = STATE_WARNING;
2719 else 2605 else
2720 status = STATE_CRITICAL; 2606 status = STATE_CRITICAL;
2721 } else if (days_left == 0 && time_left > 0) { 2607 } else if (days_left == 0 && time_left > 0) {
2722 if (time_left >= 3600) 2608 if (time_left >= 3600)
2723 time_remaining = (int) time_left / 3600; 2609 time_remaining = (int)time_left / 3600;
2724 else 2610 else
2725 time_remaining = (int) time_left / 60; 2611 time_remaining = (int)time_left / 60;
2726 2612
2727 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,
2728 (days_left>days_till_exp_crit) ? "WARNING" : "CRITICAL", host_name, time_remaining, 2614 time_remaining, time_left >= 3600 ? "hours" : "minutes", timestamp);
2729 time_left >= 3600 ? "hours" : "minutes", timestamp);
2730 2615
2731 if ( days_left > days_till_exp_crit) 2616 if (days_left > days_till_exp_crit)
2732 status = STATE_WARNING; 2617 status = STATE_WARNING;
2733 else 2618 else
2734 status = STATE_CRITICAL; 2619 status = STATE_CRITICAL;
2735 } else if (time_left < 0) { 2620 } else if (time_left < 0) {
2736 printf(_("CRITICAL - Certificate '%s' expired on %s.\n"), host_name, timestamp); 2621 printf(_("CRITICAL - Certificate '%s' expired on %s.\n"), host_name, timestamp);
2737 status=STATE_CRITICAL; 2622 status = STATE_CRITICAL;
2738 } else if (days_left == 0) { 2623 } else if (days_left == 0) {
2739 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);
2740 if (days_left > days_till_exp_crit) 2626 if (days_left > days_till_exp_crit)
2741 status = STATE_WARNING; 2627 status = STATE_WARNING;
2742 else 2628 else
@@ -2747,5 +2633,5 @@ HAVE_FIRST_CERT:
2747 } 2633 }
2748 return status; 2634 return status;
2749} 2635}
2750#endif /* USE_OPENSSL */ 2636# endif /* USE_OPENSSL */
2751#endif /* LIBCURL_FEATURE_SSL */ 2637#endif /* LIBCURL_FEATURE_SSL */
diff --git a/plugins/check_dbi.c b/plugins/check_dbi.c
index 29c8520..9657567 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 be7a610..2bbd1e0 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 b3dd301..d1d1b92 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"
@@ -48,14 +47,14 @@ const char *email = "devel@monitoring-plugins.org";
48#include "mountlist.h" 47#include "mountlist.h"
49#include <float.h> 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,25 +107,24 @@ 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
122static int process_arguments (int, char **); 120static int process_arguments(int /*argc*/, char ** /*argv*/);
123static void set_all_thresholds (struct parameter_list *path); 121static void set_all_thresholds(struct parameter_list *path);
124static void print_help (void); 122static void print_help(void);
125void print_usage (void); 123void print_usage(void);
126static double calculate_percent(uintmax_t, uintmax_t); 124static double calculate_percent(uintmax_t, uintmax_t);
127static bool stat_path (struct parameter_list *p); 125static bool stat_path(struct parameter_list *p);
128static void get_stats (struct parameter_list *p, struct fs_usage *fsp); 126static void get_stats(struct parameter_list *p, struct fs_usage *fsp);
129static void get_path_stats (struct parameter_list *p, struct fs_usage *fsp); 127static void get_path_stats(struct parameter_list *p, struct fs_usage *fsp);
130 128
131static char *units; 129static char *units;
132static uintmax_t mult = 1024 * 1024; 130static uintmax_t mult = 1024 * 1024;
@@ -155,992 +153,961 @@ static char *group = NULL;
155static struct stat *stat_buf; 153static struct stat *stat_buf;
156static struct name_list *seen = NULL; 154static struct name_list *seen = NULL;
157 155
158 156int main(int argc, char **argv) {
159int 157 int result = STATE_UNKNOWN;
160main (int argc, char **argv) 158 int disk_result = STATE_UNKNOWN;
161{ 159 char *output;
162 int result = STATE_UNKNOWN; 160 char *ignored;
163 int disk_result = STATE_UNKNOWN; 161 char *details;
164 char *output; 162 char *perf;
165 char *ignored; 163 char *perf_ilabel;
166 char *details; 164 char *preamble = " - free space:";
167 char *perf; 165 char *ignored_preamble = " - ignored paths:";
168 char *perf_ilabel; 166 char *flag_header;
169 char *preamble = " - free space:"; 167 int temp_result;
170 char *ignored_preamble = " - ignored paths:"; 168
171 char *flag_header; 169 struct mount_entry *me;
172 int temp_result; 170 struct fs_usage fsp;
173 171 struct parameter_list *temp_list;
174 struct mount_entry *me; 172 struct parameter_list *path;
175 struct fs_usage fsp;
176 struct parameter_list *temp_list, *path;
177 173
178#ifdef __CYGWIN__ 174#ifdef __CYGWIN__
179 char mountdir[32]; 175 char mountdir[32];
180#endif 176#endif
181 177
182 output = strdup (""); 178 output = strdup("");
183 ignored = strdup (""); 179 ignored = strdup("");
184 details = strdup (""); 180 details = strdup("");
185 perf = strdup (""); 181 perf = strdup("");
186 perf_ilabel = strdup (""); 182 perf_ilabel = strdup("");
187 stat_buf = malloc(sizeof *stat_buf); 183 stat_buf = malloc(sizeof *stat_buf);
188 184
189 setlocale (LC_ALL, ""); 185 setlocale(LC_ALL, "");
190 bindtextdomain (PACKAGE, LOCALEDIR); 186 bindtextdomain(PACKAGE, LOCALEDIR);
191 textdomain (PACKAGE); 187 textdomain(PACKAGE);
192 188
193 mount_list = read_file_system_list (0); 189 mount_list = read_file_system_list(0);
194 190
195 /* Parse extra opts if any */ 191 /* Parse extra opts if any */
196 argv = np_extra_opts (&argc, argv, progname); 192 argv = np_extra_opts(&argc, argv, progname);
197 193
198 if (process_arguments (argc, argv) == ERROR) 194 if (process_arguments(argc, argv) == ERROR)
199 usage4 (_("Could not parse arguments")); 195 usage4(_("Could not parse arguments"));
200 196
201 /* If a list of paths has not been selected, find entire 197 /* If a list of paths has not been selected, find entire
202 mount list and create list of paths 198 mount list and create list of paths
203 */ 199 */
204 if (path_selected == false && path_ignored == false) { 200 if (path_selected == false && path_ignored == false) {
205 for (me = mount_list; me; me = me->me_next) { 201 for (me = mount_list; me; me = me->me_next) {
206 if (! (path = np_find_parameter(path_select_list, me->me_mountdir))) { 202 if (!(path = np_find_parameter(path_select_list, me->me_mountdir))) {
207 path = np_add_parameter(&path_select_list, me->me_mountdir); 203 path = np_add_parameter(&path_select_list, me->me_mountdir);
208 } 204 }
209 path->best_match = me; 205 path->best_match = me;
210 path->group = group; 206 path->group = group;
211 set_all_thresholds(path); 207 set_all_thresholds(path);
212 } 208 }
213 } 209 }
214 210
215 if (path_ignored == false) { 211 if (path_ignored == false) {
216 np_set_best_match(path_select_list, mount_list, exact_match); 212 np_set_best_match(path_select_list, mount_list, exact_match);
217 } 213 }
218 214
219 /* Error if no match found for specified paths */ 215 /* Error if no match found for specified paths */
220 temp_list = path_select_list; 216 temp_list = path_select_list;
221 217
222 while (path_select_list) { 218 while (path_select_list) {
223 if (! path_select_list->best_match && ignore_missing == true) { 219 if (!path_select_list->best_match && ignore_missing == true) {
224 /* 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 */
225 if (path_select_list == temp_list) { 221 if (path_select_list == temp_list) {
226 temp_list = path_select_list->name_next; 222 temp_list = path_select_list->name_next;
227 } 223 }
228 /* 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 */
229 xasprintf (&ignored, "%s %s;", ignored, path_select_list->name); 225 xasprintf(&ignored, "%s %s;", ignored, path_select_list->name);
230 /* 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. */
231 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);
232 } else if (! path_select_list->best_match) { 228 } else if (!path_select_list->best_match) {
233 /* Without --ignore-missing option, exit with Critical state. */ 229 /* Without --ignore-missing option, exit with Critical state. */
234 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);
235 } else { 231 } else {
236 /* Continue jumping through the list */ 232 /* Continue jumping through the list */
237 path_select_list = path_select_list->name_next; 233 path_select_list = path_select_list->name_next;
238 } 234 }
239 } 235 }
240 236
241 path_select_list = temp_list; 237 path_select_list = temp_list;
242 238
243 if (! path_select_list && ignore_missing == true) { 239 if (!path_select_list && ignore_missing == true) {
244 result = STATE_OK; 240 result = STATE_OK;
245 if (verbose >= 2) { 241 if (verbose >= 2) {
246 printf ("None of the provided paths were found\n"); 242 printf("None of the provided paths were found\n");
247 } 243 }
248 } 244 }
249 245
250 /* Process for every path in list */ 246 /* Process for every path in list */
251 for (path = path_select_list; path; path=path->name_next) { 247 for (path = path_select_list; path; path = path->name_next) {
252 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)
253 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,
254 path->name, 250 path->freespace_percent->critical->end);
255 path->freespace_percent->warning->end, 251
256 path->freespace_percent->critical->end); 252 if (verbose >= 3 && path->group != NULL)
257 253 printf("Group of %s: %s\n", path->name, path->group);
258 if (verbose >= 3 && path->group != NULL) 254
259 printf("Group of %s: %s\n",path->name,path->group); 255 /* reset disk result */
260 256 disk_result = STATE_UNKNOWN;
261 /* reset disk result */ 257
262 disk_result = STATE_UNKNOWN; 258 me = path->best_match;
263 259
264 me = path->best_match; 260 if (!me) {
265 261 continue;
266 if (!me) { 262 }
267 continue;
268 }
269 263
270#ifdef __CYGWIN__ 264#ifdef __CYGWIN__
271 if (strncmp(path->name, "/cygdrive/", 10) != 0 || strlen(path->name) > 11) 265 if (strncmp(path->name, "/cygdrive/", 10) != 0 || strlen(path->name) > 11)
272 continue; 266 continue;
273 snprintf(mountdir, sizeof(mountdir), "%s:\\", me->me_mountdir + 10); 267 snprintf(mountdir, sizeof(mountdir), "%s:\\", me->me_mountdir + 10);
274 if (GetDriveType(mountdir) != DRIVE_FIXED) 268 if (GetDriveType(mountdir) != DRIVE_FIXED)
275 me->me_remote = 1; 269 me->me_remote = 1;
276#endif 270#endif
277 /* Filters */ 271 /* Filters */
278 272
279 /* Remove filesystems already seen */ 273 /* Remove filesystems already seen */
280 if (np_seen_name(seen, me->me_mountdir)) { 274 if (np_seen_name(seen, me->me_mountdir)) {
281 continue; 275 continue;
282 } 276 }
283 np_add_name(&seen, me->me_mountdir); 277 np_add_name(&seen, me->me_mountdir);
284 278
285 if (path->group == NULL) { 279 if (path->group == NULL) {
286 /* Skip remote filesystems if we're not interested in them */ 280 /* Skip remote filesystems if we're not interested in them */
287 if (me->me_remote && show_local_fs) { 281 if (me->me_remote && show_local_fs) {
288 if (stat_remote_fs) { 282 if (stat_remote_fs) {
289 if (!stat_path(path) && ignore_missing == true) { 283 if (!stat_path(path) && ignore_missing == true) {
290 result = STATE_OK; 284 result = STATE_OK;
291 xasprintf (&ignored, "%s %s;", ignored, path->name); 285 xasprintf(&ignored, "%s %s;", ignored, path->name);
292 } 286 }
293 } 287 }
294 continue; 288 continue;
295 /* 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 */
296 } else if (me->me_dummy && !show_all_fs) { 290 }
297 continue; 291 if (me->me_dummy && !show_all_fs) {
298 /* Skip excluded fstypes */ 292 continue;
299 } else if (fs_exclude_list && np_find_regmatch (fs_exclude_list, me->me_type)) { 293 /* Skip excluded fstypes */
300 continue; 294 }
301 /* Skip excluded fs's */ 295 if (fs_exclude_list && np_find_regmatch(fs_exclude_list, me->me_type)) {
302 } else if (dp_exclude_list && 296 continue;
303 (np_find_name (dp_exclude_list, me->me_devname) || 297 /* Skip excluded fs's */
304 np_find_name (dp_exclude_list, me->me_mountdir))) { 298 }
305 continue; 299 if (dp_exclude_list && (np_find_name(dp_exclude_list, me->me_devname) || np_find_name(dp_exclude_list, me->me_mountdir))) {
306 /* Skip not included fstypes */ 300 continue;
307 } else if (fs_include_list && !np_find_regmatch(fs_include_list, me->me_type)) { 301 /* Skip not included fstypes */
308 continue; 302 }
309 } 303 if (fs_include_list && !np_find_regmatch(fs_include_list, me->me_type)) {
310 } 304 continue;
311 305 }
312 if (!stat_path(path)) { 306 }
313 if (ignore_missing == true) { 307
314 result = STATE_OK; 308 if (!stat_path(path)) {
315 xasprintf (&ignored, "%s %s;", ignored, path->name); 309 if (ignore_missing == true) {
316 } 310 result = STATE_OK;
317 continue; 311 xasprintf(&ignored, "%s %s;", ignored, path->name);
318 } 312 }
319 get_fs_usage (me->me_mountdir, me->me_devname, &fsp); 313 continue;
320 314 }
321 if (fsp.fsu_blocks && strcmp ("none", me->me_mountdir)) { 315 get_fs_usage(me->me_mountdir, me->me_devname, &fsp);
322 get_stats (path, &fsp); 316
323 317 if (fsp.fsu_blocks && strcmp("none", me->me_mountdir)) {
324 if (verbose >= 3) { 318 get_stats(path, &fsp);
325 printf ("For %s, used_pct=%f free_pct=%f used_units=%lu free_units=%lu total_units=%lu used_inodes_pct=%f free_inodes_pct=%f fsp.fsu_blocksize=%lu mult=%lu\n", 319
326 me->me_mountdir, 320 if (verbose >= 3) {
327 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 "
328 path->dfree_pct, 322 "free_inodes_pct=%f fsp.fsu_blocksize=%lu mult=%lu\n",
329 path->dused_units, 323 me->me_mountdir, path->dused_pct, path->dfree_pct, path->dused_units, path->dfree_units, path->dtotal_units,
330 path->dfree_units, 324 path->dused_inodes_percent, path->dfree_inodes_percent, fsp.fsu_blocksize, mult);
331 path->dtotal_units, 325 }
332 path->dused_inodes_percent, 326
333 path->dfree_inodes_percent, 327 /* Threshold comparisons */
334 fsp.fsu_blocksize, 328
335 mult); 329 temp_result = get_status(path->dfree_units, path->freespace_units);
336 } 330 if (verbose >= 3)
337 331 printf("Freespace_units result=%d\n", temp_result);
338 /* Threshold comparisons */ 332 disk_result = max_state(disk_result, temp_result);
339
340 temp_result = get_status(path->dfree_units, path->freespace_units);
341 if (verbose >=3) printf("Freespace_units result=%d\n", temp_result);
342 disk_result = max_state( disk_result, temp_result );
343
344 temp_result = get_status(path->dfree_pct, path->freespace_percent);
345 if (verbose >=3) printf("Freespace%% result=%d\n", temp_result);
346 disk_result = max_state( disk_result, temp_result );
347
348 temp_result = get_status(path->dused_units, path->usedspace_units);
349 if (verbose >=3) printf("Usedspace_units result=%d\n", temp_result);
350 disk_result = max_state( disk_result, temp_result );
351
352 temp_result = get_status(path->dused_pct, path->usedspace_percent);
353 if (verbose >=3) printf("Usedspace_percent result=%d\n", temp_result);
354 disk_result = max_state( disk_result, temp_result );
355
356 temp_result = get_status(path->dused_inodes_percent, path->usedinodes_percent);
357 if (verbose >=3) printf("Usedinodes_percent result=%d\n", temp_result);
358 disk_result = max_state( disk_result, temp_result );
359
360 temp_result = get_status(path->dfree_inodes_percent, path->freeinodes_percent);
361 if (verbose >=3) printf("Freeinodes_percent result=%d\n", temp_result);
362 disk_result = max_state( disk_result, temp_result );
363
364 result = max_state(result, disk_result);
365
366 /* What a mess of units. The output shows free space, the perf data shows used space. Yikes!
367 Hack here. Trying to get warn/crit levels from freespace_(units|percent) for perf
368 data. Assumption that start=0. Roll on new syntax...
369 */
370
371 /* *_high_tide must be reinitialized at each run */
372 uint64_t warning_high_tide = UINT64_MAX;
373
374 if (path->freespace_units->warning != NULL) {
375 warning_high_tide = (path->dtotal_units - path->freespace_units->warning->end) * mult;
376 }
377 if (path->freespace_percent->warning != NULL) {
378 warning_high_tide = min( warning_high_tide, (uint64_t)((1.0 - path->freespace_percent->warning->end/100) * (path->dtotal_units * mult)) );
379 }
380
381 uint64_t critical_high_tide = UINT64_MAX;
382
383 if (path->freespace_units->critical != NULL) {
384 critical_high_tide = (path->dtotal_units - path->freespace_units->critical->end) * mult;
385 }
386 if (path->freespace_percent->critical != NULL) {
387 critical_high_tide = min( critical_high_tide, (uint64_t)((1.0 - path->freespace_percent->critical->end/100) * (path->dtotal_units * mult)) );
388 }
389
390 /* Nb: *_high_tide are unset when == UINT64_MAX */
391 xasprintf (&perf, "%s %s", perf,
392 perfdata_uint64 (
393 (!strcmp(me->me_mountdir, "none") || display_mntp) ? me->me_devname : me->me_mountdir,
394 path->dused_units * mult, "B",
395 (warning_high_tide == UINT64_MAX ? false : true), warning_high_tide,
396 (critical_high_tide == UINT64_MAX ? false : true), critical_high_tide,
397 true, 0,
398 true, path->dtotal_units * mult));
399
400 if (display_inodes_perfdata) {
401 /* *_high_tide must be reinitialized at each run */
402 warning_high_tide = UINT64_MAX;
403 critical_high_tide = UINT64_MAX;
404
405 if (path->freeinodes_percent->warning != NULL) {
406 warning_high_tide = (uint64_t) fabs( min( (double) warning_high_tide, (double) (1.0 - path->freeinodes_percent->warning->end/100)*path->inodes_total ));
407 }
408 if (path->freeinodes_percent->critical != NULL) {
409 critical_high_tide = (uint64_t) fabs( min( (double) critical_high_tide, (double) (1.0 - path->freeinodes_percent->critical->end/100)*path->inodes_total ));
410 }
411
412 xasprintf (&perf_ilabel, "%s (inodes)", (!strcmp(me->me_mountdir, "none") || display_mntp) ? me->me_devname : me->me_mountdir);
413 /* Nb: *_high_tide are unset when == UINT64_MAX */
414 xasprintf (&perf, "%s %s", perf,
415 perfdata_uint64 (perf_ilabel,
416 path->inodes_used, "",
417 (warning_high_tide != UINT64_MAX ? true : false), warning_high_tide,
418 (critical_high_tide != UINT64_MAX ? true : false), critical_high_tide,
419 true, 0,
420 true, path->inodes_total));
421 }
422
423 if (disk_result==STATE_OK && erronly && !verbose)
424 continue;
425
426 if(disk_result && verbose >= 1) {
427 xasprintf(&flag_header, " %s [", state_text (disk_result));
428 } else {
429 xasprintf(&flag_header, "");
430 }
431 xasprintf (&output, "%s%s %s %llu%s (%.1f%%",
432 output, flag_header,
433 (!strcmp(me->me_mountdir, "none") || display_mntp) ? me->me_devname : me->me_mountdir,
434 path->dfree_units,
435 units,
436 path->dfree_pct);
437 if (path->dused_inodes_percent < 0) {
438 xasprintf(&output, "%s inode=-)%s;", output, (disk_result ? "]" : ""));
439 } else {
440 xasprintf(&output, "%s inode=%.0f%%)%s;", output, path->dfree_inodes_percent, ((disk_result && verbose >= 1) ? "]" : ""));
441 }
442 free(flag_header);
443 }
444 }
445
446 if (verbose >= 2)
447 xasprintf (&output, "%s%s", output, details);
448
449 if (strcmp(output, "") == 0 && ! erronly) {
450 preamble = "";
451 xasprintf (&output, " - No disks were found for provided parameters");
452 }
453
454 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);
455 return result;
456}
457 333
334 temp_result = get_status(path->dfree_pct, path->freespace_percent);
335 if (verbose >= 3)
336 printf("Freespace%% result=%d\n", temp_result);
337 disk_result = max_state(disk_result, temp_result);
338
339 temp_result = get_status(path->dused_units, path->usedspace_units);
340 if (verbose >= 3)
341 printf("Usedspace_units result=%d\n", temp_result);
342 disk_result = max_state(disk_result, temp_result);
343
344 temp_result = get_status(path->dused_pct, path->usedspace_percent);
345 if (verbose >= 3)
346 printf("Usedspace_percent result=%d\n", temp_result);
347 disk_result = max_state(disk_result, temp_result);
348
349 temp_result = get_status(path->dused_inodes_percent, path->usedinodes_percent);
350 if (verbose >= 3)
351 printf("Usedinodes_percent result=%d\n", temp_result);
352 disk_result = max_state(disk_result, temp_result);
353
354 temp_result = get_status(path->dfree_inodes_percent, path->freeinodes_percent);
355 if (verbose >= 3)
356 printf("Freeinodes_percent result=%d\n", temp_result);
357 disk_result = max_state(disk_result, temp_result);
358
359 result = max_state(result, disk_result);
360
361 /* What a mess of units. The output shows free space, the perf data shows used space. Yikes!
362 Hack here. Trying to get warn/crit levels from freespace_(units|percent) for perf
363 data. Assumption that start=0. Roll on new syntax...
364 */
365
366 /* *_high_tide must be reinitialized at each run */
367 uint64_t warning_high_tide = UINT64_MAX;
368
369 if (path->freespace_units->warning != NULL) {
370 warning_high_tide = (path->dtotal_units - path->freespace_units->warning->end) * mult;
371 }
372 if (path->freespace_percent->warning != NULL) {
373 warning_high_tide =
374 min(warning_high_tide, (uint64_t)((1.0 - path->freespace_percent->warning->end / 100) * (path->dtotal_units * mult)));
375 }
376
377 uint64_t critical_high_tide = UINT64_MAX;
378
379 if (path->freespace_units->critical != NULL) {
380 critical_high_tide = (path->dtotal_units - path->freespace_units->critical->end) * mult;
381 }
382 if (path->freespace_percent->critical != NULL) {
383 critical_high_tide =
384 min(critical_high_tide, (uint64_t)((1.0 - path->freespace_percent->critical->end / 100) * (path->dtotal_units * mult)));
385 }
386
387 /* Nb: *_high_tide are unset when == UINT64_MAX */
388 xasprintf(&perf, "%s %s", perf,
389 perfdata_uint64((!strcmp(me->me_mountdir, "none") || display_mntp) ? me->me_devname : me->me_mountdir,
390 path->dused_units * mult, "B", (warning_high_tide == UINT64_MAX ? false : true), warning_high_tide,
391 (critical_high_tide == UINT64_MAX ? false : true), critical_high_tide, true, 0, true,
392 path->dtotal_units * mult));
393
394 if (display_inodes_perfdata) {
395 /* *_high_tide must be reinitialized at each run */
396 warning_high_tide = UINT64_MAX;
397 critical_high_tide = UINT64_MAX;
398
399 if (path->freeinodes_percent->warning != NULL) {
400 warning_high_tide = (uint64_t)fabs(
401 min((double)warning_high_tide, (double)(1.0 - path->freeinodes_percent->warning->end / 100) * path->inodes_total));
402 }
403 if (path->freeinodes_percent->critical != NULL) {
404 critical_high_tide = (uint64_t)fabs(min(
405 (double)critical_high_tide, (double)(1.0 - path->freeinodes_percent->critical->end / 100) * path->inodes_total));
406 }
407
408 xasprintf(&perf_ilabel, "%s (inodes)",
409 (!strcmp(me->me_mountdir, "none") || display_mntp) ? me->me_devname : me->me_mountdir);
410 /* Nb: *_high_tide are unset when == UINT64_MAX */
411 xasprintf(&perf, "%s %s", perf,
412 perfdata_uint64(perf_ilabel, path->inodes_used, "", (warning_high_tide != UINT64_MAX ? true : false),
413 warning_high_tide, (critical_high_tide != UINT64_MAX ? true : false), critical_high_tide, true, 0,
414 true, path->inodes_total));
415 }
416
417 if (disk_result == STATE_OK && erronly && !verbose)
418 continue;
419
420 if (disk_result && verbose >= 1) {
421 xasprintf(&flag_header, " %s [", state_text(disk_result));
422 } else {
423 xasprintf(&flag_header, "");
424 }
425 xasprintf(&output, "%s%s %s %llu%s (%.1f%%", output, flag_header,
426 (!strcmp(me->me_mountdir, "none") || display_mntp) ? me->me_devname : me->me_mountdir, path->dfree_units, units,
427 path->dfree_pct);
428 if (path->dused_inodes_percent < 0) {
429 xasprintf(&output, "%s inode=-)%s;", output, (disk_result ? "]" : ""));
430 } else {
431 xasprintf(&output, "%s inode=%.0f%%)%s;", output, path->dfree_inodes_percent, ((disk_result && verbose >= 1) ? "]" : ""));
432 }
433 free(flag_header);
434 }
435 }
436
437 if (verbose >= 2)
438 xasprintf(&output, "%s%s", output, details);
439
440 if (strcmp(output, "") == 0 && !erronly) {
441 preamble = "";
442 xasprintf(&output, " - No disks were found for provided parameters");
443 }
444
445 printf("DISK %s%s%s%s%s|%s\n", state_text(result), ((erronly && result == STATE_OK)) ? "" : preamble, output,
446 (strcmp(ignored, "") == 0) ? "" : ignored_preamble, ignored, perf);
447 return result;
448}
458 449
459double calculate_percent(uintmax_t value, uintmax_t total) { 450double calculate_percent(uintmax_t value, uintmax_t total) {
460 double pct = -1; 451 double pct = -1;
461 if(value <= DBL_MAX && total != 0) { 452 if (value <= DBL_MAX && total != 0) {
462 pct = (double)value / total * 100.0; 453 pct = (double)value / total * 100.0;
463 } 454 }
464 return pct; 455 return pct;
465} 456}
466 457
467/* process command-line arguments */ 458/* process command-line arguments */
468int 459int process_arguments(int argc, char **argv) {
469process_arguments (int argc, char **argv) 460 int c;
470{ 461 int err;
471 int c, err; 462 struct parameter_list *se;
472 struct parameter_list *se; 463 struct parameter_list *temp_list = NULL;
473 struct parameter_list *temp_list = NULL, *previous = NULL; 464 struct parameter_list *previous = NULL;
474 struct mount_entry *me; 465 struct mount_entry *me;
475 regex_t re; 466 regex_t re;
476 int cflags = REG_NOSUB | REG_EXTENDED; 467 int cflags = REG_NOSUB | REG_EXTENDED;
477 int default_cflags = cflags; 468 int default_cflags = cflags;
478 char errbuf[MAX_INPUT_BUFFER]; 469 char errbuf[MAX_INPUT_BUFFER];
479 int fnd = 0; 470 int fnd = 0;
480 471
481 int option = 0; 472 int option = 0;
482 static struct option longopts[] = { 473 static struct option longopts[] = {{"timeout", required_argument, 0, 't'},
483 {"timeout", required_argument, 0, 't'}, 474 {"warning", required_argument, 0, 'w'},
484 {"warning", required_argument, 0, 'w'}, 475 {"critical", required_argument, 0, 'c'},
485 {"critical", required_argument, 0, 'c'}, 476 {"iwarning", required_argument, 0, 'W'},
486 {"iwarning", required_argument, 0, 'W'}, 477 /* Dang, -C is taken. We might want to reshuffle this. */
487 /* Dang, -C is taken. We might want to reshuffle this. */ 478 {"icritical", required_argument, 0, 'K'},
488 {"icritical", required_argument, 0, 'K'}, 479 {"kilobytes", no_argument, 0, 'k'},
489 {"kilobytes", no_argument, 0, 'k'}, 480 {"megabytes", no_argument, 0, 'm'},
490 {"megabytes", no_argument, 0, 'm'}, 481 {"units", required_argument, 0, 'u'},
491 {"units", required_argument, 0, 'u'}, 482 {"path", required_argument, 0, 'p'},
492 {"path", required_argument, 0, 'p'}, 483 {"partition", required_argument, 0, 'p'},
493 {"partition", required_argument, 0, 'p'}, 484 {"exclude_device", required_argument, 0, 'x'},
494 {"exclude_device", required_argument, 0, 'x'}, 485 {"exclude-type", required_argument, 0, 'X'},
495 {"exclude-type", required_argument, 0, 'X'}, 486 {"include-type", required_argument, 0, 'N'},
496 {"include-type", required_argument, 0, 'N'}, 487 {"group", required_argument, 0, 'g'},
497 {"group", required_argument, 0, 'g'}, 488 {"eregi-path", required_argument, 0, 'R'},
498 {"eregi-path", required_argument, 0, 'R'}, 489 {"eregi-partition", required_argument, 0, 'R'},
499 {"eregi-partition", required_argument, 0, 'R'}, 490 {"ereg-path", required_argument, 0, 'r'},
500 {"ereg-path", required_argument, 0, 'r'}, 491 {"ereg-partition", required_argument, 0, 'r'},
501 {"ereg-partition", required_argument, 0, 'r'}, 492 {"freespace-ignore-reserved", no_argument, 0, 'f'},
502 {"freespace-ignore-reserved", no_argument, 0, 'f'}, 493 {"ignore-ereg-path", required_argument, 0, 'i'},
503 {"ignore-ereg-path", required_argument, 0, 'i'}, 494 {"ignore-ereg-partition", required_argument, 0, 'i'},
504 {"ignore-ereg-partition", required_argument, 0, 'i'}, 495 {"ignore-eregi-path", required_argument, 0, 'I'},
505 {"ignore-eregi-path", required_argument, 0, 'I'}, 496 {"ignore-eregi-partition", required_argument, 0, 'I'},
506 {"ignore-eregi-partition", required_argument, 0, 'I'}, 497 {"ignore-missing", no_argument, 0, 'n'},
507 {"ignore-missing", no_argument, 0, 'n'}, 498 {"local", no_argument, 0, 'l'},
508 {"local", no_argument, 0, 'l'}, 499 {"stat-remote-fs", no_argument, 0, 'L'},
509 {"stat-remote-fs", no_argument, 0, 'L'}, 500 {"iperfdata", no_argument, 0, 'P'},
510 {"iperfdata", no_argument, 0, 'P'}, 501 {"mountpoint", no_argument, 0, 'M'},
511 {"mountpoint", no_argument, 0, 'M'}, 502 {"errors-only", no_argument, 0, 'e'},
512 {"errors-only", no_argument, 0, 'e'}, 503 {"exact-match", no_argument, 0, 'E'},
513 {"exact-match", no_argument, 0, 'E'}, 504 {"all", no_argument, 0, 'A'},
514 {"all", no_argument, 0, 'A'}, 505 {"verbose", no_argument, 0, 'v'},
515 {"verbose", no_argument, 0, 'v'}, 506 {"quiet", no_argument, 0, 'q'},
516 {"quiet", no_argument, 0, 'q'}, 507 {"clear", no_argument, 0, 'C'},
517 {"clear", no_argument, 0, 'C'}, 508 {"version", no_argument, 0, 'V'},
518 {"version", no_argument, 0, 'V'}, 509 {"help", no_argument, 0, 'h'},
519 {"help", no_argument, 0, 'h'}, 510 {0, 0, 0, 0}};
520 {0, 0, 0, 0} 511
521 }; 512 if (argc < 2)
522 513 return ERROR;
523 if (argc < 2) 514
524 return ERROR; 515 np_add_regex(&fs_exclude_list, "iso9660", REG_EXTENDED);
525 516
526 np_add_regex(&fs_exclude_list, "iso9660", REG_EXTENDED); 517 for (c = 1; c < argc; c++)
527 518 if (strcmp("-to", argv[c]) == 0)
528 for (c = 1; c < argc; c++) 519 strcpy(argv[c], "-t");
529 if (strcmp ("-to", argv[c]) == 0) 520
530 strcpy (argv[c], "-t"); 521 while (1) {
531 522 c = getopt_long(argc, argv, "+?VqhvefCt:c:w:K:W:u:p:x:X:N:mklLPg:R:r:i:I:MEAn", longopts, &option);
532 while (1) { 523
533 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)
534 525 break;
535 if (c == -1 || c == EOF) 526
536 break; 527 switch (c) {
537 528 case 't': /* timeout period */
538 switch (c) { 529 if (is_integer(optarg)) {
539 case 't': /* timeout period */ 530 timeout_interval = atoi(optarg);
540 if (is_integer (optarg)) { 531 break;
541 timeout_interval = atoi (optarg); 532 } else {
542 break; 533 usage2(_("Timeout interval must be a positive integer"), optarg);
543 } 534 }
544 else { 535
545 usage2 (_("Timeout interval must be a positive integer"), optarg); 536 /* See comments for 'c' */
546 } 537 case 'w': /* warning threshold */
547
548 /* See comments for 'c' */
549 case 'w': /* warning threshold */
550 if (!is_percentage_expression(optarg) && !is_numeric(optarg)) { 538 if (!is_percentage_expression(optarg) && !is_numeric(optarg)) {
551 die(STATE_UNKNOWN, "Argument for --warning invalid or missing: %s\n", optarg); 539 die(STATE_UNKNOWN, "Argument for --warning invalid or missing: %s\n", optarg);
552 } 540 }
553 541
554 if (strstr(optarg, "%")) { 542 if (strstr(optarg, "%")) {
555 if (*optarg == '@') { 543 if (*optarg == '@') {
556 warn_freespace_percent = optarg; 544 warn_freespace_percent = optarg;
557 } else { 545 } else {
558 xasprintf(&warn_freespace_percent, "@%s", optarg); 546 xasprintf(&warn_freespace_percent, "@%s", optarg);
559 } 547 }
560 } else { 548 } else {
561 if (*optarg == '@') { 549 if (*optarg == '@') {
562 warn_freespace_units = optarg; 550 warn_freespace_units = optarg;
563 } else { 551 } else {
564 xasprintf(&warn_freespace_units, "@%s", optarg); 552 xasprintf(&warn_freespace_units, "@%s", optarg);
565 } 553 }
566 } 554 }
567 break; 555 break;
568 556
569 /* Awful mistake where the range values do not make sense. Normally, 557 /* Awful mistake where the range values do not make sense. Normally,
570 you alert if the value is within the range, but since we are using 558 you alert if the value is within the range, but since we are using
571 freespace, we have to alert if outside the range. Thus we artificially 559 freespace, we have to alert if outside the range. Thus we artificially
572 force @ at the beginning of the range, so that it is backwards compatible 560 force @ at the beginning of the range, so that it is backwards compatible
573 */ 561 */
574 case 'c': /* critical threshold */ 562 case 'c': /* critical threshold */
575 if (!is_percentage_expression(optarg) && !is_numeric(optarg)) { 563 if (!is_percentage_expression(optarg) && !is_numeric(optarg)) {
576 die(STATE_UNKNOWN, "Argument for --critical invalid or missing: %s\n", optarg); 564 die(STATE_UNKNOWN, "Argument for --critical invalid or missing: %s\n", optarg);
577 } 565 }
578 566
579 if (strstr(optarg, "%")) { 567 if (strstr(optarg, "%")) {
580 if (*optarg == '@') { 568 if (*optarg == '@') {
581 crit_freespace_percent = optarg; 569 crit_freespace_percent = optarg;
582 } else { 570 } else {
583 xasprintf(&crit_freespace_percent, "@%s", optarg); 571 xasprintf(&crit_freespace_percent, "@%s", optarg);
584 } 572 }
585 } else { 573 } else {
586 if (*optarg == '@') { 574 if (*optarg == '@') {
587 crit_freespace_units = optarg; 575 crit_freespace_units = optarg;
588 } else { 576 } else {
589 xasprintf(&crit_freespace_units, "@%s", optarg); 577 xasprintf(&crit_freespace_units, "@%s", optarg);
590 } 578 }
591 } 579 }
592 break; 580 break;
593
594 case 'W': /* warning inode threshold */
595 if (*optarg == '@') {
596 warn_freeinodes_percent = optarg;
597 } else {
598 xasprintf(&warn_freeinodes_percent, "@%s", optarg);
599 }
600 break;
601 case 'K': /* critical inode threshold */
602 if (*optarg == '@') {
603 crit_freeinodes_percent = optarg;
604 } else {
605 xasprintf(&crit_freeinodes_percent, "@%s", optarg);
606 }
607 break;
608 case 'u':
609 if (units)
610 free(units);
611 if (! strcasecmp (optarg, "bytes")) {
612 mult = (uintmax_t)1;
613 units = strdup ("B");
614 } else if (!strcmp(optarg, "KiB")) {
615 mult = (uintmax_t)1024;
616 units = strdup ("KiB");
617 } else if (! strcmp (optarg, "kB")) {
618 mult = (uintmax_t)1000;
619 units = strdup ("kB");
620 } else if (!strcmp(optarg, "MiB")) {
621 mult = (uintmax_t)1024 * 1024;
622 units = strdup ("MiB");
623 } else if (! strcmp (optarg, "MB")) {
624 mult = (uintmax_t)1000 * 1000;
625 units = strdup ("MB");
626 } else if (!strcmp(optarg, "GiB")) {
627 mult = (uintmax_t)1024 * 1024 * 1024;
628 units = strdup ("GiB");
629 } else if (! strcmp (optarg, "GB")){
630 mult = (uintmax_t)1000 * 1000 * 1000;
631 units = strdup ("GB");
632 } else if (!strcmp(optarg, "TiB")) {
633 mult = (uintmax_t)1024 * 1024 * 1024 * 1024;
634 units = strdup ("TiB");
635 } else if (! strcmp (optarg, "TB")) {
636 mult = (uintmax_t)1000 * 1000 * 1000 * 1000;
637 units = strdup ("TB");
638 } else if (!strcmp(optarg, "PiB")) {
639 mult = (uintmax_t)1024 * 1024 * 1024 * 1024 * 1024;
640 units = strdup ("PiB");
641 } else if (! strcmp (optarg, "PB")){
642 mult = (uintmax_t)1000 * 1000 * 1000 * 1000 * 1000;
643 units = strdup ("PB");
644 } else {
645 die (STATE_UNKNOWN, _("unit type %s not known\n"), optarg);
646 }
647 if (units == NULL)
648 die (STATE_UNKNOWN, _("failed allocating storage for '%s'\n"), "units");
649 break;
650 case 'k': /* display mountpoint */
651 mult = 1024;
652 if (units)
653 free(units);
654 units = strdup ("kiB");
655 break;
656 case 'm': /* display mountpoint */
657 mult = 1024 * 1024;
658 if (units)
659 free(units);
660 units = strdup ("MiB");
661 break;
662 case 'L':
663 stat_remote_fs = 1;
664 /* fallthrough */
665 case 'l':
666 show_local_fs = 1;
667 break;
668 case 'P':
669 display_inodes_perfdata = 1;
670 break;
671 case 'p': /* select path */
672 if (! (warn_freespace_units || crit_freespace_units || warn_freespace_percent ||
673 crit_freespace_percent || warn_usedspace_units || crit_usedspace_units ||
674 warn_usedspace_percent || crit_usedspace_percent || warn_usedinodes_percent ||
675 crit_usedinodes_percent || warn_freeinodes_percent || crit_freeinodes_percent )) {
676 die (STATE_UNKNOWN, "DISK %s: %s", _("UNKNOWN"), _("Must set a threshold value before using -p\n"));
677 }
678
679 /* add parameter if not found. overwrite thresholds if path has already been added */
680 if (! (se = np_find_parameter(path_select_list, optarg))) {
681 se = np_add_parameter(&path_select_list, optarg);
682
683 if (stat(optarg, &stat_buf[0]) && ignore_missing == true) {
684 path_ignored = true;
685 break;
686 }
687 }
688 se->group = group;
689 set_all_thresholds(se);
690
691 /* With autofs, it is required to stat() the path before re-populating the mount_list */
692 if (!stat_path(se)) {
693 break;
694 }
695 /* NB: We can't free the old mount_list "just like that": both list pointers and struct
696 * pointers are copied around. One of the reason it wasn't done yet is that other parts
697 * of check_disk need the same kind of cleanup so it'd better be done as a whole */
698 mount_list = read_file_system_list (0);
699 np_set_best_match(se, mount_list, exact_match);
700
701 path_selected = true;
702 break;
703 case 'x': /* exclude path or partition */
704 np_add_name(&dp_exclude_list, optarg);
705 break;
706 case 'X': /* exclude file system type */
707 err = np_add_regex(&fs_exclude_list, optarg, REG_EXTENDED);
708 if (err != 0) {
709 regerror (err, &fs_exclude_list->regex, errbuf, MAX_INPUT_BUFFER);
710 die (STATE_UNKNOWN, "DISK %s: %s - %s\n",_("UNKNOWN"), _("Could not compile regular expression"), errbuf);
711 }
712 break;
713 case 'N': /* include file system type */
714 err = np_add_regex(&fs_include_list, optarg, REG_EXTENDED);
715 if (err != 0) {
716 regerror (err, &fs_exclude_list->regex, errbuf, MAX_INPUT_BUFFER);
717 die (STATE_UNKNOWN, "DISK %s: %s - %s\n",_("UNKNOWN"), _("Could not compile regular expression"), errbuf);
718 }
719 break;
720 case 'v': /* verbose */
721 verbose++;
722 break;
723 case 'q': /* TODO: this function should eventually go away (removed 2007-09-20) */
724 /* verbose--; **replaced by line below**. -q was only a broken way of implementing -e */
725 erronly = true;
726 break;
727 case 'e':
728 erronly = true;
729 break;
730 case 'E':
731 if (path_selected)
732 die (STATE_UNKNOWN, "DISK %s: %s", _("UNKNOWN"), _("Must set -E before selecting paths\n"));
733 exact_match = true;
734 break;
735 case 'f':
736 freespace_ignore_reserved = true;
737 break;
738 case 'g':
739 if (path_selected)
740 die (STATE_UNKNOWN, "DISK %s: %s", _("UNKNOWN"), _("Must set group value before selecting paths\n"));
741 group = optarg;
742 break;
743 case 'I':
744 cflags |= REG_ICASE;
745 // Intentional fallthrough
746 case 'i':
747 if (!path_selected)
748 die (STATE_UNKNOWN, "DISK %s: %s\n", _("UNKNOWN"), _("Paths need to be selected before using -i/-I. Use -A to select all paths explicitly"));
749 err = regcomp(&re, optarg, cflags);
750 if (err != 0) {
751 regerror (err, &re, errbuf, MAX_INPUT_BUFFER);
752 die (STATE_UNKNOWN, "DISK %s: %s - %s\n",_("UNKNOWN"), _("Could not compile regular expression"), errbuf);
753 }
754
755 temp_list = path_select_list;
756
757 previous = NULL;
758 while (temp_list) {
759 if (temp_list->best_match) {
760 if (np_regex_match_mount_entry(temp_list->best_match, &re)) {
761
762 if (verbose >=3)
763 printf("ignoring %s matching regex\n", temp_list->name);
764
765 temp_list = np_del_parameter(temp_list, previous);
766 /* pointer to first element needs to be updated if first item gets deleted */
767 if (previous == NULL)
768 path_select_list = temp_list;
769 } else {
770 previous = temp_list;
771 temp_list = temp_list->name_next;
772 }
773 } else {
774 previous = temp_list;
775 temp_list = temp_list->name_next;
776 }
777 }
778
779
780 cflags = default_cflags;
781 break;
782
783 case 'n':
784 ignore_missing = true;
785 break;
786 case 'A':
787 optarg = strdup(".*");
788 // Intentional fallthrough
789 case 'R':
790 cflags |= REG_ICASE;
791 // Intentional fallthrough
792 case 'r':
793 if (! (warn_freespace_units || crit_freespace_units || warn_freespace_percent ||
794 crit_freespace_percent || warn_usedspace_units || crit_usedspace_units ||
795 warn_usedspace_percent || crit_usedspace_percent || warn_usedinodes_percent ||
796 crit_usedinodes_percent || warn_freeinodes_percent || crit_freeinodes_percent )) {
797 die (STATE_UNKNOWN, "DISK %s: %s", _("UNKNOWN"), _("Must set a threshold value before using -r/-R/-A (--ereg-path/--eregi-path/--all)\n"));
798 }
799
800 err = regcomp(&re, optarg, cflags);
801 if (err != 0) {
802 regerror (err, &re, errbuf, MAX_INPUT_BUFFER);
803 die (STATE_UNKNOWN, "DISK %s: %s - %s\n",_("UNKNOWN"), _("Could not compile regular expression"), errbuf);
804 }
805
806 for (me = mount_list; me; me = me->me_next) {
807 if (np_regex_match_mount_entry(me, &re)) {
808 fnd = true;
809 if (verbose >= 3)
810 printf("%s %s matching expression %s\n", me->me_devname, me->me_mountdir, optarg);
811
812 /* add parameter if not found. overwrite thresholds if path has already been added */
813 if (! (se = np_find_parameter(path_select_list, me->me_mountdir))) {
814 se = np_add_parameter(&path_select_list, me->me_mountdir);
815 }
816 se->group = group;
817 set_all_thresholds(se);
818 }
819 }
820
821 if (!fnd && ignore_missing == true) {
822 path_ignored = true;
823 path_selected = true;
824 break;
825 } else if (!fnd)
826 die (STATE_UNKNOWN, "DISK %s: %s - %s\n",_("UNKNOWN"),
827 _("Regular expression did not match any path or disk"), optarg);
828
829 fnd = false;
830 path_selected = true;
831 np_set_best_match(path_select_list, mount_list, exact_match);
832 cflags = default_cflags;
833
834 break;
835 case 'M': /* display mountpoint */
836 display_mntp = true;
837 break;
838 case 'C':
839 /* add all mount entries to path_select list if no partitions have been explicitly defined using -p */
840 if (path_selected == false) {
841 struct parameter_list *path;
842 for (me = mount_list; me; me = me->me_next) {
843 if (! (path = np_find_parameter(path_select_list, me->me_mountdir)))
844 path = np_add_parameter(&path_select_list, me->me_mountdir);
845 path->best_match = me;
846 path->group = group;
847 set_all_thresholds(path);
848 }
849 }
850 warn_freespace_units = NULL;
851 crit_freespace_units = NULL;
852 warn_usedspace_units = NULL;
853 crit_usedspace_units = NULL;
854 warn_freespace_percent = NULL;
855 crit_freespace_percent = NULL;
856 warn_usedspace_percent = NULL;
857 crit_usedspace_percent = NULL;
858 warn_usedinodes_percent = NULL;
859 crit_usedinodes_percent = NULL;
860 warn_freeinodes_percent = NULL;
861 crit_freeinodes_percent = NULL;
862
863 path_selected = false;
864 group = NULL;
865 break;
866 case 'V': /* version */
867 print_revision (progname, NP_VERSION);
868 exit (STATE_UNKNOWN);
869 case 'h': /* help */
870 print_help ();
871 exit (STATE_UNKNOWN);
872 case '?': /* help */
873 usage (_("Unknown argument"));
874 }
875 }
876
877 /* Support for "check_disk warn crit [fs]" with thresholds at used% level */
878 c = optind;
879 if (warn_usedspace_percent == NULL && argc > c && is_intnonneg (argv[c]))
880 warn_usedspace_percent = argv[c++];
881
882 if (crit_usedspace_percent == NULL && argc > c && is_intnonneg (argv[c]))
883 crit_usedspace_percent = argv[c++];
884
885 if (argc > c) {
886 se = np_add_parameter(&path_select_list, strdup(argv[c++]));
887 path_selected = true;
888 set_all_thresholds(se);
889 }
890
891 if (units == NULL) {
892 units = strdup ("MiB");
893 mult = (uintmax_t)1024 * 1024;
894 }
895
896 return true;
897}
898 581
899void 582 case 'W': /* warning inode threshold */
900set_all_thresholds (struct parameter_list *path) 583 if (*optarg == '@') {
901{ 584 warn_freeinodes_percent = optarg;
902 if (path->freespace_units != NULL) free(path->freespace_units); 585 } else {
903 set_thresholds(&path->freespace_units, warn_freespace_units, crit_freespace_units); 586 xasprintf(&warn_freeinodes_percent, "@%s", optarg);
904 if (path->freespace_percent != NULL) free (path->freespace_percent); 587 }
905 set_thresholds(&path->freespace_percent, warn_freespace_percent, crit_freespace_percent); 588 break;
906 if (path->usedspace_units != NULL) free (path->usedspace_units); 589 case 'K': /* critical inode threshold */
907 set_thresholds(&path->usedspace_units, warn_usedspace_units, crit_usedspace_units); 590 if (*optarg == '@') {
908 if (path->usedspace_percent != NULL) free (path->usedspace_percent); 591 crit_freeinodes_percent = optarg;
909 set_thresholds(&path->usedspace_percent, warn_usedspace_percent, crit_usedspace_percent); 592 } else {
910 if (path->usedinodes_percent != NULL) free (path->usedinodes_percent); 593 xasprintf(&crit_freeinodes_percent, "@%s", optarg);
911 set_thresholds(&path->usedinodes_percent, warn_usedinodes_percent, crit_usedinodes_percent); 594 }
912 if (path->freeinodes_percent != NULL) free (path->freeinodes_percent); 595 break;
913 set_thresholds(&path->freeinodes_percent, warn_freeinodes_percent, crit_freeinodes_percent); 596 case 'u':
914} 597 if (units)
598 free(units);
599 if (!strcasecmp(optarg, "bytes")) {
600 mult = (uintmax_t)1;
601 units = strdup("B");
602 } else if (!strcmp(optarg, "KiB")) {
603 mult = (uintmax_t)1024;
604 units = strdup("KiB");
605 } else if (!strcmp(optarg, "kB")) {
606 mult = (uintmax_t)1000;
607 units = strdup("kB");
608 } else if (!strcmp(optarg, "MiB")) {
609 mult = (uintmax_t)1024 * 1024;
610 units = strdup("MiB");
611 } else if (!strcmp(optarg, "MB")) {
612 mult = (uintmax_t)1000 * 1000;
613 units = strdup("MB");
614 } else if (!strcmp(optarg, "GiB")) {
615 mult = (uintmax_t)1024 * 1024 * 1024;
616 units = strdup("GiB");
617 } else if (!strcmp(optarg, "GB")) {
618 mult = (uintmax_t)1000 * 1000 * 1000;
619 units = strdup("GB");
620 } else if (!strcmp(optarg, "TiB")) {
621 mult = (uintmax_t)1024 * 1024 * 1024 * 1024;
622 units = strdup("TiB");
623 } else if (!strcmp(optarg, "TB")) {
624 mult = (uintmax_t)1000 * 1000 * 1000 * 1000;
625 units = strdup("TB");
626 } else if (!strcmp(optarg, "PiB")) {
627 mult = (uintmax_t)1024 * 1024 * 1024 * 1024 * 1024;
628 units = strdup("PiB");
629 } else if (!strcmp(optarg, "PB")) {
630 mult = (uintmax_t)1000 * 1000 * 1000 * 1000 * 1000;
631 units = strdup("PB");
632 } else {
633 die(STATE_UNKNOWN, _("unit type %s not known\n"), optarg);
634 }
635 if (units == NULL)
636 die(STATE_UNKNOWN, _("failed allocating storage for '%s'\n"), "units");
637 break;
638 case 'k': /* display mountpoint */
639 mult = 1024;
640 if (units)
641 free(units);
642 units = strdup("kiB");
643 break;
644 case 'm': /* display mountpoint */
645 mult = 1024 * 1024;
646 if (units)
647 free(units);
648 units = strdup("MiB");
649 break;
650 case 'L':
651 stat_remote_fs = 1;
652 /* fallthrough */
653 case 'l':
654 show_local_fs = 1;
655 break;
656 case 'P':
657 display_inodes_perfdata = 1;
658 break;
659 case 'p': /* select path */
660 if (!(warn_freespace_units || crit_freespace_units || warn_freespace_percent || crit_freespace_percent ||
661 warn_usedspace_units || crit_usedspace_units || warn_usedspace_percent || crit_usedspace_percent ||
662 warn_usedinodes_percent || crit_usedinodes_percent || warn_freeinodes_percent || crit_freeinodes_percent)) {
663 die(STATE_UNKNOWN, "DISK %s: %s", _("UNKNOWN"), _("Must set a threshold value before using -p\n"));
664 }
915 665
916void 666 /* add parameter if not found. overwrite thresholds if path has already been added */
917print_help (void) 667 if (!(se = np_find_parameter(path_select_list, optarg))) {
918{ 668 se = np_add_parameter(&path_select_list, optarg);
919 print_revision (progname, NP_VERSION); 669
920 670 if (stat(optarg, &stat_buf[0]) && ignore_missing == true) {
921 printf ("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n"); 671 path_ignored = true;
922 printf (COPYRIGHT, copyright, email); 672 break;
923 673 }
924 printf ("%s\n", _("This plugin checks the amount of used disk space on a mounted file system")); 674 }
925 printf ("%s\n", _("and generates an alert if free space is less than one of the threshold values")); 675 se->group = group;
926 676 set_all_thresholds(se);
927 printf ("\n\n"); 677
928 678 /* With autofs, it is required to stat() the path before re-populating the mount_list */
929 print_usage (); 679 if (!stat_path(se)) {
930 680 break;
931 printf (UT_HELP_VRSN); 681 }
932 printf (UT_EXTRA_OPTS); 682 /* NB: We can't free the old mount_list "just like that": both list pointers and struct
933 683 * pointers are copied around. One of the reason it wasn't done yet is that other parts
934 printf (" %s\n", "-w, --warning=INTEGER"); 684 * of check_disk need the same kind of cleanup so it'd better be done as a whole */
935 printf (" %s\n", _("Exit with WARNING status if less than INTEGER units of disk are free")); 685 mount_list = read_file_system_list(0);
936 printf (" %s\n", "-w, --warning=PERCENT%"); 686 np_set_best_match(se, mount_list, exact_match);
937 printf (" %s\n", _("Exit with WARNING status if less than PERCENT of disk space is free")); 687
938 printf (" %s\n", "-c, --critical=INTEGER"); 688 path_selected = true;
939 printf (" %s\n", _("Exit with CRITICAL status if less than INTEGER units of disk are free")); 689 break;
940 printf (" %s\n", "-c, --critical=PERCENT%"); 690 case 'x': /* exclude path or partition */
941 printf (" %s\n", _("Exit with CRITICAL status if less than PERCENT of disk space is free")); 691 np_add_name(&dp_exclude_list, optarg);
942 printf (" %s\n", "-W, --iwarning=PERCENT%"); 692 break;
943 printf (" %s\n", _("Exit with WARNING status if less than PERCENT of inode space is free")); 693 case 'X': /* exclude file system type */
944 printf (" %s\n", "-K, --icritical=PERCENT%"); 694 err = np_add_regex(&fs_exclude_list, optarg, REG_EXTENDED);
945 printf (" %s\n", _("Exit with CRITICAL status if less than PERCENT of inode space is free")); 695 if (err != 0) {
946 printf (" %s\n", "-p, --path=PATH, --partition=PARTITION"); 696 regerror(err, &fs_exclude_list->regex, errbuf, MAX_INPUT_BUFFER);
947 printf (" %s\n", _("Mount point or block device as emitted by the mount(8) command (may be repeated)")); 697 die(STATE_UNKNOWN, "DISK %s: %s - %s\n", _("UNKNOWN"), _("Could not compile regular expression"), errbuf);
948 printf (" %s\n", "-x, --exclude_device=PATH <STRING>"); 698 }
949 printf (" %s\n", _("Ignore device (only works if -p unspecified)")); 699 break;
950 printf (" %s\n", "-C, --clear"); 700 case 'N': /* include file system type */
951 printf (" %s\n", _("Clear thresholds")); 701 err = np_add_regex(&fs_include_list, optarg, REG_EXTENDED);
952 printf (" %s\n", "-E, --exact-match"); 702 if (err != 0) {
953 printf (" %s\n", _("For paths or partitions specified with -p, only check for exact paths")); 703 regerror(err, &fs_exclude_list->regex, errbuf, MAX_INPUT_BUFFER);
954 printf (" %s\n", "-e, --errors-only"); 704 die(STATE_UNKNOWN, "DISK %s: %s - %s\n", _("UNKNOWN"), _("Could not compile regular expression"), errbuf);
955 printf (" %s\n", _("Display only devices/mountpoints with errors")); 705 }
956 printf (" %s\n", "-f, --freespace-ignore-reserved"); 706 break;
957 printf (" %s\n", _("Don't account root-reserved blocks into freespace in perfdata")); 707 case 'v': /* verbose */
958 printf (" %s\n", "-P, --iperfdata"); 708 verbose++;
959 printf (" %s\n", _("Display inode usage in perfdata")); 709 break;
960 printf (" %s\n", "-g, --group=NAME"); 710 case 'q': /* TODO: this function should eventually go away (removed 2007-09-20) */
961 printf (" %s\n", _("Group paths. Thresholds apply to (free-)space of all partitions together")); 711 /* verbose--; **replaced by line below**. -q was only a broken way of implementing -e */
962 printf (" %s\n", "-k, --kilobytes"); 712 erronly = true;
963 printf (" %s\n", _("Same as '--units kB'")); 713 break;
964 printf (" %s\n", "-l, --local"); 714 case 'e':
965 printf (" %s\n", _("Only check local filesystems")); 715 erronly = true;
966 printf (" %s\n", "-L, --stat-remote-fs"); 716 break;
967 printf (" %s\n", _("Only check local filesystems against thresholds. Yet call stat on remote filesystems")); 717 case 'E':
968 printf (" %s\n", _("to test if they are accessible (e.g. to detect Stale NFS Handles)")); 718 if (path_selected)
969 printf (" %s\n", "-M, --mountpoint"); 719 die(STATE_UNKNOWN, "DISK %s: %s", _("UNKNOWN"), _("Must set -E before selecting paths\n"));
970 printf (" %s\n", _("Display the (block) device instead of the mount point")); 720 exact_match = true;
971 printf (" %s\n", "-m, --megabytes"); 721 break;
972 printf (" %s\n", _("Same as '--units MB'")); 722 case 'f':
973 printf (" %s\n", "-A, --all"); 723 freespace_ignore_reserved = true;
974 printf (" %s\n", _("Explicitly select all paths. This is equivalent to -R '.*'")); 724 break;
975 printf (" %s\n", "-R, --eregi-path=PATH, --eregi-partition=PARTITION"); 725 case 'g':
976 printf (" %s\n", _("Case insensitive regular expression for path/partition (may be repeated)")); 726 if (path_selected)
977 printf (" %s\n", "-r, --ereg-path=PATH, --ereg-partition=PARTITION"); 727 die(STATE_UNKNOWN, "DISK %s: %s", _("UNKNOWN"), _("Must set group value before selecting paths\n"));
978 printf (" %s\n", _("Regular expression for path or partition (may be repeated)")); 728 group = optarg;
979 printf (" %s\n", "-I, --ignore-eregi-path=PATH, --ignore-eregi-partition=PARTITION"); 729 break;
980 printf (" %s\n", _("Regular expression to ignore selected path/partition (case insensitive) (may be repeated)")); 730 case 'I':
981 printf (" %s\n", "-i, --ignore-ereg-path=PATH, --ignore-ereg-partition=PARTITION"); 731 cflags |= REG_ICASE;
982 printf (" %s\n", _("Regular expression to ignore selected path or partition (may be repeated)")); 732 // Intentional fallthrough
983 printf (" %s\n", "-n, --ignore-missing"); 733 case 'i':
984 printf (" %s\n", _("Return OK if no filesystem matches, filesystem does not exist or is inaccessible.")); 734 if (!path_selected)
985 printf (" %s\n", _("(Provide this option before -p / -r / --ereg-path if used)")); 735 die(STATE_UNKNOWN, "DISK %s: %s\n", _("UNKNOWN"),
986 printf (UT_PLUG_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); 736 _("Paths need to be selected before using -i/-I. Use -A to select all paths explicitly"));
987 printf (" %s\n", "-u, --units=STRING"); 737 err = regcomp(&re, optarg, cflags);
988 printf (" %s\n", _("Choose bytes, kB, MB, GB, TB (default: MB)")); 738 if (err != 0) {
989 printf (UT_VERBOSE); 739 regerror(err, &re, errbuf, MAX_INPUT_BUFFER);
990 printf (" %s\n", "-X, --exclude-type=TYPE_REGEX"); 740 die(STATE_UNKNOWN, "DISK %s: %s - %s\n", _("UNKNOWN"), _("Could not compile regular expression"), errbuf);
991 printf (" %s\n", _("Ignore all filesystems of types matching given regex(7) (may be repeated)")); 741 }
992 printf (" %s\n", "-N, --include-type=TYPE_REGEX"); 742
993 printf (" %s\n", _("Check only filesystems where the type matches this given regex(7) (may be repeated)")); 743 temp_list = path_select_list;
994 744
995 printf ("\n"); 745 previous = NULL;
996 printf ("%s\n", _("General usage hints:")); 746 while (temp_list) {
997 printf (" %s\n", _("- Arguments are positional! \"-w 5 -c 1 -p /foo -w6 -c2 -p /bar\" is not the same as")); 747 if (temp_list->best_match) {
998 printf (" %s\n", _("\"-w 5 -c 1 -p /bar w6 -c2 -p /foo\".")); 748 if (np_regex_match_mount_entry(temp_list->best_match, &re)) {
999 printf (" %s\n", _("- The syntax is broadly: \"{thresholds a} {paths a} -C {thresholds b} {thresholds b} ...\"")); 749
1000 750 if (verbose >= 3)
1001 751 printf("ignoring %s matching regex\n", temp_list->name);
1002 752
1003 printf ("\n"); 753 temp_list = np_del_parameter(temp_list, previous);
1004 printf ("%s\n", _("Examples:")); 754 /* pointer to first element needs to be updated if first item gets deleted */
1005 printf (" %s\n", "check_disk -w 10% -c 5% -p /tmp -p /var -C -w 100000 -c 50000 -p /"); 755 if (previous == NULL)
1006 printf (" %s\n\n", _("Checks /tmp and /var at 10% and 5%, and / at 100MB and 50MB")); 756 path_select_list = temp_list;
1007 printf (" %s\n", "check_disk -w 100 -c 50 -C -w 1000 -c 500 -g sidDATA -r '^/oracle/SID/data.*$'"); 757 } else {
1008 printf (" %s\n", _("Checks all filesystems not matching -r at 100M and 50M. The fs matching the -r regex")); 758 previous = temp_list;
1009 printf (" %s\n\n", _("are grouped which means the freespace thresholds are applied to all disks together")); 759 temp_list = temp_list->name_next;
1010 printf (" %s\n", "check_disk -w 100 -c 50 -C -w 1000 -c 500 -p /foo -C -w 5% -c 3% -p /bar"); 760 }
1011 printf (" %s\n", _("Checks /foo for 1000M/500M and /bar for 5/3%. All remaining volumes use 100M/50M")); 761 } else {
1012 762 previous = temp_list;
1013 printf (UT_SUPPORT); 763 temp_list = temp_list->name_next;
1014} 764 }
765 }
1015 766
767 cflags = default_cflags;
768 break;
769
770 case 'n':
771 ignore_missing = true;
772 break;
773 case 'A':
774 optarg = strdup(".*");
775 // Intentional fallthrough
776 case 'R':
777 cflags |= REG_ICASE;
778 // Intentional fallthrough
779 case 'r':
780 if (!(warn_freespace_units || crit_freespace_units || warn_freespace_percent || crit_freespace_percent ||
781 warn_usedspace_units || crit_usedspace_units || warn_usedspace_percent || crit_usedspace_percent ||
782 warn_usedinodes_percent || crit_usedinodes_percent || warn_freeinodes_percent || crit_freeinodes_percent)) {
783 die(STATE_UNKNOWN, "DISK %s: %s", _("UNKNOWN"),
784 _("Must set a threshold value before using -r/-R/-A (--ereg-path/--eregi-path/--all)\n"));
785 }
1016 786
787 err = regcomp(&re, optarg, cflags);
788 if (err != 0) {
789 regerror(err, &re, errbuf, MAX_INPUT_BUFFER);
790 die(STATE_UNKNOWN, "DISK %s: %s - %s\n", _("UNKNOWN"), _("Could not compile regular expression"), errbuf);
791 }
792
793 for (me = mount_list; me; me = me->me_next) {
794 if (np_regex_match_mount_entry(me, &re)) {
795 fnd = true;
796 if (verbose >= 3)
797 printf("%s %s matching expression %s\n", me->me_devname, me->me_mountdir, optarg);
798
799 /* add parameter if not found. overwrite thresholds if path has already been added */
800 if (!(se = np_find_parameter(path_select_list, me->me_mountdir))) {
801 se = np_add_parameter(&path_select_list, me->me_mountdir);
802 }
803 se->group = group;
804 set_all_thresholds(se);
805 }
806 }
1017 807
1018void 808 if (!fnd && ignore_missing == true) {
1019print_usage (void) 809 path_ignored = true;
1020{ 810 path_selected = true;
1021 printf ("%s\n", _("Usage:")); 811 break;
1022 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); 812 }
1023 printf ("[-C] [-E] [-e] [-f] [-g group ] [-k] [-l] [-M] [-m] [-R path ] [-r path ]\n"); 813 if (!fnd)
1024 printf ("[-t timeout] [-u unit] [-v] [-X type_regex] [-N type]\n"); 814 die(STATE_UNKNOWN, "DISK %s: %s - %s\n", _("UNKNOWN"), _("Regular expression did not match any path or disk"), optarg);
815
816 fnd = false;
817 path_selected = true;
818 np_set_best_match(path_select_list, mount_list, exact_match);
819 cflags = default_cflags;
820
821 break;
822 case 'M': /* display mountpoint */
823 display_mntp = true;
824 break;
825 case 'C':
826 /* add all mount entries to path_select list if no partitions have been explicitly defined using -p */
827 if (path_selected == false) {
828 struct parameter_list *path;
829 for (me = mount_list; me; me = me->me_next) {
830 if (!(path = np_find_parameter(path_select_list, me->me_mountdir)))
831 path = np_add_parameter(&path_select_list, me->me_mountdir);
832 path->best_match = me;
833 path->group = group;
834 set_all_thresholds(path);
835 }
836 }
837 warn_freespace_units = NULL;
838 crit_freespace_units = NULL;
839 warn_usedspace_units = NULL;
840 crit_usedspace_units = NULL;
841 warn_freespace_percent = NULL;
842 crit_freespace_percent = NULL;
843 warn_usedspace_percent = NULL;
844 crit_usedspace_percent = NULL;
845 warn_usedinodes_percent = NULL;
846 crit_usedinodes_percent = NULL;
847 warn_freeinodes_percent = NULL;
848 crit_freeinodes_percent = NULL;
849
850 path_selected = false;
851 group = NULL;
852 break;
853 case 'V': /* version */
854 print_revision(progname, NP_VERSION);
855 exit(STATE_UNKNOWN);
856 case 'h': /* help */
857 print_help();
858 exit(STATE_UNKNOWN);
859 case '?': /* help */
860 usage(_("Unknown argument"));
861 }
862 }
863
864 /* Support for "check_disk warn crit [fs]" with thresholds at used% level */
865 c = optind;
866 if (warn_usedspace_percent == NULL && argc > c && is_intnonneg(argv[c]))
867 warn_usedspace_percent = argv[c++];
868
869 if (crit_usedspace_percent == NULL && argc > c && is_intnonneg(argv[c]))
870 crit_usedspace_percent = argv[c++];
871
872 if (argc > c) {
873 se = np_add_parameter(&path_select_list, strdup(argv[c++]));
874 path_selected = true;
875 set_all_thresholds(se);
876 }
877
878 if (units == NULL) {
879 units = strdup("MiB");
880 mult = (uintmax_t)1024 * 1024;
881 }
882
883 return true;
1025} 884}
1026 885
1027bool 886void set_all_thresholds(struct parameter_list *path) {
1028stat_path (struct parameter_list *p) 887 if (path->freespace_units != NULL)
1029{ 888 free(path->freespace_units);
1030 /* Stat entry to check that dir exists and is accessible */ 889 set_thresholds(&path->freespace_units, warn_freespace_units, crit_freespace_units);
1031 if (verbose >= 3) 890 if (path->freespace_percent != NULL)
1032 printf("calling stat on %s\n", p->name); 891 free(path->freespace_percent);
1033 if (stat (p->name, &stat_buf[0])) { 892 set_thresholds(&path->freespace_percent, warn_freespace_percent, crit_freespace_percent);
1034 if (verbose >= 3) 893 if (path->usedspace_units != NULL)
1035 printf("stat failed on %s\n", p->name); 894 free(path->usedspace_units);
1036 if (ignore_missing == true) { 895 set_thresholds(&path->usedspace_units, warn_usedspace_units, crit_usedspace_units);
1037 return false; 896 if (path->usedspace_percent != NULL)
1038 } else { 897 free(path->usedspace_percent);
1039 printf("DISK %s - ", _("CRITICAL")); 898 set_thresholds(&path->usedspace_percent, warn_usedspace_percent, crit_usedspace_percent);
1040 die (STATE_CRITICAL, _("%s %s: %s\n"), p->name, _("is not accessible"), strerror(errno)); 899 if (path->usedinodes_percent != NULL)
1041 } 900 free(path->usedinodes_percent);
1042 } 901 set_thresholds(&path->usedinodes_percent, warn_usedinodes_percent, crit_usedinodes_percent);
1043 return true; 902 if (path->freeinodes_percent != NULL)
903 free(path->freeinodes_percent);
904 set_thresholds(&path->freeinodes_percent, warn_freeinodes_percent, crit_freeinodes_percent);
1044} 905}
1045 906
907void print_help(void) {
908 print_revision(progname, NP_VERSION);
909
910 printf("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n");
911 printf(COPYRIGHT, copyright, email);
912
913 printf("%s\n", _("This plugin checks the amount of used disk space on a mounted file system"));
914 printf("%s\n", _("and generates an alert if free space is less than one of the threshold values"));
915
916 printf("\n\n");
917
918 print_usage();
919
920 printf(UT_HELP_VRSN);
921 printf(UT_EXTRA_OPTS);
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);
1001}
1046 1002
1047void 1003void print_usage(void) {
1048get_stats (struct parameter_list *p, struct fs_usage *fsp) { 1004 printf("%s\n", _("Usage:"));
1049 struct parameter_list *p_list; 1005 printf(" %s {-w absolute_limit |-w percentage_limit%% | -W inode_percentage_limit } {-c absolute_limit|-c percentage_limit%% | -K "
1050 struct fs_usage tmpfsp; 1006 "inode_percentage_limit } {-p path | -x device}\n",
1051 int first = 1; 1007 progname);
1008 printf("[-C] [-E] [-e] [-f] [-g group ] [-k] [-l] [-M] [-m] [-R path ] [-r path ]\n");
1009 printf("[-t timeout] [-u unit] [-v] [-X type_regex] [-N type]\n");
1010}
1052 1011
1053 if (p->group == NULL) { 1012bool stat_path(struct parameter_list *p) {
1054 get_path_stats(p,fsp); 1013 /* Stat entry to check that dir exists and is accessible */
1055 } else { 1014 if (verbose >= 3)
1056 /* find all group members */ 1015 printf("calling stat on %s\n", p->name);
1057 for (p_list = path_select_list; p_list; p_list=p_list->name_next) { 1016 if (stat(p->name, &stat_buf[0])) {
1017 if (verbose >= 3)
1018 printf("stat failed on %s\n", p->name);
1019 if (ignore_missing == true) {
1020 return false;
1021 }
1022 printf("DISK %s - ", _("CRITICAL"));
1023 die(STATE_CRITICAL, _("%s %s: %s\n"), p->name, _("is not accessible"), strerror(errno));
1024 }
1025 return true;
1026}
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;
1032
1033 if (p->group == NULL) {
1034 get_path_stats(p, fsp);
1035 } else {
1036 /* find all group members */
1037 for (p_list = path_select_list; p_list; p_list = p_list->name_next) {
1058#ifdef __CYGWIN__ 1038#ifdef __CYGWIN__
1059 if (strncmp(p_list->name, "/cygdrive/", 10) != 0) 1039 if (strncmp(p_list->name, "/cygdrive/", 10) != 0)
1060 continue; 1040 continue;
1061#endif 1041#endif
1062 if (p_list->group && ! (strcmp(p_list->group, p->group))) { 1042 if (p_list->group && !(strcmp(p_list->group, p->group))) {
1063 if (! stat_path(p_list)) 1043 if (!stat_path(p_list))
1064 continue; 1044 continue;
1065 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);
1066 get_path_stats(p_list, &tmpfsp); 1046 get_path_stats(p_list, &tmpfsp);
1067 if (verbose >= 3) 1047 if (verbose >= 3)
1068 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",
1069 p_list->group, 1049 p_list->group, tmpfsp.fsu_blocks, tmpfsp.fsu_blocksize, p_list->best_match->me_mountdir, p_list->dused_units,
1070 tmpfsp.fsu_blocks, 1050 p_list->dfree_units, p_list->dtotal_units, mult);
1071 tmpfsp.fsu_blocksize, 1051
1072 p_list->best_match->me_mountdir, 1052 /* prevent counting the first FS of a group twice since its parameter_list entry
1073 p_list->dused_units, 1053 * is used to carry the information of all file systems of the entire group */
1074 p_list->dfree_units, 1054 if (!first) {
1075 p_list->dtotal_units, 1055 p->total += p_list->total;
1076 mult); 1056 p->available += p_list->available;
1077 1057 p->available_to_root += p_list->available_to_root;
1078 /* prevent counting the first FS of a group twice since its parameter_list entry 1058 p->used += p_list->used;
1079 * is used to carry the information of all file systems of the entire group */ 1059
1080 if (! first) { 1060 p->dused_units += p_list->dused_units;
1081 p->total += p_list->total; 1061 p->dfree_units += p_list->dfree_units;
1082 p->available += p_list->available; 1062 p->dtotal_units += p_list->dtotal_units;
1083 p->available_to_root += p_list->available_to_root; 1063 p->inodes_total += p_list->inodes_total;
1084 p->used += p_list->used; 1064 p->inodes_free += p_list->inodes_free;
1085 1065 p->inodes_free_to_root += p_list->inodes_free_to_root;
1086 p->dused_units += p_list->dused_units; 1066 p->inodes_used += p_list->inodes_used;
1087 p->dfree_units += p_list->dfree_units; 1067 }
1088 p->dtotal_units += p_list->dtotal_units; 1068 first = 0;
1089 p->inodes_total += p_list->inodes_total; 1069 }
1090 p->inodes_free += p_list->inodes_free; 1070 if (verbose >= 3)
1091 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,
1092 p->inodes_used += p_list->inodes_used; 1072 p->dused_units, p->dfree_units, p->dtotal_units, tmpfsp.fsu_blocksize, mult);
1093 } 1073 }
1094 first = 0; 1074 /* modify devname and mountdir for output */
1095 } 1075 p->best_match->me_mountdir = p->best_match->me_devname = p->group;
1096 if (verbose >= 3) 1076 }
1097 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 */
1098 p->group, 1078 p->dused_pct = calculate_percent(p->used, p->used + p->available); /* used + available can never be > uintmax */
1099 p->dused_units, 1079 p->dfree_pct = 100.0 - p->dused_pct;
1100 p->dfree_units, 1080 p->dused_inodes_percent = calculate_percent(p->inodes_total - p->inodes_free, p->inodes_total);
1101 p->dtotal_units, 1081 p->dfree_inodes_percent = 100 - p->dused_inodes_percent;
1102 tmpfsp.fsu_blocksize,
1103 mult);
1104 }
1105 /* modify devname and mountdir for output */
1106 p->best_match->me_mountdir = p->best_match->me_devname = p->group;
1107 }
1108 /* finally calculate percentages for either plain FS or summed up group */
1109 p->dused_pct = calculate_percent( p->used, p->used + p->available ); /* used + available can never be > uintmax */
1110 p->dfree_pct = 100.0 - p->dused_pct;
1111 p->dused_inodes_percent = calculate_percent(p->inodes_total - p->inodes_free, p->inodes_total);
1112 p->dfree_inodes_percent = 100 - p->dused_inodes_percent;
1113
1114} 1082}
1115 1083
1116void 1084void get_path_stats(struct parameter_list *p, struct fs_usage *fsp) {
1117get_path_stats (struct parameter_list *p, struct fs_usage *fsp) { 1085 p->available = fsp->fsu_bavail;
1118 p->available = fsp->fsu_bavail; 1086 p->available_to_root = fsp->fsu_bfree;
1119 p->available_to_root = fsp->fsu_bfree; 1087 p->used = fsp->fsu_blocks - fsp->fsu_bfree;
1120 p->used = fsp->fsu_blocks - fsp->fsu_bfree; 1088 if (freespace_ignore_reserved) {
1121 if (freespace_ignore_reserved) { 1089 /* option activated : we subtract the root-reserved space from the total */
1122 /* option activated : we subtract the root-reserved space from the total */ 1090 p->total = fsp->fsu_blocks - p->available_to_root + p->available;
1123 p->total = fsp->fsu_blocks - p->available_to_root + p->available; 1091 } else {
1124 } else { 1092 /* default behaviour : take all the blocks into account */
1125 /* default behaviour : take all the blocks into account */ 1093 p->total = fsp->fsu_blocks;
1126 p->total = fsp->fsu_blocks; 1094 }
1127 } 1095
1128 1096 p->dused_units = p->used * fsp->fsu_blocksize / mult;
1129 p->dused_units = p->used*fsp->fsu_blocksize/mult; 1097 p->dfree_units = p->available * fsp->fsu_blocksize / mult;
1130 p->dfree_units = p->available*fsp->fsu_blocksize/mult; 1098 p->dtotal_units = p->total * fsp->fsu_blocksize / mult;
1131 p->dtotal_units = p->total*fsp->fsu_blocksize/mult; 1099 /* Free file nodes. Not sure the workaround is required, but in case...*/
1132 /* Free file nodes. Not sure the workaround is required, but in case...*/ 1100 p->inodes_free = fsp->fsu_ffree;
1133 p->inodes_free = fsp->fsu_ffree; 1101 p->inodes_free_to_root = fsp->fsu_ffree; /* Free file nodes for root. */
1134 p->inodes_free_to_root = fsp->fsu_ffree; /* Free file nodes for root. */ 1102 p->inodes_used = fsp->fsu_files - fsp->fsu_ffree;
1135 p->inodes_used = fsp->fsu_files - fsp->fsu_ffree; 1103 if (freespace_ignore_reserved) {
1136 if (freespace_ignore_reserved) { 1104 /* option activated : we subtract the root-reserved inodes from the total */
1137 /* 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 */
1138 /* not all OS report fsp->fsu_favail, only the ones with statvfs syscall */ 1106 /* for others, fsp->fsu_ffree == fsp->fsu_favail */
1139 /* for others, fsp->fsu_ffree == fsp->fsu_favail */ 1107 p->inodes_total = fsp->fsu_files - p->inodes_free_to_root + p->inodes_free;
1140 p->inodes_total = fsp->fsu_files - p->inodes_free_to_root + p->inodes_free; 1108 } else {
1141 } else { 1109 /* default behaviour : take all the inodes into account */
1142 /* default behaviour : take all the inodes into account */ 1110 p->inodes_total = fsp->fsu_files;
1143 p->inodes_total = fsp->fsu_files; 1111 }
1144 } 1112 np_add_name(&seen, p->best_match->me_mountdir);
1145 np_add_name(&seen, p->best_match->me_mountdir);
1146} 1113}
diff --git a/plugins/check_dns.c b/plugins/check_dns.c
index 468bc95..e1e7c00 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 212a134..19f6c04 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 70d6f9f..49235e2 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 ca12697..619277e 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 c34bb08..b39bccf 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 cdf768c..97c0e39 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
diff --git a/plugins/check_ide_smart.c b/plugins/check_ide_smart.c
index 3872e34..381dbd8 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 868ffc1..1c72829 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_mrtg.c b/plugins/check_mrtg.c
index 826b77e..632e66f 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 bd25d47..e5a2e2a 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 15ec04c..1f0b709 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
diff --git a/plugins/check_mysql_query.c b/plugins/check_mysql_query.c
index 842b7a2..79b6e2f 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 40d68f0..48629be 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 19c050d..413aad6 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 61b2d69..55a4946 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 464a9e1..f99e503 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 b2e1655..703b69d 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 10c493b..3af6360 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,10 +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 VPU, /* check % used space on volume */ 49 VPU, /* check % used space on volume */
50 VMP, /* check MB purgeable space on volume */ 50 VMP, /* check MB purgeable space on volume */
51 VKF, /* check KB free space on volume */ 51 VKF, /* check KB free space on volume */
52 LTCH, /* check long-term cache hit percentage */ 52 LTCH, /* check long-term cache hit percentage */
53 CBUFF, /* check total cache buffers */ 53 CBUFF, /* check total cache buffers */
@@ -55,7 +55,7 @@ enum checkvar {
55 LRUM, /* check LRU sitting time in minutes */ 55 LRUM, /* check LRU sitting time in minutes */
56 DSDB, /* check to see if DS Database is open */ 56 DSDB, /* check to see if DS Database is open */
57 LOGINS, /* check to see if logins are enabled */ 57 LOGINS, /* check to see if logins are enabled */
58 NRMH, /* check to see NRM Health Status */ 58 NRMH, /* check to see NRM Health Status */
59 PUPRB, /* check % of used packet receive buffers */ 59 PUPRB, /* check % of used packet receive buffers */
60 UPRB, /* check used packet receive buffers */ 60 UPRB, /* check used packet receive buffers */
61 SAPENTRIES, /* check SAP entries */ 61 SAPENTRIES, /* check SAP entries */
@@ -73,8 +73,8 @@ enum checkvar {
73 DSVER, /* check NDS version */ 73 DSVER, /* check NDS version */
74 UPTIME, /* check server uptime */ 74 UPTIME, /* check server uptime */
75 NLM, /* check NLM loaded */ 75 NLM, /* check NLM loaded */
76 NRMP, /* check NRM Process Values */ 76 NRMP, /* check NRM Process Values */
77 NRMM, /* check NRM Memory Values */ 77 NRMM, /* check NRM Memory Values */
78 NRMS, /* check NRM Values */ 78 NRMS, /* check NRM Values */
79 NSS1, /* check Statistics from _Admin:Manage_NSS\GeneralStats.xml */ 79 NSS1, /* check Statistics from _Admin:Manage_NSS\GeneralStats.xml */
80 NSS2, /* check Statistics from _Admin:Manage_NSS\BufferCache.xml */ 80 NSS2, /* check Statistics from _Admin:Manage_NSS\BufferCache.xml */
@@ -89,1652 +89,1439 @@ enum {
89 PORT = 9999 89 PORT = 9999
90}; 90};
91 91
92char *server_address=NULL; 92char *server_address = NULL;
93char *volume_name=NULL; 93char *volume_name = NULL;
94char *nlm_name=NULL; 94char *nlm_name = NULL;
95char *nrmp_name=NULL; 95char *nrmp_name = NULL;
96char *nrmm_name=NULL; 96char *nrmm_name = NULL;
97char *nrms_name=NULL; 97char *nrms_name = NULL;
98char *nss1_name=NULL; 98char *nss1_name = NULL;
99char *nss2_name=NULL; 99char *nss2_name = NULL;
100char *nss3_name=NULL; 100char *nss3_name = NULL;
101char *nss4_name=NULL; 101char *nss4_name = NULL;
102char *nss5_name=NULL; 102char *nss5_name = NULL;
103char *nss6_name=NULL; 103char *nss6_name = NULL;
104char *nss7_name=NULL; 104char *nss7_name = NULL;
105int server_port=PORT; 105int server_port = PORT;
106unsigned long warning_value=0L; 106unsigned long warning_value = 0L;
107unsigned long critical_value=0L; 107unsigned long critical_value = 0L;
108bool check_warning_value = false; 108bool check_warning_value = false;
109bool check_critical_value = false; 109bool check_critical_value = false;
110bool check_netware_version = false; 110bool check_netware_version = false;
111enum checkvar vars_to_check = NONE; 111enum checkvar vars_to_check = NONE;
112int sap_number=-1; 112int sap_number = -1;
113 113
114int process_arguments(int, char **); 114int process_arguments(int, char **);
115void print_help(void); 115void print_help(void);
116void print_usage(void); 116void print_usage(void);
117 117
118 118int main(int argc, char **argv) {
119
120int
121main(int argc, char **argv) {
122 int result = STATE_UNKNOWN; 119 int result = STATE_UNKNOWN;
123 int sd; 120 int sd;
124 char *send_buffer=NULL; 121 char *send_buffer = NULL;
125 char recv_buffer[MAX_INPUT_BUFFER]; 122 char recv_buffer[MAX_INPUT_BUFFER];
126 char *output_message=NULL; 123 char *output_message = NULL;
127 char *temp_buffer=NULL; 124 char *temp_buffer = NULL;
128 char *netware_version=NULL; 125 char *netware_version = NULL;
129 126
130 int time_sync_status=0; 127 int time_sync_status = 0;
131 int nrm_health_status=0; 128 int nrm_health_status = 0;
132 unsigned long total_cache_buffers=0; 129 unsigned long total_cache_buffers = 0;
133 unsigned long dirty_cache_buffers=0; 130 unsigned long dirty_cache_buffers = 0;
134 unsigned long open_files=0; 131 unsigned long open_files = 0;
135 unsigned long abended_threads=0; 132 unsigned long abended_threads = 0;
136 unsigned long max_service_processes=0; 133 unsigned long max_service_processes = 0;
137 unsigned long current_service_processes=0; 134 unsigned long current_service_processes = 0;
138 unsigned long free_disk_space=0L; 135 unsigned long free_disk_space = 0L;
139 unsigned long nrmp_value=0L; 136 unsigned long nrmp_value = 0L;
140 unsigned long nrmm_value=0L; 137 unsigned long nrmm_value = 0L;
141 unsigned long nrms_value=0L; 138 unsigned long nrms_value = 0L;
142 unsigned long nss1_value=0L; 139 unsigned long nss1_value = 0L;
143 unsigned long nss2_value=0L; 140 unsigned long nss2_value = 0L;
144 unsigned long nss3_value=0L; 141 unsigned long nss3_value = 0L;
145 unsigned long nss4_value=0L; 142 unsigned long nss4_value = 0L;
146 unsigned long nss5_value=0L; 143 unsigned long nss5_value = 0L;
147 unsigned long nss6_value=0L; 144 unsigned long nss6_value = 0L;
148 unsigned long nss7_value=0L; 145 unsigned long nss7_value = 0L;
149 unsigned long total_disk_space=0L; 146 unsigned long total_disk_space = 0L;
150 unsigned long used_disk_space=0L; 147 unsigned long used_disk_space = 0L;
151 unsigned long percent_used_disk_space=0L; 148 unsigned long percent_used_disk_space = 0L;
152 unsigned long purgeable_disk_space=0L; 149 unsigned long purgeable_disk_space = 0L;
153 unsigned long non_purgeable_disk_space=0L; 150 unsigned long non_purgeable_disk_space = 0L;
154 unsigned long percent_free_space=0; 151 unsigned long percent_free_space = 0;
155 unsigned long percent_purgeable_space=0; 152 unsigned long percent_purgeable_space = 0;
156 unsigned long percent_non_purgeable_space=0; 153 unsigned long percent_non_purgeable_space = 0;
157 unsigned long current_connections=0L; 154 unsigned long current_connections = 0L;
158 unsigned long utilization=0L; 155 unsigned long utilization = 0L;
159 unsigned long cache_hits=0; 156 unsigned long cache_hits = 0;
160 unsigned long cache_buffers=0L; 157 unsigned long cache_buffers = 0L;
161 unsigned long lru_time=0L; 158 unsigned long lru_time = 0L;
162 unsigned long max_packet_receive_buffers=0; 159 unsigned long max_packet_receive_buffers = 0;
163 unsigned long used_packet_receive_buffers=0; 160 unsigned long used_packet_receive_buffers = 0;
164 unsigned long percent_used_packet_receive_buffers=0L; 161 unsigned long percent_used_packet_receive_buffers = 0L;
165 unsigned long sap_entries=0; 162 unsigned long sap_entries = 0;
166 char uptime[MAX_INPUT_BUFFER]; 163 char uptime[MAX_INPUT_BUFFER];
167 164
168 setlocale (LC_ALL, ""); 165 setlocale(LC_ALL, "");
169 bindtextdomain (PACKAGE, LOCALEDIR); 166 bindtextdomain(PACKAGE, LOCALEDIR);
170 textdomain (PACKAGE); 167 textdomain(PACKAGE);
171 168
172 /* Parse extra opts if any */ 169 /* Parse extra opts if any */
173 argv=np_extra_opts(&argc, argv, progname); 170 argv = np_extra_opts(&argc, argv, progname);
174 171
175 if (process_arguments(argc,argv) == ERROR) 172 if (process_arguments(argc, argv) == ERROR)
176 usage4 (_("Could not parse arguments")); 173 usage4(_("Could not parse arguments"));
177 174
178 /* initialize alarm signal handling */ 175 /* initialize alarm signal handling */
179 signal(SIGALRM,socket_timeout_alarm_handler); 176 signal(SIGALRM, socket_timeout_alarm_handler);
180 177
181 /* set socket timeout */ 178 /* set socket timeout */
182 alarm(socket_timeout); 179 alarm(socket_timeout);
183 180
184 /* open connection */ 181 /* open connection */
185 my_tcp_connect (server_address, server_port, &sd); 182 my_tcp_connect(server_address, server_port, &sd);
186 183
187 /* get OS version string */ 184 /* get OS version string */
188 if (check_netware_version) { 185 if (check_netware_version) {
189 send_buffer = strdup ("S19\r\n"); 186 send_buffer = strdup("S19\r\n");
190 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));
191 if (result!=STATE_OK) 188 if (result != STATE_OK)
192 return result; 189 return result;
193 if (!strcmp(recv_buffer,"-1\n")) 190 if (!strcmp(recv_buffer, "-1\n"))
194 netware_version = strdup(""); 191 netware_version = strdup("");
195 else { 192 else {
196 recv_buffer[strlen(recv_buffer)-1]=0; 193 recv_buffer[strlen(recv_buffer) - 1] = 0;
197 xasprintf (&netware_version,_("NetWare %s: "),recv_buffer); 194 xasprintf(&netware_version, _("NetWare %s: "), recv_buffer);
198 } 195 }
199 } else 196 } else
200 netware_version = strdup(""); 197 netware_version = strdup("");
201 198
202
203 /* check CPU load */ 199 /* check CPU load */
204 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) {
205 201
206 switch(vars_to_check) { 202 switch (vars_to_check) {
207 case LOAD1: 203 case LOAD1:
208 temp_buffer = strdup ("1"); 204 temp_buffer = strdup("1");
209 break; 205 break;
210 case LOAD5: 206 case LOAD5:
211 temp_buffer = strdup ("5"); 207 temp_buffer = strdup("5");
212 break; 208 break;
213 default: 209 default:
214 temp_buffer = strdup ("15"); 210 temp_buffer = strdup("15");
215 break; 211 break;
216 } 212 }
217 213
218 close(sd); 214 close(sd);
219 my_tcp_connect (server_address, server_port, &sd); 215 my_tcp_connect(server_address, server_port, &sd);
220 216
221 xasprintf (&send_buffer,"UTIL%s\r\n",temp_buffer); 217 xasprintf(&send_buffer, "UTIL%s\r\n", temp_buffer);
222 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));
223 if (result!=STATE_OK) 219 if (result != STATE_OK)
224 return result; 220 return result;
225 utilization=strtoul(recv_buffer,NULL,10); 221 utilization = strtoul(recv_buffer, NULL, 10);
226 222
227 close(sd); 223 close(sd);
228 my_tcp_connect (server_address, server_port, &sd); 224 my_tcp_connect(server_address, server_port, &sd);
229 225
230 send_buffer = strdup ("UPTIME\r\n"); 226 send_buffer = strdup("UPTIME\r\n");
231 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));
232 if (result!=STATE_OK) 228 if (result != STATE_OK)
233 return result; 229 return result;
234 recv_buffer[strlen(recv_buffer)-1]=0; 230 recv_buffer[strlen(recv_buffer) - 1] = 0;
235 sprintf(uptime,_("Up %s,"),recv_buffer); 231 sprintf(uptime, _("Up %s,"), recv_buffer);
236 232
237 if (check_critical_value && utilization >= critical_value) 233 if (check_critical_value && utilization >= critical_value)
238 result=STATE_CRITICAL; 234 result = STATE_CRITICAL;
239 else if (check_warning_value && utilization >= warning_value) 235 else if (check_warning_value && utilization >= warning_value)
240 result=STATE_WARNING; 236 result = STATE_WARNING;
241 237
242 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,
243 _("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);
244 state_text(result),
245 uptime,
246 temp_buffer,
247 utilization,
248 temp_buffer,
249 utilization,
250 warning_value,
251 critical_value);
252 240
253 /* check number of user connections */ 241 /* check number of user connections */
254 } else if (vars_to_check==CONNS) { 242 } else if (vars_to_check == CONNS) {
255 243
256 close(sd); 244 close(sd);
257 my_tcp_connect (server_address, server_port, &sd); 245 my_tcp_connect(server_address, server_port, &sd);
258 246
259 send_buffer = strdup ("CONNECT\r\n"); 247 send_buffer = strdup("CONNECT\r\n");
260 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));
261 if (result!=STATE_OK) 249 if (result != STATE_OK)
262 return result; 250 return result;
263 current_connections=strtoul(recv_buffer,NULL,10); 251 current_connections = strtoul(recv_buffer, NULL, 10);
264 252
265 if (check_critical_value && current_connections >= critical_value) 253 if (check_critical_value && current_connections >= critical_value)
266 result=STATE_CRITICAL; 254 result = STATE_CRITICAL;
267 else if (check_warning_value && current_connections >= warning_value) 255 else if (check_warning_value && current_connections >= warning_value)
268 result=STATE_WARNING; 256 result = STATE_WARNING;
269 257
270 xasprintf (&output_message, 258 xasprintf(&output_message, _("Conns %s - %lu current connections|Conns=%lu;%lu;%lu;;"), state_text(result), current_connections,
271 _("Conns %s - %lu current connections|Conns=%lu;%lu;%lu;;"), 259 current_connections, warning_value, critical_value);
272 state_text(result),
273 current_connections,
274 current_connections,
275 warning_value,
276 critical_value);
277 260
278 /* check % long term cache hits */ 261 /* check % long term cache hits */
279 } else if (vars_to_check==LTCH) { 262 } else if (vars_to_check == LTCH) {
280 263
281 close(sd); 264 close(sd);
282 my_tcp_connect (server_address, server_port, &sd); 265 my_tcp_connect(server_address, server_port, &sd);
283 266
284 send_buffer = strdup ("S1\r\n"); 267 send_buffer = strdup("S1\r\n");
285 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));
286 if (result!=STATE_OK) 269 if (result != STATE_OK)
287 return result; 270 return result;
288 cache_hits=atoi(recv_buffer); 271 cache_hits = atoi(recv_buffer);
289 272
290 if (check_critical_value && cache_hits <= critical_value) 273 if (check_critical_value && cache_hits <= critical_value)
291 result=STATE_CRITICAL; 274 result = STATE_CRITICAL;
292 else if (check_warning_value && cache_hits <= warning_value) 275 else if (check_warning_value && cache_hits <= warning_value)
293 result=STATE_WARNING; 276 result = STATE_WARNING;
294 277
295 xasprintf (&output_message, 278 xasprintf(&output_message, _("%s: Long term cache hits = %lu%%"), state_text(result), cache_hits);
296 _("%s: Long term cache hits = %lu%%"),
297 state_text(result),
298 cache_hits);
299 279
300 /* check cache buffers */ 280 /* check cache buffers */
301 } else if (vars_to_check==CBUFF) { 281 } else if (vars_to_check == CBUFF) {
302 282
303 close(sd); 283 close(sd);
304 my_tcp_connect (server_address, server_port, &sd); 284 my_tcp_connect(server_address, server_port, &sd);
305 285
306 send_buffer = strdup ("S2\r\n"); 286 send_buffer = strdup("S2\r\n");
307 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));
308 if (result!=STATE_OK) 288 if (result != STATE_OK)
309 return result; 289 return result;
310 cache_buffers=strtoul(recv_buffer,NULL,10); 290 cache_buffers = strtoul(recv_buffer, NULL, 10);
311 291
312 if (check_critical_value && cache_buffers <= critical_value) 292 if (check_critical_value && cache_buffers <= critical_value)
313 result=STATE_CRITICAL; 293 result = STATE_CRITICAL;
314 else if (check_warning_value && cache_buffers <= warning_value) 294 else if (check_warning_value && cache_buffers <= warning_value)
315 result=STATE_WARNING; 295 result = STATE_WARNING;
316 296
317 xasprintf (&output_message, 297 xasprintf(&output_message, _("%s: Total cache buffers = %lu|Cachebuffers=%lu;%lu;%lu;;"), state_text(result), cache_buffers,
318 _("%s: Total cache buffers = %lu|Cachebuffers=%lu;%lu;%lu;;"), 298 cache_buffers, warning_value, critical_value);
319 state_text(result),
320 cache_buffers,
321 cache_buffers,
322 warning_value,
323 critical_value);
324 299
325 /* check dirty cache buffers */ 300 /* check dirty cache buffers */
326 } else if (vars_to_check==CDBUFF) { 301 } else if (vars_to_check == CDBUFF) {
327 302
328 close(sd); 303 close(sd);
329 my_tcp_connect (server_address, server_port, &sd); 304 my_tcp_connect(server_address, server_port, &sd);
330 305
331 send_buffer = strdup ("S3\r\n"); 306 send_buffer = strdup("S3\r\n");
332 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));
333 if (result!=STATE_OK) 308 if (result != STATE_OK)
334 return result; 309 return result;
335 cache_buffers=strtoul(recv_buffer,NULL,10); 310 cache_buffers = strtoul(recv_buffer, NULL, 10);
336 311
337 if (check_critical_value && cache_buffers >= critical_value) 312 if (check_critical_value && cache_buffers >= critical_value)
338 result=STATE_CRITICAL; 313 result = STATE_CRITICAL;
339 else if (check_warning_value && cache_buffers >= warning_value) 314 else if (check_warning_value && cache_buffers >= warning_value)
340 result=STATE_WARNING; 315 result = STATE_WARNING;
341 316
342 xasprintf (&output_message, 317 xasprintf(&output_message, _("%s: Dirty cache buffers = %lu|Dirty-Cache-Buffers=%lu;%lu;%lu;;"), state_text(result), cache_buffers,
343 _("%s: Dirty cache buffers = %lu|Dirty-Cache-Buffers=%lu;%lu;%lu;;"), 318 cache_buffers, warning_value, critical_value);
344 state_text(result),
345 cache_buffers,
346 cache_buffers,
347 warning_value,
348 critical_value);
349 319
350 /* check LRU sitting time in minutes */ 320 /* check LRU sitting time in minutes */
351 } else if (vars_to_check==LRUM) { 321 } else if (vars_to_check == LRUM) {
352 322
353 close(sd); 323 close(sd);
354 my_tcp_connect (server_address, server_port, &sd); 324 my_tcp_connect(server_address, server_port, &sd);
355 325
356 send_buffer = strdup ("S5\r\n"); 326 send_buffer = strdup("S5\r\n");
357 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));
358 if (result!=STATE_OK) 328 if (result != STATE_OK)
359 return result; 329 return result;
360 lru_time=strtoul(recv_buffer,NULL,10); 330 lru_time = strtoul(recv_buffer, NULL, 10);
361 331
362 if (check_critical_value && lru_time <= critical_value) 332 if (check_critical_value && lru_time <= critical_value)
363 result=STATE_CRITICAL; 333 result = STATE_CRITICAL;
364 else if (check_warning_value && lru_time <= warning_value) 334 else if (check_warning_value && lru_time <= warning_value)
365 result=STATE_WARNING; 335 result = STATE_WARNING;
366
367 xasprintf (&output_message,
368 _("%s: LRU sitting time = %lu minutes"),
369 state_text(result),
370 lru_time);
371 336
337 xasprintf(&output_message, _("%s: LRU sitting time = %lu minutes"), state_text(result), lru_time);
372 338
373 /* check KB free space on volume */ 339 /* check KB free space on volume */
374 } else if (vars_to_check==VKF) { 340 } else if (vars_to_check == VKF) {
375 341
376 close(sd); 342 close(sd);
377 my_tcp_connect (server_address, server_port, &sd); 343 my_tcp_connect(server_address, server_port, &sd);
378 344
379 xasprintf (&send_buffer,"VKF%s\r\n",volume_name); 345 xasprintf(&send_buffer, "VKF%s\r\n", volume_name);
380 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));
381 if (result!=STATE_OK) 347 if (result != STATE_OK)
382 return result; 348 return result;
383 349
384 if (!strcmp(recv_buffer,"-1\n")) { 350 if (!strcmp(recv_buffer, "-1\n")) {
385 xasprintf (&output_message,_("CRITICAL - Volume '%s' does not exist!"),volume_name); 351 xasprintf(&output_message, _("CRITICAL - Volume '%s' does not exist!"), volume_name);
386 result=STATE_CRITICAL; 352 result = STATE_CRITICAL;
387 } else { 353 } else {
388 free_disk_space=strtoul(recv_buffer,NULL,10); 354 free_disk_space = strtoul(recv_buffer, NULL, 10);
389 if (check_critical_value && free_disk_space <= critical_value) 355 if (check_critical_value && free_disk_space <= critical_value)
390 result=STATE_CRITICAL; 356 result = STATE_CRITICAL;
391 else if (check_warning_value && free_disk_space <= warning_value) 357 else if (check_warning_value && free_disk_space <= warning_value)
392 result=STATE_WARNING; 358 result = STATE_WARNING;
393 xasprintf (&output_message, 359 xasprintf(&output_message, _("%s%lu KB free on volume %s|KBFree%s=%lu;%lu;%lu;;"), (result == STATE_OK) ? "" : _("Only "),
394 _("%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);
395 (result==STATE_OK)?"":_("Only "),
396 free_disk_space,
397 volume_name,
398 volume_name,
399 free_disk_space,
400 warning_value,
401 critical_value);
402 } 361 }
403 362
404 /* check MB free space on volume */ 363 /* check MB free space on volume */
405 } else if (vars_to_check==VMF) { 364 } else if (vars_to_check == VMF) {
406 365
407 xasprintf (&send_buffer,"VMF%s\r\n",volume_name); 366 xasprintf(&send_buffer, "VMF%s\r\n", volume_name);
408 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));
409 if (result!=STATE_OK) 368 if (result != STATE_OK)
410 return result; 369 return result;
411 370
412 if (!strcmp(recv_buffer,"-1\n")) { 371 if (!strcmp(recv_buffer, "-1\n")) {
413 xasprintf (&output_message,_("CRITICAL - Volume '%s' does not exist!"),volume_name); 372 xasprintf(&output_message, _("CRITICAL - Volume '%s' does not exist!"), volume_name);
414 result=STATE_CRITICAL; 373 result = STATE_CRITICAL;
415 } else { 374 } else {
416 free_disk_space=strtoul(recv_buffer,NULL,10); 375 free_disk_space = strtoul(recv_buffer, NULL, 10);
417 if (check_critical_value && free_disk_space <= critical_value) 376 if (check_critical_value && free_disk_space <= critical_value)
418 result=STATE_CRITICAL; 377 result = STATE_CRITICAL;
419 else if (check_warning_value && free_disk_space <= warning_value) 378 else if (check_warning_value && free_disk_space <= warning_value)
420 result=STATE_WARNING; 379 result = STATE_WARNING;
421 xasprintf (&output_message, 380 xasprintf(&output_message, _("%s%lu MB free on volume %s|MBFree%s=%lu;%lu;%lu;;"), (result == STATE_OK) ? "" : _("Only "),
422 _("%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);
423 (result==STATE_OK)?"":_("Only "),
424 free_disk_space,
425 volume_name,
426 volume_name,
427 free_disk_space,
428 warning_value,
429 critical_value);
430 } 382 }
431 /* check MB used space on volume */ 383 /* check MB used space on volume */
432 } else if (vars_to_check==VMU) { 384 } else if (vars_to_check == VMU) {
433 385
434 xasprintf (&send_buffer,"VMU%s\r\n",volume_name); 386 xasprintf(&send_buffer, "VMU%s\r\n", volume_name);
435 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));
436 if (result!=STATE_OK) 388 if (result != STATE_OK)
437 return result; 389 return result;
438 390
439 if (!strcmp(recv_buffer,"-1\n")) { 391 if (!strcmp(recv_buffer, "-1\n")) {
440 xasprintf (&output_message,_("CRITICAL - Volume '%s' does not exist!"),volume_name); 392 xasprintf(&output_message, _("CRITICAL - Volume '%s' does not exist!"), volume_name);
441 result=STATE_CRITICAL; 393 result = STATE_CRITICAL;
442 } else { 394 } else {
443 free_disk_space=strtoul(recv_buffer,NULL,10); 395 free_disk_space = strtoul(recv_buffer, NULL, 10);
444 if (check_critical_value && free_disk_space <= critical_value) 396 if (check_critical_value && free_disk_space <= critical_value)
445 result=STATE_CRITICAL; 397 result = STATE_CRITICAL;
446 else if (check_warning_value && free_disk_space <= warning_value) 398 else if (check_warning_value && free_disk_space <= warning_value)
447 result=STATE_WARNING; 399 result = STATE_WARNING;
448 xasprintf (&output_message, 400 xasprintf(&output_message, _("%s%lu MB used on volume %s|MBUsed%s=%lu;%lu;%lu;;"), (result == STATE_OK) ? "" : _("Only "),
449 _("%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);
450 (result==STATE_OK)?"":_("Only "),
451 free_disk_space,
452 volume_name,
453 volume_name,
454 free_disk_space,
455 warning_value,
456 critical_value);
457 } 402 }
458 /* check % used space on volume */ 403 /* check % used space on volume */
459 } else if (vars_to_check==VPU) { 404 } else if (vars_to_check == VPU) {
460 close(sd); 405 close(sd);
461 my_tcp_connect (server_address, server_port, &sd); 406 my_tcp_connect(server_address, server_port, &sd);
462 407
463 asprintf (&send_buffer,"VMU%s\r\n",volume_name); 408 asprintf(&send_buffer, "VMU%s\r\n", volume_name);
464 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 409 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
465 410
466 if (result!=STATE_OK) 411 if (result != STATE_OK)
467 return result; 412 return result;
468 413
469 if (!strcmp(recv_buffer,"-1\n")) { 414 if (!strcmp(recv_buffer, "-1\n")) {
470 asprintf (&output_message,_("CRITICAL - Volume '%s' does not exist!"),volume_name); 415 asprintf(&output_message, _("CRITICAL - Volume '%s' does not exist!"), volume_name);
471 result=STATE_CRITICAL; 416 result = STATE_CRITICAL;
472 417
473 } else { 418 } else {
474 used_disk_space=strtoul(recv_buffer,NULL,10); 419 used_disk_space = strtoul(recv_buffer, NULL, 10);
475 close(sd); 420 close(sd);
476 my_tcp_connect (server_address, server_port, &sd); 421 my_tcp_connect(server_address, server_port, &sd);
477 /* get total volume in MB */ 422 /* get total volume in MB */
478 asprintf (&send_buffer,"VMS%s\r\n",volume_name); 423 asprintf(&send_buffer, "VMS%s\r\n", volume_name);
479 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer)); 424 result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
480 if (result!=STATE_OK) 425 if (result != STATE_OK)
481 return result; 426 return result;
482 total_disk_space=strtoul(recv_buffer,NULL,10); 427 total_disk_space = strtoul(recv_buffer, NULL, 10);
483 /* calculate percent used on volume */ 428 /* calculate percent used on volume */
484 percent_used_disk_space=(unsigned long)(((double)used_disk_space/(double)total_disk_space)*100.0); 429 percent_used_disk_space = (unsigned long)(((double)used_disk_space / (double)total_disk_space) * 100.0);
485 430
486 if (check_critical_value && percent_used_disk_space >= critical_value) 431 if (check_critical_value && percent_used_disk_space >= critical_value)
487 result=STATE_CRITICAL; 432 result = STATE_CRITICAL;
488 else if (check_warning_value && percent_used_disk_space >= warning_value) 433 else if (check_warning_value && percent_used_disk_space >= warning_value)
489 result=STATE_WARNING; 434 result = STATE_WARNING;
490 435
491 asprintf (&output_message,_("%lu MB (%lu%%) used on volume %s - total %lu MB|Used space in percent on %s=%lu;%lu;%lu;0;100"), 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"),
492 used_disk_space, 437 used_disk_space, percent_used_disk_space, volume_name, total_disk_space, volume_name, percent_used_disk_space,
493 percent_used_disk_space, 438 warning_value, critical_value);
494 volume_name,
495 total_disk_space,
496 volume_name,
497 percent_used_disk_space,
498 warning_value,
499 critical_value
500 );
501 } 439 }
502 440
503 /* check % free space on volume */ 441 /* check % free space on volume */
504 } else if (vars_to_check==VPF) { 442 } else if (vars_to_check == VPF) {
505 443
506 close(sd); 444 close(sd);
507 my_tcp_connect (server_address, server_port, &sd); 445 my_tcp_connect(server_address, server_port, &sd);
508 446
509 xasprintf (&send_buffer,"VKF%s\r\n",volume_name); 447 xasprintf(&send_buffer, "VKF%s\r\n", volume_name);
510 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));
511 if (result!=STATE_OK) 449 if (result != STATE_OK)
512 return result; 450 return result;
513 451
514 if (!strcmp(recv_buffer,"-1\n")) { 452 if (!strcmp(recv_buffer, "-1\n")) {
515 453
516 xasprintf (&output_message,_("CRITICAL - Volume '%s' does not exist!"),volume_name); 454 xasprintf(&output_message, _("CRITICAL - Volume '%s' does not exist!"), volume_name);
517 result=STATE_CRITICAL; 455 result = STATE_CRITICAL;
518 456
519 } else { 457 } else {
520 458
521 free_disk_space=strtoul(recv_buffer,NULL,10); 459 free_disk_space = strtoul(recv_buffer, NULL, 10);
522 460
523 close(sd); 461 close(sd);
524 my_tcp_connect (server_address, server_port, &sd); 462 my_tcp_connect(server_address, server_port, &sd);
525 463
526 xasprintf (&send_buffer,"VKS%s\r\n",volume_name); 464 xasprintf(&send_buffer, "VKS%s\r\n", volume_name);
527 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));
528 if (result!=STATE_OK) 466 if (result != STATE_OK)
529 return result; 467 return result;
530 total_disk_space=strtoul(recv_buffer,NULL,10); 468 total_disk_space = strtoul(recv_buffer, NULL, 10);
531 469
532 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);
533 471
534 if (check_critical_value && percent_free_space <= critical_value) 472 if (check_critical_value && percent_free_space <= critical_value)
535 result=STATE_CRITICAL; 473 result = STATE_CRITICAL;
536 else if (check_warning_value && percent_free_space <= warning_value) 474 else if (check_warning_value && percent_free_space <= warning_value)
537 result=STATE_WARNING; 475 result = STATE_WARNING;
538 free_disk_space/=1024; 476 free_disk_space /= 1024;
539 total_disk_space/=1024; 477 total_disk_space /= 1024;
540 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,
541 free_disk_space, 479 percent_free_space, volume_name, total_disk_space, volume_name, percent_free_space, warning_value, critical_value);
542 percent_free_space,
543 volume_name,
544 total_disk_space,
545 volume_name,
546 percent_free_space,
547 warning_value,
548 critical_value
549 );
550 } 480 }
551 481
552 /* check to see if DS Database is open or closed */ 482 /* check to see if DS Database is open or closed */
553 } else if (vars_to_check==DSDB) { 483 } else if (vars_to_check == DSDB) {
554 484
555 close(sd); 485 close(sd);
556 my_tcp_connect (server_address, server_port, &sd); 486 my_tcp_connect(server_address, server_port, &sd);
557 487
558 send_buffer = strdup ("S11\r\n"); 488 send_buffer = strdup("S11\r\n");
559 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));
560 if (result!=STATE_OK) 490 if (result != STATE_OK)
561 return result; 491 return result;
562 if (atoi(recv_buffer)==1) 492 if (atoi(recv_buffer) == 1)
563 result=STATE_OK; 493 result = STATE_OK;
564 else 494 else
565 result=STATE_WARNING; 495 result = STATE_WARNING;
566 496
567 close(sd); 497 close(sd);
568 my_tcp_connect (server_address, server_port, &sd); 498 my_tcp_connect(server_address, server_port, &sd);
569 499
570 send_buffer = strdup ("S13\r\n"); 500 send_buffer = strdup("S13\r\n");
571 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));
572 temp_buffer=strtok(recv_buffer,"\r\n"); 502 temp_buffer = strtok(recv_buffer, "\r\n");
573 503
574 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);
575 506
576 /* check to see if logins are enabled */ 507 /* check to see if logins are enabled */
577 } else if (vars_to_check==LOGINS) { 508 } else if (vars_to_check == LOGINS) {
578 509
579 close(sd); 510 close(sd);
580 my_tcp_connect (server_address, server_port, &sd); 511 my_tcp_connect(server_address, server_port, &sd);
581 512
582 send_buffer = strdup ("S12\r\n"); 513 send_buffer = strdup("S12\r\n");
583 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));
584 if (result!=STATE_OK) 515 if (result != STATE_OK)
585 return result; 516 return result;
586 if (atoi(recv_buffer)==1) 517 if (atoi(recv_buffer) == 1)
587 result=STATE_OK; 518 result = STATE_OK;
588 else 519 else
589 result=STATE_WARNING; 520 result = STATE_WARNING;
590
591 xasprintf (&output_message,_("Logins are %s"),(result==STATE_OK)?_("enabled"):_("disabled"));
592 521
522 xasprintf(&output_message, _("Logins are %s"), (result == STATE_OK) ? _("enabled") : _("disabled"));
593 523
594 /* check NRM Health Status Summary*/ 524 /* check NRM Health Status Summary*/
595 } else if (vars_to_check==NRMH) { 525 } else if (vars_to_check == NRMH) {
596 526
597 xasprintf (&send_buffer,"NRMH\r\n"); 527 xasprintf(&send_buffer, "NRMH\r\n");
598 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));
599 if (result!=STATE_OK) 529 if (result != STATE_OK)
600 return result; 530 return result;
601 531
602 nrm_health_status=atoi(recv_buffer); 532 nrm_health_status = atoi(recv_buffer);
603 533
604 if (nrm_health_status==2) { 534 if (nrm_health_status == 2) {
605 result=STATE_OK; 535 result = STATE_OK;
606 xasprintf (&output_message,_("CRITICAL - NRM Status is bad!")); 536 xasprintf(&output_message, _("CRITICAL - NRM Status is bad!"));
607 } 537 } else {
608 else { 538 if (nrm_health_status == 1) {
609 if (nrm_health_status==1) { 539 result = STATE_WARNING;
610 result=STATE_WARNING; 540 xasprintf(&output_message, _("Warning - NRM Status is suspect!"));
611 xasprintf (&output_message,_("Warning - NRM Status is suspect!"));
612 } 541 }
613 542
614 xasprintf (&output_message,_("OK - NRM Status is good!")); 543 xasprintf(&output_message, _("OK - NRM Status is good!"));
615 } 544 }
616 545
617
618
619 /* check packet receive buffers */ 546 /* check packet receive buffers */
620 } else if (vars_to_check==UPRB || vars_to_check==PUPRB) { 547 } else if (vars_to_check == UPRB || vars_to_check == PUPRB) {
621 548
622 close(sd); 549 close(sd);
623 my_tcp_connect (server_address, server_port, &sd); 550 my_tcp_connect(server_address, server_port, &sd);
624 551
625 xasprintf (&send_buffer,"S15\r\n"); 552 xasprintf(&send_buffer, "S15\r\n");
626 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));
627 if (result!=STATE_OK) 554 if (result != STATE_OK)
628 return result; 555 return result;
629 556
630 used_packet_receive_buffers=atoi(recv_buffer); 557 used_packet_receive_buffers = atoi(recv_buffer);
631 558
632 close(sd); 559 close(sd);
633 my_tcp_connect (server_address, server_port, &sd); 560 my_tcp_connect(server_address, server_port, &sd);
634 561
635 xasprintf (&send_buffer,"S16\r\n"); 562 xasprintf(&send_buffer, "S16\r\n");
636 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));
637 if (result!=STATE_OK) 564 if (result != STATE_OK)
638 return result; 565 return result;
639 566
640 max_packet_receive_buffers=atoi(recv_buffer); 567 max_packet_receive_buffers = atoi(recv_buffer);
641 568
642 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);
643 571
644 if (vars_to_check==UPRB) { 572 if (vars_to_check == UPRB) {
645 if (check_critical_value && used_packet_receive_buffers >= critical_value) 573 if (check_critical_value && used_packet_receive_buffers >= critical_value)
646 result=STATE_CRITICAL; 574 result = STATE_CRITICAL;
647 else if (check_warning_value && used_packet_receive_buffers >= warning_value) 575 else if (check_warning_value && used_packet_receive_buffers >= warning_value)
648 result=STATE_WARNING; 576 result = STATE_WARNING;
649 } else { 577 } else {
650 if (check_critical_value && percent_used_packet_receive_buffers >= critical_value) 578 if (check_critical_value && percent_used_packet_receive_buffers >= critical_value)
651 result=STATE_CRITICAL; 579 result = STATE_CRITICAL;
652 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)
653 result=STATE_WARNING; 581 result = STATE_WARNING;
654 } 582 }
655 583
656 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);
657 586
658 /* check SAP table entries */ 587 /* check SAP table entries */
659 } else if (vars_to_check==SAPENTRIES) { 588 } else if (vars_to_check == SAPENTRIES) {
660 589
661 close(sd); 590 close(sd);
662 my_tcp_connect (server_address, server_port, &sd); 591 my_tcp_connect(server_address, server_port, &sd);
663 592
664 if (sap_number==-1) 593 if (sap_number == -1)
665 xasprintf (&send_buffer,"S9\r\n"); 594 xasprintf(&send_buffer, "S9\r\n");
666 else 595 else
667 xasprintf (&send_buffer,"S9.%d\r\n",sap_number); 596 xasprintf(&send_buffer, "S9.%d\r\n", sap_number);
668 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));
669 if (result!=STATE_OK) 598 if (result != STATE_OK)
670 return result; 599 return result;
671 600
672 sap_entries=atoi(recv_buffer); 601 sap_entries = atoi(recv_buffer);
673 602
674 if (check_critical_value && sap_entries >= critical_value) 603 if (check_critical_value && sap_entries >= critical_value)
675 result=STATE_CRITICAL; 604 result = STATE_CRITICAL;
676 else if (check_warning_value && sap_entries >= warning_value) 605 else if (check_warning_value && sap_entries >= warning_value)
677 result=STATE_WARNING; 606 result = STATE_WARNING;
678 607
679 if (sap_number==-1) 608 if (sap_number == -1)
680 xasprintf (&output_message,_("%lu entries in SAP table"),sap_entries); 609 xasprintf(&output_message, _("%lu entries in SAP table"), sap_entries);
681 else 610 else
682 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);
683 612
684 /* check KB purgeable space on volume */ 613 /* check KB purgeable space on volume */
685 } else if (vars_to_check==VKP) { 614 } else if (vars_to_check == VKP) {
686 615
687 close(sd); 616 close(sd);
688 my_tcp_connect (server_address, server_port, &sd); 617 my_tcp_connect(server_address, server_port, &sd);
689 618
690 xasprintf (&send_buffer,"VKP%s\r\n",volume_name); 619 xasprintf(&send_buffer, "VKP%s\r\n", volume_name);
691 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));
692 if (result!=STATE_OK) 621 if (result != STATE_OK)
693 return result; 622 return result;
694 623
695 if (!strcmp(recv_buffer,"-1\n")) { 624 if (!strcmp(recv_buffer, "-1\n")) {
696 xasprintf (&output_message,_("CRITICAL - Volume '%s' does not exist!"),volume_name); 625 xasprintf(&output_message, _("CRITICAL - Volume '%s' does not exist!"), volume_name);
697 result=STATE_CRITICAL; 626 result = STATE_CRITICAL;
698 } else { 627 } else {
699 purgeable_disk_space=strtoul(recv_buffer,NULL,10); 628 purgeable_disk_space = strtoul(recv_buffer, NULL, 10);
700 if (check_critical_value && purgeable_disk_space >= critical_value) 629 if (check_critical_value && purgeable_disk_space >= critical_value)
701 result=STATE_CRITICAL; 630 result = STATE_CRITICAL;
702 else if (check_warning_value && purgeable_disk_space >= warning_value) 631 else if (check_warning_value && purgeable_disk_space >= warning_value)
703 result=STATE_WARNING; 632 result = STATE_WARNING;
704 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 "),
705 (result==STATE_OK)?"":_("Only "), 634 purgeable_disk_space, volume_name, volume_name, purgeable_disk_space, warning_value, critical_value);
706 purgeable_disk_space,
707 volume_name,
708 volume_name,
709 purgeable_disk_space,
710 warning_value,
711 critical_value);
712 } 635 }
713 /* check MB purgeable space on volume */ 636 /* check MB purgeable space on volume */
714 } else if (vars_to_check==VMP) { 637 } else if (vars_to_check == VMP) {
715 638
716 xasprintf (&send_buffer,"VMP%s\r\n",volume_name); 639 xasprintf(&send_buffer, "VMP%s\r\n", volume_name);
717 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));
718 if (result!=STATE_OK) 641 if (result != STATE_OK)
719 return result; 642 return result;
720 643
721 if (!strcmp(recv_buffer,"-1\n")) { 644 if (!strcmp(recv_buffer, "-1\n")) {
722 xasprintf (&output_message,_("CRITICAL - Volume '%s' does not exist!"),volume_name); 645 xasprintf(&output_message, _("CRITICAL - Volume '%s' does not exist!"), volume_name);
723 result=STATE_CRITICAL; 646 result = STATE_CRITICAL;
724 } else { 647 } else {
725 purgeable_disk_space=strtoul(recv_buffer,NULL,10); 648 purgeable_disk_space = strtoul(recv_buffer, NULL, 10);
726 if (check_critical_value && purgeable_disk_space >= critical_value) 649 if (check_critical_value && purgeable_disk_space >= critical_value)
727 result=STATE_CRITICAL; 650 result = STATE_CRITICAL;
728 else if (check_warning_value && purgeable_disk_space >= warning_value) 651 else if (check_warning_value && purgeable_disk_space >= warning_value)
729 result=STATE_WARNING; 652 result = STATE_WARNING;
730 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 "),
731 (result==STATE_OK)?"":_("Only "), 654 purgeable_disk_space, volume_name, volume_name, purgeable_disk_space, warning_value, critical_value);
732 purgeable_disk_space,
733 volume_name,
734 volume_name,
735 purgeable_disk_space,
736 warning_value,
737 critical_value);
738 } 655 }
739 656
740 /* check % purgeable space on volume */ 657 /* check % purgeable space on volume */
741 } else if (vars_to_check==VPP) { 658 } else if (vars_to_check == VPP) {
742 659
743 close(sd); 660 close(sd);
744 my_tcp_connect (server_address, server_port, &sd); 661 my_tcp_connect(server_address, server_port, &sd);
745 662
746 xasprintf (&send_buffer,"VKP%s\r\n",volume_name); 663 xasprintf(&send_buffer, "VKP%s\r\n", volume_name);
747 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));
748 if (result!=STATE_OK) 665 if (result != STATE_OK)
749 return result; 666 return result;
750 667
751 if (!strcmp(recv_buffer,"-1\n")) { 668 if (!strcmp(recv_buffer, "-1\n")) {
752 669
753 xasprintf (&output_message,_("CRITICAL - Volume '%s' does not exist!"),volume_name); 670 xasprintf(&output_message, _("CRITICAL - Volume '%s' does not exist!"), volume_name);
754 result=STATE_CRITICAL; 671 result = STATE_CRITICAL;
755 672
756 } else { 673 } else {
757 674
758 purgeable_disk_space=strtoul(recv_buffer,NULL,10); 675 purgeable_disk_space = strtoul(recv_buffer, NULL, 10);
759 676
760 close(sd); 677 close(sd);
761 my_tcp_connect (server_address, server_port, &sd); 678 my_tcp_connect(server_address, server_port, &sd);
762 679
763 xasprintf (&send_buffer,"VKS%s\r\n",volume_name); 680 xasprintf(&send_buffer, "VKS%s\r\n", volume_name);
764 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));
765 if (result!=STATE_OK) 682 if (result != STATE_OK)
766 return result; 683 return result;
767 total_disk_space=strtoul(recv_buffer,NULL,10); 684 total_disk_space = strtoul(recv_buffer, NULL, 10);
768 685
769 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);
770 687
771 if (check_critical_value && percent_purgeable_space >= critical_value) 688 if (check_critical_value && percent_purgeable_space >= critical_value)
772 result=STATE_CRITICAL; 689 result = STATE_CRITICAL;
773 else if (check_warning_value && percent_purgeable_space >= warning_value) 690 else if (check_warning_value && percent_purgeable_space >= warning_value)
774 result=STATE_WARNING; 691 result = STATE_WARNING;
775 purgeable_disk_space/=1024; 692 purgeable_disk_space /= 1024;
776 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,
777 purgeable_disk_space, 694 percent_purgeable_space, volume_name, volume_name, percent_purgeable_space, warning_value, critical_value);
778 percent_purgeable_space,
779 volume_name,
780 volume_name,
781 percent_purgeable_space,
782 warning_value,
783 critical_value
784 );
785 } 695 }
786 696
787 /* check KB not yet purgeable space on volume */ 697 /* check KB not yet purgeable space on volume */
788 } else if (vars_to_check==VKNP) { 698 } else if (vars_to_check == VKNP) {
789 699
790 close(sd); 700 close(sd);
791 my_tcp_connect (server_address, server_port, &sd); 701 my_tcp_connect(server_address, server_port, &sd);
792 702
793 xasprintf (&send_buffer,"VKNP%s\r\n",volume_name); 703 xasprintf(&send_buffer, "VKNP%s\r\n", volume_name);
794 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));
795 if (result!=STATE_OK) 705 if (result != STATE_OK)
796 return result; 706 return result;
797 707
798 if (!strcmp(recv_buffer,"-1\n")) { 708 if (!strcmp(recv_buffer, "-1\n")) {
799 xasprintf (&output_message,_("CRITICAL - Volume '%s' does not exist!"),volume_name); 709 xasprintf(&output_message, _("CRITICAL - Volume '%s' does not exist!"), volume_name);
800 result=STATE_CRITICAL; 710 result = STATE_CRITICAL;
801 } else { 711 } else {
802 non_purgeable_disk_space=strtoul(recv_buffer,NULL,10); 712 non_purgeable_disk_space = strtoul(recv_buffer, NULL, 10);
803 if (check_critical_value && non_purgeable_disk_space >= critical_value) 713 if (check_critical_value && non_purgeable_disk_space >= critical_value)
804 result=STATE_CRITICAL; 714 result = STATE_CRITICAL;
805 else if (check_warning_value && non_purgeable_disk_space >= warning_value) 715 else if (check_warning_value && non_purgeable_disk_space >= warning_value)
806 result=STATE_WARNING; 716 result = STATE_WARNING;
807 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);
808 } 719 }
809 720
810 /* check % not yet purgeable space on volume */ 721 /* check % not yet purgeable space on volume */
811 } else if (vars_to_check==VPNP) { 722 } else if (vars_to_check == VPNP) {
812 723
813 close(sd); 724 close(sd);
814 my_tcp_connect (server_address, server_port, &sd); 725 my_tcp_connect(server_address, server_port, &sd);
815 726
816 xasprintf (&send_buffer,"VKNP%s\r\n",volume_name); 727 xasprintf(&send_buffer, "VKNP%s\r\n", volume_name);
817 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));
818 if (result!=STATE_OK) 729 if (result != STATE_OK)
819 return result; 730 return result;
820 731
821 if (!strcmp(recv_buffer,"-1\n")) { 732 if (!strcmp(recv_buffer, "-1\n")) {
822 733
823 xasprintf (&output_message,_("CRITICAL - Volume '%s' does not exist!"),volume_name); 734 xasprintf(&output_message, _("CRITICAL - Volume '%s' does not exist!"), volume_name);
824 result=STATE_CRITICAL; 735 result = STATE_CRITICAL;
825 736
826 } else { 737 } else {
827 738
828 non_purgeable_disk_space=strtoul(recv_buffer,NULL,10); 739 non_purgeable_disk_space = strtoul(recv_buffer, NULL, 10);
829 740
830 close(sd); 741 close(sd);
831 my_tcp_connect (server_address, server_port, &sd); 742 my_tcp_connect(server_address, server_port, &sd);
832 743
833 xasprintf (&send_buffer,"VKS%s\r\n",volume_name); 744 xasprintf(&send_buffer, "VKS%s\r\n", volume_name);
834 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));
835 if (result!=STATE_OK) 746 if (result != STATE_OK)
836 return result; 747 return result;
837 total_disk_space=strtoul(recv_buffer,NULL,10); 748 total_disk_space = strtoul(recv_buffer, NULL, 10);
838 749
839 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);
840 751
841 if (check_critical_value && percent_non_purgeable_space >= critical_value) 752 if (check_critical_value && percent_non_purgeable_space >= critical_value)
842 result=STATE_CRITICAL; 753 result = STATE_CRITICAL;
843 else if (check_warning_value && percent_non_purgeable_space >= warning_value) 754 else if (check_warning_value && percent_non_purgeable_space >= warning_value)
844 result=STATE_WARNING; 755 result = STATE_WARNING;
845 purgeable_disk_space/=1024; 756 purgeable_disk_space /= 1024;
846 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);
847 } 759 }
848 760
849 /* check # of open files */ 761 /* check # of open files */
850 } else if (vars_to_check==OFILES) { 762 } else if (vars_to_check == OFILES) {
851 763
852 close(sd); 764 close(sd);
853 my_tcp_connect (server_address, server_port, &sd); 765 my_tcp_connect(server_address, server_port, &sd);
854 766
855 xasprintf (&send_buffer,"S18\r\n"); 767 xasprintf(&send_buffer, "S18\r\n");
856 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));
857 if (result!=STATE_OK) 769 if (result != STATE_OK)
858 return result; 770 return result;
859 771
860 open_files=atoi(recv_buffer); 772 open_files = atoi(recv_buffer);
861 773
862 if (check_critical_value && open_files >= critical_value) 774 if (check_critical_value && open_files >= critical_value)
863 result=STATE_CRITICAL; 775 result = STATE_CRITICAL;
864 else if (check_warning_value && open_files >= warning_value) 776 else if (check_warning_value && open_files >= warning_value)
865 result=STATE_WARNING; 777 result = STATE_WARNING;
866
867 xasprintf (&output_message,_("%lu open files|Openfiles=%lu;%lu;%lu;0,0"),
868 open_files,
869 open_files,
870 warning_value,
871 critical_value);
872 778
779 xasprintf(&output_message, _("%lu open files|Openfiles=%lu;%lu;%lu;0,0"), open_files, open_files, warning_value, critical_value);
873 780
874 /* check # of abended threads (Netware > 5.x only) */ 781 /* check # of abended threads (Netware > 5.x only) */
875 } else if (vars_to_check==ABENDS) { 782 } else if (vars_to_check == ABENDS) {
876 783
877 close(sd); 784 close(sd);
878 my_tcp_connect (server_address, server_port, &sd); 785 my_tcp_connect(server_address, server_port, &sd);
879 786
880 xasprintf (&send_buffer,"S17\r\n"); 787 xasprintf(&send_buffer, "S17\r\n");
881 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));
882 if (result!=STATE_OK) 789 if (result != STATE_OK)
883 return result; 790 return result;
884 791
885 abended_threads=atoi(recv_buffer); 792 abended_threads = atoi(recv_buffer);
886 793
887 if (check_critical_value && abended_threads >= critical_value) 794 if (check_critical_value && abended_threads >= critical_value)
888 result=STATE_CRITICAL; 795 result = STATE_CRITICAL;
889 else if (check_warning_value && abended_threads >= warning_value) 796 else if (check_warning_value && abended_threads >= warning_value)
890 result=STATE_WARNING; 797 result = STATE_WARNING;
891 798
892 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,
893 abended_threads, 800 critical_value);
894 abended_threads,
895 warning_value,
896 critical_value);
897 801
898 /* check # of current service processes (Netware 5.x only) */ 802 /* check # of current service processes (Netware 5.x only) */
899 } else if (vars_to_check==CSPROCS) { 803 } else if (vars_to_check == CSPROCS) {
900 804
901 close(sd); 805 close(sd);
902 my_tcp_connect (server_address, server_port, &sd); 806 my_tcp_connect(server_address, server_port, &sd);
903 807
904 xasprintf (&send_buffer,"S20\r\n"); 808 xasprintf(&send_buffer, "S20\r\n");
905 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));
906 if (result!=STATE_OK) 810 if (result != STATE_OK)
907 return result; 811 return result;
908 812
909 max_service_processes=atoi(recv_buffer); 813 max_service_processes = atoi(recv_buffer);
910 814
911 close(sd); 815 close(sd);
912 my_tcp_connect (server_address, server_port, &sd); 816 my_tcp_connect(server_address, server_port, &sd);
913 817
914 xasprintf (&send_buffer,"S21\r\n"); 818 xasprintf(&send_buffer, "S21\r\n");
915 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));
916 if (result!=STATE_OK) 820 if (result != STATE_OK)
917 return result; 821 return result;
918 822
919 current_service_processes=atoi(recv_buffer); 823 current_service_processes = atoi(recv_buffer);
920 824
921 if (check_critical_value && current_service_processes >= critical_value) 825 if (check_critical_value && current_service_processes >= critical_value)
922 result=STATE_CRITICAL; 826 result = STATE_CRITICAL;
923 else if (check_warning_value && current_service_processes >= warning_value) 827 else if (check_warning_value && current_service_processes >= warning_value)
924 result=STATE_WARNING; 828 result = STATE_WARNING;
925 829
926 xasprintf (&output_message, 830 xasprintf(&output_message, _("%lu current service processes (%lu max)|Processes=%lu;%lu;%lu;0;%lu"), current_service_processes,
927 _("%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);
928 current_service_processes,
929 max_service_processes,
930 current_service_processes,
931 warning_value,
932 critical_value,
933 max_service_processes);
934 832
935 /* check # Timesync Status */ 833 /* check # Timesync Status */
936 } else if (vars_to_check==TSYNC) { 834 } else if (vars_to_check == TSYNC) {
937 835
938 close(sd); 836 close(sd);
939 my_tcp_connect (server_address, server_port, &sd); 837 my_tcp_connect(server_address, server_port, &sd);
940 838
941 xasprintf (&send_buffer,"S22\r\n"); 839 xasprintf(&send_buffer, "S22\r\n");
942 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));
943 if (result!=STATE_OK) 841 if (result != STATE_OK)
944 return result; 842 return result;
945 843
946 time_sync_status=atoi(recv_buffer); 844 time_sync_status = atoi(recv_buffer);
947 845
948 if (time_sync_status==0) { 846 if (time_sync_status == 0) {
949 result=STATE_CRITICAL; 847 result = STATE_CRITICAL;
950 xasprintf (&output_message,_("CRITICAL - Time not in sync with network!")); 848 xasprintf(&output_message, _("CRITICAL - Time not in sync with network!"));
951 } 849 } else {
952 else { 850 xasprintf(&output_message, _("OK - Time in sync with network!"));
953 xasprintf (&output_message,_("OK - Time in sync with network!"));
954 } 851 }
955 852
956
957
958
959
960 /* check LRU sitting time in secondss */ 853 /* check LRU sitting time in secondss */
961 } else if (vars_to_check==LRUS) { 854 } else if (vars_to_check == LRUS) {
962 855
963 close(sd); 856 close(sd);
964 my_tcp_connect (server_address, server_port, &sd); 857 my_tcp_connect(server_address, server_port, &sd);
965 858
966 send_buffer = strdup ("S4\r\n"); 859 send_buffer = strdup("S4\r\n");
967 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));
968 if (result!=STATE_OK) 861 if (result != STATE_OK)
969 return result; 862 return result;
970 lru_time=strtoul(recv_buffer,NULL,10); 863 lru_time = strtoul(recv_buffer, NULL, 10);
971 864
972 if (check_critical_value && lru_time <= critical_value) 865 if (check_critical_value && lru_time <= critical_value)
973 result=STATE_CRITICAL; 866 result = STATE_CRITICAL;
974 else if (check_warning_value && lru_time <= warning_value) 867 else if (check_warning_value && lru_time <= warning_value)
975 result=STATE_WARNING; 868 result = STATE_WARNING;
976 xasprintf (&output_message,_("LRU sitting time = %lu seconds"),lru_time); 869 xasprintf(&output_message, _("LRU sitting time = %lu seconds"), lru_time);
977
978 870
979 /* check % dirty cacheobuffers as a percentage of the total*/ 871 /* check % dirty cacheobuffers as a percentage of the total*/
980 } else if (vars_to_check==DCB) { 872 } else if (vars_to_check == DCB) {
981 873
982 close(sd); 874 close(sd);
983 my_tcp_connect (server_address, server_port, &sd); 875 my_tcp_connect(server_address, server_port, &sd);
984 876
985 send_buffer = strdup ("S6\r\n"); 877 send_buffer = strdup("S6\r\n");
986 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));
987 if (result!=STATE_OK) 879 if (result != STATE_OK)
988 return result; 880 return result;
989 dirty_cache_buffers=atoi(recv_buffer); 881 dirty_cache_buffers = atoi(recv_buffer);
990 882
991 if (check_critical_value && dirty_cache_buffers <= critical_value) 883 if (check_critical_value && dirty_cache_buffers <= critical_value)
992 result=STATE_CRITICAL; 884 result = STATE_CRITICAL;
993 else if (check_warning_value && dirty_cache_buffers <= warning_value) 885 else if (check_warning_value && dirty_cache_buffers <= warning_value)
994 result=STATE_WARNING; 886 result = STATE_WARNING;
995 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,
996 dirty_cache_buffers, 888 dirty_cache_buffers, warning_value, critical_value);
997 dirty_cache_buffers,
998 warning_value,
999 critical_value);
1000 889
1001 /* check % total cache buffers as a percentage of the original*/ 890 /* check % total cache buffers as a percentage of the original*/
1002 } else if (vars_to_check==TCB) { 891 } else if (vars_to_check == TCB) {
1003 892
1004 close(sd); 893 close(sd);
1005 my_tcp_connect (server_address, server_port, &sd); 894 my_tcp_connect(server_address, server_port, &sd);
1006 895
1007 send_buffer = strdup ("S7\r\n"); 896 send_buffer = strdup("S7\r\n");
1008 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));
1009 if (result!=STATE_OK) 898 if (result != STATE_OK)
1010 return result; 899 return result;
1011 total_cache_buffers=atoi(recv_buffer); 900 total_cache_buffers = atoi(recv_buffer);
1012 901
1013 if (check_critical_value && total_cache_buffers <= critical_value) 902 if (check_critical_value && total_cache_buffers <= critical_value)
1014 result=STATE_CRITICAL; 903 result = STATE_CRITICAL;
1015 else if (check_warning_value && total_cache_buffers <= warning_value) 904 else if (check_warning_value && total_cache_buffers <= warning_value)
1016 result=STATE_WARNING; 905 result = STATE_WARNING;
1017 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,
1018 total_cache_buffers, 907 total_cache_buffers, warning_value, critical_value);
1019 total_cache_buffers,
1020 warning_value,
1021 critical_value);
1022 908
1023 } else if (vars_to_check==DSVER) { 909 } else if (vars_to_check == DSVER) {
1024 910
1025 close(sd); 911 close(sd);
1026 my_tcp_connect (server_address, server_port, &sd); 912 my_tcp_connect(server_address, server_port, &sd);
1027 913
1028 xasprintf (&send_buffer,"S13\r\n"); 914 xasprintf(&send_buffer, "S13\r\n");
1029 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));
1030 if (result!=STATE_OK) 916 if (result != STATE_OK)
1031 return result; 917 return result;
1032 918
1033 recv_buffer[strlen(recv_buffer)-1]=0; 919 recv_buffer[strlen(recv_buffer) - 1] = 0;
1034 920
1035 xasprintf (&output_message,_("NDS Version %s"),recv_buffer); 921 xasprintf(&output_message, _("NDS Version %s"), recv_buffer);
1036 922
1037 } else if (vars_to_check==UPTIME) { 923 } else if (vars_to_check == UPTIME) {
1038 924
1039 close(sd); 925 close(sd);
1040 my_tcp_connect (server_address, server_port, &sd); 926 my_tcp_connect(server_address, server_port, &sd);
1041
1042 xasprintf (&send_buffer,"UPTIME\r\n");
1043 result=send_tcp_request(sd,send_buffer,recv_buffer,sizeof(recv_buffer));
1044 if (result!=STATE_OK)
1045 return result;
1046 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;
1047 932
1048 recv_buffer[sizeof(recv_buffer)-1]=0; 933 recv_buffer[sizeof(recv_buffer) - 1] = 0;
1049 recv_buffer[strlen(recv_buffer)-1]=0; 934 recv_buffer[strlen(recv_buffer) - 1] = 0;
1050 935
1051 xasprintf (&output_message,_("Up %s"),recv_buffer); 936 xasprintf(&output_message, _("Up %s"), recv_buffer);
1052 937
1053 } else if (vars_to_check==NLM) { 938 } else if (vars_to_check == NLM) {
1054 939
1055 close(sd); 940 close(sd);
1056 my_tcp_connect (server_address, server_port, &sd); 941 my_tcp_connect(server_address, server_port, &sd);
1057 942
1058 xasprintf (&send_buffer,"S24:%s\r\n",nlm_name); 943 xasprintf(&send_buffer, "S24:%s\r\n", nlm_name);
1059 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));
1060 if (result!=STATE_OK) 945 if (result != STATE_OK)
1061 return result; 946 return result;
1062 947
1063 recv_buffer[strlen(recv_buffer)-1]=0; 948 recv_buffer[strlen(recv_buffer) - 1] = 0;
1064 if (strcmp(recv_buffer,"-1")) { 949 if (strcmp(recv_buffer, "-1")) {
1065 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);
1066 } else { 951 } else {
1067 result=STATE_CRITICAL; 952 result = STATE_CRITICAL;
1068 xasprintf (&output_message,_("Module %s is not loaded"),nlm_name); 953 xasprintf(&output_message, _("Module %s is not loaded"), nlm_name);
1069 954 }
1070 } 955 } else if (vars_to_check == NRMP) {
1071 } else if (vars_to_check==NRMP) {
1072 956
1073 xasprintf (&send_buffer,"NRMP:%s\r\n",nrmp_name); 957 xasprintf(&send_buffer, "NRMP:%s\r\n", nrmp_name);
1074 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));
1075 if (result!=STATE_OK) 959 if (result != STATE_OK)
1076 return result; 960 return result;
1077 961
1078 if (!strcmp(recv_buffer,"-1\n")) { 962 if (!strcmp(recv_buffer, "-1\n")) {
1079 xasprintf (&output_message,_("CRITICAL - Value '%s' does not exist!"),nrmp_name); 963 xasprintf(&output_message, _("CRITICAL - Value '%s' does not exist!"), nrmp_name);
1080 result=STATE_CRITICAL; 964 result = STATE_CRITICAL;
1081 } else { 965 } else {
1082 nrmp_value=strtoul(recv_buffer,NULL,10); 966 nrmp_value = strtoul(recv_buffer, NULL, 10);
1083 if (check_critical_value && nrmp_value <= critical_value) 967 if (check_critical_value && nrmp_value <= critical_value)
1084 result=STATE_CRITICAL; 968 result = STATE_CRITICAL;
1085 else if (check_warning_value && nrmp_value <= warning_value) 969 else if (check_warning_value && nrmp_value <= warning_value)
1086 result=STATE_WARNING; 970 result = STATE_WARNING;
1087 xasprintf (&output_message, 971 xasprintf(&output_message, _("%s is %lu|%s=%lu;%lu;%lu;;"), nrmp_name, nrmp_value, nrmp_name, nrmp_value, warning_value,
1088 _("%s is %lu|%s=%lu;%lu;%lu;;"), 972 critical_value);
1089 nrmp_name,
1090 nrmp_value,
1091 nrmp_name,
1092 nrmp_value,
1093 warning_value,
1094 critical_value);
1095 } 973 }
1096 974
1097 } else if (vars_to_check==NRMM) { 975 } else if (vars_to_check == NRMM) {
1098 976
1099 xasprintf (&send_buffer,"NRMM:%s\r\n",nrmm_name); 977 xasprintf(&send_buffer, "NRMM:%s\r\n", nrmm_name);
1100 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));
1101 if (result!=STATE_OK) 979 if (result != STATE_OK)
1102 return result; 980 return result;
1103 981
1104 if (!strcmp(recv_buffer,"-1\n")) { 982 if (!strcmp(recv_buffer, "-1\n")) {
1105 xasprintf (&output_message,_("CRITICAL - Value '%s' does not exist!"),nrmm_name); 983 xasprintf(&output_message, _("CRITICAL - Value '%s' does not exist!"), nrmm_name);
1106 result=STATE_CRITICAL; 984 result = STATE_CRITICAL;
1107 } else { 985 } else {
1108 nrmm_value=strtoul(recv_buffer,NULL,10); 986 nrmm_value = strtoul(recv_buffer, NULL, 10);
1109 if (check_critical_value && nrmm_value <= critical_value) 987 if (check_critical_value && nrmm_value <= critical_value)
1110 result=STATE_CRITICAL; 988 result = STATE_CRITICAL;
1111 else if (check_warning_value && nrmm_value <= warning_value) 989 else if (check_warning_value && nrmm_value <= warning_value)
1112 result=STATE_WARNING; 990 result = STATE_WARNING;
1113 xasprintf (&output_message, 991 xasprintf(&output_message, _("%s is %lu|%s=%lu;%lu;%lu;;"), nrmm_name, nrmm_value, nrmm_name, nrmm_value, warning_value,
1114 _("%s is %lu|%s=%lu;%lu;%lu;;"), 992 critical_value);
1115 nrmm_name,
1116 nrmm_value,
1117 nrmm_name,
1118 nrmm_value,
1119 warning_value,
1120 critical_value);
1121 } 993 }
1122 994
1123 } else if (vars_to_check==NRMS) { 995 } else if (vars_to_check == NRMS) {
1124 996
1125 xasprintf (&send_buffer,"NRMS:%s\r\n",nrms_name); 997 xasprintf(&send_buffer, "NRMS:%s\r\n", nrms_name);
1126 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));
1127 if (result!=STATE_OK) 999 if (result != STATE_OK)
1128 return result; 1000 return result;
1129 1001
1130 if (!strcmp(recv_buffer,"-1\n")) { 1002 if (!strcmp(recv_buffer, "-1\n")) {
1131 xasprintf (&output_message,_("CRITICAL - Value '%s' does not exist!"),nrms_name); 1003 xasprintf(&output_message, _("CRITICAL - Value '%s' does not exist!"), nrms_name);
1132 result=STATE_CRITICAL; 1004 result = STATE_CRITICAL;
1133 } else { 1005 } else {
1134 nrms_value=strtoul(recv_buffer,NULL,10); 1006 nrms_value = strtoul(recv_buffer, NULL, 10);
1135 if (check_critical_value && nrms_value >= critical_value) 1007 if (check_critical_value && nrms_value >= critical_value)
1136 result=STATE_CRITICAL; 1008 result = STATE_CRITICAL;
1137 else if (check_warning_value && nrms_value >= warning_value) 1009 else if (check_warning_value && nrms_value >= warning_value)
1138 result=STATE_WARNING; 1010 result = STATE_WARNING;
1139 xasprintf (&output_message, 1011 xasprintf(&output_message, _("%s is %lu|%s=%lu;%lu;%lu;;"), nrms_name, nrms_value, nrms_name, nrms_value, warning_value,
1140 _("%s is %lu|%s=%lu;%lu;%lu;;"), 1012 critical_value);
1141 nrms_name,
1142 nrms_value,
1143 nrms_name,
1144 nrms_value,
1145 warning_value,
1146 critical_value);
1147 } 1013 }
1148 1014
1149 } else if (vars_to_check==NSS1) { 1015 } else if (vars_to_check == NSS1) {
1150 1016
1151 xasprintf (&send_buffer,"NSS1:%s\r\n",nss1_name); 1017 xasprintf(&send_buffer, "NSS1:%s\r\n", nss1_name);
1152 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));
1153 if (result!=STATE_OK) 1019 if (result != STATE_OK)
1154 return result; 1020 return result;
1155 1021
1156 if (!strcmp(recv_buffer,"-1\n")) { 1022 if (!strcmp(recv_buffer, "-1\n")) {
1157 xasprintf (&output_message,_("CRITICAL - Value '%s' does not exist!"),nss1_name); 1023 xasprintf(&output_message, _("CRITICAL - Value '%s' does not exist!"), nss1_name);
1158 result=STATE_CRITICAL; 1024 result = STATE_CRITICAL;
1159 } else { 1025 } else {
1160 nss1_value=strtoul(recv_buffer,NULL,10); 1026 nss1_value = strtoul(recv_buffer, NULL, 10);
1161 if (check_critical_value && nss1_value >= critical_value) 1027 if (check_critical_value && nss1_value >= critical_value)
1162 result=STATE_CRITICAL; 1028 result = STATE_CRITICAL;
1163 else if (check_warning_value && nss1_value >= warning_value) 1029 else if (check_warning_value && nss1_value >= warning_value)
1164 result=STATE_WARNING; 1030 result = STATE_WARNING;
1165 xasprintf (&output_message, 1031 xasprintf(&output_message, _("%s is %lu|%s=%lu;%lu;%lu;;"), nss1_name, nss1_value, nss1_name, nss1_value, warning_value,
1166 _("%s is %lu|%s=%lu;%lu;%lu;;"), 1032 critical_value);
1167 nss1_name,
1168 nss1_value,
1169 nss1_name,
1170 nss1_value,
1171 warning_value,
1172 critical_value);
1173 } 1033 }
1174 1034
1175 } else if (vars_to_check==NSS2) { 1035 } else if (vars_to_check == NSS2) {
1176 1036
1177 xasprintf (&send_buffer,"NSS2:%s\r\n",nss2_name); 1037 xasprintf(&send_buffer, "NSS2:%s\r\n", nss2_name);
1178 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));
1179 if (result!=STATE_OK) 1039 if (result != STATE_OK)
1180 return result; 1040 return result;
1181 1041
1182 if (!strcmp(recv_buffer,"-1\n")) { 1042 if (!strcmp(recv_buffer, "-1\n")) {
1183 xasprintf (&output_message,_("CRITICAL - Value '%s' does not exist!"),nss2_name); 1043 xasprintf(&output_message, _("CRITICAL - Value '%s' does not exist!"), nss2_name);
1184 result=STATE_CRITICAL; 1044 result = STATE_CRITICAL;
1185 } else { 1045 } else {
1186 nss2_value=strtoul(recv_buffer,NULL,10); 1046 nss2_value = strtoul(recv_buffer, NULL, 10);
1187 if (check_critical_value && nss2_value >= critical_value) 1047 if (check_critical_value && nss2_value >= critical_value)
1188 result=STATE_CRITICAL; 1048 result = STATE_CRITICAL;
1189 else if (check_warning_value && nss2_value >= warning_value) 1049 else if (check_warning_value && nss2_value >= warning_value)
1190 result=STATE_WARNING; 1050 result = STATE_WARNING;
1191 xasprintf (&output_message, 1051 xasprintf(&output_message, _("%s is %lu|%s=%lu;%lu;%lu;;"), nss2_name, nss2_value, nss2_name, nss2_value, warning_value,
1192 _("%s is %lu|%s=%lu;%lu;%lu;;"), 1052 critical_value);
1193 nss2_name,
1194 nss2_value,
1195 nss2_name,
1196 nss2_value,
1197 warning_value,
1198 critical_value);
1199 } 1053 }
1200 1054
1201 } else if (vars_to_check==NSS3) { 1055 } else if (vars_to_check == NSS3) {
1202 1056
1203 xasprintf (&send_buffer,"NSS3:%s\r\n",nss3_name); 1057 xasprintf(&send_buffer, "NSS3:%s\r\n", nss3_name);
1204 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));
1205 if (result!=STATE_OK) 1059 if (result != STATE_OK)
1206 return result; 1060 return result;
1207 1061
1208 if (!strcmp(recv_buffer,"-1\n")) { 1062 if (!strcmp(recv_buffer, "-1\n")) {
1209 xasprintf (&output_message,_("CRITICAL - Value '%s' does not exist!"),nss3_name); 1063 xasprintf(&output_message, _("CRITICAL - Value '%s' does not exist!"), nss3_name);
1210 result=STATE_CRITICAL; 1064 result = STATE_CRITICAL;
1211 } else { 1065 } else {
1212 nss3_value=strtoul(recv_buffer,NULL,10); 1066 nss3_value = strtoul(recv_buffer, NULL, 10);
1213 if (check_critical_value && nss3_value >= critical_value) 1067 if (check_critical_value && nss3_value >= critical_value)
1214 result=STATE_CRITICAL; 1068 result = STATE_CRITICAL;
1215 else if (check_warning_value && nss3_value >= warning_value) 1069 else if (check_warning_value && nss3_value >= warning_value)
1216 result=STATE_WARNING; 1070 result = STATE_WARNING;
1217 xasprintf (&output_message, 1071 xasprintf(&output_message, _("%s is %lu|%s=%lu;%lu;%lu;;"), nss3_name, nss3_value, nss3_name, nss3_value, warning_value,
1218 _("%s is %lu|%s=%lu;%lu;%lu;;"), 1072 critical_value);
1219 nss3_name,
1220 nss3_value,
1221 nss3_name,
1222 nss3_value,
1223 warning_value,
1224 critical_value);
1225 } 1073 }
1226 1074
1227 } else if (vars_to_check==NSS4) { 1075 } else if (vars_to_check == NSS4) {
1228 1076
1229 xasprintf (&send_buffer,"NSS4:%s\r\n",nss4_name); 1077 xasprintf(&send_buffer, "NSS4:%s\r\n", nss4_name);
1230 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));
1231 if (result!=STATE_OK) 1079 if (result != STATE_OK)
1232 return result; 1080 return result;
1233 1081
1234 if (!strcmp(recv_buffer,"-1\n")) { 1082 if (!strcmp(recv_buffer, "-1\n")) {
1235 xasprintf (&output_message,_("CRITICAL - Value '%s' does not exist!"),nss4_name); 1083 xasprintf(&output_message, _("CRITICAL - Value '%s' does not exist!"), nss4_name);
1236 result=STATE_CRITICAL; 1084 result = STATE_CRITICAL;
1237 } else { 1085 } else {
1238 nss4_value=strtoul(recv_buffer,NULL,10); 1086 nss4_value = strtoul(recv_buffer, NULL, 10);
1239 if (check_critical_value && nss4_value >= critical_value) 1087 if (check_critical_value && nss4_value >= critical_value)
1240 result=STATE_CRITICAL; 1088 result = STATE_CRITICAL;
1241 else if (check_warning_value && nss4_value >= warning_value) 1089 else if (check_warning_value && nss4_value >= warning_value)
1242 result=STATE_WARNING; 1090 result = STATE_WARNING;
1243 xasprintf (&output_message, 1091 xasprintf(&output_message, _("%s is %lu|%s=%lu;%lu;%lu;;"), nss4_name, nss4_value, nss4_name, nss4_value, warning_value,
1244 _("%s is %lu|%s=%lu;%lu;%lu;;"), 1092 critical_value);
1245 nss4_name,
1246 nss4_value,
1247 nss4_name,
1248 nss4_value,
1249 warning_value,
1250 critical_value);
1251 } 1093 }
1252 1094
1253 } else if (vars_to_check==NSS5) { 1095 } else if (vars_to_check == NSS5) {
1254 1096
1255 xasprintf (&send_buffer,"NSS5:%s\r\n",nss5_name); 1097 xasprintf(&send_buffer, "NSS5:%s\r\n", nss5_name);
1256 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));
1257 if (result!=STATE_OK) 1099 if (result != STATE_OK)
1258 return result; 1100 return result;
1259 1101
1260 if (!strcmp(recv_buffer,"-1\n")) { 1102 if (!strcmp(recv_buffer, "-1\n")) {
1261 xasprintf (&output_message,_("CRITICAL - Value '%s' does not exist!"),nss5_name); 1103 xasprintf(&output_message, _("CRITICAL - Value '%s' does not exist!"), nss5_name);
1262 result=STATE_CRITICAL; 1104 result = STATE_CRITICAL;
1263 } else { 1105 } else {
1264 nss5_value=strtoul(recv_buffer,NULL,10); 1106 nss5_value = strtoul(recv_buffer, NULL, 10);
1265 if (check_critical_value && nss5_value >= critical_value) 1107 if (check_critical_value && nss5_value >= critical_value)
1266 result=STATE_CRITICAL; 1108 result = STATE_CRITICAL;
1267 else if (check_warning_value && nss5_value >= warning_value) 1109 else if (check_warning_value && nss5_value >= warning_value)
1268 result=STATE_WARNING; 1110 result = STATE_WARNING;
1269 xasprintf (&output_message, 1111 xasprintf(&output_message, _("%s is %lu|%s=%lu;%lu;%lu;;"), nss5_name, nss5_value, nss5_name, nss5_value, warning_value,
1270 _("%s is %lu|%s=%lu;%lu;%lu;;"), 1112 critical_value);
1271 nss5_name,
1272 nss5_value,
1273 nss5_name,
1274 nss5_value,
1275 warning_value,
1276 critical_value);
1277 } 1113 }
1278 1114
1279 } else if (vars_to_check==NSS6) { 1115 } else if (vars_to_check == NSS6) {
1280 1116
1281 xasprintf (&send_buffer,"NSS6:%s\r\n",nss6_name); 1117 xasprintf(&send_buffer, "NSS6:%s\r\n", nss6_name);
1282 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));
1283 if (result!=STATE_OK) 1119 if (result != STATE_OK)
1284 return result; 1120 return result;
1285 1121
1286 if (!strcmp(recv_buffer,"-1\n")) { 1122 if (!strcmp(recv_buffer, "-1\n")) {
1287 xasprintf (&output_message,_("CRITICAL - Value '%s' does not exist!"),nss6_name); 1123 xasprintf(&output_message, _("CRITICAL - Value '%s' does not exist!"), nss6_name);
1288 result=STATE_CRITICAL; 1124 result = STATE_CRITICAL;
1289 } else { 1125 } else {
1290 nss6_value=strtoul(recv_buffer,NULL,10); 1126 nss6_value = strtoul(recv_buffer, NULL, 10);
1291 if (check_critical_value && nss6_value >= critical_value) 1127 if (check_critical_value && nss6_value >= critical_value)
1292 result=STATE_CRITICAL; 1128 result = STATE_CRITICAL;
1293 else if (check_warning_value && nss6_value >= warning_value) 1129 else if (check_warning_value && nss6_value >= warning_value)
1294 result=STATE_WARNING; 1130 result = STATE_WARNING;
1295 xasprintf (&output_message, 1131 xasprintf(&output_message, _("%s is %lu|%s=%lu;%lu;%lu;;"), nss6_name, nss6_value, nss6_name, nss6_value, warning_value,
1296 _("%s is %lu|%s=%lu;%lu;%lu;;"), 1132 critical_value);
1297 nss6_name,
1298 nss6_value,
1299 nss6_name,
1300 nss6_value,
1301 warning_value,
1302 critical_value);
1303 } 1133 }
1304 1134
1305 } else if (vars_to_check==NSS7) { 1135 } else if (vars_to_check == NSS7) {
1306 1136
1307 xasprintf (&send_buffer,"NSS7:%s\r\n",nss7_name); 1137 xasprintf(&send_buffer, "NSS7:%s\r\n", nss7_name);
1308 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));
1309 if (result!=STATE_OK) 1139 if (result != STATE_OK)
1310 return result; 1140 return result;
1311 1141
1312 if (!strcmp(recv_buffer,"-1\n")) { 1142 if (!strcmp(recv_buffer, "-1\n")) {
1313 xasprintf (&output_message,_("CRITICAL - Value '%s' does not exist!"),nss7_name); 1143 xasprintf(&output_message, _("CRITICAL - Value '%s' does not exist!"), nss7_name);
1314 result=STATE_CRITICAL; 1144 result = STATE_CRITICAL;
1315 } else { 1145 } else {
1316 nss7_value=strtoul(recv_buffer,NULL,10); 1146 nss7_value = strtoul(recv_buffer, NULL, 10);
1317 if (check_critical_value && nss7_value >= critical_value) 1147 if (check_critical_value && nss7_value >= critical_value)
1318 result=STATE_CRITICAL; 1148 result = STATE_CRITICAL;
1319 else if (check_warning_value && nss7_value >= warning_value) 1149 else if (check_warning_value && nss7_value >= warning_value)
1320 result=STATE_WARNING; 1150 result = STATE_WARNING;
1321 xasprintf (&output_message, 1151 xasprintf(&output_message, _("%s is %lu|%s=%lu;%lu;%lu;;"), nss7_name, nss7_value, nss7_name, nss7_value, warning_value,
1322 _("%s is %lu|%s=%lu;%lu;%lu;;"), 1152 critical_value);
1323 nss7_name,
1324 nss7_value,
1325 nss7_name,
1326 nss7_value,
1327 warning_value,
1328 critical_value);
1329 } 1153 }
1330 1154
1155 } else {
1331 1156
1332} 1157 output_message = strdup(_("Nothing to check!\n"));
1333 else { 1158 result = STATE_UNKNOWN;
1334
1335 output_message = strdup (_("Nothing to check!\n"));
1336 result=STATE_UNKNOWN;
1337
1338 } 1159 }
1339 1160
1340 close (sd); 1161 close(sd);
1341 1162
1342 /* reset timeout */ 1163 /* reset timeout */
1343 alarm(0); 1164 alarm(0);
1344 1165
1345 printf("%s%s\n",netware_version,output_message); 1166 printf("%s%s\n", netware_version, output_message);
1346 1167
1347 return result; 1168 return result;
1348} 1169}
1349 1170
1350
1351
1352/* process command-line arguments */ 1171/* process command-line arguments */
1353int process_arguments(int argc, char **argv) { 1172int process_arguments(int argc, char **argv) {
1354 int c; 1173 int c;
1355 1174
1356 int option = 0; 1175 int option = 0;
1357 static struct option longopts[] = 1176 static struct option longopts[] = {{"port", required_argument, 0, 'p'}, {"timeout", required_argument, 0, 't'},
1358 { 1177 {"critical", required_argument, 0, 'c'}, {"warning", required_argument, 0, 'w'},
1359 {"port", required_argument,0,'p'}, 1178 {"variable", required_argument, 0, 'v'}, {"hostname", required_argument, 0, 'H'},
1360 {"timeout", required_argument,0,'t'}, 1179 {"osversion", no_argument, 0, 'o'}, {"version", no_argument, 0, 'V'},
1361 {"critical", required_argument,0,'c'}, 1180 {"help", no_argument, 0, 'h'}, {0, 0, 0, 0}};
1362 {"warning", required_argument,0,'w'},
1363 {"variable", required_argument,0,'v'},
1364 {"hostname", required_argument,0,'H'},
1365 {"osversion",no_argument, 0,'o'},
1366 {"version", no_argument, 0,'V'},
1367 {"help", no_argument, 0,'h'},
1368 {0,0,0,0}
1369 };
1370 1181
1371 /* no options were supplied */ 1182 /* no options were supplied */
1372 if (argc<2) return ERROR; 1183 if (argc < 2)
1184 return ERROR;
1373 1185
1374 /* backwards compatibility */ 1186 /* backwards compatibility */
1375 if (! is_option(argv[1])) { 1187 if (!is_option(argv[1])) {
1376 server_address=argv[1]; 1188 server_address = argv[1];
1377 argv[1]=argv[0]; 1189 argv[1] = argv[0];
1378 argv=&argv[1]; 1190 argv = &argv[1];
1379 argc--; 1191 argc--;
1380 } 1192 }
1381 1193
1382 for (c=1;c<argc;c++) { 1194 for (c = 1; c < argc; c++) {
1383 if (strcmp("-to",argv[c])==0) 1195 if (strcmp("-to", argv[c]) == 0)
1384 strcpy(argv[c],"-t"); 1196 strcpy(argv[c], "-t");
1385 else if (strcmp("-wv",argv[c])==0) 1197 else if (strcmp("-wv", argv[c]) == 0)
1386 strcpy(argv[c],"-w"); 1198 strcpy(argv[c], "-w");
1387 else if (strcmp("-cv",argv[c])==0) 1199 else if (strcmp("-cv", argv[c]) == 0)
1388 strcpy(argv[c],"-c"); 1200 strcpy(argv[c], "-c");
1389 } 1201 }
1390 1202
1391 while (1) { 1203 while (1) {
1392 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);
1393 1205
1394 if (c==-1||c==EOF||c==1) 1206 if (c == -1 || c == EOF || c == 1)
1395 break; 1207 break;
1396 1208
1397 switch (c) 1209 switch (c) {
1398 { 1210 case '?': /* print short usage statement if args not parsable */
1399 case '?': /* print short usage statement if args not parsable */ 1211 usage5();
1400 usage5 (); 1212 case 'h': /* help */
1401 case 'h': /* help */ 1213 print_help();
1402 print_help(); 1214 exit(STATE_UNKNOWN);
1403 exit(STATE_UNKNOWN); 1215 case 'V': /* version */
1404 case 'V': /* version */ 1216 print_revision(progname, NP_VERSION);
1405 print_revision(progname, NP_VERSION); 1217 exit(STATE_UNKNOWN);
1406 exit(STATE_UNKNOWN); 1218 case 'H': /* hostname */
1407 case 'H': /* hostname */ 1219 server_address = optarg;
1408 server_address=optarg; 1220 break;
1409 break; 1221 case 'o': /* display nos version */
1410 case 'o': /* display nos version */ 1222 check_netware_version = true;
1411 check_netware_version = true; 1223 break;
1412 break; 1224 case 'p': /* port */
1413 case 'p': /* port */ 1225 if (is_intnonneg(optarg))
1414 if (is_intnonneg(optarg)) 1226 server_port = atoi(optarg);
1415 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);
1416 else 1284 else
1417 die(STATE_UNKNOWN,_("Server port an integer\n")); 1285 sap_number = -1;
1418 break; 1286 } else if (!strcmp(optarg, "OFILES"))
1419 case 'v': 1287 vars_to_check = OFILES;
1420 if (strlen(optarg)<3) 1288 else if (strncmp(optarg, "VKP", 3) == 0) {
1421 return ERROR; 1289 vars_to_check = VKP;
1422 if (!strcmp(optarg,"LOAD1")) 1290 volume_name = strdup(optarg + 3);
1423 vars_to_check=LOAD1; 1291 if (!strcmp(volume_name, ""))
1424 else if (!strcmp(optarg,"LOAD5")) 1292 volume_name = strdup("SYS");
1425 vars_to_check=LOAD5; 1293 } else if (strncmp(optarg, "VMP", 3) == 0) {
1426 else if (!strcmp(optarg,"LOAD15")) 1294 vars_to_check = VMP;
1427 vars_to_check=LOAD15; 1295 volume_name = strdup(optarg + 3);
1428 else if (!strcmp(optarg,"CONNS")) 1296 if (!strcmp(volume_name, ""))
1429 vars_to_check=CONNS; 1297 volume_name = strdup("SYS");
1430 else if (!strcmp(optarg,"LTCH")) 1298 } else if (strncmp(optarg, "VMU", 3) == 0) {
1431 vars_to_check=LTCH; 1299 vars_to_check = VMU;
1432 else if (!strcmp(optarg,"DCB")) 1300 volume_name = strdup(optarg + 3);
1433 vars_to_check=DCB; 1301 if (!strcmp(volume_name, ""))
1434 else if (!strcmp(optarg,"TCB")) 1302 volume_name = strdup("SYS");
1435 vars_to_check=TCB; 1303 } else if (strncmp(optarg, "VPU", 3) == 0) {
1436 else if (!strcmp(optarg,"CBUFF")) 1304 vars_to_check = VPU;
1437 vars_to_check=CBUFF; 1305 volume_name = strdup(optarg + 3);
1438 else if (!strcmp(optarg,"CDBUFF")) 1306 if (!strcmp(volume_name, ""))
1439 vars_to_check=CDBUFF; 1307 volume_name = strdup("SYS");
1440 else if (!strcmp(optarg,"LRUM")) 1308 } else if (strncmp(optarg, "VPP", 3) == 0) {
1441 vars_to_check=LRUM; 1309 vars_to_check = VPP;
1442 else if (!strcmp(optarg,"LRUS")) 1310 volume_name = strdup(optarg + 3);
1443 vars_to_check=LRUS; 1311 if (!strcmp(volume_name, ""))
1444 else if (strncmp(optarg,"VPF",3)==0) { 1312 volume_name = strdup("SYS");
1445 vars_to_check=VPF; 1313 } else if (strncmp(optarg, "VKNP", 4) == 0) {
1446 volume_name = strdup (optarg+3); 1314 vars_to_check = VKNP;
1447 if (!strcmp(volume_name,"")) 1315 volume_name = strdup(optarg + 4);
1448 volume_name = strdup ("SYS"); 1316 if (!strcmp(volume_name, ""))
1449 } 1317 volume_name = strdup("SYS");
1450 else if (strncmp(optarg,"VKF",3)==0) { 1318 } else if (strncmp(optarg, "VPNP", 4) == 0) {
1451 vars_to_check=VKF; 1319 vars_to_check = VPNP;
1452 volume_name = strdup (optarg+3); 1320 volume_name = strdup(optarg + 4);
1453 if (!strcmp(volume_name,"")) 1321 if (!strcmp(volume_name, ""))
1454 volume_name = strdup ("SYS"); 1322 volume_name = strdup("SYS");
1455 } 1323 } else if (!strcmp(optarg, "ABENDS"))
1456 else if (strncmp(optarg,"VMF",3)==0) { 1324 vars_to_check = ABENDS;
1457 vars_to_check=VMF; 1325 else if (!strcmp(optarg, "CSPROCS"))
1458 volume_name = strdup (optarg+3); 1326 vars_to_check = CSPROCS;
1459 if (!strcmp(volume_name,"")) 1327 else if (!strcmp(optarg, "TSYNC"))
1460 volume_name = strdup ("SYS"); 1328 vars_to_check = TSYNC;
1461 } 1329 else if (!strcmp(optarg, "DSVER"))
1462 else if (!strcmp(optarg,"DSDB")) 1330 vars_to_check = DSVER;
1463 vars_to_check=DSDB; 1331 else if (!strcmp(optarg, "UPTIME")) {
1464 else if (!strcmp(optarg,"LOGINS")) 1332 vars_to_check = UPTIME;
1465 vars_to_check=LOGINS; 1333 } else if (strncmp(optarg, "NLM:", 4) == 0) {
1466 else if (!strcmp(optarg,"NRMH")) 1334 vars_to_check = NLM;
1467 vars_to_check=NRMH; 1335 nlm_name = strdup(optarg + 4);
1468 else if (!strcmp(optarg,"UPRB")) 1336 } else if (strncmp(optarg, "NRMP", 4) == 0) {
1469 vars_to_check=UPRB; 1337 vars_to_check = NRMP;
1470 else if (!strcmp(optarg,"PUPRB")) 1338 nrmp_name = strdup(optarg + 4);
1471 vars_to_check=PUPRB; 1339 if (!strcmp(nrmp_name, ""))
1472 else if (!strncmp(optarg,"SAPENTRIES",10)) { 1340 nrmp_name = strdup("AVAILABLE_MEMORY");
1473 vars_to_check=SAPENTRIES; 1341 } else if (strncmp(optarg, "NRMM", 4) == 0) {
1474 if (strlen(optarg)>10) 1342 vars_to_check = NRMM;
1475 sap_number=atoi(optarg+10); 1343 nrmm_name = strdup(optarg + 4);
1476 else 1344 if (!strcmp(nrmm_name, ""))
1477 sap_number=-1; 1345 nrmm_name = strdup("AVAILABLE_CACHE_MEMORY");
1478 }
1479 else if (!strcmp(optarg,"OFILES"))
1480 vars_to_check=OFILES;
1481 else if (strncmp(optarg,"VKP",3)==0) {
1482 vars_to_check=VKP;
1483 volume_name = strdup (optarg+3);
1484 if (!strcmp(volume_name,""))
1485 volume_name = strdup ("SYS");
1486 }
1487 else if (strncmp(optarg,"VMP",3)==0) {
1488 vars_to_check=VMP;
1489 volume_name = strdup (optarg+3);
1490 if (!strcmp(volume_name,""))
1491 volume_name = strdup ("SYS");
1492 }
1493 else if (strncmp(optarg,"VMU",3)==0) {
1494 vars_to_check=VMU;
1495 volume_name = strdup (optarg+3);
1496 if (!strcmp(volume_name,""))
1497 volume_name = strdup ("SYS");
1498 }
1499 else if (strncmp(optarg,"VPU",3)==0) {
1500 vars_to_check=VPU;
1501 volume_name = strdup (optarg+3);
1502 if (!strcmp(volume_name,""))
1503 volume_name = strdup ("SYS");
1504 }
1505 else if (strncmp(optarg,"VPP",3)==0) {
1506 vars_to_check=VPP;
1507 volume_name = strdup (optarg+3);
1508 if (!strcmp(volume_name,""))
1509 volume_name = strdup ("SYS");
1510 }
1511 else if (strncmp(optarg,"VKNP",4)==0) {
1512 vars_to_check=VKNP;
1513 volume_name = strdup (optarg+4);
1514 if (!strcmp(volume_name,""))
1515 volume_name = strdup ("SYS");
1516 }
1517 else if (strncmp(optarg,"VPNP",4)==0) {
1518 vars_to_check=VPNP;
1519 volume_name = strdup (optarg+4);
1520 if (!strcmp(volume_name,""))
1521 volume_name = strdup("SYS");
1522 }
1523 else if (!strcmp(optarg,"ABENDS"))
1524 vars_to_check=ABENDS;
1525 else if (!strcmp(optarg,"CSPROCS"))
1526 vars_to_check=CSPROCS;
1527 else if (!strcmp(optarg,"TSYNC"))
1528 vars_to_check=TSYNC;
1529 else if (!strcmp(optarg,"DSVER"))
1530 vars_to_check=DSVER;
1531 else if (!strcmp(optarg,"UPTIME")) {
1532 vars_to_check=UPTIME;
1533 }
1534 else if (strncmp(optarg,"NLM:",4)==0) {
1535 vars_to_check=NLM;
1536 nlm_name=strdup (optarg+4);
1537 }
1538 else if (strncmp(optarg,"NRMP",4)==0) {
1539 vars_to_check=NRMP;
1540 nrmp_name = strdup (optarg+4);
1541 if (!strcmp(nrmp_name,""))
1542 nrmp_name = strdup ("AVAILABLE_MEMORY");
1543 }
1544 else if (strncmp(optarg,"NRMM",4)==0) {
1545 vars_to_check=NRMM;
1546 nrmm_name = strdup (optarg+4);
1547 if (!strcmp(nrmm_name,""))
1548 nrmm_name = strdup ("AVAILABLE_CACHE_MEMORY");
1549
1550 }
1551
1552 else if (strncmp(optarg,"NRMS",4)==0) {
1553 vars_to_check=NRMS;
1554 nrms_name = strdup (optarg+4);
1555 if (!strcmp(nrms_name,""))
1556 nrms_name = strdup ("USED_SWAP_SPACE");
1557
1558 }
1559
1560 else if (strncmp(optarg,"NSS1",4)==0) {
1561 vars_to_check=NSS1;
1562 nss1_name = strdup (optarg+4);
1563 if (!strcmp(nss1_name,""))
1564 nss1_name = strdup ("CURRENTBUFFERCACHESIZE");
1565
1566 }
1567
1568 else if (strncmp(optarg,"NSS2",4)==0) {
1569 vars_to_check=NSS2;
1570 nss2_name = strdup (optarg+4);
1571 if (!strcmp(nss2_name,""))
1572 nss2_name = strdup ("CACHEHITS");
1573
1574 }
1575
1576 else if (strncmp(optarg,"NSS3",4)==0) {
1577 vars_to_check=NSS3;
1578 nss3_name = strdup (optarg+4);
1579 if (!strcmp(nss3_name,""))
1580 nss3_name = strdup ("CACHEGITPERCENT");
1581
1582 }
1583
1584 else if (strncmp(optarg,"NSS4",4)==0) {
1585 vars_to_check=NSS4;
1586 nss4_name = strdup (optarg+4);
1587 if (!strcmp(nss4_name,""))
1588 nss4_name = strdup ("CURRENTOPENCOUNT");
1589
1590 }
1591
1592 else if (strncmp(optarg,"NSS5",4)==0) {
1593 vars_to_check=NSS5;
1594 nss5_name = strdup (optarg+4);
1595 if (!strcmp(nss5_name,""))
1596 nss5_name = strdup ("CACHEMISSES");
1597
1598 }
1599
1600
1601 else if (strncmp(optarg,"NSS6",4)==0) {
1602 vars_to_check=NSS6;
1603 nss6_name = strdup (optarg+4);
1604 if (!strcmp(nss6_name,""))
1605 nss6_name = strdup ("PENDINGWORKSCOUNT");
1606
1607 }
1608
1609
1610 else if (strncmp(optarg,"NSS7",4)==0) {
1611 vars_to_check=NSS7;
1612 nss7_name = strdup (optarg+4);
1613 if (!strcmp(nss7_name,""))
1614 nss7_name = strdup ("CACHESIZE");
1615
1616 }
1617 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");
1618 1354
1619 else
1620 return ERROR;
1621 break;
1622 case 'w': /* warning threshold */
1623 warning_value=strtoul(optarg,NULL,10);
1624 check_warning_value = true;
1625 break;
1626 case 'c': /* critical threshold */
1627 critical_value=strtoul(optarg,NULL,10);
1628 check_critical_value = true;
1629 break;
1630 case 't': /* timeout */
1631 socket_timeout=atoi(optarg);
1632 if (socket_timeout<=0)
1633 return ERROR;
1634 } 1355 }
1635 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");
1362
1363 }
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 }
1636 } 1429 }
1637 1430
1638 return OK; 1431 return OK;
1639} 1432}
1640 1433
1641 1434void print_help(void) {
1642
1643void print_help(void)
1644{
1645 char *myport; 1435 char *myport;
1646 xasprintf (&myport, "%d", PORT); 1436 xasprintf(&myport, "%d", PORT);
1647 1437
1648 print_revision (progname, NP_VERSION); 1438 print_revision(progname, NP_VERSION);
1649 1439
1650 printf ("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n"); 1440 printf("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n");
1651 printf (COPYRIGHT, copyright, email); 1441 printf(COPYRIGHT, copyright, email);
1652 1442
1653 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"));
1654 printf ("%s\n", _("Novell server to gather the requested system information.")); 1444 printf("%s\n", _("Novell server to gather the requested system information."));
1655 1445
1656 printf ("\n\n"); 1446 printf("\n\n");
1657 1447
1658 print_usage(); 1448 print_usage();
1659 1449
1660 printf (UT_HELP_VRSN); 1450 printf(UT_HELP_VRSN);
1661 printf (UT_EXTRA_OPTS); 1451 printf(UT_EXTRA_OPTS);
1662 1452
1663 printf (UT_HOST_PORT, 'p', myport); 1453 printf(UT_HOST_PORT, 'p', myport);
1664 1454
1665 printf (" %s\n", "-v, --variable=STRING"); 1455 printf(" %s\n", "-v, --variable=STRING");
1666 printf (" %s\n", _("Variable to check. Valid variables include:")); 1456 printf(" %s\n", _("Variable to check. Valid variables include:"));
1667 printf (" %s\n", _("LOAD1 = 1 minute average CPU load")); 1457 printf(" %s\n", _("LOAD1 = 1 minute average CPU load"));
1668 printf (" %s\n", _("LOAD5 = 5 minute average CPU load")); 1458 printf(" %s\n", _("LOAD5 = 5 minute average CPU load"));
1669 printf (" %s\n", _("LOAD15 = 15 minute average CPU load")); 1459 printf(" %s\n", _("LOAD15 = 15 minute average CPU load"));
1670 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)"));
1671 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)"));
1672 printf (" %s\n", _("UPTIME = server uptime")); 1462 printf(" %s\n", _("UPTIME = server uptime"));
1673 printf (" %s\n", _("LTCH = percent long term cache hits")); 1463 printf(" %s\n", _("LTCH = percent long term cache hits"));
1674 printf (" %s\n", _("CBUFF = current number of cache buffers")); 1464 printf(" %s\n", _("CBUFF = current number of cache buffers"));
1675 printf (" %s\n", _("CDBUFF = current number of dirty cache buffers")); 1465 printf(" %s\n", _("CDBUFF = current number of dirty cache buffers"));
1676 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"));
1677 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"));
1678 printf (" %s\n", _("OFILES = number of open files")); 1468 printf(" %s\n", _("OFILES = number of open files"));
1679 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>"));
1680 printf (" %s\n", _(" VMU<vol> = MB used space on Volume <vol>")); 1470 printf(" %s\n", _(" VMU<vol> = MB used space on Volume <vol>"));
1681 printf (" %s\n", _(" VPU<vol> = percent used space on Volume <vol>")); 1471 printf(" %s\n", _(" VPU<vol> = percent used space on Volume <vol>"));
1682 printf (" %s\n", _(" VMP<vol> = MB of purgeable space on Volume <vol>")); 1472 printf(" %s\n", _(" VMP<vol> = MB of purgeable space on Volume <vol>"));
1683 printf (" %s\n", _(" VPF<vol> = percent free space on volume <vol>")); 1473 printf(" %s\n", _(" VPF<vol> = percent free space on volume <vol>"));
1684 printf (" %s\n", _(" VKF<vol> = KB of free space on volume <vol>")); 1474 printf(" %s\n", _(" VKF<vol> = KB of free space on volume <vol>"));
1685 printf (" %s\n", _(" VPP<vol> = percent purgeable space on volume <vol>")); 1475 printf(" %s\n", _(" VPP<vol> = percent purgeable space on volume <vol>"));
1686 printf (" %s\n", _(" VKP<vol> = KB of purgeable space on volume <vol>")); 1476 printf(" %s\n", _(" VKP<vol> = KB of purgeable space on volume <vol>"));
1687 printf (" %s\n", _(" VPNP<vol> = percent not yet purgeable space on volume <vol>")); 1477 printf(" %s\n", _(" VPNP<vol> = percent not yet purgeable space on volume <vol>"));
1688 printf (" %s\n", _(" VKNP<vol> = KB of not yet purgeable space on volume <vol>")); 1478 printf(" %s\n", _(" VKNP<vol> = KB of not yet purgeable space on volume <vol>"));
1689 printf (" %s\n", _(" LRUM = LRU sitting time in minutes")); 1479 printf(" %s\n", _(" LRUM = LRU sitting time in minutes"));
1690 printf (" %s\n", _(" LRUS = LRU sitting time in seconds")); 1480 printf(" %s\n", _(" LRUS = LRU sitting time in seconds"));
1691 printf (" %s\n", _(" DSDB = check to see if DS Database is open")); 1481 printf(" %s\n", _(" DSDB = check to see if DS Database is open"));
1692 printf (" %s\n", _(" DSVER = NDS version")); 1482 printf(" %s\n", _(" DSVER = NDS version"));
1693 printf (" %s\n", _(" UPRB = used packet receive buffers")); 1483 printf(" %s\n", _(" UPRB = used packet receive buffers"));
1694 printf (" %s\n", _(" PUPRB = percent (of max) used packet receive buffers")); 1484 printf(" %s\n", _(" PUPRB = percent (of max) used packet receive buffers"));
1695 printf (" %s\n", _(" SAPENTRIES = number of entries in the SAP table")); 1485 printf(" %s\n", _(" SAPENTRIES = number of entries in the SAP table"));
1696 printf (" %s\n", _(" SAPENTRIES<n> = number of entries in the SAP table for SAP type <n>")); 1486 printf(" %s\n", _(" SAPENTRIES<n> = number of entries in the SAP table for SAP type <n>"));
1697 printf (" %s\n", _(" TSYNC = timesync status")); 1487 printf(" %s\n", _(" TSYNC = timesync status"));
1698 printf (" %s\n", _(" LOGINS = check to see if logins are enabled")); 1488 printf(" %s\n", _(" LOGINS = check to see if logins are enabled"));
1699 printf (" %s\n", _(" CONNS = number of currently licensed connections")); 1489 printf(" %s\n", _(" CONNS = number of currently licensed connections"));
1700 printf (" %s\n", _(" NRMH = NRM Summary Status")); 1490 printf(" %s\n", _(" NRMH = NRM Summary Status"));
1701 printf (" %s\n", _(" NRMP<stat> = Returns the current value for a NRM health item")); 1491 printf(" %s\n", _(" NRMP<stat> = Returns the current value for a NRM health item"));
1702 printf (" %s\n", _(" NRMM<stat> = Returns the current memory stats from NRM")); 1492 printf(" %s\n", _(" NRMM<stat> = Returns the current memory stats from NRM"));
1703 printf (" %s\n", _(" NRMS<stat> = Returns the current Swapfile stats from NRM")); 1493 printf(" %s\n", _(" NRMS<stat> = Returns the current Swapfile stats from NRM"));
1704 printf (" %s\n", _(" NSS1<stat> = Statistics from _Admin:Manage_NSS\\GeneralStats.xml")); 1494 printf(" %s\n", _(" NSS1<stat> = Statistics from _Admin:Manage_NSS\\GeneralStats.xml"));
1705 printf (" %s\n", _(" NSS3<stat> = Statistics from _Admin:Manage_NSS\\NameCache.xml")); 1495 printf(" %s\n", _(" NSS3<stat> = Statistics from _Admin:Manage_NSS\\NameCache.xml"));
1706 printf (" %s\n", _(" NSS4<stat> = Statistics from _Admin:Manage_NSS\\FileStats.xml")); 1496 printf(" %s\n", _(" NSS4<stat> = Statistics from _Admin:Manage_NSS\\FileStats.xml"));
1707 printf (" %s\n", _(" NSS5<stat> = Statistics from _Admin:Manage_NSS\\ObjectCache.xml")); 1497 printf(" %s\n", _(" NSS5<stat> = Statistics from _Admin:Manage_NSS\\ObjectCache.xml"));
1708 printf (" %s\n", _(" NSS6<stat> = Statistics from _Admin:Manage_NSS\\Thread.xml")); 1498 printf(" %s\n", _(" NSS6<stat> = Statistics from _Admin:Manage_NSS\\Thread.xml"));
1709 printf (" %s\n", _(" NSS7<stat> = Statistics from _Admin:Manage_NSS\\AuthorizationCache.xml")); 1499 printf(" %s\n", _(" NSS7<stat> = Statistics from _Admin:Manage_NSS\\AuthorizationCache.xml"));
1710 printf (" %s\n", _(" NLM:<nlm> = check if NLM is loaded and report version")); 1500 printf(" %s\n", _(" NLM:<nlm> = check if NLM is loaded and report version"));
1711 printf (" %s\n", _(" (e.g. NLM:TSANDS.NLM)")); 1501 printf(" %s\n", _(" (e.g. NLM:TSANDS.NLM)"));
1712 printf ("\n"); 1502 printf("\n");
1713 printf (" %s\n", "-w, --warning=INTEGER"); 1503 printf(" %s\n", "-w, --warning=INTEGER");
1714 printf (" %s\n", _("Threshold which will result in a warning status")); 1504 printf(" %s\n", _("Threshold which will result in a warning status"));
1715 printf (" %s\n", "-c, --critical=INTEGER"); 1505 printf(" %s\n", "-c, --critical=INTEGER");
1716 printf (" %s\n", _("Threshold which will result in a critical status")); 1506 printf(" %s\n", _("Threshold which will result in a critical status"));
1717 printf (" %s\n", "-o, --osversion"); 1507 printf(" %s\n", "-o, --osversion");
1718 printf (" %s\n", _("Include server version string in results")); 1508 printf(" %s\n", _("Include server version string in results"));
1719 1509
1720 printf (UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); 1510 printf(UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
1721 1511
1722 printf ("\n"); 1512 printf("\n");
1723 printf ("%s\n", _("Notes:")); 1513 printf("%s\n", _("Notes:"));
1724 printf (" %s\n", _("- This plugin requires that the MRTGEXT.NLM file from James Drews' MRTG")); 1514 printf(" %s\n", _("- This plugin requires that the MRTGEXT.NLM file from James Drews' MRTG"));
1725 printf (" %s\n", _(" extension for NetWare be loaded on the Novell servers you wish to check.")); 1515 printf(" %s\n", _(" extension for NetWare be loaded on the Novell servers you wish to check."));
1726 printf (" %s\n", _(" (available from http://www.engr.wisc.edu/~drews/mrtg/)")); 1516 printf(" %s\n", _(" (available from http://www.engr.wisc.edu/~drews/mrtg/)"));
1727 printf (" %s\n", _("- Values for critical thresholds should be lower than warning thresholds")); 1517 printf(" %s\n", _("- Values for critical thresholds should be lower than warning thresholds"));
1728 printf (" %s\n", _(" when the following variables are checked: VPF, VKF, LTCH, CBUFF, DCB, ")); 1518 printf(" %s\n", _(" when the following variables are checked: VPF, VKF, LTCH, CBUFF, DCB, "));
1729 printf (" %s\n", _(" TCB, LRUS and LRUM.")); 1519 printf(" %s\n", _(" TCB, LRUS and LRUM."));
1730 1520
1731 printf (UT_SUPPORT); 1521 printf(UT_SUPPORT);
1732} 1522}
1733 1523
1734 1524void print_usage(void) {
1735 1525 printf("%s\n", _("Usage:"));
1736void print_usage(void) 1526 printf("%s -H host [-p port] [-v variable] [-w warning] [-c critical] [-t timeout]\n", progname);
1737{
1738 printf ("%s\n", _("Usage:"));
1739 printf ("%s -H host [-p port] [-v variable] [-w warning] [-c critical] [-t timeout]\n",progname);
1740} 1527}
diff --git a/plugins/check_overcr.c b/plugins/check_overcr.c
index 5165c82..e80d477 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 94d589e..6613634 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 6e162e6..4aafaf4 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 1fcbd98..5777ba0 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 6b32710..8ed19e5 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 15e035b..369a88b 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 986c3e1..bc17528 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 90a0402..c1d8e2d 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,60 +37,68 @@ 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 58
59#define OID_COUNT_STEP 8 59#define OID_COUNT_STEP 8
60 60
61/* Longopts only arguments */ 61/* Longopts only arguments */
62#define L_CALCULATE_RATE CHAR_MAX+1 62#define L_CALCULATE_RATE CHAR_MAX + 1
63#define L_RATE_MULTIPLIER CHAR_MAX+2 63#define L_RATE_MULTIPLIER CHAR_MAX + 2
64#define L_INVERT_SEARCH CHAR_MAX+3 64#define L_INVERT_SEARCH CHAR_MAX + 3
65#define L_OFFSET CHAR_MAX+4 65#define L_OFFSET CHAR_MAX + 4
66#define L_IGNORE_MIB_PARSING_ERRORS CHAR_MAX+5 66#define L_IGNORE_MIB_PARSING_ERRORS CHAR_MAX + 5
67 67
68/* 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
69 * characters in s */ 69 * characters in s */
70#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 }
71/* Given c, keep track of backslashes (bk) and double-quotes (dq) 74/* Given c, keep track of backslashes (bk) and double-quotes (dq)
72 * from c[0] */ 75 * from c[0] */
73#define COUNT_SEQ(c, bk, dq) switch(c[0]) {\ 76#define COUNT_SEQ(c, bk, dq) \
74 case '\\': \ 77 switch (c[0]) { \
75 if (bk) bk--; \ 78 case '\\': \
76 else bk++; \ 79 if (bk) \
77 break; \ 80 bk--; \
78 case '"': \ 81 else \
79 if (!dq) { dq++; } \ 82 bk++; \
80 else if(!bk) { dq--; } \ 83 break; \
81 else { bk--; } \ 84 case '"': \
82 break; \ 85 if (!dq) { \
86 dq++; \
87 } else if (!bk) { \
88 dq--; \
89 } else { \
90 bk--; \
91 } \
92 break; \
83 } 93 }
84 94
85 95static int process_arguments(int, char **);
86 96static int validate_arguments(void);
87static int process_arguments (int, char **); 97static char *thisarg(char *str);
88static int validate_arguments (void); 98static char *nextarg(char *str);
89static char *thisarg (char *str); 99void print_usage(void);
90static char *nextarg (char *str); 100static void print_help(void);
91void print_usage (void); 101static char *multiply(char *str);
92static void print_help (void);
93static char *multiply (char *str);
94 102
95#include "regex.h" 103#include "regex.h"
96static char regex_expect[MAX_INPUT_BUFFER] = ""; 104static char regex_expect[MAX_INPUT_BUFFER] = "";
@@ -122,7 +130,7 @@ static char *units;
122static char *port; 130static char *port;
123static char *snmpcmd; 131static char *snmpcmd;
124static char string_value[MAX_INPUT_BUFFER] = ""; 132static char string_value[MAX_INPUT_BUFFER] = "";
125static int invert_search=0; 133static int invert_search = 0;
126static char **labels = NULL; 134static char **labels = NULL;
127static char **unitv = NULL; 135static char **unitv = NULL;
128static size_t nlabels = 0; 136static size_t nlabels = 0;
@@ -154,17 +162,18 @@ static state_data *previous_state;
154static double *previous_value; 162static double *previous_value;
155static size_t previous_size = OID_COUNT_STEP; 163static size_t previous_size = OID_COUNT_STEP;
156static int perf_labels = 1; 164static int perf_labels = 1;
157static char* ip_version = ""; 165static char *ip_version = "";
158static double multiplier = 1.0; 166static double multiplier = 1.0;
159static char *fmtstr = ""; 167static char *fmtstr = "";
160static bool fmtstr_set = false; 168static bool fmtstr_set = false;
161static char buffer[DEFAULT_BUFFER_SIZE]; 169static char buffer[DEFAULT_BUFFER_SIZE];
162static bool ignore_mib_parsing_errors = false; 170static bool ignore_mib_parsing_errors = false;
163 171
164static char *fix_snmp_range(char *th) 172static char *fix_snmp_range(char *th) {
165{ 173 double left;
166 double left, right; 174 double right;
167 char *colon, *ret; 175 char *colon;
176 char *ret;
168 177
169 if ((colon = strchr(th, ':')) == NULL || *(colon + 1) == '\0') 178 if ((colon = strchr(th, ':')) == NULL || *(colon + 1) == '\0')
170 return th; 179 return th;
@@ -182,12 +191,12 @@ static char *fix_snmp_range(char *th)
182 return ret; 191 return ret;
183} 192}
184 193
185int 194int main(int argc, char **argv) {
186main (int argc, char **argv) 195 int len;
187{ 196 int total_oids;
188 int len, total_oids;
189 size_t line; 197 size_t line;
190 unsigned int bk_count = 0, dq_count = 0; 198 unsigned int bk_count = 0;
199 unsigned int dq_count = 0;
191 int iresult = STATE_UNKNOWN; 200 int iresult = STATE_UNKNOWN;
192 int result = STATE_UNKNOWN; 201 int result = STATE_UNKNOWN;
193 int return_code = 0; 202 int return_code = 0;
@@ -200,80 +209,83 @@ main (int argc, char **argv)
200 char *outbuff; 209 char *outbuff;
201 char *ptr = NULL; 210 char *ptr = NULL;
202 char *show = NULL; 211 char *show = NULL;
203 char *th_warn=NULL; 212 char *th_warn = NULL;
204 char *th_crit=NULL; 213 char *th_crit = NULL;
205 char type[8] = ""; 214 char type[8] = "";
206 output chld_out, chld_err; 215 output chld_out;
207 char *previous_string=NULL; 216 output chld_err;
208 char *ap=NULL; 217 char *previous_string = NULL;
209 char *state_string=NULL; 218 char *ap = NULL;
210 size_t response_length, current_length, string_length; 219 char *state_string = NULL;
211 char *temp_string=NULL; 220 size_t response_length;
212 char *quote_string=NULL; 221 size_t current_length;
222 size_t string_length;
223 char *temp_string = NULL;
224 char *quote_string = NULL;
213 time_t current_time; 225 time_t current_time;
214 double temp_double; 226 double temp_double;
215 time_t duration; 227 time_t duration;
216 char *conv = "12345678"; 228 char *conv = "12345678";
217 int is_counter=0; 229 int is_counter = 0;
218 230
219 setlocale (LC_ALL, ""); 231 setlocale(LC_ALL, "");
220 bindtextdomain (PACKAGE, LOCALEDIR); 232 bindtextdomain(PACKAGE, LOCALEDIR);
221 textdomain (PACKAGE); 233 textdomain(PACKAGE);
222 234
223 labels = malloc (labels_size * sizeof(*labels)); 235 labels = malloc(labels_size * sizeof(*labels));
224 unitv = malloc (unitv_size * sizeof(*unitv)); 236 unitv = malloc(unitv_size * sizeof(*unitv));
225 thlds = malloc (thlds_size * sizeof(*thlds)); 237 thlds = malloc(thlds_size * sizeof(*thlds));
226 response_value = malloc (response_size * sizeof(*response_value)); 238 response_value = malloc(response_size * sizeof(*response_value));
227 previous_value = malloc (previous_size * sizeof(*previous_value)); 239 previous_value = malloc(previous_size * sizeof(*previous_value));
228 eval_method = calloc (eval_size, sizeof(*eval_method)); 240 eval_method = calloc(eval_size, sizeof(*eval_method));
229 oids = calloc(oids_size, sizeof (char *)); 241 oids = calloc(oids_size, sizeof(char *));
230 242
231 label = strdup ("SNMP"); 243 label = strdup("SNMP");
232 units = strdup (""); 244 units = strdup("");
233 port = strdup (DEFAULT_PORT); 245 port = strdup(DEFAULT_PORT);
234 outbuff = strdup (""); 246 outbuff = strdup("");
235 delimiter = strdup (" = "); 247 delimiter = strdup(" = ");
236 output_delim = strdup (DEFAULT_OUTPUT_DELIMITER); 248 output_delim = strdup(DEFAULT_OUTPUT_DELIMITER);
237 timeout_interval = DEFAULT_SOCKET_TIMEOUT; 249 timeout_interval = DEFAULT_SOCKET_TIMEOUT;
238 retries = DEFAULT_RETRIES; 250 retries = DEFAULT_RETRIES;
239 251
240 np_init( (char *) progname, argc, argv ); 252 np_init((char *)progname, argc, argv);
241 253
242 /* Parse extra opts if any */ 254 /* Parse extra opts if any */
243 argv=np_extra_opts (&argc, argv, progname); 255 argv = np_extra_opts(&argc, argv, progname);
244 256
245 np_set_args(argc, argv); 257 np_set_args(argc, argv);
246 258
247 time(&current_time); 259 time(&current_time);
248 260
249 if (process_arguments (argc, argv) == ERROR) 261 if (process_arguments(argc, argv) == ERROR)
250 usage4 (_("Could not parse arguments")); 262 usage4(_("Could not parse arguments"));
251 263
252 if(calculate_rate) { 264 if (calculate_rate) {
253 if (!strcmp(label, "SNMP")) 265 if (!strcmp(label, "SNMP"))
254 label = strdup("SNMP RATE"); 266 label = strdup("SNMP RATE");
255 267
256 size_t i = 0; 268 size_t i = 0;
257 269
258 previous_state = np_state_read(); 270 previous_state = np_state_read();
259 if(previous_state!=NULL) { 271 if (previous_state != NULL) {
260 /* Split colon separated values */ 272 /* Split colon separated values */
261 previous_string = strdup((char *) previous_state->data); 273 previous_string = strdup((char *)previous_state->data);
262 while((ap = strsep(&previous_string, ":")) != NULL) { 274 while ((ap = strsep(&previous_string, ":")) != NULL) {
263 if(verbose>2) 275 if (verbose > 2)
264 printf("State for %zd=%s\n", i, ap); 276 printf("State for %zd=%s\n", i, ap);
265 while (i >= previous_size) { 277 while (i >= previous_size) {
266 previous_size += OID_COUNT_STEP; 278 previous_size += OID_COUNT_STEP;
267 previous_value = realloc(previous_value, previous_size * sizeof(*previous_value)); 279 previous_value = realloc(previous_value, previous_size * sizeof(*previous_value));
268 } 280 }
269 previous_value[i++]=strtod(ap,NULL); 281 previous_value[i++] = strtod(ap, NULL);
270 } 282 }
271 } 283 }
272 } 284 }
273 285
274 /* Populate the thresholds */ 286 /* Populate the thresholds */
275 th_warn=warning_thresholds; 287 th_warn = warning_thresholds;
276 th_crit=critical_thresholds; 288 th_crit = critical_thresholds;
277 for (size_t i = 0; i < numoids; i++) { 289 for (size_t i = 0; i < numoids; i++) {
278 char *w = th_warn ? strndup(th_warn, strcspn(th_warn, ",")) : NULL; 290 char *w = th_warn ? strndup(th_warn, strcspn(th_warn, ",")) : NULL;
279 char *c = th_crit ? strndup(th_crit, strcspn(th_crit, ",")) : NULL; 291 char *c = th_crit ? strndup(th_crit, strcspn(th_crit, ",")) : NULL;
@@ -287,53 +299,52 @@ main (int argc, char **argv)
287 } 299 }
288 300
289 /* Skip empty thresholds, while avoiding segfault */ 301 /* Skip empty thresholds, while avoiding segfault */
290 set_thresholds(&thlds[i], 302 set_thresholds(&thlds[i], w ? strpbrk(w, NP_THRESHOLDS_CHARS) : NULL, c ? strpbrk(c, NP_THRESHOLDS_CHARS) : NULL);
291 w ? strpbrk(w, NP_THRESHOLDS_CHARS) : NULL,
292 c ? strpbrk(c, NP_THRESHOLDS_CHARS) : NULL);
293 if (w) { 303 if (w) {
294 th_warn=strchr(th_warn, ','); 304 th_warn = strchr(th_warn, ',');
295 if (th_warn) th_warn++; 305 if (th_warn)
306 th_warn++;
296 free(w); 307 free(w);
297 } 308 }
298 if (c) { 309 if (c) {
299 th_crit=strchr(th_crit, ','); 310 th_crit = strchr(th_crit, ',');
300 if (th_crit) th_crit++; 311 if (th_crit)
312 th_crit++;
301 free(c); 313 free(c);
302 } 314 }
303 } 315 }
304 316
305 /* Create the command array to execute */ 317 /* Create the command array to execute */
306 if(usesnmpgetnext) { 318 if (usesnmpgetnext) {
307 snmpcmd = strdup (PATH_TO_SNMPGETNEXT); 319 snmpcmd = strdup(PATH_TO_SNMPGETNEXT);
308 }else{ 320 } else {
309 snmpcmd = strdup (PATH_TO_SNMPGET); 321 snmpcmd = strdup(PATH_TO_SNMPGET);
310 } 322 }
311 323
312 /* 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 */
313 325
314 unsigned index = 0; 326 unsigned index = 0;
315 command_line = calloc (11 + numcontext + numauthpriv + 1 + numoids + 1, sizeof (char *)); 327 command_line = calloc(11 + numcontext + numauthpriv + 1 + numoids + 1, sizeof(char *));
316 328
317 command_line[index++] = snmpcmd; 329 command_line[index++] = snmpcmd;
318 command_line[index++] = strdup ("-Le"); 330 command_line[index++] = strdup("-Le");
319 command_line[index++] = strdup ("-t"); 331 command_line[index++] = strdup("-t");
320 xasprintf (&command_line[index++], "%d", timeout_interval); 332 xasprintf(&command_line[index++], "%d", timeout_interval);
321 command_line[index++] = strdup ("-r"); 333 command_line[index++] = strdup("-r");
322 xasprintf (&command_line[index++], "%d", retries); 334 xasprintf(&command_line[index++], "%d", retries);
323 command_line[index++] = strdup ("-m"); 335 command_line[index++] = strdup("-m");
324 command_line[index++] = strdup (miblist); 336 command_line[index++] = strdup(miblist);
325 command_line[index++] = "-v"; 337 command_line[index++] = "-v";
326 command_line[index++] = strdup (proto); 338 command_line[index++] = strdup(proto);
327 339
328 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 : "''",
329 snmpcmd, timeout_interval, retries, strlen(miblist) ? miblist : "''", proto); 341 proto);
330 342
331 if (ignore_mib_parsing_errors) { 343 if (ignore_mib_parsing_errors) {
332 command_line[index++] = "-Pe"; 344 command_line[index++] = "-Pe";
333 xasprintf(&cl_hidden_auth, "%s -Pe", cl_hidden_auth); 345 xasprintf(&cl_hidden_auth, "%s -Pe", cl_hidden_auth);
334 } 346 }
335 347
336
337 for (int i = 0; i < numcontext; i++) { 348 for (int i = 0; i < numcontext; i++) {
338 command_line[index++] = contextargs[i]; 349 command_line[index++] = contextargs[i];
339 } 350 }
@@ -342,12 +353,9 @@ main (int argc, char **argv)
342 command_line[index++] = authpriv[i]; 353 command_line[index++] = authpriv[i];
343 } 354 }
344 355
345 xasprintf (&command_line[index++], "%s:%s", server_address, port); 356 xasprintf(&command_line[index++], "%s:%s", server_address, port);
346 357
347 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);
348 cl_hidden_auth,
349 server_address,
350 port);
351 359
352 for (size_t i = 0; i < numoids; i++) { 360 for (size_t i = 0; i < numoids; i++) {
353 command_line[index++] = oids[i]; 361 command_line[index++] = oids[i];
@@ -357,17 +365,17 @@ main (int argc, char **argv)
357 command_line[index++] = NULL; 365 command_line[index++] = NULL;
358 366
359 if (verbose) { 367 if (verbose) {
360 printf ("%s\n", cl_hidden_auth); 368 printf("%s\n", cl_hidden_auth);
361 } 369 }
362 370
363 /* Set signal handling and alarm */ 371 /* Set signal handling and alarm */
364 if (signal (SIGALRM, runcmd_timeout_alarm_handler) == SIG_ERR) { 372 if (signal(SIGALRM, runcmd_timeout_alarm_handler) == SIG_ERR) {
365 usage4 (_("Cannot catch SIGALRM")); 373 usage4(_("Cannot catch SIGALRM"));
366 } 374 }
367 alarm(timeout_interval * retries + 5); 375 alarm(timeout_interval * retries + 5);
368 376
369 /* Run the command */ 377 /* Run the command */
370 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);
371 379
372 /* disable alarm again */ 380 /* disable alarm again */
373 alarm(0); 381 alarm(0);
@@ -377,80 +385,74 @@ main (int argc, char **argv)
377 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
378 */ 386 */
379 if (return_code != 0) 387 if (return_code != 0)
380 external_error=1; 388 external_error = 1;
381 if (chld_out.lines == 0) 389 if (chld_out.lines == 0)
382 external_error=1; 390 external_error = 1;
383 if (external_error) { 391 if (external_error) {
384 if (chld_err.lines > 0) { 392 if (chld_err.lines > 0) {
385 printf (_("External command error: %s\n"), chld_err.line[0]); 393 printf(_("External command error: %s\n"), chld_err.line[0]);
386 for (size_t i = 1; i < chld_err.lines; i++) { 394 for (size_t i = 1; i < chld_err.lines; i++) {
387 printf ("%s\n", chld_err.line[i]); 395 printf("%s\n", chld_err.line[i]);
388 } 396 }
389 } else { 397 } else {
390 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);
391 } 399 }
392 exit (STATE_UNKNOWN); 400 exit(STATE_UNKNOWN);
393 } 401 }
394 402
395 if (verbose) { 403 if (verbose) {
396 for (size_t i = 0; i < chld_out.lines; i++) { 404 for (size_t i = 0; i < chld_out.lines; i++) {
397 printf ("%s\n", chld_out.line[i]); 405 printf("%s\n", chld_out.line[i]);
398 } 406 }
399 } 407 }
400 408
401 line = 0; 409 line = 0;
402 total_oids = 0; 410 total_oids = 0;
403 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++) {
404 if(calculate_rate) 412 if (calculate_rate)
405 conv = "%.10g"; 413 conv = "%.10g";
406 else 414 else
407 conv = "%.0f"; 415 conv = "%.0f";
408 416
409 ptr = chld_out.line[line]; 417 ptr = chld_out.line[line];
410 oidname = strpcpy (oidname, ptr, delimiter); 418 oidname = strpcpy(oidname, ptr, delimiter);
411 response = strstr (ptr, delimiter); 419 response = strstr(ptr, delimiter);
412 if (response == NULL) 420 if (response == NULL)
413 break; 421 break;
414 422
415 if (verbose > 2) { 423 if (verbose > 2) {
416 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);
417 } 425 }
418 426
419 /* Clean up type array - Sol10 does not necessarily zero it out */ 427 /* Clean up type array - Sol10 does not necessarily zero it out */
420 bzero(type, sizeof(type)); 428 bzero(type, sizeof(type));
421 429
422 is_counter=0; 430 is_counter = 0;
423 /* We strip out the datatype indicator for PHBs */ 431 /* We strip out the datatype indicator for PHBs */
424 if (strstr (response, "Gauge: ")) { 432 if (strstr(response, "Gauge: ")) {
425 show = multiply (strstr (response, "Gauge: ") + 7); 433 show = multiply(strstr(response, "Gauge: ") + 7);
426 } 434 } else if (strstr(response, "Gauge32: ")) {
427 else if (strstr (response, "Gauge32: ")) { 435 show = multiply(strstr(response, "Gauge32: ") + 9);
428 show = multiply (strstr (response, "Gauge32: ") + 9); 436 } else if (strstr(response, "Counter32: ")) {
429 } 437 show = strstr(response, "Counter32: ") + 11;
430 else if (strstr (response, "Counter32: ")) { 438 is_counter = 1;
431 show = strstr (response, "Counter32: ") + 11; 439 if (!calculate_rate)
432 is_counter=1;
433 if(!calculate_rate)
434 strcpy(type, "c"); 440 strcpy(type, "c");
435 } 441 } else if (strstr(response, "Counter64: ")) {
436 else if (strstr (response, "Counter64: ")) { 442 show = strstr(response, "Counter64: ") + 11;
437 show = strstr (response, "Counter64: ") + 11; 443 is_counter = 1;
438 is_counter=1; 444 if (!calculate_rate)
439 if(!calculate_rate)
440 strcpy(type, "c"); 445 strcpy(type, "c");
441 } 446 } else if (strstr(response, "INTEGER: ")) {
442 else if (strstr (response, "INTEGER: ")) { 447 show = multiply(strstr(response, "INTEGER: ") + 9);
443 show = multiply (strstr (response, "INTEGER: ") + 9);
444 448
445 if (fmtstr_set) { 449 if (fmtstr_set) {
446 conv = fmtstr; 450 conv = fmtstr;
447 } 451 }
448 } 452 } else if (strstr(response, "OID: ")) {
449 else if (strstr (response, "OID: ")) { 453 show = strstr(response, "OID: ") + 5;
450 show = strstr (response, "OID: ") + 5; 454 } else if (strstr(response, "STRING: ")) {
451 } 455 show = strstr(response, "STRING: ") + 8;
452 else if (strstr (response, "STRING: ")) {
453 show = strstr (response, "STRING: ") + 8;
454 conv = "%.10g"; 456 conv = "%.10g";
455 457
456 /* Get the rest of the string on multi-line strings */ 458 /* Get the rest of the string on multi-line strings */
@@ -464,15 +466,17 @@ main (int argc, char **argv)
464 466
465 if (dq_count) { /* unfinished line */ 467 if (dq_count) { /* unfinished line */
466 /* copy show verbatim first */ 468 /* copy show verbatim first */
467 if (!mult_resp) mult_resp = strdup(""); 469 if (!mult_resp)
468 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);
469 /* then strip out unmatched double-quote from single-line output */ 472 /* then strip out unmatched double-quote from single-line output */
470 if (show[0] == '"') show++; 473 if (show[0] == '"')
474 show++;
471 475
472 /* Keep reading until we match end of double-quoted string */ 476 /* Keep reading until we match end of double-quoted string */
473 for (line++; line < chld_out.lines; line++) { 477 for (line++; line < chld_out.lines; line++) {
474 ptr = chld_out.line[line]; 478 ptr = chld_out.line[line];
475 xasprintf (&mult_resp, "%s%s\n", mult_resp, ptr); 479 xasprintf(&mult_resp, "%s%s\n", mult_resp, ptr);
476 480
477 COUNT_SEQ(ptr, bk_count, dq_count) 481 COUNT_SEQ(ptr, bk_count, dq_count)
478 while (dq_count && ptr[0] != '\n' && ptr[0] != '\0') { 482 while (dq_count && ptr[0] != '\n' && ptr[0] != '\0') {
@@ -481,15 +485,14 @@ main (int argc, char **argv)
481 COUNT_SEQ(ptr, bk_count, dq_count) 485 COUNT_SEQ(ptr, bk_count, dq_count)
482 } 486 }
483 /* Break for loop before next line increment when done */ 487 /* Break for loop before next line increment when done */
484 if (!dq_count) break; 488 if (!dq_count)
489 break;
485 } 490 }
486 } 491 }
487 492
488 } 493 } else if (strstr(response, "Timeticks: ")) {
489 else if (strstr (response, "Timeticks: ")) { 494 show = strstr(response, "Timeticks: ");
490 show = strstr (response, "Timeticks: "); 495 } else
491 }
492 else
493 show = response + 3; 496 show = response + 3;
494 497
495 iresult = STATE_DEPENDENT; 498 iresult = STATE_DEPENDENT;
@@ -500,68 +503,67 @@ main (int argc, char **argv)
500 if (verbose > 2) { 503 if (verbose > 2) {
501 print_thresholds(" thresholds", thlds[i]); 504 print_thresholds(" thresholds", thlds[i]);
502 } 505 }
503 ptr = strpbrk (show, "-0123456789"); 506 ptr = strpbrk(show, "-0123456789");
504 if (ptr == NULL){ 507 if (ptr == NULL) {
505 if (nulloid == 3) 508 if (nulloid == 3)
506 die (STATE_UNKNOWN,_("No valid data returned (%s)\n"), show); 509 die(STATE_UNKNOWN, _("No valid data returned (%s)\n"), show);
507 else if (nulloid == 0) 510 else if (nulloid == 0)
508 die (STATE_OK,_("No valid data returned (%s)\n"), show); 511 die(STATE_OK, _("No valid data returned (%s)\n"), show);
509 else if (nulloid == 1) 512 else if (nulloid == 1)
510 die (STATE_WARNING,_("No valid data returned (%s)\n"), show); 513 die(STATE_WARNING, _("No valid data returned (%s)\n"), show);
511 else if (nulloid == 2) 514 else if (nulloid == 2)
512 die (STATE_CRITICAL,_("No valid data returned (%s)\n"), show); 515 die(STATE_CRITICAL, _("No valid data returned (%s)\n"), show);
513 } 516 }
514 while (i >= response_size) { 517 while (i >= response_size) {
515 response_size += OID_COUNT_STEP; 518 response_size += OID_COUNT_STEP;
516 response_value = realloc(response_value, response_size * sizeof(*response_value)); 519 response_value = realloc(response_value, response_size * sizeof(*response_value));
517 } 520 }
518 response_value[i] = strtod (ptr, NULL) + offset; 521 response_value[i] = strtod(ptr, NULL) + offset;
519 522
520 if(calculate_rate) { 523 if (calculate_rate) {
521 if (previous_state!=NULL) { 524 if (previous_state != NULL) {
522 duration = current_time-previous_state->time; 525 duration = current_time - previous_state->time;
523 if(duration<=0) 526 if (duration <= 0)
524 die(STATE_UNKNOWN,_("Time duration between plugin calls is invalid")); 527 die(STATE_UNKNOWN, _("Time duration between plugin calls is invalid"));
525 temp_double = response_value[i]-previous_value[i]; 528 temp_double = response_value[i] - previous_value[i];
526 /* Simple overflow catcher (same as in rrdtool, rrd_update.c) */ 529 /* Simple overflow catcher (same as in rrdtool, rrd_update.c) */
527 if(is_counter) { 530 if (is_counter) {
528 if(temp_double<(double)0.0) 531 if (temp_double < (double)0.0)
529 temp_double+=(double)4294967296.0; /* 2^32 */ 532 temp_double += (double)4294967296.0; /* 2^32 */
530 if(temp_double<(double)0.0) 533 if (temp_double < (double)0.0)
531 temp_double+=(double)18446744069414584320.0; /* 2^64-2^32 */; 534 temp_double += (double)18446744069414584320.0; /* 2^64-2^32 */
535 ;
532 } 536 }
533 /* Convert to per second, then use multiplier */ 537 /* Convert to per second, then use multiplier */
534 temp_double = temp_double/duration*rate_multiplier; 538 temp_double = temp_double / duration * rate_multiplier;
535 iresult = get_status(temp_double, thlds[i]); 539 iresult = get_status(temp_double, thlds[i]);
536 xasprintf (&show, conv, temp_double); 540 xasprintf(&show, conv, temp_double);
537 } 541 }
538 } else { 542 } else {
539 iresult = get_status(response_value[i], thlds[i]); 543 iresult = get_status(response_value[i], thlds[i]);
540 xasprintf (&show, conv, response_value[i]); 544 xasprintf(&show, conv, response_value[i]);
541 } 545 }
542 } 546 }
543 547
544 /* Process this block for string matching */ 548 /* Process this block for string matching */
545 else if (eval_size > i && eval_method[i] & CRIT_STRING) { 549 else if (eval_size > i && eval_method[i] & CRIT_STRING) {
546 if (strcmp (show, string_value)) 550 if (strcmp(show, string_value))
547 iresult = (invert_search==0) ? STATE_CRITICAL : STATE_OK; 551 iresult = (invert_search == 0) ? STATE_CRITICAL : STATE_OK;
548 else 552 else
549 iresult = (invert_search==0) ? STATE_OK : STATE_CRITICAL; 553 iresult = (invert_search == 0) ? STATE_OK : STATE_CRITICAL;
550 } 554 }
551 555
552 /* Process this block for regex matching */ 556 /* Process this block for regex matching */
553 else if (eval_size > i && eval_method[i] & CRIT_REGEX) { 557 else if (eval_size > i && eval_method[i] & CRIT_REGEX) {
554 excode = regexec (&preg, response, 10, pmatch, eflags); 558 excode = regexec(&preg, response, 10, pmatch, eflags);
555 if (excode == 0) { 559 if (excode == 0) {
556 iresult = (invert_search==0) ? STATE_OK : STATE_CRITICAL; 560 iresult = (invert_search == 0) ? STATE_OK : STATE_CRITICAL;
557 } 561 } else if (excode != REG_NOMATCH) {
558 else if (excode != REG_NOMATCH) { 562 regerror(excode, &preg, errbuf, MAX_INPUT_BUFFER);
559 regerror (excode, &preg, errbuf, MAX_INPUT_BUFFER); 563 printf(_("Execute Error: %s\n"), errbuf);
560 printf (_("Execute Error: %s\n"), errbuf); 564 exit(STATE_CRITICAL);
561 exit (STATE_CRITICAL); 565 } else {
562 } 566 iresult = (invert_search == 0) ? STATE_CRITICAL : STATE_OK;
563 else {
564 iresult = (invert_search==0) ? STATE_CRITICAL : STATE_OK;
565 } 567 }
566 } 568 }
567 569
@@ -577,294 +579,283 @@ main (int argc, char **argv)
577 } 579 }
578 580
579 /* Result is the worst outcome of all the OIDs tested */ 581 /* Result is the worst outcome of all the OIDs tested */
580 result = max_state (result, iresult); 582 result = max_state(result, iresult);
581 583
582 /* Prepend a label for this OID if there is one */ 584 /* Prepend a label for this OID if there is one */
583 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)
584 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));
585 (i == 0) ? " " : output_delim,
586 labels[i], mark (iresult), show, mark (iresult));
587 else 587 else
588 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));
589 mark (iresult), show, mark (iresult));
590 589
591 /* Append a unit string for this OID if there is one */ 590 /* Append a unit string for this OID if there is one */
592 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)
593 xasprintf (&outbuff, "%s %s", outbuff, unitv[i]); 592 xasprintf(&outbuff, "%s %s", outbuff, unitv[i]);
594 593
595 /* Write perfdata with whatever can be parsed by strtod, if possible */ 594 /* Write perfdata with whatever can be parsed by strtod, if possible */
596 ptr = NULL; 595 ptr = NULL;
597 strtod(show, &ptr); 596 strtod(show, &ptr);
598 if (ptr > show) { 597 if (ptr > show) {
599 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)
600 temp_string=labels[i]; 599 temp_string = labels[i];
601 else 600 else
602 temp_string=oidname; 601 temp_string = oidname;
603 if (strpbrk (temp_string, " ='\"") == NULL) { 602 if (strpbrk(temp_string, " ='\"") == NULL) {
604 strncat(perfstr, temp_string, sizeof(perfstr)-strlen(perfstr)-1); 603 strncat(perfstr, temp_string, sizeof(perfstr) - strlen(perfstr) - 1);
605 } else { 604 } else {
606 if (strpbrk (temp_string, "'") == NULL) { 605 if (strpbrk(temp_string, "'") == NULL) {
607 quote_string="'"; 606 quote_string = "'";
608 } else { 607 } else {
609 quote_string="\""; 608 quote_string = "\"";
610 } 609 }
611 strncat(perfstr, quote_string, sizeof(perfstr)-strlen(perfstr)-1); 610 strncat(perfstr, quote_string, sizeof(perfstr) - strlen(perfstr) - 1);
612 strncat(perfstr, temp_string, sizeof(perfstr)-strlen(perfstr)-1); 611 strncat(perfstr, temp_string, sizeof(perfstr) - strlen(perfstr) - 1);
613 strncat(perfstr, quote_string, sizeof(perfstr)-strlen(perfstr)-1); 612 strncat(perfstr, quote_string, sizeof(perfstr) - strlen(perfstr) - 1);
614 } 613 }
615 strncat(perfstr, "=", sizeof(perfstr)-strlen(perfstr)-1); 614 strncat(perfstr, "=", sizeof(perfstr) - strlen(perfstr) - 1);
616 len = sizeof(perfstr)-strlen(perfstr)-1; 615 len = sizeof(perfstr) - strlen(perfstr) - 1;
617 strncat(perfstr, show, len>ptr-show ? ptr-show : len); 616 strncat(perfstr, show, len > ptr - show ? ptr - show : len);
618 617
619 if (strcmp(type, "") != 0) { 618 if (strcmp(type, "") != 0) {
620 strncat(perfstr, type, sizeof(perfstr)-strlen(perfstr)-1); 619 strncat(perfstr, type, sizeof(perfstr) - strlen(perfstr) - 1);
621 } 620 }
622 621
623 if (warning_thresholds) { 622 if (warning_thresholds) {
624 strncat(perfstr, ";", sizeof(perfstr)-strlen(perfstr)-1); 623 strncat(perfstr, ";", sizeof(perfstr) - strlen(perfstr) - 1);
625 if(thlds[i]->warning && thlds[i]->warning->text) 624 if (thlds[i]->warning && thlds[i]->warning->text)
626 strncat(perfstr, thlds[i]->warning->text, sizeof(perfstr)-strlen(perfstr)-1); 625 strncat(perfstr, thlds[i]->warning->text, sizeof(perfstr) - strlen(perfstr) - 1);
627 } 626 }
628 627
629 if (critical_thresholds) { 628 if (critical_thresholds) {
630 if (!warning_thresholds) 629 if (!warning_thresholds)
631 strncat(perfstr, ";", sizeof(perfstr)-strlen(perfstr)-1); 630 strncat(perfstr, ";", sizeof(perfstr) - strlen(perfstr) - 1);
632 strncat(perfstr, ";", sizeof(perfstr)-strlen(perfstr)-1); 631 strncat(perfstr, ";", sizeof(perfstr) - strlen(perfstr) - 1);
633 if(thlds[i]->critical && thlds[i]->critical->text) 632 if (thlds[i]->critical && thlds[i]->critical->text)
634 strncat(perfstr, thlds[i]->critical->text, sizeof(perfstr)-strlen(perfstr)-1); 633 strncat(perfstr, thlds[i]->critical->text, sizeof(perfstr) - strlen(perfstr) - 1);
635 } 634 }
636 635
637 strncat(perfstr, " ", sizeof(perfstr)-strlen(perfstr)-1); 636 strncat(perfstr, " ", sizeof(perfstr) - strlen(perfstr) - 1);
638 } 637 }
639 } 638 }
640 639
641 /* Save state data, as all data collected now */ 640 /* Save state data, as all data collected now */
642 if(calculate_rate) { 641 if (calculate_rate) {
643 string_length=1024; 642 string_length = 1024;
644 state_string=malloc(string_length); 643 state_string = malloc(string_length);
645 if(state_string==NULL) 644 if (state_string == NULL)
646 die(STATE_UNKNOWN, _("Cannot malloc")); 645 die(STATE_UNKNOWN, _("Cannot malloc"));
647 646
648 current_length=0; 647 current_length = 0;
649 for(int i = 0; i < total_oids; i++) { 648 for (int i = 0; i < total_oids; i++) {
650 xasprintf(&temp_string,"%.0f",response_value[i]); 649 xasprintf(&temp_string, "%.0f", response_value[i]);
651 if(temp_string==NULL) 650 if (temp_string == NULL)
652 die(STATE_UNKNOWN,_("Cannot asprintf()")); 651 die(STATE_UNKNOWN, _("Cannot asprintf()"));
653 response_length = strlen(temp_string); 652 response_length = strlen(temp_string);
654 if(current_length+response_length>string_length) { 653 if (current_length + response_length > string_length) {
655 string_length=current_length+1024; 654 string_length = current_length + 1024;
656 state_string=realloc(state_string,string_length); 655 state_string = realloc(state_string, string_length);
657 if(state_string==NULL) 656 if (state_string == NULL)
658 die(STATE_UNKNOWN, _("Cannot realloc()")); 657 die(STATE_UNKNOWN, _("Cannot realloc()"));
659 } 658 }
660 strcpy(&state_string[current_length],temp_string); 659 strcpy(&state_string[current_length], temp_string);
661 current_length=current_length+response_length; 660 current_length = current_length + response_length;
662 state_string[current_length]=':'; 661 state_string[current_length] = ':';
663 current_length++; 662 current_length++;
664 free(temp_string); 663 free(temp_string);
665 } 664 }
666 state_string[--current_length]='\0'; 665 state_string[--current_length] = '\0';
667 if (verbose > 2) 666 if (verbose > 2)
668 printf("State string=%s\n",state_string); 667 printf("State string=%s\n", state_string);
669 668
670 /* 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 */
671 np_state_write_string(current_time, state_string ); 670 np_state_write_string(current_time, state_string);
672 if(previous_state==NULL) { 671 if (previous_state == NULL) {
673 /* Or should this be highest state? */ 672 /* Or should this be highest state? */
674 die( STATE_OK, _("No previous data to calculate rate - assume okay" ) ); 673 die(STATE_OK, _("No previous data to calculate rate - assume okay"));
675 } 674 }
676 } 675 }
677 676
678 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);
679 if (mult_resp) printf ("%s", mult_resp); 678 if (mult_resp)
679 printf("%s", mult_resp);
680 680
681 return result; 681 return result;
682} 682}
683 683
684
685
686/* process command-line arguments */ 684/* process command-line arguments */
687int 685int process_arguments(int argc, char **argv) {
688process_arguments (int argc, char **argv) 686 static struct option longopts[] = {STD_LONG_OPTS,
689{ 687 {"community", required_argument, 0, 'C'},
690 char *ptr; 688 {"oid", required_argument, 0, 'o'},
691 int c = 1; 689 {"object", required_argument, 0, 'o'},
692 size_t j = 0, jj = 0; 690 {"delimiter", required_argument, 0, 'd'},
693 691 {"nulloid", required_argument, 0, 'z'},
694 int option = 0; 692 {"output-delimiter", required_argument, 0, 'D'},
695 static struct option longopts[] = { 693 {"string", required_argument, 0, 's'},
696 STD_LONG_OPTS, 694 {"timeout", required_argument, 0, 't'},
697 {"community", required_argument, 0, 'C'}, 695 {"regex", required_argument, 0, 'r'},
698 {"oid", required_argument, 0, 'o'}, 696 {"ereg", required_argument, 0, 'r'},
699 {"object", required_argument, 0, 'o'}, 697 {"eregi", required_argument, 0, 'R'},
700 {"delimiter", required_argument, 0, 'd'}, 698 {"label", required_argument, 0, 'l'},
701 {"nulloid", required_argument, 0, 'z'}, 699 {"units", required_argument, 0, 'u'},
702 {"output-delimiter", required_argument, 0, 'D'}, 700 {"port", required_argument, 0, 'p'},
703 {"string", required_argument, 0, 's'}, 701 {"retries", required_argument, 0, 'e'},
704 {"timeout", required_argument, 0, 't'}, 702 {"miblist", required_argument, 0, 'm'},
705 {"regex", required_argument, 0, 'r'}, 703 {"protocol", required_argument, 0, 'P'},
706 {"ereg", required_argument, 0, 'r'}, 704 {"context", required_argument, 0, 'N'},
707 {"eregi", required_argument, 0, 'R'}, 705 {"seclevel", required_argument, 0, 'L'},
708 {"label", required_argument, 0, 'l'}, 706 {"secname", required_argument, 0, 'U'},
709 {"units", required_argument, 0, 'u'}, 707 {"authproto", required_argument, 0, 'a'},
710 {"port", required_argument, 0, 'p'}, 708 {"privproto", required_argument, 0, 'x'},
711 {"retries", required_argument, 0, 'e'}, 709 {"authpasswd", required_argument, 0, 'A'},
712 {"miblist", required_argument, 0, 'm'}, 710 {"privpasswd", required_argument, 0, 'X'},
713 {"protocol", required_argument, 0, 'P'}, 711 {"next", no_argument, 0, 'n'},
714 {"context", required_argument, 0, 'N'}, 712 {"rate", no_argument, 0, L_CALCULATE_RATE},
715 {"seclevel", required_argument, 0, 'L'}, 713 {"rate-multiplier", required_argument, 0, L_RATE_MULTIPLIER},
716 {"secname", required_argument, 0, 'U'}, 714 {"offset", required_argument, 0, L_OFFSET},
717 {"authproto", required_argument, 0, 'a'}, 715 {"invert-search", no_argument, 0, L_INVERT_SEARCH},
718 {"privproto", required_argument, 0, 'x'}, 716 {"perf-oids", no_argument, 0, 'O'},
719 {"authpasswd", required_argument, 0, 'A'}, 717 {"ipv4", no_argument, 0, '4'},
720 {"privpasswd", required_argument, 0, 'X'}, 718 {"ipv6", no_argument, 0, '6'},
721 {"next", no_argument, 0, 'n'}, 719 {"multiplier", required_argument, 0, 'M'},
722 {"rate", no_argument, 0, L_CALCULATE_RATE}, 720 {"fmtstr", required_argument, 0, 'f'},
723 {"rate-multiplier", required_argument, 0, L_RATE_MULTIPLIER}, 721 {"ignore-mib-parsing-errors", no_argument, false, L_IGNORE_MIB_PARSING_ERRORS},
724 {"offset", required_argument, 0, L_OFFSET}, 722 {0, 0, 0, 0}};
725 {"invert-search", no_argument, 0, L_INVERT_SEARCH},
726 {"perf-oids", no_argument, 0, 'O'},
727 {"ipv4", no_argument, 0, '4'},
728 {"ipv6", no_argument, 0, '6'},
729 {"multiplier", required_argument, 0, 'M'},
730 {"fmtstr", required_argument, 0, 'f'},
731 {"ignore-mib-parsing-errors", no_argument, false, L_IGNORE_MIB_PARSING_ERRORS},
732 {0, 0, 0, 0}
733 };
734 723
735 if (argc < 2) 724 if (argc < 2)
736 return ERROR; 725 return ERROR;
737 726
738 /* reverse compatibility for very old non-POSIX usage forms */ 727 /* reverse compatibility for very old non-POSIX usage forms */
739 for (c = 1; c < argc; c++) { 728 for (int c = 1; c < argc; c++) {
740 if (strcmp ("-to", argv[c]) == 0) 729 if (strcmp("-to", argv[c]) == 0)
741 strcpy (argv[c], "-t"); 730 strcpy(argv[c], "-t");
742 if (strcmp ("-wv", argv[c]) == 0) 731 if (strcmp("-wv", argv[c]) == 0)
743 strcpy (argv[c], "-w"); 732 strcpy(argv[c], "-w");
744 if (strcmp ("-cv", argv[c]) == 0) 733 if (strcmp("-cv", argv[c]) == 0)
745 strcpy (argv[c], "-c"); 734 strcpy(argv[c], "-c");
746 } 735 }
747 736
748 while (1) { 737 size_t j = 0;
749 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;
750 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);
751 742
752 if (c == -1 || c == EOF) 743 if (option_char == -1 || option_char == EOF)
753 break; 744 break;
754 745
755 switch (c) { 746 switch (option_char) {
756 case '?': /* usage */ 747 case '?': /* usage */
757 usage5 (); 748 usage5();
758 case 'h': /* help */ 749 case 'h': /* help */
759 print_help (); 750 print_help();
760 exit (STATE_UNKNOWN); 751 exit(STATE_UNKNOWN);
761 case 'V': /* version */ 752 case 'V': /* version */
762 print_revision (progname, NP_VERSION); 753 print_revision(progname, NP_VERSION);
763 exit (STATE_UNKNOWN); 754 exit(STATE_UNKNOWN);
764 case 'v': /* verbose */ 755 case 'v': /* verbose */
765 verbose++; 756 verbose++;
766 break; 757 break;
767 758
768 /* Connection info */ 759 /* Connection info */
769 case 'C': /* group or community */ 760 case 'C': /* group or community */
770 community = optarg; 761 community = optarg;
771 break; 762 break;
772 case 'H': /* Host or server */ 763 case 'H': /* Host or server */
773 server_address = optarg; 764 server_address = optarg;
774 break; 765 break;
775 case 'p': /* TCP port number */ 766 case 'p': /* TCP port number */
776 port = optarg; 767 port = optarg;
777 break; 768 break;
778 case 'm': /* List of MIBS */ 769 case 'm': /* List of MIBS */
779 miblist = optarg; 770 miblist = optarg;
780 break; 771 break;
781 case 'n': /* usesnmpgetnext */ 772 case 'n': /* usesnmpgetnext */
782 usesnmpgetnext = true; 773 usesnmpgetnext = true;
783 break; 774 break;
784 case 'P': /* SNMP protocol version */ 775 case 'P': /* SNMP protocol version */
785 proto = optarg; 776 proto = optarg;
786 break; 777 break;
787 case 'N': /* SNMPv3 context */ 778 case 'N': /* SNMPv3 context */
788 context = optarg; 779 context = optarg;
789 break; 780 break;
790 case 'L': /* security level */ 781 case 'L': /* security level */
791 seclevel = optarg; 782 seclevel = optarg;
792 break; 783 break;
793 case 'U': /* security username */ 784 case 'U': /* security username */
794 secname = optarg; 785 secname = optarg;
795 break; 786 break;
796 case 'a': /* auth protocol */ 787 case 'a': /* auth protocol */
797 authproto = optarg; 788 authproto = optarg;
798 break; 789 break;
799 case 'x': /* priv protocol */ 790 case 'x': /* priv protocol */
800 privproto = optarg; 791 privproto = optarg;
801 break; 792 break;
802 case 'A': /* auth passwd */ 793 case 'A': /* auth passwd */
803 authpasswd = optarg; 794 authpasswd = optarg;
804 break; 795 break;
805 case 'X': /* priv passwd */ 796 case 'X': /* priv passwd */
806 privpasswd = optarg; 797 privpasswd = optarg;
807 break; 798 break;
808 case 't': /* timeout period */ 799 case 't': /* timeout period */
809 if (!is_integer (optarg)) 800 if (!is_integer(optarg))
810 usage2 (_("Timeout interval must be a positive integer"), optarg); 801 usage2(_("Timeout interval must be a positive integer"), optarg);
811 else 802 else
812 timeout_interval = atoi (optarg); 803 timeout_interval = atoi(optarg);
813 break; 804 break;
814 805
815 /* Test parameters */ 806 /* Test parameters */
816 case 'c': /* critical threshold */ 807 case 'c': /* critical threshold */
817 critical_thresholds = optarg; 808 critical_thresholds = optarg;
818 break; 809 break;
819 case 'w': /* warning threshold */ 810 case 'w': /* warning threshold */
820 warning_thresholds = optarg; 811 warning_thresholds = optarg;
821 break; 812 break;
822 case 'e': /* PRELIMINARY - may change */ 813 case 'e': /* PRELIMINARY - may change */
823 case 'E': /* PRELIMINARY - may change */ 814 case 'E': /* PRELIMINARY - may change */
824 if (!is_integer (optarg)) 815 if (!is_integer(optarg))
825 usage2 (_("Retries interval must be a positive integer"), optarg); 816 usage2(_("Retries interval must be a positive integer"), optarg);
826 else 817 else
827 retries = atoi(optarg); 818 retries = atoi(optarg);
828 break; 819 break;
829 case 'o': /* object identifier */ 820 case 'o': /* object identifier */
830 if ( strspn( optarg, "0123456789.," ) != strlen( optarg ) ) { 821 if (strspn(optarg, "0123456789.,") != strlen(optarg)) {
831 /* 822 /*
832 * we have something other than digits, periods and comas, 823 * we have something other than digits, periods and comas,
833 * 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,
834 * so we have to actually read the mib files 825 * so we have to actually read the mib files
835 */ 826 */
836 needmibs = true; 827 needmibs = true;
837 } 828 }
838 for (ptr = strtok(optarg, ", "); ptr != NULL; ptr = strtok(NULL, ", "), j++) { 829 for (char *ptr = strtok(optarg, ", "); ptr != NULL; ptr = strtok(NULL, ", "), j++) {
839 while (j >= oids_size) { 830 while (j >= oids_size) {
840 oids_size += OID_COUNT_STEP; 831 oids_size += OID_COUNT_STEP;
841 oids = realloc(oids, oids_size * sizeof (*oids)); 832 oids = realloc(oids, oids_size * sizeof(*oids));
842 } 833 }
843 oids[j] = strdup(ptr); 834 oids[j] = strdup(ptr);
844 } 835 }
845 numoids = j; 836 numoids = j;
846 if (c == 'E' || c == 'e') { 837 if (option_char == 'E' || option_char == 'e') {
847 jj++; 838 jj++;
848 while (j+1 >= eval_size) { 839 while (j + 1 >= eval_size) {
849 eval_size += OID_COUNT_STEP; 840 eval_size += OID_COUNT_STEP;
850 eval_method = realloc(eval_method, eval_size * sizeof(*eval_method)); 841 eval_method = realloc(eval_method, eval_size * sizeof(*eval_method));
851 memset(eval_method + eval_size - OID_COUNT_STEP, 0, 8); 842 memset(eval_method + eval_size - OID_COUNT_STEP, 0, 8);
852 } 843 }
853 if (c == 'E') 844 if (option_char == 'E')
854 eval_method[j+1] |= WARN_PRESENT; 845 eval_method[j + 1] |= WARN_PRESENT;
855 else if (c == 'e') 846 else if (option_char == 'e')
856 eval_method[j+1] |= CRIT_PRESENT; 847 eval_method[j + 1] |= CRIT_PRESENT;
857 } 848 }
858 break; 849 break;
859 case 'z': /* Null OID Return Check */ 850 case 'z': /* Null OID Return Check */
860 if (!is_integer (optarg)) 851 if (!is_integer(optarg))
861 usage2 (_("Exit status must be a positive integer"), optarg); 852 usage2(_("Exit status must be a positive integer"), optarg);
862 else 853 else
863 nulloid = atoi(optarg); 854 nulloid = atoi(optarg);
864 break; 855 break;
865 case 's': /* string or substring */ 856 case 's': /* string or substring */
866 strncpy (string_value, optarg, sizeof (string_value) - 1); 857 strncpy(string_value, optarg, sizeof(string_value) - 1);
867 string_value[sizeof (string_value) - 1] = 0; 858 string_value[sizeof(string_value) - 1] = 0;
868 while (jj >= eval_size) { 859 while (jj >= eval_size) {
869 eval_size += OID_COUNT_STEP; 860 eval_size += OID_COUNT_STEP;
870 eval_method = realloc(eval_method, eval_size * sizeof(*eval_method)); 861 eval_method = realloc(eval_method, eval_size * sizeof(*eval_method));
@@ -872,17 +863,17 @@ process_arguments (int argc, char **argv)
872 } 863 }
873 eval_method[jj++] = CRIT_STRING; 864 eval_method[jj++] = CRIT_STRING;
874 break; 865 break;
875 case 'R': /* regex */ 866 case 'R': /* regex */
876 cflags = REG_ICASE; 867 cflags = REG_ICASE;
877 // fall through 868 // fall through
878 case 'r': /* regex */ 869 case 'r': /* regex */
879 cflags |= REG_EXTENDED | REG_NOSUB | REG_NEWLINE; 870 cflags |= REG_EXTENDED | REG_NOSUB | REG_NEWLINE;
880 strncpy (regex_expect, optarg, sizeof (regex_expect) - 1); 871 strncpy(regex_expect, optarg, sizeof(regex_expect) - 1);
881 regex_expect[sizeof (regex_expect) - 1] = 0; 872 regex_expect[sizeof(regex_expect) - 1] = 0;
882 errcode = regcomp (&preg, regex_expect, cflags); 873 errcode = regcomp(&preg, regex_expect, cflags);
883 if (errcode != 0) { 874 if (errcode != 0) {
884 regerror (errcode, &preg, errbuf, MAX_INPUT_BUFFER); 875 regerror(errcode, &preg, errbuf, MAX_INPUT_BUFFER);
885 printf (_("Could Not Compile Regular Expression")); 876 printf(_("Could Not Compile Regular Expression"));
886 return ERROR; 877 return ERROR;
887 } 878 }
888 while (jj >= eval_size) { 879 while (jj >= eval_size) {
@@ -893,64 +884,64 @@ process_arguments (int argc, char **argv)
893 eval_method[jj++] = CRIT_REGEX; 884 eval_method[jj++] = CRIT_REGEX;
894 break; 885 break;
895 886
896 /* Format */ 887 /* Format */
897 case 'd': /* delimiter */ 888 case 'd': /* delimiter */
898 delimiter = strscpy (delimiter, optarg); 889 delimiter = strscpy(delimiter, optarg);
899 break; 890 break;
900 case 'D': /* output-delimiter */ 891 case 'D': /* output-delimiter */
901 output_delim = strscpy (output_delim, optarg); 892 output_delim = strscpy(output_delim, optarg);
902 break; 893 break;
903 case 'l': /* label */ 894 case 'l': /* label */
904 nlabels++; 895 nlabels++;
905 if (nlabels > labels_size) { 896 if (nlabels > labels_size) {
906 labels_size += 8; 897 labels_size += 8;
907 labels = realloc (labels, labels_size * sizeof(*labels)); 898 labels = realloc(labels, labels_size * sizeof(*labels));
908 if (labels == NULL) 899 if (labels == NULL)
909 die (STATE_UNKNOWN, _("Could not reallocate labels[%d]"), (int)nlabels); 900 die(STATE_UNKNOWN, _("Could not reallocate labels[%d]"), (int)nlabels);
910 } 901 }
911 labels[nlabels - 1] = optarg; 902 labels[nlabels - 1] = optarg;
912 ptr = thisarg (optarg); 903 char *ptr = thisarg(optarg);
913 labels[nlabels - 1] = ptr; 904 labels[nlabels - 1] = ptr;
914 if (ptr[0] == '\'') 905 if (ptr[0] == '\'')
915 labels[nlabels - 1] = ptr + 1; 906 labels[nlabels - 1] = ptr + 1;
916 while (ptr && (ptr = nextarg (ptr))) { 907 while (ptr && (ptr = nextarg(ptr))) {
917 nlabels++; 908 nlabels++;
918 if (nlabels > labels_size) { 909 if (nlabels > labels_size) {
919 labels_size += 8; 910 labels_size += 8;
920 labels = realloc (labels, labels_size * sizeof(*labels)); 911 labels = realloc(labels, labels_size * sizeof(*labels));
921 if (labels == NULL) 912 if (labels == NULL)
922 die (STATE_UNKNOWN, _("Could not reallocate labels\n")); 913 die(STATE_UNKNOWN, _("Could not reallocate labels\n"));
923 } 914 }
924 ptr = thisarg (ptr); 915 ptr = thisarg(ptr);
925 if (ptr[0] == '\'') 916 if (ptr[0] == '\'')
926 labels[nlabels - 1] = ptr + 1; 917 labels[nlabels - 1] = ptr + 1;
927 else 918 else
928 labels[nlabels - 1] = ptr; 919 labels[nlabels - 1] = ptr;
929 } 920 }
930 break; 921 break;
931 case 'u': /* units */ 922 case 'u': /* units */
932 units = optarg; 923 units = optarg;
933 nunits++; 924 nunits++;
934 if (nunits > unitv_size) { 925 if (nunits > unitv_size) {
935 unitv_size += 8; 926 unitv_size += 8;
936 unitv = realloc (unitv, unitv_size * sizeof(*unitv)); 927 unitv = realloc(unitv, unitv_size * sizeof(*unitv));
937 if (unitv == NULL) 928 if (unitv == NULL)
938 die (STATE_UNKNOWN, _("Could not reallocate units [%d]\n"), (int)nunits); 929 die(STATE_UNKNOWN, _("Could not reallocate units [%d]\n"), (int)nunits);
939 } 930 }
940 unitv[nunits - 1] = optarg; 931 unitv[nunits - 1] = optarg;
941 ptr = thisarg (optarg); 932 ptr = thisarg(optarg);
942 unitv[nunits - 1] = ptr; 933 unitv[nunits - 1] = ptr;
943 if (ptr[0] == '\'') 934 if (ptr[0] == '\'')
944 unitv[nunits - 1] = ptr + 1; 935 unitv[nunits - 1] = ptr + 1;
945 while (ptr && (ptr = nextarg (ptr))) { 936 while (ptr && (ptr = nextarg(ptr))) {
946 if (nunits > unitv_size) { 937 if (nunits > unitv_size) {
947 unitv_size += 8; 938 unitv_size += 8;
948 unitv = realloc (unitv, unitv_size * sizeof(*unitv)); 939 unitv = realloc(unitv, unitv_size * sizeof(*unitv));
949 if (units == NULL) 940 if (units == NULL)
950 die (STATE_UNKNOWN, _("Could not realloc() units\n")); 941 die(STATE_UNKNOWN, _("Could not realloc() units\n"));
951 } 942 }
952 nunits++; 943 nunits++;
953 ptr = thisarg (ptr); 944 ptr = thisarg(ptr);
954 if (ptr[0] == '\'') 945 if (ptr[0] == '\'')
955 unitv[nunits - 1] = ptr + 1; 946 unitv[nunits - 1] = ptr + 1;
956 else 947 else
@@ -958,38 +949,38 @@ process_arguments (int argc, char **argv)
958 } 949 }
959 break; 950 break;
960 case L_CALCULATE_RATE: 951 case L_CALCULATE_RATE:
961 if(calculate_rate==0) 952 if (calculate_rate == 0)
962 np_enable_state(NULL, 1); 953 np_enable_state(NULL, 1);
963 calculate_rate = 1; 954 calculate_rate = 1;
964 break; 955 break;
965 case L_RATE_MULTIPLIER: 956 case L_RATE_MULTIPLIER:
966 if(!is_integer(optarg)||((rate_multiplier=atoi(optarg))<=0)) 957 if (!is_integer(optarg) || ((rate_multiplier = atoi(optarg)) <= 0))
967 usage2(_("Rate multiplier must be a positive integer"),optarg); 958 usage2(_("Rate multiplier must be a positive integer"), optarg);
968 break; 959 break;
969 case L_OFFSET: 960 case L_OFFSET:
970 offset=strtod(optarg,NULL); 961 offset = strtod(optarg, NULL);
971 break; 962 break;
972 case L_INVERT_SEARCH: 963 case L_INVERT_SEARCH:
973 invert_search=1; 964 invert_search = 1;
974 break; 965 break;
975 case 'O': 966 case 'O':
976 perf_labels=0; 967 perf_labels = 0;
977 break; 968 break;
978 case '4': 969 case '4':
979 break; 970 break;
980 case '6': 971 case '6':
981 xasprintf(&ip_version, "udp6:"); 972 xasprintf(&ip_version, "udp6:");
982 if(verbose>2) 973 if (verbose > 2)
983 printf("IPv6 detected! Will pass \"udp6:\" to snmpget.\n"); 974 printf("IPv6 detected! Will pass \"udp6:\" to snmpget.\n");
984 break; 975 break;
985 case 'M': 976 case 'M':
986 if ( strspn( optarg, "0123456789.," ) == strlen( optarg ) ) { 977 if (strspn(optarg, "0123456789.,") == strlen(optarg)) {
987 multiplier=strtod(optarg,NULL); 978 multiplier = strtod(optarg, NULL);
988 } 979 }
989 break; 980 break;
990 case 'f': 981 case 'f':
991 if (multiplier != 1.0) { 982 if (multiplier != 1.0) {
992 fmtstr=optarg; 983 fmtstr = optarg;
993 fmtstr_set = true; 984 fmtstr_set = true;
994 } 985 }
995 break; 986 break;
@@ -1002,12 +993,11 @@ process_arguments (int argc, char **argv)
1002 server_address = argv[optind]; 993 server_address = argv[optind];
1003 994
1004 if (community == NULL) 995 if (community == NULL)
1005 community = strdup (DEFAULT_COMMUNITY); 996 community = strdup(DEFAULT_COMMUNITY);
1006 997
1007 return validate_arguments (); 998 return validate_arguments();
1008} 999}
1009 1000
1010
1011/****************************************************************************** 1001/******************************************************************************
1012 1002
1013@@- 1003@@-
@@ -1026,17 +1016,13 @@ selected.</para>
1026-@@ 1016-@@
1027******************************************************************************/ 1017******************************************************************************/
1028 1018
1029 1019static int validate_arguments() {
1030
1031static int
1032validate_arguments ()
1033{
1034 /* check whether to load locally installed MIBS (CPU/disk intensive) */ 1020 /* check whether to load locally installed MIBS (CPU/disk intensive) */
1035 if (miblist == NULL) { 1021 if (miblist == NULL) {
1036 if (needmibs) { 1022 if (needmibs) {
1037 miblist = strdup (DEFAULT_MIBLIST); 1023 miblist = strdup(DEFAULT_MIBLIST);
1038 }else{ 1024 } else {
1039 miblist = ""; /* don't read any mib files for numeric oids */ 1025 miblist = ""; /* don't read any mib files for numeric oids */
1040 } 1026 }
1041 } 1027 }
1042 1028
@@ -1051,18 +1037,17 @@ validate_arguments ()
1051 if (proto == NULL) 1037 if (proto == NULL)
1052 xasprintf(&proto, DEFAULT_PROTOCOL); 1038 xasprintf(&proto, DEFAULT_PROTOCOL);
1053 1039
1054 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 */
1055 numauthpriv = 2; 1041 numauthpriv = 2;
1056 authpriv = calloc (numauthpriv, sizeof (char *)); 1042 authpriv = calloc(numauthpriv, sizeof(char *));
1057 authpriv[0] = strdup ("-c"); 1043 authpriv[0] = strdup("-c");
1058 authpriv[1] = strdup (community); 1044 authpriv[1] = strdup(community);
1059 } 1045 } else if (strcmp(proto, "3") == 0) { /* snmpv3 args */
1060 else if ( strcmp (proto, "3") == 0 ) { /* snmpv3 args */
1061 if (!(context == NULL)) { 1046 if (!(context == NULL)) {
1062 numcontext = 2; 1047 numcontext = 2;
1063 contextargs = calloc (numcontext, sizeof (char *)); 1048 contextargs = calloc(numcontext, sizeof(char *));
1064 contextargs[0] = strdup ("-n"); 1049 contextargs[0] = strdup("-n");
1065 contextargs[1] = strdup (context); 1050 contextargs[1] = strdup(context);
1066 } 1051 }
1067 1052
1068 if (seclevel == NULL) 1053 if (seclevel == NULL)
@@ -1073,284 +1058,266 @@ validate_arguments ()
1073 1058
1074 if (strcmp(seclevel, "noAuthNoPriv") == 0) { 1059 if (strcmp(seclevel, "noAuthNoPriv") == 0) {
1075 numauthpriv = 4; 1060 numauthpriv = 4;
1076 authpriv = calloc (numauthpriv, sizeof (char *)); 1061 authpriv = calloc(numauthpriv, sizeof(char *));
1077 authpriv[0] = strdup ("-l"); 1062 authpriv[0] = strdup("-l");
1078 authpriv[1] = strdup ("noAuthNoPriv"); 1063 authpriv[1] = strdup("noAuthNoPriv");
1079 authpriv[2] = strdup ("-u"); 1064 authpriv[2] = strdup("-u");
1080 authpriv[3] = strdup (secname); 1065 authpriv[3] = strdup(secname);
1081 } else { 1066 } else {
1082 if (! ( (strcmp(seclevel, "authNoPriv")==0) || (strcmp(seclevel, "authPriv")==0) ) ) { 1067 if (!((strcmp(seclevel, "authNoPriv") == 0) || (strcmp(seclevel, "authPriv") == 0))) {
1083 usage2 (_("Invalid seclevel"), seclevel); 1068 usage2(_("Invalid seclevel"), seclevel);
1084 } 1069 }
1085 1070
1086 if (authproto == NULL ) 1071 if (authproto == NULL)
1087 xasprintf(&authproto, DEFAULT_AUTH_PROTOCOL); 1072 xasprintf(&authproto, DEFAULT_AUTH_PROTOCOL);
1088 1073
1089 if (authpasswd == NULL) 1074 if (authpasswd == NULL)
1090 die(STATE_UNKNOWN, _("Required parameter: %s\n"), "authpasswd"); 1075 die(STATE_UNKNOWN, _("Required parameter: %s\n"), "authpasswd");
1091 1076
1092 if ( strcmp(seclevel, "authNoPriv") == 0 ) { 1077 if (strcmp(seclevel, "authNoPriv") == 0) {
1093 numauthpriv = 8; 1078 numauthpriv = 8;
1094 authpriv = calloc (numauthpriv, sizeof (char *)); 1079 authpriv = calloc(numauthpriv, sizeof(char *));
1095 authpriv[0] = strdup ("-l"); 1080 authpriv[0] = strdup("-l");
1096 authpriv[1] = strdup ("authNoPriv"); 1081 authpriv[1] = strdup("authNoPriv");
1097 authpriv[2] = strdup ("-a"); 1082 authpriv[2] = strdup("-a");
1098 authpriv[3] = strdup (authproto); 1083 authpriv[3] = strdup(authproto);
1099 authpriv[4] = strdup ("-u"); 1084 authpriv[4] = strdup("-u");
1100 authpriv[5] = strdup (secname); 1085 authpriv[5] = strdup(secname);
1101 authpriv[6] = strdup ("-A"); 1086 authpriv[6] = strdup("-A");
1102 authpriv[7] = strdup (authpasswd); 1087 authpriv[7] = strdup(authpasswd);
1103 } else if ( strcmp(seclevel, "authPriv") == 0 ) { 1088 } else if (strcmp(seclevel, "authPriv") == 0) {
1104 if (privproto == NULL ) 1089 if (privproto == NULL)
1105 xasprintf(&privproto, DEFAULT_PRIV_PROTOCOL); 1090 xasprintf(&privproto, DEFAULT_PRIV_PROTOCOL);
1106 1091
1107 if (privpasswd == NULL) 1092 if (privpasswd == NULL)
1108 die(STATE_UNKNOWN, _("Required parameter: %s\n"), "privpasswd"); 1093 die(STATE_UNKNOWN, _("Required parameter: %s\n"), "privpasswd");
1109 1094
1110 numauthpriv = 12; 1095 numauthpriv = 12;
1111 authpriv = calloc (numauthpriv, sizeof (char *)); 1096 authpriv = calloc(numauthpriv, sizeof(char *));
1112 authpriv[0] = strdup ("-l"); 1097 authpriv[0] = strdup("-l");
1113 authpriv[1] = strdup ("authPriv"); 1098 authpriv[1] = strdup("authPriv");
1114 authpriv[2] = strdup ("-a"); 1099 authpriv[2] = strdup("-a");
1115 authpriv[3] = strdup (authproto); 1100 authpriv[3] = strdup(authproto);
1116 authpriv[4] = strdup ("-u"); 1101 authpriv[4] = strdup("-u");
1117 authpriv[5] = strdup (secname); 1102 authpriv[5] = strdup(secname);
1118 authpriv[6] = strdup ("-A"); 1103 authpriv[6] = strdup("-A");
1119 authpriv[7] = strdup (authpasswd); 1104 authpriv[7] = strdup(authpasswd);
1120 authpriv[8] = strdup ("-x"); 1105 authpriv[8] = strdup("-x");
1121 authpriv[9] = strdup (privproto); 1106 authpriv[9] = strdup(privproto);
1122 authpriv[10] = strdup ("-X"); 1107 authpriv[10] = strdup("-X");
1123 authpriv[11] = strdup (privpasswd); 1108 authpriv[11] = strdup(privpasswd);
1124 } 1109 }
1125 } 1110 }
1126 1111
1127 } 1112 } else {
1128 else { 1113 usage2(_("Invalid SNMP version"), proto);
1129 usage2 (_("Invalid SNMP version"), proto);
1130 } 1114 }
1131 1115
1132 return OK; 1116 return OK;
1133} 1117}
1134 1118
1135
1136
1137/* trim leading whitespace 1119/* trim leading whitespace
1138 if there is a leading quote, make sure it balances */ 1120 if there is a leading quote, make sure it balances */
1139 1121
1140static char * 1122static char *thisarg(char *str) {
1141thisarg (char *str) 1123 str += strspn(str, " \t\r\n"); /* trim any leading whitespace */
1142{ 1124 if (str[0] == '\'') { /* handle SIMPLE quoted strings */
1143 str += strspn (str, " \t\r\n"); /* trim any leading whitespace */ 1125 if (strlen(str) == 1 || !strstr(str + 1, "'"))
1144 if (str[0] == '\'') { /* handle SIMPLE quoted strings */ 1126 die(STATE_UNKNOWN, _("Unbalanced quotes\n"));
1145 if (strlen (str) == 1 || !strstr (str + 1, "'"))
1146 die (STATE_UNKNOWN, _("Unbalanced quotes\n"));
1147 } 1127 }
1148 return str; 1128 return str;
1149} 1129}
1150 1130
1151
1152
1153/* if there's a leading quote, advance to the trailing quote 1131/* if there's a leading quote, advance to the trailing quote
1154 set the trailing quote to '\x0' 1132 set the trailing quote to '\x0'
1155 if the string continues, advance beyond the comma */ 1133 if the string continues, advance beyond the comma */
1156 1134
1157static char * 1135static char *nextarg(char *str) {
1158nextarg (char *str)
1159{
1160 if (str[0] == '\'') { 1136 if (str[0] == '\'') {
1161 str[0] = 0; 1137 str[0] = 0;
1162 if (strlen (str) > 1) { 1138 if (strlen(str) > 1) {
1163 str = strstr (str + 1, "'"); 1139 str = strstr(str + 1, "'");
1164 return (++str); 1140 return (++str);
1165 } 1141 } else {
1166 else {
1167 return NULL; 1142 return NULL;
1168 } 1143 }
1169 } 1144 }
1170 if (str[0] == ',') { 1145 if (str[0] == ',') {
1171 str[0] = 0; 1146 str[0] = 0;
1172 if (strlen (str) > 1) { 1147 if (strlen(str) > 1) {
1173 return (++str); 1148 return (++str);
1174 } 1149 } else {
1175 else {
1176 return NULL; 1150 return NULL;
1177 } 1151 }
1178 } 1152 }
1179 if ((str = strstr (str, ",")) && strlen (str) > 1) { 1153 if ((str = strstr(str, ",")) && strlen(str) > 1) {
1180 str[0] = 0; 1154 str[0] = 0;
1181 return (++str); 1155 return (++str);
1182 } 1156 }
1183 return NULL; 1157 return NULL;
1184} 1158}
1185 1159
1186
1187
1188/* multiply result (values 0 < n < 1 work as divider) */ 1160/* multiply result (values 0 < n < 1 work as divider) */
1189static char * 1161static char *multiply(char *str) {
1190multiply (char *str) 1162 if (multiplier == 1)
1191{ 1163 return (str);
1192 char *endptr;
1193 double val;
1194 char *conv = "%f";
1195
1196 if(multiplier == 1)
1197 return(str);
1198 1164
1199 if(verbose>2) 1165 if (verbose > 2)
1200 printf(" multiply input: %s\n", str); 1166 printf(" multiply input: %s\n", str);
1201 1167
1202 val = strtod (str, &endptr); 1168 char *endptr;
1169 double val = strtod(str, &endptr);
1203 if ((val == 0.0) && (endptr == str)) { 1170 if ((val == 0.0) && (endptr == str)) {
1204 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);
1205 } 1172 }
1206 1173
1207 if(verbose>2) 1174 if (verbose > 2)
1208 printf(" multiply extracted double: %f\n", val); 1175 printf(" multiply extracted double: %f\n", val);
1176
1209 val *= multiplier; 1177 val *= multiplier;
1178 char *conv = "%f";
1210 if (fmtstr_set) { 1179 if (fmtstr_set) {
1211 conv = fmtstr; 1180 conv = fmtstr;
1212 } 1181 }
1213 if (val == (int)val) { 1182 if (val == (int)val) {
1214 snprintf(buffer, DEFAULT_BUFFER_SIZE, "%.0f", val); 1183 snprintf(buffer, DEFAULT_BUFFER_SIZE, "%.0f", val);
1215 } else { 1184 } else {
1216 if(verbose>2) 1185 if (verbose > 2)
1217 printf(" multiply using format: %s\n", conv); 1186 printf(" multiply using format: %s\n", conv);
1218 snprintf(buffer, DEFAULT_BUFFER_SIZE, conv, val); 1187 snprintf(buffer, DEFAULT_BUFFER_SIZE, conv, val);
1219 } 1188 }
1220 if(verbose>2) 1189 if (verbose > 2)
1221 printf(" multiply result: %s\n", buffer); 1190 printf(" multiply result: %s\n", buffer);
1222 return buffer; 1191 return buffer;
1223} 1192}
1224 1193
1194static void print_help(void) {
1195 print_revision(progname, NP_VERSION);
1225 1196
1226static void 1197 printf(COPYRIGHT, copyright, email);
1227print_help (void)
1228{
1229 print_revision (progname, NP_VERSION);
1230
1231 printf (COPYRIGHT, copyright, email);
1232 1198
1233 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"));
1234 1200
1235 printf ("\n\n"); 1201 printf("\n\n");
1236 1202
1237 print_usage (); 1203 print_usage();
1238 1204
1239 printf (UT_HELP_VRSN); 1205 printf(UT_HELP_VRSN);
1240 printf (UT_EXTRA_OPTS); 1206 printf(UT_EXTRA_OPTS);
1241 printf (UT_IPv46); 1207 printf(UT_IPv46);
1242 1208
1243 printf (UT_HOST_PORT, 'p', DEFAULT_PORT); 1209 printf(UT_HOST_PORT, 'p', DEFAULT_PORT);
1244 1210
1245 /* SNMP and Authentication Protocol */ 1211 /* SNMP and Authentication Protocol */
1246 printf (" %s\n", "-n, --next"); 1212 printf(" %s\n", "-n, --next");
1247 printf (" %s\n", _("Use SNMP GETNEXT instead of SNMP GET")); 1213 printf(" %s\n", _("Use SNMP GETNEXT instead of SNMP GET"));
1248 printf (" %s\n", "-P, --protocol=[1|2c|3]"); 1214 printf(" %s\n", "-P, --protocol=[1|2c|3]");
1249 printf (" %s\n", _("SNMP protocol version")); 1215 printf(" %s\n", _("SNMP protocol version"));
1250 printf (" %s\n", "-N, --context=CONTEXT"); 1216 printf(" %s\n", "-N, --context=CONTEXT");
1251 printf (" %s\n", _("SNMPv3 context")); 1217 printf(" %s\n", _("SNMPv3 context"));
1252 printf (" %s\n", "-L, --seclevel=[noAuthNoPriv|authNoPriv|authPriv]"); 1218 printf(" %s\n", "-L, --seclevel=[noAuthNoPriv|authNoPriv|authPriv]");
1253 printf (" %s\n", _("SNMPv3 securityLevel")); 1219 printf(" %s\n", _("SNMPv3 securityLevel"));
1254 printf (" %s\n", "-a, --authproto=AUTHENTICATION_PROTOCOL"); 1220 printf(" %s\n", "-a, --authproto=AUTHENTICATION_PROTOCOL");
1255 printf (" %s\n", _("SNMPv3 authentication protocol (default MD5), available options depend on the specific version of the net-snmp tools")); 1221 printf(" %s\n",
1256 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")); 1222 _("SNMPv3 authentication protocol (default MD5), available options depend on the specific version of the net-snmp tools"));
1257 printf (" %s\n", "-x, --privproto=PRIVACY_PROTOCOL"); 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"));
1258 printf (" %s\n", _("SNMPv3 privacy protocol (default DES), available options depend on the specific version of the net-snmp tools")); 1224 printf(" %s\n", "-x, --privproto=PRIVACY_PROTOCOL");
1259 printf (" %s\n", _("if < 5.8 DES and AES should be available, if >= 5.8 additionally AES-192 and AES-256")); 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 34ef37b..e9c55ad 100644
--- a/plugins/check_ssh.c
+++ b/plugins/check_ssh.c
@@ -3,7 +3,7 @@
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*
@@ -29,7 +29,7 @@
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"
diff --git a/plugins/check_tcp.c b/plugins/check_tcp.c
index 01dd35e..c13ac76 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 f50ea42..d1f5068 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 f60c0e9..adb7ab8 100644
--- a/plugins/check_ups.c
+++ b/plugins/check_ups.c
@@ -40,7 +40,9 @@ const char *email = "devel@monitoring-plugins.org";
40#include "netutils.h" 40#include "netutils.h"
41#include "utils.h" 41#include "utils.h"
42 42
43enum { PORT = 3493 }; 43enum {
44 PORT = 3493
45};
44 46
45#define UPS_NONE 0 /* no supported options */ 47#define UPS_NONE 0 /* no supported options */
46#define UPS_UTILITY 1 /* supports utility line */ 48#define UPS_UTILITY 1 /* supports utility line */
@@ -66,7 +68,9 @@ enum { PORT = 3493 };
66#define UPSSTATUS_UNKNOWN 4096 68#define UPSSTATUS_UNKNOWN 4096
67#define UPSSTATUS_ALARM 8192 69#define UPSSTATUS_ALARM 8192
68 70
69enum { NOSUCHVAR = ERROR - 1 }; 71enum {
72 NOSUCHVAR = ERROR - 1
73};
70 74
71typedef struct ups_config { 75typedef struct ups_config {
72 unsigned int server_port; 76 unsigned int server_port;
diff --git a/plugins/check_users.c b/plugins/check_users.c
index 89b9536..f1e1c39 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 c5fe7e1..7e52fe6 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,185 +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 only the return code of a plugin (returns OK for CRITICAL and vice-versa) by default.")); 206 printf("\n\n");
224 printf ("%s\n", _("Additional switches can be used to control:\n"));
225 printf ("\t - which state becomes what\n");
226 printf ("\t - changing the plugin output text to match the return code");
227 207
228 printf ("\n\n"); 208 print_usage();
229 209
230 print_usage (); 210 printf(UT_HELP_VRSN);
231 211
232 printf (UT_HELP_VRSN); 212 printf(UT_PLUG_TIMEOUT, timeout_interval);
233 213 printf(" %s\n", _("Keep timeout longer than the plugin timeout to retain CRITICAL status."));
234 printf (UT_PLUG_TIMEOUT, timeout_interval); 214 printf(" -T, --timeout-result=STATUS\n");
235 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"));
236 printf (" -T, --timeout-result=STATUS\n");
237 printf (" %s\n", _("Custom result on Negate timeouts; see below for STATUS definition\n"));
238 216
239 printf(" -o, --ok=STATUS\n"); 217 printf(" -o, --ok=STATUS\n");
240 printf(" -w, --warning=STATUS\n"); 218 printf(" -w, --warning=STATUS\n");
@@ -246,31 +224,27 @@ print_help (void)
246 printf(" -s, --substitute\n"); 224 printf(" -s, --substitute\n");
247 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"));
248 226
249 printf ("\n"); 227 printf("\n");
250 printf ("%s\n", _("Examples:")); 228 printf("%s\n", _("Examples:"));
251 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");
252 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"));
253 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'");
254 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"));
255 printf ("\n"); 233 printf("\n");
256 printf ("%s\n", _("Notes:")); 234 printf("%s\n", _("Notes:"));
257 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."));
258 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."));
259 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."));
260 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."));
261 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."));
262 printf ("\n"); 240 printf("\n");
263 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"));
264 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."));
265 243
266 printf (UT_SUPPORT); 244 printf(UT_SUPPORT);
267} 245}
268 246
269 247void print_usage(void) {
270 248 printf("%s\n", _("Usage:"));
271void 249 printf("%s [-t timeout] [-Towcu STATE] [-s] <definition of wrapped plugin>\n", progname);
272print_usage (void)
273{
274 printf ("%s\n", _("Usage:"));
275 printf ("%s [-t timeout] [-Towcu STATE] [-s] <definition of wrapped plugin>\n", progname);
276} 250}
diff --git a/plugins/netutils.c b/plugins/netutils.c
index c6af248..ee81912 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 d0bfac6..2ae92d6 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 54e63bc..2b9824b 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 ed49bb9..2e53dc0 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 6bc0ba8..3c92841 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/urlize.c b/plugins/urlize.c
index 6fda72d..1aa4e42 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 77d6a6f..f11db73 100644
--- a/plugins/utils.c
+++ b/plugins/utils.c
@@ -1,26 +1,26 @@
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"
@@ -34,7 +34,7 @@
34 34
35#include <arpa/inet.h> 35#include <arpa/inet.h>
36 36
37extern void print_usage (void); 37extern void print_usage(void);
38extern const char *progname; 38extern const char *progname;
39 39
40#define STRLEN 64 40#define STRLEN 64
@@ -50,9 +50,7 @@ time_t start_time, end_time;
50 * Note that numerically the above does not hold 50 * Note that numerically the above does not hold
51 ****************************************************************************/ 51 ****************************************************************************/
52 52
53int 53int max_state(int a, int b) {
54max_state (int a, int b)
55{
56 if (a == STATE_CRITICAL || b == STATE_CRITICAL) 54 if (a == STATE_CRITICAL || b == STATE_CRITICAL)
57 return STATE_CRITICAL; 55 return STATE_CRITICAL;
58 else if (a == STATE_WARNING || b == STATE_WARNING) 56 else if (a == STATE_WARNING || b == STATE_WARNING)
@@ -64,7 +62,7 @@ max_state (int a, int b)
64 else if (a == STATE_DEPENDENT || b == STATE_DEPENDENT) 62 else if (a == STATE_DEPENDENT || b == STATE_DEPENDENT)
65 return STATE_DEPENDENT; 63 return STATE_DEPENDENT;
66 else 64 else
67 return max (a, b); 65 return max(a, b);
68} 66}
69 67
70/* ************************************************************************** 68/* **************************************************************************
@@ -77,9 +75,7 @@ max_state (int a, int b)
77 * non-OK state. 75 * non-OK state.
78 ****************************************************************************/ 76 ****************************************************************************/
79 77
80int 78int max_state_alt(int a, int b) {
81max_state_alt (int a, int b)
82{
83 if (a == STATE_CRITICAL || b == STATE_CRITICAL) 79 if (a == STATE_CRITICAL || b == STATE_CRITICAL)
84 return STATE_CRITICAL; 80 return STATE_CRITICAL;
85 else if (a == STATE_WARNING || b == STATE_WARNING) 81 else if (a == STATE_WARNING || b == STATE_WARNING)
@@ -91,124 +87,112 @@ max_state_alt (int a, int b)
91 else if (a == STATE_OK || b == STATE_OK) 87 else if (a == STATE_OK || b == STATE_OK)
92 return STATE_OK; 88 return STATE_OK;
93 else 89 else
94 return max (a, b); 90 return max(a, b);
95} 91}
96 92
97void usage (const char *msg) 93void usage(const char *msg) {
98{ 94 printf("%s\n", msg);
99 printf ("%s\n", msg); 95 print_usage();
100 print_usage (); 96 exit(STATE_UNKNOWN);
101 exit (STATE_UNKNOWN);
102} 97}
103 98
104void usage_va (const char *fmt, ...) 99void usage_va(const char *fmt, ...) {
105{
106 va_list ap; 100 va_list ap;
107 printf("%s: ", progname); 101 printf("%s: ", progname);
108 va_start(ap, fmt); 102 va_start(ap, fmt);
109 vprintf(fmt, ap); 103 vprintf(fmt, ap);
110 va_end(ap); 104 va_end(ap);
111 printf("\n"); 105 printf("\n");
112 exit (STATE_UNKNOWN); 106 exit(STATE_UNKNOWN);
113} 107}
114 108
115void usage2(const char *msg, const char *arg) 109void usage2(const char *msg, const char *arg) {
116{ 110 printf("%s: %s - %s\n", progname, msg, arg ? arg : "(null)");
117 printf ("%s: %s - %s\n", progname, msg, arg?arg:"(null)" ); 111 print_usage();
118 print_usage (); 112 exit(STATE_UNKNOWN);
119 exit (STATE_UNKNOWN);
120} 113}
121 114
122void 115void usage3(const char *msg, int arg) {
123usage3 (const char *msg, int arg) 116 printf("%s: %s - %c\n", progname, msg, arg);
124{
125 printf ("%s: %s - %c\n", progname, msg, arg);
126 print_usage(); 117 print_usage();
127 exit (STATE_UNKNOWN); 118 exit(STATE_UNKNOWN);
128} 119}
129 120
130void 121void usage4(const char *msg) {
131usage4 (const char *msg) 122 printf("%s: %s\n", progname, msg);
132{
133 printf ("%s: %s\n", progname, msg);
134 print_usage(); 123 print_usage();
135 exit (STATE_UNKNOWN); 124 exit(STATE_UNKNOWN);
136} 125}
137 126
138void 127void usage5(void) {
139usage5 (void)
140{
141 print_usage(); 128 print_usage();
142 exit (STATE_UNKNOWN); 129 exit(STATE_UNKNOWN);
143} 130}
144 131
145void 132void print_revision(const char *command_name, const char *revision) {
146print_revision (const char *command_name, const char *revision) 133 printf("%s v%s (%s %s)\n", command_name, revision, PACKAGE, VERSION);
147{
148 printf ("%s v%s (%s %s)\n",
149 command_name, revision, PACKAGE, VERSION);
150} 134}
151 135
152bool is_numeric (char *number) { 136bool is_numeric(char *number) {
153 char tmp[1]; 137 char tmp[1];
154 float x; 138 float x;
155 139
156 if (!number) 140 if (!number)
157 return false; 141 return false;
158 else if (sscanf (number, "%f%c", &x, tmp) == 1) 142 else if (sscanf(number, "%f%c", &x, tmp) == 1)
159 return true; 143 return true;
160 else 144 else
161 return false; 145 return false;
162} 146}
163 147
164bool is_positive (char *number) { 148bool is_positive(char *number) {
165 if (is_numeric (number) && atof (number) > 0.0) 149 if (is_numeric(number) && atof(number) > 0.0)
166 return true; 150 return true;
167 else 151 else
168 return false; 152 return false;
169} 153}
170 154
171bool is_negative (char *number) { 155bool is_negative(char *number) {
172 if (is_numeric (number) && atof (number) < 0.0) 156 if (is_numeric(number) && atof(number) < 0.0)
173 return true; 157 return true;
174 else 158 else
175 return false; 159 return false;
176} 160}
177 161
178bool is_nonnegative (char *number) { 162bool is_nonnegative(char *number) {
179 if (is_numeric (number) && atof (number) >= 0.0) 163 if (is_numeric(number) && atof(number) >= 0.0)
180 return true; 164 return true;
181 else 165 else
182 return false; 166 return false;
183} 167}
184 168
185bool is_percentage (char *number) { 169bool is_percentage(char *number) {
186 int x; 170 int x;
187 if (is_numeric (number) && (x = atof (number)) >= 0 && x <= 100) 171 if (is_numeric(number) && (x = atof(number)) >= 0 && x <= 100)
188 return true; 172 return true;
189 else 173 else
190 return false; 174 return false;
191} 175}
192 176
193bool is_percentage_expression (const char str[]) { 177bool is_percentage_expression(const char str[]) {
194 if (!str) { 178 if (!str) {
195 return false; 179 return false;
196 } 180 }
197 181
198 size_t len = strlen(str); 182 size_t len = strlen(str);
199 183
200 if (str[len-1] != '%') { 184 if (str[len - 1] != '%') {
201 return false; 185 return false;
202 } 186 }
203 187
204 char *foo = calloc(sizeof(char), len + 1); 188 char *foo = calloc(sizeof(char), len + 1);
205 189
206 if (!foo) { 190 if (!foo) {
207 die (STATE_UNKNOWN, _("calloc failed \n")); 191 die(STATE_UNKNOWN, _("calloc failed \n"));
208 } 192 }
209 193
210 strcpy(foo, str); 194 strcpy(foo, str);
211 foo[len-1] = '\0'; 195 foo[len - 1] = '\0';
212 196
213 bool result = is_numeric(foo); 197 bool result = is_numeric(foo);
214 198
@@ -217,13 +201,13 @@ bool is_percentage_expression (const char str[]) {
217 return result; 201 return result;
218} 202}
219 203
220bool is_integer (char *number) { 204bool is_integer(char *number) {
221 long int n; 205 long int n;
222 206
223 if (!number || (strspn (number, "-0123456789 ") != strlen (number))) 207 if (!number || (strspn(number, "-0123456789 ") != strlen(number)))
224 return false; 208 return false;
225 209
226 n = strtol (number, NULL, 10); 210 n = strtol(number, NULL, 10);
227 211
228 if (errno != ERANGE && n >= INT_MIN && n <= INT_MAX) 212 if (errno != ERANGE && n >= INT_MIN && n <= INT_MAX)
229 return true; 213 return true;
@@ -231,22 +215,22 @@ bool is_integer (char *number) {
231 return false; 215 return false;
232} 216}
233 217
234bool is_intpos (char *number) { 218bool is_intpos(char *number) {
235 if (is_integer (number) && atoi (number) > 0) 219 if (is_integer(number) && atoi(number) > 0)
236 return true; 220 return true;
237 else 221 else
238 return false; 222 return false;
239} 223}
240 224
241bool is_intneg (char *number) { 225bool is_intneg(char *number) {
242 if (is_integer (number) && atoi (number) < 0) 226 if (is_integer(number) && atoi(number) < 0)
243 return true; 227 return true;
244 else 228 else
245 return false; 229 return false;
246} 230}
247 231
248bool is_intnonneg (char *number) { 232bool is_intnonneg(char *number) {
249 if (is_integer (number) && atoi (number) >= 0) 233 if (is_integer(number) && atoi(number) >= 0)
250 return true; 234 return true;
251 else 235 else
252 return false; 236 return false;
@@ -259,7 +243,7 @@ bool is_intnonneg (char *number) {
259 */ 243 */
260bool is_int64(char *number, int64_t *target) { 244bool is_int64(char *number, int64_t *target) {
261 errno = 0; 245 errno = 0;
262 char *endptr = { 0 }; 246 char *endptr = {0};
263 247
264 int64_t tmp = strtoll(number, &endptr, 10); 248 int64_t tmp = strtoll(number, &endptr, 10);
265 if (errno != 0) { 249 if (errno != 0) {
@@ -287,7 +271,7 @@ bool is_int64(char *number, int64_t *target) {
287 */ 271 */
288bool is_uint64(char *number, uint64_t *target) { 272bool is_uint64(char *number, uint64_t *target) {
289 errno = 0; 273 errno = 0;
290 char *endptr = { 0 }; 274 char *endptr = {0};
291 unsigned long long tmp = strtoull(number, &endptr, 10); 275 unsigned long long tmp = strtoull(number, &endptr, 10);
292 276
293 if (errno != 0) { 277 if (errno != 0) {
@@ -309,66 +293,50 @@ bool is_uint64(char *number, uint64_t *target) {
309 return true; 293 return true;
310} 294}
311 295
312bool is_intpercent (char *number) { 296bool is_intpercent(char *number) {
313 int i; 297 int i;
314 if (is_integer (number) && (i = atoi (number)) >= 0 && i <= 100) 298 if (is_integer(number) && (i = atoi(number)) >= 0 && i <= 100)
315 return true; 299 return true;
316 else 300 else
317 return false; 301 return false;
318} 302}
319 303
320bool is_option (char *str) { 304bool is_option(char *str) {
321 if (!str) 305 if (!str)
322 return false; 306 return false;
323 else if (strspn (str, "-") == 1 || strspn (str, "-") == 2) 307 else if (strspn(str, "-") == 1 || strspn(str, "-") == 2)
324 return true; 308 return true;
325 else 309 else
326 return false; 310 return false;
327} 311}
328 312
329#ifdef NEED_GETTIMEOFDAY 313#ifdef NEED_GETTIMEOFDAY
330int 314int gettimeofday(struct timeval *tv, struct timezone *tz) {
331gettimeofday (struct timeval *tv, struct timezone *tz)
332{
333 tv->tv_usec = 0; 315 tv->tv_usec = 0;
334 tv->tv_sec = (long) time ((time_t) 0); 316 tv->tv_sec = (long)time((time_t)0);
335} 317}
336#endif 318#endif
337 319
338 320double delta_time(struct timeval tv) {
339
340double
341delta_time (struct timeval tv)
342{
343 struct timeval now; 321 struct timeval now;
344 322
345 gettimeofday (&now, NULL); 323 gettimeofday(&now, NULL);
346 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);
347} 325}
348 326
349 327long deltime(struct timeval tv) {
350
351long
352deltime (struct timeval tv)
353{
354 struct timeval now; 328 struct timeval now;
355 gettimeofday (&now, NULL); 329 gettimeofday(&now, NULL);
356 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;
357} 331}
358 332
359 333void strip(char *buffer) {
360
361
362void
363strip (char *buffer)
364{
365 size_t x; 334 size_t x;
366 int i; 335 int i;
367 336
368 for (x = strlen (buffer); x >= 1; x--) { 337 for (x = strlen(buffer); x >= 1; x--) {
369 i = x - 1; 338 i = x - 1;
370 if (buffer[i] == ' ' || 339 if (buffer[i] == ' ' || buffer[i] == '\r' || buffer[i] == '\n' || buffer[i] == '\t')
371 buffer[i] == '\r' || buffer[i] == '\n' || buffer[i] == '\t')
372 buffer[i] = '\0'; 340 buffer[i] = '\0';
373 else 341 else
374 break; 342 break;
@@ -376,7 +344,6 @@ strip (char *buffer)
376 return; 344 return;
377} 345}
378 346
379
380/****************************************************************************** 347/******************************************************************************
381 * 348 *
382 * Copies one string to another. Any previously existing data in 349 * Copies one string to another. Any previously existing data in
@@ -389,19 +356,15 @@ strip (char *buffer)
389 * 356 *
390 *****************************************************************************/ 357 *****************************************************************************/
391 358
392char * 359char *strscpy(char *dest, const char *src) {
393strscpy (char *dest, const char *src)
394{
395 if (src == NULL) 360 if (src == NULL)
396 return NULL; 361 return NULL;
397 362
398 xasprintf (&dest, "%s", src); 363 xasprintf(&dest, "%s", src);
399 364
400 return dest; 365 return dest;
401} 366}
402 367
403
404
405/****************************************************************************** 368/******************************************************************************
406 * 369 *
407 * 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
@@ -418,7 +381,7 @@ strscpy (char *dest, const char *src)
418 * This 381 * This
419 * is 382 * is
420 * a 383 * a
421 * 384 *
422 * multiline string buffer 385 * multiline string buffer
423 * ============================== 386 * ==============================
424 * 387 *
@@ -431,7 +394,7 @@ strscpy (char *dest, const char *src)
431 * printf("%d %s",i++,firstword(ptr)); 394 * printf("%d %s",i++,firstword(ptr));
432 * ptr = strnl(ptr); 395 * ptr = strnl(ptr);
433 * } 396 * }
434 * 397 *
435 * Produces the following: 398 * Produces the following:
436 * 399 *
437 * 1 This 400 * 1 This
@@ -452,25 +415,22 @@ strscpy (char *dest, const char *src)
452 * 415 *
453 *****************************************************************************/ 416 *****************************************************************************/
454 417
455char * 418char *strnl(char *str) {
456strnl (char *str)
457{
458 size_t len; 419 size_t len;
459 if (str == NULL) 420 if (str == NULL)
460 return NULL; 421 return NULL;
461 str = strpbrk (str, "\r\n"); 422 str = strpbrk(str, "\r\n");
462 if (str == NULL) 423 if (str == NULL)
463 return NULL; 424 return NULL;
464 len = strspn (str, "\r\n"); 425 len = strspn(str, "\r\n");
465 if (str[len] == '\0') 426 if (str[len] == '\0')
466 return NULL; 427 return NULL;
467 str += len; 428 str += len;
468 if (strlen (str) == 0) 429 if (strlen(str) == 0)
469 return NULL; 430 return NULL;
470 return str; 431 return str;
471} 432}
472 433
473
474/****************************************************************************** 434/******************************************************************************
475 * 435 *
476 * 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
@@ -487,29 +447,25 @@ strnl (char *str)
487 * 447 *
488 *****************************************************************************/ 448 *****************************************************************************/
489 449
490char * 450char *strpcpy(char *dest, const char *src, const char *str) {
491strpcpy (char *dest, const char *src, const char *str)
492{
493 size_t len; 451 size_t len;
494 452
495 if (src) 453 if (src)
496 len = strcspn (src, str); 454 len = strcspn(src, str);
497 else 455 else
498 return NULL; 456 return NULL;
499 457
500 if (dest == NULL || strlen (dest) < len) 458 if (dest == NULL || strlen(dest) < len)
501 dest = realloc (dest, len + 1); 459 dest = realloc(dest, len + 1);
502 if (dest == NULL) 460 if (dest == NULL)
503 die (STATE_UNKNOWN, _("failed realloc in strpcpy\n")); 461 die(STATE_UNKNOWN, _("failed realloc in strpcpy\n"));
504 462
505 strncpy (dest, src, len); 463 strncpy(dest, src, len);
506 dest[len] = '\0'; 464 dest[len] = '\0';
507 465
508 return dest; 466 return dest;
509} 467}
510 468
511
512
513/****************************************************************************** 469/******************************************************************************
514 * 470 *
515 * 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
@@ -518,62 +474,54 @@ strpcpy (char *dest, const char *src, const char *str)
518 * 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");
519 * 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");
520 * printf("%s\n",str); 476 * printf("%s\n",str);
521 * 477 *
522 *This is a line of texThis is a line of tex 478 *This is a line of texThis is a line of tex
523 * 479 *
524 *****************************************************************************/ 480 *****************************************************************************/
525 481
526char * 482char *strpcat(char *dest, const char *src, const char *str) {
527strpcat (char *dest, const char *src, const char *str)
528{
529 size_t len, l2; 483 size_t len, l2;
530 484
531 if (dest) 485 if (dest)
532 len = strlen (dest); 486 len = strlen(dest);
533 else 487 else
534 len = 0; 488 len = 0;
535 489
536 if (src) { 490 if (src) {
537 l2 = strcspn (src, str); 491 l2 = strcspn(src, str);
538 } 492 } else {
539 else {
540 return dest; 493 return dest;
541 } 494 }
542 495
543 dest = realloc (dest, len + l2 + 1); 496 dest = realloc(dest, len + l2 + 1);
544 if (dest == NULL) 497 if (dest == NULL)
545 die (STATE_UNKNOWN, _("failed malloc in strscat\n")); 498 die(STATE_UNKNOWN, _("failed malloc in strscat\n"));
546 499
547 strncpy (dest + len, src, l2); 500 strncpy(dest + len, src, l2);
548 dest[len + l2] = '\0'; 501 dest[len + l2] = '\0';
549 502
550 return dest; 503 return dest;
551} 504}
552 505
553
554/****************************************************************************** 506/******************************************************************************
555 * 507 *
556 * asprintf, but die on failure 508 * asprintf, but die on failure
557 * 509 *
558 ******************************************************************************/ 510 ******************************************************************************/
559 511
560int 512int xvasprintf(char **strp, const char *fmt, va_list ap) {
561xvasprintf (char **strp, const char *fmt, va_list ap) 513 int result = vasprintf(strp, fmt, ap);
562{
563 int result = vasprintf (strp, fmt, ap);
564 if (result == -1 || *strp == NULL) 514 if (result == -1 || *strp == NULL)
565 die (STATE_UNKNOWN, _("failed malloc in xvasprintf\n")); 515 die(STATE_UNKNOWN, _("failed malloc in xvasprintf\n"));
566 return result; 516 return result;
567} 517}
568 518
569int 519int xasprintf(char **strp, const char *fmt, ...) {
570xasprintf (char **strp, const char *fmt, ...)
571{
572 va_list ap; 520 va_list ap;
573 int result; 521 int result;
574 va_start (ap, fmt); 522 va_start(ap, fmt);
575 result = xvasprintf (strp, fmt, ap); 523 result = xvasprintf(strp, fmt, ap);
576 va_end (ap); 524 va_end(ap);
577 return result; 525 return result;
578} 526}
579 527
@@ -583,247 +531,192 @@ xasprintf (char **strp, const char *fmt, ...)
583 * 531 *
584 ******************************************************************************/ 532 ******************************************************************************/
585 533
586char *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,
587 long int val, 535 long int minv, int maxp, long int maxv) {
588 const char *uom,
589 int warnp,
590 long int warn,
591 int critp,
592 long int crit,
593 int minp,
594 long int minv,
595 int maxp,
596 long int maxv)
597{
598 char *data = NULL; 536 char *data = NULL;
599 537
600 if (strpbrk (label, "'= ")) 538 if (strpbrk(label, "'= "))
601 xasprintf (&data, "'%s'=%ld%s;", label, val, uom); 539 xasprintf(&data, "'%s'=%ld%s;", label, val, uom);
602 else 540 else
603 xasprintf (&data, "%s=%ld%s;", label, val, uom); 541 xasprintf(&data, "%s=%ld%s;", label, val, uom);
604 542
605 if (warnp) 543 if (warnp)
606 xasprintf (&data, "%s%ld;", data, warn); 544 xasprintf(&data, "%s%ld;", data, warn);
607 else 545 else
608 xasprintf (&data, "%s;", data); 546 xasprintf(&data, "%s;", data);
609 547
610 if (critp) 548 if (critp)
611 xasprintf (&data, "%s%ld;", data, crit); 549 xasprintf(&data, "%s%ld;", data, crit);
612 else 550 else
613 xasprintf (&data, "%s;", data); 551 xasprintf(&data, "%s;", data);
614 552
615 if (minp) 553 if (minp)
616 xasprintf (&data, "%s%ld;", data, minv); 554 xasprintf(&data, "%s%ld;", data, minv);
617 else 555 else
618 xasprintf (&data, "%s;", data); 556 xasprintf(&data, "%s;", data);
619 557
620 if (maxp) 558 if (maxp)
621 xasprintf (&data, "%s%ld", data, maxv); 559 xasprintf(&data, "%s%ld", data, maxv);
622 560
623 return data; 561 return data;
624} 562}
625 563
626 564char *perfdata_uint64(const char *label, uint64_t val, const char *uom, int warnp, /* Warning present */
627char *perfdata_uint64 (const char *label, 565 uint64_t warn, int critp, /* Critical present */
628 uint64_t val, 566 uint64_t crit, int minp, /* Minimum present */
629 const char *uom, 567 uint64_t minv, int maxp, /* Maximum present */
630 int warnp, /* Warning present */ 568 uint64_t maxv) {
631 uint64_t warn,
632 int critp, /* Critical present */
633 uint64_t crit,
634 int minp, /* Minimum present */
635 uint64_t minv,
636 int maxp, /* Maximum present */
637 uint64_t maxv)
638{
639 char *data = NULL; 569 char *data = NULL;
640 570
641 if (strpbrk (label, "'= ")) 571 if (strpbrk(label, "'= "))
642 xasprintf (&data, "'%s'=%" PRIu64 "%s;", label, val, uom); 572 xasprintf(&data, "'%s'=%" PRIu64 "%s;", label, val, uom);
643 else 573 else
644 xasprintf (&data, "%s=%" PRIu64 "%s;", label, val, uom); 574 xasprintf(&data, "%s=%" PRIu64 "%s;", label, val, uom);
645 575
646 if (warnp) 576 if (warnp)
647 xasprintf (&data, "%s%" PRIu64 ";", data, warn); 577 xasprintf(&data, "%s%" PRIu64 ";", data, warn);
648 else 578 else
649 xasprintf (&data, "%s;", data); 579 xasprintf(&data, "%s;", data);
650 580
651 if (critp) 581 if (critp)
652 xasprintf (&data, "%s%" PRIu64 ";", data, crit); 582 xasprintf(&data, "%s%" PRIu64 ";", data, crit);
653 else 583 else
654 xasprintf (&data, "%s;", data); 584 xasprintf(&data, "%s;", data);
655 585
656 if (minp) 586 if (minp)
657 xasprintf (&data, "%s%" PRIu64 ";", data, minv); 587 xasprintf(&data, "%s%" PRIu64 ";", data, minv);
658 else 588 else
659 xasprintf (&data, "%s;", data); 589 xasprintf(&data, "%s;", data);
660 590
661 if (maxp) 591 if (maxp)
662 xasprintf (&data, "%s%" PRIu64, data, maxv); 592 xasprintf(&data, "%s%" PRIu64, data, maxv);
663 593
664 return data; 594 return data;
665} 595}
666 596
667 597char *perfdata_int64(const char *label, int64_t val, const char *uom, int warnp, /* Warning present */
668char *perfdata_int64 (const char *label, 598 int64_t warn, int critp, /* Critical present */
669 int64_t val, 599 int64_t crit, int minp, /* Minimum present */
670 const char *uom, 600 int64_t minv, int maxp, /* Maximum present */
671 int warnp, /* Warning present */ 601 int64_t maxv) {
672 int64_t warn,
673 int critp, /* Critical present */
674 int64_t crit,
675 int minp, /* Minimum present */
676 int64_t minv,
677 int maxp, /* Maximum present */
678 int64_t maxv)
679{
680 char *data = NULL; 602 char *data = NULL;
681 603
682 if (strpbrk (label, "'= ")) 604 if (strpbrk(label, "'= "))
683 xasprintf (&data, "'%s'=%" PRId64 "%s;", label, val, uom); 605 xasprintf(&data, "'%s'=%" PRId64 "%s;", label, val, uom);
684 else 606 else
685 xasprintf (&data, "%s=%" PRId64 "%s;", label, val, uom); 607 xasprintf(&data, "%s=%" PRId64 "%s;", label, val, uom);
686 608
687 if (warnp) 609 if (warnp)
688 xasprintf (&data, "%s%" PRId64 ";", data, warn); 610 xasprintf(&data, "%s%" PRId64 ";", data, warn);
689 else 611 else
690 xasprintf (&data, "%s;", data); 612 xasprintf(&data, "%s;", data);
691 613
692 if (critp) 614 if (critp)
693 xasprintf (&data, "%s%" PRId64 ";", data, crit); 615 xasprintf(&data, "%s%" PRId64 ";", data, crit);
694 else 616 else
695 xasprintf (&data, "%s;", data); 617 xasprintf(&data, "%s;", data);
696 618
697 if (minp) 619 if (minp)
698 xasprintf (&data, "%s%" PRId64 ";", data, minv); 620 xasprintf(&data, "%s%" PRId64 ";", data, minv);
699 else 621 else
700 xasprintf (&data, "%s;", data); 622 xasprintf(&data, "%s;", data);
701 623
702 if (maxp) 624 if (maxp)
703 xasprintf (&data, "%s%" PRId64, data, maxv); 625 xasprintf(&data, "%s%" PRId64, data, maxv);
704 626
705 return data; 627 return data;
706} 628}
707 629
708 630char *fperfdata(const char *label, double val, const char *uom, int warnp, double warn, int critp, double crit, int minp, double minv,
709char *fperfdata (const char *label, 631 int maxp, double maxv) {
710 double val,
711 const char *uom,
712 int warnp,
713 double warn,
714 int critp,
715 double crit,
716 int minp,
717 double minv,
718 int maxp,
719 double maxv)
720{
721 char *data = NULL; 632 char *data = NULL;
722 633
723 if (strpbrk (label, "'= ")) 634 if (strpbrk(label, "'= "))
724 xasprintf (&data, "'%s'=", label); 635 xasprintf(&data, "'%s'=", label);
725 else 636 else
726 xasprintf (&data, "%s=", label); 637 xasprintf(&data, "%s=", label);
727 638
728 xasprintf (&data, "%s%f", data, val); 639 xasprintf(&data, "%s%f", data, val);
729 xasprintf (&data, "%s%s;", data, uom); 640 xasprintf(&data, "%s%s;", data, uom);
730 641
731 if (warnp) 642 if (warnp)
732 xasprintf (&data, "%s%f", data, warn); 643 xasprintf(&data, "%s%f", data, warn);
733 644
734 xasprintf (&data, "%s;", data); 645 xasprintf(&data, "%s;", data);
735 646
736 if (critp) 647 if (critp)
737 xasprintf (&data, "%s%f", data, crit); 648 xasprintf(&data, "%s%f", data, crit);
738 649
739 xasprintf (&data, "%s;", data); 650 xasprintf(&data, "%s;", data);
740 651
741 if (minp) 652 if (minp)
742 xasprintf (&data, "%s%f", data, minv); 653 xasprintf(&data, "%s%f", data, minv);
743 654
744 if (maxp) { 655 if (maxp) {
745 xasprintf (&data, "%s;", data); 656 xasprintf(&data, "%s;", data);
746 xasprintf (&data, "%s%f", data, maxv); 657 xasprintf(&data, "%s%f", data, maxv);
747 } 658 }
748 659
749 return data; 660 return data;
750} 661}
751 662
752char *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) {
753 double val,
754 const char *uom,
755 char *warn,
756 char *crit,
757 int minp,
758 double minv,
759 int maxp,
760 double maxv)
761{
762 char *data = NULL; 664 char *data = NULL;
763 if (strpbrk (label, "'= ")) 665 if (strpbrk(label, "'= "))
764 xasprintf (&data, "'%s'=", label); 666 xasprintf(&data, "'%s'=", label);
765 else 667 else
766 xasprintf (&data, "%s=", label); 668 xasprintf(&data, "%s=", label);
767 669
768 xasprintf (&data, "%s%f", data, val); 670 xasprintf(&data, "%s%f", data, val);
769 xasprintf (&data, "%s%s;", data, uom); 671 xasprintf(&data, "%s%s;", data, uom);
770 672
771 if (warn!=NULL) 673 if (warn != NULL)
772 xasprintf (&data, "%s%s", data, warn); 674 xasprintf(&data, "%s%s", data, warn);
773 675
774 xasprintf (&data, "%s;", data); 676 xasprintf(&data, "%s;", data);
775 677
776 if (crit!=NULL) 678 if (crit != NULL)
777 xasprintf (&data, "%s%s", data, crit); 679 xasprintf(&data, "%s%s", data, crit);
778 680
779 xasprintf (&data, "%s;", data); 681 xasprintf(&data, "%s;", data);
780 682
781 if (minp) 683 if (minp)
782 xasprintf (&data, "%s%f", data, minv); 684 xasprintf(&data, "%s%f", data, minv);
783 685
784 if (maxp) { 686 if (maxp) {
785 xasprintf (&data, "%s;", data); 687 xasprintf(&data, "%s;", data);
786 xasprintf (&data, "%s%f", data, maxv); 688 xasprintf(&data, "%s%f", data, maxv);
787 } 689 }
788 690
789 return data; 691 return data;
790} 692}
791 693
792char *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) {
793 int val,
794 const char *uom,
795 char *warn,
796 char *crit,
797 int minp,
798 int minv,
799 int maxp,
800 int maxv)
801{
802 char *data = NULL; 695 char *data = NULL;
803 if (strpbrk (label, "'= ")) 696 if (strpbrk(label, "'= "))
804 xasprintf (&data, "'%s'=", label); 697 xasprintf(&data, "'%s'=", label);
805 else 698 else
806 xasprintf (&data, "%s=", label); 699 xasprintf(&data, "%s=", label);
807 700
808 xasprintf (&data, "%s%d", data, val); 701 xasprintf(&data, "%s%d", data, val);
809 xasprintf (&data, "%s%s;", data, uom); 702 xasprintf(&data, "%s%s;", data, uom);
810 703
811 if (warn!=NULL) 704 if (warn != NULL)
812 xasprintf (&data, "%s%s", data, warn); 705 xasprintf(&data, "%s%s", data, warn);
813 706
814 xasprintf (&data, "%s;", data); 707 xasprintf(&data, "%s;", data);
815 708
816 if (crit!=NULL) 709 if (crit != NULL)
817 xasprintf (&data, "%s%s", data, crit); 710 xasprintf(&data, "%s%s", data, crit);
818 711
819 xasprintf (&data, "%s;", data); 712 xasprintf(&data, "%s;", data);
820 713
821 if (minp) 714 if (minp)
822 xasprintf (&data, "%s%d", data, minv); 715 xasprintf(&data, "%s%d", data, minv);
823 716
824 if (maxp) { 717 if (maxp) {
825 xasprintf (&data, "%s;", data); 718 xasprintf(&data, "%s;", data);
826 xasprintf (&data, "%s%d", data, maxv); 719 xasprintf(&data, "%s%d", data, maxv);
827 } 720 }
828 721
829 return data; 722 return data;