summaryrefslogtreecommitdiffstats
path: root/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'plugins')
-rw-r--r--plugins/check_apt.c666
-rw-r--r--plugins/check_by_ssh.c528
-rw-r--r--plugins/check_cluster.c255
-rw-r--r--plugins/check_curl.c4581
-rw-r--r--plugins/check_dbi.c827
-rw-r--r--plugins/check_dig.c650
-rw-r--r--plugins/check_disk.c2036
-rw-r--r--plugins/check_dns.c1101
-rw-r--r--plugins/check_dummy.c195
-rw-r--r--plugins/check_fping.c962
-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.c46
-rw-r--r--plugins/check_mrtg.c456
-rw-r--r--plugins/check_mrtgtraf.c457
-rw-r--r--plugins/check_mysql.c50
-rw-r--r--plugins/check_mysql_query.c396
-rw-r--r--plugins/check_nagios.c306
-rw-r--r--plugins/check_nt.c962
-rw-r--r--plugins/check_ntp.c12
-rw-r--r--plugins/check_ntp_peer.c636
-rw-r--r--plugins/check_ntp_time.c628
-rw-r--r--plugins/check_nwstat.c2151
-rw-r--r--plugins/check_overcr.c426
-rw-r--r--plugins/check_pgsql.c629
-rw-r--r--plugins/check_ping.c603
-rw-r--r--plugins/check_procs.c62
-rw-r--r--plugins/check_radius.c32
-rw-r--r--plugins/check_real.c484
-rw-r--r--plugins/check_smtp.c102
-rw-r--r--plugins/check_snmp.c1399
-rw-r--r--plugins/check_ssh.c400
-rw-r--r--plugins/check_tcp.c600
-rw-r--r--plugins/check_time.c431
-rw-r--r--plugins/check_ups.c124
-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.c256
-rw-r--r--plugins/sslutils.c228
-rw-r--r--plugins/urlize.c195
-rw-r--r--plugins/utils.c511
46 files changed, 13277 insertions, 14801 deletions
diff --git a/plugins/check_apt.c b/plugins/check_apt.c
index 5c0f6e2..1eda45d 100644
--- a/plugins/check_apt.c
+++ b/plugins/check_apt.c
@@ -1,36 +1,36 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
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 *
10* Description: 10 * Description:
11* 11 *
12* This file contains the check_apt plugin 12 * This file contains the check_apt plugin
13* 13 *
14* Check for available updates in apt package management systems 14 * Check for available updates in apt package management systems
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
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"
@@ -39,17 +39,21 @@ const char *email = "devel@monitoring-plugins.org";
39#include "regex.h" 39#include "regex.h"
40 40
41/* some constants */ 41/* some constants */
42typedef enum { UPGRADE, DIST_UPGRADE, NO_UPGRADE } upgrade_type; 42typedef enum {
43 UPGRADE,
44 DIST_UPGRADE,
45 NO_UPGRADE
46} upgrade_type;
43 47
44/* Character for hidden input file option (for testing). */ 48/* Character for hidden input file option (for testing). */
45#define INPUT_FILE_OPT CHAR_MAX+1 49#define INPUT_FILE_OPT CHAR_MAX + 1
46/* the default opts can be overridden via the cmdline */ 50/* the default opts can be overridden via the cmdline */
47#define UPGRADE_DEFAULT_OPTS "-o 'Debug::NoLocking=true' -s -qq" 51#define UPGRADE_DEFAULT_OPTS "-o 'Debug::NoLocking=true' -s -qq"
48#define UPDATE_DEFAULT_OPTS "-q" 52#define UPDATE_DEFAULT_OPTS "-q"
49/* until i commit the configure.in patch which gets this, i'll define 53/* until i commit the configure.in patch which gets this, i'll define
50 * it here as well */ 54 * it here as well */
51#ifndef PATH_TO_APTGET 55#ifndef PATH_TO_APTGET
52# define PATH_TO_APTGET "/usr/bin/apt-get" 56# define PATH_TO_APTGET "/usr/bin/apt-get"
53#endif /* PATH_TO_APTGET */ 57#endif /* PATH_TO_APTGET */
54/* String found at the beginning of the apt output lines we're interested in */ 58/* String found at the beginning of the apt output lines we're interested in */
55#define PKGINST_PREFIX "Inst " 59#define PKGINST_PREFIX "Inst "
@@ -57,97 +61,108 @@ typedef enum { UPGRADE, DIST_UPGRADE, NO_UPGRADE } upgrade_type;
57#define SECURITY_RE "^[^\\(]*\\(.* (Debian-Security:|Ubuntu:[^/]*/[^-]*-security)" 61#define SECURITY_RE "^[^\\(]*\\(.* (Debian-Security:|Ubuntu:[^/]*/[^-]*-security)"
58 62
59/* some standard functions */ 63/* some standard functions */
60int process_arguments(int, char **); 64static int process_arguments(int /*argc*/, char ** /*argv*/);
61void print_help(void); 65static void print_help(void);
62void print_usage(void); 66void print_usage(void);
63 67
64/* construct the appropriate apt-get cmdline */ 68/* construct the appropriate apt-get cmdline */
65char* construct_cmdline(upgrade_type u, const char *opts); 69static char *construct_cmdline(upgrade_type u, const char *opts);
66/* run an apt-get update */ 70/* run an apt-get update */
67int run_update(void); 71static int run_update(void);
72
73typedef struct {
74 int errorcode;
75 int package_count;
76 int security_package_count;
77 char **packages_list;
78 char **secpackages_list;
79} run_upgrade_result;
80
68/* run an apt-get upgrade */ 81/* run an apt-get upgrade */
69int run_upgrade(int *pkgcount, int *secpkgcount, char ***pkglist, char ***secpkglist); 82static run_upgrade_result run_upgrade(void);
83
70/* add another clause to a regexp */ 84/* add another clause to a regexp */
71char* add_to_regexp(char *expr, const char *next); 85static char *add_to_regexp(char *expr, const char *next);
72/* extract package name from Inst line */ 86/* extract package name from Inst line */
73char* pkg_name(char *line); 87static char *pkg_name(char *line);
74/* string comparison function for qsort */ 88/* string comparison function for qsort */
75int cmpstringp(const void *p1, const void *p2); 89static int cmpstringp(const void *p1, const void *p2);
76 90
77/* configuration variables */ 91/* configuration variables */
78static int verbose = 0; /* -v */ 92static int verbose = 0; /* -v */
79static bool list = false; /* list packages available for upgrade */ 93static bool list = false; /* list packages available for upgrade */
80static bool do_update = false; /* whether to call apt-get update */ 94static bool do_update = false; /* whether to call apt-get update */
81static bool only_critical = false; /* whether to warn about non-critical updates */ 95static bool only_critical = false; /* whether to warn about non-critical updates */
82static upgrade_type upgrade = UPGRADE; /* which type of upgrade to do */ 96static upgrade_type upgrade = UPGRADE; /* which type of upgrade to do */
83static char *upgrade_opts = NULL; /* options to override defaults for upgrade */ 97static char *upgrade_opts = NULL; /* options to override defaults for upgrade */
84static char *update_opts = NULL; /* options to override defaults for update */ 98static char *update_opts = NULL; /* options to override defaults for update */
85static char *do_include = NULL; /* regexp to only include certain packages */ 99static char *do_include = NULL; /* regexp to only include certain packages */
86static char *do_exclude = NULL; /* regexp to only exclude certain packages */ 100static char *do_exclude = NULL; /* regexp to only exclude certain packages */
87static char *do_critical = NULL; /* regexp specifying critical packages */ 101static char *do_critical = NULL; /* regexp specifying critical packages */
88static char *input_filename = NULL; /* input filename for testing */ 102static char *input_filename = NULL; /* input filename for testing */
89/* number of packages available for upgrade to return WARNING status */ 103/* number of packages available for upgrade to return WARNING status */
90static int packages_warning = 1; 104static int packages_warning = 1;
91 105
92/* other global variables */ 106/* other global variables */
93static int stderr_warning = 0; /* if a cmd issued output on stderr */ 107static int stderr_warning = 0; /* if a cmd issued output on stderr */
94static int exec_warning = 0; /* if a cmd exited non-zero */ 108static int exec_warning = 0; /* if a cmd exited non-zero */
95
96int main (int argc, char **argv) {
97 int result=STATE_UNKNOWN, packages_available=0, sec_count=0;
98 char **packages_list=NULL, **secpackages_list=NULL;
99 109
110int main(int argc, char **argv) {
100 /* Parse extra opts if any */ 111 /* Parse extra opts if any */
101 argv=np_extra_opts(&argc, argv, progname); 112 argv = np_extra_opts(&argc, argv, progname);
102 113
103 if (process_arguments(argc, argv) == ERROR) 114 if (process_arguments(argc, argv) == ERROR) {
104 usage_va(_("Could not parse arguments")); 115 usage_va(_("Could not parse arguments"));
116 }
105 117
106 /* Set signal handling and alarm timeout */ 118 /* Set signal handling and alarm timeout */
107 if (signal (SIGALRM, timeout_alarm_handler) == SIG_ERR) { 119 if (signal(SIGALRM, timeout_alarm_handler) == SIG_ERR) {
108 usage_va(_("Cannot catch SIGALRM")); 120 usage_va(_("Cannot catch SIGALRM"));
109 } 121 }
110 122
111 /* handle timeouts gracefully... */ 123 /* handle timeouts gracefully... */
112 alarm (timeout_interval); 124 alarm(timeout_interval);
113 125
126 int result = STATE_UNKNOWN;
114 /* if they want to run apt-get update first... */ 127 /* if they want to run apt-get update first... */
115 if(do_update) result = run_update(); 128 if (do_update) {
129 result = run_update();
130 }
116 131
117 /* apt-get upgrade */ 132 /* apt-get upgrade */
118 result = max_state(result, run_upgrade(&packages_available, &sec_count, &packages_list, &secpackages_list)); 133 run_upgrade_result upgrad_res = run_upgrade();
119 134
120 if(sec_count > 0){ 135 result = max_state(result, upgrad_res.errorcode);
136 int packages_available = upgrad_res.package_count;
137 int sec_count = upgrad_res.security_package_count;
138 char **packages_list = upgrad_res.packages_list;
139 char **secpackages_list = upgrad_res.secpackages_list;
140
141 if (sec_count > 0) {
121 result = max_state(result, STATE_CRITICAL); 142 result = max_state(result, STATE_CRITICAL);
122 } else if(packages_available >= packages_warning && only_critical == false){ 143 } else if (packages_available >= packages_warning && only_critical == false) {
123 result = max_state(result, STATE_WARNING); 144 result = max_state(result, STATE_WARNING);
124 } else if(result > STATE_UNKNOWN){ 145 } else if (result > STATE_UNKNOWN) {
125 result = STATE_UNKNOWN; 146 result = STATE_UNKNOWN;
126 } 147 }
127 148
128 printf(_("APT %s: %d packages available for %s (%d critical updates). %s%s%s%s|available_upgrades=%d;;;0 critical_updates=%d;;;0\n"), 149 printf(_("APT %s: %d packages available for %s (%d critical updates). %s%s%s%s|available_upgrades=%d;;;0 critical_updates=%d;;;0\n"),
129 state_text(result), 150 state_text(result), packages_available, (upgrade == DIST_UPGRADE) ? "dist-upgrade" : "upgrade", sec_count,
130 packages_available, 151 (stderr_warning) ? " warnings detected" : "", (stderr_warning && exec_warning) ? "," : "",
131 (upgrade==DIST_UPGRADE)?"dist-upgrade":"upgrade", 152 (exec_warning) ? " errors detected" : "", (stderr_warning || exec_warning) ? "." : "", packages_available, sec_count);
132 sec_count, 153
133 (stderr_warning)?" warnings detected":"", 154 if (list) {
134 (stderr_warning && exec_warning)?",":"", 155 qsort(secpackages_list, sec_count, sizeof(char *), cmpstringp);
135 (exec_warning)?" errors detected":"", 156 qsort(packages_list, packages_available - sec_count, sizeof(char *), cmpstringp);
136 (stderr_warning||exec_warning)?".":"", 157
137 packages_available, 158 for (int i = 0; i < sec_count; i++) {
138 sec_count
139 );
140
141 if(list) {
142 qsort(secpackages_list, sec_count, sizeof(char*), cmpstringp);
143 qsort(packages_list, packages_available-sec_count, sizeof(char*), cmpstringp);
144
145 for(int i = 0; i < sec_count; i++)
146 printf("%s (security)\n", secpackages_list[i]); 159 printf("%s (security)\n", secpackages_list[i]);
160 }
147 161
148 if (only_critical == false) { 162 if (only_critical == false) {
149 for(int i = 0; i < packages_available - sec_count; i++) 163 for (int i = 0; i < packages_available - sec_count; i++) {
150 printf("%s\n", packages_list[i]); 164 printf("%s\n", packages_list[i]);
165 }
151 } 166 }
152 } 167 }
153 168
@@ -155,34 +170,32 @@ int main (int argc, char **argv) {
155} 170}
156 171
157/* process command-line arguments */ 172/* process command-line arguments */
158int process_arguments (int argc, char **argv) { 173int process_arguments(int argc, char **argv) {
159 int c; 174 static struct option longopts[] = {{"version", no_argument, 0, 'V'},
160 175 {"help", no_argument, 0, 'h'},
161 static struct option longopts[] = { 176 {"verbose", no_argument, 0, 'v'},
162 {"version", no_argument, 0, 'V'}, 177 {"timeout", required_argument, 0, 't'},
163 {"help", no_argument, 0, 'h'}, 178 {"update", optional_argument, 0, 'u'},
164 {"verbose", no_argument, 0, 'v'}, 179 {"upgrade", optional_argument, 0, 'U'},
165 {"timeout", required_argument, 0, 't'}, 180 {"no-upgrade", no_argument, 0, 'n'},
166 {"update", optional_argument, 0, 'u'}, 181 {"dist-upgrade", optional_argument, 0, 'd'},
167 {"upgrade", optional_argument, 0, 'U'}, 182 {"list", no_argument, false, 'l'},
168 {"no-upgrade", no_argument, 0, 'n'}, 183 {"include", required_argument, 0, 'i'},
169 {"dist-upgrade", optional_argument, 0, 'd'}, 184 {"exclude", required_argument, 0, 'e'},
170 {"list", no_argument, false, 'l'}, 185 {"critical", required_argument, 0, 'c'},
171 {"include", required_argument, 0, 'i'}, 186 {"only-critical", no_argument, 0, 'o'},
172 {"exclude", required_argument, 0, 'e'}, 187 {"input-file", required_argument, 0, INPUT_FILE_OPT},
173 {"critical", required_argument, 0, 'c'}, 188 {"packages-warning", required_argument, 0, 'w'},
174 {"only-critical", no_argument, 0, 'o'}, 189 {0, 0, 0, 0}};
175 {"input-file", required_argument, 0, INPUT_FILE_OPT}, 190
176 {"packages-warning", required_argument, 0, 'w'}, 191 while (true) {
177 {0, 0, 0, 0} 192 int option_char = getopt_long(argc, argv, "hVvt:u::U::d::nli:e:c:ow:", longopts, NULL);
178 }; 193
179 194 if (option_char == -1 || option_char == EOF || option_char == 1) {
180 while(1) { 195 break;
181 c = getopt_long(argc, argv, "hVvt:u::U::d::nli:e:c:ow:", longopts, NULL); 196 }
182
183 if(c == -1 || c == EOF || c == 1) break;
184 197
185 switch(c) { 198 switch (option_char) {
186 case 'h': 199 case 'h':
187 print_help(); 200 print_help();
188 exit(STATE_UNKNOWN); 201 exit(STATE_UNKNOWN);
@@ -193,46 +206,52 @@ int process_arguments (int argc, char **argv) {
193 verbose++; 206 verbose++;
194 break; 207 break;
195 case 't': 208 case 't':
196 timeout_interval=atoi(optarg); 209 timeout_interval = atoi(optarg);
197 break; 210 break;
198 case 'd': 211 case 'd':
199 upgrade=DIST_UPGRADE; 212 upgrade = DIST_UPGRADE;
200 if(optarg!=NULL){ 213 if (optarg != NULL) {
201 upgrade_opts=strdup(optarg); 214 upgrade_opts = strdup(optarg);
202 if(upgrade_opts==NULL) die(STATE_UNKNOWN, "strdup failed"); 215 if (upgrade_opts == NULL) {
216 die(STATE_UNKNOWN, "strdup failed");
217 }
203 } 218 }
204 break; 219 break;
205 case 'U': 220 case 'U':
206 upgrade=UPGRADE; 221 upgrade = UPGRADE;
207 if(optarg!=NULL){ 222 if (optarg != NULL) {
208 upgrade_opts=strdup(optarg); 223 upgrade_opts = strdup(optarg);
209 if(upgrade_opts==NULL) die(STATE_UNKNOWN, "strdup failed"); 224 if (upgrade_opts == NULL) {
225 die(STATE_UNKNOWN, "strdup failed");
226 }
210 } 227 }
211 break; 228 break;
212 case 'n': 229 case 'n':
213 upgrade=NO_UPGRADE; 230 upgrade = NO_UPGRADE;
214 break; 231 break;
215 case 'u': 232 case 'u':
216 do_update=true; 233 do_update = true;
217 if(optarg!=NULL){ 234 if (optarg != NULL) {
218 update_opts=strdup(optarg); 235 update_opts = strdup(optarg);
219 if(update_opts==NULL) die(STATE_UNKNOWN, "strdup failed"); 236 if (update_opts == NULL) {
237 die(STATE_UNKNOWN, "strdup failed");
238 }
220 } 239 }
221 break; 240 break;
222 case 'l': 241 case 'l':
223 list=true; 242 list = true;
224 break; 243 break;
225 case 'i': 244 case 'i':
226 do_include=add_to_regexp(do_include, optarg); 245 do_include = add_to_regexp(do_include, optarg);
227 break; 246 break;
228 case 'e': 247 case 'e':
229 do_exclude=add_to_regexp(do_exclude, optarg); 248 do_exclude = add_to_regexp(do_exclude, optarg);
230 break; 249 break;
231 case 'c': 250 case 'c':
232 do_critical=add_to_regexp(do_critical, optarg); 251 do_critical = add_to_regexp(do_critical, optarg);
233 break; 252 break;
234 case 'o': 253 case 'o':
235 only_critical=true; 254 only_critical = true;
236 break; 255 break;
237 case INPUT_FILE_OPT: 256 case INPUT_FILE_OPT:
238 input_filename = optarg; 257 input_filename = optarg;
@@ -249,68 +268,78 @@ int process_arguments (int argc, char **argv) {
249 return OK; 268 return OK;
250} 269}
251 270
252
253/* run an apt-get upgrade */ 271/* run an apt-get upgrade */
254int run_upgrade(int *pkgcount, int *secpkgcount, char ***pkglist, char ***secpkglist){ 272run_upgrade_result run_upgrade(void) {
255 int result=STATE_UNKNOWN, regres=0, pc=0, spc=0; 273 regex_t ereg;
256 struct output chld_out, chld_err;
257 regex_t ireg, ereg, sreg;
258 char *cmdline=NULL, rerrbuf[64];
259
260 /* initialize ereg as it is possible it is printed while uninitialized */ 274 /* initialize ereg as it is possible it is printed while uninitialized */
261 memset(&ereg, '\0', sizeof(ereg.buffer)); 275 memset(&ereg, '\0', sizeof(ereg.buffer));
262 276
263 if(upgrade==NO_UPGRADE) return STATE_OK; 277 run_upgrade_result result = {
278 .errorcode = STATE_UNKNOWN,
279 };
264 280
281 if (upgrade == NO_UPGRADE) {
282 result.errorcode = STATE_OK;
283 return result;
284 }
285
286 int regres = 0;
287 regex_t ireg;
288 char rerrbuf[64];
265 /* compile the regexps */ 289 /* compile the regexps */
266 if (do_include != NULL) { 290 if (do_include != NULL) {
267 regres=regcomp(&ireg, do_include, REG_EXTENDED); 291 regres = regcomp(&ireg, do_include, REG_EXTENDED);
268 if (regres!=0) { 292 if (regres != 0) {
269 regerror(regres, &ireg, rerrbuf, 64); 293 regerror(regres, &ireg, rerrbuf, 64);
270 die(STATE_UNKNOWN, _("%s: Error compiling regexp: %s"), progname, rerrbuf); 294 die(STATE_UNKNOWN, _("%s: Error compiling regexp: %s"), progname, rerrbuf);
271 } 295 }
272 } 296 }
273 297
274 if(do_exclude!=NULL){ 298 if (do_exclude != NULL) {
275 regres=regcomp(&ereg, do_exclude, REG_EXTENDED); 299 regres = regcomp(&ereg, do_exclude, REG_EXTENDED);
276 if(regres!=0) { 300 if (regres != 0) {
277 regerror(regres, &ereg, rerrbuf, 64); 301 regerror(regres, &ereg, rerrbuf, 64);
278 die(STATE_UNKNOWN, _("%s: Error compiling regexp: %s"), 302 die(STATE_UNKNOWN, _("%s: Error compiling regexp: %s"), progname, rerrbuf);
279 progname, rerrbuf);
280 } 303 }
281 } 304 }
282 305
306 regex_t sreg;
283 const char *crit_ptr = (do_critical != NULL) ? do_critical : SECURITY_RE; 307 const char *crit_ptr = (do_critical != NULL) ? do_critical : SECURITY_RE;
284 regres=regcomp(&sreg, crit_ptr, REG_EXTENDED); 308 regres = regcomp(&sreg, crit_ptr, REG_EXTENDED);
285 if(regres!=0) { 309 if (regres != 0) {
286 regerror(regres, &ereg, rerrbuf, 64); 310 regerror(regres, &ereg, rerrbuf, 64);
287 die(STATE_UNKNOWN, _("%s: Error compiling regexp: %s"), 311 die(STATE_UNKNOWN, _("%s: Error compiling regexp: %s"), progname, rerrbuf);
288 progname, rerrbuf);
289 } 312 }
290 313
291 cmdline=construct_cmdline(upgrade, upgrade_opts); 314 struct output chld_out;
315 struct output chld_err;
316 char *cmdline = NULL;
317 cmdline = construct_cmdline(upgrade, upgrade_opts);
292 if (input_filename != NULL) { 318 if (input_filename != NULL) {
293 /* read input from a file for testing */ 319 /* read input from a file for testing */
294 result = cmd_file_read(input_filename, &chld_out, 0); 320 result.errorcode = cmd_file_read(input_filename, &chld_out, 0);
295 } else { 321 } else {
296 /* run the upgrade */ 322 /* run the upgrade */
297 result = np_runcmd(cmdline, &chld_out, &chld_err, 0); 323 result.errorcode = np_runcmd(cmdline, &chld_out, &chld_err, 0);
298 } 324 }
299 325
300 /* apt-get upgrade only changes exit status if there is an 326 /* apt-get upgrade only changes exit status if there is an
301 * internal error when run in dry-run mode. therefore we will 327 * internal error when run in dry-run mode. therefore we will
302 * treat such an error as UNKNOWN */ 328 * treat such an error as UNKNOWN */
303 if(result != 0){ 329 if (result.errorcode != STATE_OK) {
304 exec_warning=1; 330 exec_warning = 1;
305 result = STATE_UNKNOWN; 331 result.errorcode = STATE_UNKNOWN;
306 fprintf(stderr, _("'%s' exited with non-zero status.\n"), 332 fprintf(stderr, _("'%s' exited with non-zero status.\n"), cmdline);
307 cmdline);
308 } 333 }
309 334
310 *pkglist=malloc(sizeof(char *) * chld_out.lines); 335 char **pkglist = malloc(sizeof(char *) * chld_out.lines);
311 if(!pkglist) die(STATE_UNKNOWN, "malloc failed!\n"); 336 if (!pkglist) {
312 *secpkglist=malloc(sizeof(char *) * chld_out.lines); 337 die(STATE_UNKNOWN, "malloc failed!\n");
313 if(!secpkglist) die(STATE_UNKNOWN, "malloc failed!\n"); 338 }
339 char **secpkglist = malloc(sizeof(char *) * chld_out.lines);
340 if (!secpkglist) {
341 die(STATE_UNKNOWN, "malloc failed!\n");
342 }
314 343
315 /* parse the output, which should only consist of lines like 344 /* parse the output, which should only consist of lines like
316 * 345 *
@@ -321,82 +350,91 @@ int run_upgrade(int *pkgcount, int *secpkgcount, char ***pkglist, char ***secpkg
321 * we may need to switch to the --print-uris output format, 350 * we may need to switch to the --print-uris output format,
322 * in which case the logic here will slightly change. 351 * in which case the logic here will slightly change.
323 */ 352 */
324 for(size_t i = 0; i < chld_out.lines; i++) { 353 int package_counter = 0;
325 if(verbose){ 354 int security_package_counter = 0;
355 for (size_t i = 0; i < chld_out.lines; i++) {
356 if (verbose) {
326 printf("%s\n", chld_out.line[i]); 357 printf("%s\n", chld_out.line[i]);
327 } 358 }
328 /* if it is a package we care about */ 359 /* if it is a package we care about */
329 if (strncmp(PKGINST_PREFIX, chld_out.line[i], strlen(PKGINST_PREFIX)) == 0 && 360 if (strncmp(PKGINST_PREFIX, chld_out.line[i], strlen(PKGINST_PREFIX)) == 0 &&
330 (do_include == NULL || regexec(&ireg, chld_out.line[i], 0, NULL, 0) == 0)) { 361 (do_include == NULL || regexec(&ireg, chld_out.line[i], 0, NULL, 0) == 0)) {
331 /* if we're not excluding, or it's not in the 362 /* if we're not excluding, or it's not in the
332 * list of stuff to exclude */ 363 * list of stuff to exclude */
333 if(do_exclude==NULL || 364 if (do_exclude == NULL || regexec(&ereg, chld_out.line[i], 0, NULL, 0) != 0) {
334 regexec(&ereg, chld_out.line[i], 0, NULL, 0)!=0){ 365 package_counter++;
335 pc++; 366 if (regexec(&sreg, chld_out.line[i], 0, NULL, 0) == 0) {
336 if(regexec(&sreg, chld_out.line[i], 0, NULL, 0)==0){ 367 security_package_counter++;
337 spc++; 368 if (verbose) {
338 if(verbose) printf("*"); 369 printf("*");
339 (*secpkglist)[spc-1] = pkg_name(chld_out.line[i]); 370 }
371 (secpkglist)[security_package_counter - 1] = pkg_name(chld_out.line[i]);
340 } else { 372 } else {
341 (*pkglist)[pc-spc-1] = pkg_name(chld_out.line[i]); 373 (pkglist)[package_counter - security_package_counter - 1] = pkg_name(chld_out.line[i]);
342 } 374 }
343 if(verbose){ 375 if (verbose) {
344 printf("*%s\n", chld_out.line[i]); 376 printf("*%s\n", chld_out.line[i]);
345 } 377 }
346 } 378 }
347 } 379 }
348 } 380 }
349 *pkgcount=pc; 381 result.package_count = package_counter;
350 *secpkgcount=spc; 382 result.security_package_count = security_package_counter;
383 result.packages_list = pkglist;
384 result.secpackages_list = secpkglist;
351 385
352 /* If we get anything on stderr, at least set warning */ 386 /* If we get anything on stderr, at least set warning */
353 if (input_filename == NULL && chld_err.buflen) { 387 if (input_filename == NULL && chld_err.buflen) {
354 stderr_warning=1; 388 stderr_warning = 1;
355 result = max_state(result, STATE_WARNING); 389 result.errorcode = max_state(result.errorcode, STATE_WARNING);
356 if(verbose){ 390 if (verbose) {
357 for(size_t i = 0; i < chld_err.lines; i++) { 391 for (size_t i = 0; i < chld_err.lines; i++) {
358 fprintf(stderr, "%s\n", chld_err.line[i]); 392 fprintf(stderr, "%s\n", chld_err.line[i]);
359 } 393 }
360 } 394 }
361 } 395 }
362 if (do_include != NULL) regfree(&ireg); 396 if (do_include != NULL) {
397 regfree(&ireg);
398 }
363 regfree(&sreg); 399 regfree(&sreg);
364 if(do_exclude!=NULL) regfree(&ereg); 400 if (do_exclude != NULL) {
401 regfree(&ereg);
402 }
365 free(cmdline); 403 free(cmdline);
366 return result; 404 return result;
367} 405}
368 406
369/* run an apt-get update (needs root) */ 407/* run an apt-get update (needs root) */
370int run_update(void){ 408int run_update(void) {
371 int result=STATE_UNKNOWN; 409 int result = STATE_UNKNOWN;
372 struct output chld_out, chld_err;
373 char *cmdline; 410 char *cmdline;
374
375 /* run the update */ 411 /* run the update */
376 cmdline = construct_cmdline(NO_UPGRADE, update_opts); 412 cmdline = construct_cmdline(NO_UPGRADE, update_opts);
413
414 struct output chld_out;
415 struct output chld_err;
377 result = np_runcmd(cmdline, &chld_out, &chld_err, 0); 416 result = np_runcmd(cmdline, &chld_out, &chld_err, 0);
378 /* apt-get update changes exit status if it can't fetch packages. 417 /* apt-get update changes exit status if it can't fetch packages.
379 * since we were explicitly asked to do so, this is treated as 418 * since we were explicitly asked to do so, this is treated as
380 * a critical error. */ 419 * a critical error. */
381 if(result != 0){ 420 if (result != 0) {
382 exec_warning=1; 421 exec_warning = 1;
383 result = STATE_CRITICAL; 422 result = STATE_CRITICAL;
384 fprintf(stderr, _("'%s' exited with non-zero status.\n"), 423 fprintf(stderr, _("'%s' exited with non-zero status.\n"), cmdline);
385 cmdline);
386 } 424 }
387 425
388 if(verbose){ 426 if (verbose) {
389 for(size_t i = 0; i < chld_out.lines; i++) { 427 for (size_t i = 0; i < chld_out.lines; i++) {
390 printf("%s\n", chld_out.line[i]); 428 printf("%s\n", chld_out.line[i]);
391 } 429 }
392 } 430 }
393 431
394 /* If we get anything on stderr, at least set warning */ 432 /* If we get anything on stderr, at least set warning */
395 if(chld_err.buflen){ 433 if (chld_err.buflen) {
396 stderr_warning=1; 434 stderr_warning = 1;
397 result = max_state(result, STATE_WARNING); 435 result = max_state(result, STATE_WARNING);
398 if(verbose){ 436 if (verbose) {
399 for(size_t i = 0; i < chld_err.lines; i++) { 437 for (size_t i = 0; i < chld_err.lines; i++) {
400 fprintf(stderr, "%s\n", chld_err.line[i]); 438 fprintf(stderr, "%s\n", chld_err.line[i]);
401 } 439 }
402 } 440 }
@@ -405,158 +443,166 @@ int run_update(void){
405 return result; 443 return result;
406} 444}
407 445
408char* pkg_name(char *line){ 446char *pkg_name(char *line) {
409 char *start=NULL, *space=NULL, *pkg=NULL; 447 char *start = line + strlen(PKGINST_PREFIX);
410 int len=0;
411 448
412 start = line + strlen(PKGINST_PREFIX); 449 int len = strlen(start);
413 len = strlen(start);
414 450
415 space = index(start, ' '); 451 char *space = index(start, ' ');
416 if(space!=NULL){ 452 if (space != NULL) {
417 len = space - start; 453 len = space - start;
418 } 454 }
419 455
420 pkg=malloc(sizeof(char)*(len+1)); 456 char *pkg = malloc(sizeof(char) * (len + 1));
421 if(!pkg) die(STATE_UNKNOWN, "malloc failed!\n"); 457 if (!pkg) {
458 die(STATE_UNKNOWN, "malloc failed!\n");
459 }
422 460
423 strncpy(pkg, start, len); 461 strncpy(pkg, start, len);
424 pkg[len]='\0'; 462 pkg[len] = '\0';
425 463
426 return pkg; 464 return pkg;
427} 465}
428 466
429int cmpstringp(const void *p1, const void *p2){ 467int cmpstringp(const void *p1, const void *p2) { return strcmp(*(char *const *)p1, *(char *const *)p2); }
430 return strcmp(* (char * const *) p1, * (char * const *) p2);
431}
432 468
433char* add_to_regexp(char *expr, const char *next){ 469char *add_to_regexp(char *expr, const char *next) {
434 char *re=NULL; 470 char *re = NULL;
435 471
436 if(expr==NULL){ 472 if (expr == NULL) {
437 re=malloc(sizeof(char)*(strlen("()")+strlen(next)+1)); 473 re = malloc(sizeof(char) * (strlen("()") + strlen(next) + 1));
438 if(!re) die(STATE_UNKNOWN, "malloc failed!\n"); 474 if (!re) {
475 die(STATE_UNKNOWN, "malloc failed!\n");
476 }
439 sprintf(re, "(%s)", next); 477 sprintf(re, "(%s)", next);
440 } else { 478 } else {
441 /* resize it, adding an extra char for the new '|' separator */ 479 /* resize it, adding an extra char for the new '|' separator */
442 re=realloc(expr, sizeof(char)*(strlen(expr)+1+strlen(next)+1)); 480 re = realloc(expr, sizeof(char) * (strlen(expr) + 1 + strlen(next) + 1));
443 if(!re) die(STATE_UNKNOWN, "realloc failed!\n"); 481 if (!re) {
482 die(STATE_UNKNOWN, "realloc failed!\n");
483 }
444 /* append it starting at ')' in the old re */ 484 /* append it starting at ')' in the old re */
445 sprintf((char*)(re+strlen(re)-1), "|%s)", next); 485 sprintf((char *)(re + strlen(re) - 1), "|%s)", next);
446 } 486 }
447 487
448 return re; 488 return re;
449} 489}
450 490
451char* construct_cmdline(upgrade_type u, const char *opts){ 491char *construct_cmdline(upgrade_type u, const char *opts) {
452 int len=0; 492 const char *opts_ptr = NULL;
453 const char *opts_ptr=NULL, *aptcmd=NULL; 493 const char *aptcmd = NULL;
454 char *cmd=NULL;
455 494
456 switch(u){ 495 switch (u) {
457 case UPGRADE: 496 case UPGRADE:
458 if(opts==NULL) opts_ptr=UPGRADE_DEFAULT_OPTS; 497 if (opts == NULL) {
459 else opts_ptr=opts; 498 opts_ptr = UPGRADE_DEFAULT_OPTS;
460 aptcmd="upgrade"; 499 } else {
500 opts_ptr = opts;
501 }
502 aptcmd = "upgrade";
461 break; 503 break;
462 case DIST_UPGRADE: 504 case DIST_UPGRADE:
463 if(opts==NULL) opts_ptr=UPGRADE_DEFAULT_OPTS; 505 if (opts == NULL) {
464 else opts_ptr=opts; 506 opts_ptr = UPGRADE_DEFAULT_OPTS;
465 aptcmd="dist-upgrade"; 507 } else {
508 opts_ptr = opts;
509 }
510 aptcmd = "dist-upgrade";
466 break; 511 break;
467 case NO_UPGRADE: 512 case NO_UPGRADE:
468 if(opts==NULL) opts_ptr=UPDATE_DEFAULT_OPTS; 513 if (opts == NULL) {
469 else opts_ptr=opts; 514 opts_ptr = UPDATE_DEFAULT_OPTS;
470 aptcmd="update"; 515 } else {
516 opts_ptr = opts;
517 }
518 aptcmd = "update";
471 break; 519 break;
472 } 520 }
473 521
474 len+=strlen(PATH_TO_APTGET)+1; /* "/usr/bin/apt-get " */ 522 int len = 0;
475 len+=strlen(opts_ptr)+1; /* "opts " */ 523 len += strlen(PATH_TO_APTGET) + 1; /* "/usr/bin/apt-get " */
476 len+=strlen(aptcmd)+1; /* "upgrade\0" */ 524 len += strlen(opts_ptr) + 1; /* "opts " */
525 len += strlen(aptcmd) + 1; /* "upgrade\0" */
477 526
478 cmd=(char*)malloc(sizeof(char)*len); 527 char *cmd = (char *)malloc(sizeof(char) * len);
479 if(cmd==NULL) die(STATE_UNKNOWN, "malloc failed"); 528 if (cmd == NULL) {
529 die(STATE_UNKNOWN, "malloc failed");
530 }
480 sprintf(cmd, "%s %s %s", PATH_TO_APTGET, opts_ptr, aptcmd); 531 sprintf(cmd, "%s %s %s", PATH_TO_APTGET, opts_ptr, aptcmd);
481 return cmd; 532 return cmd;
482} 533}
483 534
484/* informative help message */ 535/* informative help message */
485void 536void print_help(void) {
486print_help (void) 537 print_revision(progname, NP_VERSION);
487{ 538
488 print_revision(progname, NP_VERSION); 539 printf(_(COPYRIGHT), copyright, email);
489 540
490 printf(_(COPYRIGHT), copyright, email); 541 printf("%s\n", _("This plugin checks for software updates on systems that use"));
491 542 printf("%s\n", _("package management systems based on the apt-get(8) command"));
492 printf("%s\n", _("This plugin checks for software updates on systems that use")); 543 printf("%s\n", _("found in Debian GNU/Linux"));
493 printf("%s\n", _("package management systems based on the apt-get(8) command")); 544
494 printf("%s\n", _("found in Debian GNU/Linux")); 545 printf("\n\n");
495 546
496 printf ("\n\n"); 547 print_usage();
497 548
498 print_usage(); 549 printf(UT_HELP_VRSN);
499 550 printf(UT_EXTRA_OPTS);
500 printf(UT_HELP_VRSN); 551
501 printf(UT_EXTRA_OPTS); 552 printf(UT_PLUG_TIMEOUT, timeout_interval);
502 553
503 printf(UT_PLUG_TIMEOUT, timeout_interval); 554 printf(" %s\n", "-n, --no-upgrade");
504 555 printf(" %s\n", _("Do not run the upgrade. Probably not useful (without -u at least)."));
505 printf (" %s\n", "-n, --no-upgrade"); 556 printf(" %s\n", "-l, --list");
506 printf (" %s\n", _("Do not run the upgrade. Probably not useful (without -u at least).")); 557 printf(" %s\n", _("List packages available for upgrade. Packages are printed sorted by"));
507 printf (" %s\n", "-l, --list"); 558 printf(" %s\n", _("name with security packages listed first."));
508 printf (" %s\n", _("List packages available for upgrade. Packages are printed sorted by")); 559 printf(" %s\n", "-i, --include=REGEXP");
509 printf (" %s\n", _("name with security packages listed first.")); 560 printf(" %s\n", _("Include only packages matching REGEXP. Can be specified multiple times"));
510 printf (" %s\n", "-i, --include=REGEXP"); 561 printf(" %s\n", _("the values will be combined together. Any packages matching this list"));
511 printf (" %s\n", _("Include only packages matching REGEXP. Can be specified multiple times")); 562 printf(" %s\n", _("cause the plugin to return WARNING status. Others will be ignored."));
512 printf (" %s\n", _("the values will be combined together. Any packages matching this list")); 563 printf(" %s\n", _("Default is to include all packages."));
513 printf (" %s\n", _("cause the plugin to return WARNING status. Others will be ignored.")); 564 printf(" %s\n", "-e, --exclude=REGEXP");
514 printf (" %s\n", _("Default is to include all packages.")); 565 printf(" %s\n", _("Exclude packages matching REGEXP from the list of packages that would"));
515 printf (" %s\n", "-e, --exclude=REGEXP"); 566 printf(" %s\n", _("otherwise be included. Can be specified multiple times; the values"));
516 printf (" %s\n", _("Exclude packages matching REGEXP from the list of packages that would")); 567 printf(" %s\n", _("will be combined together. Default is to exclude no packages."));
517 printf (" %s\n", _("otherwise be included. Can be specified multiple times; the values")); 568 printf(" %s\n", "-c, --critical=REGEXP");
518 printf (" %s\n", _("will be combined together. Default is to exclude no packages.")); 569 printf(" %s\n", _("If the full package information of any of the upgradable packages match"));
519 printf (" %s\n", "-c, --critical=REGEXP"); 570 printf(" %s\n", _("this REGEXP, the plugin will return CRITICAL status. Can be specified"));
520 printf (" %s\n", _("If the full package information of any of the upgradable packages match")); 571 printf(" %s\n", _("multiple times like above. Default is a regexp matching security"));
521 printf (" %s\n", _("this REGEXP, the plugin will return CRITICAL status. Can be specified")); 572 printf(" %s\n", _("upgrades for Debian and Ubuntu:"));
522 printf (" %s\n", _("multiple times like above. Default is a regexp matching security")); 573 printf(" \t%s\n", SECURITY_RE);
523 printf (" %s\n", _("upgrades for Debian and Ubuntu:")); 574 printf(" %s\n", _("Note that the package must first match the include list before its"));
524 printf (" \t%s\n", SECURITY_RE); 575 printf(" %s\n", _("information is compared against the critical list."));
525 printf (" %s\n", _("Note that the package must first match the include list before its")); 576 printf(" %s\n", "-o, --only-critical");
526 printf (" %s\n", _("information is compared against the critical list.")); 577 printf(" %s\n", _("Only warn about upgrades matching the critical list. The total number"));
527 printf (" %s\n", "-o, --only-critical"); 578 printf(" %s\n", _("of upgrades will be printed, but any non-critical upgrades will not cause"));
528 printf (" %s\n", _("Only warn about upgrades matching the critical list. The total number")); 579 printf(" %s\n", _("the plugin to return WARNING status."));
529 printf (" %s\n", _("of upgrades will be printed, but any non-critical upgrades will not cause")); 580 printf(" %s\n", "-w, --packages-warning");
530 printf (" %s\n", _("the plugin to return WARNING status.")); 581 printf(" %s\n", _("Minimum number of packages available for upgrade to return WARNING status."));
531 printf (" %s\n", "-w, --packages-warning"); 582 printf(" %s\n\n", _("Default is 1 package."));
532 printf (" %s\n", _("Minimum number of packages available for upgrade to return WARNING status.")); 583
533 printf (" %s\n\n", _("Default is 1 package.")); 584 printf("%s\n\n", _("The following options require root privileges and should be used with care:"));
534 585 printf(" %s\n", "-u, --update=OPTS");
535 printf ("%s\n\n", _("The following options require root privileges and should be used with care:")); 586 printf(" %s\n", _("First perform an 'apt-get update'. An optional OPTS parameter overrides"));
536 printf (" %s\n", "-u, --update=OPTS"); 587 printf(" %s\n", _("the default options. Note: you may also need to adjust the global"));
537 printf (" %s\n", _("First perform an 'apt-get update'. An optional OPTS parameter overrides")); 588 printf(" %s\n", _("timeout (with -t) to prevent the plugin from timing out if apt-get"));
538 printf (" %s\n", _("the default options. Note: you may also need to adjust the global")); 589 printf(" %s\n", _("upgrade is expected to take longer than the default timeout."));
539 printf (" %s\n", _("timeout (with -t) to prevent the plugin from timing out if apt-get")); 590 printf(" %s\n", "-U, --upgrade=OPTS");
540 printf (" %s\n", _("upgrade is expected to take longer than the default timeout.")); 591 printf(" %s\n", _("Perform an upgrade. If an optional OPTS argument is provided,"));
541 printf (" %s\n", "-U, --upgrade=OPTS"); 592 printf(" %s\n", _("apt-get will be run with these command line options instead of the"));
542 printf (" %s\n", _("Perform an upgrade. If an optional OPTS argument is provided,")); 593 printf(" %s", _("default "));
543 printf (" %s\n", _("apt-get will be run with these command line options instead of the")); 594 printf("(%s).\n", UPGRADE_DEFAULT_OPTS);
544 printf (" %s", _("default ")); 595 printf(" %s\n", _("Note that you may be required to have root privileges if you do not use"));
545 printf ("(%s).\n", UPGRADE_DEFAULT_OPTS); 596 printf(" %s\n", _("the default options, which will only run a simulation and NOT perform the upgrade"));
546 printf (" %s\n", _("Note that you may be required to have root privileges if you do not use")); 597 printf(" %s\n", "-d, --dist-upgrade=OPTS");
547 printf (" %s\n", _("the default options, which will only run a simulation and NOT perform the upgrade")); 598 printf(" %s\n", _("Perform a dist-upgrade instead of normal upgrade. Like with -U OPTS"));
548 printf (" %s\n", "-d, --dist-upgrade=OPTS"); 599 printf(" %s\n", _("can be provided to override the default options."));
549 printf (" %s\n", _("Perform a dist-upgrade instead of normal upgrade. Like with -U OPTS")); 600
550 printf (" %s\n", _("can be provided to override the default options.")); 601 printf(UT_SUPPORT);
551
552 printf(UT_SUPPORT);
553} 602}
554 603
555
556/* simple usage heading */ 604/* simple usage heading */
557void 605void print_usage(void) {
558print_usage(void) 606 printf("%s\n", _("Usage:"));
559{ 607 printf("%s [[-d|-u|-U]opts] [-n] [-l] [-t timeout] [-w packages-warning]\n", progname);
560 printf ("%s\n", _("Usage:"));
561 printf ("%s [[-d|-u|-U]opts] [-n] [-l] [-t timeout] [-w packages-warning]\n", progname);
562} 608}
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 e25d7a7..8ea73ce 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,1092 +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;
215static bool add_sslctx_verify_fun = false;
217#if defined(HAVE_SSL) && defined(USE_OPENSSL) 216#if defined(HAVE_SSL) && defined(USE_OPENSSL)
218X509 *cert = NULL; 217static X509 *cert = NULL;
219#endif /* defined(HAVE_SSL) && defined(USE_OPENSSL) */ 218#endif /* defined(HAVE_SSL) && defined(USE_OPENSSL) */
220bool no_body = false; 219static bool no_body = false;
221int maximum_age = -1; 220static int maximum_age = -1;
222int address_family = AF_UNSPEC; 221static int address_family = AF_UNSPEC;
223curlhelp_ssl_library ssl_library = CURLHELP_SSL_LIBRARY_UNKNOWN; 222static curlhelp_ssl_library ssl_library = CURLHELP_SSL_LIBRARY_UNKNOWN;
224int curl_http_version = CURL_HTTP_VERSION_NONE; 223static int curl_http_version = CURL_HTTP_VERSION_NONE;
225bool automatic_decompression = false; 224static bool automatic_decompression = false;
226char *cookie_jar_file = NULL; 225static char *cookie_jar_file = NULL;
227bool haproxy_protocol = false; 226static bool haproxy_protocol = false;
228 227
229bool process_arguments (int, char**); 228static bool process_arguments(int /*argc*/, char ** /*argv*/);
230void handle_curl_option_return_code (CURLcode res, const char* option); 229static void handle_curl_option_return_code(CURLcode res, const char *option);
231int check_http (void); 230static int check_http(void);
232void redir (curlhelp_write_curlbuf*); 231static void redir(curlhelp_write_curlbuf * /*header_buf*/);
233char *perfd_time (double microsec); 232static char *perfd_time(double elapsed_time);
234char *perfd_time_connect (double microsec); 233static char *perfd_time_connect(double elapsed_time_connect);
235char *perfd_time_ssl (double microsec); 234static char *perfd_time_ssl(double elapsed_time_ssl);
236char *perfd_time_firstbyte (double microsec); 235static char *perfd_time_firstbyte(double elapsed_time_firstbyte);
237char *perfd_time_headers (double microsec); 236static char *perfd_time_headers(double elapsed_time_headers);
238char *perfd_time_transfer (double microsec); 237static char *perfd_time_transfer(double elapsed_time_transfer);
239char *perfd_size (int page_len); 238static char *perfd_size(int page_len);
240void print_help (void); 239static void print_help(void);
241void print_usage (void); 240void print_usage(void);
242void print_curl_version (void); 241static void print_curl_version(void);
243int curlhelp_initwritebuffer (curlhelp_write_curlbuf*); 242static int curlhelp_initwritebuffer(curlhelp_write_curlbuf * /*buf*/);
244size_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*/);
245void curlhelp_freewritebuffer (curlhelp_write_curlbuf*); 244static void curlhelp_freewritebuffer(curlhelp_write_curlbuf * /*buf*/);
246int curlhelp_initreadbuffer (curlhelp_read_curlbuf *, const char *, size_t); 245static int curlhelp_initreadbuffer(curlhelp_read_curlbuf * /*buf*/, const char * /*data*/, size_t /*datalen*/);
247size_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*/);
248void curlhelp_freereadbuffer (curlhelp_read_curlbuf *); 247static void curlhelp_freereadbuffer(curlhelp_read_curlbuf * /*buf*/);
249curlhelp_ssl_library curlhelp_get_ssl_library (); 248static curlhelp_ssl_library curlhelp_get_ssl_library(void);
250const char* curlhelp_get_ssl_library_string (curlhelp_ssl_library); 249static const char *curlhelp_get_ssl_library_string(curlhelp_ssl_library /*ssl_library*/);
251int net_noopenssl_check_certificate (cert_ptr_union*, int, int); 250int net_noopenssl_check_certificate(cert_ptr_union *, int, int);
252 251
253int curlhelp_parse_statusline (const char*, curlhelp_statusline *); 252static int curlhelp_parse_statusline(const char * /*buf*/, curlhelp_statusline * /*status_line*/);
254void curlhelp_free_statusline (curlhelp_statusline *); 253static void curlhelp_free_statusline(curlhelp_statusline * /*status_line*/);
255char *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);
256int 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]);
257int 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);
258 257
259#if defined(HAVE_SSL) && defined(USE_OPENSSL) 258#if defined(HAVE_SSL) && defined(USE_OPENSSL)
260int 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);
261#endif /* defined(HAVE_SSL) && defined(USE_OPENSSL) */ 260#endif /* defined(HAVE_SSL) && defined(USE_OPENSSL) */
262 261
263void remove_newlines (char *); 262static void test_file(char * /*path*/);
264void test_file (char *);
265 263
266int 264int main(int argc, char **argv) {
267main (int argc, char **argv) 265 int result = STATE_UNKNOWN;
268{
269 int result = STATE_UNKNOWN;
270 266
271 setlocale (LC_ALL, ""); 267 setlocale(LC_ALL, "");
272 bindtextdomain (PACKAGE, LOCALEDIR); 268 bindtextdomain(PACKAGE, LOCALEDIR);
273 textdomain (PACKAGE); 269 textdomain(PACKAGE);
274 270
275 /* Parse extra opts if any */ 271 /* Parse extra opts if any */
276 argv = np_extra_opts (&argc, argv, progname); 272 argv = np_extra_opts(&argc, argv, progname);
277 273
278 /* set defaults */ 274 /* set defaults */
279 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());
280 progname, NP_VERSION, VERSION, curl_version());
281 276
282 /* parse arguments */ 277 /* parse arguments */
283 if (process_arguments (argc, argv) == false) 278 if (process_arguments(argc, argv) == false)
284 usage4 (_("Could not parse arguments")); 279 usage4(_("Could not parse arguments"));
285 280
286 if (display_html) 281 if (display_html)
287 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,
288 use_ssl ? "https" : "http", 283 virtual_port ? virtual_port : server_port, server_url);
289 host_name ? host_name : server_address,
290 virtual_port ? virtual_port : server_port,
291 server_url);
292 284
293 result = check_http (); 285 result = check_http();
294 return result; 286 return result;
295} 287}
296 288
297#ifdef HAVE_SSL 289#ifdef HAVE_SSL
298#ifdef USE_OPENSSL 290# ifdef USE_OPENSSL
299 291
300int verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx) 292int verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx) {
301{ 293 (void)preverify_ok;
302 (void) preverify_ok; 294 /* TODO: we get all certificates of the chain, so which ones
303 /* TODO: we get all certificates of the chain, so which ones 295 * should we test?
304 * should we test? 296 * TODO: is the last certificate always the server certificate?
305 * TODO: is the last certificate always the server certificate? 297 */
306 */ 298 cert = X509_STORE_CTX_get_current_cert(x509_ctx);
307 cert = X509_STORE_CTX_get_current_cert(x509_ctx); 299# if OPENSSL_VERSION_NUMBER >= 0x10100000L
308#if OPENSSL_VERSION_NUMBER >= 0x10100000L 300 X509_up_ref(cert);
309 X509_up_ref(cert); 301# endif
310#endif 302 if (verbose >= 2) {
311 if (verbose>=2) { 303 puts("* SSL verify callback with certificate:");
312 puts("* SSL verify callback with certificate:"); 304 X509_NAME *subject;
313 X509_NAME *subject, *issuer; 305 X509_NAME *issuer;
314 printf("* issuer:\n"); 306 printf("* issuer:\n");
315 issuer = X509_get_issuer_name( cert ); 307 issuer = X509_get_issuer_name(cert);
316 X509_NAME_print_ex_fp(stdout, issuer, 5, XN_FLAG_MULTILINE); 308 X509_NAME_print_ex_fp(stdout, issuer, 5, XN_FLAG_MULTILINE);
317 printf("* curl verify_callback:\n* subject:\n"); 309 printf("* curl verify_callback:\n* subject:\n");
318 subject = X509_get_subject_name( cert ); 310 subject = X509_get_subject_name(cert);
319 X509_NAME_print_ex_fp(stdout, subject, 5, XN_FLAG_MULTILINE); 311 X509_NAME_print_ex_fp(stdout, subject, 5, XN_FLAG_MULTILINE);
320 puts(""); 312 puts("");
321 } 313 }
322 return 1; 314 return 1;
323} 315}
324 316
325CURLcode sslctxfun(CURL *curl, SSL_CTX *sslctx, void *parm) 317CURLcode sslctxfun(CURL *curl, SSL_CTX *sslctx, void *parm) {
326{ 318 (void)curl; // ignore unused parameter
327 (void) curl; // ignore unused parameter 319 (void)parm; // ignore unused parameter
328 (void) parm; // ignore unused parameter 320 if (add_sslctx_verify_fun) {
329 SSL_CTX_set_verify(sslctx, SSL_VERIFY_PEER, verify_callback); 321 SSL_CTX_set_verify(sslctx, SSL_VERIFY_PEER, verify_callback);
322 }
330 323
331 return CURLE_OK; 324 // workaround for issue:
325 // OpenSSL SSL_read: error:0A000126:SSL routines::unexpected eof while reading, errno 0
326 // see discussion https://github.com/openssl/openssl/discussions/22690
327# ifdef SSL_OP_IGNORE_UNEXPECTED_EOF
328 SSL_CTX_set_options(sslctx, SSL_OP_IGNORE_UNEXPECTED_EOF);
329# endif
330
331 return CURLE_OK;
332} 332}
333 333
334#endif /* USE_OPENSSL */ 334# endif /* USE_OPENSSL */
335#endif /* HAVE_SSL */ 335#endif /* HAVE_SSL */
336 336
337/* returns a string "HTTP/1.x" or "HTTP/2" */ 337/* returns a string "HTTP/1.x" or "HTTP/2" */
338static char *string_statuscode (int major, int minor) 338static char *string_statuscode(int major, int minor) {
339{ 339 static char buf[10];
340 static char buf[10]; 340
341 341 switch (major) {
342 switch (major) { 342 case 1:
343 case 1: 343 snprintf(buf, sizeof(buf), "HTTP/%d.%d", major, minor);
344 snprintf (buf, sizeof (buf), "HTTP/%d.%d", major, minor); 344 break;
345 break; 345 case 2:
346 case 2: 346 case 3:
347 case 3: 347 snprintf(buf, sizeof(buf), "HTTP/%d", major);
348 snprintf (buf, sizeof (buf), "HTTP/%d", major); 348 break;
349 break; 349 default:
350 default: 350 /* assuming here HTTP/N with N>=4 */
351 /* assuming here HTTP/N with N>=4 */ 351 snprintf(buf, sizeof(buf), "HTTP/%d", major);
352 snprintf (buf, sizeof (buf), "HTTP/%d", major); 352 break;
353 break; 353 }
354 } 354
355 355 return buf;
356 return buf;
357} 356}
358 357
359/* Checks if the server 'reply' is one of the expected 'statuscodes' */ 358/* Checks if the server 'reply' is one of the expected 'statuscodes' */
360static int 359static int expected_statuscode(const char *reply, const char *statuscodes) {
361expected_statuscode (const char *reply, const char *statuscodes) 360 char *expected;
362{ 361 char *code;
363 char *expected, *code; 362 int result = 0;
364 int result = 0; 363
365 364 if ((expected = strdup(statuscodes)) == NULL)
366 if ((expected = strdup (statuscodes)) == NULL) 365 die(STATE_UNKNOWN, _("HTTP UNKNOWN - Memory allocation error\n"));
367 die (STATE_UNKNOWN, _("HTTP UNKNOWN - Memory allocation error\n")); 366
368 367 for (code = strtok(expected, ","); code != NULL; code = strtok(NULL, ","))
369 for (code = strtok (expected, ","); code != NULL; code = strtok (NULL, ",")) 368 if (strstr(reply, code) != NULL) {
370 if (strstr (reply, code) != NULL) { 369 result = 1;
371 result = 1; 370 break;
372 break; 371 }
373 } 372
374 373 free(expected);
375 free (expected); 374 return result;
376 return result;
377} 375}
378 376
379void 377void handle_curl_option_return_code(CURLcode res, const char *option) {
380handle_curl_option_return_code (CURLcode res, const char* option) 378 if (res != CURLE_OK) {
381{ 379 snprintf(msg, DEFAULT_BUFFER_SIZE, _("Error while setting cURL option '%s': cURL returned %d - %s"), option, res,
382 if (res != CURLE_OK) { 380 curl_easy_strerror(res));
383 snprintf (msg, 381 die(STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg);
384 DEFAULT_BUFFER_SIZE, 382 }
385 _("Error while setting cURL option '%s': cURL returned %d - %s"),
386 option,
387 res,
388 curl_easy_strerror(res));
389 die (STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg);
390 }
391} 383}
392 384
393int 385int lookup_host(const char *host, char *buf, size_t buflen) {
394lookup_host (const char *host, char *buf, size_t buflen) 386 struct addrinfo hints, *res, *result;
395{ 387 char addrstr[100];
396 struct addrinfo hints, *res, *result; 388 size_t addrstr_len;
397 char addrstr[100]; 389 int errcode;
398 size_t addrstr_len; 390 void *ptr = {0};
399 int errcode; 391 size_t buflen_remaining = buflen - 1;
400 void *ptr = { 0 }; 392
401 size_t buflen_remaining = buflen - 1; 393 memset(&hints, 0, sizeof(hints));
402 394 hints.ai_family = address_family;
403 memset (&hints, 0, sizeof (hints)); 395 hints.ai_socktype = SOCK_STREAM;
404 hints.ai_family = address_family; 396 hints.ai_flags |= AI_CANONNAME;
405 hints.ai_socktype = SOCK_STREAM; 397
406 hints.ai_flags |= AI_CANONNAME; 398 errcode = getaddrinfo(host, NULL, &hints, &result);
407 399 if (errcode != 0)
408 errcode = getaddrinfo (host, NULL, &hints, &result); 400 return errcode;
409 if (errcode != 0) 401
410 return errcode; 402 strcpy(buf, "");
411 403 res = result;
412 strcpy(buf, ""); 404
413 res = result; 405 while (res) {
414 406 switch (res->ai_family) {
415 while (res) { 407 case AF_INET:
416 switch (res->ai_family) { 408 ptr = &((struct sockaddr_in *)res->ai_addr)->sin_addr;
417 case AF_INET: 409 break;
418 ptr = &((struct sockaddr_in *) res->ai_addr)->sin_addr; 410 case AF_INET6:
419 break; 411 ptr = &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr;
420 case AF_INET6: 412 break;
421 ptr = &((struct sockaddr_in6 *) res->ai_addr)->sin6_addr; 413 }
422 break; 414
423 } 415 inet_ntop(res->ai_family, ptr, addrstr, 100);
424 416 if (verbose >= 1) {
425 inet_ntop (res->ai_family, ptr, addrstr, 100); 417 printf("* getaddrinfo IPv%d address: %s\n", res->ai_family == PF_INET6 ? 6 : 4, addrstr);
426 if (verbose >= 1) { 418 }
427 printf ("* getaddrinfo IPv%d address: %s\n", 419
428 res->ai_family == PF_INET6 ? 6 : 4, addrstr); 420 // Append all IPs to buf as a comma-separated string
429 } 421 addrstr_len = strlen(addrstr);
430 422 if (buflen_remaining > addrstr_len + 1) {
431 // Append all IPs to buf as a comma-separated string 423 if (buf[0] != '\0') {
432 addrstr_len = strlen(addrstr); 424 strncat(buf, ",", buflen_remaining);
433 if (buflen_remaining > addrstr_len + 1) { 425 buflen_remaining -= 1;
434 if (buf[0] != '\0') { 426 }
435 strncat(buf, ",", buflen_remaining); 427 strncat(buf, addrstr, buflen_remaining);
436 buflen_remaining -= 1; 428 buflen_remaining -= addrstr_len;
437 } 429 }
438 strncat(buf, addrstr, buflen_remaining); 430
439 buflen_remaining -= addrstr_len; 431 res = res->ai_next;
440 } 432 }
441 433
442 res = res->ai_next; 434 freeaddrinfo(result);
443 } 435
444 436 return 0;
445 freeaddrinfo(result);
446
447 return 0;
448} 437}
449 438
450static void 439static void cleanup(void) {
451cleanup (void) 440 if (status_line_initialized)
452{ 441 curlhelp_free_statusline(&status_line);
453 if (status_line_initialized) curlhelp_free_statusline(&status_line); 442 status_line_initialized = false;
454 status_line_initialized = false; 443 if (curl_easy_initialized)
455 if (curl_easy_initialized) curl_easy_cleanup (curl); 444 curl_easy_cleanup(curl);
456 curl_easy_initialized = false; 445 curl_easy_initialized = false;
457 if (curl_global_initialized) curl_global_cleanup (); 446 if (curl_global_initialized)
458 curl_global_initialized = false; 447 curl_global_cleanup();
459 if (body_buf_initialized) curlhelp_freewritebuffer (&body_buf); 448 curl_global_initialized = false;
460 body_buf_initialized = false; 449 if (body_buf_initialized)
461 if (header_buf_initialized) curlhelp_freewritebuffer (&header_buf); 450 curlhelp_freewritebuffer(&body_buf);
462 header_buf_initialized = false; 451 body_buf_initialized = false;
463 if (put_buf_initialized) curlhelp_freereadbuffer (&put_buf); 452 if (header_buf_initialized)
464 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;
465} 458}
466 459
467int 460int check_http(void) {
468check_http (void) 461 int result = STATE_OK;
469{ 462 int result_ssl = STATE_OK;
470 int result = STATE_OK; 463 int page_len = 0;
471 int result_ssl = STATE_OK; 464 int i;
472 int page_len = 0; 465 char *force_host_header = NULL;
473 int i; 466 struct curl_slist *host = NULL;
474 char *force_host_header = NULL; 467 char addrstr[DEFAULT_BUFFER_SIZE / 2];
475 struct curl_slist *host = NULL; 468 char dnscache[DEFAULT_BUFFER_SIZE];
476 char addrstr[DEFAULT_BUFFER_SIZE/2]; 469
477 char dnscache[DEFAULT_BUFFER_SIZE]; 470 /* initialize curl */
478 471 if (curl_global_init(CURL_GLOBAL_DEFAULT) != CURLE_OK)
479 /* initialize curl */ 472 die(STATE_UNKNOWN, "HTTP UNKNOWN - curl_global_init failed\n");
480 if (curl_global_init (CURL_GLOBAL_DEFAULT) != CURLE_OK) 473 curl_global_initialized = true;
481 die (STATE_UNKNOWN, "HTTP UNKNOWN - curl_global_init failed\n"); 474
482 curl_global_initialized = true; 475 if ((curl = curl_easy_init()) == NULL) {
483 476 die(STATE_UNKNOWN, "HTTP UNKNOWN - curl_easy_init failed\n");
484 if ((curl = curl_easy_init()) == NULL) { 477 }
485 die (STATE_UNKNOWN, "HTTP UNKNOWN - curl_easy_init failed\n"); 478 curl_easy_initialized = true;
486 } 479
487 curl_easy_initialized = true; 480 /* register cleanup function to shut down libcurl properly */
488 481 atexit(cleanup);
489 /* register cleanup function to shut down libcurl properly */ 482
490 atexit (cleanup); 483 if (verbose >= 1)
491 484 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_VERBOSE, 1), "CURLOPT_VERBOSE");
492 if (verbose >= 1) 485
493 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_VERBOSE, 1), "CURLOPT_VERBOSE"); 486 /* print everything on stdout like check_http would do */
494 487 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_STDERR, stdout), "CURLOPT_STDERR");
495 /* print everything on stdout like check_http would do */ 488
496 handle_curl_option_return_code (curl_easy_setopt(curl, CURLOPT_STDERR, stdout), "CURLOPT_STDERR"); 489 if (automatic_decompression)
497
498 if (automatic_decompression)
499#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 21, 6) 490#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 21, 6)
500 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");
501#else 492#else
502 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");
503#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 21, 6) */ 494#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 21, 6) */
504 495
505 /* initialize buffer for body of the answer */ 496 /* initialize buffer for body of the answer */
506 if (curlhelp_initwritebuffer(&body_buf) < 0) 497 if (curlhelp_initwritebuffer(&body_buf) < 0)
507 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");
508 body_buf_initialized = true; 499 body_buf_initialized = true;
509 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),
510 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_WRITEDATA, (void *)&body_buf), "CURLOPT_WRITEDATA"); 501 "CURLOPT_WRITEFUNCTION");
511 502 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&body_buf), "CURLOPT_WRITEDATA");
512 /* initialize buffer for header of the answer */ 503
513 if (curlhelp_initwritebuffer( &header_buf ) < 0) 504 /* initialize buffer for header of the answer */
514 die (STATE_UNKNOWN, "HTTP CRITICAL - out of memory allocating buffer for header\n" ); 505 if (curlhelp_initwritebuffer(&header_buf) < 0)
515 header_buf_initialized = true; 506 die(STATE_UNKNOWN, "HTTP CRITICAL - out of memory allocating buffer for header\n");
516 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;
517 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),
518 509 "CURLOPT_HEADERFUNCTION");
519 /* set the error buffer */ 510 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_WRITEHEADER, (void *)&header_buf), "CURLOPT_WRITEHEADER");
520 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_ERRORBUFFER, errbuf), "CURLOPT_ERRORBUFFER"); 511
521 512 /* set the error buffer */
522 /* set timeouts */ 513 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errbuf), "CURLOPT_ERRORBUFFER");
523 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_CONNECTTIMEOUT, socket_timeout), "CURLOPT_CONNECTTIMEOUT"); 514
524 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_TIMEOUT, socket_timeout), "CURLOPT_TIMEOUT"); 515 /* set timeouts */
525 516 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, socket_timeout), "CURLOPT_CONNECTTIMEOUT");
526 /* enable haproxy protocol */ 517 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_TIMEOUT, socket_timeout), "CURLOPT_TIMEOUT");
527 if (haproxy_protocol) { 518
528 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_HAPROXYPROTOCOL, 1L), "CURLOPT_HAPROXYPROTOCOL"); 519 /* enable haproxy protocol */
529 } 520 if (haproxy_protocol) {
530 521 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_HAPROXYPROTOCOL, 1L), "CURLOPT_HAPROXYPROTOCOL");
531 // 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 }
532 if(use_ssl && host_name != NULL) { 523
533 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
534 snprintf (msg, 525 // use the host_name later on to make SNI happy
535 DEFAULT_BUFFER_SIZE, 526 if (use_ssl && host_name != NULL) {
536 _("Unable to lookup IP address for '%s': getaddrinfo returned %d - %s"), 527 if ((res = lookup_host(server_address, addrstr, DEFAULT_BUFFER_SIZE / 2)) != 0) {
537 server_address, 528 snprintf(msg, DEFAULT_BUFFER_SIZE, _("Unable to lookup IP address for '%s': getaddrinfo returned %d - %s"), server_address, res,
538 res, 529 gai_strerror(res));
539 gai_strerror (res)); 530 die(STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg);
540 die (STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg); 531 }
541 } 532 snprintf(dnscache, DEFAULT_BUFFER_SIZE, "%s:%d:%s", host_name, server_port, addrstr);
542 snprintf (dnscache, DEFAULT_BUFFER_SIZE, "%s:%d:%s", host_name, server_port, addrstr); 533 host = curl_slist_append(NULL, dnscache);
543 host = curl_slist_append(NULL, dnscache); 534 curl_easy_setopt(curl, CURLOPT_RESOLVE, host);
544 curl_easy_setopt(curl, CURLOPT_RESOLVE, host); 535 if (verbose >= 1)
545 if (verbose>=1) 536 printf("* curl CURLOPT_RESOLVE: %s\n", dnscache);
546 printf ("* curl CURLOPT_RESOLVE: %s\n", dnscache); 537 }
547 } 538
548 539 // If server_address is an IPv6 address it must be surround by square brackets
549 // If server_address is an IPv6 address it must be surround by square brackets 540 struct in6_addr tmp_in_addr;
550 struct in6_addr tmp_in_addr; 541 if (inet_pton(AF_INET6, server_address, &tmp_in_addr) == 1) {
551 if (inet_pton(AF_INET6, server_address, &tmp_in_addr) == 1) { 542 char *new_server_address = malloc(strlen(server_address) + 3);
552 char *new_server_address = malloc(strlen(server_address) + 3); 543 if (new_server_address == NULL) {
553 if (new_server_address == NULL) { 544 die(STATE_UNKNOWN, "HTTP UNKNOWN - Unable to allocate memory\n");
554 die(STATE_UNKNOWN, "HTTP UNKNOWN - Unable to allocate memory\n"); 545 }
555 } 546 snprintf(new_server_address, strlen(server_address) + 3, "[%s]", server_address);
556 snprintf(new_server_address, strlen(server_address)+3, "[%s]", server_address); 547 free(server_address);
557 free(server_address); 548 server_address = new_server_address;
558 server_address = new_server_address; 549 }
559 } 550
560 551 /* compose URL: use the address we want to connect to, set Host: header later */
561 /* 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",
562 snprintf (url, DEFAULT_BUFFER_SIZE, "%s://%s:%d%s", 553 (use_ssl & (host_name != NULL)) ? host_name : server_address, server_port, server_url);
563 use_ssl ? "https" : "http", 554
564 ( use_ssl & ( host_name != NULL ) ) ? host_name : server_address, 555 if (verbose >= 1)
565 server_port, 556 printf("* curl CURLOPT_URL: %s\n", url);
566 server_url 557 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_URL, url), "CURLOPT_URL");
567 ); 558
568 559 /* extract proxy information for legacy proxy https requests */
569 if (verbose>=1) 560 if (!strcmp(http_method, "CONNECT") || strstr(server_url, "http") == server_url) {
570 printf ("* curl CURLOPT_URL: %s\n", url); 561 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_PROXY, server_address), "CURLOPT_PROXY");
571 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");
572 563 if (verbose >= 2)
573 /* extract proxy information for legacy proxy https requests */ 564 printf("* curl CURLOPT_PROXY: %s:%d\n", server_address, server_port);
574 if (!strcmp(http_method, "CONNECT") || strstr(server_url, "http") == server_url) { 565 http_method = "GET";
575 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");
576 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_PROXYPORT, (long)server_port), "CURLOPT_PROXYPORT"); 567 }
577 if (verbose>=2) 568
578 printf ("* curl CURLOPT_PROXY: %s:%d\n", server_address, server_port); 569 /* disable body for HEAD request */
579 http_method = "GET"; 570 if (http_method && !strcmp(http_method, "HEAD")) {
580 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_URL, server_url), "CURLOPT_URL"); 571 no_body = true;
581 } 572 }
582 573
583 /* disable body for HEAD request */ 574 /* set HTTP protocol version */
584 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");
585 no_body = true; 576
586 } 577 /* set HTTP method */
587 578 if (http_method) {
588 /* set HTTP protocol version */ 579 if (!strcmp(http_method, "POST"))
589 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");
590 581 else if (!strcmp(http_method, "PUT"))
591 /* set HTTP method */ 582 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_UPLOAD, 1), "CURLOPT_UPLOAD");
592 if (http_method) { 583 else
593 if (!strcmp(http_method, "POST")) 584 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, http_method), "CURLOPT_CUSTOMREQUEST");
594 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_POST, 1), "CURLOPT_POST"); 585 }
595 else if (!strcmp(http_method, "PUT")) 586
596 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_UPLOAD, 1), "CURLOPT_UPLOAD"); 587 /* check if Host header is explicitly set in options */
597 else 588 if (http_opt_headers_count) {
598 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++) {
599 } 590 if (strncmp(http_opt_headers[i], "Host:", 5) == 0) {
600 591 force_host_header = http_opt_headers[i];
601 /* check if Host header is explicitly set in options */ 592 }
602 if (http_opt_headers_count) { 593 }
603 for (i = 0; i < http_opt_headers_count ; i++) { 594 }
604 if (strncmp(http_opt_headers[i], "Host:", 5) == 0) { 595
605 force_host_header = http_opt_headers[i]; 596 /* set hostname (virtual hosts), not needed if CURLOPT_CONNECT_TO is used, but left in anyway */
606 } 597 if (host_name != NULL && force_host_header == NULL) {
607 } 598 if ((virtual_port != HTTP_PORT && !use_ssl) || (virtual_port != HTTPS_PORT && use_ssl)) {
608 } 599 snprintf(http_header, DEFAULT_BUFFER_SIZE, "Host: %s:%d", host_name, virtual_port);
609 600 } else {
610 /* 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);
611 if(host_name != NULL && force_host_header == NULL) { 602 }
612 if((virtual_port != HTTP_PORT && !use_ssl) || (virtual_port != HTTPS_PORT && use_ssl)) { 603 header_list = curl_slist_append(header_list, http_header);
613 snprintf(http_header, DEFAULT_BUFFER_SIZE, "Host: %s:%d", host_name, virtual_port); 604 }
614 } else { 605
615 snprintf(http_header, DEFAULT_BUFFER_SIZE, "Host: %s", host_name); 606 /* always close connection, be nice to servers */
616 } 607 snprintf(http_header, DEFAULT_BUFFER_SIZE, "Connection: close");
617 header_list = curl_slist_append (header_list, http_header); 608 header_list = curl_slist_append(header_list, http_header);
618 } 609
619 610 /* attach additional headers supplied by the user */
620 /* always close connection, be nice to servers */ 611 /* optionally send any other header tag */
621 snprintf (http_header, DEFAULT_BUFFER_SIZE, "Connection: close"); 612 if (http_opt_headers_count) {
622 header_list = curl_slist_append (header_list, http_header); 613 for (i = 0; i < http_opt_headers_count; i++) {
623 614 header_list = curl_slist_append(header_list, http_opt_headers[i]);
624 /* attach additional headers supplied by the user */ 615 }
625 /* optionally send any other header tag */ 616 /* This cannot be free'd here because a redirection will then try to access this and segfault */
626 if (http_opt_headers_count) { 617 /* Covered in a testcase in tests/check_http.t */
627 for (i = 0; i < http_opt_headers_count ; i++) { 618 /* free(http_opt_headers); */
628 header_list = curl_slist_append (header_list, http_opt_headers[i]); 619 }
629 } 620
630 /* This cannot be free'd here because a redirection will then try to access this and segfault */ 621 /* set HTTP headers */
631 /* 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");
632 /* free(http_opt_headers); */
633 }
634
635 /* set HTTP headers */
636 handle_curl_option_return_code (curl_easy_setopt( curl, CURLOPT_HTTPHEADER, header_list ), "CURLOPT_HTTPHEADER");
637 623
638#ifdef LIBCURL_FEATURE_SSL 624#ifdef LIBCURL_FEATURE_SSL
639 625
640 /* set SSL version, warn about insecure or unsupported versions */ 626 /* set SSL version, warn about insecure or unsupported versions */
641 if (use_ssl) { 627 if (use_ssl) {
642 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");
643 } 629 }
644 630
645 /* client certificate and key to present to server (SSL) */ 631 /* client certificate and key to present to server (SSL) */
646 if (client_cert) 632 if (client_cert)
647 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");
648 if (client_privkey) 634 if (client_privkey)
649 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");
650 if (ca_cert) { 636 if (ca_cert) {
651 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");
652 } 638 }
653 if (ca_cert || verify_peer_and_host) { 639 if (ca_cert || verify_peer_and_host) {
654 /* 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
655 * hostname in the certificate, can be switched off later */ 641 * hostname in the certificate, can be switched off later */
656 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");
657 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");
658 } else { 644 } else {
659 /* backward-compatible behaviour, be tolerant in checks 645 /* backward-compatible behaviour, be tolerant in checks
660 * TODO: depending on more options have aspects we want 646 * TODO: depending on more options have aspects we want
661 * to be less tolerant about ssl verfications 647 * to be less tolerant about ssl verfications
662 */ 648 */
663 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");
664 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");
665 } 651 }
666 652
667 /* detect SSL library used by libcurl */ 653 /* detect SSL library used by libcurl */
668 ssl_library = curlhelp_get_ssl_library (); 654 ssl_library = curlhelp_get_ssl_library();
669 655
670 /* try hard to get a stack of certificates to verify against */ 656 /* try hard to get a stack of certificates to verify against */
671 if (check_cert) { 657 if (check_cert) {
672#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 19, 1) 658# if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 19, 1)
673 /* inform curl to report back certificates */ 659 /* inform curl to report back certificates */
674 switch (ssl_library) { 660 switch (ssl_library) {
675 case CURLHELP_SSL_LIBRARY_OPENSSL: 661 case CURLHELP_SSL_LIBRARY_OPENSSL:
676 case CURLHELP_SSL_LIBRARY_LIBRESSL: 662 case CURLHELP_SSL_LIBRARY_LIBRESSL:
677 /* set callback to extract certificate with OpenSSL context function (works with 663 /* set callback to extract certificate with OpenSSL context function (works with
678 * OpenSSL-style libraries only!) */ 664 * OpenSSL-style libraries only!) */
679#ifdef USE_OPENSSL 665# ifdef USE_OPENSSL
680 /* libcurl and monitoring plugins built with OpenSSL, good */ 666 /* libcurl and monitoring plugins built with OpenSSL, good */
681 handle_curl_option_return_code (curl_easy_setopt(curl, CURLOPT_SSL_CTX_FUNCTION, sslctxfun), "CURLOPT_SSL_CTX_FUNCTION"); 667 add_sslctx_verify_fun = true;
682 is_openssl_callback = true; 668 is_openssl_callback = true;
683#else /* USE_OPENSSL */ 669# endif /* USE_OPENSSL */
684#endif /* USE_OPENSSL */ 670 /* libcurl is built with OpenSSL, monitoring plugins, so falling
685 /* libcurl is built with OpenSSL, monitoring plugins, so falling 671 * back to manually extracting certificate information */
686 * back to manually extracting certificate information */ 672 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_CERTINFO, 1L), "CURLOPT_CERTINFO");
687 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_CERTINFO, 1L), "CURLOPT_CERTINFO"); 673 break;
688 break; 674
689 675 case CURLHELP_SSL_LIBRARY_NSS:
690 case CURLHELP_SSL_LIBRARY_NSS: 676# if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0)
691#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) 677 /* NSS: support for CERTINFO is implemented since 7.34.0 */
692 /* NSS: support for CERTINFO is implemented since 7.34.0 */ 678 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_CERTINFO, 1L), "CURLOPT_CERTINFO");
693 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_CERTINFO, 1L), "CURLOPT_CERTINFO"); 679# else /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) */
694#else /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) */ 680 die(STATE_CRITICAL, "HTTP CRITICAL - Cannot retrieve certificates (libcurl linked with SSL library '%s' is too old)\n",
695 die (STATE_CRITICAL, "HTTP CRITICAL - Cannot retrieve certificates (libcurl linked with SSL library '%s' is too old)\n", curlhelp_get_ssl_library_string (ssl_library)); 681 curlhelp_get_ssl_library_string(ssl_library));
696#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) */ 682# endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) */
697 break; 683 break;
698 684
699 case CURLHELP_SSL_LIBRARY_GNUTLS: 685 case CURLHELP_SSL_LIBRARY_GNUTLS:
700#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 42, 0) 686# if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 42, 0)
701 /* GnuTLS: support for CERTINFO is implemented since 7.42.0 */ 687 /* GnuTLS: support for CERTINFO is implemented since 7.42.0 */
702 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_CERTINFO, 1L), "CURLOPT_CERTINFO"); 688 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_CERTINFO, 1L), "CURLOPT_CERTINFO");
703#else /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 42, 0) */ 689# else /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 42, 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)); 690 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, 42, 0) */ 691 curlhelp_get_ssl_library_string(ssl_library));
706 break; 692# endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 42, 0) */
707 693 break;
708 case CURLHELP_SSL_LIBRARY_UNKNOWN: 694
709 default: 695 case CURLHELP_SSL_LIBRARY_UNKNOWN:
710 die (STATE_CRITICAL, "HTTP CRITICAL - Cannot retrieve certificates (unknown SSL library '%s', must implement first)\n", curlhelp_get_ssl_library_string (ssl_library)); 696 default:
711 break; 697 die(STATE_CRITICAL, "HTTP CRITICAL - Cannot retrieve certificates (unknown SSL library '%s', must implement first)\n",
712 } 698 curlhelp_get_ssl_library_string(ssl_library));
713#else /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 19, 1) */ 699 break;
714 /* old libcurl, our only hope is OpenSSL, otherwise we are out of luck */ 700 }
715 if (ssl_library == CURLHELP_SSL_LIBRARY_OPENSSL || ssl_library == CURLHELP_SSL_LIBRARY_LIBRESSL) 701# else /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 19, 1) */
716 handle_curl_option_return_code (curl_easy_setopt(curl, CURLOPT_SSL_CTX_FUNCTION, sslctxfun), "CURLOPT_SSL_CTX_FUNCTION"); 702 /* old libcurl, our only hope is OpenSSL, otherwise we are out of luck */
717 else 703 if (ssl_library == CURLHELP_SSL_LIBRARY_OPENSSL || ssl_library == CURLHELP_SSL_LIBRARY_LIBRESSL)
718 die (STATE_CRITICAL, "HTTP CRITICAL - Cannot retrieve certificates (no CURLOPT_SSL_CTX_FUNCTION, no OpenSSL library or libcurl too old and has no CURLOPT_CERTINFO)\n"); 704 add_sslctx_verify_fun = true;
719#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 19, 1) */ 705 else
720 } 706 die(STATE_CRITICAL, "HTTP CRITICAL - Cannot retrieve certificates (no CURLOPT_SSL_CTX_FUNCTION, no OpenSSL library or libcurl "
707 "too old and has no CURLOPT_CERTINFO)\n");
708# endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 19, 1) */
709 }
710
711# if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 10, 6) /* required for CURLOPT_SSL_CTX_FUNCTION */
712 // ssl ctx function is not available with all ssl backends
713 if (curl_easy_setopt(curl, CURLOPT_SSL_CTX_FUNCTION, NULL) != CURLE_UNKNOWN_OPTION)
714 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_SSL_CTX_FUNCTION, sslctxfun), "CURLOPT_SSL_CTX_FUNCTION");
715# endif
721 716
722#endif /* LIBCURL_FEATURE_SSL */ 717#endif /* LIBCURL_FEATURE_SSL */
723 718
724 /* set default or user-given user agent identification */ 719 /* set default or user-given user agent identification */
725 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");
726 721
727 /* proxy-authentication */ 722 /* proxy-authentication */
728 if (strcmp(proxy_auth, "")) 723 if (strcmp(proxy_auth, ""))
729 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");
730 725
731 /* authentication */ 726 /* authentication */
732 if (strcmp(user_auth, "")) 727 if (strcmp(user_auth, ""))
733 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");
734 729
735 /* TODO: parameter auth method, bitfield of following methods: 730 /* TODO: parameter auth method, bitfield of following methods:
736 * CURLAUTH_BASIC (default) 731 * CURLAUTH_BASIC (default)
737 * CURLAUTH_DIGEST 732 * CURLAUTH_DIGEST
738 * CURLAUTH_DIGEST_IE 733 * CURLAUTH_DIGEST_IE
739 * CURLAUTH_NEGOTIATE 734 * CURLAUTH_NEGOTIATE
740 * CURLAUTH_NTLM 735 * CURLAUTH_NTLM
741 * CURLAUTH_NTLM_WB 736 * CURLAUTH_NTLM_WB
742 * 737 *
743 * convenience tokens for typical sets of methods: 738 * convenience tokens for typical sets of methods:
744 * CURLAUTH_ANYSAFE: most secure, without BASIC 739 * CURLAUTH_ANYSAFE: most secure, without BASIC
745 * or CURLAUTH_ANY: most secure, even BASIC if necessary 740 * or CURLAUTH_ANY: most secure, even BASIC if necessary
746 * 741 *
747 * 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");
748 */ 743 */
749 744
750 /* handle redirections */ 745 /* handle redirections */
751 if (onredirect == STATE_DEPENDENT) { 746 if (onredirect == STATE_DEPENDENT) {
752 if( followmethod == FOLLOW_LIBCURL ) { 747 if (followmethod == FOLLOW_LIBCURL) {
753 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");
754 749
755 /* default -1 is infinite, not good, could lead to zombie plugins! 750 /* default -1 is infinite, not good, could lead to zombie plugins!
756 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
757 */ 752 */
758 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");
759 754
760 /* 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) */
761#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 85, 0) 756#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 85, 0)
762 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");
763#elif LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 19, 4) 759#elif LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 19, 4)
764 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");
765#endif 762#endif
766 763
767 /* TODO: handle the following aspects of redirection, make them 764 /* TODO: handle the following aspects of redirection, make them
768 * command line options too later: 765 * command line options too later:
769 CURLOPT_POSTREDIR: method switch 766 CURLOPT_POSTREDIR: method switch
770 CURLINFO_REDIRECT_URL: custom redirect option 767 CURLINFO_REDIRECT_URL: custom redirect option
771 CURLOPT_REDIRECT_PROTOCOLS: allow people to step outside safe protocols 768 CURLOPT_REDIRECT_PROTOCOLS: allow people to step outside safe protocols
772 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?
773 */ 770 */
774 } else { 771 } else {
775 /* old style redirection is handled below */ 772 /* old style redirection is handled below */
776 } 773 }
777 } 774 }
778 775
779 /* no-body */ 776 /* no-body */
780 if (no_body) 777 if (no_body)
781 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");
782 779
783 /* IPv4 or IPv6 forced DNS resolution */ 780 /* IPv4 or IPv6 forced DNS resolution */
784 if (address_family == AF_UNSPEC) 781 if (address_family == AF_UNSPEC)
785 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),
786 else if (address_family == AF_INET) 783 "CURLOPT_IPRESOLVE(CURL_IPRESOLVE_WHATEVER)");
787 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)
788#if defined (USE_IPV6) && defined (LIBCURL_FEATURE_IPV6) 785 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4),
789 else if (address_family == AF_INET6) 786 "CURLOPT_IPRESOLVE(CURL_IPRESOLVE_V4)");
790 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)");
791#endif 791#endif
792 792
793 /* either send http POST data (any data, not only POST)*/ 793 /* either send http POST data (any data, not only POST)*/
794 if (!strcmp(http_method, "POST") ||!strcmp(http_method, "PUT")) { 794 if (!strcmp(http_method, "POST") || !strcmp(http_method, "PUT")) {
795 /* set content of payload for POST and PUT */ 795 /* set content of payload for POST and PUT */
796 if (http_content_type) { 796 if (http_content_type) {
797 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);
798 header_list = curl_slist_append (header_list, http_header); 798 header_list = curl_slist_append(header_list, http_header);
799 } 799 }
800 /* NULL indicates "HTTP Continue" in libcurl, provide an empty string 800 /* NULL indicates "HTTP Continue" in libcurl, provide an empty string
801 * in case of no POST/PUT data */ 801 * in case of no POST/PUT data */
802 if (!http_post_data) 802 if (!http_post_data)
803 http_post_data = ""; 803 http_post_data = "";
804 if (!strcmp(http_method, "POST")) { 804 if (!strcmp(http_method, "POST")) {
805 /* POST method, set payload with CURLOPT_POSTFIELDS */ 805 /* POST method, set payload with CURLOPT_POSTFIELDS */
806 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");
807 } else if (!strcmp(http_method, "PUT")) { 807 } else if (!strcmp(http_method, "PUT")) {
808 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),
809 if (curlhelp_initreadbuffer (&put_buf, http_post_data, strlen (http_post_data)) < 0) 809 "CURLOPT_READFUNCTION");
810 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)
811 put_buf_initialized = true; 811 die(STATE_UNKNOWN, "HTTP CRITICAL - out of memory allocating read buffer for PUT\n");
812 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_READDATA, (void *)&put_buf), "CURLOPT_READDATA"); 812 put_buf_initialized = true;
813 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");
814 } 814 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_INFILESIZE, (curl_off_t)strlen(http_post_data)),
815 } 815 "CURLOPT_INFILESIZE");
816 816 }
817 /* cookie handling */ 817 }
818 if (cookie_jar_file != NULL) { 818
819 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_COOKIEJAR, cookie_jar_file), "CURLOPT_COOKIEJAR"); 819 /* cookie handling */
820 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_COOKIEFILE, cookie_jar_file), "CURLOPT_COOKIEFILE"); 820 if (cookie_jar_file != NULL) {
821 } 821 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_COOKIEJAR, cookie_jar_file), "CURLOPT_COOKIEJAR");
822 822 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_COOKIEFILE, cookie_jar_file), "CURLOPT_COOKIEFILE");
823 /* do the request */ 823 }
824 res = curl_easy_perform(curl); 824
825 825 /* do the request */
826 if (verbose>=2 && http_post_data) 826 res = curl_easy_perform(curl);
827 printf ("**** REQUEST CONTENT ****\n%s\n", http_post_data); 827
828 828 if (verbose >= 2 && http_post_data)
829 /* free header and server IP resolve lists, we don't need it anymore */ 829 printf("**** REQUEST CONTENT ****\n%s\n", http_post_data);
830 curl_slist_free_all (header_list); header_list = NULL; 830
831 curl_slist_free_all (server_ips); server_ips = NULL; 831 /* free header and server IP resolve lists, we don't need it anymore */
832 if (host) { 832 curl_slist_free_all(header_list);
833 curl_slist_free_all (host); host = NULL; 833 header_list = NULL;
834 } 834 curl_slist_free_all(server_ips);
835 835 server_ips = NULL;
836 /* Curl errors, result in critical Nagios state */ 836 if (host) {
837 if (res != CURLE_OK) { 837 curl_slist_free_all(host);
838 snprintf (msg, 838 host = NULL;
839 DEFAULT_BUFFER_SIZE, 839 }
840 _("Invalid HTTP response received from host on port %d: cURL returned %d - %s"), 840
841 server_port, 841 /* Curl errors, result in critical Nagios state */
842 res, 842 if (res != CURLE_OK) {
843 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,
844 die (STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg); 844 res, errbuf[0] ? errbuf : curl_easy_strerror(res));
845 } 845 die(STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg);
846 846 }
847 /* certificate checks */ 847
848 /* certificate checks */
848#ifdef LIBCURL_FEATURE_SSL 849#ifdef LIBCURL_FEATURE_SSL
849 if (use_ssl) { 850 if (use_ssl) {
850 if (check_cert) { 851 if (check_cert) {
851 if (is_openssl_callback) { 852 if (is_openssl_callback) {
852#ifdef USE_OPENSSL 853# ifdef USE_OPENSSL
853 /* check certificate with OpenSSL functions, curl has been built against OpenSSL 854 /* check certificate with OpenSSL functions, curl has been built against OpenSSL
854 * and we actually have OpenSSL in the monitoring tools 855 * and we actually have OpenSSL in the monitoring tools
855 */ 856 */
856 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);
857 if (!continue_after_check_cert) { 858 if (!continue_after_check_cert) {
858 return result_ssl; 859 return result_ssl;
859 } 860 }
860#else /* USE_OPENSSL */ 861# else /* USE_OPENSSL */
861 die (STATE_CRITICAL, "HTTP CRITICAL - Cannot retrieve certificates - OpenSSL callback used and not linked against OpenSSL\n"); 862 die(STATE_CRITICAL,
862#endif /* USE_OPENSSL */ 863 "HTTP CRITICAL - Cannot retrieve certificates - OpenSSL callback used and not linked against OpenSSL\n");
863 } else { 864# endif /* USE_OPENSSL */
864 int i; 865 } else {
865 struct curl_slist *slist; 866 int i;
866 867 struct curl_slist *slist;
867 cert_ptr.to_info = NULL; 868
868 res = curl_easy_getinfo (curl, CURLINFO_CERTINFO, &cert_ptr.to_info); 869 cert_ptr.to_info = NULL;
869 if (!res && cert_ptr.to_info) { 870 res = curl_easy_getinfo(curl, CURLINFO_CERTINFO, &cert_ptr.to_info);
870#ifdef USE_OPENSSL 871 if (!res && cert_ptr.to_info) {
871 /* We have no OpenSSL in libcurl, but we can use OpenSSL for X509 cert parsing 872# ifdef USE_OPENSSL
872 * 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
873 */ 874 * We only check the first certificate and assume it's the one of the server
874 const char* raw_cert = NULL; 875 */
875 for (i = 0; i < cert_ptr.to_certinfo->num_of_certs; i++) { 876 const char *raw_cert = NULL;
876 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++) {
877 if (verbose >= 2) 878 for (slist = cert_ptr.to_certinfo->certinfo[i]; slist; slist = slist->next) {
878 printf ("%d ** %s\n", i, slist->data); 879 if (verbose >= 2)
879 if (strncmp (slist->data, "Cert:", 5) == 0) { 880 printf("%d ** %s\n", i, slist->data);
880 raw_cert = &slist->data[5]; 881 if (strncmp(slist->data, "Cert:", 5) == 0) {
881 goto GOT_FIRST_CERT; 882 raw_cert = &slist->data[5];
882 } 883 goto GOT_FIRST_CERT;
883 } 884 }
884 } 885 }
885GOT_FIRST_CERT: 886 }
886 if (!raw_cert) { 887 GOT_FIRST_CERT:
887 snprintf (msg, 888 if (!raw_cert) {
888 DEFAULT_BUFFER_SIZE, 889 snprintf(msg, DEFAULT_BUFFER_SIZE,
889 _("Cannot retrieve certificates from CERTINFO information - certificate data was empty")); 890 _("Cannot retrieve certificates from CERTINFO information - certificate data was empty"));
890 die (STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg); 891 die(STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg);
891 } 892 }
892 BIO* cert_BIO = BIO_new (BIO_s_mem()); 893 BIO *cert_BIO = BIO_new(BIO_s_mem());
893 BIO_write (cert_BIO, raw_cert, strlen(raw_cert)); 894 BIO_write(cert_BIO, raw_cert, strlen(raw_cert));
894 cert = PEM_read_bio_X509 (cert_BIO, NULL, NULL, NULL); 895 cert = PEM_read_bio_X509(cert_BIO, NULL, NULL, NULL);
895 if (!cert) { 896 if (!cert) {
896 snprintf (msg, 897 snprintf(msg, DEFAULT_BUFFER_SIZE, _("Cannot read certificate from CERTINFO information - BIO error"));
897 DEFAULT_BUFFER_SIZE, 898 die(STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg);
898 _("Cannot read certificate from CERTINFO information - BIO error")); 899 }
899 die (STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg); 900 BIO_free(cert_BIO);
900 } 901 result_ssl = np_net_ssl_check_certificate(cert, days_till_exp_warn, days_till_exp_crit);
901 BIO_free (cert_BIO); 902 if (!continue_after_check_cert) {
902 result_ssl = np_net_ssl_check_certificate(cert, days_till_exp_warn, days_till_exp_crit); 903 return result_ssl;
903 if (!continue_after_check_cert) { 904 }
904 return result_ssl; 905# else /* USE_OPENSSL */
905 } 906 /* We assume we don't have OpenSSL and np_net_ssl_check_certificate at our disposal,
906#else /* USE_OPENSSL */ 907 * so we use the libcurl CURLINFO data
907 /* We assume we don't have OpenSSL and np_net_ssl_check_certificate at our disposal, 908 */
908 * so we use the libcurl CURLINFO data 909 result_ssl = net_noopenssl_check_certificate(&cert_ptr, days_till_exp_warn, days_till_exp_crit);
909 */ 910 if (!continue_after_check_cert) {
910 result_ssl = net_noopenssl_check_certificate(&cert_ptr, days_till_exp_warn, days_till_exp_crit); 911 return result_ssl;
911 if (!continue_after_check_cert) { 912 }
912 return result_ssl; 913# endif /* USE_OPENSSL */
913 } 914 } else {
914#endif /* USE_OPENSSL */ 915 snprintf(msg, DEFAULT_BUFFER_SIZE, _("Cannot retrieve certificates - cURL returned %d - %s"), res,
915 } else { 916 curl_easy_strerror(res));
916 snprintf (msg, 917 die(STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg);
917 DEFAULT_BUFFER_SIZE, 918 }
918 _("Cannot retrieve certificates - cURL returned %d - %s"), 919 }
919 res, 920 }
920 curl_easy_strerror(res)); 921 }
921 die (STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg);
922 }
923 }
924 }
925 }
926#endif /* LIBCURL_FEATURE_SSL */ 922#endif /* LIBCURL_FEATURE_SSL */
927 923
928 /* 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
929 * performance data to the answer always 925 * performance data to the answer always
930 */ 926 */
931 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");
932 page_len = get_content_length(&header_buf, &body_buf); 928 page_len = get_content_length(&header_buf, &body_buf);
933 if(show_extended_perfdata) { 929 if (show_extended_perfdata) {
934 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");
935 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");
936 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");
937 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),
938 snprintf(perfstring, DEFAULT_BUFFER_SIZE, "%s %s %s %s %s %s %s", 934 "CURLINFO_STARTTRANSFER_TIME");
939 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),
940 perfd_size(page_len), 936 perfd_time_connect(time_connect), use_ssl ? perfd_time_ssl(time_appconnect - time_connect) : "",
941 perfd_time_connect(time_connect), 937 perfd_time_headers(time_headers - time_appconnect), perfd_time_firstbyte(time_firstbyte - time_headers),
942 use_ssl ? perfd_time_ssl (time_appconnect-time_connect) : "", 938 perfd_time_transfer(total_time - time_firstbyte));
943 perfd_time_headers(time_headers - time_appconnect), 939 } else {
944 perfd_time_firstbyte(time_firstbyte - time_headers), 940 snprintf(perfstring, DEFAULT_BUFFER_SIZE, "%s %s", perfd_time(total_time), perfd_size(page_len));
945 perfd_time_transfer(total_time-time_firstbyte) 941 }
946 );
947 } else {
948 snprintf(perfstring, DEFAULT_BUFFER_SIZE, "%s %s",
949 perfd_time(total_time),
950 perfd_size(page_len)
951 );
952 }
953
954 /* return a CRITICAL status if we couldn't read any data */
955 if (strlen(header_buf.buf) == 0 && strlen(body_buf.buf) == 0)
956 die (STATE_CRITICAL, _("HTTP CRITICAL - No header received from host\n"));
957
958 /* get status line of answer, check sanity of HTTP code */
959 if (curlhelp_parse_statusline (header_buf.buf, &status_line) < 0) {
960 snprintf (msg,
961 DEFAULT_BUFFER_SIZE,
962 "Unparsable status line in %.3g seconds response time|%s\n",
963 total_time,
964 perfstring);
965 /* we cannot know the major/minor version here for sure as we cannot parse the first line */
966 die (STATE_CRITICAL, "HTTP CRITICAL HTTP/x.x %ld unknown - %s", code, msg);
967 }
968 status_line_initialized = true;
969
970 /* get result code from cURL */
971 handle_curl_option_return_code (curl_easy_getinfo (curl, CURLINFO_RESPONSE_CODE, &code), "CURLINFO_RESPONSE_CODE");
972 if (verbose>=2)
973 printf ("* curl CURLINFO_RESPONSE_CODE is %ld\n", code);
974
975 /* print status line, header, body if verbose */
976 if (verbose >= 2) {
977 printf ("**** HEADER ****\n%s\n**** CONTENT ****\n%s\n", header_buf.buf,
978 (no_body ? " [[ skipped ]]" : body_buf.buf));
979 }
980
981 /* make sure the status line matches the response we are looking for */
982 if (!expected_statuscode(status_line.first_line, server_expect)) {
983 if (server_port == HTTP_PORT)
984 snprintf(msg,
985 DEFAULT_BUFFER_SIZE,
986 _("Invalid HTTP response received from host: %s\n"),
987 status_line.first_line);
988 else
989 snprintf(msg,
990 DEFAULT_BUFFER_SIZE,
991 _("Invalid HTTP response received from host on port %d: %s\n"),
992 server_port,
993 status_line.first_line);
994 die (STATE_CRITICAL, "HTTP CRITICAL - %s%s%s", msg,
995 show_body ? "\n" : "",
996 show_body ? body_buf.buf : "");
997 }
998
999 if( server_expect_yn ) {
1000 snprintf(msg, DEFAULT_BUFFER_SIZE, _("Status line output matched \"%s\" - "), server_expect);
1001 if (verbose)
1002 printf ("%s\n",msg);
1003 result = STATE_OK;
1004 }
1005 else {
1006 /* illegal return codes result in a critical state */
1007 if (code >= 600 || code < 100) {
1008 die (STATE_CRITICAL, _("HTTP CRITICAL: Invalid Status (%d, %.40s)\n"), status_line.http_code, status_line.msg);
1009 /* server errors result in a critical state */
1010 } else if (code >= 500) {
1011 result = STATE_CRITICAL;
1012 /* client errors result in a warning state */
1013 } else if (code >= 400) {
1014 result = STATE_WARNING;
1015 /* check redirected page if specified */
1016 } else if (code >= 300) {
1017 if (onredirect == STATE_DEPENDENT) {
1018 if( followmethod == FOLLOW_LIBCURL ) {
1019 code = status_line.http_code;
1020 } else {
1021 /* old check_http style redirection, if we come
1022 * back here, we are in the same status as with
1023 * the libcurl method
1024 */
1025 redir (&header_buf);
1026 }
1027 } else {
1028 /* this is a specific code in the command line to
1029 * be returned when a redirection is encountered
1030 */
1031 }
1032 result = max_state_alt (onredirect, result);
1033 /* all other codes are considered ok */
1034 } else {
1035 result = STATE_OK;
1036 }
1037 }
1038
1039 /* libcurl redirection internally, handle error states here */
1040 if( followmethod == FOLLOW_LIBCURL ) {
1041 handle_curl_option_return_code (curl_easy_getinfo (curl, CURLINFO_REDIRECT_COUNT, &redir_depth), "CURLINFO_REDIRECT_COUNT");
1042 if (verbose >= 2)
1043 printf(_("* curl LIBINFO_REDIRECT_COUNT is %d\n"), redir_depth);
1044 if (redir_depth > max_depth) {
1045 snprintf (msg, DEFAULT_BUFFER_SIZE, "maximum redirection depth %d exceeded in libcurl",
1046 max_depth);
1047 die (STATE_WARNING, "HTTP WARNING - %s", msg);
1048 }
1049 }
1050
1051 /* check status codes, set exit status accordingly */
1052 if( status_line.http_code != code ) {
1053 die (STATE_CRITICAL, _("HTTP CRITICAL %s %d %s - different HTTP codes (cUrl has %ld)\n"),
1054 string_statuscode (status_line.http_major, status_line.http_minor),
1055 status_line.http_code, status_line.msg, code);
1056 }
1057
1058 if (maximum_age >= 0) {
1059 result = max_state_alt(check_document_dates(&header_buf, &msg), result);
1060 }
1061
1062 /* Page and Header content checks go here */
1063
1064 if (strlen (header_expect)) {
1065 if (!strstr (header_buf.buf, header_expect)) {
1066
1067 strncpy(&output_header_search[0],header_expect,sizeof(output_header_search));
1068
1069 if(output_header_search[sizeof(output_header_search)-1]!='\0') {
1070 bcopy("...",&output_header_search[sizeof(output_header_search)-4],4);
1071 }
1072 942
1073 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"));
1074 946
1075 snprintf (tmp, 947 /* get status line of answer, check sanity of HTTP code */
1076 DEFAULT_BUFFER_SIZE, 948 if (curlhelp_parse_statusline(header_buf.buf, &status_line) < 0) {
1077 _("%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);
1078 msg, 950 /* we cannot know the major/minor version here for sure as we cannot parse the first line */
1079 output_header_search, 951 die(STATE_CRITICAL, "HTTP CRITICAL HTTP/x.x %ld unknown - %s", code, msg);
1080 use_ssl ? "https" : "http", 952 }
1081 host_name ? host_name : server_address, 953 status_line_initialized = true;
1082 server_port,
1083 server_url);
1084 954
1085 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);
1086 959
1087 result = STATE_CRITICAL; 960 /* print status line, header, body if verbose */
1088 } 961 if (verbose >= 2) {
1089 } 962 printf("**** HEADER ****\n%s\n**** CONTENT ****\n%s\n", header_buf.buf, (no_body ? " [[ skipped ]]" : body_buf.buf));
963 }
1090 964
1091 if (strlen (string_expect)) { 965 /* make sure the status line matches the response we are looking for */
1092 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 }
1093 974
1094 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 }
1095 1013
1096 if(output_string_search[sizeof(output_string_search)-1]!='\0') { 1014 /* libcurl redirection internally, handle error states here */
1097 bcopy("...",&output_string_search[sizeof(output_string_search)-4],4); 1015 if (followmethod == FOLLOW_LIBCURL) {
1098 } 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 }
1099 1065
1100 char tmp[DEFAULT_BUFFER_SIZE]; 1066 char tmp[DEFAULT_BUFFER_SIZE];
1101 1067
1102 snprintf (tmp, 1068 snprintf(tmp, DEFAULT_BUFFER_SIZE, _("%sstring '%s' not found on '%s://%s:%d%s', "), msg, output_string_search,
1103 DEFAULT_BUFFER_SIZE, 1069 use_ssl ? "https" : "http", host_name ? host_name : server_address, server_port, server_url);
1104 _("%sstring '%s' not found on '%s://%s:%d%s', "),
1105 msg,
1106 output_string_search,
1107 use_ssl ? "https" : "http",
1108 host_name ? host_name : server_address,
1109 server_port,
1110 server_url);
1111 1070
1112 strcpy(msg, tmp); 1071 strcpy(msg, tmp);
1113 1072
1114 result = STATE_CRITICAL; 1073 result = STATE_CRITICAL;
1115 } 1074 }
1116 } 1075 }
1117 1076
1118 if (strlen (regexp)) { 1077 if (strlen(regexp)) {
1119 errcode = regexec (&preg, body_buf.buf, REGS, pmatch, 0); 1078 errcode = regexec(&preg, body_buf.buf, REGS, pmatch, 0);
1120 if ((errcode == 0 && !invert_regex) || (errcode == REG_NOMATCH && invert_regex)) { 1079 if ((errcode == 0 && !invert_regex) || (errcode == REG_NOMATCH && invert_regex)) {
1121 /* OK - No-op to avoid changing the logic around it */ 1080 /* OK - No-op to avoid changing the logic around it */
1122 result = max_state_alt(STATE_OK, result); 1081 result = max_state_alt(STATE_OK, result);
1123 } 1082 } else if ((errcode == REG_NOMATCH && !invert_regex) || (errcode == 0 && invert_regex)) {
1124 else if ((errcode == REG_NOMATCH && !invert_regex) || (errcode == 0 && invert_regex)) {
1125 if (!invert_regex) { 1083 if (!invert_regex) {
1126 char tmp[DEFAULT_BUFFER_SIZE]; 1084 char tmp[DEFAULT_BUFFER_SIZE];
1127 1085
1128 snprintf (tmp, DEFAULT_BUFFER_SIZE, _("%spattern not found, "), msg); 1086 snprintf(tmp, DEFAULT_BUFFER_SIZE, _("%spattern not found, "), msg);
1129 strcpy(msg, tmp); 1087 strcpy(msg, tmp);
1130 1088
1131 } else { 1089 } else {
1132 char tmp[DEFAULT_BUFFER_SIZE]; 1090 char tmp[DEFAULT_BUFFER_SIZE];
1133 1091
1134 snprintf (tmp, DEFAULT_BUFFER_SIZE, _("%spattern found, "), msg); 1092 snprintf(tmp, DEFAULT_BUFFER_SIZE, _("%spattern found, "), msg);
1135 strcpy(msg, tmp); 1093 strcpy(msg, tmp);
1136
1137 } 1094 }
1138 result = state_regex; 1095 result = state_regex;
1139 } else { 1096 } else {
1140 regerror (errcode, &preg, errbuf, MAX_INPUT_BUFFER); 1097 regerror(errcode, &preg, errbuf, MAX_INPUT_BUFFER);
1141 1098
1142 char tmp[DEFAULT_BUFFER_SIZE]; 1099 char tmp[DEFAULT_BUFFER_SIZE];
1143 1100
1144 snprintf (tmp, DEFAULT_BUFFER_SIZE, _("%sExecute Error: %s, "), msg, errbuf); 1101 snprintf(tmp, DEFAULT_BUFFER_SIZE, _("%sExecute Error: %s, "), msg, errbuf);
1145 strcpy(msg, tmp); 1102 strcpy(msg, tmp);
1146 result = STATE_UNKNOWN; 1103 result = STATE_UNKNOWN;
1147 } 1104 }
1148 } 1105 }
1149 1106
1150 /* make sure the page is of an appropriate size */ 1107 /* make sure the page is of an appropriate size */
1151 if ((max_page_len > 0) && (page_len > max_page_len)) { 1108 if ((max_page_len > 0) && (page_len > max_page_len)) {
1152 char tmp[DEFAULT_BUFFER_SIZE]; 1109 char tmp[DEFAULT_BUFFER_SIZE];
1153 1110
1154 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);
1155 1112
1156 strcpy(msg, tmp); 1113 strcpy(msg, tmp);
1157 1114
@@ -1160,1281 +1117,1230 @@ GOT_FIRST_CERT:
1160 } else if ((min_page_len > 0) && (page_len < min_page_len)) { 1117 } else if ((min_page_len > 0) && (page_len < min_page_len)) {
1161 char tmp[DEFAULT_BUFFER_SIZE]; 1118 char tmp[DEFAULT_BUFFER_SIZE];
1162 1119
1163 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);
1164 strcpy(msg, tmp); 1121 strcpy(msg, tmp);
1165 result = max_state_alt(STATE_WARNING, result); 1122 result = max_state_alt(STATE_WARNING, result);
1166 } 1123 }
1167 1124
1168 /* -w, -c: check warning and critical level */ 1125 /* -w, -c: check warning and critical level */
1169 result = max_state_alt(get_status(total_time, thlds), result); 1126 result = max_state_alt(get_status(total_time, thlds), result);
1170 1127
1171 /* Cut-off trailing characters */ 1128 /* Cut-off trailing characters */
1172 if (strlen(msg) >= 2) { 1129 if (strlen(msg) >= 2) {
1173 if(msg[strlen(msg)-2] == ',') 1130 if (msg[strlen(msg) - 2] == ',')
1174 msg[strlen(msg)-2] = '\0'; 1131 msg[strlen(msg) - 2] = '\0';
1175 else 1132 else
1176 msg[strlen(msg)-3] = '\0'; 1133 msg[strlen(msg) - 3] = '\0';
1177 } 1134 }
1178 1135
1179 /* 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); */
1180 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),
1181 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,
1182 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 : ""),
1183 strlen(msg) > 0 ? " - " : "", 1140 (show_body ? "\n" : ""));
1184 msg, page_len, total_time, 1141
1185 (display_html ? "</A>" : ""), 1142 return max_state_alt(result, result_ssl);
1186 perfstring,
1187 (show_body ? body_buf.buf : ""),
1188 (show_body ? "\n" : "") );
1189
1190 return max_state_alt(result, result_ssl);
1191} 1143}
1192 1144
1193int 1145int uri_strcmp(const UriTextRangeA range, const char *s) {
1194uri_strcmp (const UriTextRangeA range, const char* s) 1146 if (!range.first)
1195{ 1147 return -1;
1196 if (!range.first) return -1; 1148 if ((size_t)(range.afterLast - range.first) < strlen(s))
1197 if ( (size_t)(range.afterLast - range.first) < strlen (s) ) return -1; 1149 return -1;
1198 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)));
1199} 1151}
1200 1152
1201char* 1153char *uri_string(const UriTextRangeA range, char *buf, size_t buflen) {
1202uri_string (const UriTextRangeA range, char* buf, size_t buflen) 1154 if (!range.first)
1203{ 1155 return "(null)";
1204 if (!range.first) return "(null)"; 1156 strncpy(buf, range.first, max(buflen - 1, (size_t)(range.afterLast - range.first)));
1205 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';
1206 buf[max (buflen-1, (size_t)(range.afterLast - range.first))] = '\0'; 1158 buf[range.afterLast - range.first] = '\0';
1207 buf[range.afterLast - range.first] = '\0'; 1159 return buf;
1208 return buf;
1209} 1160}
1210 1161
1211void 1162void redir(curlhelp_write_curlbuf *header_buf) {
1212redir (curlhelp_write_curlbuf* header_buf) 1163 char *location = NULL;
1213{ 1164 curlhelp_statusline status_line;
1214 char *location = NULL; 1165 struct phr_header headers[255];
1215 curlhelp_statusline status_line; 1166 size_t nof_headers = 255;
1216 struct phr_header headers[255]; 1167 size_t msglen;
1217 size_t nof_headers = 255; 1168 char buf[DEFAULT_BUFFER_SIZE];
1218 size_t msglen; 1169 char ipstr[INET_ADDR_MAX_SIZE];
1219 char buf[DEFAULT_BUFFER_SIZE]; 1170 int new_port;
1220 char ipstr[INET_ADDR_MAX_SIZE]; 1171 char *new_host;
1221 int new_port; 1172 char *new_url;
1222 char *new_host; 1173
1223 char *new_url; 1174 int res = phr_parse_response(header_buf->buf, header_buf->buflen, &status_line.http_major, &status_line.http_minor,
1224 1175 &status_line.http_code, &status_line.msg, &msglen, headers, &nof_headers, 0);
1225 int res = phr_parse_response (header_buf->buf, header_buf->buflen,
1226 &status_line.http_major, &status_line.http_minor, &status_line.http_code, &status_line.msg, &msglen,
1227 headers, &nof_headers, 0);
1228 1176
1229 if (res == -1) { 1177 if (res == -1) {
1230 die (STATE_UNKNOWN, _("HTTP UNKNOWN - Failed to parse Response\n")); 1178 die(STATE_UNKNOWN, _("HTTP UNKNOWN - Failed to parse Response\n"));
1231 } 1179 }
1232 1180
1233 location = get_header_value (headers, nof_headers, "location"); 1181 location = get_header_value(headers, nof_headers, "location");
1234 1182
1235 if (verbose >= 2) 1183 if (verbose >= 2)
1236 printf(_("* Seen redirect location %s\n"), location); 1184 printf(_("* Seen redirect location %s\n"), location);
1237 1185
1238 if (++redir_depth > max_depth) 1186 if (++redir_depth > max_depth)
1239 die (STATE_WARNING, 1187 die(STATE_WARNING, _("HTTP WARNING - maximum redirection depth %d exceeded - %s%s\n"), max_depth, location,
1240 _("HTTP WARNING - maximum redirection depth %d exceeded - %s%s\n"), 1188 (display_html ? "</A>" : ""));
1241 max_depth, location, (display_html ? "</A>" : "")); 1189
1242 1190 UriParserStateA state;
1243 UriParserStateA state; 1191 UriUriA uri;
1244 UriUriA uri; 1192 state.uri = &uri;
1245 state.uri = &uri; 1193 if (uriParseUriA(&state, location) != URI_SUCCESS) {
1246 if (uriParseUriA (&state, location) != URI_SUCCESS) { 1194 if (state.errorCode == URI_ERROR_SYNTAX) {
1247 if (state.errorCode == URI_ERROR_SYNTAX) { 1195 die(STATE_UNKNOWN, _("HTTP UNKNOWN - Could not parse redirect location '%s'%s\n"), location, (display_html ? "</A>" : ""));
1248 die (STATE_UNKNOWN, 1196 } else if (state.errorCode == URI_ERROR_MALLOC) {
1249 _("HTTP UNKNOWN - Could not parse redirect location '%s'%s\n"), 1197 die(STATE_UNKNOWN, _("HTTP UNKNOWN - Could not allocate URL\n"));
1250 location, (display_html ? "</A>" : "")); 1198 }
1251 } else if (state.errorCode == URI_ERROR_MALLOC) { 1199 }
1252 die (STATE_UNKNOWN, _("HTTP UNKNOWN - Could not allocate URL\n")); 1200
1253 } 1201 if (verbose >= 2) {
1254 } 1202 printf(_("** scheme: %s\n"), uri_string(uri.scheme, buf, DEFAULT_BUFFER_SIZE));
1255 1203 printf(_("** host: %s\n"), uri_string(uri.hostText, buf, DEFAULT_BUFFER_SIZE));
1256 if (verbose >= 2) { 1204 printf(_("** port: %s\n"), uri_string(uri.portText, buf, DEFAULT_BUFFER_SIZE));
1257 printf (_("** scheme: %s\n"), 1205 if (uri.hostData.ip4) {
1258 uri_string (uri.scheme, buf, DEFAULT_BUFFER_SIZE)); 1206 inet_ntop(AF_INET, uri.hostData.ip4->data, ipstr, sizeof(ipstr));
1259 printf (_("** host: %s\n"), 1207 printf(_("** IPv4: %s\n"), ipstr);
1260 uri_string (uri.hostText, buf, DEFAULT_BUFFER_SIZE)); 1208 }
1261 printf (_("** port: %s\n"), 1209 if (uri.hostData.ip6) {
1262 uri_string (uri.portText, buf, DEFAULT_BUFFER_SIZE)); 1210 inet_ntop(AF_INET, uri.hostData.ip6->data, ipstr, sizeof(ipstr));
1263 if (uri.hostData.ip4) { 1211 printf(_("** IPv6: %s\n"), ipstr);
1264 inet_ntop (AF_INET, uri.hostData.ip4->data, ipstr, sizeof (ipstr)); 1212 }
1265 printf (_("** IPv4: %s\n"), ipstr); 1213 if (uri.pathHead) {
1266 } 1214 printf(_("** path: "));
1267 if (uri.hostData.ip6) { 1215 const UriPathSegmentA *p = uri.pathHead;
1268 inet_ntop (AF_INET, uri.hostData.ip6->data, ipstr, sizeof (ipstr)); 1216 for (; p; p = p->next) {
1269 printf (_("** IPv6: %s\n"), ipstr); 1217 printf("/%s", uri_string(p->text, buf, DEFAULT_BUFFER_SIZE));
1270 } 1218 }
1271 if (uri.pathHead) { 1219 puts("");
1272 printf (_("** path: ")); 1220 }
1273 const UriPathSegmentA* p = uri.pathHead; 1221 if (uri.query.first) {
1274 for (; p; p = p->next) { 1222 printf(_("** query: %s\n"), uri_string(uri.query, buf, DEFAULT_BUFFER_SIZE));
1275 printf ("/%s", uri_string (p->text, buf, DEFAULT_BUFFER_SIZE)); 1223 }
1276 } 1224 if (uri.fragment.first) {
1277 puts (""); 1225 printf(_("** fragment: %s\n"), uri_string(uri.fragment, buf, DEFAULT_BUFFER_SIZE));
1278 } 1226 }
1279 if (uri.query.first) { 1227 }
1280 printf (_("** query: %s\n"), 1228
1281 uri_string (uri.query, buf, DEFAULT_BUFFER_SIZE)); 1229 if (uri.scheme.first) {
1282 } 1230 if (!uri_strcmp(uri.scheme, "https"))
1283 if (uri.fragment.first) { 1231 use_ssl = true;
1284 printf (_("** fragment: %s\n"), 1232 else
1285 uri_string (uri.fragment, buf, DEFAULT_BUFFER_SIZE)); 1233 use_ssl = false;
1286 } 1234 }
1287 } 1235
1288 1236 /* we do a sloppy test here only, because uriparser would have failed
1289 if (uri.scheme.first) { 1237 * above, if the port would be invalid, we just check for MAX_PORT
1290 if (!uri_strcmp (uri.scheme, "https")) 1238 */
1291 use_ssl = true; 1239 if (uri.portText.first) {
1292 else 1240 new_port = atoi(uri_string(uri.portText, buf, DEFAULT_BUFFER_SIZE));
1293 use_ssl = false; 1241 } else {
1294 } 1242 new_port = HTTP_PORT;
1295 1243 if (use_ssl)
1296 /* we do a sloppy test here only, because uriparser would have failed 1244 new_port = HTTPS_PORT;
1297 * above, if the port would be invalid, we just check for MAX_PORT 1245 }
1298 */ 1246 if (new_port > MAX_PORT)
1299 if (uri.portText.first) { 1247 die(STATE_UNKNOWN, _("HTTP UNKNOWN - Redirection to port above %d - %s%s\n"), MAX_PORT, location, display_html ? "</A>" : "");
1300 new_port = atoi (uri_string (uri.portText, buf, DEFAULT_BUFFER_SIZE)); 1248
1301 } else { 1249 /* by RFC 7231 relative URLs in Location should be taken relative to
1302 new_port = HTTP_PORT; 1250 * the original URL, so we try to form a new absolute URL here
1303 if (use_ssl) 1251 */
1304 new_port = HTTPS_PORT; 1252 if (!uri.scheme.first && !uri.hostText.first) {
1305 } 1253 new_host = strdup(host_name ? host_name : server_address);
1306 if (new_port > MAX_PORT) 1254 new_port = server_port;
1307 die (STATE_UNKNOWN, 1255 if (use_ssl)
1308 _("HTTP UNKNOWN - Redirection to port above %d - %s%s\n"), 1256 uri_string(uri.scheme, "https", DEFAULT_BUFFER_SIZE);
1309 MAX_PORT, location, display_html ? "</A>" : ""); 1257 } else {
1310 1258 new_host = strdup(uri_string(uri.hostText, buf, DEFAULT_BUFFER_SIZE));
1311 /* by RFC 7231 relative URLs in Location should be taken relative to 1259 }
1312 * the original URL, so we try to form a new absolute URL here 1260
1313 */ 1261 /* compose new path */
1314 if (!uri.scheme.first && !uri.hostText.first) { 1262 /* TODO: handle fragments and query part of URL */
1315 new_host = strdup (host_name ? host_name : server_address); 1263 new_url = (char *)calloc(1, DEFAULT_BUFFER_SIZE);
1316 new_port = server_port; 1264 if (uri.pathHead) {
1317 if(use_ssl) 1265 const UriPathSegmentA *p = uri.pathHead;
1318 uri_string (uri.scheme, "https", DEFAULT_BUFFER_SIZE); 1266 for (; p; p = p->next) {
1319 } else { 1267 strncat(new_url, "/", DEFAULT_BUFFER_SIZE);
1320 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);
1321 } 1269 }
1322 1270 }
1323 /* compose new path */ 1271
1324 /* TODO: handle fragments and query part of URL */ 1272 if (server_port == new_port && !strncmp(server_address, new_host, MAX_IPV4_HOSTLENGTH) &&
1325 new_url = (char *)calloc( 1, DEFAULT_BUFFER_SIZE); 1273 (host_name && !strncmp(host_name, new_host, MAX_IPV4_HOSTLENGTH)) && !strcmp(server_url, new_url))
1326 if (uri.pathHead) { 1274 die(STATE_CRITICAL, _("HTTP CRITICAL - redirection creates an infinite loop - %s://%s:%d%s%s\n"), use_ssl ? "https" : "http",
1327 const UriPathSegmentA* p = uri.pathHead; 1275 new_host, new_port, new_url, (display_html ? "</A>" : ""));
1328 for (; p; p = p->next) { 1276
1329 strncat (new_url, "/", DEFAULT_BUFFER_SIZE); 1277 /* set new values for redirected request */
1330 strncat (new_url, uri_string (p->text, buf, DEFAULT_BUFFER_SIZE), DEFAULT_BUFFER_SIZE-1); 1278
1331 } 1279 if (!(followsticky & STICKY_HOST)) {
1332 } 1280 free(server_address);
1333 1281 server_address = strndup(new_host, MAX_IPV4_HOSTLENGTH);
1334 if (server_port==new_port && 1282 }
1335 !strncmp(server_address, new_host, MAX_IPV4_HOSTLENGTH) && 1283 if (!(followsticky & STICKY_PORT)) {
1336 (host_name && !strncmp(host_name, new_host, MAX_IPV4_HOSTLENGTH)) && 1284 server_port = (unsigned short)new_port;
1337 !strcmp(server_url, new_url)) 1285 }
1338 die (STATE_CRITICAL, 1286
1339 _("HTTP CRITICAL - redirection creates an infinite loop - %s://%s:%d%s%s\n"), 1287 free(host_name);
1340 use_ssl ? "https" : "http", new_host, new_port, new_url, (display_html ? "</A>" : "")); 1288 host_name = strndup(new_host, MAX_IPV4_HOSTLENGTH);
1341 1289
1342 /* set new values for redirected request */ 1290 /* reset virtual port */
1343 1291 virtual_port = server_port;
1344 if (!(followsticky & STICKY_HOST)) { 1292
1345 free (server_address); 1293 free(new_host);
1346 server_address = strndup (new_host, MAX_IPV4_HOSTLENGTH); 1294 free(server_url);
1347 } 1295 server_url = new_url;
1348 if (!(followsticky & STICKY_PORT)) { 1296
1349 server_port = (unsigned short)new_port; 1297 uriFreeUriMembersA(&uri);
1350 } 1298
1351 1299 if (verbose)
1352 free (host_name); 1300 printf(_("Redirection to %s://%s:%d%s\n"), use_ssl ? "https" : "http", host_name ? host_name : server_address, server_port,
1353 host_name = strndup (new_host, MAX_IPV4_HOSTLENGTH); 1301 server_url);
1354 1302
1355 /* reset virtual port */ 1303 /* TODO: the hash component MUST be taken from the original URL and
1356 virtual_port = server_port; 1304 * attached to the URL in Location
1357 1305 */
1358 free(new_host); 1306
1359 free (server_url); 1307 cleanup();
1360 server_url = new_url; 1308 check_http();
1361
1362 uriFreeUriMembersA (&uri);
1363
1364 if (verbose)
1365 printf (_("Redirection to %s://%s:%d%s\n"), use_ssl ? "https" : "http",
1366 host_name ? host_name : server_address, server_port, server_url);
1367
1368 /* TODO: the hash component MUST be taken from the original URL and
1369 * attached to the URL in Location
1370 */
1371
1372 cleanup ();
1373 check_http ();
1374} 1309}
1375 1310
1376/* check whether a file exists */ 1311/* check whether a file exists */
1377void 1312void test_file(char *path) {
1378test_file (char *path) 1313 if (access(path, R_OK) == 0)
1379{ 1314 return;
1380 if (access(path, R_OK) == 0) 1315 usage2(_("file does not exist or is not readable"), path);
1381 return;
1382 usage2 (_("file does not exist or is not readable"), path);
1383} 1316}
1384 1317
1385bool 1318bool process_arguments(int argc, char **argv) {
1386process_arguments (int argc, char **argv) 1319 char *p;
1387{ 1320 int c = 1;
1388 char *p; 1321 char *temp;
1389 int c = 1; 1322
1390 char *temp; 1323 enum {
1391 1324 INVERT_REGEX = CHAR_MAX + 1,
1392 enum { 1325 SNI_OPTION,
1393 INVERT_REGEX = CHAR_MAX + 1, 1326 MAX_REDIRS_OPTION,
1394 SNI_OPTION, 1327 CONTINUE_AFTER_CHECK_CERT,
1395 MAX_REDIRS_OPTION, 1328 CA_CERT_OPTION,
1396 CONTINUE_AFTER_CHECK_CERT, 1329 HTTP_VERSION_OPTION,
1397 CA_CERT_OPTION, 1330 AUTOMATIC_DECOMPRESSION,
1398 HTTP_VERSION_OPTION, 1331 COOKIE_JAR,
1399 AUTOMATIC_DECOMPRESSION, 1332 HAPROXY_PROTOCOL,
1400 COOKIE_JAR, 1333 STATE_REGEX
1401 HAPROXY_PROTOCOL, 1334 };
1402 STATE_REGEX 1335
1403 }; 1336 int option = 0;
1404 1337 int got_plus = 0;
1405 int option = 0; 1338 static struct option longopts[] = {STD_LONG_OPTS,
1406 int got_plus = 0; 1339 {"link", no_argument, 0, 'L'},
1407 static struct option longopts[] = { 1340 {"nohtml", no_argument, 0, 'n'},
1408 STD_LONG_OPTS, 1341 {"ssl", optional_argument, 0, 'S'},
1409 {"link", no_argument, 0, 'L'}, 1342 {"sni", no_argument, 0, SNI_OPTION},
1410 {"nohtml", no_argument, 0, 'n'}, 1343 {"post", required_argument, 0, 'P'},
1411 {"ssl", optional_argument, 0, 'S'}, 1344 {"method", required_argument, 0, 'j'},
1412 {"sni", no_argument, 0, SNI_OPTION}, 1345 {"IP-address", required_argument, 0, 'I'},
1413 {"post", required_argument, 0, 'P'}, 1346 {"url", required_argument, 0, 'u'},
1414 {"method", required_argument, 0, 'j'}, 1347 {"port", required_argument, 0, 'p'},
1415 {"IP-address", required_argument, 0, 'I'}, 1348 {"authorization", required_argument, 0, 'a'},
1416 {"url", required_argument, 0, 'u'}, 1349 {"proxy-authorization", required_argument, 0, 'b'},
1417 {"port", required_argument, 0, 'p'}, 1350 {"header-string", required_argument, 0, 'd'},
1418 {"authorization", required_argument, 0, 'a'}, 1351 {"string", required_argument, 0, 's'},
1419 {"proxy-authorization", required_argument, 0, 'b'}, 1352 {"expect", required_argument, 0, 'e'},
1420 {"header-string", required_argument, 0, 'd'}, 1353 {"regex", required_argument, 0, 'r'},
1421 {"string", required_argument, 0, 's'}, 1354 {"ereg", required_argument, 0, 'r'},
1422 {"expect", required_argument, 0, 'e'}, 1355 {"eregi", required_argument, 0, 'R'},
1423 {"regex", required_argument, 0, 'r'}, 1356 {"linespan", no_argument, 0, 'l'},
1424 {"ereg", required_argument, 0, 'r'}, 1357 {"onredirect", required_argument, 0, 'f'},
1425 {"eregi", required_argument, 0, 'R'}, 1358 {"certificate", required_argument, 0, 'C'},
1426 {"linespan", no_argument, 0, 'l'}, 1359 {"client-cert", required_argument, 0, 'J'},
1427 {"onredirect", required_argument, 0, 'f'}, 1360 {"private-key", required_argument, 0, 'K'},
1428 {"certificate", required_argument, 0, 'C'}, 1361 {"ca-cert", required_argument, 0, CA_CERT_OPTION},
1429 {"client-cert", required_argument, 0, 'J'}, 1362 {"verify-cert", no_argument, 0, 'D'},
1430 {"private-key", required_argument, 0, 'K'}, 1363 {"continue-after-certificate", no_argument, 0, CONTINUE_AFTER_CHECK_CERT},
1431 {"ca-cert", required_argument, 0, CA_CERT_OPTION}, 1364 {"useragent", required_argument, 0, 'A'},
1432 {"verify-cert", no_argument, 0, 'D'}, 1365 {"header", required_argument, 0, 'k'},
1433 {"continue-after-certificate", no_argument, 0, CONTINUE_AFTER_CHECK_CERT}, 1366 {"no-body", no_argument, 0, 'N'},
1434 {"useragent", required_argument, 0, 'A'}, 1367 {"max-age", required_argument, 0, 'M'},
1435 {"header", required_argument, 0, 'k'}, 1368 {"content-type", required_argument, 0, 'T'},
1436 {"no-body", no_argument, 0, 'N'}, 1369 {"pagesize", required_argument, 0, 'm'},
1437 {"max-age", required_argument, 0, 'M'}, 1370 {"invert-regex", no_argument, NULL, INVERT_REGEX},
1438 {"content-type", required_argument, 0, 'T'}, 1371 {"state-regex", required_argument, 0, STATE_REGEX},
1439 {"pagesize", required_argument, 0, 'm'}, 1372 {"use-ipv4", no_argument, 0, '4'},
1440 {"invert-regex", no_argument, NULL, INVERT_REGEX}, 1373 {"use-ipv6", no_argument, 0, '6'},
1441 {"state-regex", required_argument, 0, STATE_REGEX}, 1374 {"extended-perfdata", no_argument, 0, 'E'},
1442 {"use-ipv4", no_argument, 0, '4'}, 1375 {"show-body", no_argument, 0, 'B'},
1443 {"use-ipv6", no_argument, 0, '6'}, 1376 {"max-redirs", required_argument, 0, MAX_REDIRS_OPTION},
1444 {"extended-perfdata", no_argument, 0, 'E'}, 1377 {"http-version", required_argument, 0, HTTP_VERSION_OPTION},
1445 {"show-body", no_argument, 0, 'B'}, 1378 {"enable-automatic-decompression", no_argument, 0, AUTOMATIC_DECOMPRESSION},
1446 {"max-redirs", required_argument, 0, MAX_REDIRS_OPTION}, 1379 {"cookie-jar", required_argument, 0, COOKIE_JAR},
1447 {"http-version", required_argument, 0, HTTP_VERSION_OPTION}, 1380 {"haproxy-protocol", no_argument, 0, HAPROXY_PROTOCOL},
1448 {"enable-automatic-decompression", no_argument, 0, AUTOMATIC_DECOMPRESSION}, 1381 {0, 0, 0, 0}};
1449 {"cookie-jar", required_argument, 0, COOKIE_JAR}, 1382
1450 {"haproxy-protocol", no_argument, 0, HAPROXY_PROTOCOL}, 1383 if (argc < 2)
1451 {0, 0, 0, 0} 1384 return false;
1452 }; 1385
1453 1386 /* support check_http compatible arguments */
1454 if (argc < 2) 1387 for (c = 1; c < argc; c++) {
1455 return false; 1388 if (strcmp("-to", argv[c]) == 0)
1456 1389 strcpy(argv[c], "-t");
1457 /* support check_http compatible arguments */ 1390 if (strcmp("-hn", argv[c]) == 0)
1458 for (c = 1; c < argc; c++) { 1391 strcpy(argv[c], "-H");
1459 if (strcmp ("-to", argv[c]) == 0) 1392 if (strcmp("-wt", argv[c]) == 0)
1460 strcpy (argv[c], "-t"); 1393 strcpy(argv[c], "-w");
1461 if (strcmp ("-hn", argv[c]) == 0) 1394 if (strcmp("-ct", argv[c]) == 0)
1462 strcpy (argv[c], "-H"); 1395 strcpy(argv[c], "-c");
1463 if (strcmp ("-wt", argv[c]) == 0) 1396 if (strcmp("-nohtml", argv[c]) == 0)
1464 strcpy (argv[c], "-w"); 1397 strcpy(argv[c], "-n");
1465 if (strcmp ("-ct", argv[c]) == 0) 1398 }
1466 strcpy (argv[c], "-c"); 1399
1467 if (strcmp ("-nohtml", argv[c]) == 0) 1400 server_url = strdup(DEFAULT_SERVER_URL);
1468 strcpy (argv[c], "-n"); 1401
1469 } 1402 while (1) {
1470 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);
1471 server_url = strdup(DEFAULT_SERVER_URL); 1404 if (c == -1 || c == EOF || c == 1)
1472 1405 break;
1473 while (1) { 1406
1474 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) {
1475 if (c == -1 || c == EOF || c == 1) 1408 case 'h':
1476 break; 1409 print_help();
1477 1410 exit(STATE_UNKNOWN);
1478 switch (c) { 1411 break;
1479 case 'h': 1412 case 'V':
1480 print_help(); 1413 print_revision(progname, NP_VERSION);
1481 exit(STATE_UNKNOWN); 1414 print_curl_version();
1482 break; 1415 exit(STATE_UNKNOWN);
1483 case 'V': 1416 break;
1484 print_revision(progname, NP_VERSION); 1417 case 'v':
1485 print_curl_version(); 1418 verbose++;
1486 exit(STATE_UNKNOWN); 1419 break;
1487 break; 1420 case 't': /* timeout period */
1488 case 'v': 1421 if (!is_intnonneg(optarg))
1489 verbose++; 1422 usage2(_("Timeout interval must be a positive integer"), optarg);
1490 break; 1423 else
1491 case 't': /* timeout period */ 1424 socket_timeout = (int)strtol(optarg, NULL, 10);
1492 if (!is_intnonneg (optarg)) 1425 break;
1493 usage2 (_("Timeout interval must be a positive integer"), optarg); 1426 case 'c': /* critical time threshold */
1494 else 1427 critical_thresholds = optarg;
1495 socket_timeout = (int)strtol (optarg, NULL, 10); 1428 break;
1496 break; 1429 case 'w': /* warning time threshold */
1497 case 'c': /* critical time threshold */ 1430 warning_thresholds = optarg;
1498 critical_thresholds = optarg; 1431 break;
1499 break; 1432 case 'H': /* virtual host */
1500 case 'w': /* warning time threshold */ 1433 host_name = strdup(optarg);
1501 warning_thresholds = optarg; 1434 if (host_name[0] == '[') {
1502 break; 1435 if ((p = strstr(host_name, "]:")) != NULL) { /* [IPv6]:port */
1503 case 'H': /* virtual host */ 1436 virtual_port = atoi(p + 2);
1504 host_name = strdup (optarg); 1437 /* cut off the port */
1505 if (host_name[0] == '[') { 1438 host_name_length = strlen(host_name) - strlen(p) - 1;
1506 if ((p = strstr (host_name, "]:")) != NULL) { /* [IPv6]:port */ 1439 free(host_name);
1507 virtual_port = atoi (p + 2); 1440 host_name = strndup(optarg, host_name_length);
1508 /* cut off the port */ 1441 }
1509 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 */
1510 free (host_name); 1443 virtual_port = atoi(p);
1511 host_name = strndup (optarg, host_name_length); 1444 /* cut off the port */
1512 } 1445 host_name_length = strlen(host_name) - strlen(p) - 1;
1513 } else if ((p = strchr (host_name, ':')) != NULL 1446 free(host_name);
1514 && strchr (++p, ':') == NULL) { /* IPv4:port or host:port */ 1447 host_name = strndup(optarg, host_name_length);
1515 virtual_port = atoi (p); 1448 }
1516 /* cut off the port */ 1449 break;
1517 host_name_length = strlen (host_name) - strlen (p) - 1; 1450 case 'I': /* internet address */
1518 free (host_name); 1451 server_address = strdup(optarg);
1519 host_name = strndup (optarg, host_name_length); 1452 break;
1520 } 1453 case 'u': /* URL path */
1521 break; 1454 server_url = strdup(optarg);
1522 case 'I': /* internet address */ 1455 break;
1523 server_address = strdup (optarg); 1456 case 'p': /* Server port */
1524 break; 1457 if (!is_intnonneg(optarg))
1525 case 'u': /* URL path */ 1458 usage2(_("Invalid port number, expecting a non-negative number"), optarg);
1526 server_url = strdup (optarg); 1459 else {
1527 break; 1460 if (strtol(optarg, NULL, 10) > MAX_PORT)
1528 case 'p': /* Server port */ 1461 usage2(_("Invalid port number, supplied port number is too big"), optarg);
1529 if (!is_intnonneg (optarg)) 1462 server_port = (unsigned short)strtol(optarg, NULL, 10);
1530 usage2 (_("Invalid port number, expecting a non-negative number"), optarg); 1463 specify_port = true;
1531 else { 1464 }
1532 if( strtol(optarg, NULL, 10) > MAX_PORT) 1465 break;
1533 usage2 (_("Invalid port number, supplied port number is too big"), optarg); 1466 case 'a': /* authorization info */
1534 server_port = (unsigned short)strtol(optarg, NULL, 10); 1467 strncpy(user_auth, optarg, MAX_INPUT_BUFFER - 1);
1535 specify_port = true; 1468 user_auth[MAX_INPUT_BUFFER - 1] = 0;
1536 } 1469 break;
1537 break; 1470 case 'b': /* proxy-authorization info */
1538 case 'a': /* authorization info */ 1471 strncpy(proxy_auth, optarg, MAX_INPUT_BUFFER - 1);
1539 strncpy (user_auth, optarg, MAX_INPUT_BUFFER - 1); 1472 proxy_auth[MAX_INPUT_BUFFER - 1] = 0;
1540 user_auth[MAX_INPUT_BUFFER - 1] = 0; 1473 break;
1541 break; 1474 case 'P': /* HTTP POST data in URL encoded format; ignored if settings already */
1542 case 'b': /* proxy-authorization info */ 1475 if (!http_post_data)
1543 strncpy (proxy_auth, optarg, MAX_INPUT_BUFFER - 1); 1476 http_post_data = strdup(optarg);
1544 proxy_auth[MAX_INPUT_BUFFER - 1] = 0; 1477 if (!http_method)
1545 break; 1478 http_method = strdup("POST");
1546 case 'P': /* HTTP POST data in URL encoded format; ignored if settings already */ 1479 break;
1547 if (! http_post_data) 1480 case 'j': /* Set HTTP method */
1548 http_post_data = strdup (optarg); 1481 if (http_method)
1549 if (! http_method) 1482 free(http_method);
1550 http_method = strdup("POST"); 1483 http_method = strdup(optarg);
1551 break; 1484 break;
1552 case 'j': /* Set HTTP method */ 1485 case 'A': /* useragent */
1553 if (http_method) 1486 strncpy(user_agent, optarg, DEFAULT_BUFFER_SIZE);
1554 free(http_method); 1487 user_agent[DEFAULT_BUFFER_SIZE - 1] = '\0';
1555 http_method = strdup (optarg); 1488 break;
1556 break; 1489 case 'k': /* Additional headers */
1557 case 'A': /* useragent */ 1490 if (http_opt_headers_count == 0)
1558 strncpy (user_agent, optarg, DEFAULT_BUFFER_SIZE); 1491 http_opt_headers = malloc(sizeof(char *) * (++http_opt_headers_count));
1559 user_agent[DEFAULT_BUFFER_SIZE-1] = '\0'; 1492 else
1560 break; 1493 http_opt_headers = realloc(http_opt_headers, sizeof(char *) * (++http_opt_headers_count));
1561 case 'k': /* Additional headers */ 1494 http_opt_headers[http_opt_headers_count - 1] = optarg;
1562 if (http_opt_headers_count == 0) 1495 break;
1563 http_opt_headers = malloc (sizeof (char *) * (++http_opt_headers_count)); 1496 case 'L': /* show html link */
1564 else 1497 display_html = true;
1565 http_opt_headers = realloc (http_opt_headers, sizeof (char *) * (++http_opt_headers_count)); 1498 break;
1566 http_opt_headers[http_opt_headers_count - 1] = optarg; 1499 case 'n': /* do not show html link */
1567 break; 1500 display_html = false;
1568 case 'L': /* show html link */ 1501 break;
1569 display_html = true; 1502 case 'C': /* Check SSL cert validity */
1570 break;
1571 case 'n': /* do not show html link */
1572 display_html = false;
1573 break;
1574 case 'C': /* Check SSL cert validity */
1575#ifdef LIBCURL_FEATURE_SSL 1503#ifdef LIBCURL_FEATURE_SSL
1576 if ((temp=strchr(optarg,','))!=NULL) { 1504 if ((temp = strchr(optarg, ',')) != NULL) {
1577 *temp='\0'; 1505 *temp = '\0';
1578 if (!is_intnonneg (optarg)) 1506 if (!is_intnonneg(optarg))
1579 usage2 (_("Invalid certificate expiration period"), optarg); 1507 usage2(_("Invalid certificate expiration period"), optarg);
1580 days_till_exp_warn = atoi(optarg); 1508 days_till_exp_warn = atoi(optarg);
1581 *temp=','; 1509 *temp = ',';
1582 temp++; 1510 temp++;
1583 if (!is_intnonneg (temp)) 1511 if (!is_intnonneg(temp))
1584 usage2 (_("Invalid certificate expiration period"), temp); 1512 usage2(_("Invalid certificate expiration period"), temp);
1585 days_till_exp_crit = atoi (temp); 1513 days_till_exp_crit = atoi(temp);
1586 } 1514 } else {
1587 else { 1515 days_till_exp_crit = 0;
1588 days_till_exp_crit=0; 1516 if (!is_intnonneg(optarg))
1589 if (!is_intnonneg (optarg)) 1517 usage2(_("Invalid certificate expiration period"), optarg);
1590 usage2 (_("Invalid certificate expiration period"), optarg); 1518 days_till_exp_warn = atoi(optarg);
1591 days_till_exp_warn = atoi (optarg); 1519 }
1592 } 1520 check_cert = true;
1593 check_cert = true; 1521 goto enable_ssl;
1594 goto enable_ssl;
1595#endif 1522#endif
1596 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 */
1597#ifdef HAVE_SSL 1524#ifdef HAVE_SSL
1598 continue_after_check_cert = true; 1525 continue_after_check_cert = true;
1599 break; 1526 break;
1600#endif 1527#endif
1601 case 'J': /* use client certificate */ 1528 case 'J': /* use client certificate */
1602#ifdef LIBCURL_FEATURE_SSL 1529#ifdef LIBCURL_FEATURE_SSL
1603 test_file(optarg); 1530 test_file(optarg);
1604 client_cert = optarg; 1531 client_cert = optarg;
1605 goto enable_ssl; 1532 goto enable_ssl;
1606#endif 1533#endif
1607 case 'K': /* use client private key */ 1534 case 'K': /* use client private key */
1608#ifdef LIBCURL_FEATURE_SSL 1535#ifdef LIBCURL_FEATURE_SSL
1609 test_file(optarg); 1536 test_file(optarg);
1610 client_privkey = optarg; 1537 client_privkey = optarg;
1611 goto enable_ssl; 1538 goto enable_ssl;
1612#endif 1539#endif
1613#ifdef LIBCURL_FEATURE_SSL 1540#ifdef LIBCURL_FEATURE_SSL
1614 case CA_CERT_OPTION: /* use CA chain file */ 1541 case CA_CERT_OPTION: /* use CA chain file */
1615 test_file(optarg); 1542 test_file(optarg);
1616 ca_cert = optarg; 1543 ca_cert = optarg;
1617 goto enable_ssl; 1544 goto enable_ssl;
1618#endif 1545#endif
1619#ifdef LIBCURL_FEATURE_SSL 1546#ifdef LIBCURL_FEATURE_SSL
1620 case 'D': /* verify peer certificate & host */ 1547 case 'D': /* verify peer certificate & host */
1621 verify_peer_and_host = true; 1548 verify_peer_and_host = true;
1622 break; 1549 break;
1623#endif 1550#endif
1624 case 'S': /* use SSL */ 1551 case 'S': /* use SSL */
1625#ifdef LIBCURL_FEATURE_SSL 1552#ifdef LIBCURL_FEATURE_SSL
1626 enable_ssl: 1553 enable_ssl:
1627 use_ssl = true; 1554 use_ssl = true;
1628 /* ssl_version initialized to CURL_SSLVERSION_DEFAULT as a default. 1555 /* ssl_version initialized to CURL_SSLVERSION_DEFAULT as a default.
1629 * 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
1630 * parameters, like -S and -C combinations */ 1557 * parameters, like -S and -C combinations */
1631 ssl_version = CURL_SSLVERSION_DEFAULT; 1558 ssl_version = CURL_SSLVERSION_DEFAULT;
1632 if (c=='S' && optarg != NULL) { 1559 if (c == 'S' && optarg != NULL) {
1633 char *plus_ptr = strchr(optarg, '+'); 1560 char *plus_ptr = strchr(optarg, '+');
1634 if (plus_ptr) { 1561 if (plus_ptr) {
1635 got_plus = 1; 1562 got_plus = 1;
1636 *plus_ptr = '\0'; 1563 *plus_ptr = '\0';
1637 } 1564 }
1638 1565
1639 if (optarg[0] == '2') 1566 if (optarg[0] == '2')
1640 ssl_version = CURL_SSLVERSION_SSLv2; 1567 ssl_version = CURL_SSLVERSION_SSLv2;
1641 else if (optarg[0] == '3') 1568 else if (optarg[0] == '3')
1642 ssl_version = CURL_SSLVERSION_SSLv3; 1569 ssl_version = CURL_SSLVERSION_SSLv3;
1643 else if (!strcmp (optarg, "1") || !strcmp (optarg, "1.0")) 1570 else if (!strcmp(optarg, "1") || !strcmp(optarg, "1.0"))
1644#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) 1571# if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0)
1645 ssl_version = CURL_SSLVERSION_TLSv1_0; 1572 ssl_version = CURL_SSLVERSION_TLSv1_0;
1646#else 1573# else
1647 ssl_version = CURL_SSLVERSION_DEFAULT; 1574 ssl_version = CURL_SSLVERSION_DEFAULT;
1648#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) */ 1575# endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) */
1649 else if (!strcmp (optarg, "1.1")) 1576 else if (!strcmp(optarg, "1.1"))
1650#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) 1577# if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0)
1651 ssl_version = CURL_SSLVERSION_TLSv1_1; 1578 ssl_version = CURL_SSLVERSION_TLSv1_1;
1652#else 1579# else
1653 ssl_version = CURL_SSLVERSION_DEFAULT; 1580 ssl_version = CURL_SSLVERSION_DEFAULT;
1654#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) */ 1581# endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) */
1655 else if (!strcmp (optarg, "1.2")) 1582 else if (!strcmp(optarg, "1.2"))
1656#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) 1583# if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0)
1657 ssl_version = CURL_SSLVERSION_TLSv1_2; 1584 ssl_version = CURL_SSLVERSION_TLSv1_2;
1658#else 1585# else
1659 ssl_version = CURL_SSLVERSION_DEFAULT; 1586 ssl_version = CURL_SSLVERSION_DEFAULT;
1660#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) */ 1587# endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) */
1661 else if (!strcmp (optarg, "1.3")) 1588 else if (!strcmp(optarg, "1.3"))
1662#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 52, 0) 1589# if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 52, 0)
1663 ssl_version = CURL_SSLVERSION_TLSv1_3; 1590 ssl_version = CURL_SSLVERSION_TLSv1_3;
1664#else 1591# else
1665 ssl_version = CURL_SSLVERSION_DEFAULT; 1592 ssl_version = CURL_SSLVERSION_DEFAULT;
1666#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 52, 0) */ 1593# endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 52, 0) */
1667 else 1594 else
1668 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)"));
1669 } 1596 }
1670#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 54, 0) 1597# if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 54, 0)
1671 if (got_plus) { 1598 if (got_plus) {
1672 switch (ssl_version) { 1599 switch (ssl_version) {
1673 case CURL_SSLVERSION_TLSv1_3: 1600 case CURL_SSLVERSION_TLSv1_3:
1674 ssl_version |= CURL_SSLVERSION_MAX_TLSv1_3; 1601 ssl_version |= CURL_SSLVERSION_MAX_TLSv1_3;
1675 break; 1602 break;
1676 case CURL_SSLVERSION_TLSv1_2: 1603 case CURL_SSLVERSION_TLSv1_2:
1677 case CURL_SSLVERSION_TLSv1_1: 1604 case CURL_SSLVERSION_TLSv1_1:
1678 case CURL_SSLVERSION_TLSv1_0: 1605 case CURL_SSLVERSION_TLSv1_0:
1679 ssl_version |= CURL_SSLVERSION_MAX_DEFAULT; 1606 ssl_version |= CURL_SSLVERSION_MAX_DEFAULT;
1680 break; 1607 break;
1681 } 1608 }
1682 } else { 1609 } else {
1683 switch (ssl_version) { 1610 switch (ssl_version) {
1684 case CURL_SSLVERSION_TLSv1_3: 1611 case CURL_SSLVERSION_TLSv1_3:
1685 ssl_version |= CURL_SSLVERSION_MAX_TLSv1_3; 1612 ssl_version |= CURL_SSLVERSION_MAX_TLSv1_3;
1686 break; 1613 break;
1687 case CURL_SSLVERSION_TLSv1_2: 1614 case CURL_SSLVERSION_TLSv1_2:
1688 ssl_version |= CURL_SSLVERSION_MAX_TLSv1_2; 1615 ssl_version |= CURL_SSLVERSION_MAX_TLSv1_2;
1689 break; 1616 break;
1690 case CURL_SSLVERSION_TLSv1_1: 1617 case CURL_SSLVERSION_TLSv1_1:
1691 ssl_version |= CURL_SSLVERSION_MAX_TLSv1_1; 1618 ssl_version |= CURL_SSLVERSION_MAX_TLSv1_1;
1692 break; 1619 break;
1693 case CURL_SSLVERSION_TLSv1_0: 1620 case CURL_SSLVERSION_TLSv1_0:
1694 ssl_version |= CURL_SSLVERSION_MAX_TLSv1_0; 1621 ssl_version |= CURL_SSLVERSION_MAX_TLSv1_0;
1695 break; 1622 break;
1696 } 1623 }
1697 } 1624 }
1698#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 54, 0) */ 1625# endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 54, 0) */
1699 if (verbose >= 2) 1626 if (verbose >= 2)
1700 printf(_("* Set SSL/TLS version to %d\n"), ssl_version); 1627 printf(_("* Set SSL/TLS version to %d\n"), ssl_version);
1701 if (!specify_port) 1628 if (!specify_port)
1702 server_port = HTTPS_PORT; 1629 server_port = HTTPS_PORT;
1703 break; 1630 break;
1704#else /* LIBCURL_FEATURE_SSL */ 1631#else /* LIBCURL_FEATURE_SSL */
1705 /* -C -J and -K fall through to here without SSL */ 1632 /* -C -J and -K fall through to here without SSL */
1706 usage4 (_("Invalid option - SSL is not available")); 1633 usage4(_("Invalid option - SSL is not available"));
1707 break; 1634 break;
1708 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 */
1709 use_sni = true; 1636 use_sni = true;
1710 break; 1637 break;
1711#endif /* LIBCURL_FEATURE_SSL */ 1638#endif /* LIBCURL_FEATURE_SSL */
1712 case MAX_REDIRS_OPTION: 1639 case MAX_REDIRS_OPTION:
1713 if (!is_intnonneg (optarg)) 1640 if (!is_intnonneg(optarg))
1714 usage2 (_("Invalid max_redirs count"), optarg); 1641 usage2(_("Invalid max_redirs count"), optarg);
1715 else { 1642 else {
1716 max_depth = atoi (optarg); 1643 max_depth = atoi(optarg);
1717 } 1644 }
1718 break; 1645 break;
1719 case 'f': /* onredirect */ 1646 case 'f': /* onredirect */
1720 if (!strcmp (optarg, "ok")) 1647 if (!strcmp(optarg, "ok"))
1721 onredirect = STATE_OK; 1648 onredirect = STATE_OK;
1722 else if (!strcmp (optarg, "warning")) 1649 else if (!strcmp(optarg, "warning"))
1723 onredirect = STATE_WARNING; 1650 onredirect = STATE_WARNING;
1724 else if (!strcmp (optarg, "critical")) 1651 else if (!strcmp(optarg, "critical"))
1725 onredirect = STATE_CRITICAL; 1652 onredirect = STATE_CRITICAL;
1726 else if (!strcmp (optarg, "unknown")) 1653 else if (!strcmp(optarg, "unknown"))
1727 onredirect = STATE_UNKNOWN; 1654 onredirect = STATE_UNKNOWN;
1728 else if (!strcmp (optarg, "follow")) 1655 else if (!strcmp(optarg, "follow"))
1729 onredirect = STATE_DEPENDENT; 1656 onredirect = STATE_DEPENDENT;
1730 else if (!strcmp (optarg, "stickyport")) 1657 else if (!strcmp(optarg, "stickyport"))
1731 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;
1732 else if (!strcmp (optarg, "sticky")) 1659 else if (!strcmp(optarg, "sticky"))
1733 onredirect = STATE_DEPENDENT, followmethod = FOLLOW_HTTP_CURL, followsticky = STICKY_HOST; 1660 onredirect = STATE_DEPENDENT, followmethod = FOLLOW_HTTP_CURL, followsticky = STICKY_HOST;
1734 else if (!strcmp (optarg, "follow")) 1661 else if (!strcmp(optarg, "follow"))
1735 onredirect = STATE_DEPENDENT, followmethod = FOLLOW_HTTP_CURL, followsticky = STICKY_NONE; 1662 onredirect = STATE_DEPENDENT, followmethod = FOLLOW_HTTP_CURL, followsticky = STICKY_NONE;
1736 else if (!strcmp (optarg, "curl")) 1663 else if (!strcmp(optarg, "curl"))
1737 onredirect = STATE_DEPENDENT, followmethod = FOLLOW_LIBCURL; 1664 onredirect = STATE_DEPENDENT, followmethod = FOLLOW_LIBCURL;
1738 else usage2 (_("Invalid onredirect option"), optarg); 1665 else
1739 if (verbose >= 2) 1666 usage2(_("Invalid onredirect option"), optarg);
1740 printf(_("* Following redirects set to %s\n"), state_text(onredirect)); 1667 if (verbose >= 2)
1741 break; 1668 printf(_("* Following redirects set to %s\n"), state_text(onredirect));
1742 case 'd': /* string or substring */ 1669 break;
1743 strncpy (header_expect, optarg, MAX_INPUT_BUFFER - 1); 1670 case 'd': /* string or substring */
1744 header_expect[MAX_INPUT_BUFFER - 1] = 0; 1671 strncpy(header_expect, optarg, MAX_INPUT_BUFFER - 1);
1745 break; 1672 header_expect[MAX_INPUT_BUFFER - 1] = 0;
1746 case 's': /* string or substring */ 1673 break;
1747 strncpy (string_expect, optarg, MAX_INPUT_BUFFER - 1); 1674 case 's': /* string or substring */
1748 string_expect[MAX_INPUT_BUFFER - 1] = 0; 1675 strncpy(string_expect, optarg, MAX_INPUT_BUFFER - 1);
1749 break; 1676 string_expect[MAX_INPUT_BUFFER - 1] = 0;
1750 case 'e': /* string or substring */ 1677 break;
1751 strncpy (server_expect, optarg, MAX_INPUT_BUFFER - 1); 1678 case 'e': /* string or substring */
1752 server_expect[MAX_INPUT_BUFFER - 1] = 0; 1679 strncpy(server_expect, optarg, MAX_INPUT_BUFFER - 1);
1753 server_expect_yn = 1; 1680 server_expect[MAX_INPUT_BUFFER - 1] = 0;
1754 break; 1681 server_expect_yn = 1;
1755 case 'T': /* Content-type */ 1682 break;
1756 http_content_type = strdup (optarg); 1683 case 'T': /* Content-type */
1757 break; 1684 http_content_type = strdup(optarg);
1758 case 'l': /* linespan */ 1685 break;
1759 cflags &= ~REG_NEWLINE; 1686 case 'l': /* linespan */
1760 break; 1687 cflags &= ~REG_NEWLINE;
1761 case 'R': /* regex */ 1688 break;
1762 cflags |= REG_ICASE; 1689 case 'R': /* regex */
1690 cflags |= REG_ICASE;
1763 // fall through 1691 // fall through
1764 case 'r': /* regex */ 1692 case 'r': /* regex */
1765 strncpy (regexp, optarg, MAX_RE_SIZE - 1); 1693 strncpy(regexp, optarg, MAX_RE_SIZE - 1);
1766 regexp[MAX_RE_SIZE - 1] = 0; 1694 regexp[MAX_RE_SIZE - 1] = 0;
1767 errcode = regcomp (&preg, regexp, cflags); 1695 errcode = regcomp(&preg, regexp, cflags);
1768 if (errcode != 0) { 1696 if (errcode != 0) {
1769 (void) regerror (errcode, &preg, errbuf, MAX_INPUT_BUFFER); 1697 (void)regerror(errcode, &preg, errbuf, MAX_INPUT_BUFFER);
1770 printf (_("Could Not Compile Regular Expression: %s"), errbuf); 1698 printf(_("Could Not Compile Regular Expression: %s"), errbuf);
1771 return false; 1699 return false;
1772 } 1700 }
1773 break; 1701 break;
1774 case INVERT_REGEX: 1702 case INVERT_REGEX:
1775 invert_regex = true; 1703 invert_regex = true;
1776 break; 1704 break;
1777 case STATE_REGEX: 1705 case STATE_REGEX:
1778 if (!strcmp (optarg, "critical")) 1706 if (!strcasecmp(optarg, "critical"))
1779 state_regex = STATE_CRITICAL; 1707 state_regex = STATE_CRITICAL;
1780 else if (!strcmp (optarg, "warning")) 1708 else if (!strcasecmp(optarg, "warning"))
1781 state_regex = STATE_WARNING; 1709 state_regex = STATE_WARNING;
1782 else usage2 (_("Invalid state-regex option"), optarg); 1710 else
1783 break; 1711 usage2(_("Invalid state-regex option"), optarg);
1784 case '4': 1712 break;
1785 address_family = AF_INET; 1713 case '4':
1786 break; 1714 address_family = AF_INET;
1787 case '6': 1715 break;
1788#if defined (USE_IPV6) && defined (LIBCURL_FEATURE_IPV6) 1716 case '6':
1789 address_family = AF_INET6; 1717#if defined(USE_IPV6) && defined(LIBCURL_FEATURE_IPV6)
1718 address_family = AF_INET6;
1790#else 1719#else
1791 usage4 (_("IPv6 support not available")); 1720 usage4(_("IPv6 support not available"));
1792#endif 1721#endif
1793 break; 1722 break;
1794 case 'm': /* min_page_length */ 1723 case 'm': /* min_page_length */
1795 { 1724 {
1796 char *tmp; 1725 char *tmp;
1797 if (strchr(optarg, ':') != (char *)NULL) { 1726 if (strchr(optarg, ':') != (char *)NULL) {
1798 /* range, so get two values, min:max */ 1727 /* range, so get two values, min:max */
1799 tmp = strtok(optarg, ":"); 1728 tmp = strtok(optarg, ":");
1800 if (tmp == NULL) { 1729 if (tmp == NULL) {
1801 printf("Bad format: try \"-m min:max\"\n"); 1730 printf("Bad format: try \"-m min:max\"\n");
1802 exit (STATE_WARNING); 1731 exit(STATE_WARNING);
1803 } else 1732 } else
1804 min_page_len = atoi(tmp); 1733 min_page_len = atoi(tmp);
1805 1734
1806 tmp = strtok(NULL, ":"); 1735 tmp = strtok(NULL, ":");
1807 if (tmp == NULL) { 1736 if (tmp == NULL) {
1808 printf("Bad format: try \"-m min:max\"\n"); 1737 printf("Bad format: try \"-m min:max\"\n");
1809 exit (STATE_WARNING); 1738 exit(STATE_WARNING);
1810 } else 1739 } else
1811 max_page_len = atoi(tmp); 1740 max_page_len = atoi(tmp);
1812 } else 1741 } else
1813 min_page_len = atoi (optarg); 1742 min_page_len = atoi(optarg);
1814 break; 1743 break;
1815 } 1744 }
1816 case 'N': /* no-body */ 1745 case 'N': /* no-body */
1817 no_body = true; 1746 no_body = true;
1818 break; 1747 break;
1819 case 'M': /* max-age */ 1748 case 'M': /* max-age */
1820 { 1749 {
1821 int L = strlen(optarg); 1750 int L = strlen(optarg);
1822 if (L && optarg[L-1] == 'm') 1751 if (L && optarg[L - 1] == 'm')
1823 maximum_age = atoi (optarg) * 60; 1752 maximum_age = atoi(optarg) * 60;
1824 else if (L && optarg[L-1] == 'h') 1753 else if (L && optarg[L - 1] == 'h')
1825 maximum_age = atoi (optarg) * 60 * 60; 1754 maximum_age = atoi(optarg) * 60 * 60;
1826 else if (L && optarg[L-1] == 'd') 1755 else if (L && optarg[L - 1] == 'd')
1827 maximum_age = atoi (optarg) * 60 * 60 * 24; 1756 maximum_age = atoi(optarg) * 60 * 60 * 24;
1828 else if (L && (optarg[L-1] == 's' || 1757 else if (L && (optarg[L - 1] == 's' || isdigit(optarg[L - 1])))
1829 isdigit (optarg[L-1]))) 1758 maximum_age = atoi(optarg);
1830 maximum_age = atoi (optarg); 1759 else {
1831 else { 1760 fprintf(stderr, "unparsable max-age: %s\n", optarg);
1832 fprintf (stderr, "unparsable max-age: %s\n", optarg); 1761 exit(STATE_WARNING);
1833 exit (STATE_WARNING); 1762 }
1834 } 1763 if (verbose >= 2)
1835 if (verbose >= 2) 1764 printf("* Maximal age of document set to %d seconds\n", maximum_age);
1836 printf ("* Maximal age of document set to %d seconds\n", maximum_age); 1765 } break;
1837 } 1766 case 'E': /* show extended perfdata */
1838 break; 1767 show_extended_perfdata = true;
1839 case 'E': /* show extended perfdata */ 1768 break;
1840 show_extended_perfdata = true; 1769 case 'B': /* print body content after status line */
1841 break; 1770 show_body = true;
1842 case 'B': /* print body content after status line */ 1771 break;
1843 show_body = true; 1772 case HTTP_VERSION_OPTION:
1844 break; 1773 curl_http_version = CURL_HTTP_VERSION_NONE;
1845 case HTTP_VERSION_OPTION: 1774 if (strcmp(optarg, "1.0") == 0) {
1846 curl_http_version = CURL_HTTP_VERSION_NONE; 1775 curl_http_version = CURL_HTTP_VERSION_1_0;
1847 if (strcmp (optarg, "1.0") == 0) { 1776 } else if (strcmp(optarg, "1.1") == 0) {
1848 curl_http_version = CURL_HTTP_VERSION_1_0; 1777 curl_http_version = CURL_HTTP_VERSION_1_1;
1849 } else if (strcmp (optarg, "1.1") == 0) { 1778 } else if ((strcmp(optarg, "2.0") == 0) || (strcmp(optarg, "2") == 0)) {
1850 curl_http_version = CURL_HTTP_VERSION_1_1;
1851 } else if ((strcmp (optarg, "2.0") == 0) || (strcmp (optarg, "2") == 0)) {
1852#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 33, 0) 1779#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 33, 0)
1853 curl_http_version = CURL_HTTP_VERSION_2_0; 1780 curl_http_version = CURL_HTTP_VERSION_2_0;
1854#else 1781#else
1855 curl_http_version = CURL_HTTP_VERSION_NONE; 1782 curl_http_version = CURL_HTTP_VERSION_NONE;
1856#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 33, 0) */ 1783#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 33, 0) */
1857 } else { 1784 } else {
1858 fprintf (stderr, "unknown http-version parameter: %s\n", optarg); 1785 fprintf(stderr, "unknown http-version parameter: %s\n", optarg);
1859 exit (STATE_WARNING); 1786 exit(STATE_WARNING);
1860 } 1787 }
1861 break; 1788 break;
1862 case AUTOMATIC_DECOMPRESSION: 1789 case AUTOMATIC_DECOMPRESSION:
1863 automatic_decompression = true; 1790 automatic_decompression = true;
1864 break; 1791 break;
1865 case COOKIE_JAR: 1792 case COOKIE_JAR:
1866 cookie_jar_file = optarg; 1793 cookie_jar_file = optarg;
1867 break; 1794 break;
1868 case HAPROXY_PROTOCOL: 1795 case HAPROXY_PROTOCOL:
1869 haproxy_protocol = true; 1796 haproxy_protocol = true;
1870 break; 1797 break;
1871 case '?': 1798 case '?':
1872 /* print short usage statement if args not parsable */ 1799 /* print short usage statement if args not parsable */
1873 usage5 (); 1800 usage5();
1874 break; 1801 break;
1875 } 1802 }
1876 } 1803 }
1877 1804
1878 c = optind; 1805 c = optind;
1879 1806
1880 if (server_address == NULL && c < argc) 1807 if (server_address == NULL && c < argc)
1881 server_address = strdup (argv[c++]); 1808 server_address = strdup(argv[c++]);
1882 1809
1883 if (host_name == NULL && c < argc) 1810 if (host_name == NULL && c < argc)
1884 host_name = strdup (argv[c++]); 1811 host_name = strdup(argv[c++]);
1885 1812
1886 if (server_address == NULL) { 1813 if (server_address == NULL) {
1887 if (host_name == NULL) 1814 if (host_name == NULL)
1888 usage4 (_("You must specify a server address or host name")); 1815 usage4(_("You must specify a server address or host name"));
1889 else 1816 else
1890 server_address = strdup (host_name); 1817 server_address = strdup(host_name);
1891 } 1818 }
1892 1819
1893 set_thresholds(&thlds, warning_thresholds, critical_thresholds); 1820 set_thresholds(&thlds, warning_thresholds, critical_thresholds);
1894 1821
1895 if (critical_thresholds && thlds->critical->end>(double)socket_timeout) 1822 if (critical_thresholds && thlds->critical->end > (double)socket_timeout)
1896 socket_timeout = (int)thlds->critical->end + 1; 1823 socket_timeout = (int)thlds->critical->end + 1;
1897 if (verbose >= 2) 1824 if (verbose >= 2)
1898 printf ("* Socket timeout set to %ld seconds\n", socket_timeout); 1825 printf("* Socket timeout set to %ld seconds\n", socket_timeout);
1899 1826
1900 if (http_method == NULL) 1827 if (http_method == NULL)
1901 http_method = strdup ("GET"); 1828 http_method = strdup("GET");
1902 1829
1903 if (client_cert && !client_privkey) 1830 if (client_cert && !client_privkey)
1904 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"));
1905 1832
1906 if (virtual_port == 0) 1833 if (virtual_port == 0)
1907 virtual_port = server_port; 1834 virtual_port = server_port;
1908 else { 1835 else {
1909 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))
1910 if(!specify_port) 1837 if (!specify_port)
1911 server_port = virtual_port; 1838 server_port = virtual_port;
1912 } 1839 }
1913 1840
1914 return true; 1841 return true;
1915} 1842}
1916 1843
1917char *perfd_time (double elapsed_time) 1844char *perfd_time(double elapsed_time) {
1918{ 1845 return fperfdata("time", elapsed_time, "s", thlds->warning ? true : false, thlds->warning ? thlds->warning->end : 0,
1919 return fperfdata ("time", elapsed_time, "s", 1846 thlds->critical ? true : false, thlds->critical ? thlds->critical->end : 0, true, 0, true, socket_timeout);
1920 thlds->warning?true:false, thlds->warning?thlds->warning->end:0,
1921 thlds->critical?true:false, thlds->critical?thlds->critical->end:0,
1922 true, 0, true, socket_timeout);
1923} 1847}
1924 1848
1925char *perfd_time_connect (double elapsed_time_connect) 1849char *perfd_time_connect(double elapsed_time_connect) {
1926{ 1850 return fperfdata("time_connect", elapsed_time_connect, "s", false, 0, false, 0, false, 0, true, socket_timeout);
1927 return fperfdata ("time_connect", elapsed_time_connect, "s", false, 0, false, 0, false, 0, true, socket_timeout);
1928} 1851}
1929 1852
1930char *perfd_time_ssl (double elapsed_time_ssl) 1853char *perfd_time_ssl(double elapsed_time_ssl) {
1931{ 1854 return fperfdata("time_ssl", elapsed_time_ssl, "s", false, 0, false, 0, false, 0, true, socket_timeout);
1932 return fperfdata ("time_ssl", elapsed_time_ssl, "s", false, 0, false, 0, false, 0, true, socket_timeout);
1933} 1855}
1934 1856
1935char *perfd_time_headers (double elapsed_time_headers) 1857char *perfd_time_headers(double elapsed_time_headers) {
1936{ 1858 return fperfdata("time_headers", elapsed_time_headers, "s", false, 0, false, 0, false, 0, true, socket_timeout);
1937 return fperfdata ("time_headers", elapsed_time_headers, "s", false, 0, false, 0, false, 0, true, socket_timeout);
1938} 1859}
1939 1860
1940char *perfd_time_firstbyte (double elapsed_time_firstbyte) 1861char *perfd_time_firstbyte(double elapsed_time_firstbyte) {
1941{ 1862 return fperfdata("time_firstbyte", elapsed_time_firstbyte, "s", false, 0, false, 0, false, 0, true, socket_timeout);
1942 return fperfdata ("time_firstbyte", elapsed_time_firstbyte, "s", false, 0, false, 0, false, 0, true, socket_timeout);
1943} 1863}
1944 1864
1945char *perfd_time_transfer (double elapsed_time_transfer) 1865char *perfd_time_transfer(double elapsed_time_transfer) {
1946{ 1866 return fperfdata("time_transfer", elapsed_time_transfer, "s", false, 0, false, 0, false, 0, true, socket_timeout);
1947 return fperfdata ("time_transfer", elapsed_time_transfer, "s", false, 0, false, 0, false, 0, true, socket_timeout);
1948} 1867}
1949 1868
1950char *perfd_size (int page_len) 1869char *perfd_size(int page_len) {
1951{ 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,
1952 return perfdata ("size", page_len, "B", 1871 false, 0);
1953 (min_page_len>0?true:false), min_page_len,
1954 (min_page_len>0?true:false), 0,
1955 true, 0, false, 0);
1956} 1872}
1957 1873
1958void 1874void print_help(void) {
1959print_help (void) 1875 print_revision(progname, NP_VERSION);
1960{
1961 print_revision (progname, NP_VERSION);
1962 1876
1963 printf ("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n"); 1877 printf("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n");
1964 printf (COPYRIGHT, copyright, email); 1878 printf(COPYRIGHT, copyright, email);
1965 1879
1966 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"));
1967 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"));
1968 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"));
1969 printf ("%s\n", _("certificate expiration times.")); 1883 printf("%s\n", _("certificate expiration times."));
1970 printf ("\n"); 1884 printf("\n");
1971 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"));
1972 printf ("%s\n", _("as possible.")); 1886 printf("%s\n", _("as possible."));
1973 1887
1974 printf ("\n\n"); 1888 printf("\n\n");
1975 1889
1976 print_usage (); 1890 print_usage();
1977 1891
1978 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"));
1979 1893
1980 printf ("\n"); 1894 printf("\n");
1981 1895
1982 printf (UT_HELP_VRSN); 1896 printf(UT_HELP_VRSN);
1983 printf (UT_EXTRA_OPTS); 1897 printf(UT_EXTRA_OPTS);
1984 1898
1985 printf (" %s\n", "-H, --hostname=ADDRESS"); 1899 printf(" %s\n", "-H, --hostname=ADDRESS");
1986 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)"));
1987 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)"));
1988 printf (" %s\n", "-I, --IP-address=ADDRESS"); 1902 printf(" %s\n", "-I, --IP-address=ADDRESS");
1989 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)."));
1990 printf (" %s\n", "-p, --port=INTEGER"); 1904 printf(" %s\n", "-p, --port=INTEGER");
1991 printf (" %s", _("Port number (default: ")); 1905 printf(" %s", _("Port number (default: "));
1992 printf ("%d)\n", HTTP_PORT); 1906 printf("%d)\n", HTTP_PORT);
1993 1907
1994 printf (UT_IPv46); 1908 printf(UT_IPv46);
1995 1909
1996#ifdef LIBCURL_FEATURE_SSL 1910#ifdef LIBCURL_FEATURE_SSL
1997 printf (" %s\n", "-S, --ssl=VERSION[+]"); 1911 printf(" %s\n", "-S, --ssl=VERSION[+]");
1998 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"));
1999 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,"));
2000 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."));
2001 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"));
2002 printf (" %s\n", "--sni"); 1916 printf(" %s\n", "--sni");
2003 printf (" %s\n", _("Enable SSL/TLS hostname extension support (SNI)")); 1917 printf(" %s\n", _("Enable SSL/TLS hostname extension support (SNI)"));
2004#if LIBCURL_VERSION_NUM >= 0x071801 1918# if LIBCURL_VERSION_NUM >= 0x071801
2005 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"));
2006 printf (" %s\n", _(" SNI only really works since TLSv1.0")); 1920 printf(" %s\n", _(" SNI only really works since TLSv1.0"));
2007#else 1921# else
2008 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"));
2009#endif 1923# endif
2010 printf (" %s\n", "-C, --certificate=INTEGER[,INTEGER]"); 1924 printf(" %s\n", "-C, --certificate=INTEGER[,INTEGER]");
2011 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."));
2012 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"));
2013 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"));
2014 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."));
2015 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"));
2016 printf (" %s\n", _(" --continue-after-certificate to override this behavior)")); 1930 printf(" %s\n", _(" --continue-after-certificate to override this behavior)"));
2017 printf (" %s\n", "--continue-after-certificate"); 1931 printf(" %s\n", "--continue-after-certificate");
2018 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."));
2019 printf (" %s\n", _("Does nothing unless -C is used.")); 1933 printf(" %s\n", _("Does nothing unless -C is used."));
2020 printf (" %s\n", "-J, --client-cert=FILE"); 1934 printf(" %s\n", "-J, --client-cert=FILE");
2021 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)"));
2022 printf (" %s\n", _("to be used in establishing the SSL session")); 1936 printf(" %s\n", _("to be used in establishing the SSL session"));
2023 printf (" %s\n", "-K, --private-key=FILE"); 1937 printf(" %s\n", "-K, --private-key=FILE");
2024 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)"));
2025 printf (" %s\n", _("matching the client certificate")); 1939 printf(" %s\n", _("matching the client certificate"));
2026 printf (" %s\n", "--ca-cert=FILE"); 1940 printf(" %s\n", "--ca-cert=FILE");
2027 printf (" %s\n", _("CA certificate file to verify peer against")); 1941 printf(" %s\n", _("CA certificate file to verify peer against"));
2028 printf (" %s\n", "-D, --verify-cert"); 1942 printf(" %s\n", "-D, --verify-cert");
2029 printf (" %s\n", _("Verify the peer's SSL certificate and hostname")); 1943 printf(" %s\n", _("Verify the peer's SSL certificate and hostname"));
2030#endif 1944#endif
2031 1945
2032 printf (" %s\n", "-e, --expect=STRING"); 1946 printf(" %s\n", "-e, --expect=STRING");
2033 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"));
2034 printf (" %s", _("the first (status) line of the server response (default: ")); 1948 printf(" %s", _("the first (status) line of the server response (default: "));
2035 printf ("%s)\n", HTTP_EXPECT); 1949 printf("%s)\n", HTTP_EXPECT);
2036 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)"));
2037 printf (" %s\n", "-d, --header-string=STRING"); 1951 printf(" %s\n", "-d, --header-string=STRING");
2038 printf (" %s\n", _("String to expect in the response headers")); 1952 printf(" %s\n", _("String to expect in the response headers"));
2039 printf (" %s\n", "-s, --string=STRING"); 1953 printf(" %s\n", "-s, --string=STRING");
2040 printf (" %s\n", _("String to expect in the content")); 1954 printf(" %s\n", _("String to expect in the content"));
2041 printf (" %s\n", "-u, --url=PATH"); 1955 printf(" %s\n", "-u, --url=PATH");
2042 printf (" %s\n", _("URL to GET or POST (default: /)")); 1956 printf(" %s\n", _("URL to GET or POST (default: /)"));
2043 printf (" %s\n", "-P, --post=STRING"); 1957 printf(" %s\n", "-P, --post=STRING");
2044 printf (" %s\n", _("URL decoded http POST data")); 1958 printf(" %s\n", _("URL decoded http POST data"));
2045 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)");
2046 printf (" %s\n", _("Set HTTP method.")); 1960 printf(" %s\n", _("Set HTTP method."));
2047 printf (" %s\n", "-N, --no-body"); 1961 printf(" %s\n", "-N, --no-body");
2048 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."));
2049 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.)"));
2050 printf (" %s\n", "-M, --max-age=SECONDS"); 1964 printf(" %s\n", "-M, --max-age=SECONDS");
2051 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"));
2052 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."));
2053 printf (" %s\n", "-T, --content-type=STRING"); 1967 printf(" %s\n", "-T, --content-type=STRING");
2054 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"));
2055 printf (" %s\n", "-l, --linespan"); 1969 printf(" %s\n", "-l, --linespan");
2056 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)"));
2057 printf (" %s\n", "-r, --regex, --ereg=STRING"); 1971 printf(" %s\n", "-r, --regex, --ereg=STRING");
2058 printf (" %s\n", _("Search page for regex STRING")); 1972 printf(" %s\n", _("Search page for regex STRING"));
2059 printf (" %s\n", "-R, --eregi=STRING"); 1973 printf(" %s\n", "-R, --eregi=STRING");
2060 printf (" %s\n", _("Search page for case-insensitive regex STRING")); 1974 printf(" %s\n", _("Search page for case-insensitive regex STRING"));
2061 printf (" %s\n", "--invert-regex"); 1975 printf(" %s\n", "--invert-regex");
2062 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)"));
2063 printf (" %s\n", _("can be changed with --state--regex)")); 1977 printf(" %s\n", _("can be changed with --state--regex)"));
2064 printf (" %s\n", "--regex-state=STATE"); 1978 printf(" %s\n", "--state-regex=STATE");
2065 printf (" %s\n", _("Return STATE if regex is found, OK if not\n")); 1979 printf(" %s\n", _("Return STATE if regex is found, OK if not. STATE can be one of \"critical\",\"warning\""));
2066 printf (" %s\n", "-a, --authorization=AUTH_PAIR"); 1980 printf(" %s\n", "-a, --authorization=AUTH_PAIR");
2067 printf (" %s\n", _("Username:password on sites with basic authentication")); 1981 printf(" %s\n", _("Username:password on sites with basic authentication"));
2068 printf (" %s\n", "-b, --proxy-authorization=AUTH_PAIR"); 1982 printf(" %s\n", "-b, --proxy-authorization=AUTH_PAIR");
2069 printf (" %s\n", _("Username:password on proxy-servers with basic authentication")); 1983 printf(" %s\n", _("Username:password on proxy-servers with basic authentication"));
2070 printf (" %s\n", "-A, --useragent=STRING"); 1984 printf(" %s\n", "-A, --useragent=STRING");
2071 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\""));
2072 printf (" %s\n", "-k, --header=STRING"); 1986 printf(" %s\n", "-k, --header=STRING");
2073 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"));
2074 printf (" %s\n", "-E, --extended-perfdata"); 1988 printf(" %s\n", "-E, --extended-perfdata");
2075 printf (" %s\n", _("Print additional performance data")); 1989 printf(" %s\n", _("Print additional performance data"));
2076 printf (" %s\n", "-B, --show-body"); 1990 printf(" %s\n", "-B, --show-body");
2077 printf (" %s\n", _("Print body content below status line")); 1991 printf(" %s\n", _("Print body content below status line"));
2078 printf (" %s\n", "-L, --link"); 1992 printf(" %s\n", "-L, --link");
2079 printf (" %s\n", _("Wrap output in HTML link (obsoleted by urlize)")); 1993 printf(" %s\n", _("Wrap output in HTML link (obsoleted by urlize)"));
2080 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>");
2081 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"));
2082 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."));
2083 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."));
2084 printf (" %s\n", _("curl uses CURL_FOLLOWLOCATION built into libcurl.")); 1998 printf(" %s\n", _("curl uses CURL_FOLLOWLOCATION built into libcurl."));
2085 printf (" %s\n", "--max-redirs=INTEGER"); 1999 printf(" %s\n", "--max-redirs=INTEGER");
2086 printf (" %s", _("Maximal number of redirects (default: ")); 2000 printf(" %s", _("Maximal number of redirects (default: "));
2087 printf ("%d)\n", DEFAULT_MAX_REDIRS); 2001 printf("%d)\n", DEFAULT_MAX_REDIRS);
2088 printf (" %s\n", "-m, --pagesize=INTEGER<:INTEGER>"); 2002 printf(" %s\n", "-m, --pagesize=INTEGER<:INTEGER>");
2089 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)"));
2090 printf ("\n"); 2004 printf("\n");
2091 printf (" %s\n", "--http-version=VERSION"); 2005 printf(" %s\n", "--http-version=VERSION");
2092 printf (" %s\n", _("Connect via specific HTTP protocol.")); 2006 printf(" %s\n", _("Connect via specific HTTP protocol."));
2093 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)"));
2094 printf (" %s\n", "--enable-automatic-decompression"); 2008 printf(" %s\n", "--enable-automatic-decompression");
2095 printf (" %s\n", _("Enable automatic decompression of body (CURLOPT_ACCEPT_ENCODING).")); 2009 printf(" %s\n", _("Enable automatic decompression of body (CURLOPT_ACCEPT_ENCODING)."));
2096 printf(" %s\n", "--haproxy-protocol"); 2010 printf(" %s\n", "--haproxy-protocol");
2097 printf(" %s\n", _("Send HAProxy proxy protocol v1 header (CURLOPT_HAPROXYPROTOCOL).")); 2011 printf(" %s\n", _("Send HAProxy proxy protocol v1 header (CURLOPT_HAPROXYPROTOCOL)."));
2098 printf (" %s\n", "--cookie-jar=FILE"); 2012 printf(" %s\n", "--cookie-jar=FILE");
2099 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."));
2100 printf ("\n"); 2014 printf("\n");
2101 2015
2102 printf (UT_WARN_CRIT); 2016 printf(UT_WARN_CRIT);
2103 2017
2104 printf (UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); 2018 printf(UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
2105 2019
2106 printf (UT_VERBOSE); 2020 printf(UT_VERBOSE);
2107 2021
2108 printf ("\n"); 2022 printf("\n");
2109 printf ("%s\n", _("Notes:")); 2023 printf("%s\n", _("Notes:"));
2110 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."));
2111 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"));
2112 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"));
2113 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"));
2114 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"));
2115 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."));
2116 2030
2117#ifdef LIBCURL_FEATURE_SSL 2031#ifdef LIBCURL_FEATURE_SSL
2118 printf ("\n"); 2032 printf("\n");
2119 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"));
2120 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 "));
2121 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."));
2122 printf ("\n"); 2036 printf("\n");
2123 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"));
2124 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"));
2125 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."));
2126 printf ("\n"); 2040 printf("\n");
2127 printf ("%s\n", _("Examples:")); 2041 printf("%s\n", _("Examples:"));
2128 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");
2129 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,"));
2130 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"));
2131 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,"));
2132 printf (" %s\n", _("a STATE_CRITICAL will be returned.")); 2046 printf(" %s\n", _("a STATE_CRITICAL will be returned."));
2133 printf ("\n"); 2047 printf("\n");
2134 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");
2135 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,"));
2136 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"));
2137 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"));
2138 printf (" %s\n\n", _("the certificate is expired.")); 2052 printf(" %s\n\n", _("the certificate is expired."));
2139 printf ("\n"); 2053 printf("\n");
2140 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");
2141 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,"));
2142 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"));
2143 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."));
2144 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"));
2145#endif 2059#endif
2146 2060
2147 printf ("\n %s\n", "CHECK WEBSERVER CONTENT VIA PROXY:"); 2061 printf("\n %s\n", "CHECK WEBSERVER CONTENT VIA PROXY:");
2148 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:"));
2149 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"));
2150 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:"));
2151 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"));
2152 2066
2153#ifdef LIBCURL_FEATURE_SSL 2067#ifdef LIBCURL_FEATURE_SSL
2154 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: ");
2155 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:"));
2156 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"));
2157 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:"));
2158 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 "));
2159 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>"));
2160 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"));
2161 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,"));
2162 printf (" %s\n", _("a STATE_CRITICAL will be returned.")); 2076 printf(" %s\n", _("a STATE_CRITICAL will be returned."));
2163 2077
2164#endif 2078#endif
2165 2079
2166 printf (UT_SUPPORT); 2080 printf(UT_SUPPORT);
2167
2168} 2081}
2169 2082
2170 2083void print_usage(void) {
2171 2084 printf("%s\n", _("Usage:"));
2172void 2085 printf(" %s -H <vhost> | -I <IP-address> [-u <uri>] [-p <port>]\n", progname);
2173print_usage (void) 2086 printf(" [-J <client certificate file>] [-K <private key>] [--ca-cert <CA certificate file>] [-D]\n");
2174{ 2087 printf(" [-w <warn time>] [-c <critical time>] [-t <timeout>] [-L] [-E] [-a auth]\n");
2175 printf ("%s\n", _("Usage:")); 2088 printf(" [-b proxy_auth] [-f <ok|warning|critical|follow|sticky|stickyport|curl>]\n");
2176 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");
2177 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");
2178 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");
2179 printf (" [-b proxy_auth] [-f <ok|warning|critical|follow|sticky|stickyport|curl>]\n"); 2092 printf(" [-T <content-type>] [-j method]\n");
2180 printf (" [-e <expect>] [-d string] [-s string] [-l] [-r <regex> | -R <case-insensitive regex>]\n"); 2093 printf(" [--http-version=<version>] [--enable-automatic-decompression]\n");
2181 printf (" [-P string] [-m <min_pg_size>:<max_pg_size>] [-4|-6] [-N] [-M <age>]\n"); 2094 printf(" [--cookie-jar=<cookie jar file>\n");
2182 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);
2183 printf (" [-T <content-type>] [-j method]\n"); 2096 printf(" [-p <port>] [-t <timeout>] [-4|-6] [--sni]\n");
2184 printf (" [--http-version=<version>] [--enable-automatic-decompression]\n"); 2097 printf("\n");
2185 printf (" [--cookie-jar=<cookie jar file>\n");
2186 printf (" %s -H <vhost> | -I <IP-address> -C <warn_age>[,<crit_age>]\n",progname);
2187 printf (" [-p <port>] [-t <timeout>] [-4|-6] [--sni]\n");
2188 printf ("\n");
2189#ifdef LIBCURL_FEATURE_SSL 2098#ifdef LIBCURL_FEATURE_SSL
2190 printf ("%s\n", _("In the first form, make an HTTP request.")); 2099 printf("%s\n", _("In the first form, make an HTTP request."));
2191 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."));
2192#endif 2101#endif
2193} 2102}
2194 2103
2195void 2104void print_curl_version(void) { printf("%s\n", curl_version()); }
2196print_curl_version (void)
2197{
2198 printf( "%s\n", curl_version());
2199}
2200 2105
2201int 2106int curlhelp_initwritebuffer(curlhelp_write_curlbuf *buf) {
2202curlhelp_initwritebuffer (curlhelp_write_curlbuf *buf) 2107 buf->bufsize = DEFAULT_BUFFER_SIZE;
2203{ 2108 buf->buflen = 0;
2204 buf->bufsize = DEFAULT_BUFFER_SIZE; 2109 buf->buf = (char *)malloc((size_t)buf->bufsize);
2205 buf->buflen = 0; 2110 if (buf->buf == NULL)
2206 buf->buf = (char *)malloc ((size_t)buf->bufsize); 2111 return -1;
2207 if (buf->buf == NULL) return -1; 2112 return 0;
2208 return 0;
2209} 2113}
2210 2114
2211size_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) {
2212{ 2116 curlhelp_write_curlbuf *buf = (curlhelp_write_curlbuf *)stream;
2213 curlhelp_write_curlbuf *buf = (curlhelp_write_curlbuf *)stream;
2214 2117
2215 while (buf->bufsize < buf->buflen + size * nmemb + 1) { 2118 while (buf->bufsize < buf->buflen + size * nmemb + 1) {
2216 buf->bufsize = buf->bufsize * 2; 2119 buf->bufsize = buf->bufsize * 2;
2217 buf->buf = (char *)realloc (buf->buf, buf->bufsize); 2120 buf->buf = (char *)realloc(buf->buf, buf->bufsize);
2218 if (buf->buf == NULL) { 2121 if (buf->buf == NULL) {
2219 fprintf(stderr, "malloc failed (%d) %s\n", errno, strerror(errno)); 2122 fprintf(stderr, "malloc failed (%d) %s\n", errno, strerror(errno));
2220 return -1; 2123 return -1;
2221 } 2124 }
2222 } 2125 }
2223 2126
2224 memcpy (buf->buf + buf->buflen, buffer, size * nmemb); 2127 memcpy(buf->buf + buf->buflen, buffer, size * nmemb);
2225 buf->buflen += size * nmemb; 2128 buf->buflen += size * nmemb;
2226 buf->buf[buf->buflen] = '\0'; 2129 buf->buf[buf->buflen] = '\0';
2227 2130
2228 return (int)(size * nmemb); 2131 return (int)(size * nmemb);
2229} 2132}
2230 2133
2231size_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) {
2232{ 2135 curlhelp_read_curlbuf *buf = (curlhelp_read_curlbuf *)stream;
2233 curlhelp_read_curlbuf *buf = (curlhelp_read_curlbuf *)stream;
2234 2136
2235 size_t n = min (nmemb * size, buf->buflen - buf->pos); 2137 size_t n = min(nmemb * size, buf->buflen - buf->pos);
2236 2138
2237 memcpy (buffer, buf->buf + buf->pos, n); 2139 memcpy(buffer, buf->buf + buf->pos, n);
2238 buf->pos += n; 2140 buf->pos += n;
2239 2141
2240 return (int)n; 2142 return (int)n;
2241} 2143}
2242 2144
2243void 2145void curlhelp_freewritebuffer(curlhelp_write_curlbuf *buf) {
2244curlhelp_freewritebuffer (curlhelp_write_curlbuf *buf) 2146 free(buf->buf);
2245{ 2147 buf->buf = NULL;
2246 free (buf->buf);
2247 buf->buf = NULL;
2248} 2148}
2249 2149
2250int 2150int curlhelp_initreadbuffer(curlhelp_read_curlbuf *buf, const char *data, size_t datalen) {
2251curlhelp_initreadbuffer (curlhelp_read_curlbuf *buf, const char *data, size_t datalen) 2151 buf->buflen = datalen;
2252{ 2152 buf->buf = (char *)malloc((size_t)buf->buflen);
2253 buf->buflen = datalen; 2153 if (buf->buf == NULL)
2254 buf->buf = (char *)malloc ((size_t)buf->buflen); 2154 return -1;
2255 if (buf->buf == NULL) return -1; 2155 memcpy(buf->buf, data, datalen);
2256 memcpy (buf->buf, data, datalen); 2156 buf->pos = 0;
2257 buf->pos = 0; 2157 return 0;
2258 return 0;
2259} 2158}
2260 2159
2261void 2160void curlhelp_freereadbuffer(curlhelp_read_curlbuf *buf) {
2262curlhelp_freereadbuffer (curlhelp_read_curlbuf *buf) 2161 free(buf->buf);
2263{ 2162 buf->buf = NULL;
2264 free (buf->buf);
2265 buf->buf = NULL;
2266} 2163}
2267 2164
2268/* 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)?
2269 */ 2166 */
2270const char* 2167const char *strrstr2(const char *haystack, const char *needle) {
2271strrstr2(const char *haystack, const char *needle) 2168 int counter;
2272{ 2169 size_t len;
2273 int counter; 2170 const char *prev_pos;
2274 size_t len; 2171 const char *pos;
2275 const char *prev_pos; 2172
2276 const char *pos; 2173 if (haystack == NULL || needle == NULL)
2277 2174 return NULL;
2278 if (haystack == NULL || needle == NULL) 2175
2279 return NULL; 2176 if (haystack[0] == '\0' || needle[0] == '\0')
2280 2177 return NULL;
2281 if (haystack[0] == '\0' || needle[0] == '\0') 2178
2282 return NULL; 2179 counter = 0;
2283 2180 prev_pos = NULL;
2284 counter = 0; 2181 pos = haystack;
2285 prev_pos = NULL; 2182 len = strlen(needle);
2286 pos = haystack; 2183 for (;;) {
2287 len = strlen (needle); 2184 pos = strstr(pos, needle);
2288 for (;;) { 2185 if (pos == NULL) {
2289 pos = strstr (pos, needle); 2186 if (counter == 0)
2290 if (pos == NULL) { 2187 return NULL;
2291 if (counter == 0) 2188 return prev_pos;
2292 return NULL; 2189 }
2293 else 2190 counter++;
2294 return prev_pos; 2191 prev_pos = pos;
2295 } 2192 pos += len;
2296 counter++; 2193 if (*pos == '\0')
2297 prev_pos = pos; 2194 return prev_pos;
2298 pos += len; 2195 }
2299 if (*pos == '\0') return prev_pos;
2300 }
2301} 2196}
2302 2197
2303int 2198int curlhelp_parse_statusline(const char *buf, curlhelp_statusline *status_line) {
2304curlhelp_parse_statusline (const char *buf, curlhelp_statusline *status_line) 2199 char *first_line_end;
2305{ 2200 char *p;
2306 char *first_line_end; 2201 size_t first_line_len;
2307 char *p; 2202 char *pp;
2308 size_t first_line_len; 2203 const char *start;
2309 char *pp; 2204 char *first_line_buf;
2310 const char *start; 2205
2311 char *first_line_buf; 2206 /* find last start of a new header */
2312 2207 start = strrstr2(buf, "\r\nHTTP/");
2313 /* find last start of a new header */ 2208 if (start != NULL) {
2314 start = strrstr2 (buf, "\r\nHTTP/"); 2209 start += 2;
2315 if (start != NULL) { 2210 buf = start;
2316 start += 2; 2211 }
2317 buf = start;
2318 }
2319
2320 first_line_end = strstr(buf, "\r\n");
2321 if (first_line_end == NULL) return -1;
2322
2323 first_line_len = (size_t)(first_line_end - buf);
2324 status_line->first_line = (char *)malloc (first_line_len + 1);
2325 if (status_line->first_line == NULL) return -1;
2326 memcpy (status_line->first_line, buf, first_line_len);
2327 status_line->first_line[first_line_len] = '\0';
2328 first_line_buf = strdup( status_line->first_line );
2329
2330 /* protocol and version: "HTTP/x.x" SP or "HTTP/2" SP */
2331
2332 p = strtok(first_line_buf, "/");
2333 if( p == NULL ) { free( first_line_buf ); return -1; }
2334 if( strcmp( p, "HTTP" ) != 0 ) { free( first_line_buf ); return -1; }
2335
2336 p = strtok( NULL, " " );
2337 if( p == NULL ) { free( first_line_buf ); return -1; }
2338 if( strchr( p, '.' ) != NULL ) {
2339
2340 /* HTTP 1.x case */
2341 strtok( p, "." );
2342 status_line->http_major = (int)strtol( p, &pp, 10 );
2343 if( *pp != '\0' ) { free( first_line_buf ); return -1; }
2344 strtok( NULL, " " );
2345 status_line->http_minor = (int)strtol( p, &pp, 10 );
2346 if( *pp != '\0' ) { free( first_line_buf ); return -1; }
2347 p += 4; /* 1.x SP */
2348 } else {
2349 /* HTTP 2 case */
2350 status_line->http_major = (int)strtol( p, &pp, 10 );
2351 status_line->http_minor = 0;
2352 p += 2; /* 2 SP */
2353 }
2354
2355 /* status code: "404" or "404.1", then SP */
2356
2357 p = strtok( p, " " );
2358 if( p == NULL ) { free( first_line_buf ); return -1; }
2359 if( strchr( p, '.' ) != NULL ) {
2360 char *ppp;
2361 ppp = strtok( p, "." );
2362 status_line->http_code = (int)strtol( ppp, &pp, 10 );
2363 if( *pp != '\0' ) { free( first_line_buf ); return -1; }
2364 ppp = strtok( NULL, "" );
2365 status_line->http_subcode = (int)strtol( ppp, &pp, 10 );
2366 if( *pp != '\0' ) { free( first_line_buf ); return -1; }
2367 p += 6; /* 400.1 SP */
2368 } else {
2369 status_line->http_code = (int)strtol( p, &pp, 10 );
2370 status_line->http_subcode = -1;
2371 if( *pp != '\0' ) { free( first_line_buf ); return -1; }
2372 p += 4; /* 400 SP */
2373 }
2374
2375 /* Human readable message: "Not Found" CRLF */
2376
2377 p = strtok( p, "" );
2378 if( p == NULL ) { status_line->msg = ""; return 0; }
2379 status_line->msg = status_line->first_line + ( p - first_line_buf );
2380 free( first_line_buf );
2381
2382 return 0;
2383}
2384 2212
2385void 2213 first_line_end = strstr(buf, "\r\n");
2386curlhelp_free_statusline (curlhelp_statusline *status_line) 2214 if (first_line_end == NULL)
2387{ 2215 return -1;
2388 free (status_line->first_line); 2216
2389} 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 }
2390 2264
2391void 2265 /* status code: "404" or "404.1", then SP */
2392remove_newlines (char *s)
2393{
2394 char *p;
2395 2266
2396 for (p = s; *p != '\0'; p++) 2267 p = strtok(p, " ");
2397 if (*p == '\r' || *p == '\n') 2268 if (p == NULL) {
2398 *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;
2399} 2308}
2400 2309
2401char * 2310void curlhelp_free_statusline(curlhelp_statusline *status_line) { free(status_line->first_line); }
2402get_header_value (const struct phr_header* headers, const size_t nof_headers, const char* header) 2311
2403{ 2312char *get_header_value(const struct phr_header *headers, const size_t nof_headers, const char *header) {
2404 for(size_t i = 0; i < nof_headers; i++ ) { 2313 for (size_t i = 0; i < nof_headers; i++) {
2405 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) {
2406 return strndup( headers[i].value, headers[i].value_len ); 2315 return strndup(headers[i].value, headers[i].value_len);
2407 } 2316 }
2408 } 2317 }
2409 return NULL; 2318 return NULL;
2410} 2319}
2411 2320
2412int 2321int check_document_dates(const curlhelp_write_curlbuf *header_buf, char (*msg)[DEFAULT_BUFFER_SIZE]) {
2413check_document_dates (const curlhelp_write_curlbuf *header_buf, char (*msg)[DEFAULT_BUFFER_SIZE]) 2322 char *server_date = NULL;
2414{ 2323 char *document_date = NULL;
2415 char *server_date = NULL; 2324 int date_result = STATE_OK;
2416 char *document_date = NULL; 2325 curlhelp_statusline status_line;
2417 int date_result = STATE_OK; 2326 struct phr_header headers[255];
2418 curlhelp_statusline status_line; 2327 size_t nof_headers = 255;
2419 struct phr_header headers[255]; 2328 size_t msglen;
2420 size_t nof_headers = 255; 2329
2421 size_t msglen; 2330 int res = phr_parse_response(header_buf->buf, header_buf->buflen, &status_line.http_major, &status_line.http_minor,
2422 2331 &status_line.http_code, &status_line.msg, &msglen, headers, &nof_headers, 0);
2423 int res = phr_parse_response (header_buf->buf, header_buf->buflen,
2424 &status_line.http_major, &status_line.http_minor, &status_line.http_code, &status_line.msg, &msglen,
2425 headers, &nof_headers, 0);
2426 2332
2427 if (res == -1) { 2333 if (res == -1) {
2428 die (STATE_UNKNOWN, _("HTTP UNKNOWN - Failed to parse Response\n")); 2334 die(STATE_UNKNOWN, _("HTTP UNKNOWN - Failed to parse Response\n"));
2429 } 2335 }
2430 2336
2431 server_date = get_header_value (headers, nof_headers, "date"); 2337 server_date = get_header_value(headers, nof_headers, "date");
2432 document_date = get_header_value (headers, nof_headers, "last-modified"); 2338 document_date = get_header_value(headers, nof_headers, "last-modified");
2433 2339
2434 if (!server_date || !*server_date) { 2340 if (!server_date || !*server_date) {
2435 char tmp[DEFAULT_BUFFER_SIZE]; 2341 char tmp[DEFAULT_BUFFER_SIZE];
2436 2342
2437 snprintf (tmp, DEFAULT_BUFFER_SIZE, _("%sServer date unknown, "), *msg); 2343 snprintf(tmp, DEFAULT_BUFFER_SIZE, _("%sServer date unknown, "), *msg);
2438 strcpy(*msg, tmp); 2344 strcpy(*msg, tmp);
2439 2345
2440 date_result = max_state_alt(STATE_UNKNOWN, date_result); 2346 date_result = max_state_alt(STATE_UNKNOWN, date_result);
@@ -2442,34 +2348,34 @@ check_document_dates (const curlhelp_write_curlbuf *header_buf, char (*msg)[DEFA
2442 } else if (!document_date || !*document_date) { 2348 } else if (!document_date || !*document_date) {
2443 char tmp[DEFAULT_BUFFER_SIZE]; 2349 char tmp[DEFAULT_BUFFER_SIZE];
2444 2350
2445 snprintf (tmp, DEFAULT_BUFFER_SIZE, _("%sDocument modification date unknown, "), *msg); 2351 snprintf(tmp, DEFAULT_BUFFER_SIZE, _("%sDocument modification date unknown, "), *msg);
2446 strcpy(*msg, tmp); 2352 strcpy(*msg, tmp);
2447 2353
2448 date_result = max_state_alt(STATE_CRITICAL, date_result); 2354 date_result = max_state_alt(STATE_CRITICAL, date_result);
2449 2355
2450 } else { 2356 } else {
2451 time_t srv_data = curl_getdate (server_date, NULL); 2357 time_t srv_data = curl_getdate(server_date, NULL);
2452 time_t doc_data = curl_getdate (document_date, NULL); 2358 time_t doc_data = curl_getdate(document_date, NULL);
2453 if (verbose >= 2) 2359 if (verbose >= 2)
2454 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);
2455 if (srv_data <= 0) { 2361 if (srv_data <= 0) {
2456 char tmp[DEFAULT_BUFFER_SIZE]; 2362 char tmp[DEFAULT_BUFFER_SIZE];
2457 2363
2458 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);
2459 strcpy(*msg, tmp); 2365 strcpy(*msg, tmp);
2460 2366
2461 date_result = max_state_alt(STATE_CRITICAL, date_result); 2367 date_result = max_state_alt(STATE_CRITICAL, date_result);
2462 } else if (doc_data <= 0) { 2368 } else if (doc_data <= 0) {
2463 char tmp[DEFAULT_BUFFER_SIZE]; 2369 char tmp[DEFAULT_BUFFER_SIZE];
2464 2370
2465 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);
2466 strcpy(*msg, tmp); 2372 strcpy(*msg, tmp);
2467 2373
2468 date_result = max_state_alt(STATE_CRITICAL, date_result); 2374 date_result = max_state_alt(STATE_CRITICAL, date_result);
2469 } else if (doc_data > srv_data + 30) { 2375 } else if (doc_data > srv_data + 30) {
2470 char tmp[DEFAULT_BUFFER_SIZE]; 2376 char tmp[DEFAULT_BUFFER_SIZE];
2471 2377
2472 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);
2473 strcpy(*msg, tmp); 2379 strcpy(*msg, tmp);
2474 2380
2475 date_result = max_state_alt(STATE_CRITICAL, date_result); 2381 date_result = max_state_alt(STATE_CRITICAL, date_result);
@@ -2478,14 +2384,14 @@ check_document_dates (const curlhelp_write_curlbuf *header_buf, char (*msg)[DEFA
2478 if (n > (60 * 60 * 24 * 2)) { 2384 if (n > (60 * 60 * 24 * 2)) {
2479 char tmp[DEFAULT_BUFFER_SIZE]; 2385 char tmp[DEFAULT_BUFFER_SIZE];
2480 2386
2481 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));
2482 strcpy(*msg, tmp); 2388 strcpy(*msg, tmp);
2483 2389
2484 date_result = max_state_alt(STATE_CRITICAL, date_result); 2390 date_result = max_state_alt(STATE_CRITICAL, date_result);
2485 } else { 2391 } else {
2486 char tmp[DEFAULT_BUFFER_SIZE]; 2392 char tmp[DEFAULT_BUFFER_SIZE];
2487 2393
2488 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);
2489 strcpy(*msg, tmp); 2395 strcpy(*msg, tmp);
2490 2396
2491 date_result = max_state_alt(STATE_CRITICAL, date_result); 2397 date_result = max_state_alt(STATE_CRITICAL, date_result);
@@ -2493,132 +2399,128 @@ check_document_dates (const curlhelp_write_curlbuf *header_buf, char (*msg)[DEFA
2493 } 2399 }
2494 } 2400 }
2495 2401
2496 if (server_date) free (server_date); 2402 if (server_date)
2497 if (document_date) free (document_date); 2403 free(server_date);
2404 if (document_date)
2405 free(document_date);
2498 2406
2499 return date_result; 2407 return date_result;
2500} 2408}
2501 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;
2502 2417
2503int 2418 int res = phr_parse_response(header_buf->buf, header_buf->buflen, &status_line.http_major, &status_line.http_minor,
2504get_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);
2505{
2506 size_t content_length = 0;
2507 struct phr_header headers[255];
2508 size_t nof_headers = 255;
2509 size_t msglen;
2510 char *content_length_s = NULL;
2511 curlhelp_statusline status_line;
2512
2513 int res = phr_parse_response (header_buf->buf, header_buf->buflen,
2514 &status_line.http_major, &status_line.http_minor, &status_line.http_code, &status_line.msg, &msglen,
2515 headers, &nof_headers, 0);
2516 2420
2517 if (res == -1) { 2421 if (res == -1) {
2518 die (STATE_UNKNOWN, _("HTTP UNKNOWN - Failed to parse Response\n")); 2422 die(STATE_UNKNOWN, _("HTTP UNKNOWN - Failed to parse Response\n"));
2519 } 2423 }
2520 2424
2521 content_length_s = get_header_value (headers, nof_headers, "content-length"); 2425 content_length_s = get_header_value(headers, nof_headers, "content-length");
2522 if (!content_length_s) { 2426 if (!content_length_s) {
2523 return header_buf->buflen + body_buf->buflen; 2427 return header_buf->buflen + body_buf->buflen;
2524 } 2428 }
2525 content_length_s += strspn (content_length_s, " \t"); 2429 content_length_s += strspn(content_length_s, " \t");
2526 content_length = atoi (content_length_s); 2430 content_length = atoi(content_length_s);
2527 if (content_length != body_buf->buflen) { 2431 if (content_length != body_buf->buflen) {
2528 /* 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? */
2529 } 2433 }
2530 2434
2531 if (content_length_s) free (content_length_s); 2435 if (content_length_s)
2436 free(content_length_s);
2532 2437
2533 return header_buf->buflen + body_buf->buflen; 2438 return header_buf->buflen + body_buf->buflen;
2534} 2439}
2535 2440
2536/* 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? */
2537curlhelp_ssl_library 2442curlhelp_ssl_library curlhelp_get_ssl_library(void) {
2538curlhelp_get_ssl_library () 2443 curl_version_info_data *version_data;
2539{ 2444 char *ssl_version;
2540 curl_version_info_data* version_data; 2445 char *library;
2541 char *ssl_version; 2446 curlhelp_ssl_library ssl_library = CURLHELP_SSL_LIBRARY_UNKNOWN;
2542 char *library; 2447
2543 curlhelp_ssl_library ssl_library = CURLHELP_SSL_LIBRARY_UNKNOWN; 2448 version_data = curl_version_info(CURLVERSION_NOW);
2544 2449 if (version_data == NULL)
2545 version_data = curl_version_info (CURLVERSION_NOW); 2450 return CURLHELP_SSL_LIBRARY_UNKNOWN;
2546 if (version_data == NULL) return CURLHELP_SSL_LIBRARY_UNKNOWN; 2451
2547 2452 ssl_version = strdup(version_data->ssl_version);
2548 ssl_version = strdup (version_data->ssl_version); 2453 if (ssl_version == NULL)
2549 if (ssl_version == NULL ) return CURLHELP_SSL_LIBRARY_UNKNOWN; 2454 return CURLHELP_SSL_LIBRARY_UNKNOWN;
2550 2455
2551 library = strtok (ssl_version, "/"); 2456 library = strtok(ssl_version, "/");
2552 if (library == NULL) return CURLHELP_SSL_LIBRARY_UNKNOWN; 2457 if (library == NULL)
2553 2458 return CURLHELP_SSL_LIBRARY_UNKNOWN;
2554 if (strcmp (library, "OpenSSL") == 0) 2459
2555 ssl_library = CURLHELP_SSL_LIBRARY_OPENSSL; 2460 if (strcmp(library, "OpenSSL") == 0)
2556 else if (strcmp (library, "LibreSSL") == 0) 2461 ssl_library = CURLHELP_SSL_LIBRARY_OPENSSL;
2557 ssl_library = CURLHELP_SSL_LIBRARY_LIBRESSL; 2462 else if (strcmp(library, "LibreSSL") == 0)
2558 else if (strcmp (library, "GnuTLS") == 0) 2463 ssl_library = CURLHELP_SSL_LIBRARY_LIBRESSL;
2559 ssl_library = CURLHELP_SSL_LIBRARY_GNUTLS; 2464 else if (strcmp(library, "GnuTLS") == 0)
2560 else if (strcmp (library, "NSS") == 0) 2465 ssl_library = CURLHELP_SSL_LIBRARY_GNUTLS;
2561 ssl_library = CURLHELP_SSL_LIBRARY_NSS; 2466 else if (strcmp(library, "NSS") == 0)
2562 2467 ssl_library = CURLHELP_SSL_LIBRARY_NSS;
2563 if (verbose >= 2) 2468
2564 printf ("* SSL library string is : %s %s (%d)\n", version_data->ssl_version, library, ssl_library); 2469 if (verbose >= 2)
2565 2470 printf("* SSL library string is : %s %s (%d)\n", version_data->ssl_version, library, ssl_library);
2566 free (ssl_version); 2471
2567 2472 free(ssl_version);
2568 return ssl_library; 2473
2474 return ssl_library;
2569} 2475}
2570 2476
2571const char* 2477const char *curlhelp_get_ssl_library_string(curlhelp_ssl_library ssl_library) {
2572curlhelp_get_ssl_library_string (curlhelp_ssl_library ssl_library) 2478 switch (ssl_library) {
2573{ 2479 case CURLHELP_SSL_LIBRARY_OPENSSL:
2574 switch (ssl_library) { 2480 return "OpenSSL";
2575 case CURLHELP_SSL_LIBRARY_OPENSSL: 2481 case CURLHELP_SSL_LIBRARY_LIBRESSL:
2576 return "OpenSSL"; 2482 return "LibreSSL";
2577 case CURLHELP_SSL_LIBRARY_LIBRESSL: 2483 case CURLHELP_SSL_LIBRARY_GNUTLS:
2578 return "LibreSSL"; 2484 return "GnuTLS";
2579 case CURLHELP_SSL_LIBRARY_GNUTLS: 2485 case CURLHELP_SSL_LIBRARY_NSS:
2580 return "GnuTLS"; 2486 return "NSS";
2581 case CURLHELP_SSL_LIBRARY_NSS: 2487 case CURLHELP_SSL_LIBRARY_UNKNOWN:
2582 return "NSS"; 2488 default:
2583 case CURLHELP_SSL_LIBRARY_UNKNOWN: 2489 return "unknown";
2584 default: 2490 }
2585 return "unknown";
2586 }
2587} 2491}
2588 2492
2589#ifdef LIBCURL_FEATURE_SSL 2493#ifdef LIBCURL_FEATURE_SSL
2590#ifndef USE_OPENSSL 2494# ifndef USE_OPENSSL
2591time_t 2495time_t parse_cert_date(const char *s) {
2592parse_cert_date (const char *s) 2496 struct tm tm;
2593{ 2497 time_t date;
2594 struct tm tm; 2498 char *res;
2595 time_t date; 2499
2596 char *res; 2500 if (!s)
2597 2501 return -1;
2598 if (!s) return -1; 2502
2599 2503 /* Jan 17 14:25:12 2020 GMT */
2600 /* Jan 17 14:25:12 2020 GMT */ 2504 res = strptime(s, "%Y-%m-%d %H:%M:%S GMT", &tm);
2601 res = strptime (s, "%Y-%m-%d %H:%M:%S GMT", &tm); 2505 /* Sep 11 12:00:00 2020 GMT */
2602 /* Sep 11 12:00:00 2020 GMT */ 2506 if (res == NULL)
2603 if (res == NULL) strptime (s, "%Y %m %d %H:%M:%S GMT", &tm); 2507 strptime(s, "%Y %m %d %H:%M:%S GMT", &tm);
2604 date = mktime (&tm); 2508 date = mktime(&tm);
2605 2509
2606 return date; 2510 return date;
2607} 2511}
2608 2512
2609/* 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
2610 * OpenSSL could be this function 2514 * OpenSSL could be this function
2611 */ 2515 */
2612int 2516int net_noopenssl_check_certificate(cert_ptr_union *cert_ptr, int days_till_exp_warn, int days_till_exp_crit) {
2613net_noopenssl_check_certificate (cert_ptr_union* cert_ptr, int days_till_exp_warn, int days_till_exp_crit) 2517 int i;
2614{ 2518 struct curl_slist *slist;
2615 int i; 2519 int cname_found = 0;
2616 struct curl_slist* slist; 2520 char *start_date_str = NULL;
2617 int cname_found = 0; 2521 char *end_date_str = NULL;
2618 char* start_date_str = NULL; 2522 time_t start_date;
2619 char* end_date_str = NULL; 2523 time_t end_date;
2620 time_t start_date;
2621 time_t end_date;
2622 char *tz; 2524 char *tz;
2623 float time_left; 2525 float time_left;
2624 int days_left; 2526 int days_left;
@@ -2626,66 +2528,64 @@ net_noopenssl_check_certificate (cert_ptr_union* cert_ptr, int days_till_exp_war
2626 char timestamp[50] = ""; 2528 char timestamp[50] = "";
2627 int status = STATE_UNKNOWN; 2529 int status = STATE_UNKNOWN;
2628 2530
2629 if (verbose >= 2) 2531 if (verbose >= 2)
2630 printf ("**** REQUEST CERTIFICATES ****\n"); 2532 printf("**** REQUEST CERTIFICATES ****\n");
2631 2533
2632 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++) {
2633 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) {
2634 /* find first common name in subject, 2536 /* find first common name in subject,
2635 * TODO: check alternative subjects for 2537 * TODO: check alternative subjects for
2636 * TODO: have a decent parser here and not a hack 2538 * TODO: have a decent parser here and not a hack
2637 * multi-host certificate, check wildcards 2539 * multi-host certificate, check wildcards
2638 */ 2540 */
2639 if (strncasecmp (slist->data, "Subject:", 8) == 0) { 2541 if (strncasecmp(slist->data, "Subject:", 8) == 0) {
2640 int d = 3; 2542 int d = 3;
2641 char* p = strstr (slist->data, "CN="); 2543 char *p = strstr(slist->data, "CN=");
2642 if (p == NULL) { 2544 if (p == NULL) {
2643 d = 5; 2545 d = 5;
2644 p = strstr (slist->data, "CN = "); 2546 p = strstr(slist->data, "CN = ");
2645 } 2547 }
2646 if (p != NULL) { 2548 if (p != NULL) {
2647 if (strncmp (host_name, p+d, strlen (host_name)) == 0) { 2549 if (strncmp(host_name, p + d, strlen(host_name)) == 0) {
2648 cname_found = 1; 2550 cname_found = 1;
2649 } 2551 }
2650 } 2552 }
2651 } else if (strncasecmp (slist->data, "Start Date:", 11) == 0) { 2553 } else if (strncasecmp(slist->data, "Start Date:", 11) == 0) {
2652 start_date_str = &slist->data[11]; 2554 start_date_str = &slist->data[11];
2653 } else if (strncasecmp (slist->data, "Expire Date:", 12) == 0) { 2555 } else if (strncasecmp(slist->data, "Expire Date:", 12) == 0) {
2654 end_date_str = &slist->data[12]; 2556 end_date_str = &slist->data[12];
2655 } else if (strncasecmp (slist->data, "Cert:", 5) == 0) { 2557 } else if (strncasecmp(slist->data, "Cert:", 5) == 0) {
2656 goto HAVE_FIRST_CERT; 2558 goto HAVE_FIRST_CERT;
2657 } 2559 }
2658 if (verbose >= 2) 2560 if (verbose >= 2)
2659 printf ("%d ** %s\n", i, slist->data); 2561 printf("%d ** %s\n", i, slist->data);
2660 } 2562 }
2661 } 2563 }
2662HAVE_FIRST_CERT: 2564HAVE_FIRST_CERT:
2663 2565
2664 if (verbose >= 2) 2566 if (verbose >= 2)
2665 printf ("**** REQUEST CERTIFICATES ****\n"); 2567 printf("**** REQUEST CERTIFICATES ****\n");
2666 2568
2667 if (!cname_found) { 2569 if (!cname_found) {
2668 printf("%s\n",_("CRITICAL - Cannot retrieve certificate subject.")); 2570 printf("%s\n", _("CRITICAL - Cannot retrieve certificate subject."));
2669 return STATE_CRITICAL; 2571 return STATE_CRITICAL;
2670 } 2572 }
2671 2573
2672 start_date = parse_cert_date (start_date_str); 2574 start_date = parse_cert_date(start_date_str);
2673 if (start_date <= 0) { 2575 if (start_date <= 0) {
2674 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);
2675 start_date_str); 2577 puts(msg);
2676 puts (msg); 2578 return STATE_WARNING;
2677 return STATE_WARNING; 2579 }
2678 } 2580
2679 2581 end_date = parse_cert_date(end_date_str);
2680 end_date = parse_cert_date (end_date_str); 2582 if (end_date <= 0) {
2681 if (end_date <= 0) { 2583 snprintf(msg, DEFAULT_BUFFER_SIZE, _("WARNING - Unparsable 'Expire Date' in certificate: '%s'"), start_date_str);
2682 snprintf (msg, DEFAULT_BUFFER_SIZE, _("WARNING - Unparsable 'Expire Date' in certificate: '%s'"), 2584 puts(msg);
2683 start_date_str); 2585 return STATE_WARNING;
2684 puts (msg); 2586 }
2685 return STATE_WARNING; 2587
2686 } 2588 time_left = difftime(end_date, time(NULL));
2687
2688 time_left = difftime (end_date, time(NULL));
2689 days_left = time_left / 86400; 2589 days_left = time_left / 86400;
2690 tz = getenv("TZ"); 2590 tz = getenv("TZ");
2691 setenv("TZ", "GMT", 1); 2591 setenv("TZ", "GMT", 1);
@@ -2698,30 +2598,31 @@ HAVE_FIRST_CERT:
2698 tzset(); 2598 tzset();
2699 2599
2700 if (days_left > 0 && days_left <= days_till_exp_warn) { 2600 if (days_left > 0 && days_left <= days_till_exp_warn) {
2701 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);
2702 if (days_left > days_till_exp_crit) 2603 if (days_left > days_till_exp_crit)
2703 status = STATE_WARNING; 2604 status = STATE_WARNING;
2704 else 2605 else
2705 status = STATE_CRITICAL; 2606 status = STATE_CRITICAL;
2706 } else if (days_left == 0 && time_left > 0) { 2607 } else if (days_left == 0 && time_left > 0) {
2707 if (time_left >= 3600) 2608 if (time_left >= 3600)
2708 time_remaining = (int) time_left / 3600; 2609 time_remaining = (int)time_left / 3600;
2709 else 2610 else
2710 time_remaining = (int) time_left / 60; 2611 time_remaining = (int)time_left / 60;
2711 2612
2712 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,
2713 (days_left>days_till_exp_crit) ? "WARNING" : "CRITICAL", host_name, time_remaining, 2614 time_remaining, time_left >= 3600 ? "hours" : "minutes", timestamp);
2714 time_left >= 3600 ? "hours" : "minutes", timestamp);
2715 2615
2716 if ( days_left > days_till_exp_crit) 2616 if (days_left > days_till_exp_crit)
2717 status = STATE_WARNING; 2617 status = STATE_WARNING;
2718 else 2618 else
2719 status = STATE_CRITICAL; 2619 status = STATE_CRITICAL;
2720 } else if (time_left < 0) { 2620 } else if (time_left < 0) {
2721 printf(_("CRITICAL - Certificate '%s' expired on %s.\n"), host_name, timestamp); 2621 printf(_("CRITICAL - Certificate '%s' expired on %s.\n"), host_name, timestamp);
2722 status=STATE_CRITICAL; 2622 status = STATE_CRITICAL;
2723 } else if (days_left == 0) { 2623 } else if (days_left == 0) {
2724 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);
2725 if (days_left > days_till_exp_crit) 2626 if (days_left > days_till_exp_crit)
2726 status = STATE_WARNING; 2627 status = STATE_WARNING;
2727 else 2628 else
@@ -2732,5 +2633,5 @@ HAVE_FIRST_CERT:
2732 } 2633 }
2733 return status; 2634 return status;
2734} 2635}
2735#endif /* USE_OPENSSL */ 2636# endif /* USE_OPENSSL */
2736#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 24de2d4..037a6f7 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,1054 +107,1007 @@ static struct mount_entry *mount_list;
108 107
109/* For long options that have no equivalent short option, use a 108/* For long options that have no equivalent short option, use a
110 non-character as a pseudo short option, starting with CHAR_MAX + 1. */ 109 non-character as a pseudo short option, starting with CHAR_MAX + 1. */
111enum 110enum {
112{ 111 SYNC_OPTION = CHAR_MAX + 1,
113 SYNC_OPTION = CHAR_MAX + 1, 112 NO_SYNC_OPTION,
114 NO_SYNC_OPTION, 113 BLOCK_SIZE_OPTION
115 BLOCK_SIZE_OPTION
116}; 114};
117 115
118#ifdef _AIX 116#ifdef _AIX
119#pragma alloca 117# pragma alloca
120#endif 118#endif
121 119
122int process_arguments (int, char **); 120static int process_arguments(int /*argc*/, char ** /*argv*/);
123void print_path (const char *mypath); 121static void set_all_thresholds(struct parameter_list *path);
124void set_all_thresholds (struct parameter_list *path); 122static void print_help(void);
125int validate_arguments (uintmax_t, uintmax_t, double, double, double, double, char *); 123void print_usage(void);
126void print_help (void); 124static double calculate_percent(uintmax_t, uintmax_t);
127void print_usage (void); 125static bool stat_path(struct parameter_list *p);
128double calculate_percent(uintmax_t, uintmax_t); 126static void get_stats(struct parameter_list *p, struct fs_usage *fsp);
129bool stat_path (struct parameter_list *p); 127static void get_path_stats(struct parameter_list *p, struct fs_usage *fsp);
130void get_stats (struct parameter_list *p, struct fs_usage *fsp); 128
131void get_path_stats (struct parameter_list *p, struct fs_usage *fsp); 129static char *units;
132 130static uintmax_t mult = 1024 * 1024;
133char *exclude_device; 131static int verbose = 0;
134char *units; 132static bool erronly = false;
135uintmax_t mult = 1024 * 1024; 133static bool display_mntp = false;
136int verbose = 0; 134static bool exact_match = false;
137bool erronly = false; 135static bool ignore_missing = false;
138bool display_mntp = false; 136static bool freespace_ignore_reserved = false;
139bool exact_match = false; 137static bool display_inodes_perfdata = false;
140bool ignore_missing = false; 138static char *warn_freespace_units = NULL;
141bool freespace_ignore_reserved = false; 139static char *crit_freespace_units = NULL;
142bool display_inodes_perfdata = false; 140static char *warn_freespace_percent = NULL;
143char *warn_freespace_units = NULL; 141static char *crit_freespace_percent = NULL;
144char *crit_freespace_units = NULL; 142static char *warn_usedspace_units = NULL;
145char *warn_freespace_percent = NULL; 143static char *crit_usedspace_units = NULL;
146char *crit_freespace_percent = NULL; 144static char *warn_usedspace_percent = NULL;
147char *warn_usedspace_units = NULL; 145static char *crit_usedspace_percent = NULL;
148char *crit_usedspace_units = NULL; 146static char *warn_usedinodes_percent = NULL;
149char *warn_usedspace_percent = NULL; 147static char *crit_usedinodes_percent = NULL;
150char *crit_usedspace_percent = NULL; 148static char *warn_freeinodes_percent = NULL;
151char *warn_usedinodes_percent = NULL; 149static char *crit_freeinodes_percent = NULL;
152char *crit_usedinodes_percent = NULL; 150static bool path_selected = false;
153char *warn_freeinodes_percent = NULL; 151static bool path_ignored = false;
154char *crit_freeinodes_percent = NULL; 152static char *group = NULL;
155bool path_selected = false; 153static struct stat *stat_buf;
156bool path_ignored = false; 154static struct name_list *seen = NULL;
157char *group = NULL; 155
158struct stat *stat_buf; 156int main(int argc, char **argv) {
159struct name_list *seen = NULL; 157 int result = STATE_UNKNOWN;
160 158 int disk_result = STATE_UNKNOWN;
161 159 char *output = NULL;
162int 160 char *ignored = NULL;
163main (int argc, char **argv) 161 char *details = NULL;
164{ 162 char *perf = NULL;
165 int result = STATE_UNKNOWN; 163 char *perf_ilabel = NULL;
166 int disk_result = STATE_UNKNOWN; 164 char *preamble = " - free space:";
167 char *output; 165 char *ignored_preamble = " - ignored paths:";
168 char *ignored; 166 char *flag_header = NULL;
169 char *details; 167 int temp_result = STATE_UNKNOWN;
170 char *perf; 168
171 char *perf_ilabel; 169 struct mount_entry *me = NULL;
172 char *preamble = " - free space:"; 170 struct fs_usage fsp = {0};
173 char *ignored_preamble = " - ignored paths:"; 171 struct parameter_list *temp_list = NULL;
174 char *flag_header; 172 struct parameter_list *path = NULL;
175 int temp_result;
176
177 struct mount_entry *me;
178 struct fs_usage fsp;
179 struct parameter_list *temp_list, *path;
180 173
181#ifdef __CYGWIN__ 174#ifdef __CYGWIN__
182 char mountdir[32]; 175 char mountdir[32];
183#endif 176#endif
184 177
185 output = strdup (""); 178 output = strdup("");
186 ignored = strdup (""); 179 ignored = strdup("");
187 details = strdup (""); 180 details = strdup("");
188 perf = strdup (""); 181 perf = strdup("");
189 perf_ilabel = strdup (""); 182 perf_ilabel = strdup("");
190 stat_buf = malloc(sizeof *stat_buf); 183 stat_buf = malloc(sizeof *stat_buf);
191 184
192 setlocale (LC_ALL, ""); 185 setlocale(LC_ALL, "");
193 bindtextdomain (PACKAGE, LOCALEDIR); 186 bindtextdomain(PACKAGE, LOCALEDIR);
194 textdomain (PACKAGE); 187 textdomain(PACKAGE);
195 188
196 mount_list = read_file_system_list (0); 189 mount_list = read_file_system_list(0);
197 190
198 /* Parse extra opts if any */ 191 /* Parse extra opts if any */
199 argv = np_extra_opts (&argc, argv, progname); 192 argv = np_extra_opts(&argc, argv, progname);
200 193
201 if (process_arguments (argc, argv) == ERROR) 194 if (process_arguments(argc, argv) == ERROR)
202 usage4 (_("Could not parse arguments")); 195 usage4(_("Could not parse arguments"));
203 196
204 /* If a list of paths has not been selected, find entire 197 /* If a list of paths has not been selected, find entire
205 mount list and create list of paths 198 mount list and create list of paths
206 */ 199 */
207 if (path_selected == false && path_ignored == false) { 200 if (path_selected == false && path_ignored == false) {
208 for (me = mount_list; me; me = me->me_next) { 201 for (me = mount_list; me; me = me->me_next) {
209 if (! (path = np_find_parameter(path_select_list, me->me_mountdir))) { 202 if (!(path = np_find_parameter(path_select_list, me->me_mountdir))) {
210 path = np_add_parameter(&path_select_list, me->me_mountdir); 203 path = np_add_parameter(&path_select_list, me->me_mountdir);
211 } 204 }
212 path->best_match = me; 205 path->best_match = me;
213 path->group = group; 206 path->group = group;
214 set_all_thresholds(path); 207 set_all_thresholds(path);
215 } 208 }
216 } 209 }
217 210
218 if (path_ignored == false) { 211 if (path_ignored == false) {
219 np_set_best_match(path_select_list, mount_list, exact_match); 212 np_set_best_match(path_select_list, mount_list, exact_match);
220 } 213 }
221 214
222 /* Error if no match found for specified paths */ 215 /* Error if no match found for specified paths */
223 temp_list = path_select_list; 216 temp_list = path_select_list;
224 217
225 while (path_select_list) { 218 while (path_select_list) {
226 if (! path_select_list->best_match && ignore_missing == true) { 219 if (!path_select_list->best_match && ignore_missing == true) {
227 /* If the first element will be deleted, the temp_list must be updated with the new start address as well */ 220 /* If the first element will be deleted, the temp_list must be updated with the new start address as well */
228 if (path_select_list == temp_list) { 221 if (path_select_list == temp_list) {
229 temp_list = path_select_list->name_next; 222 temp_list = path_select_list->name_next;
230 } 223 }
231 /* Add path argument to list of ignored paths to inform about missing paths being ignored and not alerted */ 224 /* Add path argument to list of ignored paths to inform about missing paths being ignored and not alerted */
232 xasprintf (&ignored, "%s %s;", ignored, path_select_list->name); 225 xasprintf(&ignored, "%s %s;", ignored, path_select_list->name);
233 /* Delete the path from the list so that it is not stat-checked later in the code. */ 226 /* Delete the path from the list so that it is not stat-checked later in the code. */
234 path_select_list = np_del_parameter(path_select_list, path_select_list->name_prev); 227 path_select_list = np_del_parameter(path_select_list, path_select_list->name_prev);
235 } else if (! path_select_list->best_match) { 228 } else if (!path_select_list->best_match) {
236 /* Without --ignore-missing option, exit with Critical state. */ 229 /* Without --ignore-missing option, exit with Critical state. */
237 die (STATE_CRITICAL, _("DISK %s: %s not found\n"), _("CRITICAL"), path_select_list->name); 230 die(STATE_CRITICAL, _("DISK %s: %s not found\n"), _("CRITICAL"), path_select_list->name);
238 } else { 231 } else {
239 /* Continue jumping through the list */ 232 /* Continue jumping through the list */
240 path_select_list = path_select_list->name_next; 233 path_select_list = path_select_list->name_next;
241 } 234 }
242 } 235 }
243 236
244 path_select_list = temp_list; 237 path_select_list = temp_list;
245 238
246 if (! path_select_list && ignore_missing == true) { 239 if (!path_select_list && ignore_missing == true) {
247 result = STATE_OK; 240 result = STATE_OK;
248 if (verbose >= 2) { 241 if (verbose >= 2) {
249 printf ("None of the provided paths were found\n"); 242 printf("None of the provided paths were found\n");
250 } 243 }
251 } 244 }
252 245
253 /* Process for every path in list */ 246 /* Process for every path in list */
254 for (path = path_select_list; path; path=path->name_next) { 247 for (path = path_select_list; path; path = path->name_next) {
255 if (verbose >= 3 && path->freespace_percent->warning != NULL && path->freespace_percent->critical != NULL) 248 if (verbose >= 3 && path->freespace_percent->warning != NULL && path->freespace_percent->critical != NULL)
256 printf("Thresholds(pct) for %s warn: %f crit %f\n", 249 printf("Thresholds(pct) for %s warn: %f crit %f\n", path->name, path->freespace_percent->warning->end,
257 path->name, 250 path->freespace_percent->critical->end);
258 path->freespace_percent->warning->end, 251
259 path->freespace_percent->critical->end); 252 if (verbose >= 3 && path->group != NULL)
260 253 printf("Group of %s: %s\n", path->name, path->group);
261 if (verbose >= 3 && path->group != NULL) 254
262 printf("Group of %s: %s\n",path->name,path->group); 255 /* reset disk result */
263 256 disk_result = STATE_UNKNOWN;
264 /* reset disk result */ 257
265 disk_result = STATE_UNKNOWN; 258 me = path->best_match;
266 259
267 me = path->best_match; 260 if (!me) {
268 261 continue;
269 if (!me) { 262 }
270 continue;
271 }
272 263
273#ifdef __CYGWIN__ 264#ifdef __CYGWIN__
274 if (strncmp(path->name, "/cygdrive/", 10) != 0 || strlen(path->name) > 11) 265 if (strncmp(path->name, "/cygdrive/", 10) != 0 || strlen(path->name) > 11)
275 continue; 266 continue;
276 snprintf(mountdir, sizeof(mountdir), "%s:\\", me->me_mountdir + 10); 267 snprintf(mountdir, sizeof(mountdir), "%s:\\", me->me_mountdir + 10);
277 if (GetDriveType(mountdir) != DRIVE_FIXED) 268 if (GetDriveType(mountdir) != DRIVE_FIXED)
278 me->me_remote = 1; 269 me->me_remote = 1;
279#endif 270#endif
280 /* Filters */ 271 /* Filters */
281 272
282 /* Remove filesystems already seen */ 273 /* Remove filesystems already seen */
283 if (np_seen_name(seen, me->me_mountdir)) { 274 if (np_seen_name(seen, me->me_mountdir)) {
284 continue; 275 continue;
285 } 276 }
286 np_add_name(&seen, me->me_mountdir); 277 np_add_name(&seen, me->me_mountdir);
287 278
288 if (path->group == NULL) { 279 if (path->group == NULL) {
289 /* Skip remote filesystems if we're not interested in them */ 280 /* Skip remote filesystems if we're not interested in them */
290 if (me->me_remote && show_local_fs) { 281 if (me->me_remote && show_local_fs) {
291 if (stat_remote_fs) { 282 if (stat_remote_fs) {
292 if (!stat_path(path) && ignore_missing == true) { 283 if (!stat_path(path) && ignore_missing == true) {
293 result = STATE_OK; 284 result = STATE_OK;
294 xasprintf (&ignored, "%s %s;", ignored, path->name); 285 xasprintf(&ignored, "%s %s;", ignored, path->name);
295 } 286 }
296 } 287 }
297 continue; 288 continue;
298 /* Skip pseudo fs's if we haven't asked for all fs's */ 289 /* Skip pseudo fs's if we haven't asked for all fs's */
299 } else if (me->me_dummy && !show_all_fs) { 290 }
300 continue; 291 if (me->me_dummy && !show_all_fs) {
301 /* Skip excluded fstypes */ 292 continue;
302 } else if (fs_exclude_list && np_find_regmatch (fs_exclude_list, me->me_type)) { 293 /* Skip excluded fstypes */
303 continue; 294 }
304 /* Skip excluded fs's */ 295 if (fs_exclude_list && np_find_regmatch(fs_exclude_list, me->me_type)) {
305 } else if (dp_exclude_list && 296 continue;
306 (np_find_name (dp_exclude_list, me->me_devname) || 297 /* Skip excluded fs's */
307 np_find_name (dp_exclude_list, me->me_mountdir))) { 298 }
308 continue; 299 if (dp_exclude_list && (np_find_name(dp_exclude_list, me->me_devname) || np_find_name(dp_exclude_list, me->me_mountdir))) {
309 /* Skip not included fstypes */ 300 continue;
310 } else if (fs_include_list && !np_find_regmatch(fs_include_list, me->me_type)) { 301 /* Skip not included fstypes */
311 continue; 302 }
312 } 303 if (fs_include_list && !np_find_regmatch(fs_include_list, me->me_type)) {
313 } 304 continue;
314 305 }
315 if (!stat_path(path)) { 306 }
316 if (ignore_missing == true) { 307
317 result = STATE_OK; 308 if (!stat_path(path)) {
318 xasprintf (&ignored, "%s %s;", ignored, path->name); 309 if (ignore_missing == true) {
319 } 310 result = STATE_OK;
320 continue; 311 xasprintf(&ignored, "%s %s;", ignored, path->name);
321 } 312 }
322 get_fs_usage (me->me_mountdir, me->me_devname, &fsp); 313 continue;
323 314 }
324 if (fsp.fsu_blocks && strcmp ("none", me->me_mountdir)) { 315 get_fs_usage(me->me_mountdir, me->me_devname, &fsp);
325 get_stats (path, &fsp); 316
326 317 if (fsp.fsu_blocks && strcmp("none", me->me_mountdir)) {
327 if (verbose >= 3) { 318 get_stats(path, &fsp);
328 printf ("For %s, used_pct=%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
329 me->me_mountdir, 320 if (verbose >= 3) {
330 path->dused_pct, 321 printf("For %s, used_pct=%f free_pct=%f used_units=%lu free_units=%lu total_units=%lu used_inodes_pct=%f "
331 path->dfree_pct, 322 "free_inodes_pct=%f fsp.fsu_blocksize=%lu mult=%lu\n",
332 path->dused_units, 323 me->me_mountdir, path->dused_pct, path->dfree_pct, path->dused_units, path->dfree_units, path->dtotal_units,
333 path->dfree_units, 324 path->dused_inodes_percent, path->dfree_inodes_percent, fsp.fsu_blocksize, mult);
334 path->dtotal_units, 325 }
335 path->dused_inodes_percent, 326
336 path->dfree_inodes_percent, 327 /* Threshold comparisons */
337 fsp.fsu_blocksize, 328
338 mult); 329 temp_result = get_status(path->dfree_units, path->freespace_units);
339 } 330 if (verbose >= 3)
340 331 printf("Freespace_units result=%d\n", temp_result);
341 /* Threshold comparisons */ 332 disk_result = max_state(disk_result, temp_result);
342
343 temp_result = get_status(path->dfree_units, path->freespace_units);
344 if (verbose >=3) printf("Freespace_units result=%d\n", temp_result);
345 disk_result = max_state( disk_result, temp_result );
346
347 temp_result = get_status(path->dfree_pct, path->freespace_percent);
348 if (verbose >=3) printf("Freespace%% result=%d\n", temp_result);
349 disk_result = max_state( disk_result, temp_result );
350
351 temp_result = get_status(path->dused_units, path->usedspace_units);
352 if (verbose >=3) printf("Usedspace_units result=%d\n", temp_result);
353 disk_result = max_state( disk_result, temp_result );
354
355 temp_result = get_status(path->dused_pct, path->usedspace_percent);
356 if (verbose >=3) printf("Usedspace_percent result=%d\n", temp_result);
357 disk_result = max_state( disk_result, temp_result );
358
359 temp_result = get_status(path->dused_inodes_percent, path->usedinodes_percent);
360 if (verbose >=3) printf("Usedinodes_percent result=%d\n", temp_result);
361 disk_result = max_state( disk_result, temp_result );
362
363 temp_result = get_status(path->dfree_inodes_percent, path->freeinodes_percent);
364 if (verbose >=3) printf("Freeinodes_percent result=%d\n", temp_result);
365 disk_result = max_state( disk_result, temp_result );
366
367 result = max_state(result, disk_result);
368
369 /* What a mess of units. The output shows free space, the perf data shows used space. Yikes!
370 Hack here. Trying to get warn/crit levels from freespace_(units|percent) for perf
371 data. Assumption that start=0. Roll on new syntax...
372 */
373
374 /* *_high_tide must be reinitialized at each run */
375 uint64_t warning_high_tide = UINT64_MAX;
376
377 if (path->freespace_units->warning != NULL) {
378 warning_high_tide = (path->dtotal_units - path->freespace_units->warning->end) * mult;
379 }
380 if (path->freespace_percent->warning != NULL) {
381 warning_high_tide = min( warning_high_tide, (uint64_t)((1.0 - path->freespace_percent->warning->end/100) * (path->dtotal_units * mult)) );
382 }
383
384 uint64_t critical_high_tide = UINT64_MAX;
385
386 if (path->freespace_units->critical != NULL) {
387 critical_high_tide = (path->dtotal_units - path->freespace_units->critical->end) * mult;
388 }
389 if (path->freespace_percent->critical != NULL) {
390 critical_high_tide = min( critical_high_tide, (uint64_t)((1.0 - path->freespace_percent->critical->end/100) * (path->dtotal_units * mult)) );
391 }
392
393 /* Nb: *_high_tide are unset when == UINT64_MAX */
394 xasprintf (&perf, "%s %s", perf,
395 perfdata_uint64 (
396 (!strcmp(me->me_mountdir, "none") || display_mntp) ? me->me_devname : me->me_mountdir,
397 path->dused_units * mult, "B",
398 (warning_high_tide == UINT64_MAX ? false : true), warning_high_tide,
399 (critical_high_tide == UINT64_MAX ? false : true), critical_high_tide,
400 true, 0,
401 true, path->dtotal_units * mult));
402
403 if (display_inodes_perfdata) {
404 /* *_high_tide must be reinitialized at each run */
405 warning_high_tide = UINT64_MAX;
406 critical_high_tide = UINT64_MAX;
407
408 if (path->freeinodes_percent->warning != NULL) {
409 warning_high_tide = (uint64_t) fabs( min( (double) warning_high_tide, (double) (1.0 - path->freeinodes_percent->warning->end/100)*path->inodes_total ));
410 }
411 if (path->freeinodes_percent->critical != NULL) {
412 critical_high_tide = (uint64_t) fabs( min( (double) critical_high_tide, (double) (1.0 - path->freeinodes_percent->critical->end/100)*path->inodes_total ));
413 }
414
415 xasprintf (&perf_ilabel, "%s (inodes)", (!strcmp(me->me_mountdir, "none") || display_mntp) ? me->me_devname : me->me_mountdir);
416 /* Nb: *_high_tide are unset when == UINT64_MAX */
417 xasprintf (&perf, "%s %s", perf,
418 perfdata_uint64 (perf_ilabel,
419 path->inodes_used, "",
420 (warning_high_tide != UINT64_MAX ? true : false), warning_high_tide,
421 (critical_high_tide != UINT64_MAX ? true : false), critical_high_tide,
422 true, 0,
423 true, path->inodes_total));
424 }
425
426 if (disk_result==STATE_OK && erronly && !verbose)
427 continue;
428
429 if(disk_result && verbose >= 1) {
430 xasprintf(&flag_header, " %s [", state_text (disk_result));
431 } else {
432 xasprintf(&flag_header, "");
433 }
434 xasprintf (&output, "%s%s %s %llu%s (%.1f%%",
435 output, flag_header,
436 (!strcmp(me->me_mountdir, "none") || display_mntp) ? me->me_devname : me->me_mountdir,
437 path->dfree_units,
438 units,
439 path->dfree_pct);
440 if (path->dused_inodes_percent < 0) {
441 xasprintf(&output, "%s inode=-)%s;", output, (disk_result ? "]" : ""));
442 } else {
443 xasprintf(&output, "%s inode=%.0f%%)%s;", output, path->dfree_inodes_percent, ((disk_result && verbose >= 1) ? "]" : ""));
444 }
445 free(flag_header);
446 }
447 }
448
449 if (verbose >= 2)
450 xasprintf (&output, "%s%s", output, details);
451
452 if (strcmp(output, "") == 0 && ! erronly) {
453 preamble = "";
454 xasprintf (&output, " - No disks were found for provided parameters");
455 }
456
457 printf ("DISK %s%s%s%s%s|%s\n", state_text (result), ((erronly && result==STATE_OK)) ? "" : preamble, output, (strcmp(ignored, "") == 0) ? "" : ignored_preamble, ignored, perf);
458 return result;
459}
460 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}
461 449
462double calculate_percent(uintmax_t value, uintmax_t total) { 450double calculate_percent(uintmax_t value, uintmax_t total) {
463 double pct = -1; 451 double pct = -1;
464 if(value <= DBL_MAX && total != 0) { 452 if (value <= DBL_MAX && total != 0) {
465 pct = (double)value / total * 100.0; 453 pct = (double)value / total * 100.0;
466 } 454 }
467 return pct; 455 return pct;
468} 456}
469 457
470/* process command-line arguments */ 458/* process command-line arguments */
471int 459int process_arguments(int argc, char **argv) {
472process_arguments (int argc, char **argv) 460 int c;
473{ 461 int err;
474 int c, err; 462 struct parameter_list *se;
475 struct parameter_list *se; 463 struct parameter_list *temp_list = NULL;
476 struct parameter_list *temp_list = NULL, *previous = NULL; 464 struct parameter_list *previous = NULL;
477 struct mount_entry *me; 465 struct mount_entry *me;
478 regex_t re; 466 regex_t re;
479 int cflags = REG_NOSUB | REG_EXTENDED; 467 int cflags = REG_NOSUB | REG_EXTENDED;
480 int default_cflags = cflags; 468 int default_cflags = cflags;
481 char errbuf[MAX_INPUT_BUFFER]; 469 char errbuf[MAX_INPUT_BUFFER];
482 int fnd = 0; 470 int fnd = 0;
483 471
484 int option = 0; 472 int option = 0;
485 static struct option longopts[] = { 473 static struct option longopts[] = {{"timeout", required_argument, 0, 't'},
486 {"timeout", required_argument, 0, 't'}, 474 {"warning", required_argument, 0, 'w'},
487 {"warning", required_argument, 0, 'w'}, 475 {"critical", required_argument, 0, 'c'},
488 {"critical", required_argument, 0, 'c'}, 476 {"iwarning", required_argument, 0, 'W'},
489 {"iwarning", required_argument, 0, 'W'}, 477 /* Dang, -C is taken. We might want to reshuffle this. */
490 /* Dang, -C is taken. We might want to reshuffle this. */ 478 {"icritical", required_argument, 0, 'K'},
491 {"icritical", required_argument, 0, 'K'}, 479 {"kilobytes", no_argument, 0, 'k'},
492 {"kilobytes", no_argument, 0, 'k'}, 480 {"megabytes", no_argument, 0, 'm'},
493 {"megabytes", no_argument, 0, 'm'}, 481 {"units", required_argument, 0, 'u'},
494 {"units", required_argument, 0, 'u'}, 482 {"path", required_argument, 0, 'p'},
495 {"path", required_argument, 0, 'p'}, 483 {"partition", required_argument, 0, 'p'},
496 {"partition", required_argument, 0, 'p'}, 484 {"exclude_device", required_argument, 0, 'x'},
497 {"exclude_device", required_argument, 0, 'x'}, 485 {"exclude-type", required_argument, 0, 'X'},
498 {"exclude-type", required_argument, 0, 'X'}, 486 {"include-type", required_argument, 0, 'N'},
499 {"include-type", required_argument, 0, 'N'}, 487 {"group", required_argument, 0, 'g'},
500 {"group", required_argument, 0, 'g'}, 488 {"eregi-path", required_argument, 0, 'R'},
501 {"eregi-path", required_argument, 0, 'R'}, 489 {"eregi-partition", required_argument, 0, 'R'},
502 {"eregi-partition", required_argument, 0, 'R'}, 490 {"ereg-path", required_argument, 0, 'r'},
503 {"ereg-path", required_argument, 0, 'r'}, 491 {"ereg-partition", required_argument, 0, 'r'},
504 {"ereg-partition", required_argument, 0, 'r'}, 492 {"freespace-ignore-reserved", no_argument, 0, 'f'},
505 {"freespace-ignore-reserved", no_argument, 0, 'f'}, 493 {"ignore-ereg-path", required_argument, 0, 'i'},
506 {"ignore-ereg-path", required_argument, 0, 'i'}, 494 {"ignore-ereg-partition", required_argument, 0, 'i'},
507 {"ignore-ereg-partition", required_argument, 0, 'i'}, 495 {"ignore-eregi-path", required_argument, 0, 'I'},
508 {"ignore-eregi-path", required_argument, 0, 'I'}, 496 {"ignore-eregi-partition", required_argument, 0, 'I'},
509 {"ignore-eregi-partition", required_argument, 0, 'I'}, 497 {"ignore-missing", no_argument, 0, 'n'},
510 {"ignore-missing", no_argument, 0, 'n'}, 498 {"local", no_argument, 0, 'l'},
511 {"local", no_argument, 0, 'l'}, 499 {"stat-remote-fs", no_argument, 0, 'L'},
512 {"stat-remote-fs", no_argument, 0, 'L'}, 500 {"iperfdata", no_argument, 0, 'P'},
513 {"iperfdata", no_argument, 0, 'P'}, 501 {"mountpoint", no_argument, 0, 'M'},
514 {"mountpoint", no_argument, 0, 'M'}, 502 {"errors-only", no_argument, 0, 'e'},
515 {"errors-only", no_argument, 0, 'e'}, 503 {"exact-match", no_argument, 0, 'E'},
516 {"exact-match", no_argument, 0, 'E'}, 504 {"all", no_argument, 0, 'A'},
517 {"all", no_argument, 0, 'A'}, 505 {"verbose", no_argument, 0, 'v'},
518 {"verbose", no_argument, 0, 'v'}, 506 {"quiet", no_argument, 0, 'q'},
519 {"quiet", no_argument, 0, 'q'}, 507 {"clear", no_argument, 0, 'C'},
520 {"clear", no_argument, 0, 'C'}, 508 {"version", no_argument, 0, 'V'},
521 {"version", no_argument, 0, 'V'}, 509 {"help", no_argument, 0, 'h'},
522 {"help", no_argument, 0, 'h'}, 510 {0, 0, 0, 0}};
523 {0, 0, 0, 0} 511
524 }; 512 if (argc < 2)
525 513 return ERROR;
526 if (argc < 2) 514
527 return ERROR; 515 np_add_regex(&fs_exclude_list, "iso9660", REG_EXTENDED);
528 516
529 np_add_regex(&fs_exclude_list, "iso9660", REG_EXTENDED); 517 for (c = 1; c < argc; c++)
530 518 if (strcmp("-to", argv[c]) == 0)
531 for (c = 1; c < argc; c++) 519 strcpy(argv[c], "-t");
532 if (strcmp ("-to", argv[c]) == 0) 520
533 strcpy (argv[c], "-t"); 521 while (1) {
534 522 c = getopt_long(argc, argv, "+?VqhvefCt:c:w:K:W:u:p:x:X:N:mklLPg:R:r:i:I:MEAn", longopts, &option);
535 while (1) { 523
536 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)
537 525 break;
538 if (c == -1 || c == EOF) 526
539 break; 527 switch (c) {
540 528 case 't': /* timeout period */
541 switch (c) { 529 if (is_integer(optarg)) {
542 case 't': /* timeout period */ 530 timeout_interval = atoi(optarg);
543 if (is_integer (optarg)) { 531 break;
544 timeout_interval = atoi (optarg); 532 } else {
545 break; 533 usage2(_("Timeout interval must be a positive integer"), optarg);
546 } 534 }
547 else { 535
548 usage2 (_("Timeout interval must be a positive integer"), optarg); 536 /* See comments for 'c' */
549 } 537 case 'w': /* warning threshold */
550
551 /* See comments for 'c' */
552 case 'w': /* warning threshold */
553 if (!is_percentage_expression(optarg) && !is_numeric(optarg)) { 538 if (!is_percentage_expression(optarg) && !is_numeric(optarg)) {
554 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);
555 } 540 }
556 541
557 if (strstr(optarg, "%")) { 542 if (strstr(optarg, "%")) {
558 if (*optarg == '@') { 543 if (*optarg == '@') {
559 warn_freespace_percent = optarg; 544 warn_freespace_percent = optarg;
560 } else { 545 } else {
561 xasprintf(&warn_freespace_percent, "@%s", optarg); 546 xasprintf(&warn_freespace_percent, "@%s", optarg);
562 } 547 }
563 } else { 548 } else {
564 if (*optarg == '@') { 549 if (*optarg == '@') {
565 warn_freespace_units = optarg; 550 warn_freespace_units = optarg;
566 } else { 551 } else {
567 xasprintf(&warn_freespace_units, "@%s", optarg); 552 xasprintf(&warn_freespace_units, "@%s", optarg);
568 } 553 }
569 } 554 }
570 break; 555 break;
571 556
572 /* Awful mistake where the range values do not make sense. Normally, 557 /* Awful mistake where the range values do not make sense. Normally,
573 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
574 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
575 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
576 */ 561 */
577 case 'c': /* critical threshold */ 562 case 'c': /* critical threshold */
578 if (!is_percentage_expression(optarg) && !is_numeric(optarg)) { 563 if (!is_percentage_expression(optarg) && !is_numeric(optarg)) {
579 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);
580 } 565 }
581 566
582 if (strstr(optarg, "%")) { 567 if (strstr(optarg, "%")) {
583 if (*optarg == '@') { 568 if (*optarg == '@') {
584 crit_freespace_percent = optarg; 569 crit_freespace_percent = optarg;
585 } else { 570 } else {
586 xasprintf(&crit_freespace_percent, "@%s", optarg); 571 xasprintf(&crit_freespace_percent, "@%s", optarg);
587 } 572 }
588 } else { 573 } else {
589 if (*optarg == '@') { 574 if (*optarg == '@') {
590 crit_freespace_units = optarg; 575 crit_freespace_units = optarg;
591 } else { 576 } else {
592 xasprintf(&crit_freespace_units, "@%s", optarg); 577 xasprintf(&crit_freespace_units, "@%s", optarg);
593 } 578 }
594 } 579 }
595 break; 580 break;
596
597 case 'W': /* warning inode threshold */
598 if (*optarg == '@') {
599 warn_freeinodes_percent = optarg;
600 } else {
601 xasprintf(&warn_freeinodes_percent, "@%s", optarg);
602 }
603 break;
604 case 'K': /* critical inode threshold */
605 if (*optarg == '@') {
606 crit_freeinodes_percent = optarg;
607 } else {
608 xasprintf(&crit_freeinodes_percent, "@%s", optarg);
609 }
610 break;
611 case 'u':
612 if (units)
613 free(units);
614 if (! strcasecmp (optarg, "bytes")) {
615 mult = (uintmax_t)1;
616 units = strdup ("B");
617 } else if (!strcmp(optarg, "KiB")) {
618 mult = (uintmax_t)1024;
619 units = strdup ("KiB");
620 } else if (! strcmp (optarg, "kB")) {
621 mult = (uintmax_t)1000;
622 units = strdup ("kB");
623 } else if (!strcmp(optarg, "MiB")) {
624 mult = (uintmax_t)1024 * 1024;
625 units = strdup ("MiB");
626 } else if (! strcmp (optarg, "MB")) {
627 mult = (uintmax_t)1000 * 1000;
628 units = strdup ("MB");
629 } else if (!strcmp(optarg, "GiB")) {
630 mult = (uintmax_t)1024 * 1024 * 1024;
631 units = strdup ("GiB");
632 } else if (! strcmp (optarg, "GB")){
633 mult = (uintmax_t)1000 * 1000 * 1000;
634 units = strdup ("GB");
635 } else if (!strcmp(optarg, "TiB")) {
636 mult = (uintmax_t)1024 * 1024 * 1024 * 1024;
637 units = strdup ("TiB");
638 } else if (! strcmp (optarg, "TB")) {
639 mult = (uintmax_t)1000 * 1000 * 1000 * 1000;
640 units = strdup ("TB");
641 } else if (!strcmp(optarg, "PiB")) {
642 mult = (uintmax_t)1024 * 1024 * 1024 * 1024 * 1024;
643 units = strdup ("PiB");
644 } else if (! strcmp (optarg, "PB")){
645 mult = (uintmax_t)1000 * 1000 * 1000 * 1000 * 1000;
646 units = strdup ("PB");
647 } else {
648 die (STATE_UNKNOWN, _("unit type %s not known\n"), optarg);
649 }
650 if (units == NULL)
651 die (STATE_UNKNOWN, _("failed allocating storage for '%s'\n"), "units");
652 break;
653 case 'k': /* display mountpoint */
654 mult = 1024;
655 if (units)
656 free(units);
657 units = strdup ("kiB");
658 break;
659 case 'm': /* display mountpoint */
660 mult = 1024 * 1024;
661 if (units)
662 free(units);
663 units = strdup ("MiB");
664 break;
665 case 'L':
666 stat_remote_fs = 1;
667 /* fallthrough */
668 case 'l':
669 show_local_fs = 1;
670 break;
671 case 'P':
672 display_inodes_perfdata = 1;
673 break;
674 case 'p': /* select path */
675 if (! (warn_freespace_units || crit_freespace_units || warn_freespace_percent ||
676 crit_freespace_percent || warn_usedspace_units || crit_usedspace_units ||
677 warn_usedspace_percent || crit_usedspace_percent || warn_usedinodes_percent ||
678 crit_usedinodes_percent || warn_freeinodes_percent || crit_freeinodes_percent )) {
679 die (STATE_UNKNOWN, "DISK %s: %s", _("UNKNOWN"), _("Must set a threshold value before using -p\n"));
680 }
681
682 /* add parameter if not found. overwrite thresholds if path has already been added */
683 if (! (se = np_find_parameter(path_select_list, optarg))) {
684 se = np_add_parameter(&path_select_list, optarg);
685
686 if (stat(optarg, &stat_buf[0]) && ignore_missing == true) {
687 path_ignored = true;
688 break;
689 }
690 }
691 se->group = group;
692 set_all_thresholds(se);
693
694 /* With autofs, it is required to stat() the path before re-populating the mount_list */
695 if (!stat_path(se)) {
696 break;
697 }
698 /* NB: We can't free the old mount_list "just like that": both list pointers and struct
699 * pointers are copied around. One of the reason it wasn't done yet is that other parts
700 * of check_disk need the same kind of cleanup so it'd better be done as a whole */
701 mount_list = read_file_system_list (0);
702 np_set_best_match(se, mount_list, exact_match);
703
704 path_selected = true;
705 break;
706 case 'x': /* exclude path or partition */
707 np_add_name(&dp_exclude_list, optarg);
708 break;
709 case 'X': /* exclude file system type */
710 err = np_add_regex(&fs_exclude_list, optarg, REG_EXTENDED);
711 if (err != 0) {
712 regerror (err, &fs_exclude_list->regex, errbuf, MAX_INPUT_BUFFER);
713 die (STATE_UNKNOWN, "DISK %s: %s - %s\n",_("UNKNOWN"), _("Could not compile regular expression"), errbuf);
714 }
715 break;
716 case 'N': /* include file system type */
717 err = np_add_regex(&fs_include_list, optarg, REG_EXTENDED);
718 if (err != 0) {
719 regerror (err, &fs_exclude_list->regex, errbuf, MAX_INPUT_BUFFER);
720 die (STATE_UNKNOWN, "DISK %s: %s - %s\n",_("UNKNOWN"), _("Could not compile regular expression"), errbuf);
721 }
722 break;
723 case 'v': /* verbose */
724 verbose++;
725 break;
726 case 'q': /* TODO: this function should eventually go away (removed 2007-09-20) */
727 /* verbose--; **replaced by line below**. -q was only a broken way of implementing -e */
728 erronly = true;
729 break;
730 case 'e':
731 erronly = true;
732 break;
733 case 'E':
734 if (path_selected)
735 die (STATE_UNKNOWN, "DISK %s: %s", _("UNKNOWN"), _("Must set -E before selecting paths\n"));
736 exact_match = true;
737 break;
738 case 'f':
739 freespace_ignore_reserved = true;
740 break;
741 case 'g':
742 if (path_selected)
743 die (STATE_UNKNOWN, "DISK %s: %s", _("UNKNOWN"), _("Must set group value before selecting paths\n"));
744 group = optarg;
745 break;
746 case 'I':
747 cflags |= REG_ICASE;
748 // Intentional fallthrough
749 case 'i':
750 if (!path_selected)
751 die (STATE_UNKNOWN, "DISK %s: %s\n", _("UNKNOWN"), _("Paths need to be selected before using -i/-I. Use -A to select all paths explicitly"));
752 err = regcomp(&re, optarg, cflags);
753 if (err != 0) {
754 regerror (err, &re, errbuf, MAX_INPUT_BUFFER);
755 die (STATE_UNKNOWN, "DISK %s: %s - %s\n",_("UNKNOWN"), _("Could not compile regular expression"), errbuf);
756 }
757
758 temp_list = path_select_list;
759
760 previous = NULL;
761 while (temp_list) {
762 if (temp_list->best_match) {
763 if (np_regex_match_mount_entry(temp_list->best_match, &re)) {
764
765 if (verbose >=3)
766 printf("ignoring %s matching regex\n", temp_list->name);
767
768 temp_list = np_del_parameter(temp_list, previous);
769 /* pointer to first element needs to be updated if first item gets deleted */
770 if (previous == NULL)
771 path_select_list = temp_list;
772 } else {
773 previous = temp_list;
774 temp_list = temp_list->name_next;
775 }
776 } else {
777 previous = temp_list;
778 temp_list = temp_list->name_next;
779 }
780 }
781
782
783 cflags = default_cflags;
784 break;
785
786 case 'n':
787 ignore_missing = true;
788 break;
789 case 'A':
790 optarg = strdup(".*");
791 // Intentional fallthrough
792 case 'R':
793 cflags |= REG_ICASE;
794 // Intentional fallthrough
795 case 'r':
796 if (! (warn_freespace_units || crit_freespace_units || warn_freespace_percent ||
797 crit_freespace_percent || warn_usedspace_units || crit_usedspace_units ||
798 warn_usedspace_percent || crit_usedspace_percent || warn_usedinodes_percent ||
799 crit_usedinodes_percent || warn_freeinodes_percent || crit_freeinodes_percent )) {
800 die (STATE_UNKNOWN, "DISK %s: %s", _("UNKNOWN"), _("Must set a threshold value before using -r/-R/-A (--ereg-path/--eregi-path/--all)\n"));
801 }
802
803 err = regcomp(&re, optarg, cflags);
804 if (err != 0) {
805 regerror (err, &re, errbuf, MAX_INPUT_BUFFER);
806 die (STATE_UNKNOWN, "DISK %s: %s - %s\n",_("UNKNOWN"), _("Could not compile regular expression"), errbuf);
807 }
808
809 for (me = mount_list; me; me = me->me_next) {
810 if (np_regex_match_mount_entry(me, &re)) {
811 fnd = true;
812 if (verbose >= 3)
813 printf("%s %s matching expression %s\n", me->me_devname, me->me_mountdir, optarg);
814
815 /* add parameter if not found. overwrite thresholds if path has already been added */
816 if (! (se = np_find_parameter(path_select_list, me->me_mountdir))) {
817 se = np_add_parameter(&path_select_list, me->me_mountdir);
818 }
819 se->group = group;
820 set_all_thresholds(se);
821 }
822 }
823
824 if (!fnd && ignore_missing == true) {
825 path_ignored = true;
826 path_selected = true;
827 break;
828 } else if (!fnd)
829 die (STATE_UNKNOWN, "DISK %s: %s - %s\n",_("UNKNOWN"),
830 _("Regular expression did not match any path or disk"), optarg);
831
832 fnd = false;
833 path_selected = true;
834 np_set_best_match(path_select_list, mount_list, exact_match);
835 cflags = default_cflags;
836
837 break;
838 case 'M': /* display mountpoint */
839 display_mntp = true;
840 break;
841 case 'C':
842 /* add all mount entries to path_select list if no partitions have been explicitly defined using -p */
843 if (path_selected == false) {
844 struct parameter_list *path;
845 for (me = mount_list; me; me = me->me_next) {
846 if (! (path = np_find_parameter(path_select_list, me->me_mountdir)))
847 path = np_add_parameter(&path_select_list, me->me_mountdir);
848 path->best_match = me;
849 path->group = group;
850 set_all_thresholds(path);
851 }
852 }
853 warn_freespace_units = NULL;
854 crit_freespace_units = NULL;
855 warn_usedspace_units = NULL;
856 crit_usedspace_units = NULL;
857 warn_freespace_percent = NULL;
858 crit_freespace_percent = NULL;
859 warn_usedspace_percent = NULL;
860 crit_usedspace_percent = NULL;
861 warn_usedinodes_percent = NULL;
862 crit_usedinodes_percent = NULL;
863 warn_freeinodes_percent = NULL;
864 crit_freeinodes_percent = NULL;
865
866 path_selected = false;
867 group = NULL;
868 break;
869 case 'V': /* version */
870 print_revision (progname, NP_VERSION);
871 exit (STATE_UNKNOWN);
872 case 'h': /* help */
873 print_help ();
874 exit (STATE_UNKNOWN);
875 case '?': /* help */
876 usage (_("Unknown argument"));
877 }
878 }
879
880 /* Support for "check_disk warn crit [fs]" with thresholds at used% level */
881 c = optind;
882 if (warn_usedspace_percent == NULL && argc > c && is_intnonneg (argv[c]))
883 warn_usedspace_percent = argv[c++];
884
885 if (crit_usedspace_percent == NULL && argc > c && is_intnonneg (argv[c]))
886 crit_usedspace_percent = argv[c++];
887
888 if (argc > c) {
889 se = np_add_parameter(&path_select_list, strdup(argv[c++]));
890 path_selected = true;
891 set_all_thresholds(se);
892 }
893
894 if (units == NULL) {
895 units = strdup ("MiB");
896 mult = (uintmax_t)1024 * 1024;
897 }
898
899 return true;
900}
901 581
582 case 'W': /* warning inode threshold */
583 if (*optarg == '@') {
584 warn_freeinodes_percent = optarg;
585 } else {
586 xasprintf(&warn_freeinodes_percent, "@%s", optarg);
587 }
588 break;
589 case 'K': /* critical inode threshold */
590 if (*optarg == '@') {
591 crit_freeinodes_percent = optarg;
592 } else {
593 xasprintf(&crit_freeinodes_percent, "@%s", optarg);
594 }
595 break;
596 case 'u':
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 }
902 665
666 /* add parameter if not found. overwrite thresholds if path has already been added */
667 if (!(se = np_find_parameter(path_select_list, optarg))) {
668 se = np_add_parameter(&path_select_list, optarg);
903 669
904void 670 if (stat(optarg, &stat_buf[0]) && ignore_missing == true) {
905print_path (const char *mypath) 671 path_ignored = true;
906{ 672 break;
907 if (mypath == NULL) 673 }
908 printf ("\n"); 674 }
909 else 675 se->group = group;
910 printf (_(" for %s\n"), mypath); 676 set_all_thresholds(se);
911} 677
678 /* With autofs, it is required to stat() the path before re-populating the mount_list */
679 if (!stat_path(se)) {
680 break;
681 }
682 /* NB: We can't free the old mount_list "just like that": both list pointers and struct
683 * pointers are copied around. One of the reason it wasn't done yet is that other parts
684 * of check_disk need the same kind of cleanup so it'd better be done as a whole */
685 mount_list = read_file_system_list(0);
686 np_set_best_match(se, mount_list, exact_match);
687
688 path_selected = true;
689 break;
690 case 'x': /* exclude path or partition */
691 np_add_name(&dp_exclude_list, optarg);
692 break;
693 case 'X': /* exclude file system type */
694 err = np_add_regex(&fs_exclude_list, optarg, REG_EXTENDED);
695 if (err != 0) {
696 regerror(err, &fs_exclude_list->regex, errbuf, MAX_INPUT_BUFFER);
697 die(STATE_UNKNOWN, "DISK %s: %s - %s\n", _("UNKNOWN"), _("Could not compile regular expression"), errbuf);
698 }
699 break;
700 case 'N': /* include file system type */
701 err = np_add_regex(&fs_include_list, optarg, REG_EXTENDED);
702 if (err != 0) {
703 regerror(err, &fs_exclude_list->regex, errbuf, MAX_INPUT_BUFFER);
704 die(STATE_UNKNOWN, "DISK %s: %s - %s\n", _("UNKNOWN"), _("Could not compile regular expression"), errbuf);
705 }
706 break;
707 case 'v': /* verbose */
708 verbose++;
709 break;
710 case 'q': /* TODO: this function should eventually go away (removed 2007-09-20) */
711 /* verbose--; **replaced by line below**. -q was only a broken way of implementing -e */
712 erronly = true;
713 break;
714 case 'e':
715 erronly = true;
716 break;
717 case 'E':
718 if (path_selected)
719 die(STATE_UNKNOWN, "DISK %s: %s", _("UNKNOWN"), _("Must set -E before selecting paths\n"));
720 exact_match = true;
721 break;
722 case 'f':
723 freespace_ignore_reserved = true;
724 break;
725 case 'g':
726 if (path_selected)
727 die(STATE_UNKNOWN, "DISK %s: %s", _("UNKNOWN"), _("Must set group value before selecting paths\n"));
728 group = optarg;
729 break;
730 case 'I':
731 cflags |= REG_ICASE;
732 // Intentional fallthrough
733 case 'i':
734 if (!path_selected)
735 die(STATE_UNKNOWN, "DISK %s: %s\n", _("UNKNOWN"),
736 _("Paths need to be selected before using -i/-I. Use -A to select all paths explicitly"));
737 err = regcomp(&re, optarg, cflags);
738 if (err != 0) {
739 regerror(err, &re, errbuf, MAX_INPUT_BUFFER);
740 die(STATE_UNKNOWN, "DISK %s: %s - %s\n", _("UNKNOWN"), _("Could not compile regular expression"), errbuf);
741 }
912 742
743 temp_list = path_select_list;
744
745 previous = NULL;
746 while (temp_list) {
747 if (temp_list->best_match) {
748 if (np_regex_match_mount_entry(temp_list->best_match, &re)) {
749
750 if (verbose >= 3)
751 printf("ignoring %s matching regex\n", temp_list->name);
752
753 temp_list = np_del_parameter(temp_list, previous);
754 /* pointer to first element needs to be updated if first item gets deleted */
755 if (previous == NULL)
756 path_select_list = temp_list;
757 } else {
758 previous = temp_list;
759 temp_list = temp_list->name_next;
760 }
761 } else {
762 previous = temp_list;
763 temp_list = temp_list->name_next;
764 }
765 }
913 766
914void 767 cflags = default_cflags;
915set_all_thresholds (struct parameter_list *path) 768 break;
916{ 769
917 if (path->freespace_units != NULL) free(path->freespace_units); 770 case 'n':
918 set_thresholds(&path->freespace_units, warn_freespace_units, crit_freespace_units); 771 ignore_missing = true;
919 if (path->freespace_percent != NULL) free (path->freespace_percent); 772 break;
920 set_thresholds(&path->freespace_percent, warn_freespace_percent, crit_freespace_percent); 773 case 'A':
921 if (path->usedspace_units != NULL) free (path->usedspace_units); 774 optarg = strdup(".*");
922 set_thresholds(&path->usedspace_units, warn_usedspace_units, crit_usedspace_units); 775 // Intentional fallthrough
923 if (path->usedspace_percent != NULL) free (path->usedspace_percent); 776 case 'R':
924 set_thresholds(&path->usedspace_percent, warn_usedspace_percent, crit_usedspace_percent); 777 cflags |= REG_ICASE;
925 if (path->usedinodes_percent != NULL) free (path->usedinodes_percent); 778 // Intentional fallthrough
926 set_thresholds(&path->usedinodes_percent, warn_usedinodes_percent, crit_usedinodes_percent); 779 case 'r':
927 if (path->freeinodes_percent != NULL) free (path->freeinodes_percent); 780 if (!(warn_freespace_units || crit_freespace_units || warn_freespace_percent || crit_freespace_percent ||
928 set_thresholds(&path->freeinodes_percent, warn_freeinodes_percent, crit_freeinodes_percent); 781 warn_usedspace_units || crit_usedspace_units || warn_usedspace_percent || crit_usedspace_percent ||
929} 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 }
930 786
931void 787 err = regcomp(&re, optarg, cflags);
932print_help (void) 788 if (err != 0) {
933{ 789 regerror(err, &re, errbuf, MAX_INPUT_BUFFER);
934 print_revision (progname, NP_VERSION); 790 die(STATE_UNKNOWN, "DISK %s: %s - %s\n", _("UNKNOWN"), _("Could not compile regular expression"), errbuf);
935 791 }
936 printf ("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n");
937 printf (COPYRIGHT, copyright, email);
938
939 printf ("%s\n", _("This plugin checks the amount of used disk space on a mounted file system"));
940 printf ("%s\n", _("and generates an alert if free space is less than one of the threshold values"));
941
942 printf ("\n\n");
943
944 print_usage ();
945
946 printf (UT_HELP_VRSN);
947 printf (UT_EXTRA_OPTS);
948
949 printf (" %s\n", "-w, --warning=INTEGER");
950 printf (" %s\n", _("Exit with WARNING status if less than INTEGER units of disk are free"));
951 printf (" %s\n", "-w, --warning=PERCENT%");
952 printf (" %s\n", _("Exit with WARNING status if less than PERCENT of disk space is free"));
953 printf (" %s\n", "-c, --critical=INTEGER");
954 printf (" %s\n", _("Exit with CRITICAL status if less than INTEGER units of disk are free"));
955 printf (" %s\n", "-c, --critical=PERCENT%");
956 printf (" %s\n", _("Exit with CRITICAL status if less than PERCENT of disk space is free"));
957 printf (" %s\n", "-W, --iwarning=PERCENT%");
958 printf (" %s\n", _("Exit with WARNING status if less than PERCENT of inode space is free"));
959 printf (" %s\n", "-K, --icritical=PERCENT%");
960 printf (" %s\n", _("Exit with CRITICAL status if less than PERCENT of inode space is free"));
961 printf (" %s\n", "-p, --path=PATH, --partition=PARTITION");
962 printf (" %s\n", _("Mount point or block device as emitted by the mount(8) command (may be repeated)"));
963 printf (" %s\n", "-x, --exclude_device=PATH <STRING>");
964 printf (" %s\n", _("Ignore device (only works if -p unspecified)"));
965 printf (" %s\n", "-C, --clear");
966 printf (" %s\n", _("Clear thresholds"));
967 printf (" %s\n", "-E, --exact-match");
968 printf (" %s\n", _("For paths or partitions specified with -p, only check for exact paths"));
969 printf (" %s\n", "-e, --errors-only");
970 printf (" %s\n", _("Display only devices/mountpoints with errors"));
971 printf (" %s\n", "-f, --freespace-ignore-reserved");
972 printf (" %s\n", _("Don't account root-reserved blocks into freespace in perfdata"));
973 printf (" %s\n", "-P, --iperfdata");
974 printf (" %s\n", _("Display inode usage in perfdata"));
975 printf (" %s\n", "-g, --group=NAME");
976 printf (" %s\n", _("Group paths. Thresholds apply to (free-)space of all partitions together"));
977 printf (" %s\n", "-k, --kilobytes");
978 printf (" %s\n", _("Same as '--units kB'"));
979 printf (" %s\n", "-l, --local");
980 printf (" %s\n", _("Only check local filesystems"));
981 printf (" %s\n", "-L, --stat-remote-fs");
982 printf (" %s\n", _("Only check local filesystems against thresholds. Yet call stat on remote filesystems"));
983 printf (" %s\n", _("to test if they are accessible (e.g. to detect Stale NFS Handles)"));
984 printf (" %s\n", "-M, --mountpoint");
985 printf (" %s\n", _("Display the (block) device instead of the mount point"));
986 printf (" %s\n", "-m, --megabytes");
987 printf (" %s\n", _("Same as '--units MB'"));
988 printf (" %s\n", "-A, --all");
989 printf (" %s\n", _("Explicitly select all paths. This is equivalent to -R '.*'"));
990 printf (" %s\n", "-R, --eregi-path=PATH, --eregi-partition=PARTITION");
991 printf (" %s\n", _("Case insensitive regular expression for path/partition (may be repeated)"));
992 printf (" %s\n", "-r, --ereg-path=PATH, --ereg-partition=PARTITION");
993 printf (" %s\n", _("Regular expression for path or partition (may be repeated)"));
994 printf (" %s\n", "-I, --ignore-eregi-path=PATH, --ignore-eregi-partition=PARTITION");
995 printf (" %s\n", _("Regular expression to ignore selected path/partition (case insensitive) (may be repeated)"));
996 printf (" %s\n", "-i, --ignore-ereg-path=PATH, --ignore-ereg-partition=PARTITION");
997 printf (" %s\n", _("Regular expression to ignore selected path or partition (may be repeated)"));
998 printf (" %s\n", "-n, --ignore-missing");
999 printf (" %s\n", _("Return OK if no filesystem matches, filesystem does not exist or is inaccessible."));
1000 printf (" %s\n", _("(Provide this option before -p / -r / --ereg-path if used)"));
1001 printf (UT_PLUG_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
1002 printf (" %s\n", "-u, --units=STRING");
1003 printf (" %s\n", _("Choose bytes, kB, MB, GB, TB (default: MB)"));
1004 printf (UT_VERBOSE);
1005 printf (" %s\n", "-X, --exclude-type=TYPE_REGEX");
1006 printf (" %s\n", _("Ignore all filesystems of types matching given regex(7) (may be repeated)"));
1007 printf (" %s\n", "-N, --include-type=TYPE_REGEX");
1008 printf (" %s\n", _("Check only filesystems where the type matches this given regex(7) (may be repeated)"));
1009
1010 printf ("\n");
1011 printf ("%s\n", _("General usage hints:"));
1012 printf (" %s\n", _("- Arguments are positional! \"-w 5 -c 1 -p /foo -w6 -c2 -p /bar\" is not the same as"));
1013 printf (" %s\n", _("\"-w 5 -c 1 -p /bar w6 -c2 -p /foo\"."));
1014 printf (" %s\n", _("- The syntax is broadly: \"{thresholds a} {paths a} -C {thresholds b} {thresholds b} ...\""));
1015
1016
1017
1018 printf ("\n");
1019 printf ("%s\n", _("Examples:"));
1020 printf (" %s\n", "check_disk -w 10% -c 5% -p /tmp -p /var -C -w 100000 -c 50000 -p /");
1021 printf (" %s\n\n", _("Checks /tmp and /var at 10% and 5%, and / at 100MB and 50MB"));
1022 printf (" %s\n", "check_disk -w 100 -c 50 -C -w 1000 -c 500 -g sidDATA -r '^/oracle/SID/data.*$'");
1023 printf (" %s\n", _("Checks all filesystems not matching -r at 100M and 50M. The fs matching the -r regex"));
1024 printf (" %s\n\n", _("are grouped which means the freespace thresholds are applied to all disks together"));
1025 printf (" %s\n", "check_disk -w 100 -c 50 -C -w 1000 -c 500 -p /foo -C -w 5% -c 3% -p /bar");
1026 printf (" %s\n", _("Checks /foo for 1000M/500M and /bar for 5/3%. All remaining volumes use 100M/50M"));
1027
1028 printf (UT_SUPPORT);
1029}
1030 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 }
1031 807
808 if (!fnd && ignore_missing == true) {
809 path_ignored = true;
810 path_selected = true;
811 break;
812 }
813 if (!fnd)
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;
884}
1032 885
1033void 886void set_all_thresholds(struct parameter_list *path) {
1034print_usage (void) 887 if (path->freespace_units != NULL)
1035{ 888 free(path->freespace_units);
1036 printf ("%s\n", _("Usage:")); 889 set_thresholds(&path->freespace_units, warn_freespace_units, crit_freespace_units);
1037 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); 890 if (path->freespace_percent != NULL)
1038 printf ("[-C] [-E] [-e] [-f] [-g group ] [-k] [-l] [-M] [-m] [-R path ] [-r path ]\n"); 891 free(path->freespace_percent);
1039 printf ("[-t timeout] [-u unit] [-v] [-X type_regex] [-N type]\n"); 892 set_thresholds(&path->freespace_percent, warn_freespace_percent, crit_freespace_percent);
893 if (path->usedspace_units != NULL)
894 free(path->usedspace_units);
895 set_thresholds(&path->usedspace_units, warn_usedspace_units, crit_usedspace_units);
896 if (path->usedspace_percent != NULL)
897 free(path->usedspace_percent);
898 set_thresholds(&path->usedspace_percent, warn_usedspace_percent, crit_usedspace_percent);
899 if (path->usedinodes_percent != NULL)
900 free(path->usedinodes_percent);
901 set_thresholds(&path->usedinodes_percent, warn_usedinodes_percent, crit_usedinodes_percent);
902 if (path->freeinodes_percent != NULL)
903 free(path->freeinodes_percent);
904 set_thresholds(&path->freeinodes_percent, warn_freeinodes_percent, crit_freeinodes_percent);
1040} 905}
1041 906
1042bool 907void print_help(void) {
1043stat_path (struct parameter_list *p) 908 print_revision(progname, NP_VERSION);
1044{ 909
1045 /* Stat entry to check that dir exists and is accessible */ 910 printf("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n");
1046 if (verbose >= 3) 911 printf(COPYRIGHT, copyright, email);
1047 printf("calling stat on %s\n", p->name); 912
1048 if (stat (p->name, &stat_buf[0])) { 913 printf("%s\n", _("This plugin checks the amount of used disk space on a mounted file system"));
1049 if (verbose >= 3) 914 printf("%s\n", _("and generates an alert if free space is less than one of the threshold values"));
1050 printf("stat failed on %s\n", p->name); 915
1051 if (ignore_missing == true) { 916 printf("\n\n");
1052 return false; 917
1053 } else { 918 print_usage();
1054 printf("DISK %s - ", _("CRITICAL")); 919
1055 die (STATE_CRITICAL, _("%s %s: %s\n"), p->name, _("is not accessible"), strerror(errno)); 920 printf(UT_HELP_VRSN);
1056 } 921 printf(UT_EXTRA_OPTS);
1057 } 922
1058 return true; 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);
1059} 1001}
1060 1002
1003void print_usage(void) {
1004 printf("%s\n", _("Usage:"));
1005 printf(" %s {-w absolute_limit |-w percentage_limit%% | -W inode_percentage_limit } {-c absolute_limit|-c percentage_limit%% | -K "
1006 "inode_percentage_limit } {-p path | -x device}\n",
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}
1061 1011
1062void 1012bool stat_path(struct parameter_list *p) {
1063get_stats (struct parameter_list *p, struct fs_usage *fsp) { 1013 /* Stat entry to check that dir exists and is accessible */
1064 struct parameter_list *p_list; 1014 if (verbose >= 3)
1065 struct fs_usage tmpfsp; 1015 printf("calling stat on %s\n", p->name);
1066 int first = 1; 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;
1067 1032
1068 if (p->group == NULL) { 1033 if (p->group == NULL) {
1069 get_path_stats(p,fsp); 1034 get_path_stats(p, fsp);
1070 } else { 1035 } else {
1071 /* find all group members */ 1036 /* find all group members */
1072 for (p_list = path_select_list; p_list; p_list=p_list->name_next) { 1037 for (p_list = path_select_list; p_list; p_list = p_list->name_next) {
1073#ifdef __CYGWIN__ 1038#ifdef __CYGWIN__
1074 if (strncmp(p_list->name, "/cygdrive/", 10) != 0) 1039 if (strncmp(p_list->name, "/cygdrive/", 10) != 0)
1075 continue; 1040 continue;
1076#endif 1041#endif
1077 if (p_list->group && ! (strcmp(p_list->group, p->group))) { 1042 if (p_list->group && !(strcmp(p_list->group, p->group))) {
1078 if (! stat_path(p_list)) 1043 if (!stat_path(p_list))
1079 continue; 1044 continue;
1080 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);
1081 get_path_stats(p_list, &tmpfsp); 1046 get_path_stats(p_list, &tmpfsp);
1082 if (verbose >= 3) 1047 if (verbose >= 3)
1083 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",
1084 p_list->group, 1049 p_list->group, tmpfsp.fsu_blocks, tmpfsp.fsu_blocksize, p_list->best_match->me_mountdir, p_list->dused_units,
1085 tmpfsp.fsu_blocks, 1050 p_list->dfree_units, p_list->dtotal_units, mult);
1086 tmpfsp.fsu_blocksize, 1051
1087 p_list->best_match->me_mountdir, 1052 /* prevent counting the first FS of a group twice since its parameter_list entry
1088 p_list->dused_units, 1053 * is used to carry the information of all file systems of the entire group */
1089 p_list->dfree_units, 1054 if (!first) {
1090 p_list->dtotal_units, 1055 p->total += p_list->total;
1091 mult); 1056 p->available += p_list->available;
1092 1057 p->available_to_root += p_list->available_to_root;
1093 /* prevent counting the first FS of a group twice since its parameter_list entry 1058 p->used += p_list->used;
1094 * is used to carry the information of all file systems of the entire group */ 1059
1095 if (! first) { 1060 p->dused_units += p_list->dused_units;
1096 p->total += p_list->total; 1061 p->dfree_units += p_list->dfree_units;
1097 p->available += p_list->available; 1062 p->dtotal_units += p_list->dtotal_units;
1098 p->available_to_root += p_list->available_to_root; 1063 p->inodes_total += p_list->inodes_total;
1099 p->used += p_list->used; 1064 p->inodes_free += p_list->inodes_free;
1100 1065 p->inodes_free_to_root += p_list->inodes_free_to_root;
1101 p->dused_units += p_list->dused_units; 1066 p->inodes_used += p_list->inodes_used;
1102 p->dfree_units += p_list->dfree_units; 1067 }
1103 p->dtotal_units += p_list->dtotal_units; 1068 first = 0;
1104 p->inodes_total += p_list->inodes_total; 1069 }
1105 p->inodes_free += p_list->inodes_free; 1070 if (verbose >= 3)
1106 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,
1107 p->inodes_used += p_list->inodes_used; 1072 p->dused_units, p->dfree_units, p->dtotal_units, tmpfsp.fsu_blocksize, mult);
1108 } 1073 }
1109 first = 0; 1074 /* modify devname and mountdir for output */
1110 } 1075 p->best_match->me_mountdir = p->best_match->me_devname = p->group;
1111 if (verbose >= 3) 1076 }
1112 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 */
1113 p->group, 1078 p->dused_pct = calculate_percent(p->used, p->used + p->available); /* used + available can never be > uintmax */
1114 p->dused_units, 1079 p->dfree_pct = 100.0 - p->dused_pct;
1115 p->dfree_units, 1080 p->dused_inodes_percent = calculate_percent(p->inodes_total - p->inodes_free, p->inodes_total);
1116 p->dtotal_units, 1081 p->dfree_inodes_percent = 100 - p->dused_inodes_percent;
1117 tmpfsp.fsu_blocksize,
1118 mult);
1119 }
1120 /* modify devname and mountdir for output */
1121 p->best_match->me_mountdir = p->best_match->me_devname = p->group;
1122 }
1123 /* finally calculate percentages for either plain FS or summed up group */
1124 p->dused_pct = calculate_percent( p->used, p->used + p->available ); /* used + available can never be > uintmax */
1125 p->dfree_pct = 100.0 - p->dused_pct;
1126 p->dused_inodes_percent = calculate_percent(p->inodes_total - p->inodes_free, p->inodes_total);
1127 p->dfree_inodes_percent = 100 - p->dused_inodes_percent;
1128
1129} 1082}
1130 1083
1131void 1084void get_path_stats(struct parameter_list *p, struct fs_usage *fsp) {
1132get_path_stats (struct parameter_list *p, struct fs_usage *fsp) { 1085 p->available = fsp->fsu_bavail;
1133 p->available = fsp->fsu_bavail; 1086 p->available_to_root = fsp->fsu_bfree;
1134 p->available_to_root = fsp->fsu_bfree; 1087 p->used = fsp->fsu_blocks - fsp->fsu_bfree;
1135 p->used = fsp->fsu_blocks - fsp->fsu_bfree; 1088 if (freespace_ignore_reserved) {
1136 if (freespace_ignore_reserved) { 1089 /* option activated : we subtract the root-reserved space from the total */
1137 /* option activated : we subtract the root-reserved space from the total */ 1090 p->total = fsp->fsu_blocks - p->available_to_root + p->available;
1138 p->total = fsp->fsu_blocks - p->available_to_root + p->available; 1091 } else {
1139 } else { 1092 /* default behaviour : take all the blocks into account */
1140 /* default behaviour : take all the blocks into account */ 1093 p->total = fsp->fsu_blocks;
1141 p->total = fsp->fsu_blocks; 1094 }
1142 } 1095
1143 1096 p->dused_units = p->used * fsp->fsu_blocksize / mult;
1144 p->dused_units = p->used*fsp->fsu_blocksize/mult; 1097 p->dfree_units = p->available * fsp->fsu_blocksize / mult;
1145 p->dfree_units = p->available*fsp->fsu_blocksize/mult; 1098 p->dtotal_units = p->total * fsp->fsu_blocksize / mult;
1146 p->dtotal_units = p->total*fsp->fsu_blocksize/mult; 1099 /* Free file nodes. Not sure the workaround is required, but in case...*/
1147 /* Free file nodes. Not sure the workaround is required, but in case...*/ 1100 p->inodes_free = fsp->fsu_ffree;
1148 p->inodes_free = fsp->fsu_ffree; 1101 p->inodes_free_to_root = fsp->fsu_ffree; /* Free file nodes for root. */
1149 p->inodes_free_to_root = fsp->fsu_ffree; /* Free file nodes for root. */ 1102 p->inodes_used = fsp->fsu_files - fsp->fsu_ffree;
1150 p->inodes_used = fsp->fsu_files - fsp->fsu_ffree; 1103 if (freespace_ignore_reserved) {
1151 if (freespace_ignore_reserved) { 1104 /* option activated : we subtract the root-reserved inodes from the total */
1152 /* 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 */
1153 /* not all OS report fsp->fsu_favail, only the ones with statvfs syscall */ 1106 /* for others, fsp->fsu_ffree == fsp->fsu_favail */
1154 /* for others, fsp->fsu_ffree == fsp->fsu_favail */ 1107 p->inodes_total = fsp->fsu_files - p->inodes_free_to_root + p->inodes_free;
1155 p->inodes_total = fsp->fsu_files - p->inodes_free_to_root + p->inodes_free; 1108 } else {
1156 } else { 1109 /* default behaviour : take all the inodes into account */
1157 /* default behaviour : take all the inodes into account */ 1110 p->inodes_total = fsp->fsu_files;
1158 p->inodes_total = fsp->fsu_files; 1111 }
1159 } 1112 np_add_name(&seen, p->best_match->me_mountdir);
1160 np_add_name(&seen, p->best_match->me_mountdir);
1161} 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..c1d03ec 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_fping 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,468 @@ 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 bool dontfrag = false;
64int wpl; 64static bool randomize_packet_data = false;
65double crta; 65static int cpl;
66double wrta; 66static int wpl;
67bool cpl_p = false; 67static double crta;
68bool wpl_p = false; 68static double wrta;
69bool alive_p = false; 69static bool cpl_p = false;
70bool crta_p = false; 70static bool wpl_p = false;
71bool wrta_p = false; 71static bool alive_p = false;
72 72static bool crta_p = false;
73int 73static bool wrta_p = false;
74main (int argc, char **argv) 74
75{ 75int main(int argc, char **argv) {
76/* normally should be int result = STATE_UNKNOWN; */ 76 /* normally should be int result = STATE_UNKNOWN; */
77 77
78 int status = STATE_UNKNOWN; 78 int status = STATE_UNKNOWN;
79 int result = 0; 79 int result = 0;
80 char *fping_prog = NULL; 80 char *fping_prog = NULL;
81 char *server = NULL; 81 char *server = NULL;
82 char *command_line = NULL; 82 char *command_line = NULL;
83 char *input_buffer = NULL; 83 char *input_buffer = NULL;
84 char *option_string = ""; 84 char *option_string = "";
85 input_buffer = malloc (MAX_INPUT_BUFFER); 85 input_buffer = malloc(MAX_INPUT_BUFFER);
86 86
87 setlocale (LC_ALL, ""); 87 setlocale(LC_ALL, "");
88 bindtextdomain (PACKAGE, LOCALEDIR); 88 bindtextdomain(PACKAGE, LOCALEDIR);
89 textdomain (PACKAGE); 89 textdomain(PACKAGE);
90 90
91 /* Parse extra opts if any */ 91 /* Parse extra opts if any */
92 argv=np_extra_opts (&argc, argv, progname); 92 argv = np_extra_opts(&argc, argv, progname);
93 93
94 if (process_arguments (argc, argv) == ERROR) 94 if (process_arguments(argc, argv) == ERROR)
95 usage4 (_("Could not parse arguments")); 95 usage4(_("Could not parse arguments"));
96 96
97 server = strscpy (server, server_name); 97 server = strscpy(server, server_name);
98 98
99 /* compose the command */ 99 /* compose the command */
100 if (target_timeout) 100 if (target_timeout)
101 xasprintf(&option_string, "%s-t %d ", option_string, target_timeout); 101 xasprintf(&option_string, "%s-t %d ", option_string, target_timeout);
102 if (packet_interval) 102 if (packet_interval)
103 xasprintf(&option_string, "%s-p %d ", option_string, packet_interval); 103 xasprintf(&option_string, "%s-p %d ", option_string, packet_interval);
104 if (sourceip) 104 if (sourceip)
105 xasprintf(&option_string, "%s-S %s ", option_string, sourceip); 105 xasprintf(&option_string, "%s-S %s ", option_string, sourceip);
106 if (sourceif) 106 if (sourceif)
107 xasprintf(&option_string, "%s-I %s ", option_string, sourceif); 107 xasprintf(&option_string, "%s-I %s ", option_string, sourceif);
108 if (dontfrag)
109 xasprintf(&option_string, "%s-M ", option_string);
110 if (randomize_packet_data)
111 xasprintf(&option_string, "%s-R ", option_string);
112
108 113
109#ifdef PATH_TO_FPING6 114#ifdef PATH_TO_FPING6
110 if (address_family != AF_INET && is_inet6_addr(server)) 115 if (address_family != AF_INET && is_inet6_addr(server))
111 fping_prog = strdup(PATH_TO_FPING6); 116 fping_prog = strdup(PATH_TO_FPING6);
112 else 117 else
113 fping_prog = strdup(PATH_TO_FPING); 118 fping_prog = strdup(PATH_TO_FPING);
114#else 119#else
115 fping_prog = strdup(PATH_TO_FPING); 120 fping_prog = strdup(PATH_TO_FPING);
116#endif 121#endif
117 122
118 xasprintf (&command_line, "%s %s-b %d -c %d %s", fping_prog, 123 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); 124
120 125 if (verbose)
121 if (verbose) 126 printf("%s\n", command_line);
122 printf ("%s\n", command_line); 127
123 128 /* run the command */
124 /* run the command */ 129 child_process = spopen(command_line);
125 child_process = spopen (command_line); 130 if (child_process == NULL) {
126 if (child_process == NULL) { 131 printf(_("Could not open pipe: %s\n"), command_line);
127 printf (_("Could not open pipe: %s\n"), command_line); 132 return STATE_UNKNOWN;
128 return STATE_UNKNOWN; 133 }
129 } 134
130 135 child_stderr = fdopen(child_stderr_array[fileno(child_process)], "r");
131 child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r"); 136 if (child_stderr == NULL) {
132 if (child_stderr == NULL) { 137 printf(_("Could not open stderr for %s\n"), command_line);
133 printf (_("Could not open stderr for %s\n"), command_line); 138 }
134 } 139
135 140 while (fgets(input_buffer, MAX_INPUT_BUFFER - 1, child_process)) {
136 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) { 141 if (verbose)
137 if (verbose) 142 printf("%s", input_buffer);
138 printf ("%s", input_buffer); 143 status = max_state(status, textscan(input_buffer));
139 status = max_state (status, textscan (input_buffer)); 144 }
140 } 145
141 146 /* If we get anything on STDERR, at least set warning */
142 /* If we get anything on STDERR, at least set warning */ 147 while (fgets(input_buffer, MAX_INPUT_BUFFER - 1, child_stderr)) {
143 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr)) { 148 status = max_state(status, STATE_WARNING);
144 status = max_state (status, STATE_WARNING); 149 if (verbose)
145 if (verbose) 150 printf("%s", input_buffer);
146 printf ("%s", input_buffer); 151 status = max_state(status, textscan(input_buffer));
147 status = max_state (status, textscan (input_buffer)); 152 }
148 } 153 (void)fclose(child_stderr);
149 (void) fclose (child_stderr); 154
150 155 /* close the pipe */
151 /* close the pipe */ 156 result = spclose(child_process);
152 result = spclose (child_process); 157 if (result) {
153 if (result) { 158 /* need to use max_state not max */
154 /* need to use max_state not max */ 159 status = max_state(status, STATE_WARNING);
155 status = max_state (status, STATE_WARNING); 160 }
156 } 161
157 162 if (result > 1) {
158 if (result > 1 ) { 163 status = max_state(status, STATE_UNKNOWN);
159 status = max_state (status, STATE_UNKNOWN); 164 if (result == 2) {
160 if (result == 2) { 165 die(STATE_UNKNOWN, _("FPING UNKNOWN - IP address not found\n"));
161 die (STATE_UNKNOWN, _("FPING UNKNOWN - IP address not found\n")); 166 }
162 } 167 if (result == 3) {
163 if (result == 3) { 168 die(STATE_UNKNOWN, _("FPING UNKNOWN - invalid commandline argument\n"));
164 die (STATE_UNKNOWN, _("FPING UNKNOWN - invalid commandline argument\n")); 169 }
165 } 170 if (result == 4) {
166 if (result == 4) { 171 die(STATE_UNKNOWN, _("FPING UNKNOWN - failed system call\n"));
167 die (STATE_UNKNOWN, _("FPING UNKNOWN - failed system call\n")); 172 }
168 } 173 }
169 174
170 } 175 printf("FPING %s - %s\n", state_text(status), server_name);
171 176
172 printf ("FPING %s - %s\n", state_text (status), server_name); 177 return status;
173
174 return status;
175} 178}
176 179
177 180int textscan(char *buf) {
178int textscan (char *buf) { 181 char *rtastr = NULL;
179 char *rtastr = NULL; 182 char *losstr = NULL;
180 char *losstr = NULL; 183 char *xmtstr = NULL;
181 char *xmtstr = NULL; 184 double loss;
182 double loss; 185 double rta;
183 double rta; 186 double xmt;
184 double xmt; 187 int status = STATE_UNKNOWN;
185 int status = STATE_UNKNOWN; 188
186 189 /* stops testing after the first successful reply. */
187 /* stops testing after the first successful reply. */ 190 if (alive_p && strstr(buf, "avg, 0% loss)")) {
188 if (alive_p && strstr(buf, "avg, 0% loss)")) { 191 rtastr = strstr(buf, "ms (");
189 rtastr = strstr (buf, "ms ("); 192 rtastr = 1 + index(rtastr, '(');
190 rtastr = 1 + index(rtastr, '('); 193 rta = strtod(rtastr, NULL);
191 rta = strtod(rtastr, NULL); 194 loss = strtod("0", NULL);
192 loss=strtod("0",NULL); 195 die(STATE_OK, _("FPING %s - %s (rta=%f ms)|%s\n"), state_text(STATE_OK), server_name, rta,
193 die (STATE_OK, 196 /* No loss since we only waited for the first reply
194 _("FPING %s - %s (rta=%f ms)|%s\n"), 197 perfdata ("loss", (long int)loss, "%", wpl_p, wpl, cpl_p, cpl, true, 0, true, 100), */
195 state_text (STATE_OK), server_name,rta, 198 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 199 }
197 perfdata ("loss", (long int)loss, "%", wpl_p, wpl, cpl_p, cpl, true, 0, true, 100), */ 200
198 fperfdata ("rta", rta/1.0e3, "s", wrta_p, wrta/1.0e3, crta_p, crta/1.0e3, true, 0, false, 0)); 201 if (strstr(buf, "not found")) {
199 } 202 die(STATE_CRITICAL, _("FPING UNKNOWN - %s not found\n"), server_name);
200 203
201 if (strstr (buf, "not found")) { 204 } else if (strstr(buf, "is unreachable") || strstr(buf, "Unreachable")) {
202 die (STATE_CRITICAL, _("FPING UNKNOWN - %s not found\n"), server_name); 205 die(STATE_CRITICAL, _("FPING CRITICAL - %s is unreachable\n"), "host");
203 206
204 } 207 } else if (strstr(buf, "Operation not permitted") || strstr(buf, "No such device")) {
205 else if (strstr (buf, "is unreachable") || strstr (buf, "Unreachable")) { 208 die(STATE_UNKNOWN, _("FPING UNKNOWN - %s parameter error\n"), "host");
206 die (STATE_CRITICAL, _("FPING CRITICAL - %s is unreachable\n"), 209 } else if (strstr(buf, "is down")) {
207 "host"); 210 die(STATE_CRITICAL, _("FPING CRITICAL - %s is down\n"), server_name);
208 211
209 } 212 } else if (strstr(buf, "is alive")) {
210 else if (strstr (buf, "Operation not permitted") || strstr (buf, "No such device") ) { 213 status = STATE_OK;
211 die (STATE_UNKNOWN, _("FPING UNKNOWN - %s parameter error\n"), 214
212 "host"); 215 } else if (strstr(buf, "xmt/rcv/%loss") && strstr(buf, "min/avg/max")) {
213 } 216 losstr = strstr(buf, "=");
214 else if (strstr (buf, "is down")) { 217 losstr = 1 + strstr(losstr, "/");
215 die (STATE_CRITICAL, _("FPING CRITICAL - %s is down\n"), server_name); 218 losstr = 1 + strstr(losstr, "/");
216 219 rtastr = strstr(buf, "min/avg/max");
217 } 220 rtastr = strstr(rtastr, "=");
218 else if (strstr (buf, "is alive")) { 221 rtastr = 1 + index(rtastr, '/');
219 status = STATE_OK; 222 loss = strtod(losstr, NULL);
220 223 rta = strtod(rtastr, NULL);
221 } 224 if (cpl_p && loss > cpl)
222 else if (strstr (buf, "xmt/rcv/%loss") && strstr (buf, "min/avg/max")) { 225 status = STATE_CRITICAL;
223 losstr = strstr (buf, "="); 226 else if (crta_p && rta > crta)
224 losstr = 1 + strstr (losstr, "/"); 227 status = STATE_CRITICAL;
225 losstr = 1 + strstr (losstr, "/"); 228 else if (wpl_p && loss > wpl)
226 rtastr = strstr (buf, "min/avg/max"); 229 status = STATE_WARNING;
227 rtastr = strstr (rtastr, "="); 230 else if (wrta_p && rta > wrta)
228 rtastr = 1 + index (rtastr, '/'); 231 status = STATE_WARNING;
229 loss = strtod (losstr, NULL); 232 else
230 rta = strtod (rtastr, NULL); 233 status = STATE_OK;
231 if (cpl_p && loss > cpl) 234 die(status, _("FPING %s - %s (loss=%.0f%%, rta=%f ms)|%s %s\n"), state_text(status), server_name, loss, rta,
232 status = STATE_CRITICAL; 235 perfdata("loss", (long int)loss, "%", wpl_p, wpl, cpl_p, cpl, true, 0, true, 100),
233 else if (crta_p && rta > crta) 236 fperfdata("rta", rta / 1.0e3, "s", wrta_p, wrta / 1.0e3, crta_p, crta / 1.0e3, true, 0, false, 0));
234 status = STATE_CRITICAL; 237
235 else if (wpl_p && loss > wpl) 238 } else if (strstr(buf, "xmt/rcv/%loss")) {
236 status = STATE_WARNING; 239 /* no min/max/avg if host was unreachable in fping v2.2.b1 */
237 else if (wrta_p && rta > wrta) 240 /* in v2.4b2: 10.99.0.1 : xmt/rcv/%loss = 0/0/0% */
238 status = STATE_WARNING; 241 losstr = strstr(buf, "=");
239 else 242 xmtstr = 1 + losstr;
240 status = STATE_OK; 243 xmt = strtod(xmtstr, NULL);
241 die (status, 244 if (xmt == 0)
242 _("FPING %s - %s (loss=%.0f%%, rta=%f ms)|%s %s\n"), 245 die(STATE_CRITICAL, _("FPING CRITICAL - %s is down\n"), server_name);
243 state_text (status), server_name, loss, rta, 246 losstr = 1 + strstr(losstr, "/");
244 perfdata ("loss", (long int)loss, "%", wpl_p, wpl, cpl_p, cpl, true, 0, true, 100), 247 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)); 248 loss = strtod(losstr, NULL);
246 249 if (atoi(losstr) == 100)
247 } 250 status = STATE_CRITICAL;
248 else if(strstr (buf, "xmt/rcv/%loss") ) { 251 else if (cpl_p && loss > cpl)
249 /* no min/max/avg if host was unreachable in fping v2.2.b1 */ 252 status = STATE_CRITICAL;
250 /* in v2.4b2: 10.99.0.1 : xmt/rcv/%loss = 0/0/0% */ 253 else if (wpl_p && loss > wpl)
251 losstr = strstr (buf, "="); 254 status = STATE_WARNING;
252 xmtstr = 1 + losstr; 255 else
253 xmt = strtod (xmtstr, NULL); 256 status = STATE_OK;
254 if(xmt == 0) 257 /* loss=%.0f%%;%d;%d;0;100 */
255 die (STATE_CRITICAL, _("FPING CRITICAL - %s is down\n"), server_name); 258 die(status, _("FPING %s - %s (loss=%.0f%% )|%s\n"), state_text(status), server_name, loss,
256 losstr = 1 + strstr (losstr, "/"); 259 perfdata("loss", (long int)loss, "%", wpl_p, wpl, cpl_p, cpl, true, 0, true, 100));
257 losstr = 1 + strstr (losstr, "/"); 260
258 loss = strtod (losstr, NULL); 261 } else {
259 if (atoi(losstr) == 100) 262 status = max_state(status, STATE_WARNING);
260 status = STATE_CRITICAL; 263 }
261 else if (cpl_p && loss > cpl) 264
262 status = STATE_CRITICAL; 265 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} 266}
279 267
280
281
282/* process command-line arguments */ 268/* process command-line arguments */
283int 269int process_arguments(int argc, char **argv) {
284process_arguments (int argc, char **argv) 270 int c;
285{ 271 char *rv[2];
286 int c; 272
287 char *rv[2]; 273 int option = 0;
288 274 static struct option longopts[] = {{"hostname", required_argument, 0, 'H'},
289 int option = 0; 275 {"sourceip", required_argument, 0, 'S'},
290 static struct option longopts[] = { 276 {"sourceif", required_argument, 0, 'I'},
291 {"hostname", required_argument, 0, 'H'}, 277 {"critical", required_argument, 0, 'c'},
292 {"sourceip", required_argument, 0, 'S'}, 278 {"warning", required_argument, 0, 'w'},
293 {"sourceif", required_argument, 0, 'I'}, 279 {"alive", no_argument, 0, 'a'},
294 {"critical", required_argument, 0, 'c'}, 280 {"bytes", required_argument, 0, 'b'},
295 {"warning", required_argument, 0, 'w'}, 281 {"number", required_argument, 0, 'n'},
296 {"alive", no_argument, 0, 'a'}, 282 {"target-timeout", required_argument, 0, 'T'},
297 {"bytes", required_argument, 0, 'b'}, 283 {"interval", required_argument, 0, 'i'},
298 {"number", required_argument, 0, 'n'}, 284 {"verbose", no_argument, 0, 'v'},
299 {"target-timeout", required_argument, 0, 'T'}, 285 {"version", no_argument, 0, 'V'},
300 {"interval", required_argument, 0, 'i'}, 286 {"help", no_argument, 0, 'h'},
301 {"verbose", no_argument, 0, 'v'}, 287 {"use-ipv4", no_argument, 0, '4'},
302 {"version", no_argument, 0, 'V'}, 288 {"use-ipv6", no_argument, 0, '6'},
303 {"help", no_argument, 0, 'h'}, 289 {"dontfrag", no_argument, 0, 'M'},
304 {"use-ipv4", no_argument, 0, '4'}, 290 {"random", no_argument, 0, 'R'},
305 {"use-ipv6", no_argument, 0, '6'}, 291 {0, 0, 0, 0}};
306 {0, 0, 0, 0} 292
307 }; 293 rv[PL] = NULL;
308 294 rv[RTA] = NULL;
309 rv[PL] = NULL; 295
310 rv[RTA] = NULL; 296 if (argc < 2)
311 297 return ERROR;
312 if (argc < 2) 298
313 return ERROR; 299 if (!is_option(argv[1])) {
314 300 server_name = argv[1];
315 if (!is_option (argv[1])) { 301 argv[1] = argv[0];
316 server_name = argv[1]; 302 argv = &argv[1];
317 argv[1] = argv[0]; 303 argc--;
318 argv = &argv[1]; 304 }
319 argc--; 305
320 } 306 while (1) {
321 307 c = getopt_long(argc, argv, "+hVvaH:S:c:w:b:n:T:i:I:M:R:46", longopts, &option);
322 while (1) { 308
323 c = getopt_long (argc, argv, "+hVvaH:S:c:w:b:n:T:i:I:46", longopts, &option); 309 if (c == -1 || c == EOF || c == 1)
324 310 break;
325 if (c == -1 || c == EOF || c == 1) 311
326 break; 312 switch (c) {
327 313 case '?': /* print short usage statement if args not parsable */
328 switch (c) { 314 usage5();
329 case '?': /* print short usage statement if args not parsable */ 315 case 'a': /* host alive mode */
330 usage5 (); 316 alive_p = true;
331 case 'a': /* host alive mode */ 317 break;
332 alive_p = true; 318 case 'h': /* help */
333 break; 319 print_help();
334 case 'h': /* help */ 320 exit(STATE_UNKNOWN);
335 print_help (); 321 case 'V': /* version */
336 exit (STATE_UNKNOWN); 322 print_revision(progname, NP_VERSION);
337 case 'V': /* version */ 323 exit(STATE_UNKNOWN);
338 print_revision (progname, NP_VERSION); 324 case 'v': /* verbose mode */
339 exit (STATE_UNKNOWN); 325 verbose = true;
340 case 'v': /* verbose mode */ 326 break;
341 verbose = true; 327 case 'H': /* hostname */
342 break; 328 if (is_host(optarg) == false) {
343 case 'H': /* hostname */ 329 usage2(_("Invalid hostname/address"), optarg);
344 if (is_host (optarg) == false) { 330 }
345 usage2 (_("Invalid hostname/address"), optarg); 331 server_name = strscpy(server_name, optarg);
346 } 332 break;
347 server_name = strscpy (server_name, optarg); 333 case 'S': /* sourceip */
348 break; 334 if (is_host(optarg) == false) {
349 case 'S': /* sourceip */ 335 usage2(_("Invalid hostname/address"), optarg);
350 if (is_host (optarg) == false) { 336 }
351 usage2 (_("Invalid hostname/address"), optarg); 337 sourceip = strscpy(sourceip, optarg);
352 }
353 sourceip = strscpy (sourceip, optarg);
354 break;
355 case 'I': /* sourceip */
356 sourceif = strscpy (sourceif, optarg);
357 break; 338 break;
358 case '4': /* IPv4 only */ 339 case 'I': /* sourceip */
359 address_family = AF_INET; 340 sourceif = strscpy(sourceif, optarg);
360 break; 341 break;
361 case '6': /* IPv6 only */ 342 case '4': /* IPv4 only */
343 address_family = AF_INET;
344 break;
345 case '6': /* IPv6 only */
362#ifdef USE_IPV6 346#ifdef USE_IPV6
363 address_family = AF_INET6; 347 address_family = AF_INET6;
364#else 348#else
365 usage (_("IPv6 support not available\n")); 349 usage(_("IPv6 support not available\n"));
366#endif 350#endif
367 break; 351 break;
368 case 'c': 352 case 'c':
369 get_threshold (optarg, rv); 353 get_threshold(optarg, rv);
370 if (rv[RTA]) { 354 if (rv[RTA]) {
371 crta = strtod (rv[RTA], NULL); 355 crta = strtod(rv[RTA], NULL);
372 crta_p = true; 356 crta_p = true;
373 rv[RTA] = NULL; 357 rv[RTA] = NULL;
374 } 358 }
375 if (rv[PL]) { 359 if (rv[PL]) {
376 cpl = atoi (rv[PL]); 360 cpl = atoi(rv[PL]);
377 cpl_p = true; 361 cpl_p = true;
378 rv[PL] = NULL; 362 rv[PL] = NULL;
379 } 363 }
380 break; 364 break;
381 case 'w': 365 case 'w':
382 get_threshold (optarg, rv); 366 get_threshold(optarg, rv);
383 if (rv[RTA]) { 367 if (rv[RTA]) {
384 wrta = strtod (rv[RTA], NULL); 368 wrta = strtod(rv[RTA], NULL);
385 wrta_p = true; 369 wrta_p = true;
386 rv[RTA] = NULL; 370 rv[RTA] = NULL;
387 } 371 }
388 if (rv[PL]) { 372 if (rv[PL]) {
389 wpl = atoi (rv[PL]); 373 wpl = atoi(rv[PL]);
390 wpl_p = true; 374 wpl_p = true;
391 rv[PL] = NULL; 375 rv[PL] = NULL;
392 } 376 }
393 break; 377 break;
394 case 'b': /* bytes per packet */ 378 case 'b': /* bytes per packet */
395 if (is_intpos (optarg)) 379 if (is_intpos(optarg))
396 packet_size = atoi (optarg); 380 packet_size = atoi(optarg);
397 else 381 else
398 usage (_("Packet size must be a positive integer")); 382 usage(_("Packet size must be a positive integer"));
399 break; 383 break;
400 case 'n': /* number of packets */ 384 case 'n': /* number of packets */
401 if (is_intpos (optarg)) 385 if (is_intpos(optarg))
402 packet_count = atoi (optarg); 386 packet_count = atoi(optarg);
403 else 387 else
404 usage (_("Packet count must be a positive integer")); 388 usage(_("Packet count must be a positive integer"));
405 break; 389 break;
406 case 'T': /* timeout in msec */ 390 case 'T': /* timeout in msec */
407 if (is_intpos (optarg)) 391 if (is_intpos(optarg))
408 target_timeout = atoi (optarg); 392 target_timeout = atoi(optarg);
409 else 393 else
410 usage (_("Target timeout must be a positive integer")); 394 usage(_("Target timeout must be a positive integer"));
411 break; 395 break;
412 case 'i': /* interval in msec */ 396 case 'i': /* interval in msec */
413 if (is_intpos (optarg)) 397 if (is_intpos(optarg))
414 packet_interval = atoi (optarg); 398 packet_interval = atoi(optarg);
415 else 399 else
416 usage (_("Interval must be a positive integer")); 400 usage(_("Interval must be a positive integer"));
417 break; 401 break;
418 } 402 case 'R':
419 } 403 randomize_packet_data = true;
420 404 break;
421 if (server_name == NULL) 405 case 'M':
422 usage4 (_("Hostname was not supplied")); 406 dontfrag = true;
423 407 break;
424 return OK; 408 }
425} 409 }
426 410
411 if (server_name == NULL)
412 usage4(_("Hostname was not supplied"));
427 413
428int 414 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} 415}
467 416
468 417int get_threshold(char *arg, char *rv[2]) {
469void print_help (void) { 418 char *arg1 = NULL;
470 419 char *arg2 = NULL;
471 print_revision (progname, NP_VERSION); 420
472 421 arg1 = strscpy(arg1, arg);
473 printf ("Copyright (c) 1999 Didi Rieder <adrieder@sbox.tu-graz.ac.at>\n"); 422 if (strpbrk(arg1, ",:"))
474 printf (COPYRIGHT, copyright, email); 423 arg2 = 1 + strpbrk(arg1, ",:");
475 424
476 printf ("%s\n", _("This plugin will use the fping command to ping the specified host for a fast check")); 425 if (arg2) {
477 426 arg1[strcspn(arg1, ",:")] = 0;
478 printf ("%s\n", _("Note that it is necessary to set the suid flag on fping.")); 427 if (strstr(arg1, "%") && strstr(arg2, "%"))
479 428 die(STATE_UNKNOWN, _("%s: Only one threshold may be packet loss (%s)\n"), progname, arg);
480 printf ("\n\n"); 429 if (!strstr(arg1, "%") && !strstr(arg2, "%"))
481 430 die(STATE_UNKNOWN, _("%s: Only one threshold must be packet loss (%s)\n"), progname, arg);
482 print_usage (); 431 }
483 432
484 printf (UT_HELP_VRSN); 433 if (arg2 && strstr(arg2, "%")) {
485 printf (UT_EXTRA_OPTS); 434 rv[PL] = arg2;
486 435 rv[RTA] = arg1;
487 printf (UT_IPv46); 436 } else if (arg2) {
488 437 rv[PL] = arg1;
489 printf (" %s\n", "-H, --hostname=HOST"); 438 rv[RTA] = arg2;
490 printf (" %s\n", _("name or IP Address of host to ping (IP Address bypasses name lookup, reducing system load)")); 439 } else if (strstr(arg1, "%")) {
491 printf (" %s\n", "-w, --warning=THRESHOLD"); 440 rv[PL] = arg1;
492 printf (" %s\n", _("warning threshold pair")); 441 } else {
493 printf (" %s\n", "-c, --critical=THRESHOLD"); 442 rv[RTA] = arg1;
494 printf (" %s\n", _("critical threshold pair")); 443 }
495 printf (" %s\n", "-a, --alive"); 444
496 printf (" %s\n", _("Return OK after first successful reply")); 445 return OK;
497 printf (" %s\n", "-b, --bytes=INTEGER");
498 printf (" %s (default: %d)\n", _("size of ICMP packet"),PACKET_SIZE);
499 printf (" %s\n", "-n, --number=INTEGER");
500 printf (" %s (default: %d)\n", _("number of ICMP packets to send"),PACKET_COUNT);
501 printf (" %s\n", "-T, --target-timeout=INTEGER");
502 printf (" %s (default: fping's default for -t)\n", _("Target timeout (ms)"));
503 printf (" %s\n", "-i, --interval=INTEGER");
504 printf (" %s (default: fping's default for -p)\n", _("Interval (ms) between sending packets"));
505 printf (" %s\n", "-S, --sourceip=HOST");
506 printf (" %s\n", _("name or IP Address of sourceip"));
507 printf (" %s\n", "-I, --sourceif=IF");
508 printf (" %s\n", _("source interface name"));
509 printf (UT_VERBOSE);
510 printf ("\n");
511 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"));
513 printf (" %s\n", _("packet loss to trigger an alarm state."));
514
515 printf ("\n");
516 printf (" %s\n", _("IPv4 is used by default. Specify -6 to use IPv6."));
517
518 printf (UT_SUPPORT);
519} 446}
520 447
448void print_help(void) {
449
450 print_revision(progname, NP_VERSION);
451
452 printf("Copyright (c) 1999 Didi Rieder <adrieder@sbox.tu-graz.ac.at>\n");
453 printf(COPYRIGHT, copyright, email);
454
455 printf("%s\n", _("This plugin will use the fping command to ping the specified host for a fast check"));
456
457 printf("%s\n", _("Note that it is necessary to set the suid flag on fping."));
458
459 printf("\n\n");
460
461 print_usage();
462
463 printf(UT_HELP_VRSN);
464 printf(UT_EXTRA_OPTS);
465
466 printf(UT_IPv46);
467
468 printf(" %s\n", "-H, --hostname=HOST");
469 printf(" %s\n", _("name or IP Address of host to ping (IP Address bypasses name lookup, reducing system load)"));
470 printf(" %s\n", "-w, --warning=THRESHOLD");
471 printf(" %s\n", _("warning threshold pair"));
472 printf(" %s\n", "-c, --critical=THRESHOLD");
473 printf(" %s\n", _("critical threshold pair"));
474 printf(" %s\n", "-a, --alive");
475 printf(" %s\n", _("Return OK after first successful reply"));
476 printf(" %s\n", "-b, --bytes=INTEGER");
477 printf(" %s (default: %d)\n", _("size of ICMP packet"), PACKET_SIZE);
478 printf(" %s\n", "-n, --number=INTEGER");
479 printf(" %s (default: %d)\n", _("number of ICMP packets to send"), PACKET_COUNT);
480 printf(" %s\n", "-T, --target-timeout=INTEGER");
481 printf(" %s (default: fping's default for -t)\n", _("Target timeout (ms)"));
482 printf(" %s\n", "-i, --interval=INTEGER");
483 printf(" %s (default: fping's default for -p)\n", _("Interval (ms) between sending packets"));
484 printf(" %s\n", "-S, --sourceip=HOST");
485 printf(" %s\n", _("name or IP Address of sourceip"));
486 printf(" %s\n", "-I, --sourceif=IF");
487 printf(" %s\n", _("source interface name"));
488 printf(" %s\n", "-M, --dontfrag");
489 printf(" %s\n", _("set the Don't Fragment flag"));
490 printf(" %s\n", "-R, --random");
491 printf(" %s\n", _("random packet data (to foil link data compression)"));
492 printf(UT_VERBOSE);
493 printf("\n");
494 printf(" %s\n", _("THRESHOLD is <rta>,<pl>%% where <rta> is the round trip average travel time (ms)"));
495 printf(" %s\n", _("which triggers a WARNING or CRITICAL state, and <pl> is the percentage of"));
496 printf(" %s\n", _("packet loss to trigger an alarm state."));
497
498 printf("\n");
499 printf(" %s\n", _("IPv4 is used by default. Specify -6 to use IPv6."));
500
501 printf(UT_SUPPORT);
502}
521 503
522void 504void print_usage(void) {
523print_usage (void) 505 printf("%s\n", _("Usage:"));
524{ 506 printf(" %s <host_address> -w limit -c limit [-b size] [-n number] [-T number] [-i number]\n", progname);
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} 507}
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..9640ef7 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,69 @@ 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 116static struct {
125{
126 __u8 value; 117 __u8 value;
127 char *text; 118 char *text;
128} 119} offline_status_text[] = {{0x00, "NeverStarted"}, {0x02, "Completed"}, {0x04, "Suspended"},
120 {0x05, "Aborted"}, {0x06, "Failed"}, {0, 0}};
129 121
130offline_status_text[] = 122static struct {
131 {
132 {0x00, "NeverStarted"},
133 {0x02, "Completed"},
134 {0x04, "Suspended"},
135 {0x05, "Aborted"},
136 {0x06, "Failed"},
137 {0, 0}
138 };
139
140struct
141{
142 __u8 value; 123 __u8 value;
143 char *text; 124 char *text;
144} 125} smart_command[] = {{SMART_ENABLE, "SMART_ENABLE"},
145 126 {SMART_DISABLE, "SMART_DISABLE"},
146smart_command[] = 127 {SMART_IMMEDIATE_OFFLINE, "SMART_IMMEDIATE_OFFLINE"},
147 { 128 {SMART_AUTO_OFFLINE, "SMART_AUTO_OFFLINE"}};
148 {SMART_ENABLE, "SMART_ENABLE"}, 129
149 {SMART_DISABLE, "SMART_DISABLE"}, 130/* Index to smart_command table, keep in order */
150 {SMART_IMMEDIATE_OFFLINE, "SMART_IMMEDIATE_OFFLINE"}, 131enum SmartCommand {
151 {SMART_AUTO_OFFLINE, "SMART_AUTO_OFFLINE"} 132 SMART_CMD_ENABLE,
152 }; 133 SMART_CMD_DISABLE,
153 134 SMART_CMD_IMMEDIATE_OFFLINE,
154 135 SMART_CMD_AUTO_OFFLINE
155/* Index to smart_command table, keep in order */ 136};
156enum SmartCommand 137
157 { SMART_CMD_ENABLE, 138static char *get_offline_text(int);
158 SMART_CMD_DISABLE, 139static int smart_read_values(int, values_t *);
159 SMART_CMD_IMMEDIATE_OFFLINE, 140static int nagios(values_t *, thresholds_t *);
160 SMART_CMD_AUTO_OFFLINE 141static void print_value(value_t *, threshold_t *);
161 }; 142static void print_values(values_t *, thresholds_t *);
162 143static int smart_cmd_simple(int, enum SmartCommand, __u8, bool);
163char *get_offline_text (int); 144static int smart_read_thresholds(int, thresholds_t *);
164int smart_read_values (int, values_t *); 145static bool verbose = false;
165int nagios (values_t *, thresholds_t *); 146
166void print_value (value_t *, threshold_t *); 147int 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; 148 char *device = NULL;
176 int o, longindex; 149 int o;
150 int longindex;
177 int retval = 0; 151 int retval = 0;
178 152
179 thresholds_t thresholds; 153 thresholds_t thresholds;
180 values_t values; 154 values_t values;
181 int fd; 155 int fd;
182 156
183 static struct option longopts[] = { 157 static struct option longopts[] = {{"device", required_argument, 0, 'd'},
184 {"device", required_argument, 0, 'd'}, 158 {"immediate", no_argument, 0, 'i'},
185 {"immediate", no_argument, 0, 'i'}, 159 {"quiet-check", no_argument, 0, 'q'},
186 {"quiet-check", no_argument, 0, 'q'}, 160 {"auto-on", no_argument, 0, '1'},
187 {"auto-on", no_argument, 0, '1'}, 161 {"auto-off", no_argument, 0, '0'},
188 {"auto-off", no_argument, 0, '0'}, 162 {"nagios", no_argument, 0, 'n'}, /* DEPRECATED, but we still accept it */
189 {"nagios", no_argument, 0, 'n'}, /* DEPRECATED, but we still accept it */ 163 {"help", no_argument, 0, 'h'},
190 {"help", no_argument, 0, 'h'}, 164 {"version", no_argument, 0, 'V'},
191 {"version", no_argument, 0, 'V'}, 165 {0, 0, 0, 0}};
192 {0, 0, 0, 0}
193 };
194 166
195 /* Parse extra opts if any */ 167 /* Parse extra opts if any */
196 argv=np_extra_opts (&argc, argv, progname); 168 argv = np_extra_opts(&argc, argv, progname);
197 169
198 setlocale (LC_ALL, ""); 170 setlocale(LC_ALL, "");
199 bindtextdomain (PACKAGE, LOCALEDIR); 171 bindtextdomain(PACKAGE, LOCALEDIR);
200 textdomain (PACKAGE); 172 textdomain(PACKAGE);
201 173
202 while (true) { 174 while (true) {
203 175
204 o = getopt_long (argc, argv, "+d:iq10nhVv", longopts, &longindex); 176 o = getopt_long(argc, argv, "+d:iq10nhVv", longopts, &longindex);
205 177
206 if (o == -1 || o == EOF || o == 1) 178 if (o == -1 || o == EOF || o == 1)
207 break; 179 break;
@@ -211,30 +183,30 @@ main (int argc, char *argv[])
211 device = optarg; 183 device = optarg;
212 break; 184 break;
213 case 'q': 185 case 'q':
214 fprintf (stderr, "%s\n", _("DEPRECATION WARNING: the -q switch (quiet output) is no longer \"quiet\".")); 186 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.")); 187 fprintf(stderr, "%s\n", _("Nagios-compatible output is now always returned."));
216 break; 188 break;
217 case 'i': 189 case 'i':
218 case '1': 190 case '1':
219 case '0': 191 case '0':
220 printf ("%s\n", _("SMART commands are broken and have been disabled (See Notes in --help).")); 192 printf("%s\n", _("SMART commands are broken and have been disabled (See Notes in --help)."));
221 return STATE_CRITICAL; 193 return STATE_CRITICAL;
222 break; 194 break;
223 case 'n': 195 case 'n':
224 fprintf (stderr, "%s\n", _("DEPRECATION WARNING: the -n switch (Nagios-compatible output) is now the")); 196 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.")); 197 fprintf(stderr, "%s\n", _("default and will be removed from future releases."));
226 break; 198 break;
227 case 'v': /* verbose */ 199 case 'v': /* verbose */
228 verbose = true; 200 verbose = true;
229 break; 201 break;
230 case 'h': 202 case 'h':
231 print_help (); 203 print_help();
232 return STATE_UNKNOWN; 204 return STATE_UNKNOWN;
233 case 'V': 205 case 'V':
234 print_revision (progname, NP_VERSION); 206 print_revision(progname, NP_VERSION);
235 return STATE_UNKNOWN; 207 return STATE_UNKNOWN;
236 default: 208 default:
237 usage5 (); 209 usage5();
238 } 210 }
239 } 211 }
240 212
@@ -243,36 +215,33 @@ main (int argc, char *argv[])
243 } 215 }
244 216
245 if (!device) { 217 if (!device) {
246 print_help (); 218 print_help();
247 return STATE_UNKNOWN; 219 return STATE_UNKNOWN;
248 } 220 }
249 221
250 fd = open (device, OPEN_MODE); 222 fd = open(device, OPEN_MODE);
251 223
252 if (fd < 0) { 224 if (fd < 0) {
253 printf (_("CRITICAL - Couldn't open device %s: %s\n"), device, strerror (errno)); 225 printf(_("CRITICAL - Couldn't open device %s: %s\n"), device, strerror(errno));
254 return STATE_CRITICAL; 226 return STATE_CRITICAL;
255 } 227 }
256 228
257 if (smart_cmd_simple (fd, SMART_CMD_ENABLE, 0, false)) { 229 if (smart_cmd_simple(fd, SMART_CMD_ENABLE, 0, false)) {
258 printf (_("CRITICAL - SMART_CMD_ENABLE\n")); 230 printf(_("CRITICAL - SMART_CMD_ENABLE\n"));
259 return STATE_CRITICAL; 231 return STATE_CRITICAL;
260 } 232 }
261 233
262 smart_read_values (fd, &values); 234 smart_read_values(fd, &values);
263 smart_read_thresholds (fd, &thresholds); 235 smart_read_thresholds(fd, &thresholds);
264 retval = nagios (&values, &thresholds); 236 retval = nagios(&values, &thresholds);
265 if (verbose) print_values (&values, &thresholds); 237 if (verbose)
238 print_values(&values, &thresholds);
266 239
267 close (fd); 240 close(fd);
268 return retval; 241 return retval;
269} 242}
270 243
271 244char *get_offline_text(int status) {
272
273char *
274get_offline_text (int status)
275{
276 int i; 245 int i;
277 for (i = 0; offline_status_text[i].text; i++) { 246 for (i = 0; offline_status_text[i].text; i++) {
278 if (offline_status_text[i].value == status) { 247 if (offline_status_text[i].value == status) {
@@ -282,11 +251,7 @@ get_offline_text (int status)
282 return "UNKNOWN"; 251 return "UNKNOWN";
283} 252}
284 253
285 254int smart_read_values(int fd, values_t *values) {
286
287int
288smart_read_values (int fd, values_t * values)
289{
290#ifdef __linux__ 255#ifdef __linux__
291 int e; 256 int e;
292 __u8 args[4 + 512]; 257 __u8 args[4 + 512];
@@ -294,12 +259,12 @@ smart_read_values (int fd, values_t * values)
294 args[1] = 0; 259 args[1] = 0;
295 args[2] = SMART_READ_VALUES; 260 args[2] = SMART_READ_VALUES;
296 args[3] = 1; 261 args[3] = 1;
297 if (ioctl (fd, HDIO_DRIVE_CMD, &args)) { 262 if (ioctl(fd, HDIO_DRIVE_CMD, &args)) {
298 e = errno; 263 e = errno;
299 printf (_("CRITICAL - SMART_READ_VALUES: %s\n"), strerror (errno)); 264 printf(_("CRITICAL - SMART_READ_VALUES: %s\n"), strerror(errno));
300 return e; 265 return e;
301 } 266 }
302 memcpy (values, args + 4, 512); 267 memcpy(values, args + 4, 512);
303#endif /* __linux__ */ 268#endif /* __linux__ */
304#ifdef __NetBSD__ 269#ifdef __NetBSD__
305 struct atareq req; 270 struct atareq req;
@@ -323,7 +288,7 @@ smart_read_values (int fd, values_t * values)
323 288
324 if (errno != 0) { 289 if (errno != 0) {
325 int e = errno; 290 int e = errno;
326 printf (_("CRITICAL - SMART_READ_VALUES: %s\n"), strerror (errno)); 291 printf(_("CRITICAL - SMART_READ_VALUES: %s\n"), strerror(errno));
327 return e; 292 return e;
328 } 293 }
329 294
@@ -332,13 +297,9 @@ smart_read_values (int fd, values_t * values)
332 return 0; 297 return 0;
333} 298}
334 299
335 300int nagios(values_t *p, thresholds_t *t) {
336 301 value_t *value = p->values;
337int 302 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; 303 int status = OPERATIONAL;
343 int prefailure = 0; 304 int prefailure = 0;
344 int advisory = 0; 305 int advisory = 0;
@@ -353,13 +314,11 @@ nagios (values_t * p, thresholds_t * t)
353 if (value->status & 1) { 314 if (value->status & 1) {
354 status = PREFAILURE; 315 status = PREFAILURE;
355 ++prefailure; 316 ++prefailure;
356 } 317 } else {
357 else {
358 status = ADVISORY; 318 status = ADVISORY;
359 ++advisory; 319 ++advisory;
360 } 320 }
361 } 321 } else {
362 else {
363 ++passed; 322 ++passed;
364 } 323 }
365 ++total; 324 ++total;
@@ -369,81 +328,49 @@ nagios (values_t * p, thresholds_t * t)
369 } 328 }
370 switch (status) { 329 switch (status) {
371 case PREFAILURE: 330 case PREFAILURE:
372 printf (_("CRITICAL - %d Harddrive PreFailure%cDetected! %d/%d tests failed.\n"), 331 printf(_("CRITICAL - %d Harddrive PreFailure%cDetected! %d/%d tests failed.\n"), prefailure, prefailure > 1 ? 's' : ' ', failed,
373 prefailure, 332 total);
374 prefailure > 1 ? 's' : ' ', 333 status = STATE_CRITICAL;
375 failed,
376 total);
377 status=STATE_CRITICAL;
378 break; 334 break;
379 case ADVISORY: 335 case ADVISORY:
380 printf (_("WARNING - %d Harddrive Advisor%s Detected. %d/%d tests failed.\n"), 336 printf(_("WARNING - %d Harddrive Advisor%s Detected. %d/%d tests failed.\n"), advisory, advisory > 1 ? "ies" : "y", failed, total);
381 advisory, 337 status = STATE_WARNING;
382 advisory > 1 ? "ies" : "y",
383 failed,
384 total);
385 status=STATE_WARNING;
386 break; 338 break;
387 case OPERATIONAL: 339 case OPERATIONAL:
388 printf (_("OK - Operational (%d/%d tests passed)\n"), passed, total); 340 printf(_("OK - Operational (%d/%d tests passed)\n"), passed, total);
389 status=STATE_OK; 341 status = STATE_OK;
390 break; 342 break;
391 default: 343 default:
392 printf (_("ERROR - Status '%d' unknown. %d/%d tests passed\n"), status, 344 printf(_("ERROR - Status '%d' unknown. %d/%d tests passed\n"), status, passed, total);
393 passed, total);
394 status = STATE_UNKNOWN; 345 status = STATE_UNKNOWN;
395 break; 346 break;
396 } 347 }
397 return status; 348 return status;
398} 349}
399 350
400 351void print_value(value_t *p, threshold_t *t) {
401 352 printf("Id=%3d, Status=%2d {%s , %s}, Value=%3d, Threshold=%3d, %s\n", p->id, p->status, p->status & 1 ? "PreFailure" : "Advisory ",
402void 353 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} 354}
410 355
411 356void print_values(values_t *p, thresholds_t *t) {
412 357 value_t *value = p->values;
413void 358 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; 359 int i;
419 for (i = 0; i < NR_ATTRIBUTES; i++) { 360 for (i = 0; i < NR_ATTRIBUTES; i++) {
420 if (value->id && threshold->id && value->id == threshold->id) { 361 if (value->id && threshold->id && value->id == threshold->id) {
421 print_value (value++, threshold++); 362 print_value(value++, threshold++);
422 } 363 }
423 } 364 }
424 printf 365 printf(_("OffLineStatus=%d {%s}, AutoOffLine=%s, OffLineTimeout=%d minutes\n"), p->offline_status,
425 (_("OffLineStatus=%d {%s}, AutoOffLine=%s, OffLineTimeout=%d minutes\n"), 366 get_offline_text(p->offline_status & 0x7f), (p->offline_status & 0x80 ? "Yes" : "No"), p->offline_timeout / 60);
426 p->offline_status, 367 printf(_("OffLineCapability=%d {%s %s %s}\n"), p->offline_capability, p->offline_capability & 1 ? "Immediate" : "",
427 get_offline_text (p->offline_status & 0x7f), 368 p->offline_capability & 2 ? "Auto" : "", p->offline_capability & 4 ? "AbortOnCmd" : "SuspendOnCmd");
428 (p->offline_status & 0x80 ? "Yes" : "No"), 369 printf(_("SmartRevision=%d, CheckSum=%d, SmartCapability=%d {%s %s}\n"), p->revision, p->checksum, p->smart_capability,
429 p->offline_timeout / 60); 370 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} 371}
444 372
445 373int 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; 374 int e = STATE_UNKNOWN;
448#ifdef __linux__ 375#ifdef __linux__
449 __u8 args[4]; 376 __u8 args[4];
@@ -451,14 +378,14 @@ int smart_cmd_simple (int fd, enum SmartCommand command, __u8 val0, bool show_er
451 args[1] = val0; 378 args[1] = val0;
452 args[2] = smart_command[command].value; 379 args[2] = smart_command[command].value;
453 args[3] = 0; 380 args[3] = 0;
454 if (ioctl (fd, HDIO_DRIVE_CMD, &args)) { 381 if (ioctl(fd, HDIO_DRIVE_CMD, &args)) {
455 e = STATE_CRITICAL; 382 e = STATE_CRITICAL;
456 if (show_error) 383 if (show_error)
457 printf (_("CRITICAL - %s: %s\n"), smart_command[command].text, strerror (errno)); 384 printf(_("CRITICAL - %s: %s\n"), smart_command[command].text, strerror(errno));
458 } else { 385 } else {
459 e = STATE_OK; 386 e = STATE_OK;
460 if (show_error) 387 if (show_error)
461 printf (_("OK - Command sent (%s)\n"), smart_command[command].text); 388 printf(_("OK - Command sent (%s)\n"), smart_command[command].text);
462 } 389 }
463 390
464#endif /* __linux__ */ 391#endif /* __linux__ */
@@ -483,35 +410,31 @@ int smart_cmd_simple (int fd, enum SmartCommand command, __u8 val0, bool show_er
483 if (errno != 0) { 410 if (errno != 0) {
484 e = STATE_CRITICAL; 411 e = STATE_CRITICAL;
485 if (show_error) 412 if (show_error)
486 printf (_("CRITICAL - %s: %s\n"), smart_command[command].text, strerror (errno)); 413 printf(_("CRITICAL - %s: %s\n"), smart_command[command].text, strerror(errno));
487 } else { 414 } else {
488 e = STATE_OK; 415 e = STATE_OK;
489 if (show_error) 416 if (show_error)
490 printf (_("OK - Command sent (%s)\n"), smart_command[command].text); 417 printf(_("OK - Command sent (%s)\n"), smart_command[command].text);
491 } 418 }
492 419
493#endif /* __NetBSD__ */ 420#endif /* __NetBSD__ */
494 return e; 421 return e;
495} 422}
496 423
497 424int smart_read_thresholds(int fd, thresholds_t *thresholds) {
498
499int
500smart_read_thresholds (int fd, thresholds_t * thresholds)
501{
502#ifdef __linux__ 425#ifdef __linux__
503 int e; 426 int e;
504 __u8 args[4 + 512]; 427 __u8 args[4 + 512];
505 args[0] = WIN_SMART; 428 args[0] = WIN_SMART;
506 args[1] = 0; 429 args[1] = 0;
507 args[2] = SMART_READ_THRESHOLDS; 430 args[2] = SMART_READ_THRESHOLDS;
508 args[3] = 1; 431 args[3] = 1;
509 if (ioctl (fd, HDIO_DRIVE_CMD, &args)) { 432 if (ioctl(fd, HDIO_DRIVE_CMD, &args)) {
510 e = errno; 433 e = errno;
511 printf (_("CRITICAL - SMART_READ_THRESHOLDS: %s\n"), strerror (errno)); 434 printf(_("CRITICAL - SMART_READ_THRESHOLDS: %s\n"), strerror(errno));
512 return e; 435 return e;
513 } 436 }
514 memcpy (thresholds, args + 4, 512); 437 memcpy(thresholds, args + 4, 512);
515#endif /* __linux__ */ 438#endif /* __linux__ */
516#ifdef __NetBSD__ 439#ifdef __NetBSD__
517 struct atareq req; 440 struct atareq req;
@@ -535,7 +458,7 @@ smart_read_thresholds (int fd, thresholds_t * thresholds)
535 458
536 if (errno != 0) { 459 if (errno != 0) {
537 int e = errno; 460 int e = errno;
538 printf (_("CRITICAL - SMART_READ_THRESHOLDS: %s\n"), strerror (errno)); 461 printf(_("CRITICAL - SMART_READ_THRESHOLDS: %s\n"), strerror(errno));
539 return e; 462 return e;
540 } 463 }
541 464
@@ -544,45 +467,43 @@ smart_read_thresholds (int fd, thresholds_t * thresholds)
544 return 0; 467 return 0;
545} 468}
546 469
470void print_help(void) {
471 print_revision(progname, NP_VERSION);
547 472
548void 473 printf("(C) 1999 Ragnar Hojland Espinosa <ragnar@lightside.dhis.org>\n");
549print_help (void) 474 printf("Plugin implementation - 1999 Robert Dale <rdale@digital-mission.com>\n");
550{ 475 printf(COPYRIGHT, copyright, email);
551 print_revision (progname, NP_VERSION);
552 476
553 printf ("(C) 1999 Ragnar Hojland Espinosa <ragnar@lightside.dhis.org>\n"); 477 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"); 478 "[http://smartlinux.sourceforge.net/smart/index.php]."));
555 printf (COPYRIGHT, copyright, email);
556 479
557 printf (_("This plugin checks a local hard drive with the (Linux specific) SMART interface [http://smartlinux.sourceforge.net/smart/index.php].")); 480 printf("\n\n");
558 481
559 printf ("\n\n"); 482 print_usage();
560 483
561 print_usage (); 484 printf(UT_HELP_VRSN);
485 printf(UT_EXTRA_OPTS);
562 486
563 printf (UT_HELP_VRSN); 487 printf(" %s\n", "-d, --device=DEVICE");
564 printf (UT_EXTRA_OPTS); 488 printf(" %s\n", _("Select device DEVICE"));
489 printf(" %s\n", _("Note: if the device is specified without this option, any further option will"));
490 printf(" %s\n", _("be ignored."));
565 491
566 printf (" %s\n", "-d, --device=DEVICE"); 492 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 493
571 printf (UT_VERBOSE); 494 printf("\n");
495 printf("%s\n", _("Notes:"));
496 printf(" %s\n", _("The SMART command modes (-i/--immediate, -0/--auto-off and -1/--auto-on) were"));
497 printf(" %s\n", _("broken in an underhand manner and have been disabled. You can use smartctl"));
498 printf(" %s\n", _("instead:"));
499 printf(" %s\n", _("-0/--auto-off: use \"smartctl --offlineauto=off\""));
500 printf(" %s\n", _("-1/--auto-on: use \"smartctl --offlineauto=on\""));
501 printf(" %s\n", _("-i/--immediate: use \"smartctl --test=offline\""));
572 502
573 printf ("\n"); 503 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} 504}
584 505
585 /* todo : add to the long nanual as example 506/* todo : add to the long nanual as example
586 * 507 *
587 * Run with: check_ide-smart --nagios [-d] <DRIVE> 508 * Run with: check_ide-smart --nagios [-d] <DRIVE>
588 * Where DRIVE is an IDE drive, ie. /dev/hda, /dev/hdb, /dev/hdc 509 * Where DRIVE is an IDE drive, ie. /dev/hda, /dev/hdb, /dev/hdc
@@ -593,10 +514,7 @@ print_help (void)
593 * - Returns -1 not too often 514 * - Returns -1 not too often
594 */ 515 */
595 516
596 517void print_usage(void) {
597void 518 printf("%s\n", _("Usage:"));
598print_usage (void) 519 printf("%s [-d <device>] [-v]", progname);
599{
600 printf ("%s\n", _("Usage:"));
601 printf ("%s [-d <device>] [-v]", progname);
602} 520}
diff --git a/plugins/check_ldap.c b/plugins/check_ldap.c
index 868ffc1..87818da 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"
@@ -47,37 +47,37 @@ enum {
47 DEFAULT_PORT = 389 47 DEFAULT_PORT = 389
48}; 48};
49 49
50int process_arguments (int, char **); 50static int process_arguments (int, char **);
51int validate_arguments (void); 51static int validate_arguments (void);
52void print_help (void); 52static void print_help (void);
53void print_usage (void); 53void print_usage (void);
54 54
55char ld_defattr[] = "(objectclass=*)"; 55static char ld_defattr[] = "(objectclass=*)";
56char *ld_attr = ld_defattr; 56static char *ld_attr = ld_defattr;
57char *ld_host = NULL; 57static char *ld_host = NULL;
58char *ld_base = NULL; 58static char *ld_base = NULL;
59char *ld_passwd = NULL; 59static char *ld_passwd = NULL;
60char *ld_binddn = NULL; 60static char *ld_binddn = NULL;
61int ld_port = -1; 61static int ld_port = -1;
62#ifdef HAVE_LDAP_SET_OPTION 62#ifdef HAVE_LDAP_SET_OPTION
63int ld_protocol = DEFAULT_PROTOCOL; 63static int ld_protocol = DEFAULT_PROTOCOL;
64#endif 64#endif
65#ifndef LDAP_OPT_SUCCESS 65#ifndef LDAP_OPT_SUCCESS
66# define LDAP_OPT_SUCCESS LDAP_SUCCESS 66# define LDAP_OPT_SUCCESS LDAP_SUCCESS
67#endif 67#endif
68double warn_time = UNDEFINED; 68static double warn_time = UNDEFINED;
69double crit_time = UNDEFINED; 69static double crit_time = UNDEFINED;
70thresholds *entries_thresholds = NULL; 70static thresholds *entries_thresholds = NULL;
71struct timeval tv; 71static struct timeval tv;
72char* warn_entries = NULL; 72static char* warn_entries = NULL;
73char* crit_entries = NULL; 73static char* crit_entries = NULL;
74bool starttls = false; 74static bool starttls = false;
75bool ssl_on_connect = false; 75static bool ssl_on_connect = false;
76bool verbose = false; 76static bool verbose = false;
77 77
78/* for ldap tls */ 78/* for ldap tls */
79 79
80char *SERVICE = "LDAP"; 80static char *SERVICE = "LDAP";
81 81
82int 82int
83main (int argc, char *argv[]) 83main (int argc, char *argv[])
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 6a7daf1..8a73772 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
@@ -45,23 +45,23 @@ const char *email = "devel@monitoring-plugins.org";
45#include <mysqld_error.h> 45#include <mysqld_error.h>
46#include <errmsg.h> 46#include <errmsg.h>
47 47
48char *db_user = NULL; 48static char *db_user = NULL;
49char *db_host = NULL; 49static char *db_host = NULL;
50char *db_socket = NULL; 50static char *db_socket = NULL;
51char *db_pass = NULL; 51static char *db_pass = NULL;
52char *db = NULL; 52static char *db = NULL;
53char *ca_cert = NULL; 53static char *ca_cert = NULL;
54char *ca_dir = NULL; 54static char *ca_dir = NULL;
55char *cert = NULL; 55static char *cert = NULL;
56char *key = NULL; 56static char *key = NULL;
57char *ciphers = NULL; 57static char *ciphers = NULL;
58bool ssl = false; 58static bool ssl = false;
59char *opt_file = NULL; 59static char *opt_file = NULL;
60char *opt_group = NULL; 60static char *opt_group = NULL;
61unsigned int db_port = MYSQL_PORT; 61static unsigned int db_port = MYSQL_PORT;
62int check_slave = 0, warn_sec = 0, crit_sec = 0; 62static bool check_slave = false;
63int ignore_auth = 0; 63static bool ignore_auth = false;
64int verbose = 0; 64static int verbose = 0;
65 65
66static double warning_time = 0; 66static double warning_time = 0;
67static double critical_time = 0; 67static double critical_time = 0;
@@ -91,11 +91,11 @@ static const char *metric_counter[LENGTH_METRIC_COUNTER] = {
91 91
92#define MYSQLDUMP_THREADS_QUERY "SELECT COUNT(1) mysqldumpThreads FROM information_schema.processlist WHERE info LIKE 'SELECT /*!40001 SQL_NO_CACHE */%'" 92#define MYSQLDUMP_THREADS_QUERY "SELECT COUNT(1) mysqldumpThreads FROM information_schema.processlist WHERE info LIKE 'SELECT /*!40001 SQL_NO_CACHE */%'"
93 93
94thresholds *my_threshold = NULL; 94static thresholds *my_threshold = NULL;
95 95
96int process_arguments (int, char **); 96static int process_arguments (int, char **);
97int validate_arguments (void); 97static int validate_arguments (void);
98void print_help (void); 98static void print_help (void);
99void print_usage (void); 99void print_usage (void);
100 100
101int 101int
@@ -456,10 +456,10 @@ process_arguments (int argc, char **argv)
456 db_port = atoi (optarg); 456 db_port = atoi (optarg);
457 break; 457 break;
458 case 'S': 458 case 'S':
459 check_slave = 1; /* check-slave */ 459 check_slave = true; /* check-slave */
460 break; 460 break;
461 case 'n': 461 case 'n':
462 ignore_auth = 1; /* ignore-auth */ 462 ignore_auth = true; /* ignore-auth */
463 break; 463 break;
464 case 'w': 464 case 'w':
465 warning = optarg; 465 warning = optarg;
diff --git a/plugins/check_mysql_query.c b/plugins/check_mysql_query.c
index 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..dec0b66 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,74 @@ enum {
59 PORT = 1248 59 PORT = 1248
60}; 60};
61 61
62char *server_address=NULL; 62static char *server_address = NULL;
63char *volume_name=NULL; 63static int server_port = PORT;
64int server_port=PORT; 64static char *value_list = NULL;
65char *value_list=NULL; 65static char *req_password = NULL;
66char *req_password=NULL; 66static unsigned long lvalue_list[MAX_VALUE_LIST];
67unsigned long lvalue_list[MAX_VALUE_LIST]; 67static unsigned long warning_value = 0L;
68unsigned long warning_value=0L; 68static unsigned long critical_value = 0L;
69unsigned long critical_value=0L; 69static bool check_warning_value = false;
70bool check_warning_value=false; 70static bool check_critical_value = false;
71bool check_critical_value=false; 71static enum checkvars vars_to_check = CHECK_NONE;
72enum checkvars vars_to_check = CHECK_NONE; 72static bool show_all = false;
73bool show_all = false; 73
74 74static char recv_buffer[MAX_INPUT_BUFFER];
75char recv_buffer[MAX_INPUT_BUFFER]; 75
76 76static void fetch_data(const char *address, int port, const char *sendb);
77void fetch_data (const char* address, int port, const char* sendb); 77static int process_arguments(int /*argc*/, char ** /*argv*/);
78int process_arguments(int, char **); 78static void preparelist(char *string);
79void preparelist(char *string); 79static bool strtoularray(unsigned long *array, char *string, const char *delim);
80bool strtoularray(unsigned long *array, char *string, const char *delim); 80static void print_help(void);
81void print_help(void);
82void print_usage(void); 81void print_usage(void);
83 82
84int main(int argc, char **argv){ 83int main(int argc, char **argv) {
85 84
86/* should be int result = STATE_UNKNOWN; */ 85 /* should be int result = STATE_UNKNOWN; */
87 86
88 int return_code = STATE_UNKNOWN; 87 int return_code = STATE_UNKNOWN;
89 char *send_buffer=NULL; 88 char *send_buffer = NULL;
90 char *output_message=NULL; 89 char *output_message = NULL;
91 char *perfdata=NULL; 90 char *perfdata = NULL;
92 char *temp_string=NULL; 91 char *temp_string = NULL;
93 char *temp_string_perf=NULL; 92 char *temp_string_perf = NULL;
94 char *description=NULL,*counter_unit = NULL; 93 char *description = NULL, *counter_unit = NULL;
95 char *minval = NULL, *maxval = NULL, *errcvt = NULL; 94 char *minval = NULL, *maxval = NULL, *errcvt = NULL;
96 char *fds=NULL, *tds=NULL; 95 char *fds = NULL, *tds = NULL;
97 char *numstr; 96 char *numstr;
98 97
99 double total_disk_space=0; 98 double total_disk_space = 0;
100 double free_disk_space=0; 99 double free_disk_space = 0;
101 double percent_used_space=0; 100 double percent_used_space = 0;
102 double warning_used_space=0; 101 double warning_used_space = 0;
103 double critical_used_space=0; 102 double critical_used_space = 0;
104 double mem_commitLimit=0; 103 double mem_commitLimit = 0;
105 double mem_commitByte=0; 104 double mem_commitByte = 0;
106 double fminval = 0, fmaxval = 0; 105 double fminval = 0, fmaxval = 0;
107 unsigned long utilization; 106 unsigned long utilization;
108 unsigned long uptime; 107 unsigned long uptime;
109 unsigned long age_in_minutes; 108 unsigned long age_in_minutes;
110 double counter_value = 0.0; 109 double counter_value = 0.0;
111 int offset=0; 110 int offset = 0;
112 int updays=0; 111 int updays = 0;
113 int uphours=0; 112 int uphours = 0;
114 int upminutes=0; 113 int upminutes = 0;
115 114
116 bool isPercent = false; 115 bool isPercent = false;
117 bool allRight = false; 116 bool allRight = false;
118 117
119 setlocale (LC_ALL, ""); 118 setlocale(LC_ALL, "");
120 bindtextdomain (PACKAGE, LOCALEDIR); 119 bindtextdomain(PACKAGE, LOCALEDIR);
121 textdomain (PACKAGE); 120 textdomain(PACKAGE);
122 121
123 /* Parse extra opts if any */ 122 /* Parse extra opts if any */
124 argv=np_extra_opts (&argc, argv, progname); 123 argv = np_extra_opts(&argc, argv, progname);
125 124
126 if(process_arguments(argc,argv) == ERROR) 125 if (process_arguments(argc, argv) == ERROR)
127 usage4 (_("Could not parse arguments")); 126 usage4(_("Could not parse arguments"));
128 127
129 /* initialize alarm signal handling */ 128 /* initialize alarm signal handling */
130 signal(SIGALRM,socket_timeout_alarm_handler); 129 signal(SIGALRM, socket_timeout_alarm_handler);
131 130
132 /* set socket timeout */ 131 /* set socket timeout */
133 alarm(socket_timeout); 132 alarm(socket_timeout);
@@ -137,61 +136,58 @@ int main(int argc, char **argv){
137 case CHECK_CLIENTVERSION: 136 case CHECK_CLIENTVERSION:
138 137
139 xasprintf(&send_buffer, "%s&1", req_password); 138 xasprintf(&send_buffer, "%s&1", req_password);
140 fetch_data (server_address, server_port, send_buffer); 139 fetch_data(server_address, server_port, send_buffer);
141 if (value_list != NULL && strcmp(recv_buffer, value_list) != 0) { 140 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); 141 xasprintf(&output_message, _("Wrong client version - running: %s, required: %s"), recv_buffer, value_list);
143 return_code = STATE_WARNING; 142 return_code = STATE_WARNING;
144 } else { 143 } else {
145 xasprintf (&output_message, "%s", recv_buffer); 144 xasprintf(&output_message, "%s", recv_buffer);
146 return_code = STATE_OK; 145 return_code = STATE_OK;
147 } 146 }
148 break; 147 break;
149 148
150 case CHECK_CPULOAD: 149 case CHECK_CPULOAD:
151 150
152 if (value_list==NULL) 151 if (value_list == NULL)
153 output_message = strdup (_("missing -l parameters")); 152 output_message = strdup(_("missing -l parameters"));
154 else if (! strtoularray(lvalue_list,value_list,",")) 153 else if (!strtoularray(lvalue_list, value_list, ","))
155 output_message = strdup (_("wrong -l parameter.")); 154 output_message = strdup(_("wrong -l parameter."));
156 else { 155 else {
157 /* -l parameters is present with only integers */ 156 /* -l parameters is present with only integers */
158 return_code=STATE_OK; 157 return_code = STATE_OK;
159 temp_string = strdup (_("CPU Load")); 158 temp_string = strdup(_("CPU Load"));
160 temp_string_perf = strdup (" "); 159 temp_string_perf = strdup(" ");
161 160
162 /* loop until one of the parameters is wrong or not present */ 161 /* loop until one of the parameters is wrong or not present */
163 while (lvalue_list[0+offset]> (unsigned long)0 && 162 while (lvalue_list[0 + offset] > (unsigned long)0 && lvalue_list[0 + offset] <= (unsigned long)17280 &&
164 lvalue_list[0+offset]<=(unsigned long)17280 && 163 lvalue_list[1 + offset] > (unsigned long)0 && lvalue_list[1 + offset] <= (unsigned long)100 &&
165 lvalue_list[1+offset]> (unsigned long)0 && 164 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 165
170 /* Send request and retrieve data */ 166 /* Send request and retrieve data */
171 xasprintf(&send_buffer,"%s&2&%lu",req_password,lvalue_list[0+offset]); 167 xasprintf(&send_buffer, "%s&2&%lu", req_password, lvalue_list[0 + offset]);
172 fetch_data (server_address, server_port, send_buffer); 168 fetch_data(server_address, server_port, send_buffer);
173 169
174 utilization=strtoul(recv_buffer,NULL,10); 170 utilization = strtoul(recv_buffer, NULL, 10);
175 171
176 /* Check if any of the request is in a warning or critical state */ 172 /* Check if any of the request is in a warning or critical state */
177 if(utilization >= lvalue_list[2+offset]) 173 if (utilization >= lvalue_list[2 + offset])
178 return_code=STATE_CRITICAL; 174 return_code = STATE_CRITICAL;
179 else if(utilization >= lvalue_list[1+offset] && return_code<STATE_WARNING) 175 else if (utilization >= lvalue_list[1 + offset] && return_code < STATE_WARNING)
180 return_code=STATE_WARNING; 176 return_code = STATE_WARNING;
181 177
182 xasprintf(&output_message,_(" %lu%% (%lu min average)"), utilization, lvalue_list[0+offset]); 178 xasprintf(&output_message, _(" %lu%% (%lu min average)"), utilization, lvalue_list[0 + offset]);
183 xasprintf(&temp_string,"%s%s",temp_string,output_message); 179 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, 180 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]); 181 lvalue_list[1 + offset], lvalue_list[2 + offset]);
186 xasprintf(&temp_string_perf,"%s%s",temp_string_perf,perfdata); 182 xasprintf(&temp_string_perf, "%s%s", temp_string_perf, perfdata);
187 offset+=3; /* move across the array */ 183 offset += 3; /* move across the array */
188 } 184 }
189 185
190 if (strlen(temp_string)>10) { /* we had at least one loop */ 186 if (strlen(temp_string) > 10) { /* we had at least one loop */
191 output_message = strdup (temp_string); 187 output_message = strdup(temp_string);
192 perfdata = temp_string_perf; 188 perfdata = temp_string_perf;
193 } else 189 } else
194 output_message = strdup (_("not enough values for -l parameters")); 190 output_message = strdup(_("not enough values for -l parameters"));
195 } 191 }
196 break; 192 break;
197 193
@@ -200,16 +196,14 @@ int main(int argc, char **argv){
200 if (value_list == NULL) { 196 if (value_list == NULL) {
201 value_list = "minutes"; 197 value_list = "minutes";
202 } 198 }
203 if (strncmp(value_list, "seconds", strlen("seconds") + 1 ) && 199 if (strncmp(value_list, "seconds", strlen("seconds") + 1) && strncmp(value_list, "minutes", strlen("minutes") + 1) &&
204 strncmp(value_list, "minutes", strlen("minutes") + 1) && 200 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 201
208 output_message = strdup (_("wrong -l argument")); 202 output_message = strdup(_("wrong -l argument"));
209 } else { 203 } else {
210 xasprintf(&send_buffer, "%s&3", req_password); 204 xasprintf(&send_buffer, "%s&3", req_password);
211 fetch_data (server_address, server_port, send_buffer); 205 fetch_data(server_address, server_port, send_buffer);
212 uptime=strtoul(recv_buffer,NULL,10); 206 uptime = strtoul(recv_buffer, NULL, 10);
213 updays = uptime / 86400; 207 updays = uptime / 86400;
214 uphours = (uptime % 86400) / 3600; 208 uphours = (uptime % 86400) / 3600;
215 upminutes = ((uptime % 86400) % 3600) / 60; 209 upminutes = ((uptime % 86400) % 3600) / 60;
@@ -222,57 +216,58 @@ int main(int argc, char **argv){
222 uptime = uptime / 86400; 216 uptime = uptime / 86400;
223 /* else uptime in seconds, nothing to do */ 217 /* else uptime in seconds, nothing to do */
224 218
225 xasprintf(&output_message,_("System Uptime - %u day(s) %u hour(s) %u minute(s) |uptime=%lu"),updays, uphours, upminutes, uptime); 219 xasprintf(&output_message, _("System Uptime - %u day(s) %u hour(s) %u minute(s) |uptime=%lu"), updays, uphours, upminutes,
220 uptime);
226 221
227 if (check_critical_value && uptime <= critical_value) 222 if (check_critical_value && uptime <= critical_value)
228 return_code=STATE_CRITICAL; 223 return_code = STATE_CRITICAL;
229 else if (check_warning_value && uptime <= warning_value) 224 else if (check_warning_value && uptime <= warning_value)
230 return_code=STATE_WARNING; 225 return_code = STATE_WARNING;
231 else 226 else
232 return_code=STATE_OK; 227 return_code = STATE_OK;
233 } 228 }
234 break; 229 break;
235 230
236 case CHECK_USEDDISKSPACE: 231 case CHECK_USEDDISKSPACE:
237 232
238 if (value_list==NULL) 233 if (value_list == NULL)
239 output_message = strdup (_("missing -l parameters")); 234 output_message = strdup(_("missing -l parameters"));
240 else if (strlen(value_list)!=1) 235 else if (strlen(value_list) != 1)
241 output_message = strdup (_("wrong -l argument")); 236 output_message = strdup(_("wrong -l argument"));
242 else { 237 else {
243 xasprintf(&send_buffer,"%s&4&%s", req_password, value_list); 238 xasprintf(&send_buffer, "%s&4&%s", req_password, value_list);
244 fetch_data (server_address, server_port, send_buffer); 239 fetch_data(server_address, server_port, send_buffer);
245 fds=strtok(recv_buffer,"&"); 240 fds = strtok(recv_buffer, "&");
246 tds=strtok(NULL,"&"); 241 tds = strtok(NULL, "&");
247 if(fds!=NULL) 242 if (fds != NULL)
248 free_disk_space=atof(fds); 243 free_disk_space = atof(fds);
249 if(tds!=NULL) 244 if (tds != NULL)
250 total_disk_space=atof(tds); 245 total_disk_space = atof(tds);
251 246
252 if (total_disk_space>0 && free_disk_space>=0) { 247 if (total_disk_space > 0 && free_disk_space >= 0) {
253 percent_used_space = ((total_disk_space - free_disk_space) / total_disk_space) * 100; 248 percent_used_space = ((total_disk_space - free_disk_space) / total_disk_space) * 100;
254 warning_used_space = ((float)warning_value / 100) * total_disk_space; 249 warning_used_space = ((float)warning_value / 100) * total_disk_space;
255 critical_used_space = ((float)critical_value / 100) * total_disk_space; 250 critical_used_space = ((float)critical_value / 100) * total_disk_space;
256 251
257 xasprintf(&temp_string,_("%s:\\ - total: %.2f Gb - used: %.2f Gb (%.0f%%) - free %.2f Gb (%.0f%%)"), 252 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, 253 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); 254 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, 255 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, 256 (total_disk_space - free_disk_space) / 1073741824, warning_used_space / 1073741824,
262 critical_used_space / 1073741824, total_disk_space / 1073741824); 257 critical_used_space / 1073741824, total_disk_space / 1073741824);
263 258
264 if(check_critical_value && percent_used_space >= critical_value) 259 if (check_critical_value && percent_used_space >= critical_value)
265 return_code=STATE_CRITICAL; 260 return_code = STATE_CRITICAL;
266 else if (check_warning_value && percent_used_space >= warning_value) 261 else if (check_warning_value && percent_used_space >= warning_value)
267 return_code=STATE_WARNING; 262 return_code = STATE_WARNING;
268 else 263 else
269 return_code=STATE_OK; 264 return_code = STATE_OK;
270 265
271 output_message = strdup (temp_string); 266 output_message = strdup(temp_string);
272 perfdata = temp_string_perf; 267 perfdata = temp_string_perf;
273 } else { 268 } else {
274 output_message = strdup (_("Free disk space : Invalid drive")); 269 output_message = strdup(_("Free disk space : Invalid drive"));
275 return_code=STATE_UNKNOWN; 270 return_code = STATE_UNKNOWN;
276 } 271 }
277 } 272 }
278 break; 273 break;
@@ -280,57 +275,56 @@ int main(int argc, char **argv){
280 case CHECK_SERVICESTATE: 275 case CHECK_SERVICESTATE:
281 case CHECK_PROCSTATE: 276 case CHECK_PROCSTATE:
282 277
283 if (value_list==NULL) 278 if (value_list == NULL)
284 output_message = strdup (_("No service/process specified")); 279 output_message = strdup(_("No service/process specified"));
285 else { 280 else {
286 preparelist(value_list); /* replace , between services with & to send the request */ 281 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, 282 xasprintf(&send_buffer, "%s&%u&%s&%s", req_password, (vars_to_check == CHECK_SERVICESTATE) ? 5 : 6,
288 (show_all) ? "ShowAll" : "ShowFail",value_list); 283 (show_all) ? "ShowAll" : "ShowFail", value_list);
289 fetch_data (server_address, server_port, send_buffer); 284 fetch_data(server_address, server_port, send_buffer);
290 numstr = strtok(recv_buffer,"&"); 285 numstr = strtok(recv_buffer, "&");
291 if (numstr == NULL) 286 if (numstr == NULL)
292 die(STATE_UNKNOWN, _("could not fetch information from server\n")); 287 die(STATE_UNKNOWN, _("could not fetch information from server\n"));
293 return_code=atoi(numstr); 288 return_code = atoi(numstr);
294 temp_string=strtok(NULL,"&"); 289 temp_string = strtok(NULL, "&");
295 output_message = strdup (temp_string); 290 output_message = strdup(temp_string);
296 } 291 }
297 break; 292 break;
298 293
299 case CHECK_MEMUSE: 294 case CHECK_MEMUSE:
300 295
301 xasprintf(&send_buffer,"%s&7", req_password); 296 xasprintf(&send_buffer, "%s&7", req_password);
302 fetch_data (server_address, server_port, send_buffer); 297 fetch_data(server_address, server_port, send_buffer);
303 numstr = strtok(recv_buffer,"&"); 298 numstr = strtok(recv_buffer, "&");
304 if (numstr == NULL) 299 if (numstr == NULL)
305 die(STATE_UNKNOWN, _("could not fetch information from server\n")); 300 die(STATE_UNKNOWN, _("could not fetch information from server\n"));
306 mem_commitLimit=atof(numstr); 301 mem_commitLimit = atof(numstr);
307 numstr = strtok(NULL,"&"); 302 numstr = strtok(NULL, "&");
308 if (numstr == NULL) 303 if (numstr == NULL)
309 die(STATE_UNKNOWN, _("could not fetch information from server\n")); 304 die(STATE_UNKNOWN, _("could not fetch information from server\n"));
310 mem_commitByte=atof(numstr); 305 mem_commitByte = atof(numstr);
311 percent_used_space = (mem_commitByte / mem_commitLimit) * 100; 306 percent_used_space = (mem_commitByte / mem_commitLimit) * 100;
312 warning_used_space = ((float)warning_value / 100) * mem_commitLimit; 307 warning_used_space = ((float)warning_value / 100) * mem_commitLimit;
313 critical_used_space = ((float)critical_value / 100) * mem_commitLimit; 308 critical_used_space = ((float)critical_value / 100) * mem_commitLimit;
314 309
315 /* Divisor should be 1048567, not 3044515, as we are measuring "Commit Charge" here, 310 /* Divisor should be 1048567, not 3044515, as we are measuring "Commit Charge" here,
316 which equals RAM + Pagefiles. */ 311 which equals RAM + Pagefiles. */
317 xasprintf(&output_message,_("Memory usage: total:%.2f MB - used: %.2f MB (%.0f%%) - free: %.2f MB (%.0f%%)"), 312 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, 313 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); 314 (mem_commitLimit - mem_commitByte) / mem_commitLimit * 100);
320 xasprintf(&perfdata,_("'Memory usage'=%.2fMB;%.2f;%.2f;0.00;%.2f"), mem_commitByte / 1048567, 315 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); 316 critical_used_space / 1048567, mem_commitLimit / 1048567);
322 317
323 return_code=STATE_OK; 318 return_code = STATE_OK;
324 if(check_critical_value && percent_used_space >= critical_value) 319 if (check_critical_value && percent_used_space >= critical_value)
325 return_code=STATE_CRITICAL; 320 return_code = STATE_CRITICAL;
326 else if (check_warning_value && percent_used_space >= warning_value) 321 else if (check_warning_value && percent_used_space >= warning_value)
327 return_code=STATE_WARNING; 322 return_code = STATE_WARNING;
328 323
329 break; 324 break;
330 325
331 case CHECK_COUNTER: 326 case CHECK_COUNTER:
332 327
333
334 /* 328 /*
335 CHECK_COUNTER has been modified to provide extensive perfdata information. 329 CHECK_COUNTER has been modified to provide extensive perfdata information.
336 In order to do this, some modifications have been done to the code 330 In order to do this, some modifications have been done to the code
@@ -353,311 +347,290 @@ int main(int argc, char **argv){
353 */ 347 */
354 348
355 if (value_list == NULL) 349 if (value_list == NULL)
356 output_message = strdup (_("No counter specified")); 350 output_message = strdup(_("No counter specified"));
357 else 351 else {
358 { 352 preparelist(value_list); /* replace , between services with & to send the request */
359 preparelist (value_list); /* replace , between services with & to send the request */ 353 isPercent = (strchr(value_list, '%') != NULL);
360 isPercent = (strchr (value_list, '%') != NULL); 354
361 355 strtok(value_list, "&"); /* burn the first parameters */
362 strtok (value_list, "&"); /* burn the first parameters */ 356 description = strtok(NULL, "&");
363 description = strtok (NULL, "&"); 357 counter_unit = strtok(NULL, "&");
364 counter_unit = strtok (NULL, "&"); 358 xasprintf(&send_buffer, "%s&8&%s", req_password, value_list);
365 xasprintf (&send_buffer, "%s&8&%s", req_password, value_list); 359 fetch_data(server_address, server_port, send_buffer);
366 fetch_data (server_address, server_port, send_buffer); 360 counter_value = atof(recv_buffer);
367 counter_value = atof (recv_buffer);
368 361
369 if (description == NULL) 362 if (description == NULL)
370 xasprintf (&output_message, "%.f", counter_value); 363 xasprintf(&output_message, "%.f", counter_value);
371 else if (isPercent) 364 else if (isPercent) {
372 { 365 counter_unit = strdup("%");
373 counter_unit = strdup ("%");
374 allRight = true; 366 allRight = true;
375 } 367 }
376 368
377 if ((counter_unit != NULL) && (!allRight)) 369 if ((counter_unit != NULL) && (!allRight)) {
378 { 370 minval = strtok(NULL, "&");
379 minval = strtok (NULL, "&"); 371 maxval = strtok(NULL, "&");
380 maxval = strtok (NULL, "&");
381 372
382 /* All parameters specified. Let's check the numbers */ 373 /* All parameters specified. Let's check the numbers */
383 374
384 fminval = (minval != NULL) ? strtod (minval, &errcvt) : -1; 375 fminval = (minval != NULL) ? strtod(minval, &errcvt) : -1;
385 fmaxval = (minval != NULL) ? strtod (maxval, &errcvt) : -1; 376 fmaxval = (minval != NULL) ? strtod(maxval, &errcvt) : -1;
386 377
387 if ((fminval == 0) && (minval == errcvt)) 378 if ((fminval == 0) && (minval == errcvt))
388 output_message = strdup (_("Minimum value contains non-numbers")); 379 output_message = strdup(_("Minimum value contains non-numbers"));
389 else 380 else {
390 {
391 if ((fmaxval == 0) && (maxval == errcvt)) 381 if ((fmaxval == 0) && (maxval == errcvt))
392 output_message = strdup (_("Maximum value contains non-numbers")); 382 output_message = strdup(_("Maximum value contains non-numbers"));
393 else 383 else
394 allRight = true; /* Everything is OK. */ 384 allRight = true; /* Everything is OK. */
395
396 } 385 }
397 } 386 } else if ((counter_unit == NULL) && (description != NULL))
398 else if ((counter_unit == NULL) && (description != NULL)) 387 output_message = strdup(_("No unit counter specified"));
399 output_message = strdup (_("No unit counter specified"));
400 388
401 if (allRight) 389 if (allRight) {
402 {
403 /* Let's format the output string, finally... */ 390 /* Let's format the output string, finally... */
404 if (strstr(description, "%") == NULL) { 391 if (strstr(description, "%") == NULL) {
405 xasprintf (&output_message, "%s = %.2f %s", description, counter_value, counter_unit); 392 xasprintf(&output_message, "%s = %.2f %s", description, counter_value, counter_unit);
406 } else { 393 } else {
407 /* has formatting, will segv if wrong */ 394 /* has formatting, will segv if wrong */
408 xasprintf (&output_message, description, counter_value); 395 xasprintf(&output_message, description, counter_value);
409 } 396 }
410 xasprintf (&output_message, "%s |", output_message); 397 xasprintf(&output_message, "%s |", output_message);
411 xasprintf (&output_message,"%s %s", output_message, 398 xasprintf(&output_message, "%s %s", output_message,
412 fperfdata (description, counter_value, 399 fperfdata(description, counter_value, counter_unit, 1, warning_value, 1, critical_value,
413 counter_unit, 1, warning_value, 1, critical_value, 400 (!(isPercent) && (minval != NULL)), fminval, (!(isPercent) && (minval != NULL)), fmaxval));
414 (!(isPercent) && (minval != NULL)), fminval,
415 (!(isPercent) && (minval != NULL)), fmaxval));
416 } 401 }
417 } 402 }
418 403
419 if (critical_value > warning_value) 404 if (critical_value > warning_value) { /* Normal thresholds */
420 { /* Normal thresholds */
421 if (check_critical_value && counter_value >= critical_value) 405 if (check_critical_value && counter_value >= critical_value)
422 return_code = STATE_CRITICAL; 406 return_code = STATE_CRITICAL;
423 else if (check_warning_value && counter_value >= warning_value) 407 else if (check_warning_value && counter_value >= warning_value)
424 return_code = STATE_WARNING; 408 return_code = STATE_WARNING;
425 else 409 else
426 return_code = STATE_OK; 410 return_code = STATE_OK;
427 } 411 } else { /* inverse thresholds */
428 else
429 { /* inverse thresholds */
430 return_code = STATE_OK; 412 return_code = STATE_OK;
431 if (check_critical_value && counter_value <= critical_value) 413 if (check_critical_value && counter_value <= critical_value)
432 return_code = STATE_CRITICAL; 414 return_code = STATE_CRITICAL;
433 else if (check_warning_value && counter_value <= warning_value) 415 else if (check_warning_value && counter_value <= warning_value)
434 return_code = STATE_WARNING; 416 return_code = STATE_WARNING;
435 } 417 }
436 break; 418 break;
437 419
438 case CHECK_FILEAGE: 420 case CHECK_FILEAGE:
439 421
440 if (value_list==NULL) 422 if (value_list == NULL)
441 output_message = strdup (_("No counter specified")); 423 output_message = strdup(_("No counter specified"));
442 else { 424 else {
443 preparelist(value_list); /* replace , between services with & to send the request */ 425 preparelist(value_list); /* replace , between services with & to send the request */
444 xasprintf(&send_buffer,"%s&9&%s", req_password,value_list); 426 xasprintf(&send_buffer, "%s&9&%s", req_password, value_list);
445 fetch_data (server_address, server_port, send_buffer); 427 fetch_data(server_address, server_port, send_buffer);
446 age_in_minutes = atoi(strtok(recv_buffer,"&")); 428 age_in_minutes = atoi(strtok(recv_buffer, "&"));
447 description = strtok(NULL,"&"); 429 description = strtok(NULL, "&");
448 output_message = strdup (description); 430 output_message = strdup(description);
449 431
450 if (critical_value > warning_value) { /* Normal thresholds */ 432 if (critical_value > warning_value) { /* Normal thresholds */
451 if(check_critical_value && age_in_minutes >= critical_value) 433 if (check_critical_value && age_in_minutes >= critical_value)
452 return_code=STATE_CRITICAL; 434 return_code = STATE_CRITICAL;
453 else if (check_warning_value && age_in_minutes >= warning_value) 435 else if (check_warning_value && age_in_minutes >= warning_value)
454 return_code=STATE_WARNING; 436 return_code = STATE_WARNING;
455 else 437 else
456 return_code=STATE_OK; 438 return_code = STATE_OK;
457 } 439 } else { /* inverse thresholds */
458 else { /* inverse thresholds */ 440 if (check_critical_value && age_in_minutes <= critical_value)
459 if(check_critical_value && age_in_minutes <= critical_value) 441 return_code = STATE_CRITICAL;
460 return_code=STATE_CRITICAL;
461 else if (check_warning_value && age_in_minutes <= warning_value) 442 else if (check_warning_value && age_in_minutes <= warning_value)
462 return_code=STATE_WARNING; 443 return_code = STATE_WARNING;
463 else 444 else
464 return_code=STATE_OK; 445 return_code = STATE_OK;
465 } 446 }
466 } 447 }
467 break; 448 break;
468 449
469 case CHECK_INSTANCES: 450 case CHECK_INSTANCES:
470 if (value_list==NULL) 451 if (value_list == NULL)
471 output_message = strdup (_("No counter specified")); 452 output_message = strdup(_("No counter specified"));
472 else { 453 else {
473 xasprintf(&send_buffer,"%s&10&%s", req_password,value_list); 454 xasprintf(&send_buffer, "%s&10&%s", req_password, value_list);
474 fetch_data (server_address, server_port, send_buffer); 455 fetch_data(server_address, server_port, send_buffer);
475 if (!strncmp(recv_buffer,"ERROR",5)) { 456 if (!strncmp(recv_buffer, "ERROR", 5)) {
476 printf("NSClient - %s\n",recv_buffer); 457 printf("NSClient - %s\n", recv_buffer);
477 exit(STATE_UNKNOWN); 458 exit(STATE_UNKNOWN);
478 } 459 }
479 xasprintf(&output_message,"%s",recv_buffer); 460 xasprintf(&output_message, "%s", recv_buffer);
480 return_code=STATE_OK; 461 return_code = STATE_OK;
481 } 462 }
482 break; 463 break;
483 464
484 case CHECK_NONE: 465 case CHECK_NONE:
485 default: 466 default:
486 usage4 (_("Please specify a variable to check")); 467 usage4(_("Please specify a variable to check"));
487 break; 468 break;
488
489 } 469 }
490 470
491 /* reset timeout */ 471 /* reset timeout */
492 alarm(0); 472 alarm(0);
493 473
494 if (perfdata==NULL) 474 if (perfdata == NULL)
495 printf("%s\n",output_message); 475 printf("%s\n", output_message);
496 else 476 else
497 printf("%s | %s\n",output_message,perfdata); 477 printf("%s | %s\n", output_message, perfdata);
498 return return_code; 478 return return_code;
499} 479}
500 480
501
502
503/* process command-line arguments */ 481/* process command-line arguments */
504int process_arguments(int argc, char **argv){ 482int process_arguments(int argc, char **argv) {
505 int c; 483 int c;
506 484
507 int option = 0; 485 int option = 0;
508 static struct option longopts[] = 486 static struct option longopts[] = {{"port", required_argument, 0, 'p'},
509 { 487 {"timeout", required_argument, 0, 't'},
510 {"port", required_argument,0,'p'}, 488 {"critical", required_argument, 0, 'c'},
511 {"timeout", required_argument,0,'t'}, 489 {"warning", required_argument, 0, 'w'},
512 {"critical", required_argument,0,'c'}, 490 {"variable", required_argument, 0, 'v'},
513 {"warning", required_argument,0,'w'}, 491 {"hostname", required_argument, 0, 'H'},
514 {"variable", required_argument,0,'v'}, 492 {"params", required_argument, 0, 'l'},
515 {"hostname", required_argument,0,'H'}, 493 {"secret", required_argument, 0, 's'},
516 {"params", required_argument,0,'l'}, 494 {"display", required_argument, 0, 'd'},
517 {"secret", required_argument,0,'s'}, 495 {"unknown-timeout", no_argument, 0, 'u'},
518 {"display", required_argument,0,'d'}, 496 {"version", no_argument, 0, 'V'},
519 {"unknown-timeout", no_argument, 0, 'u'}, 497 {"help", no_argument, 0, 'h'},
520 {"version", no_argument, 0,'V'}, 498 {0, 0, 0, 0}};
521 {"help", no_argument, 0,'h'},
522 {0,0,0,0}
523 };
524 499
525 /* no options were supplied */ 500 /* no options were supplied */
526 if(argc<2) return ERROR; 501 if (argc < 2)
502 return ERROR;
527 503
528 /* backwards compatibility */ 504 /* backwards compatibility */
529 if (! is_option(argv[1])) { 505 if (!is_option(argv[1])) {
530 server_address = strdup(argv[1]); 506 server_address = strdup(argv[1]);
531 argv[1]=argv[0]; 507 argv[1] = argv[0];
532 argv=&argv[1]; 508 argv = &argv[1];
533 argc--; 509 argc--;
534 } 510 }
535 511
536 for (c=1;c<argc;c++) { 512 for (c = 1; c < argc; c++) {
537 if(strcmp("-to",argv[c])==0) 513 if (strcmp("-to", argv[c]) == 0)
538 strcpy(argv[c],"-t"); 514 strcpy(argv[c], "-t");
539 else if (strcmp("-wv",argv[c])==0) 515 else if (strcmp("-wv", argv[c]) == 0)
540 strcpy(argv[c],"-w"); 516 strcpy(argv[c], "-w");
541 else if (strcmp("-cv",argv[c])==0) 517 else if (strcmp("-cv", argv[c]) == 0)
542 strcpy(argv[c],"-c"); 518 strcpy(argv[c], "-c");
543 } 519 }
544 520
545 while (1) { 521 while (1) {
546 c = getopt_long(argc,argv,"+hVH:t:c:w:p:v:l:s:d:u",longopts,&option); 522 c = getopt_long(argc, argv, "+hVH:t:c:w:p:v:l:s:d:u", longopts, &option);
547 523
548 if (c==-1||c==EOF||c==1) 524 if (c == -1 || c == EOF || c == 1)
549 break; 525 break;
550 526
551 switch (c) { 527 switch (c) {
552 case '?': /* print short usage statement if args not parsable */ 528 case '?': /* print short usage statement if args not parsable */
553 usage5 (); 529 usage5();
554 case 'h': /* help */ 530 case 'h': /* help */
555 print_help(); 531 print_help();
556 exit(STATE_UNKNOWN); 532 exit(STATE_UNKNOWN);
557 case 'V': /* version */ 533 case 'V': /* version */
558 print_revision(progname, NP_VERSION); 534 print_revision(progname, NP_VERSION);
559 exit(STATE_UNKNOWN); 535 exit(STATE_UNKNOWN);
560 case 'H': /* hostname */ 536 case 'H': /* hostname */
561 server_address = optarg; 537 server_address = optarg;
562 break; 538 break;
563 case 's': /* password */ 539 case 's': /* password */
564 req_password = optarg; 540 req_password = optarg;
565 break; 541 break;
566 case 'p': /* port */ 542 case 'p': /* port */
567 if (is_intnonneg(optarg)) 543 if (is_intnonneg(optarg))
568 server_port=atoi(optarg); 544 server_port = atoi(optarg);
569 else 545 else
570 die(STATE_UNKNOWN,_("Server port must be an integer\n")); 546 die(STATE_UNKNOWN, _("Server port must be an integer\n"));
571 break; 547 break;
572 case 'v': 548 case 'v':
573 if(strlen(optarg)<4) 549 if (strlen(optarg) < 4)
574 return ERROR; 550 return ERROR;
575 if(!strcmp(optarg,"CLIENTVERSION")) 551 if (!strcmp(optarg, "CLIENTVERSION"))
576 vars_to_check=CHECK_CLIENTVERSION; 552 vars_to_check = CHECK_CLIENTVERSION;
577 else if(!strcmp(optarg,"CPULOAD")) 553 else if (!strcmp(optarg, "CPULOAD"))
578 vars_to_check=CHECK_CPULOAD; 554 vars_to_check = CHECK_CPULOAD;
579 else if(!strcmp(optarg,"UPTIME")) 555 else if (!strcmp(optarg, "UPTIME"))
580 vars_to_check=CHECK_UPTIME; 556 vars_to_check = CHECK_UPTIME;
581 else if(!strcmp(optarg,"USEDDISKSPACE")) 557 else if (!strcmp(optarg, "USEDDISKSPACE"))
582 vars_to_check=CHECK_USEDDISKSPACE; 558 vars_to_check = CHECK_USEDDISKSPACE;
583 else if(!strcmp(optarg,"SERVICESTATE")) 559 else if (!strcmp(optarg, "SERVICESTATE"))
584 vars_to_check=CHECK_SERVICESTATE; 560 vars_to_check = CHECK_SERVICESTATE;
585 else if(!strcmp(optarg,"PROCSTATE")) 561 else if (!strcmp(optarg, "PROCSTATE"))
586 vars_to_check=CHECK_PROCSTATE; 562 vars_to_check = CHECK_PROCSTATE;
587 else if(!strcmp(optarg,"MEMUSE")) 563 else if (!strcmp(optarg, "MEMUSE"))
588 vars_to_check=CHECK_MEMUSE; 564 vars_to_check = CHECK_MEMUSE;
589 else if(!strcmp(optarg,"COUNTER")) 565 else if (!strcmp(optarg, "COUNTER"))
590 vars_to_check=CHECK_COUNTER; 566 vars_to_check = CHECK_COUNTER;
591 else if(!strcmp(optarg,"FILEAGE")) 567 else if (!strcmp(optarg, "FILEAGE"))
592 vars_to_check=CHECK_FILEAGE; 568 vars_to_check = CHECK_FILEAGE;
593 else if(!strcmp(optarg,"INSTANCES")) 569 else if (!strcmp(optarg, "INSTANCES"))
594 vars_to_check=CHECK_INSTANCES; 570 vars_to_check = CHECK_INSTANCES;
595 else 571 else
596 return ERROR; 572 return ERROR;
597 break; 573 break;
598 case 'l': /* value list */ 574 case 'l': /* value list */
599 value_list = optarg; 575 value_list = optarg;
600 break; 576 break;
601 case 'w': /* warning threshold */ 577 case 'w': /* warning threshold */
602 warning_value=strtoul(optarg,NULL,10); 578 warning_value = strtoul(optarg, NULL, 10);
603 check_warning_value=true; 579 check_warning_value = true;
604 break; 580 break;
605 case 'c': /* critical threshold */ 581 case 'c': /* critical threshold */
606 critical_value=strtoul(optarg,NULL,10); 582 critical_value = strtoul(optarg, NULL, 10);
607 check_critical_value=true; 583 check_critical_value = true;
608 break; 584 break;
609 case 'd': /* Display select for services */ 585 case 'd': /* Display select for services */
610 if (!strcmp(optarg,"SHOWALL")) 586 if (!strcmp(optarg, "SHOWALL"))
611 show_all = true; 587 show_all = true;
612 break; 588 break;
613 case 'u': 589 case 'u':
614 socket_timeout_state=STATE_UNKNOWN; 590 socket_timeout_state = STATE_UNKNOWN;
615 break; 591 break;
616 case 't': /* timeout */ 592 case 't': /* timeout */
617 socket_timeout=atoi(optarg); 593 socket_timeout = atoi(optarg);
618 if(socket_timeout<=0) 594 if (socket_timeout <= 0)
619 return ERROR; 595 return ERROR;
620 } 596 }
621
622 } 597 }
623 if (server_address == NULL) 598 if (server_address == NULL)
624 usage4 (_("You must provide a server address or host name")); 599 usage4(_("You must provide a server address or host name"));
625 600
626 if (vars_to_check==CHECK_NONE) 601 if (vars_to_check == CHECK_NONE)
627 return ERROR; 602 return ERROR;
628 603
629 if (req_password == NULL) 604 if (req_password == NULL)
630 req_password = strdup (_("None")); 605 req_password = strdup(_("None"));
631 606
632 return OK; 607 return OK;
633} 608}
634 609
635 610void 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; 611 int result;
639 612
640 result=process_tcp_request(address, port, sendb, recv_buffer,sizeof(recv_buffer)); 613 result = process_tcp_request(address, port, sendb, recv_buffer, sizeof(recv_buffer));
641 614
642 if(result!=STATE_OK) 615 if (result != STATE_OK)
643 die (result, _("could not fetch information from server\n")); 616 die(result, _("could not fetch information from server\n"));
644 617
645 if (!strncmp(recv_buffer,"ERROR",5)) 618 if (!strncmp(recv_buffer, "ERROR", 5))
646 die (STATE_UNKNOWN, "NSClient - %s\n",recv_buffer); 619 die(STATE_UNKNOWN, "NSClient - %s\n", recv_buffer);
647} 620}
648 621
649bool strtoularray(unsigned long *array, char *string, const char *delim) { 622bool strtoularray(unsigned long *array, char *string, const char *delim) {
650 /* split a <delim> delimited string into a long array */ 623 /* split a <delim> delimited string into a long array */
651 int idx=0; 624 int idx = 0;
652 char *t1; 625 char *t1;
653 626
654 for (idx=0;idx<MAX_VALUE_LIST;idx++) 627 for (idx = 0; idx < MAX_VALUE_LIST; idx++)
655 array[idx]=0; 628 array[idx] = 0;
656 629
657 idx=0; 630 idx = 0;
658 for(t1 = strtok(string,delim);t1 != NULL; t1 = strtok(NULL, delim)) { 631 for (t1 = strtok(string, delim); t1 != NULL; t1 = strtok(NULL, delim)) {
659 if (is_numeric(t1) && idx<MAX_VALUE_LIST) { 632 if (is_numeric(t1) && idx < MAX_VALUE_LIST) {
660 array[idx]=strtoul(t1,NULL,10); 633 array[idx] = strtoul(t1, NULL, 10);
661 idx++; 634 idx++;
662 } else 635 } else
663 return false; 636 return false;
@@ -671,131 +644,124 @@ void preparelist(char *string) {
671 644
672 for (i = 0; (size_t)i < strlen(string); i++) 645 for (i = 0; (size_t)i < strlen(string); i++)
673 if (string[i] == ',') { 646 if (string[i] == ',') {
674 string[i]='&'; 647 string[i] = '&';
675 } 648 }
676} 649}
677 650
678 651void print_help(void) {
679
680void print_help(void)
681{
682 print_revision(progname, NP_VERSION); 652 print_revision(progname, NP_VERSION);
683 653
684 printf ("Copyright (c) 2000 Yves Rubin (rubiyz@yahoo.com)\n"); 654 printf("Copyright (c) 2000 Yves Rubin (rubiyz@yahoo.com)\n");
685 printf (COPYRIGHT, copyright, email); 655 printf(COPYRIGHT, copyright, email);
686 656
687 printf ("%s\n", _("This plugin collects data from the NSClient service running on a")); 657 printf("%s\n", _("This plugin collects data from the NSClient service running on a"));
688 printf ("%s\n", _("Windows NT/2000/XP/2003 server.")); 658 printf("%s\n", _("Windows NT/2000/XP/2003 server."));
689 659
690 printf ("\n\n"); 660 printf("\n\n");
691 661
692 print_usage(); 662 print_usage();
693 663
694 printf (UT_HELP_VRSN); 664 printf(UT_HELP_VRSN);
695 printf (UT_EXTRA_OPTS); 665 printf(UT_EXTRA_OPTS);
696 666
697 printf ("%s\n", _("Options:")); 667 printf("%s\n", _("Options:"));
698 printf (" %s\n", "-H, --hostname=HOST"); 668 printf(" %s\n", "-H, --hostname=HOST");
699 printf (" %s\n", _("Name of the host to check")); 669 printf(" %s\n", _("Name of the host to check"));
700 printf (" %s\n", "-p, --port=INTEGER"); 670 printf(" %s\n", "-p, --port=INTEGER");
701 printf (" %s", _("Optional port number (default: ")); 671 printf(" %s", _("Optional port number (default: "));
702 printf ("%d)\n", PORT); 672 printf("%d)\n", PORT);
703 printf (" %s\n", "-s, --secret=<password>"); 673 printf(" %s\n", "-s, --secret=<password>");
704 printf (" %s\n", _("Password needed for the request")); 674 printf(" %s\n", _("Password needed for the request"));
705 printf (" %s\n", "-w, --warning=INTEGER"); 675 printf(" %s\n", "-w, --warning=INTEGER");
706 printf (" %s\n", _("Threshold which will result in a warning status")); 676 printf(" %s\n", _("Threshold which will result in a warning status"));
707 printf (" %s\n", "-c, --critical=INTEGER"); 677 printf(" %s\n", "-c, --critical=INTEGER");
708 printf (" %s\n", _("Threshold which will result in a critical status")); 678 printf(" %s\n", _("Threshold which will result in a critical status"));
709 printf (" %s\n", "-t, --timeout=INTEGER"); 679 printf(" %s\n", "-t, --timeout=INTEGER");
710 printf (" %s", _("Seconds before connection attempt times out (default: ")); 680 printf(" %s", _("Seconds before connection attempt times out (default: "));
711 printf (" %s\n", "-l, --params=<parameters>"); 681 printf(" %s\n", "-l, --params=<parameters>");
712 printf (" %s", _("Parameters passed to specified check (see below)")); 682 printf(" %s", _("Parameters passed to specified check (see below)"));
713 printf (" %s\n", "-d, --display={SHOWALL}"); 683 printf(" %s\n", "-d, --display={SHOWALL}");
714 printf (" %s", _("Display options (currently only SHOWALL works)")); 684 printf(" %s", _("Display options (currently only SHOWALL works)"));
715 printf (" %s\n", "-u, --unknown-timeout"); 685 printf(" %s\n", "-u, --unknown-timeout");
716 printf (" %s", _("Return UNKNOWN on timeouts")); 686 printf(" %s", _("Return UNKNOWN on timeouts"));
717 printf ("%d)\n", DEFAULT_SOCKET_TIMEOUT); 687 printf("%d)\n", DEFAULT_SOCKET_TIMEOUT);
718 printf (" %s\n", "-h, --help"); 688 printf(" %s\n", "-h, --help");
719 printf (" %s\n", _("Print this help screen")); 689 printf(" %s\n", _("Print this help screen"));
720 printf (" %s\n", "-V, --version"); 690 printf(" %s\n", "-V, --version");
721 printf (" %s\n", _("Print version information")); 691 printf(" %s\n", _("Print version information"));
722 printf (" %s\n", "-v, --variable=STRING"); 692 printf(" %s\n", "-v, --variable=STRING");
723 printf (" %s\n\n", _("Variable to check")); 693 printf(" %s\n\n", _("Variable to check"));
724 printf ("%s\n", _("Valid variables are:")); 694 printf("%s\n", _("Valid variables are:"));
725 printf (" %s", "CLIENTVERSION ="); 695 printf(" %s", "CLIENTVERSION =");
726 printf (" %s\n", _("Get the NSClient version")); 696 printf(" %s\n", _("Get the NSClient version"));
727 printf (" %s\n", _("If -l <version> is specified, will return warning if versions differ.")); 697 printf(" %s\n", _("If -l <version> is specified, will return warning if versions differ."));
728 printf (" %s\n", "CPULOAD ="); 698 printf(" %s\n", "CPULOAD =");
729 printf (" %s\n", _("Average CPU load on last x minutes.")); 699 printf(" %s\n", _("Average CPU load on last x minutes."));
730 printf (" %s\n", _("Request a -l parameter with the following syntax:")); 700 printf(" %s\n", _("Request a -l parameter with the following syntax:"));
731 printf (" %s\n", _("-l <minutes range>,<warning threshold>,<critical threshold>.")); 701 printf(" %s\n", _("-l <minutes range>,<warning threshold>,<critical threshold>."));
732 printf (" %s\n", _("<minute range> should be less than 24*60.")); 702 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.")); 703 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"); 704 printf(" %s\n", "ie: -l 60,90,95,120,90,95");
735 printf (" %s\n", "UPTIME ="); 705 printf(" %s\n", "UPTIME =");
736 printf (" %s\n", _("Get the uptime of the machine.")); 706 printf(" %s\n", _("Get the uptime of the machine."));
737 printf (" %s\n", _("-l <unit> ")); 707 printf(" %s\n", _("-l <unit> "));
738 printf (" %s\n", _("<unit> = seconds, minutes, hours, or days. (default: minutes)")); 708 printf(" %s\n", _("<unit> = seconds, minutes, hours, or days. (default: minutes)"));
739 printf (" %s\n", _("Thresholds will use the unit specified above.")); 709 printf(" %s\n", _("Thresholds will use the unit specified above."));
740 printf (" %s\n", "USEDDISKSPACE ="); 710 printf(" %s\n", "USEDDISKSPACE =");
741 printf (" %s\n", _("Size and percentage of disk use.")); 711 printf(" %s\n", _("Size and percentage of disk use."));
742 printf (" %s\n", _("Request a -l parameter containing the drive letter only.")); 712 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.")); 713 printf(" %s\n", _("Warning and critical thresholds can be specified with -w and -c."));
744 printf (" %s\n", "MEMUSE ="); 714 printf(" %s\n", "MEMUSE =");
745 printf (" %s\n", _("Memory use.")); 715 printf(" %s\n", _("Memory use."));
746 printf (" %s\n", _("Warning and critical thresholds can be specified with -w and -c.")); 716 printf(" %s\n", _("Warning and critical thresholds can be specified with -w and -c."));
747 printf (" %s\n", "SERVICESTATE ="); 717 printf(" %s\n", "SERVICESTATE =");
748 printf (" %s\n", _("Check the state of one or several services.")); 718 printf(" %s\n", _("Check the state of one or several services."));
749 printf (" %s\n", _("Request a -l parameters with the following syntax:")); 719 printf(" %s\n", _("Request a -l parameters with the following syntax:"));
750 printf (" %s\n", _("-l <service1>,<service2>,<service3>,...")); 720 printf(" %s\n", _("-l <service1>,<service2>,<service3>,..."));
751 printf (" %s\n", _("You can specify -d SHOWALL in case you want to see working services")); 721 printf(" %s\n", _("You can specify -d SHOWALL in case you want to see working services"));
752 printf (" %s\n", _("in the returned string.")); 722 printf(" %s\n", _("in the returned string."));
753 printf (" %s\n", "PROCSTATE ="); 723 printf(" %s\n", "PROCSTATE =");
754 printf (" %s\n", _("Check if one or several process are running.")); 724 printf(" %s\n", _("Check if one or several process are running."));
755 printf (" %s\n", _("Same syntax as SERVICESTATE.")); 725 printf(" %s\n", _("Same syntax as SERVICESTATE."));
756 printf (" %s\n", "COUNTER ="); 726 printf(" %s\n", "COUNTER =");
757 printf (" %s\n", _("Check any performance counter of Windows NT/2000.")); 727 printf(" %s\n", _("Check any performance counter of Windows NT/2000."));
758 printf (" %s\n", _("Request a -l parameters with the following syntax:")); 728 printf(" %s\n", _("Request a -l parameters with the following syntax:"));
759 printf (" %s\n", _("-l \"\\\\<performance object>\\\\counter\",\"<description>")); 729 printf(" %s\n", _("-l \"\\\\<performance object>\\\\counter\",\"<description>"));
760 printf (" %s\n", _("The <description> parameter is optional and is given to a printf ")); 730 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.")); 731 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.")); 732 printf(" %s\n", _("If <description> does not include \"%%\", it is used as a label."));
763 printf (" %s\n", _("Some examples:")); 733 printf(" %s\n", _("Some examples:"));
764 printf (" %s\n", "\"Paging file usage is %%.2f %%%%\""); 734 printf(" %s\n", "\"Paging file usage is %%.2f %%%%\"");
765 printf (" %s\n", "\"%%.f %%%% paging file used.\""); 735 printf(" %s\n", "\"%%.f %%%% paging file used.\"");
766 printf (" %s\n", "INSTANCES ="); 736 printf(" %s\n", "INSTANCES =");
767 printf (" %s\n", _("Check any performance counter object of Windows NT/2000.")); 737 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>")); 738 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),")); 739 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")); 740 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 ")); 741 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.")); 742 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")); 743 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")); 744 printf(" %s\n", _(" are available for monitoring without having to log onto the Windows server"));
775 printf (" %s\n", _(" to run Perfmon directly.")); 745 printf(" %s\n", _(" to run Perfmon directly."));
776 printf (" %s\n", _("It can also be used in scripts that automatically create the monitoring service")); 746 printf(" %s\n", _("It can also be used in scripts that automatically create the monitoring service"));
777 printf (" %s\n", _(" configuration files.")); 747 printf(" %s\n", _(" configuration files."));
778 printf (" %s\n", _("Some examples:")); 748 printf(" %s\n", _("Some examples:"));
779 printf (" %s\n\n", _("check_nt -H 192.168.1.1 -p 1248 -v INSTANCES -l Process")); 749 printf(" %s\n\n", _("check_nt -H 192.168.1.1 -p 1248 -v INSTANCES -l Process"));
780 750
781 printf ("%s\n", _("Notes:")); 751 printf("%s\n", _("Notes:"));
782 printf (" %s\n", _("- The NSClient service should be running on the server to get any information")); 752 printf(" %s\n", _("- The NSClient service should be running on the server to get any information"));
783 printf (" %s\n", "(http://nsclient.ready2run.nl)."); 753 printf(" %s\n", "(http://nsclient.ready2run.nl).");
784 printf (" %s\n", _("- Critical thresholds should be lower than warning thresholds")); 754 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")); 755 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\".")); 756 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 ")); 757 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.")); 758 printf(" %s\n", _("and on the client service it\'s connecting to."));
789 759
790 printf (UT_SUPPORT); 760 printf(UT_SUPPORT);
791} 761}
792 762
793 763void print_usage(void) {
794 764 printf("%s\n", _("Usage:"));
795void print_usage(void) 765 printf("%s -H host -v variable [-p port] [-w warning] [-c critical]\n", progname);
796{ 766 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} 767}
801
diff --git a/plugins/check_ntp.c b/plugins/check_ntp.c
index 61b2d69..d33f878 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"
@@ -47,10 +47,10 @@ static bool do_jitter = false;
47static char *jwarn="5000"; 47static char *jwarn="5000";
48static char *jcrit="10000"; 48static char *jcrit="10000";
49 49
50int process_arguments (int, char **); 50static int process_arguments (int /*argc*/, char ** /*argv*/);
51thresholds *offset_thresholds = NULL; 51static thresholds *offset_thresholds = NULL;
52thresholds *jitter_thresholds = NULL; 52static thresholds *jitter_thresholds = NULL;
53void print_help (void); 53static void print_help (void);
54void print_usage (void); 54void print_usage (void);
55 55
56/* number of times to perform each request to get a good average. */ 56/* number of times to perform each request to get a good average. */
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..176dfbc 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; 92static char *server_address = NULL;
93char *volume_name=NULL; 93static char *volume_name = NULL;
94char *nlm_name=NULL; 94static char *nlm_name = NULL;
95char *nrmp_name=NULL; 95static char *nrmp_name = NULL;
96char *nrmm_name=NULL; 96static char *nrmm_name = NULL;
97char *nrms_name=NULL; 97static char *nrms_name = NULL;
98char *nss1_name=NULL; 98static char *nss1_name = NULL;
99char *nss2_name=NULL; 99static char *nss2_name = NULL;
100char *nss3_name=NULL; 100static char *nss3_name = NULL;
101char *nss4_name=NULL; 101static char *nss4_name = NULL;
102char *nss5_name=NULL; 102static char *nss5_name = NULL;
103char *nss6_name=NULL; 103static char *nss6_name = NULL;
104char *nss7_name=NULL; 104static char *nss7_name = NULL;
105int server_port=PORT; 105static int server_port = PORT;
106unsigned long warning_value=0L; 106static unsigned long warning_value = 0L;
107unsigned long critical_value=0L; 107static unsigned long critical_value = 0L;
108bool check_warning_value = false; 108static bool check_warning_value = false;
109bool check_critical_value = false; 109static bool check_critical_value = false;
110bool check_netware_version = false; 110static bool check_netware_version = false;
111enum checkvar vars_to_check = NONE; 111static enum checkvar vars_to_check = NONE;
112int sap_number=-1; 112static int sap_number = -1;
113 113
114int process_arguments(int, char **); 114static int process_arguments(int /*argc*/, char ** /*argv*/);
115void print_help(void); 115static void 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..599540b 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"
@@ -52,27 +52,24 @@ enum {
52 PORT = 2000 52 PORT = 2000
53}; 53};
54 54
55char *server_address = NULL; 55static char *server_address = NULL;
56int server_port = PORT; 56static int server_port = PORT;
57double warning_value = 0L; 57static double warning_value = 0L;
58double critical_value = 0L; 58static double critical_value = 0L;
59bool check_warning_value = false; 59static bool check_warning_value = false;
60bool check_critical_value = false; 60static bool check_critical_value = false;
61enum checkvar vars_to_check = NONE; 61static enum checkvar vars_to_check = NONE;
62int cmd_timeout = 1; 62
63 63static int netstat_port = 0;
64int netstat_port = 0; 64static char *disk_name = NULL;
65char *disk_name = NULL; 65static char *process_name = NULL;
66char *process_name = NULL; 66static char send_buffer[MAX_INPUT_BUFFER];
67char send_buffer[MAX_INPUT_BUFFER]; 67
68 68static int process_arguments(int, char **);
69int process_arguments (int, char **); 69void print_usage(void);
70void print_usage (void); 70static void print_help(void);
71void print_help (void); 71
72 72int main(int argc, char **argv) {
73int
74main (int argc, char **argv)
75{
76 int result = STATE_UNKNOWN; 73 int result = STATE_UNKNOWN;
77 char recv_buffer[MAX_INPUT_BUFFER]; 74 char recv_buffer[MAX_INPUT_BUFFER];
78 char temp_buffer[MAX_INPUT_BUFFER]; 75 char temp_buffer[MAX_INPUT_BUFFER];
@@ -91,66 +88,62 @@ main (int argc, char **argv)
91 int uptime_hours = 0; 88 int uptime_hours = 0;
92 int uptime_minutes = 0; 89 int uptime_minutes = 0;
93 90
94 setlocale (LC_ALL, ""); 91 setlocale(LC_ALL, "");
95 bindtextdomain (PACKAGE, LOCALEDIR); 92 bindtextdomain(PACKAGE, LOCALEDIR);
96 textdomain (PACKAGE); 93 textdomain(PACKAGE);
97 94
98 /* Parse extra opts if any */ 95 /* Parse extra opts if any */
99 argv=np_extra_opts (&argc, argv, progname); 96 argv = np_extra_opts(&argc, argv, progname);
100 97
101 if (process_arguments (argc, argv) == ERROR) 98 if (process_arguments(argc, argv) == ERROR)
102 usage4 (_("Could not parse arguments")); 99 usage4(_("Could not parse arguments"));
103 100
104 /* initialize alarm signal handling */ 101 /* initialize alarm signal handling */
105 signal (SIGALRM, socket_timeout_alarm_handler); 102 signal(SIGALRM, socket_timeout_alarm_handler);
106 103
107 /* set socket timeout */ 104 /* set socket timeout */
108 alarm (socket_timeout); 105 alarm(socket_timeout);
109 106
110 result = process_tcp_request2 (server_address, 107 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 108
116 switch (vars_to_check) { 109 switch (vars_to_check) {
117 110
118 case LOAD1: 111 case LOAD1:
119 case LOAD5: 112 case LOAD5:
120 case LOAD15: 113 case LOAD15:
121 114
122 if (result != STATE_OK) 115 if (result != STATE_OK)
123 die (result, _("Unknown error fetching load data\n")); 116 die(result, _("Unknown error fetching load data\n"));
124 117
125 temp_ptr = (char *) strtok (recv_buffer, "\r\n"); 118 temp_ptr = (char *)strtok(recv_buffer, "\r\n");
126 if (temp_ptr == NULL) 119 if (temp_ptr == NULL)
127 die (STATE_CRITICAL, _("Invalid response from server - no load information\n")); 120 die(STATE_CRITICAL, _("Invalid response from server - no load information\n"));
128 else 121 else
129 load_1min = strtod (temp_ptr, NULL); 122 load_1min = strtod(temp_ptr, NULL);
130 123
131 temp_ptr = (char *) strtok (NULL, "\r\n"); 124 temp_ptr = (char *)strtok(NULL, "\r\n");
132 if (temp_ptr == NULL) 125 if (temp_ptr == NULL)
133 die (STATE_CRITICAL, _("Invalid response from server after load 1\n")); 126 die(STATE_CRITICAL, _("Invalid response from server after load 1\n"));
134 else 127 else
135 load_5min = strtod (temp_ptr, NULL); 128 load_5min = strtod(temp_ptr, NULL);
136 129
137 temp_ptr = (char *) strtok (NULL, "\r\n"); 130 temp_ptr = (char *)strtok(NULL, "\r\n");
138 if (temp_ptr == NULL) 131 if (temp_ptr == NULL)
139 die (STATE_CRITICAL, _("Invalid response from server after load 5\n")); 132 die(STATE_CRITICAL, _("Invalid response from server after load 5\n"));
140 else 133 else
141 load_15min = strtod (temp_ptr, NULL); 134 load_15min = strtod(temp_ptr, NULL);
142 135
143 switch (vars_to_check) { 136 switch (vars_to_check) {
144 case LOAD1: 137 case LOAD1:
145 strcpy (temp_buffer, "1"); 138 strcpy(temp_buffer, "1");
146 load = load_1min; 139 load = load_1min;
147 break; 140 break;
148 case LOAD5: 141 case LOAD5:
149 strcpy (temp_buffer, "5"); 142 strcpy(temp_buffer, "5");
150 load = load_5min; 143 load = load_5min;
151 break; 144 break;
152 default: 145 default:
153 strcpy (temp_buffer, "15"); 146 strcpy(temp_buffer, "15");
154 load = load_15min; 147 load = load_15min;
155 break; 148 break;
156 } 149 }
@@ -160,98 +153,82 @@ main (int argc, char **argv)
160 else if (check_warning_value && (load >= warning_value)) 153 else if (check_warning_value && (load >= warning_value))
161 result = STATE_WARNING; 154 result = STATE_WARNING;
162 155
163 die (result, 156 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 157
169 break; 158 break;
170 159
171 case DPU: 160 case DPU:
172 161
173 if (result != STATE_OK) 162 if (result != STATE_OK)
174 die (result, _("Unknown error fetching disk data\n")); 163 die(result, _("Unknown error fetching disk data\n"));
175 164
176 for (temp_ptr = (char *) strtok (recv_buffer, " "); 165 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 166
180 if (!strcmp (temp_ptr, disk_name)) { 167 if (!strcmp(temp_ptr, disk_name)) {
181 found_disk = true; 168 found_disk = true;
182 temp_ptr = (char *) strtok (NULL, "%"); 169 temp_ptr = (char *)strtok(NULL, "%");
183 if (temp_ptr == NULL) 170 if (temp_ptr == NULL)
184 die (STATE_CRITICAL, _("Invalid response from server\n")); 171 die(STATE_CRITICAL, _("Invalid response from server\n"));
185 else 172 else
186 percent_used_disk_space = strtoul (temp_ptr, NULL, 10); 173 percent_used_disk_space = strtoul(temp_ptr, NULL, 10);
187 break; 174 break;
188 } 175 }
189 176
190 temp_ptr = (char *) strtok (NULL, "\r\n"); 177 temp_ptr = (char *)strtok(NULL, "\r\n");
191 } 178 }
192 179
193 /* error if we couldn't find the info for the disk */ 180 /* error if we couldn't find the info for the disk */
194 if (!found_disk) 181 if (!found_disk)
195 die (STATE_CRITICAL, 182 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 183
199 if (check_critical_value && (percent_used_disk_space >= critical_value)) 184 if (check_critical_value && (percent_used_disk_space >= critical_value))
200 result = STATE_CRITICAL; 185 result = STATE_CRITICAL;
201 else if (check_warning_value && (percent_used_disk_space >= warning_value)) 186 else if (check_warning_value && (percent_used_disk_space >= warning_value))
202 result = STATE_WARNING; 187 result = STATE_WARNING;
203 188
204 die (result, "Disk %s - %lu%% used on %s", state_text(result), percent_used_disk_space, disk_name); 189 die(result, "Disk %s - %lu%% used on %s", state_text(result), percent_used_disk_space, disk_name);
205 190
206 break; 191 break;
207 192
208 case NETSTAT: 193 case NETSTAT:
209 194
210 if (result != STATE_OK) 195 if (result != STATE_OK)
211 die (result, _("Unknown error fetching network status\n")); 196 die(result, _("Unknown error fetching network status\n"));
212 else 197 else
213 port_connections = strtod (recv_buffer, NULL); 198 port_connections = strtod(recv_buffer, NULL);
214 199
215 if (check_critical_value && (port_connections >= critical_value)) 200 if (check_critical_value && (port_connections >= critical_value))
216 result = STATE_CRITICAL; 201 result = STATE_CRITICAL;
217 else if (check_warning_value && (port_connections >= warning_value)) 202 else if (check_warning_value && (port_connections >= warning_value))
218 result = STATE_WARNING; 203 result = STATE_WARNING;
219 204
220 die (result, 205 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"), 206 netstat_port);
222 state_text(result),
223 port_connections,
224 (port_connections == 1) ? "" : "s",
225 netstat_port);
226 207
227 break; 208 break;
228 209
229 case PROCS: 210 case PROCS:
230 211
231 if (result != STATE_OK) 212 if (result != STATE_OK)
232 die (result, _("Unknown error fetching process status\n")); 213 die(result, _("Unknown error fetching process status\n"));
233 214
234 temp_ptr = (char *) strtok (recv_buffer, "("); 215 temp_ptr = (char *)strtok(recv_buffer, "(");
235 if (temp_ptr == NULL) 216 if (temp_ptr == NULL)
236 die (STATE_CRITICAL, _("Invalid response from server\n")); 217 die(STATE_CRITICAL, _("Invalid response from server\n"));
237 218
238 temp_ptr = (char *) strtok (NULL, ")"); 219 temp_ptr = (char *)strtok(NULL, ")");
239 if (temp_ptr == NULL) 220 if (temp_ptr == NULL)
240 die (STATE_CRITICAL, _("Invalid response from server\n")); 221 die(STATE_CRITICAL, _("Invalid response from server\n"));
241 else 222 else
242 processes = strtod (temp_ptr, NULL); 223 processes = strtod(temp_ptr, NULL);
243 224
244 if (check_critical_value && (processes >= critical_value)) 225 if (check_critical_value && (processes >= critical_value))
245 result = STATE_CRITICAL; 226 result = STATE_CRITICAL;
246 else if (check_warning_value && (processes >= warning_value)) 227 else if (check_warning_value && (processes >= warning_value))
247 result = STATE_WARNING; 228 result = STATE_WARNING;
248 229
249 die (result, 230 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"), 231 process_name);
251 state_text(result),
252 processes,
253 (processes == 1) ? "" : "s",
254 process_name);
255 break; 232 break;
256 233
257 case UPTIME: 234 case UPTIME:
@@ -259,8 +236,8 @@ main (int argc, char **argv)
259 if (result != STATE_OK) 236 if (result != STATE_OK)
260 return result; 237 return result;
261 238
262 uptime_raw_hours = strtod (recv_buffer, NULL); 239 uptime_raw_hours = strtod(recv_buffer, NULL);
263 uptime_raw_minutes = (unsigned long) (uptime_raw_hours * 60.0); 240 uptime_raw_minutes = (unsigned long)(uptime_raw_hours * 60.0);
264 241
265 if (check_critical_value && (uptime_raw_minutes <= critical_value)) 242 if (check_critical_value && (uptime_raw_minutes <= critical_value))
266 result = STATE_CRITICAL; 243 result = STATE_CRITICAL;
@@ -273,46 +250,31 @@ main (int argc, char **argv)
273 uptime_raw_minutes %= 60; 250 uptime_raw_minutes %= 60;
274 uptime_minutes = uptime_raw_minutes; 251 uptime_minutes = uptime_raw_minutes;
275 252
276 die (result, 253 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; 254 break;
283 255
284 default: 256 default:
285 die (STATE_UNKNOWN, _("Nothing to check!\n")); 257 die(STATE_UNKNOWN, _("Nothing to check!\n"));
286 break; 258 break;
287 } 259 }
288} 260}
289 261
290
291/* process command-line arguments */ 262/* process command-line arguments */
292int 263int process_arguments(int argc, char **argv) {
293process_arguments (int argc, char **argv)
294{
295 int c; 264 int c;
296 265
297 int option = 0; 266 int option = 0;
298 static struct option longopts[] = { 267 static struct option longopts[] = {
299 {"port", required_argument, 0, 'p'}, 268 {"port", required_argument, 0, 'p'}, {"timeout", required_argument, 0, 't'}, {"critical", required_argument, 0, 'c'},
300 {"timeout", required_argument, 0, 't'}, 269 {"warning", required_argument, 0, 'w'}, {"variable", required_argument, 0, 'v'}, {"hostname", required_argument, 0, 'H'},
301 {"critical", required_argument, 0, 'c'}, 270 {"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 271
310 /* no options were supplied */ 272 /* no options were supplied */
311 if (argc < 2) 273 if (argc < 2)
312 return ERROR; 274 return ERROR;
313 275
314 /* backwards compatibility */ 276 /* backwards compatibility */
315 if (!is_option (argv[1])) { 277 if (!is_option(argv[1])) {
316 server_address = argv[1]; 278 server_address = argv[1];
317 argv[1] = argv[0]; 279 argv[1] = argv[0];
318 argv = &argv[1]; 280 argv = &argv[1];
@@ -320,150 +282,136 @@ process_arguments (int argc, char **argv)
320 } 282 }
321 283
322 for (c = 1; c < argc; c++) { 284 for (c = 1; c < argc; c++) {
323 if (strcmp ("-to", argv[c]) == 0) 285 if (strcmp("-to", argv[c]) == 0)
324 strcpy (argv[c], "-t"); 286 strcpy(argv[c], "-t");
325 else if (strcmp ("-wv", argv[c]) == 0) 287 else if (strcmp("-wv", argv[c]) == 0)
326 strcpy (argv[c], "-w"); 288 strcpy(argv[c], "-w");
327 else if (strcmp ("-cv", argv[c]) == 0) 289 else if (strcmp("-cv", argv[c]) == 0)
328 strcpy (argv[c], "-c"); 290 strcpy(argv[c], "-c");
329 } 291 }
330 292
331 while (1) { 293 while (1) {
332 c = getopt_long (argc, argv, "+hVH:t:c:w:p:v:", longopts, 294 c = getopt_long(argc, argv, "+hVH:t:c:w:p:v:", longopts, &option);
333 &option);
334 295
335 if (c == -1 || c == EOF || c == 1) 296 if (c == -1 || c == EOF || c == 1)
336 break; 297 break;
337 298
338 switch (c) { 299 switch (c) {
339 case '?': /* print short usage statement if args not parsable */ 300 case '?': /* print short usage statement if args not parsable */
340 usage5 (); 301 usage5();
341 case 'h': /* help */ 302 case 'h': /* help */
342 print_help (); 303 print_help();
343 exit (STATE_UNKNOWN); 304 exit(STATE_UNKNOWN);
344 case 'V': /* version */ 305 case 'V': /* version */
345 print_revision (progname, NP_VERSION); 306 print_revision(progname, NP_VERSION);
346 exit (STATE_UNKNOWN); 307 exit(STATE_UNKNOWN);
347 case 'H': /* hostname */ 308 case 'H': /* hostname */
348 server_address = optarg; 309 server_address = optarg;
349 break; 310 break;
350 case 'p': /* port */ 311 case 'p': /* port */
351 if (is_intnonneg (optarg)) 312 if (is_intnonneg(optarg))
352 server_port = atoi (optarg); 313 server_port = atoi(optarg);
353 else 314 else
354 die (STATE_UNKNOWN, 315 die(STATE_UNKNOWN, _("Server port an integer\n"));
355 _("Server port an integer\n"));
356 break; 316 break;
357 case 'v': /* variable */ 317 case 'v': /* variable */
358 if (strcmp (optarg, "LOAD") == 0) { 318 if (strcmp(optarg, "LOAD") == 0) {
359 strcpy (send_buffer, "LOAD\r\nQUIT\r\n"); 319 strcpy(send_buffer, "LOAD\r\nQUIT\r\n");
360 if (strcmp (optarg, "LOAD1") == 0) 320 if (strcmp(optarg, "LOAD1") == 0)
361 vars_to_check = LOAD1; 321 vars_to_check = LOAD1;
362 else if (strcmp (optarg, "LOAD5") == 0) 322 else if (strcmp(optarg, "LOAD5") == 0)
363 vars_to_check = LOAD5; 323 vars_to_check = LOAD5;
364 else if (strcmp (optarg, "LOAD15") == 0) 324 else if (strcmp(optarg, "LOAD15") == 0)
365 vars_to_check = LOAD15; 325 vars_to_check = LOAD15;
366 } 326 } else if (strcmp(optarg, "UPTIME") == 0) {
367 else if (strcmp (optarg, "UPTIME") == 0) {
368 vars_to_check = UPTIME; 327 vars_to_check = UPTIME;
369 strcpy (send_buffer, "UPTIME\r\n"); 328 strcpy(send_buffer, "UPTIME\r\n");
370 } 329 } else if (strstr(optarg, "PROC") == optarg) {
371 else if (strstr (optarg, "PROC") == optarg) {
372 vars_to_check = PROCS; 330 vars_to_check = PROCS;
373 process_name = strscpy (process_name, optarg + 4); 331 process_name = strscpy(process_name, optarg + 4);
374 sprintf (send_buffer, "PROCESS %s\r\n", process_name); 332 sprintf(send_buffer, "PROCESS %s\r\n", process_name);
375 } 333 } else if (strstr(optarg, "NET") == optarg) {
376 else if (strstr (optarg, "NET") == optarg) {
377 vars_to_check = NETSTAT; 334 vars_to_check = NETSTAT;
378 netstat_port = atoi (optarg + 3); 335 netstat_port = atoi(optarg + 3);
379 sprintf (send_buffer, "NETSTAT %d\r\n", netstat_port); 336 sprintf(send_buffer, "NETSTAT %d\r\n", netstat_port);
380 } 337 } else if (strstr(optarg, "DPU") == optarg) {
381 else if (strstr (optarg, "DPU") == optarg) {
382 vars_to_check = DPU; 338 vars_to_check = DPU;
383 strcpy (send_buffer, "DISKSPACE\r\n"); 339 strcpy(send_buffer, "DISKSPACE\r\n");
384 disk_name = strscpy (disk_name, optarg + 3); 340 disk_name = strscpy(disk_name, optarg + 3);
385 } 341 } else
386 else
387 return ERROR; 342 return ERROR;
388 break; 343 break;
389 case 'w': /* warning threshold */ 344 case 'w': /* warning threshold */
390 warning_value = strtoul (optarg, NULL, 10); 345 warning_value = strtoul(optarg, NULL, 10);
391 check_warning_value = true; 346 check_warning_value = true;
392 break; 347 break;
393 case 'c': /* critical threshold */ 348 case 'c': /* critical threshold */
394 critical_value = strtoul (optarg, NULL, 10); 349 critical_value = strtoul(optarg, NULL, 10);
395 check_critical_value = true; 350 check_critical_value = true;
396 break; 351 break;
397 case 't': /* timeout */ 352 case 't': /* timeout */
398 socket_timeout = atoi (optarg); 353 socket_timeout = atoi(optarg);
399 if (socket_timeout <= 0) 354 if (socket_timeout <= 0)
400 return ERROR; 355 return ERROR;
401 } 356 }
402
403 } 357 }
404 return OK; 358 return OK;
405} 359}
406 360
407 361void print_help(void) {
408void
409print_help (void)
410{
411 char *myport; 362 char *myport;
412 xasprintf (&myport, "%d", PORT); 363 xasprintf(&myport, "%d", PORT);
413 364
414 print_revision (progname, NP_VERSION); 365 print_revision(progname, NP_VERSION);
415 366
416 printf ("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n"); 367 printf("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n");
417 printf (COPYRIGHT, copyright, email); 368 printf(COPYRIGHT, copyright, email);
418 369
419 printf ("%s\n", _("This plugin attempts to contact the Over-CR collector daemon running on the")); 370 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.")); 371 printf("%s\n", _("remote UNIX server in order to gather the requested system information."));
421 372
422 printf ("\n\n"); 373 printf("\n\n");
423 374
424 print_usage (); 375 print_usage();
425 376
426 printf (UT_HELP_VRSN); 377 printf(UT_HELP_VRSN);
427 printf (UT_EXTRA_OPTS); 378 printf(UT_EXTRA_OPTS);
428 379
429 printf (UT_HOST_PORT, 'p', myport); 380 printf(UT_HOST_PORT, 'p', myport);
430 381
431 printf (" %s\n", "-w, --warning=INTEGER"); 382 printf(" %s\n", "-w, --warning=INTEGER");
432 printf (" %s\n", _("Threshold which will result in a warning status")); 383 printf(" %s\n", _("Threshold which will result in a warning status"));
433 printf (" %s\n", "-c, --critical=INTEGER"); 384 printf(" %s\n", "-c, --critical=INTEGER");
434 printf (" %s\n", _("Threshold which will result in a critical status")); 385 printf(" %s\n", _("Threshold which will result in a critical status"));
435 printf (" %s\n", "-v, --variable=STRING"); 386 printf(" %s\n", "-v, --variable=STRING");
436 printf (" %s\n", _("Variable to check. Valid variables include:")); 387 printf(" %s\n", _("Variable to check. Valid variables include:"));
437 printf (" %s\n", _("LOAD1 = 1 minute average CPU load")); 388 printf(" %s\n", _("LOAD1 = 1 minute average CPU load"));
438 printf (" %s\n", _("LOAD5 = 5 minute average CPU load")); 389 printf(" %s\n", _("LOAD5 = 5 minute average CPU load"));
439 printf (" %s\n", _("LOAD15 = 15 minute average CPU load")); 390 printf(" %s\n", _("LOAD15 = 15 minute average CPU load"));
440 printf (" %s\n", _("DPU<filesys> = percent used disk space on filesystem <filesys>")); 391 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>")); 392 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>")); 393 printf(" %s\n", _("NET<port> = number of active connections on TCP port <port>"));
443 printf (" %s\n", _("UPTIME = system uptime in seconds")); 394 printf(" %s\n", _("UPTIME = system uptime in seconds"));
444 395
445 printf (UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); 396 printf(UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
446 397
447 printf (UT_VERBOSE); 398 printf(UT_VERBOSE);
448 399
449 printf ("\n"); 400 printf("\n");
450 printf ("%s\n", _("This plugin requires that Eric Molitors' Over-CR collector daemon be")); 401 printf("%s\n", _("This plugin requires that Eric Molitors' Over-CR collector daemon be"));
451 printf ("%s\n", _("running on the remote server.")); 402 printf("%s\n", _("running on the remote server."));
452 printf ("%s\n", _("Over-CR can be downloaded from http://www.molitor.org/overcr")); 403 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")); 404 printf("%s\n", _("This plugin was tested with version 0.99.53 of the Over-CR collector"));
454 405
455 printf ("\n"); 406 printf("\n");
456 printf ("%s\n", _("Notes:")); 407 printf("%s\n", _("Notes:"));
457 printf (" %s\n", _("For the available options, the critical threshold value should always be")); 408 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")); 409 printf(" %s\n", _("higher than the warning threshold value, EXCEPT with the uptime variable"));
459 410
460 printf (UT_SUPPORT); 411 printf(UT_SUPPORT);
461} 412}
462 413
463 414void print_usage(void) {
464void 415 printf("%s\n", _("Usage:"));
465print_usage (void) 416 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} 417}
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..1d78cce 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"
@@ -51,17 +51,17 @@ const char *email = "devel@monitoring-plugins.org";
51#include <sys/stat.h> 51#include <sys/stat.h>
52#endif 52#endif
53 53
54int process_arguments (int, char **); 54static int process_arguments (int /*argc*/, char ** /*argv*/);
55int validate_arguments (void); 55static int validate_arguments (void);
56int convert_to_seconds (char *); 56static int convert_to_seconds (char * /*etime*/);
57void print_help (void); 57static void print_help (void);
58void print_usage (void); 58void print_usage (void);
59 59
60char *warning_range = NULL; 60static char *warning_range = NULL;
61char *critical_range = NULL; 61static char *critical_range = NULL;
62thresholds *procs_thresholds = NULL; 62static thresholds *procs_thresholds = NULL;
63 63
64int options = 0; /* bitmask of filter criteria to test against */ 64static int options = 0; /* bitmask of filter criteria to test against */
65#define ALL 1 65#define ALL 1
66#define STAT 2 66#define STAT 2
67#define PPID 4 67#define PPID 4
@@ -89,27 +89,25 @@ enum metric {
89}; 89};
90enum metric metric = METRIC_PROCS; 90enum metric metric = METRIC_PROCS;
91 91
92int verbose = 0; 92static int verbose = 0;
93int uid; 93static int uid;
94pid_t ppid; 94static pid_t ppid;
95int vsz; 95static int vsz;
96int rss; 96static int rss;
97float pcpu; 97static float pcpu;
98char *statopts; 98static char *statopts;
99char *prog; 99static char *prog;
100char *exclude_progs; 100static char *exclude_progs;
101char **exclude_progs_arr = NULL; 101static char **exclude_progs_arr = NULL;
102char exclude_progs_counter = 0; 102static char exclude_progs_counter = 0;
103char *args; 103static char *args;
104char *input_filename = NULL; 104static char *input_filename = NULL;
105regex_t re_args; 105static regex_t re_args;
106char *fmt; 106static char *fmt;
107char *fails; 107static char *fails;
108char tmp[MAX_INPUT_BUFFER]; 108static char tmp[MAX_INPUT_BUFFER];
109int kthread_filter = 0; 109static int kthread_filter = 0;
110int usepid = 0; /* whether to test for pid or /proc/pid/exe */ 110static int usepid = 0; /* whether to test for pid or /proc/pid/exe */
111
112FILE *ps_input = NULL;
113 111
114static int 112static int
115stat_exe (const pid_t pid, struct stat *buf) { 113stat_exe (const pid_t pid, struct stat *buf) {
@@ -834,7 +832,7 @@ be the total number of running processes\n\n"));
834 printf (" %s\n", "check_procs -w 50000 -c 100000 --metric=VSZ"); 832 printf (" %s\n", "check_procs -w 50000 -c 100000 --metric=VSZ");
835 printf (" %s\n\n", _("Alert if VSZ of any processes over 50K or 100K")); 833 printf (" %s\n\n", _("Alert if VSZ of any processes over 50K or 100K"));
836 printf (" %s\n", "check_procs -w 10 -c 20 --metric=CPU"); 834 printf (" %s\n", "check_procs -w 10 -c 20 --metric=CPU");
837 printf (" %s\n", _("Alert if CPU of any processes over 10\% or 20\%")); 835 printf (" %s\n", _("Alert if CPU of any processes over 10%% or 20%%"));
838 836
839 printf (UT_SUPPORT); 837 printf (UT_SUPPORT);
840} 838}
diff --git a/plugins/check_radius.c b/plugins/check_radius.c
index 6b32710..d9ff8fa 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"
@@ -46,8 +46,8 @@ const char *email = "devel@monitoring-plugins.org";
46#include <radiusclient.h> 46#include <radiusclient.h>
47#endif 47#endif
48 48
49int process_arguments (int, char **); 49static int process_arguments (int /*argc*/, char ** /*argv*/);
50void print_help (void); 50static void print_help (void);
51void print_usage (void); 51void print_usage (void);
52 52
53#if defined(HAVE_LIBFREERADIUS_CLIENT) || defined(HAVE_LIBRADIUSCLIENT_NG) || defined(HAVE_LIBRADCLI) 53#if defined(HAVE_LIBFREERADIUS_CLIENT) || defined(HAVE_LIBRADIUSCLIENT_NG) || defined(HAVE_LIBRADCLI)
@@ -78,22 +78,22 @@ void print_usage (void);
78#define REJECT_RC BADRESP_RC 78#define REJECT_RC BADRESP_RC
79#endif 79#endif
80 80
81int my_rc_read_config(char *); 81static int my_rc_read_config(char * /*a*/);
82 82
83#if defined(HAVE_LIBFREERADIUS_CLIENT) || defined(HAVE_LIBRADIUSCLIENT_NG) || defined(HAVE_LIBRADCLI) 83#if defined(HAVE_LIBFREERADIUS_CLIENT) || defined(HAVE_LIBRADIUSCLIENT_NG) || defined(HAVE_LIBRADCLI)
84rc_handle *rch = NULL; 84static rc_handle *rch = NULL;
85#endif 85#endif
86 86
87char *server = NULL; 87static char *server = NULL;
88char *username = NULL; 88static char *username = NULL;
89char *password = NULL; 89static char *password = NULL;
90char *nasid = NULL; 90static char *nasid = NULL;
91char *nasipaddress = NULL; 91static char *nasipaddress = NULL;
92char *expect = NULL; 92static char *expect = NULL;
93char *config_file = NULL; 93static char *config_file = NULL;
94unsigned short port = PW_AUTH_UDP_PORT; 94static unsigned short port = PW_AUTH_UDP_PORT;
95int retries = 1; 95static int retries = 1;
96bool verbose = false; 96static bool verbose = false;
97 97
98/****************************************************************************** 98/******************************************************************************
99 99
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..e6369e6 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"
@@ -40,8 +40,8 @@ const char *email = "devel@monitoring-plugins.org";
40#include <ctype.h> 40#include <ctype.h>
41 41
42#ifdef HAVE_SSL 42#ifdef HAVE_SSL
43bool check_cert = false; 43static bool check_cert = false;
44int days_till_exp_warn, days_till_exp_crit; 44static int days_till_exp_warn, days_till_exp_crit;
45# define my_recv(buf, len) (((use_starttls || use_ssl) && ssl_established) ? np_net_ssl_read(buf, len) : read(sd, buf, len)) 45# define my_recv(buf, len) (((use_starttls || use_ssl) && ssl_established) ? np_net_ssl_read(buf, len) : read(sd, buf, len))
46# define my_send(buf, len) (((use_starttls || use_ssl) && ssl_established) ? np_net_ssl_write(buf, len) : send(sd, buf, len, 0)) 46# define my_send(buf, len) (((use_starttls || use_ssl) && ssl_established) ? np_net_ssl_write(buf, len) : send(sd, buf, len, 0))
47#else /* ifndef HAVE_SSL */ 47#else /* ifndef HAVE_SSL */
@@ -64,61 +64,59 @@ enum {
64 64
65#define EHLO_SUPPORTS_STARTTLS 1 65#define EHLO_SUPPORTS_STARTTLS 1
66 66
67int process_arguments (int, char **); 67static int process_arguments (int, char **);
68int validate_arguments (void); 68static int validate_arguments (void);
69void print_help (void); 69static void print_help (void);
70void print_usage (void); 70void print_usage (void);
71void smtp_quit(void); 71static void smtp_quit(void);
72int recvline(char *, size_t); 72static int recvline(char *, size_t);
73int recvlines(char *, size_t); 73static int recvlines(char *, size_t);
74int my_close(void); 74static int my_close(void);
75 75
76#include "regex.h" 76#include "regex.h"
77char regex_expect[MAX_INPUT_BUFFER] = ""; 77static regex_t preg;
78regex_t preg; 78static regmatch_t pmatch[10];
79regmatch_t pmatch[10]; 79static char errbuf[MAX_INPUT_BUFFER];
80char timestamp[20] = ""; 80static int cflags = REG_EXTENDED | REG_NOSUB | REG_NEWLINE;
81char errbuf[MAX_INPUT_BUFFER]; 81static int eflags = 0;
82int cflags = REG_EXTENDED | REG_NOSUB | REG_NEWLINE; 82static int errcode, excode;
83int eflags = 0; 83
84int errcode, excode; 84static int server_port = SMTP_PORT;
85 85static int server_port_option = 0;
86int server_port = SMTP_PORT; 86static char *server_address = NULL;
87int server_port_option = 0; 87static char *server_expect = NULL;
88char *server_address = NULL; 88static char *mail_command = NULL;
89char *server_expect = NULL; 89static char *from_arg = NULL;
90char *mail_command = NULL; 90static int send_mail_from=0;
91char *from_arg = NULL; 91static int ncommands=0;
92int send_mail_from=0; 92static int command_size=0;
93int ncommands=0; 93static int nresponses=0;
94int command_size=0; 94static int response_size=0;
95int nresponses=0; 95static char **commands = NULL;
96int response_size=0; 96static char **responses = NULL;
97char **commands = NULL; 97static char *authtype = NULL;
98char **responses = NULL; 98static char *authuser = NULL;
99char *authtype = NULL; 99static char *authpass = NULL;
100char *authuser = NULL; 100static double warning_time = 0;
101char *authpass = NULL; 101static bool check_warning_time = false;
102double warning_time = 0; 102static double critical_time = 0;
103bool check_warning_time = false; 103static bool check_critical_time = false;
104double critical_time = 0; 104static int verbose = 0;
105bool check_critical_time = false; 105static bool use_ssl = false;
106int verbose = 0; 106static bool use_starttls = false;
107bool use_ssl = false; 107static bool use_sni = false;
108bool use_starttls = false; 108static bool use_proxy_prefix = false;
109bool use_sni = false; 109static bool use_ehlo = false;
110bool use_proxy_prefix = false; 110static bool use_lhlo = false;
111bool use_ehlo = false; 111static bool ssl_established = false;
112bool use_lhlo = false; 112static char *localhostname = NULL;
113bool ssl_established = false; 113static int sd;
114char *localhostname = NULL; 114static char buffer[MAX_INPUT_BUFFER];
115int sd;
116char buffer[MAX_INPUT_BUFFER];
117enum { 115enum {
118 TCP_PROTOCOL = 1, 116 TCP_PROTOCOL = 1,
119 UDP_PROTOCOL = 2, 117 UDP_PROTOCOL = 2,
120}; 118};
121bool ignore_send_quit_failure = false; 119static bool ignore_send_quit_failure = false;
122 120
123 121
124int 122int
diff --git a/plugins/check_snmp.c b/plugins/check_snmp.c
index 937b3a5..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,136 +37,143 @@ const char *email = "devel@monitoring-plugins.org";
37#include "utils.h" 37#include "utils.h"
38#include "utils_cmd.h" 38#include "utils_cmd.h"
39 39
40#define DEFAULT_COMMUNITY "public" 40#define DEFAULT_COMMUNITY "public"
41#define DEFAULT_PORT "161" 41#define DEFAULT_PORT "161"
42#define DEFAULT_MIBLIST "ALL" 42#define DEFAULT_MIBLIST "ALL"
43#define DEFAULT_PROTOCOL "1" 43#define DEFAULT_PROTOCOL "1"
44#define DEFAULT_RETRIES 5 44#define DEFAULT_RETRIES 5
45#define DEFAULT_AUTH_PROTOCOL "MD5" 45#define DEFAULT_AUTH_PROTOCOL "MD5"
46#define DEFAULT_PRIV_PROTOCOL "DES" 46#define DEFAULT_PRIV_PROTOCOL "DES"
47#define DEFAULT_DELIMITER "=" 47#define DEFAULT_DELIMITER "="
48#define DEFAULT_OUTPUT_DELIMITER " " 48#define DEFAULT_OUTPUT_DELIMITER " "
49#define DEFAULT_BUFFER_SIZE 100 49#define DEFAULT_BUFFER_SIZE 100
50 50
51#define mark(a) ((a)!=0?"*":"") 51#define mark(a) ((a) != 0 ? "*" : "")
52 52
53#define CHECK_UNDEF 0 53#define CHECK_UNDEF 0
54#define CRIT_PRESENT 1 54#define CRIT_PRESENT 1
55#define CRIT_STRING 2 55#define CRIT_STRING 2
56#define CRIT_REGEX 4 56#define CRIT_REGEX 4
57#define WARN_PRESENT 8 57#define WARN_PRESENT 8
58#define WARN_STRING 16
59#define WARN_REGEX 32
60 58
61#define OID_COUNT_STEP 8 59#define OID_COUNT_STEP 8
62 60
63/* Longopts only arguments */ 61/* Longopts only arguments */
64#define L_CALCULATE_RATE CHAR_MAX+1 62#define L_CALCULATE_RATE CHAR_MAX + 1
65#define L_RATE_MULTIPLIER CHAR_MAX+2 63#define L_RATE_MULTIPLIER CHAR_MAX + 2
66#define L_INVERT_SEARCH CHAR_MAX+3 64#define L_INVERT_SEARCH CHAR_MAX + 3
67#define L_OFFSET CHAR_MAX+4 65#define L_OFFSET CHAR_MAX + 4
68#define L_IGNORE_MIB_PARSING_ERRORS CHAR_MAX+5 66#define L_IGNORE_MIB_PARSING_ERRORS CHAR_MAX + 5
69 67
70/* Gobble to string - stop incrementing c when c[0] match one of the 68/* Gobble to string - stop incrementing c when c[0] match one of the
71 * characters in s */ 69 * characters in s */
72#define GOBBLE_TOS(c, s) while(c[0]!='\0' && strchr(s, c[0])==NULL) { c++; } 70#define GOBBLE_TOS(c, s) \
71 while (c[0] != '\0' && strchr(s, c[0]) == NULL) { \
72 c++; \
73 }
73/* Given c, keep track of backslashes (bk) and double-quotes (dq) 74/* Given c, keep track of backslashes (bk) and double-quotes (dq)
74 * from c[0] */ 75 * from c[0] */
75#define COUNT_SEQ(c, bk, dq) switch(c[0]) {\ 76#define COUNT_SEQ(c, bk, dq) \
76 case '\\': \ 77 switch (c[0]) { \
77 if (bk) bk--; \ 78 case '\\': \
78 else bk++; \ 79 if (bk) \
79 break; \ 80 bk--; \
80 case '"': \ 81 else \
81 if (!dq) { dq++; } \ 82 bk++; \
82 else if(!bk) { dq--; } \ 83 break; \
83 else { bk--; } \ 84 case '"': \
84 break; \ 85 if (!dq) { \
86 dq++; \
87 } else if (!bk) { \
88 dq--; \
89 } else { \
90 bk--; \
91 } \
92 break; \
85 } 93 }
86 94
87 95static int process_arguments(int, char **);
88 96static int validate_arguments(void);
89int process_arguments (int, char **); 97static char *thisarg(char *str);
90int validate_arguments (void); 98static char *nextarg(char *str);
91char *thisarg (char *str); 99void print_usage(void);
92char *nextarg (char *str); 100static void print_help(void);
93void print_usage (void); 101static char *multiply(char *str);
94void print_help (void);
95char *multiply (char *str);
96 102
97#include "regex.h" 103#include "regex.h"
98char regex_expect[MAX_INPUT_BUFFER] = ""; 104static char regex_expect[MAX_INPUT_BUFFER] = "";
99regex_t preg; 105static regex_t preg;
100regmatch_t pmatch[10]; 106static regmatch_t pmatch[10];
101char errbuf[MAX_INPUT_BUFFER] = ""; 107static char errbuf[MAX_INPUT_BUFFER] = "";
102char perfstr[MAX_INPUT_BUFFER] = "| "; 108static char perfstr[MAX_INPUT_BUFFER] = "| ";
103int cflags = REG_EXTENDED | REG_NOSUB | REG_NEWLINE; 109static int cflags = REG_EXTENDED | REG_NOSUB | REG_NEWLINE;
104int eflags = 0; 110static int eflags = 0;
105int errcode, excode; 111static int errcode, excode;
106 112
107char *server_address = NULL; 113static char *server_address = NULL;
108char *community = NULL; 114static char *community = NULL;
109char **contextargs = NULL; 115static char **contextargs = NULL;
110char *context = NULL; 116static char *context = NULL;
111char **authpriv = NULL; 117static char **authpriv = NULL;
112char *proto = NULL; 118static char *proto = NULL;
113char *seclevel = NULL; 119static char *seclevel = NULL;
114char *secname = NULL; 120static char *secname = NULL;
115char *authproto = NULL; 121static char *authproto = NULL;
116char *privproto = NULL; 122static char *privproto = NULL;
117char *authpasswd = NULL; 123static char *authpasswd = NULL;
118char *privpasswd = NULL; 124static char *privpasswd = NULL;
119int nulloid = STATE_UNKNOWN; 125static int nulloid = STATE_UNKNOWN;
120char **oids = NULL; 126static char **oids = NULL;
121size_t oids_size = 0; 127static size_t oids_size = 0;
122char *label; 128static char *label;
123char *units; 129static char *units;
124char *port; 130static char *port;
125char *snmpcmd; 131static char *snmpcmd;
126char string_value[MAX_INPUT_BUFFER] = ""; 132static char string_value[MAX_INPUT_BUFFER] = "";
127int invert_search=0; 133static int invert_search = 0;
128char **labels = NULL; 134static char **labels = NULL;
129char **unitv = NULL; 135static char **unitv = NULL;
130size_t nlabels = 0; 136static size_t nlabels = 0;
131size_t labels_size = OID_COUNT_STEP; 137static size_t labels_size = OID_COUNT_STEP;
132size_t nunits = 0; 138static size_t nunits = 0;
133size_t unitv_size = OID_COUNT_STEP; 139static size_t unitv_size = OID_COUNT_STEP;
134size_t numoids = 0; 140static size_t numoids = 0;
135int numauthpriv = 0; 141static int numauthpriv = 0;
136int numcontext = 0; 142static int numcontext = 0;
137int verbose = 0; 143static int verbose = 0;
138bool usesnmpgetnext = false; 144static bool usesnmpgetnext = false;
139char *warning_thresholds = NULL; 145static char *warning_thresholds = NULL;
140char *critical_thresholds = NULL; 146static char *critical_thresholds = NULL;
141thresholds **thlds; 147static thresholds **thlds;
142size_t thlds_size = OID_COUNT_STEP; 148static size_t thlds_size = OID_COUNT_STEP;
143double *response_value; 149static double *response_value;
144size_t response_size = OID_COUNT_STEP; 150static size_t response_size = OID_COUNT_STEP;
145int retries = 0; 151static int retries = 0;
146int *eval_method; 152static int *eval_method;
147size_t eval_size = OID_COUNT_STEP; 153static size_t eval_size = OID_COUNT_STEP;
148char *delimiter; 154static char *delimiter;
149char *output_delim; 155static char *output_delim;
150char *miblist = NULL; 156static char *miblist = NULL;
151bool needmibs = false; 157static bool needmibs = false;
152int calculate_rate = 0; 158static int calculate_rate = 0;
153double offset = 0.0; 159static double offset = 0.0;
154int rate_multiplier = 1; 160static int rate_multiplier = 1;
155state_data *previous_state; 161static state_data *previous_state;
156double *previous_value; 162static double *previous_value;
157size_t previous_size = OID_COUNT_STEP; 163static size_t previous_size = OID_COUNT_STEP;
158int perf_labels = 1; 164static int perf_labels = 1;
159char* ip_version = ""; 165static char *ip_version = "";
160double multiplier = 1.0; 166static double multiplier = 1.0;
161char *fmtstr = ""; 167static char *fmtstr = "";
162bool fmtstr_set = false; 168static bool fmtstr_set = false;
163char buffer[DEFAULT_BUFFER_SIZE]; 169static char buffer[DEFAULT_BUFFER_SIZE];
164bool ignore_mib_parsing_errors = false; 170static bool ignore_mib_parsing_errors = false;
165 171
166static char *fix_snmp_range(char *th) 172static char *fix_snmp_range(char *th) {
167{ 173 double left;
168 double left, right; 174 double right;
169 char *colon, *ret; 175 char *colon;
176 char *ret;
170 177
171 if ((colon = strchr(th, ':')) == NULL || *(colon + 1) == '\0') 178 if ((colon = strchr(th, ':')) == NULL || *(colon + 1) == '\0')
172 return th; 179 return th;
@@ -184,12 +191,12 @@ static char *fix_snmp_range(char *th)
184 return ret; 191 return ret;
185} 192}
186 193
187int 194int main(int argc, char **argv) {
188main (int argc, char **argv) 195 int len;
189{ 196 int total_oids;
190 int len, total_oids;
191 size_t line; 197 size_t line;
192 unsigned int bk_count = 0, dq_count = 0; 198 unsigned int bk_count = 0;
199 unsigned int dq_count = 0;
193 int iresult = STATE_UNKNOWN; 200 int iresult = STATE_UNKNOWN;
194 int result = STATE_UNKNOWN; 201 int result = STATE_UNKNOWN;
195 int return_code = 0; 202 int return_code = 0;
@@ -202,80 +209,83 @@ main (int argc, char **argv)
202 char *outbuff; 209 char *outbuff;
203 char *ptr = NULL; 210 char *ptr = NULL;
204 char *show = NULL; 211 char *show = NULL;
205 char *th_warn=NULL; 212 char *th_warn = NULL;
206 char *th_crit=NULL; 213 char *th_crit = NULL;
207 char type[8] = ""; 214 char type[8] = "";
208 output chld_out, chld_err; 215 output chld_out;
209 char *previous_string=NULL; 216 output chld_err;
210 char *ap=NULL; 217 char *previous_string = NULL;
211 char *state_string=NULL; 218 char *ap = NULL;
212 size_t response_length, current_length, string_length; 219 char *state_string = NULL;
213 char *temp_string=NULL; 220 size_t response_length;
214 char *quote_string=NULL; 221 size_t current_length;
222 size_t string_length;
223 char *temp_string = NULL;
224 char *quote_string = NULL;
215 time_t current_time; 225 time_t current_time;
216 double temp_double; 226 double temp_double;
217 time_t duration; 227 time_t duration;
218 char *conv = "12345678"; 228 char *conv = "12345678";
219 int is_counter=0; 229 int is_counter = 0;
220 230
221 setlocale (LC_ALL, ""); 231 setlocale(LC_ALL, "");
222 bindtextdomain (PACKAGE, LOCALEDIR); 232 bindtextdomain(PACKAGE, LOCALEDIR);
223 textdomain (PACKAGE); 233 textdomain(PACKAGE);
224 234
225 labels = malloc (labels_size * sizeof(*labels)); 235 labels = malloc(labels_size * sizeof(*labels));
226 unitv = malloc (unitv_size * sizeof(*unitv)); 236 unitv = malloc(unitv_size * sizeof(*unitv));
227 thlds = malloc (thlds_size * sizeof(*thlds)); 237 thlds = malloc(thlds_size * sizeof(*thlds));
228 response_value = malloc (response_size * sizeof(*response_value)); 238 response_value = malloc(response_size * sizeof(*response_value));
229 previous_value = malloc (previous_size * sizeof(*previous_value)); 239 previous_value = malloc(previous_size * sizeof(*previous_value));
230 eval_method = calloc (eval_size, sizeof(*eval_method)); 240 eval_method = calloc(eval_size, sizeof(*eval_method));
231 oids = calloc(oids_size, sizeof (char *)); 241 oids = calloc(oids_size, sizeof(char *));
232 242
233 label = strdup ("SNMP"); 243 label = strdup("SNMP");
234 units = strdup (""); 244 units = strdup("");
235 port = strdup (DEFAULT_PORT); 245 port = strdup(DEFAULT_PORT);
236 outbuff = strdup (""); 246 outbuff = strdup("");
237 delimiter = strdup (" = "); 247 delimiter = strdup(" = ");
238 output_delim = strdup (DEFAULT_OUTPUT_DELIMITER); 248 output_delim = strdup(DEFAULT_OUTPUT_DELIMITER);
239 timeout_interval = DEFAULT_SOCKET_TIMEOUT; 249 timeout_interval = DEFAULT_SOCKET_TIMEOUT;
240 retries = DEFAULT_RETRIES; 250 retries = DEFAULT_RETRIES;
241 251
242 np_init( (char *) progname, argc, argv ); 252 np_init((char *)progname, argc, argv);
243 253
244 /* Parse extra opts if any */ 254 /* Parse extra opts if any */
245 argv=np_extra_opts (&argc, argv, progname); 255 argv = np_extra_opts(&argc, argv, progname);
246 256
247 np_set_args(argc, argv); 257 np_set_args(argc, argv);
248 258
249 time(&current_time); 259 time(&current_time);
250 260
251 if (process_arguments (argc, argv) == ERROR) 261 if (process_arguments(argc, argv) == ERROR)
252 usage4 (_("Could not parse arguments")); 262 usage4(_("Could not parse arguments"));
253 263
254 if(calculate_rate) { 264 if (calculate_rate) {
255 if (!strcmp(label, "SNMP")) 265 if (!strcmp(label, "SNMP"))
256 label = strdup("SNMP RATE"); 266 label = strdup("SNMP RATE");
257 267
258 size_t i = 0; 268 size_t i = 0;
259 269
260 previous_state = np_state_read(); 270 previous_state = np_state_read();
261 if(previous_state!=NULL) { 271 if (previous_state != NULL) {
262 /* Split colon separated values */ 272 /* Split colon separated values */
263 previous_string = strdup((char *) previous_state->data); 273 previous_string = strdup((char *)previous_state->data);
264 while((ap = strsep(&previous_string, ":")) != NULL) { 274 while ((ap = strsep(&previous_string, ":")) != NULL) {
265 if(verbose>2) 275 if (verbose > 2)
266 printf("State for %zd=%s\n", i, ap); 276 printf("State for %zd=%s\n", i, ap);
267 while (i >= previous_size) { 277 while (i >= previous_size) {
268 previous_size += OID_COUNT_STEP; 278 previous_size += OID_COUNT_STEP;
269 previous_value = realloc(previous_value, previous_size * sizeof(*previous_value)); 279 previous_value = realloc(previous_value, previous_size * sizeof(*previous_value));
270 } 280 }
271 previous_value[i++]=strtod(ap,NULL); 281 previous_value[i++] = strtod(ap, NULL);
272 } 282 }
273 } 283 }
274 } 284 }
275 285
276 /* Populate the thresholds */ 286 /* Populate the thresholds */
277 th_warn=warning_thresholds; 287 th_warn = warning_thresholds;
278 th_crit=critical_thresholds; 288 th_crit = critical_thresholds;
279 for (size_t i = 0; i < numoids; i++) { 289 for (size_t i = 0; i < numoids; i++) {
280 char *w = th_warn ? strndup(th_warn, strcspn(th_warn, ",")) : NULL; 290 char *w = th_warn ? strndup(th_warn, strcspn(th_warn, ",")) : NULL;
281 char *c = th_crit ? strndup(th_crit, strcspn(th_crit, ",")) : NULL; 291 char *c = th_crit ? strndup(th_crit, strcspn(th_crit, ",")) : NULL;
@@ -289,53 +299,52 @@ main (int argc, char **argv)
289 } 299 }
290 300
291 /* Skip empty thresholds, while avoiding segfault */ 301 /* Skip empty thresholds, while avoiding segfault */
292 set_thresholds(&thlds[i], 302 set_thresholds(&thlds[i], w ? strpbrk(w, NP_THRESHOLDS_CHARS) : NULL, c ? strpbrk(c, NP_THRESHOLDS_CHARS) : NULL);
293 w ? strpbrk(w, NP_THRESHOLDS_CHARS) : NULL,
294 c ? strpbrk(c, NP_THRESHOLDS_CHARS) : NULL);
295 if (w) { 303 if (w) {
296 th_warn=strchr(th_warn, ','); 304 th_warn = strchr(th_warn, ',');
297 if (th_warn) th_warn++; 305 if (th_warn)
306 th_warn++;
298 free(w); 307 free(w);
299 } 308 }
300 if (c) { 309 if (c) {
301 th_crit=strchr(th_crit, ','); 310 th_crit = strchr(th_crit, ',');
302 if (th_crit) th_crit++; 311 if (th_crit)
312 th_crit++;
303 free(c); 313 free(c);
304 } 314 }
305 } 315 }
306 316
307 /* Create the command array to execute */ 317 /* Create the command array to execute */
308 if(usesnmpgetnext) { 318 if (usesnmpgetnext) {
309 snmpcmd = strdup (PATH_TO_SNMPGETNEXT); 319 snmpcmd = strdup(PATH_TO_SNMPGETNEXT);
310 }else{ 320 } else {
311 snmpcmd = strdup (PATH_TO_SNMPGET); 321 snmpcmd = strdup(PATH_TO_SNMPGET);
312 } 322 }
313 323
314 /* 10 arguments to pass before context and authpriv options + 1 for host and numoids. Add one for terminating NULL */ 324 /* 10 arguments to pass before context and authpriv options + 1 for host and numoids. Add one for terminating NULL */
315 325
316 unsigned index = 0; 326 unsigned index = 0;
317 command_line = calloc (11 + numcontext + numauthpriv + 1 + numoids + 1, sizeof (char *)); 327 command_line = calloc(11 + numcontext + numauthpriv + 1 + numoids + 1, sizeof(char *));
318 328
319 command_line[index++] = snmpcmd; 329 command_line[index++] = snmpcmd;
320 command_line[index++] = strdup ("-Le"); 330 command_line[index++] = strdup("-Le");
321 command_line[index++] = strdup ("-t"); 331 command_line[index++] = strdup("-t");
322 xasprintf (&command_line[index++], "%d", timeout_interval); 332 xasprintf(&command_line[index++], "%d", timeout_interval);
323 command_line[index++] = strdup ("-r"); 333 command_line[index++] = strdup("-r");
324 xasprintf (&command_line[index++], "%d", retries); 334 xasprintf(&command_line[index++], "%d", retries);
325 command_line[index++] = strdup ("-m"); 335 command_line[index++] = strdup("-m");
326 command_line[index++] = strdup (miblist); 336 command_line[index++] = strdup(miblist);
327 command_line[index++] = "-v"; 337 command_line[index++] = "-v";
328 command_line[index++] = strdup (proto); 338 command_line[index++] = strdup(proto);
329 339
330 xasprintf(&cl_hidden_auth, "%s -Le -t %d -r %d -m %s -v %s", 340 xasprintf(&cl_hidden_auth, "%s -Le -t %d -r %d -m %s -v %s", snmpcmd, timeout_interval, retries, strlen(miblist) ? miblist : "''",
331 snmpcmd, timeout_interval, retries, strlen(miblist) ? miblist : "''", proto); 341 proto);
332 342
333 if (ignore_mib_parsing_errors) { 343 if (ignore_mib_parsing_errors) {
334 command_line[index++] = "-Pe"; 344 command_line[index++] = "-Pe";
335 xasprintf(&cl_hidden_auth, "%s -Pe", cl_hidden_auth); 345 xasprintf(&cl_hidden_auth, "%s -Pe", cl_hidden_auth);
336 } 346 }
337 347
338
339 for (int i = 0; i < numcontext; i++) { 348 for (int i = 0; i < numcontext; i++) {
340 command_line[index++] = contextargs[i]; 349 command_line[index++] = contextargs[i];
341 } 350 }
@@ -344,12 +353,9 @@ main (int argc, char **argv)
344 command_line[index++] = authpriv[i]; 353 command_line[index++] = authpriv[i];
345 } 354 }
346 355
347 xasprintf (&command_line[index++], "%s:%s", server_address, port); 356 xasprintf(&command_line[index++], "%s:%s", server_address, port);
348 357
349 xasprintf(&cl_hidden_auth, "%s [context] [authpriv] %s:%s", 358 xasprintf(&cl_hidden_auth, "%s [context] [authpriv] %s:%s", cl_hidden_auth, server_address, port);
350 cl_hidden_auth,
351 server_address,
352 port);
353 359
354 for (size_t i = 0; i < numoids; i++) { 360 for (size_t i = 0; i < numoids; i++) {
355 command_line[index++] = oids[i]; 361 command_line[index++] = oids[i];
@@ -359,17 +365,17 @@ main (int argc, char **argv)
359 command_line[index++] = NULL; 365 command_line[index++] = NULL;
360 366
361 if (verbose) { 367 if (verbose) {
362 printf ("%s\n", cl_hidden_auth); 368 printf("%s\n", cl_hidden_auth);
363 } 369 }
364 370
365 /* Set signal handling and alarm */ 371 /* Set signal handling and alarm */
366 if (signal (SIGALRM, runcmd_timeout_alarm_handler) == SIG_ERR) { 372 if (signal(SIGALRM, runcmd_timeout_alarm_handler) == SIG_ERR) {
367 usage4 (_("Cannot catch SIGALRM")); 373 usage4(_("Cannot catch SIGALRM"));
368 } 374 }
369 alarm(timeout_interval * retries + 5); 375 alarm(timeout_interval * retries + 5);
370 376
371 /* Run the command */ 377 /* Run the command */
372 return_code = cmd_run_array (command_line, &chld_out, &chld_err, 0); 378 return_code = cmd_run_array(command_line, &chld_out, &chld_err, 0);
373 379
374 /* disable alarm again */ 380 /* disable alarm again */
375 alarm(0); 381 alarm(0);
@@ -379,80 +385,74 @@ main (int argc, char **argv)
379 Do this way so that if there is stderr, will get added to output, which helps problem diagnosis 385 Do this way so that if there is stderr, will get added to output, which helps problem diagnosis
380 */ 386 */
381 if (return_code != 0) 387 if (return_code != 0)
382 external_error=1; 388 external_error = 1;
383 if (chld_out.lines == 0) 389 if (chld_out.lines == 0)
384 external_error=1; 390 external_error = 1;
385 if (external_error) { 391 if (external_error) {
386 if (chld_err.lines > 0) { 392 if (chld_err.lines > 0) {
387 printf (_("External command error: %s\n"), chld_err.line[0]); 393 printf(_("External command error: %s\n"), chld_err.line[0]);
388 for (size_t i = 1; i < chld_err.lines; i++) { 394 for (size_t i = 1; i < chld_err.lines; i++) {
389 printf ("%s\n", chld_err.line[i]); 395 printf("%s\n", chld_err.line[i]);
390 } 396 }
391 } else { 397 } else {
392 printf(_("External command error with no output (return code: %d)\n"), return_code); 398 printf(_("External command error with no output (return code: %d)\n"), return_code);
393 } 399 }
394 exit (STATE_UNKNOWN); 400 exit(STATE_UNKNOWN);
395 } 401 }
396 402
397 if (verbose) { 403 if (verbose) {
398 for (size_t i = 0; i < chld_out.lines; i++) { 404 for (size_t i = 0; i < chld_out.lines; i++) {
399 printf ("%s\n", chld_out.line[i]); 405 printf("%s\n", chld_out.line[i]);
400 } 406 }
401 } 407 }
402 408
403 line = 0; 409 line = 0;
404 total_oids = 0; 410 total_oids = 0;
405 for (size_t i = 0; line < chld_out.lines && i < numoids ; line++, i++, total_oids++) { 411 for (size_t i = 0; line < chld_out.lines && i < numoids; line++, i++, total_oids++) {
406 if(calculate_rate) 412 if (calculate_rate)
407 conv = "%.10g"; 413 conv = "%.10g";
408 else 414 else
409 conv = "%.0f"; 415 conv = "%.0f";
410 416
411 ptr = chld_out.line[line]; 417 ptr = chld_out.line[line];
412 oidname = strpcpy (oidname, ptr, delimiter); 418 oidname = strpcpy(oidname, ptr, delimiter);
413 response = strstr (ptr, delimiter); 419 response = strstr(ptr, delimiter);
414 if (response == NULL) 420 if (response == NULL)
415 break; 421 break;
416 422
417 if (verbose > 2) { 423 if (verbose > 2) {
418 printf("Processing oid %zi (line %zi)\n oidname: %s\n response: %s\n", i+1, line+1, oidname, response); 424 printf("Processing oid %zi (line %zi)\n oidname: %s\n response: %s\n", i + 1, line + 1, oidname, response);
419 } 425 }
420 426
421 /* Clean up type array - Sol10 does not necessarily zero it out */ 427 /* Clean up type array - Sol10 does not necessarily zero it out */
422 bzero(type, sizeof(type)); 428 bzero(type, sizeof(type));
423 429
424 is_counter=0; 430 is_counter = 0;
425 /* We strip out the datatype indicator for PHBs */ 431 /* We strip out the datatype indicator for PHBs */
426 if (strstr (response, "Gauge: ")) { 432 if (strstr(response, "Gauge: ")) {
427 show = multiply (strstr (response, "Gauge: ") + 7); 433 show = multiply(strstr(response, "Gauge: ") + 7);
428 } 434 } else if (strstr(response, "Gauge32: ")) {
429 else if (strstr (response, "Gauge32: ")) { 435 show = multiply(strstr(response, "Gauge32: ") + 9);
430 show = multiply (strstr (response, "Gauge32: ") + 9); 436 } else if (strstr(response, "Counter32: ")) {
431 } 437 show = strstr(response, "Counter32: ") + 11;
432 else if (strstr (response, "Counter32: ")) { 438 is_counter = 1;
433 show = strstr (response, "Counter32: ") + 11; 439 if (!calculate_rate)
434 is_counter=1;
435 if(!calculate_rate)
436 strcpy(type, "c"); 440 strcpy(type, "c");
437 } 441 } else if (strstr(response, "Counter64: ")) {
438 else if (strstr (response, "Counter64: ")) { 442 show = strstr(response, "Counter64: ") + 11;
439 show = strstr (response, "Counter64: ") + 11; 443 is_counter = 1;
440 is_counter=1; 444 if (!calculate_rate)
441 if(!calculate_rate)
442 strcpy(type, "c"); 445 strcpy(type, "c");
443 } 446 } else if (strstr(response, "INTEGER: ")) {
444 else if (strstr (response, "INTEGER: ")) { 447 show = multiply(strstr(response, "INTEGER: ") + 9);
445 show = multiply (strstr (response, "INTEGER: ") + 9);
446 448
447 if (fmtstr_set) { 449 if (fmtstr_set) {
448 conv = fmtstr; 450 conv = fmtstr;
449 } 451 }
450 } 452 } else if (strstr(response, "OID: ")) {
451 else if (strstr (response, "OID: ")) { 453 show = strstr(response, "OID: ") + 5;
452 show = strstr (response, "OID: ") + 5; 454 } else if (strstr(response, "STRING: ")) {
453 } 455 show = strstr(response, "STRING: ") + 8;
454 else if (strstr (response, "STRING: ")) {
455 show = strstr (response, "STRING: ") + 8;
456 conv = "%.10g"; 456 conv = "%.10g";
457 457
458 /* Get the rest of the string on multi-line strings */ 458 /* Get the rest of the string on multi-line strings */
@@ -466,15 +466,17 @@ main (int argc, char **argv)
466 466
467 if (dq_count) { /* unfinished line */ 467 if (dq_count) { /* unfinished line */
468 /* copy show verbatim first */ 468 /* copy show verbatim first */
469 if (!mult_resp) mult_resp = strdup(""); 469 if (!mult_resp)
470 xasprintf (&mult_resp, "%s%s:\n%s\n", mult_resp, oids[i], show); 470 mult_resp = strdup("");
471 xasprintf(&mult_resp, "%s%s:\n%s\n", mult_resp, oids[i], show);
471 /* then strip out unmatched double-quote from single-line output */ 472 /* then strip out unmatched double-quote from single-line output */
472 if (show[0] == '"') show++; 473 if (show[0] == '"')
474 show++;
473 475
474 /* Keep reading until we match end of double-quoted string */ 476 /* Keep reading until we match end of double-quoted string */
475 for (line++; line < chld_out.lines; line++) { 477 for (line++; line < chld_out.lines; line++) {
476 ptr = chld_out.line[line]; 478 ptr = chld_out.line[line];
477 xasprintf (&mult_resp, "%s%s\n", mult_resp, ptr); 479 xasprintf(&mult_resp, "%s%s\n", mult_resp, ptr);
478 480
479 COUNT_SEQ(ptr, bk_count, dq_count) 481 COUNT_SEQ(ptr, bk_count, dq_count)
480 while (dq_count && ptr[0] != '\n' && ptr[0] != '\0') { 482 while (dq_count && ptr[0] != '\n' && ptr[0] != '\0') {
@@ -483,15 +485,14 @@ main (int argc, char **argv)
483 COUNT_SEQ(ptr, bk_count, dq_count) 485 COUNT_SEQ(ptr, bk_count, dq_count)
484 } 486 }
485 /* Break for loop before next line increment when done */ 487 /* Break for loop before next line increment when done */
486 if (!dq_count) break; 488 if (!dq_count)
489 break;
487 } 490 }
488 } 491 }
489 492
490 } 493 } else if (strstr(response, "Timeticks: ")) {
491 else if (strstr (response, "Timeticks: ")) { 494 show = strstr(response, "Timeticks: ");
492 show = strstr (response, "Timeticks: "); 495 } else
493 }
494 else
495 show = response + 3; 496 show = response + 3;
496 497
497 iresult = STATE_DEPENDENT; 498 iresult = STATE_DEPENDENT;
@@ -502,68 +503,67 @@ main (int argc, char **argv)
502 if (verbose > 2) { 503 if (verbose > 2) {
503 print_thresholds(" thresholds", thlds[i]); 504 print_thresholds(" thresholds", thlds[i]);
504 } 505 }
505 ptr = strpbrk (show, "-0123456789"); 506 ptr = strpbrk(show, "-0123456789");
506 if (ptr == NULL){ 507 if (ptr == NULL) {
507 if (nulloid == 3) 508 if (nulloid == 3)
508 die (STATE_UNKNOWN,_("No valid data returned (%s)\n"), show); 509 die(STATE_UNKNOWN, _("No valid data returned (%s)\n"), show);
509 else if (nulloid == 0) 510 else if (nulloid == 0)
510 die (STATE_OK,_("No valid data returned (%s)\n"), show); 511 die(STATE_OK, _("No valid data returned (%s)\n"), show);
511 else if (nulloid == 1) 512 else if (nulloid == 1)
512 die (STATE_WARNING,_("No valid data returned (%s)\n"), show); 513 die(STATE_WARNING, _("No valid data returned (%s)\n"), show);
513 else if (nulloid == 2) 514 else if (nulloid == 2)
514 die (STATE_CRITICAL,_("No valid data returned (%s)\n"), show); 515 die(STATE_CRITICAL, _("No valid data returned (%s)\n"), show);
515 } 516 }
516 while (i >= response_size) { 517 while (i >= response_size) {
517 response_size += OID_COUNT_STEP; 518 response_size += OID_COUNT_STEP;
518 response_value = realloc(response_value, response_size * sizeof(*response_value)); 519 response_value = realloc(response_value, response_size * sizeof(*response_value));
519 } 520 }
520 response_value[i] = strtod (ptr, NULL) + offset; 521 response_value[i] = strtod(ptr, NULL) + offset;
521 522
522 if(calculate_rate) { 523 if (calculate_rate) {
523 if (previous_state!=NULL) { 524 if (previous_state != NULL) {
524 duration = current_time-previous_state->time; 525 duration = current_time - previous_state->time;
525 if(duration<=0) 526 if (duration <= 0)
526 die(STATE_UNKNOWN,_("Time duration between plugin calls is invalid")); 527 die(STATE_UNKNOWN, _("Time duration between plugin calls is invalid"));
527 temp_double = response_value[i]-previous_value[i]; 528 temp_double = response_value[i] - previous_value[i];
528 /* Simple overflow catcher (same as in rrdtool, rrd_update.c) */ 529 /* Simple overflow catcher (same as in rrdtool, rrd_update.c) */
529 if(is_counter) { 530 if (is_counter) {
530 if(temp_double<(double)0.0) 531 if (temp_double < (double)0.0)
531 temp_double+=(double)4294967296.0; /* 2^32 */ 532 temp_double += (double)4294967296.0; /* 2^32 */
532 if(temp_double<(double)0.0) 533 if (temp_double < (double)0.0)
533 temp_double+=(double)18446744069414584320.0; /* 2^64-2^32 */; 534 temp_double += (double)18446744069414584320.0; /* 2^64-2^32 */
535 ;
534 } 536 }
535 /* Convert to per second, then use multiplier */ 537 /* Convert to per second, then use multiplier */
536 temp_double = temp_double/duration*rate_multiplier; 538 temp_double = temp_double / duration * rate_multiplier;
537 iresult = get_status(temp_double, thlds[i]); 539 iresult = get_status(temp_double, thlds[i]);
538 xasprintf (&show, conv, temp_double); 540 xasprintf(&show, conv, temp_double);
539 } 541 }
540 } else { 542 } else {
541 iresult = get_status(response_value[i], thlds[i]); 543 iresult = get_status(response_value[i], thlds[i]);
542 xasprintf (&show, conv, response_value[i]); 544 xasprintf(&show, conv, response_value[i]);
543 } 545 }
544 } 546 }
545 547
546 /* Process this block for string matching */ 548 /* Process this block for string matching */
547 else if (eval_size > i && eval_method[i] & CRIT_STRING) { 549 else if (eval_size > i && eval_method[i] & CRIT_STRING) {
548 if (strcmp (show, string_value)) 550 if (strcmp(show, string_value))
549 iresult = (invert_search==0) ? STATE_CRITICAL : STATE_OK; 551 iresult = (invert_search == 0) ? STATE_CRITICAL : STATE_OK;
550 else 552 else
551 iresult = (invert_search==0) ? STATE_OK : STATE_CRITICAL; 553 iresult = (invert_search == 0) ? STATE_OK : STATE_CRITICAL;
552 } 554 }
553 555
554 /* Process this block for regex matching */ 556 /* Process this block for regex matching */
555 else if (eval_size > i && eval_method[i] & CRIT_REGEX) { 557 else if (eval_size > i && eval_method[i] & CRIT_REGEX) {
556 excode = regexec (&preg, response, 10, pmatch, eflags); 558 excode = regexec(&preg, response, 10, pmatch, eflags);
557 if (excode == 0) { 559 if (excode == 0) {
558 iresult = (invert_search==0) ? STATE_OK : STATE_CRITICAL; 560 iresult = (invert_search == 0) ? STATE_OK : STATE_CRITICAL;
559 } 561 } else if (excode != REG_NOMATCH) {
560 else if (excode != REG_NOMATCH) { 562 regerror(excode, &preg, errbuf, MAX_INPUT_BUFFER);
561 regerror (excode, &preg, errbuf, MAX_INPUT_BUFFER); 563 printf(_("Execute Error: %s\n"), errbuf);
562 printf (_("Execute Error: %s\n"), errbuf); 564 exit(STATE_CRITICAL);
563 exit (STATE_CRITICAL); 565 } else {
564 } 566 iresult = (invert_search == 0) ? STATE_CRITICAL : STATE_OK;
565 else {
566 iresult = (invert_search==0) ? STATE_CRITICAL : STATE_OK;
567 } 567 }
568 } 568 }
569 569
@@ -579,294 +579,283 @@ main (int argc, char **argv)
579 } 579 }
580 580
581 /* Result is the worst outcome of all the OIDs tested */ 581 /* Result is the worst outcome of all the OIDs tested */
582 result = max_state (result, iresult); 582 result = max_state(result, iresult);
583 583
584 /* Prepend a label for this OID if there is one */ 584 /* Prepend a label for this OID if there is one */
585 if (nlabels >= (size_t)1 && (size_t)i < nlabels && labels[i] != NULL) 585 if (nlabels >= (size_t)1 && (size_t)i < nlabels && labels[i] != NULL)
586 xasprintf (&outbuff, "%s%s%s %s%s%s", outbuff, 586 xasprintf(&outbuff, "%s%s%s %s%s%s", outbuff, (i == 0) ? " " : output_delim, labels[i], mark(iresult), show, mark(iresult));
587 (i == 0) ? " " : output_delim,
588 labels[i], mark (iresult), show, mark (iresult));
589 else 587 else
590 xasprintf (&outbuff, "%s%s%s%s%s", outbuff, (i == 0) ? " " : output_delim, 588 xasprintf(&outbuff, "%s%s%s%s%s", outbuff, (i == 0) ? " " : output_delim, mark(iresult), show, mark(iresult));
591 mark (iresult), show, mark (iresult));
592 589
593 /* Append a unit string for this OID if there is one */ 590 /* Append a unit string for this OID if there is one */
594 if (nunits > (size_t)0 && (size_t)i < nunits && unitv[i] != NULL) 591 if (nunits > (size_t)0 && (size_t)i < nunits && unitv[i] != NULL)
595 xasprintf (&outbuff, "%s %s", outbuff, unitv[i]); 592 xasprintf(&outbuff, "%s %s", outbuff, unitv[i]);
596 593
597 /* Write perfdata with whatever can be parsed by strtod, if possible */ 594 /* Write perfdata with whatever can be parsed by strtod, if possible */
598 ptr = NULL; 595 ptr = NULL;
599 strtod(show, &ptr); 596 strtod(show, &ptr);
600 if (ptr > show) { 597 if (ptr > show) {
601 if (perf_labels && nlabels >= (size_t)1 && (size_t)i < nlabels && labels[i] != NULL) 598 if (perf_labels && nlabels >= (size_t)1 && (size_t)i < nlabels && labels[i] != NULL)
602 temp_string=labels[i]; 599 temp_string = labels[i];
603 else 600 else
604 temp_string=oidname; 601 temp_string = oidname;
605 if (strpbrk (temp_string, " ='\"") == NULL) { 602 if (strpbrk(temp_string, " ='\"") == NULL) {
606 strncat(perfstr, temp_string, sizeof(perfstr)-strlen(perfstr)-1); 603 strncat(perfstr, temp_string, sizeof(perfstr) - strlen(perfstr) - 1);
607 } else { 604 } else {
608 if (strpbrk (temp_string, "'") == NULL) { 605 if (strpbrk(temp_string, "'") == NULL) {
609 quote_string="'"; 606 quote_string = "'";
610 } else { 607 } else {
611 quote_string="\""; 608 quote_string = "\"";
612 } 609 }
613 strncat(perfstr, quote_string, sizeof(perfstr)-strlen(perfstr)-1); 610 strncat(perfstr, quote_string, sizeof(perfstr) - strlen(perfstr) - 1);
614 strncat(perfstr, temp_string, sizeof(perfstr)-strlen(perfstr)-1); 611 strncat(perfstr, temp_string, sizeof(perfstr) - strlen(perfstr) - 1);
615 strncat(perfstr, quote_string, sizeof(perfstr)-strlen(perfstr)-1); 612 strncat(perfstr, quote_string, sizeof(perfstr) - strlen(perfstr) - 1);
616 } 613 }
617 strncat(perfstr, "=", sizeof(perfstr)-strlen(perfstr)-1); 614 strncat(perfstr, "=", sizeof(perfstr) - strlen(perfstr) - 1);
618 len = sizeof(perfstr)-strlen(perfstr)-1; 615 len = sizeof(perfstr) - strlen(perfstr) - 1;
619 strncat(perfstr, show, len>ptr-show ? ptr-show : len); 616 strncat(perfstr, show, len > ptr - show ? ptr - show : len);
620 617
621 if (strcmp(type, "") != 0) { 618 if (strcmp(type, "") != 0) {
622 strncat(perfstr, type, sizeof(perfstr)-strlen(perfstr)-1); 619 strncat(perfstr, type, sizeof(perfstr) - strlen(perfstr) - 1);
623 } 620 }
624 621
625 if (warning_thresholds) { 622 if (warning_thresholds) {
626 strncat(perfstr, ";", sizeof(perfstr)-strlen(perfstr)-1); 623 strncat(perfstr, ";", sizeof(perfstr) - strlen(perfstr) - 1);
627 if(thlds[i]->warning && thlds[i]->warning->text) 624 if (thlds[i]->warning && thlds[i]->warning->text)
628 strncat(perfstr, thlds[i]->warning->text, sizeof(perfstr)-strlen(perfstr)-1); 625 strncat(perfstr, thlds[i]->warning->text, sizeof(perfstr) - strlen(perfstr) - 1);
629 } 626 }
630 627
631 if (critical_thresholds) { 628 if (critical_thresholds) {
632 if (!warning_thresholds) 629 if (!warning_thresholds)
633 strncat(perfstr, ";", sizeof(perfstr)-strlen(perfstr)-1); 630 strncat(perfstr, ";", sizeof(perfstr) - strlen(perfstr) - 1);
634 strncat(perfstr, ";", sizeof(perfstr)-strlen(perfstr)-1); 631 strncat(perfstr, ";", sizeof(perfstr) - strlen(perfstr) - 1);
635 if(thlds[i]->critical && thlds[i]->critical->text) 632 if (thlds[i]->critical && thlds[i]->critical->text)
636 strncat(perfstr, thlds[i]->critical->text, sizeof(perfstr)-strlen(perfstr)-1); 633 strncat(perfstr, thlds[i]->critical->text, sizeof(perfstr) - strlen(perfstr) - 1);
637 } 634 }
638 635
639 strncat(perfstr, " ", sizeof(perfstr)-strlen(perfstr)-1); 636 strncat(perfstr, " ", sizeof(perfstr) - strlen(perfstr) - 1);
640 } 637 }
641 } 638 }
642 639
643 /* Save state data, as all data collected now */ 640 /* Save state data, as all data collected now */
644 if(calculate_rate) { 641 if (calculate_rate) {
645 string_length=1024; 642 string_length = 1024;
646 state_string=malloc(string_length); 643 state_string = malloc(string_length);
647 if(state_string==NULL) 644 if (state_string == NULL)
648 die(STATE_UNKNOWN, _("Cannot malloc")); 645 die(STATE_UNKNOWN, _("Cannot malloc"));
649 646
650 current_length=0; 647 current_length = 0;
651 for(int i = 0; i < total_oids; i++) { 648 for (int i = 0; i < total_oids; i++) {
652 xasprintf(&temp_string,"%.0f",response_value[i]); 649 xasprintf(&temp_string, "%.0f", response_value[i]);
653 if(temp_string==NULL) 650 if (temp_string == NULL)
654 die(STATE_UNKNOWN,_("Cannot asprintf()")); 651 die(STATE_UNKNOWN, _("Cannot asprintf()"));
655 response_length = strlen(temp_string); 652 response_length = strlen(temp_string);
656 if(current_length+response_length>string_length) { 653 if (current_length + response_length > string_length) {
657 string_length=current_length+1024; 654 string_length = current_length + 1024;
658 state_string=realloc(state_string,string_length); 655 state_string = realloc(state_string, string_length);
659 if(state_string==NULL) 656 if (state_string == NULL)
660 die(STATE_UNKNOWN, _("Cannot realloc()")); 657 die(STATE_UNKNOWN, _("Cannot realloc()"));
661 } 658 }
662 strcpy(&state_string[current_length],temp_string); 659 strcpy(&state_string[current_length], temp_string);
663 current_length=current_length+response_length; 660 current_length = current_length + response_length;
664 state_string[current_length]=':'; 661 state_string[current_length] = ':';
665 current_length++; 662 current_length++;
666 free(temp_string); 663 free(temp_string);
667 } 664 }
668 state_string[--current_length]='\0'; 665 state_string[--current_length] = '\0';
669 if (verbose > 2) 666 if (verbose > 2)
670 printf("State string=%s\n",state_string); 667 printf("State string=%s\n", state_string);
671 668
672 /* This is not strictly the same as time now, but any subtle variations will cancel out */ 669 /* This is not strictly the same as time now, but any subtle variations will cancel out */
673 np_state_write_string(current_time, state_string ); 670 np_state_write_string(current_time, state_string);
674 if(previous_state==NULL) { 671 if (previous_state == NULL) {
675 /* Or should this be highest state? */ 672 /* Or should this be highest state? */
676 die( STATE_OK, _("No previous data to calculate rate - assume okay" ) ); 673 die(STATE_OK, _("No previous data to calculate rate - assume okay"));
677 } 674 }
678 } 675 }
679 676
680 printf ("%s %s -%s %s\n", label, state_text (result), outbuff, perfstr); 677 printf("%s %s -%s %s\n", label, state_text(result), outbuff, perfstr);
681 if (mult_resp) printf ("%s", mult_resp); 678 if (mult_resp)
679 printf("%s", mult_resp);
682 680
683 return result; 681 return result;
684} 682}
685 683
686
687
688/* process command-line arguments */ 684/* process command-line arguments */
689int 685int process_arguments(int argc, char **argv) {
690process_arguments (int argc, char **argv) 686 static struct option longopts[] = {STD_LONG_OPTS,
691{ 687 {"community", required_argument, 0, 'C'},
692 char *ptr; 688 {"oid", required_argument, 0, 'o'},
693 int c = 1; 689 {"object", required_argument, 0, 'o'},
694 size_t j = 0, jj = 0; 690 {"delimiter", required_argument, 0, 'd'},
695 691 {"nulloid", required_argument, 0, 'z'},
696 int option = 0; 692 {"output-delimiter", required_argument, 0, 'D'},
697 static struct option longopts[] = { 693 {"string", required_argument, 0, 's'},
698 STD_LONG_OPTS, 694 {"timeout", required_argument, 0, 't'},
699 {"community", required_argument, 0, 'C'}, 695 {"regex", required_argument, 0, 'r'},
700 {"oid", required_argument, 0, 'o'}, 696 {"ereg", required_argument, 0, 'r'},
701 {"object", required_argument, 0, 'o'}, 697 {"eregi", required_argument, 0, 'R'},
702 {"delimiter", required_argument, 0, 'd'}, 698 {"label", required_argument, 0, 'l'},
703 {"nulloid", required_argument, 0, 'z'}, 699 {"units", required_argument, 0, 'u'},
704 {"output-delimiter", required_argument, 0, 'D'}, 700 {"port", required_argument, 0, 'p'},
705 {"string", required_argument, 0, 's'}, 701 {"retries", required_argument, 0, 'e'},
706 {"timeout", required_argument, 0, 't'}, 702 {"miblist", required_argument, 0, 'm'},
707 {"regex", required_argument, 0, 'r'}, 703 {"protocol", required_argument, 0, 'P'},
708 {"ereg", required_argument, 0, 'r'}, 704 {"context", required_argument, 0, 'N'},
709 {"eregi", required_argument, 0, 'R'}, 705 {"seclevel", required_argument, 0, 'L'},
710 {"label", required_argument, 0, 'l'}, 706 {"secname", required_argument, 0, 'U'},
711 {"units", required_argument, 0, 'u'}, 707 {"authproto", required_argument, 0, 'a'},
712 {"port", required_argument, 0, 'p'}, 708 {"privproto", required_argument, 0, 'x'},
713 {"retries", required_argument, 0, 'e'}, 709 {"authpasswd", required_argument, 0, 'A'},
714 {"miblist", required_argument, 0, 'm'}, 710 {"privpasswd", required_argument, 0, 'X'},
715 {"protocol", required_argument, 0, 'P'}, 711 {"next", no_argument, 0, 'n'},
716 {"context", required_argument, 0, 'N'}, 712 {"rate", no_argument, 0, L_CALCULATE_RATE},
717 {"seclevel", required_argument, 0, 'L'}, 713 {"rate-multiplier", required_argument, 0, L_RATE_MULTIPLIER},
718 {"secname", required_argument, 0, 'U'}, 714 {"offset", required_argument, 0, L_OFFSET},
719 {"authproto", required_argument, 0, 'a'}, 715 {"invert-search", no_argument, 0, L_INVERT_SEARCH},
720 {"privproto", required_argument, 0, 'x'}, 716 {"perf-oids", no_argument, 0, 'O'},
721 {"authpasswd", required_argument, 0, 'A'}, 717 {"ipv4", no_argument, 0, '4'},
722 {"privpasswd", required_argument, 0, 'X'}, 718 {"ipv6", no_argument, 0, '6'},
723 {"next", no_argument, 0, 'n'}, 719 {"multiplier", required_argument, 0, 'M'},
724 {"rate", no_argument, 0, L_CALCULATE_RATE}, 720 {"fmtstr", required_argument, 0, 'f'},
725 {"rate-multiplier", required_argument, 0, L_RATE_MULTIPLIER}, 721 {"ignore-mib-parsing-errors", no_argument, false, L_IGNORE_MIB_PARSING_ERRORS},
726 {"offset", required_argument, 0, L_OFFSET}, 722 {0, 0, 0, 0}};
727 {"invert-search", no_argument, 0, L_INVERT_SEARCH},
728 {"perf-oids", no_argument, 0, 'O'},
729 {"ipv4", no_argument, 0, '4'},
730 {"ipv6", no_argument, 0, '6'},
731 {"multiplier", required_argument, 0, 'M'},
732 {"fmtstr", required_argument, 0, 'f'},
733 {"ignore-mib-parsing-errors", no_argument, false, L_IGNORE_MIB_PARSING_ERRORS},
734 {0, 0, 0, 0}
735 };
736 723
737 if (argc < 2) 724 if (argc < 2)
738 return ERROR; 725 return ERROR;
739 726
740 /* reverse compatibility for very old non-POSIX usage forms */ 727 /* reverse compatibility for very old non-POSIX usage forms */
741 for (c = 1; c < argc; c++) { 728 for (int c = 1; c < argc; c++) {
742 if (strcmp ("-to", argv[c]) == 0) 729 if (strcmp("-to", argv[c]) == 0)
743 strcpy (argv[c], "-t"); 730 strcpy(argv[c], "-t");
744 if (strcmp ("-wv", argv[c]) == 0) 731 if (strcmp("-wv", argv[c]) == 0)
745 strcpy (argv[c], "-w"); 732 strcpy(argv[c], "-w");
746 if (strcmp ("-cv", argv[c]) == 0) 733 if (strcmp("-cv", argv[c]) == 0)
747 strcpy (argv[c], "-c"); 734 strcpy(argv[c], "-c");
748 } 735 }
749 736
750 while (1) { 737 size_t j = 0;
751 c = getopt_long (argc, argv, "nhvVO46t:c:w:H:C:o:e:E:d:D:s:t:R:r:l:u:p:m:P:N:L:U:a:x:A:X:M:f:z:", 738 size_t jj = 0;
752 longopts, &option); 739 while (true) {
740 int option = 0;
741 int option_char = getopt_long(argc, argv, "nhvVO46t:c:w:H:C:o:e:E:d:D:s:t:R:r:l:u:p:m:P:N:L:U:a:x:A:X:M:f:z:", longopts, &option);
753 742
754 if (c == -1 || c == EOF) 743 if (option_char == -1 || option_char == EOF)
755 break; 744 break;
756 745
757 switch (c) { 746 switch (option_char) {
758 case '?': /* usage */ 747 case '?': /* usage */
759 usage5 (); 748 usage5();
760 case 'h': /* help */ 749 case 'h': /* help */
761 print_help (); 750 print_help();
762 exit (STATE_UNKNOWN); 751 exit(STATE_UNKNOWN);
763 case 'V': /* version */ 752 case 'V': /* version */
764 print_revision (progname, NP_VERSION); 753 print_revision(progname, NP_VERSION);
765 exit (STATE_UNKNOWN); 754 exit(STATE_UNKNOWN);
766 case 'v': /* verbose */ 755 case 'v': /* verbose */
767 verbose++; 756 verbose++;
768 break; 757 break;
769 758
770 /* Connection info */ 759 /* Connection info */
771 case 'C': /* group or community */ 760 case 'C': /* group or community */
772 community = optarg; 761 community = optarg;
773 break; 762 break;
774 case 'H': /* Host or server */ 763 case 'H': /* Host or server */
775 server_address = optarg; 764 server_address = optarg;
776 break; 765 break;
777 case 'p': /* TCP port number */ 766 case 'p': /* TCP port number */
778 port = optarg; 767 port = optarg;
779 break; 768 break;
780 case 'm': /* List of MIBS */ 769 case 'm': /* List of MIBS */
781 miblist = optarg; 770 miblist = optarg;
782 break; 771 break;
783 case 'n': /* usesnmpgetnext */ 772 case 'n': /* usesnmpgetnext */
784 usesnmpgetnext = true; 773 usesnmpgetnext = true;
785 break; 774 break;
786 case 'P': /* SNMP protocol version */ 775 case 'P': /* SNMP protocol version */
787 proto = optarg; 776 proto = optarg;
788 break; 777 break;
789 case 'N': /* SNMPv3 context */ 778 case 'N': /* SNMPv3 context */
790 context = optarg; 779 context = optarg;
791 break; 780 break;
792 case 'L': /* security level */ 781 case 'L': /* security level */
793 seclevel = optarg; 782 seclevel = optarg;
794 break; 783 break;
795 case 'U': /* security username */ 784 case 'U': /* security username */
796 secname = optarg; 785 secname = optarg;
797 break; 786 break;
798 case 'a': /* auth protocol */ 787 case 'a': /* auth protocol */
799 authproto = optarg; 788 authproto = optarg;
800 break; 789 break;
801 case 'x': /* priv protocol */ 790 case 'x': /* priv protocol */
802 privproto = optarg; 791 privproto = optarg;
803 break; 792 break;
804 case 'A': /* auth passwd */ 793 case 'A': /* auth passwd */
805 authpasswd = optarg; 794 authpasswd = optarg;
806 break; 795 break;
807 case 'X': /* priv passwd */ 796 case 'X': /* priv passwd */
808 privpasswd = optarg; 797 privpasswd = optarg;
809 break; 798 break;
810 case 't': /* timeout period */ 799 case 't': /* timeout period */
811 if (!is_integer (optarg)) 800 if (!is_integer(optarg))
812 usage2 (_("Timeout interval must be a positive integer"), optarg); 801 usage2(_("Timeout interval must be a positive integer"), optarg);
813 else 802 else
814 timeout_interval = atoi (optarg); 803 timeout_interval = atoi(optarg);
815 break; 804 break;
816 805
817 /* Test parameters */ 806 /* Test parameters */
818 case 'c': /* critical threshold */ 807 case 'c': /* critical threshold */
819 critical_thresholds = optarg; 808 critical_thresholds = optarg;
820 break; 809 break;
821 case 'w': /* warning threshold */ 810 case 'w': /* warning threshold */
822 warning_thresholds = optarg; 811 warning_thresholds = optarg;
823 break; 812 break;
824 case 'e': /* PRELIMINARY - may change */ 813 case 'e': /* PRELIMINARY - may change */
825 case 'E': /* PRELIMINARY - may change */ 814 case 'E': /* PRELIMINARY - may change */
826 if (!is_integer (optarg)) 815 if (!is_integer(optarg))
827 usage2 (_("Retries interval must be a positive integer"), optarg); 816 usage2(_("Retries interval must be a positive integer"), optarg);
828 else 817 else
829 retries = atoi(optarg); 818 retries = atoi(optarg);
830 break; 819 break;
831 case 'o': /* object identifier */ 820 case 'o': /* object identifier */
832 if ( strspn( optarg, "0123456789.," ) != strlen( optarg ) ) { 821 if (strspn(optarg, "0123456789.,") != strlen(optarg)) {
833 /* 822 /*
834 * we have something other than digits, periods and comas, 823 * we have something other than digits, periods and comas,
835 * so we have a mib variable, rather than just an SNMP OID, 824 * so we have a mib variable, rather than just an SNMP OID,
836 * so we have to actually read the mib files 825 * so we have to actually read the mib files
837 */ 826 */
838 needmibs = true; 827 needmibs = true;
839 } 828 }
840 for (ptr = strtok(optarg, ", "); ptr != NULL; ptr = strtok(NULL, ", "), j++) { 829 for (char *ptr = strtok(optarg, ", "); ptr != NULL; ptr = strtok(NULL, ", "), j++) {
841 while (j >= oids_size) { 830 while (j >= oids_size) {
842 oids_size += OID_COUNT_STEP; 831 oids_size += OID_COUNT_STEP;
843 oids = realloc(oids, oids_size * sizeof (*oids)); 832 oids = realloc(oids, oids_size * sizeof(*oids));
844 } 833 }
845 oids[j] = strdup(ptr); 834 oids[j] = strdup(ptr);
846 } 835 }
847 numoids = j; 836 numoids = j;
848 if (c == 'E' || c == 'e') { 837 if (option_char == 'E' || option_char == 'e') {
849 jj++; 838 jj++;
850 while (j+1 >= eval_size) { 839 while (j + 1 >= eval_size) {
851 eval_size += OID_COUNT_STEP; 840 eval_size += OID_COUNT_STEP;
852 eval_method = realloc(eval_method, eval_size * sizeof(*eval_method)); 841 eval_method = realloc(eval_method, eval_size * sizeof(*eval_method));
853 memset(eval_method + eval_size - OID_COUNT_STEP, 0, 8); 842 memset(eval_method + eval_size - OID_COUNT_STEP, 0, 8);
854 } 843 }
855 if (c == 'E') 844 if (option_char == 'E')
856 eval_method[j+1] |= WARN_PRESENT; 845 eval_method[j + 1] |= WARN_PRESENT;
857 else if (c == 'e') 846 else if (option_char == 'e')
858 eval_method[j+1] |= CRIT_PRESENT; 847 eval_method[j + 1] |= CRIT_PRESENT;
859 } 848 }
860 break; 849 break;
861 case 'z': /* Null OID Return Check */ 850 case 'z': /* Null OID Return Check */
862 if (!is_integer (optarg)) 851 if (!is_integer(optarg))
863 usage2 (_("Exit status must be a positive integer"), optarg); 852 usage2(_("Exit status must be a positive integer"), optarg);
864 else 853 else
865 nulloid = atoi(optarg); 854 nulloid = atoi(optarg);
866 break; 855 break;
867 case 's': /* string or substring */ 856 case 's': /* string or substring */
868 strncpy (string_value, optarg, sizeof (string_value) - 1); 857 strncpy(string_value, optarg, sizeof(string_value) - 1);
869 string_value[sizeof (string_value) - 1] = 0; 858 string_value[sizeof(string_value) - 1] = 0;
870 while (jj >= eval_size) { 859 while (jj >= eval_size) {
871 eval_size += OID_COUNT_STEP; 860 eval_size += OID_COUNT_STEP;
872 eval_method = realloc(eval_method, eval_size * sizeof(*eval_method)); 861 eval_method = realloc(eval_method, eval_size * sizeof(*eval_method));
@@ -874,17 +863,17 @@ process_arguments (int argc, char **argv)
874 } 863 }
875 eval_method[jj++] = CRIT_STRING; 864 eval_method[jj++] = CRIT_STRING;
876 break; 865 break;
877 case 'R': /* regex */ 866 case 'R': /* regex */
878 cflags = REG_ICASE; 867 cflags = REG_ICASE;
879 // fall through 868 // fall through
880 case 'r': /* regex */ 869 case 'r': /* regex */
881 cflags |= REG_EXTENDED | REG_NOSUB | REG_NEWLINE; 870 cflags |= REG_EXTENDED | REG_NOSUB | REG_NEWLINE;
882 strncpy (regex_expect, optarg, sizeof (regex_expect) - 1); 871 strncpy(regex_expect, optarg, sizeof(regex_expect) - 1);
883 regex_expect[sizeof (regex_expect) - 1] = 0; 872 regex_expect[sizeof(regex_expect) - 1] = 0;
884 errcode = regcomp (&preg, regex_expect, cflags); 873 errcode = regcomp(&preg, regex_expect, cflags);
885 if (errcode != 0) { 874 if (errcode != 0) {
886 regerror (errcode, &preg, errbuf, MAX_INPUT_BUFFER); 875 regerror(errcode, &preg, errbuf, MAX_INPUT_BUFFER);
887 printf (_("Could Not Compile Regular Expression")); 876 printf(_("Could Not Compile Regular Expression"));
888 return ERROR; 877 return ERROR;
889 } 878 }
890 while (jj >= eval_size) { 879 while (jj >= eval_size) {
@@ -895,64 +884,64 @@ process_arguments (int argc, char **argv)
895 eval_method[jj++] = CRIT_REGEX; 884 eval_method[jj++] = CRIT_REGEX;
896 break; 885 break;
897 886
898 /* Format */ 887 /* Format */
899 case 'd': /* delimiter */ 888 case 'd': /* delimiter */
900 delimiter = strscpy (delimiter, optarg); 889 delimiter = strscpy(delimiter, optarg);
901 break; 890 break;
902 case 'D': /* output-delimiter */ 891 case 'D': /* output-delimiter */
903 output_delim = strscpy (output_delim, optarg); 892 output_delim = strscpy(output_delim, optarg);
904 break; 893 break;
905 case 'l': /* label */ 894 case 'l': /* label */
906 nlabels++; 895 nlabels++;
907 if (nlabels > labels_size) { 896 if (nlabels > labels_size) {
908 labels_size += 8; 897 labels_size += 8;
909 labels = realloc (labels, labels_size * sizeof(*labels)); 898 labels = realloc(labels, labels_size * sizeof(*labels));
910 if (labels == NULL) 899 if (labels == NULL)
911 die (STATE_UNKNOWN, _("Could not reallocate labels[%d]"), (int)nlabels); 900 die(STATE_UNKNOWN, _("Could not reallocate labels[%d]"), (int)nlabels);
912 } 901 }
913 labels[nlabels - 1] = optarg; 902 labels[nlabels - 1] = optarg;
914 ptr = thisarg (optarg); 903 char *ptr = thisarg(optarg);
915 labels[nlabels - 1] = ptr; 904 labels[nlabels - 1] = ptr;
916 if (ptr[0] == '\'') 905 if (ptr[0] == '\'')
917 labels[nlabels - 1] = ptr + 1; 906 labels[nlabels - 1] = ptr + 1;
918 while (ptr && (ptr = nextarg (ptr))) { 907 while (ptr && (ptr = nextarg(ptr))) {
919 nlabels++; 908 nlabels++;
920 if (nlabels > labels_size) { 909 if (nlabels > labels_size) {
921 labels_size += 8; 910 labels_size += 8;
922 labels = realloc (labels, labels_size * sizeof(*labels)); 911 labels = realloc(labels, labels_size * sizeof(*labels));
923 if (labels == NULL) 912 if (labels == NULL)
924 die (STATE_UNKNOWN, _("Could not reallocate labels\n")); 913 die(STATE_UNKNOWN, _("Could not reallocate labels\n"));
925 } 914 }
926 ptr = thisarg (ptr); 915 ptr = thisarg(ptr);
927 if (ptr[0] == '\'') 916 if (ptr[0] == '\'')
928 labels[nlabels - 1] = ptr + 1; 917 labels[nlabels - 1] = ptr + 1;
929 else 918 else
930 labels[nlabels - 1] = ptr; 919 labels[nlabels - 1] = ptr;
931 } 920 }
932 break; 921 break;
933 case 'u': /* units */ 922 case 'u': /* units */
934 units = optarg; 923 units = optarg;
935 nunits++; 924 nunits++;
936 if (nunits > unitv_size) { 925 if (nunits > unitv_size) {
937 unitv_size += 8; 926 unitv_size += 8;
938 unitv = realloc (unitv, unitv_size * sizeof(*unitv)); 927 unitv = realloc(unitv, unitv_size * sizeof(*unitv));
939 if (unitv == NULL) 928 if (unitv == NULL)
940 die (STATE_UNKNOWN, _("Could not reallocate units [%d]\n"), (int)nunits); 929 die(STATE_UNKNOWN, _("Could not reallocate units [%d]\n"), (int)nunits);
941 } 930 }
942 unitv[nunits - 1] = optarg; 931 unitv[nunits - 1] = optarg;
943 ptr = thisarg (optarg); 932 ptr = thisarg(optarg);
944 unitv[nunits - 1] = ptr; 933 unitv[nunits - 1] = ptr;
945 if (ptr[0] == '\'') 934 if (ptr[0] == '\'')
946 unitv[nunits - 1] = ptr + 1; 935 unitv[nunits - 1] = ptr + 1;
947 while (ptr && (ptr = nextarg (ptr))) { 936 while (ptr && (ptr = nextarg(ptr))) {
948 if (nunits > unitv_size) { 937 if (nunits > unitv_size) {
949 unitv_size += 8; 938 unitv_size += 8;
950 unitv = realloc (unitv, unitv_size * sizeof(*unitv)); 939 unitv = realloc(unitv, unitv_size * sizeof(*unitv));
951 if (units == NULL) 940 if (units == NULL)
952 die (STATE_UNKNOWN, _("Could not realloc() units\n")); 941 die(STATE_UNKNOWN, _("Could not realloc() units\n"));
953 } 942 }
954 nunits++; 943 nunits++;
955 ptr = thisarg (ptr); 944 ptr = thisarg(ptr);
956 if (ptr[0] == '\'') 945 if (ptr[0] == '\'')
957 unitv[nunits - 1] = ptr + 1; 946 unitv[nunits - 1] = ptr + 1;
958 else 947 else
@@ -960,38 +949,38 @@ process_arguments (int argc, char **argv)
960 } 949 }
961 break; 950 break;
962 case L_CALCULATE_RATE: 951 case L_CALCULATE_RATE:
963 if(calculate_rate==0) 952 if (calculate_rate == 0)
964 np_enable_state(NULL, 1); 953 np_enable_state(NULL, 1);
965 calculate_rate = 1; 954 calculate_rate = 1;
966 break; 955 break;
967 case L_RATE_MULTIPLIER: 956 case L_RATE_MULTIPLIER:
968 if(!is_integer(optarg)||((rate_multiplier=atoi(optarg))<=0)) 957 if (!is_integer(optarg) || ((rate_multiplier = atoi(optarg)) <= 0))
969 usage2(_("Rate multiplier must be a positive integer"),optarg); 958 usage2(_("Rate multiplier must be a positive integer"), optarg);
970 break; 959 break;
971 case L_OFFSET: 960 case L_OFFSET:
972 offset=strtod(optarg,NULL); 961 offset = strtod(optarg, NULL);
973 break; 962 break;
974 case L_INVERT_SEARCH: 963 case L_INVERT_SEARCH:
975 invert_search=1; 964 invert_search = 1;
976 break; 965 break;
977 case 'O': 966 case 'O':
978 perf_labels=0; 967 perf_labels = 0;
979 break; 968 break;
980 case '4': 969 case '4':
981 break; 970 break;
982 case '6': 971 case '6':
983 xasprintf(&ip_version, "udp6:"); 972 xasprintf(&ip_version, "udp6:");
984 if(verbose>2) 973 if (verbose > 2)
985 printf("IPv6 detected! Will pass \"udp6:\" to snmpget.\n"); 974 printf("IPv6 detected! Will pass \"udp6:\" to snmpget.\n");
986 break; 975 break;
987 case 'M': 976 case 'M':
988 if ( strspn( optarg, "0123456789.," ) == strlen( optarg ) ) { 977 if (strspn(optarg, "0123456789.,") == strlen(optarg)) {
989 multiplier=strtod(optarg,NULL); 978 multiplier = strtod(optarg, NULL);
990 } 979 }
991 break; 980 break;
992 case 'f': 981 case 'f':
993 if (multiplier != 1.0) { 982 if (multiplier != 1.0) {
994 fmtstr=optarg; 983 fmtstr = optarg;
995 fmtstr_set = true; 984 fmtstr_set = true;
996 } 985 }
997 break; 986 break;
@@ -1004,12 +993,11 @@ process_arguments (int argc, char **argv)
1004 server_address = argv[optind]; 993 server_address = argv[optind];
1005 994
1006 if (community == NULL) 995 if (community == NULL)
1007 community = strdup (DEFAULT_COMMUNITY); 996 community = strdup(DEFAULT_COMMUNITY);
1008 997
1009 return validate_arguments (); 998 return validate_arguments();
1010} 999}
1011 1000
1012
1013/****************************************************************************** 1001/******************************************************************************
1014 1002
1015@@- 1003@@-
@@ -1028,17 +1016,13 @@ selected.</para>
1028-@@ 1016-@@
1029******************************************************************************/ 1017******************************************************************************/
1030 1018
1031 1019static int validate_arguments() {
1032
1033int
1034validate_arguments ()
1035{
1036 /* check whether to load locally installed MIBS (CPU/disk intensive) */ 1020 /* check whether to load locally installed MIBS (CPU/disk intensive) */
1037 if (miblist == NULL) { 1021 if (miblist == NULL) {
1038 if (needmibs) { 1022 if (needmibs) {
1039 miblist = strdup (DEFAULT_MIBLIST); 1023 miblist = strdup(DEFAULT_MIBLIST);
1040 }else{ 1024 } else {
1041 miblist = ""; /* don't read any mib files for numeric oids */ 1025 miblist = ""; /* don't read any mib files for numeric oids */
1042 } 1026 }
1043 } 1027 }
1044 1028
@@ -1053,18 +1037,17 @@ validate_arguments ()
1053 if (proto == NULL) 1037 if (proto == NULL)
1054 xasprintf(&proto, DEFAULT_PROTOCOL); 1038 xasprintf(&proto, DEFAULT_PROTOCOL);
1055 1039
1056 if ((strcmp(proto,"1") == 0) || (strcmp(proto, "2c")==0)) { /* snmpv1 or snmpv2c */ 1040 if ((strcmp(proto, "1") == 0) || (strcmp(proto, "2c") == 0)) { /* snmpv1 or snmpv2c */
1057 numauthpriv = 2; 1041 numauthpriv = 2;
1058 authpriv = calloc (numauthpriv, sizeof (char *)); 1042 authpriv = calloc(numauthpriv, sizeof(char *));
1059 authpriv[0] = strdup ("-c"); 1043 authpriv[0] = strdup("-c");
1060 authpriv[1] = strdup (community); 1044 authpriv[1] = strdup(community);
1061 } 1045 } else if (strcmp(proto, "3") == 0) { /* snmpv3 args */
1062 else if ( strcmp (proto, "3") == 0 ) { /* snmpv3 args */
1063 if (!(context == NULL)) { 1046 if (!(context == NULL)) {
1064 numcontext = 2; 1047 numcontext = 2;
1065 contextargs = calloc (numcontext, sizeof (char *)); 1048 contextargs = calloc(numcontext, sizeof(char *));
1066 contextargs[0] = strdup ("-n"); 1049 contextargs[0] = strdup("-n");
1067 contextargs[1] = strdup (context); 1050 contextargs[1] = strdup(context);
1068 } 1051 }
1069 1052
1070 if (seclevel == NULL) 1053 if (seclevel == NULL)
@@ -1075,284 +1058,266 @@ validate_arguments ()
1075 1058
1076 if (strcmp(seclevel, "noAuthNoPriv") == 0) { 1059 if (strcmp(seclevel, "noAuthNoPriv") == 0) {
1077 numauthpriv = 4; 1060 numauthpriv = 4;
1078 authpriv = calloc (numauthpriv, sizeof (char *)); 1061 authpriv = calloc(numauthpriv, sizeof(char *));
1079 authpriv[0] = strdup ("-l"); 1062 authpriv[0] = strdup("-l");
1080 authpriv[1] = strdup ("noAuthNoPriv"); 1063 authpriv[1] = strdup("noAuthNoPriv");
1081 authpriv[2] = strdup ("-u"); 1064 authpriv[2] = strdup("-u");
1082 authpriv[3] = strdup (secname); 1065 authpriv[3] = strdup(secname);
1083 } else { 1066 } else {
1084 if (! ( (strcmp(seclevel, "authNoPriv")==0) || (strcmp(seclevel, "authPriv")==0) ) ) { 1067 if (!((strcmp(seclevel, "authNoPriv") == 0) || (strcmp(seclevel, "authPriv") == 0))) {
1085 usage2 (_("Invalid seclevel"), seclevel); 1068 usage2(_("Invalid seclevel"), seclevel);
1086 } 1069 }
1087 1070
1088 if (authproto == NULL ) 1071 if (authproto == NULL)
1089 xasprintf(&authproto, DEFAULT_AUTH_PROTOCOL); 1072 xasprintf(&authproto, DEFAULT_AUTH_PROTOCOL);
1090 1073
1091 if (authpasswd == NULL) 1074 if (authpasswd == NULL)
1092 die(STATE_UNKNOWN, _("Required parameter: %s\n"), "authpasswd"); 1075 die(STATE_UNKNOWN, _("Required parameter: %s\n"), "authpasswd");
1093 1076
1094 if ( strcmp(seclevel, "authNoPriv") == 0 ) { 1077 if (strcmp(seclevel, "authNoPriv") == 0) {
1095 numauthpriv = 8; 1078 numauthpriv = 8;
1096 authpriv = calloc (numauthpriv, sizeof (char *)); 1079 authpriv = calloc(numauthpriv, sizeof(char *));
1097 authpriv[0] = strdup ("-l"); 1080 authpriv[0] = strdup("-l");
1098 authpriv[1] = strdup ("authNoPriv"); 1081 authpriv[1] = strdup("authNoPriv");
1099 authpriv[2] = strdup ("-a"); 1082 authpriv[2] = strdup("-a");
1100 authpriv[3] = strdup (authproto); 1083 authpriv[3] = strdup(authproto);
1101 authpriv[4] = strdup ("-u"); 1084 authpriv[4] = strdup("-u");
1102 authpriv[5] = strdup (secname); 1085 authpriv[5] = strdup(secname);
1103 authpriv[6] = strdup ("-A"); 1086 authpriv[6] = strdup("-A");
1104 authpriv[7] = strdup (authpasswd); 1087 authpriv[7] = strdup(authpasswd);
1105 } else if ( strcmp(seclevel, "authPriv") == 0 ) { 1088 } else if (strcmp(seclevel, "authPriv") == 0) {
1106 if (privproto == NULL ) 1089 if (privproto == NULL)
1107 xasprintf(&privproto, DEFAULT_PRIV_PROTOCOL); 1090 xasprintf(&privproto, DEFAULT_PRIV_PROTOCOL);
1108 1091
1109 if (privpasswd == NULL) 1092 if (privpasswd == NULL)
1110 die(STATE_UNKNOWN, _("Required parameter: %s\n"), "privpasswd"); 1093 die(STATE_UNKNOWN, _("Required parameter: %s\n"), "privpasswd");
1111 1094
1112 numauthpriv = 12; 1095 numauthpriv = 12;
1113 authpriv = calloc (numauthpriv, sizeof (char *)); 1096 authpriv = calloc(numauthpriv, sizeof(char *));
1114 authpriv[0] = strdup ("-l"); 1097 authpriv[0] = strdup("-l");
1115 authpriv[1] = strdup ("authPriv"); 1098 authpriv[1] = strdup("authPriv");
1116 authpriv[2] = strdup ("-a"); 1099 authpriv[2] = strdup("-a");
1117 authpriv[3] = strdup (authproto); 1100 authpriv[3] = strdup(authproto);
1118 authpriv[4] = strdup ("-u"); 1101 authpriv[4] = strdup("-u");
1119 authpriv[5] = strdup (secname); 1102 authpriv[5] = strdup(secname);
1120 authpriv[6] = strdup ("-A"); 1103 authpriv[6] = strdup("-A");
1121 authpriv[7] = strdup (authpasswd); 1104 authpriv[7] = strdup(authpasswd);
1122 authpriv[8] = strdup ("-x"); 1105 authpriv[8] = strdup("-x");
1123 authpriv[9] = strdup (privproto); 1106 authpriv[9] = strdup(privproto);
1124 authpriv[10] = strdup ("-X"); 1107 authpriv[10] = strdup("-X");
1125 authpriv[11] = strdup (privpasswd); 1108 authpriv[11] = strdup(privpasswd);
1126 } 1109 }
1127 } 1110 }
1128 1111
1129 } 1112 } else {
1130 else { 1113 usage2(_("Invalid SNMP version"), proto);
1131 usage2 (_("Invalid SNMP version"), proto);
1132 } 1114 }
1133 1115
1134 return OK; 1116 return OK;
1135} 1117}
1136 1118
1137
1138
1139/* trim leading whitespace 1119/* trim leading whitespace
1140 if there is a leading quote, make sure it balances */ 1120 if there is a leading quote, make sure it balances */
1141 1121
1142char * 1122static char *thisarg(char *str) {
1143thisarg (char *str) 1123 str += strspn(str, " \t\r\n"); /* trim any leading whitespace */
1144{ 1124 if (str[0] == '\'') { /* handle SIMPLE quoted strings */
1145 str += strspn (str, " \t\r\n"); /* trim any leading whitespace */ 1125 if (strlen(str) == 1 || !strstr(str + 1, "'"))
1146 if (str[0] == '\'') { /* handle SIMPLE quoted strings */ 1126 die(STATE_UNKNOWN, _("Unbalanced quotes\n"));
1147 if (strlen (str) == 1 || !strstr (str + 1, "'"))
1148 die (STATE_UNKNOWN, _("Unbalanced quotes\n"));
1149 } 1127 }
1150 return str; 1128 return str;
1151} 1129}
1152 1130
1153
1154
1155/* if there's a leading quote, advance to the trailing quote 1131/* if there's a leading quote, advance to the trailing quote
1156 set the trailing quote to '\x0' 1132 set the trailing quote to '\x0'
1157 if the string continues, advance beyond the comma */ 1133 if the string continues, advance beyond the comma */
1158 1134
1159char * 1135static char *nextarg(char *str) {
1160nextarg (char *str)
1161{
1162 if (str[0] == '\'') { 1136 if (str[0] == '\'') {
1163 str[0] = 0; 1137 str[0] = 0;
1164 if (strlen (str) > 1) { 1138 if (strlen(str) > 1) {
1165 str = strstr (str + 1, "'"); 1139 str = strstr(str + 1, "'");
1166 return (++str); 1140 return (++str);
1167 } 1141 } else {
1168 else {
1169 return NULL; 1142 return NULL;
1170 } 1143 }
1171 } 1144 }
1172 if (str[0] == ',') { 1145 if (str[0] == ',') {
1173 str[0] = 0; 1146 str[0] = 0;
1174 if (strlen (str) > 1) { 1147 if (strlen(str) > 1) {
1175 return (++str); 1148 return (++str);
1176 } 1149 } else {
1177 else {
1178 return NULL; 1150 return NULL;
1179 } 1151 }
1180 } 1152 }
1181 if ((str = strstr (str, ",")) && strlen (str) > 1) { 1153 if ((str = strstr(str, ",")) && strlen(str) > 1) {
1182 str[0] = 0; 1154 str[0] = 0;
1183 return (++str); 1155 return (++str);
1184 } 1156 }
1185 return NULL; 1157 return NULL;
1186} 1158}
1187 1159
1188
1189
1190/* multiply result (values 0 < n < 1 work as divider) */ 1160/* multiply result (values 0 < n < 1 work as divider) */
1191char * 1161static char *multiply(char *str) {
1192multiply (char *str) 1162 if (multiplier == 1)
1193{ 1163 return (str);
1194 char *endptr;
1195 double val;
1196 char *conv = "%f";
1197
1198 if(multiplier == 1)
1199 return(str);
1200 1164
1201 if(verbose>2) 1165 if (verbose > 2)
1202 printf(" multiply input: %s\n", str); 1166 printf(" multiply input: %s\n", str);
1203 1167
1204 val = strtod (str, &endptr); 1168 char *endptr;
1169 double val = strtod(str, &endptr);
1205 if ((val == 0.0) && (endptr == str)) { 1170 if ((val == 0.0) && (endptr == str)) {
1206 die(STATE_UNKNOWN, _("multiplier set (%.1f), but input is not a number: %s"), multiplier, str); 1171 die(STATE_UNKNOWN, _("multiplier set (%.1f), but input is not a number: %s"), multiplier, str);
1207 } 1172 }
1208 1173
1209 if(verbose>2) 1174 if (verbose > 2)
1210 printf(" multiply extracted double: %f\n", val); 1175 printf(" multiply extracted double: %f\n", val);
1176
1211 val *= multiplier; 1177 val *= multiplier;
1178 char *conv = "%f";
1212 if (fmtstr_set) { 1179 if (fmtstr_set) {
1213 conv = fmtstr; 1180 conv = fmtstr;
1214 } 1181 }
1215 if (val == (int)val) { 1182 if (val == (int)val) {
1216 snprintf(buffer, DEFAULT_BUFFER_SIZE, "%.0f", val); 1183 snprintf(buffer, DEFAULT_BUFFER_SIZE, "%.0f", val);
1217 } else { 1184 } else {
1218 if(verbose>2) 1185 if (verbose > 2)
1219 printf(" multiply using format: %s\n", conv); 1186 printf(" multiply using format: %s\n", conv);
1220 snprintf(buffer, DEFAULT_BUFFER_SIZE, conv, val); 1187 snprintf(buffer, DEFAULT_BUFFER_SIZE, conv, val);
1221 } 1188 }
1222 if(verbose>2) 1189 if (verbose > 2)
1223 printf(" multiply result: %s\n", buffer); 1190 printf(" multiply result: %s\n", buffer);
1224 return buffer; 1191 return buffer;
1225} 1192}
1226 1193
1194static void print_help(void) {
1195 print_revision(progname, NP_VERSION);
1227 1196
1228void 1197 printf(COPYRIGHT, copyright, email);
1229print_help (void)
1230{
1231 print_revision (progname, NP_VERSION);
1232
1233 printf (COPYRIGHT, copyright, email);
1234 1198
1235 printf ("%s\n", _("Check status of remote machines and obtain system information via SNMP")); 1199 printf("%s\n", _("Check status of remote machines and obtain system information via SNMP"));
1236 1200
1237 printf ("\n\n"); 1201 printf("\n\n");
1238 1202
1239 print_usage (); 1203 print_usage();
1240 1204
1241 printf (UT_HELP_VRSN); 1205 printf(UT_HELP_VRSN);
1242 printf (UT_EXTRA_OPTS); 1206 printf(UT_EXTRA_OPTS);
1243 printf (UT_IPv46); 1207 printf(UT_IPv46);
1244 1208
1245 printf (UT_HOST_PORT, 'p', DEFAULT_PORT); 1209 printf(UT_HOST_PORT, 'p', DEFAULT_PORT);
1246 1210
1247 /* SNMP and Authentication Protocol */ 1211 /* SNMP and Authentication Protocol */
1248 printf (" %s\n", "-n, --next"); 1212 printf(" %s\n", "-n, --next");
1249 printf (" %s\n", _("Use SNMP GETNEXT instead of SNMP GET")); 1213 printf(" %s\n", _("Use SNMP GETNEXT instead of SNMP GET"));
1250 printf (" %s\n", "-P, --protocol=[1|2c|3]"); 1214 printf(" %s\n", "-P, --protocol=[1|2c|3]");
1251 printf (" %s\n", _("SNMP protocol version")); 1215 printf(" %s\n", _("SNMP protocol version"));
1252 printf (" %s\n", "-N, --context=CONTEXT"); 1216 printf(" %s\n", "-N, --context=CONTEXT");
1253 printf (" %s\n", _("SNMPv3 context")); 1217 printf(" %s\n", _("SNMPv3 context"));
1254 printf (" %s\n", "-L, --seclevel=[noAuthNoPriv|authNoPriv|authPriv]"); 1218 printf(" %s\n", "-L, --seclevel=[noAuthNoPriv|authNoPriv|authPriv]");
1255 printf (" %s\n", _("SNMPv3 securityLevel")); 1219 printf(" %s\n", _("SNMPv3 securityLevel"));
1256 printf (" %s\n", "-a, --authproto=AUTHENTICATION_PROTOCOL"); 1220 printf(" %s\n", "-a, --authproto=AUTHENTICATION_PROTOCOL");
1257 printf (" %s\n", _("SNMPv3 authentication protocol (default MD5), available options depend on the specific version of the net-snmp tools")); 1221 printf(" %s\n",
1258 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"));
1259 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"));
1260 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");
1261 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"));
1262 1227
1263 /* Authentication Tokens*/ 1228 /* Authentication Tokens*/
1264 printf (" %s\n", "-C, --community=STRING"); 1229 printf(" %s\n", "-C, --community=STRING");
1265 printf (" %s ", _("Optional community string for SNMP communication")); 1230 printf(" %s ", _("Optional community string for SNMP communication"));
1266 printf ("(%s \"%s\")\n", _("default is") ,DEFAULT_COMMUNITY); 1231 printf("(%s \"%s\")\n", _("default is"), DEFAULT_COMMUNITY);
1267 printf (" %s\n", "-U, --secname=USERNAME"); 1232 printf(" %s\n", "-U, --secname=USERNAME");
1268 printf (" %s\n", _("SNMPv3 username")); 1233 printf(" %s\n", _("SNMPv3 username"));
1269 printf (" %s\n", "-A, --authpasswd=PASSWORD"); 1234 printf(" %s\n", "-A, --authpasswd=PASSWORD");
1270 printf (" %s\n", _("SNMPv3 authentication password")); 1235 printf(" %s\n", _("SNMPv3 authentication password"));
1271 printf (" %s\n", "-X, --privpasswd=PASSWORD"); 1236 printf(" %s\n", "-X, --privpasswd=PASSWORD");
1272 printf (" %s\n", _("SNMPv3 privacy password")); 1237 printf(" %s\n", _("SNMPv3 privacy password"));
1273 1238
1274 /* OID Stuff */ 1239 /* OID Stuff */
1275 printf (" %s\n", "-o, --oid=OID(s)"); 1240 printf(" %s\n", "-o, --oid=OID(s)");
1276 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"));
1277 printf (" %s\n", "-m, --miblist=STRING"); 1242 printf(" %s\n", "-m, --miblist=STRING");
1278 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'"));
1279 printf (" %s\n", _("for symbolic OIDs.)")); 1244 printf(" %s\n", _("for symbolic OIDs.)"));
1280 printf (" %s\n", "-d, --delimiter=STRING"); 1245 printf(" %s\n", "-d, --delimiter=STRING");
1281 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);
1282 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"));
1283 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."));
1284 printf (" %s\n", "-z, --nulloid=#"); 1249 printf(" %s\n", "-z, --nulloid=#");
1285 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"));
1286 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"));
1287 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)"));
1288 printf (" %s\n", _("0 = OK")); 1253 printf(" %s\n", _("0 = OK"));
1289 printf (" %s\n", _("1 = WARNING")); 1254 printf(" %s\n", _("1 = WARNING"));
1290 printf (" %s\n", _("2 = CRITICAL")); 1255 printf(" %s\n", _("2 = CRITICAL"));
1291 printf (" %s\n", _("3 = UNKNOWN")); 1256 printf(" %s\n", _("3 = UNKNOWN"));
1292 1257
1293 /* Tests Against Integers */ 1258 /* Tests Against Integers */
1294 printf (" %s\n", "-w, --warning=THRESHOLD(s)"); 1259 printf(" %s\n", "-w, --warning=THRESHOLD(s)");
1295 printf (" %s\n", _("Warning threshold range(s)")); 1260 printf(" %s\n", _("Warning threshold range(s)"));
1296 printf (" %s\n", "-c, --critical=THRESHOLD(s)"); 1261 printf(" %s\n", "-c, --critical=THRESHOLD(s)");
1297 printf (" %s\n", _("Critical threshold range(s)")); 1262 printf(" %s\n", _("Critical threshold range(s)"));
1298 printf (" %s\n", "--rate"); 1263 printf(" %s\n", "--rate");
1299 printf (" %s\n", _("Enable rate calculation. See 'Rate Calculation' below")); 1264 printf(" %s\n", _("Enable rate calculation. See 'Rate Calculation' below"));
1300 printf (" %s\n", "--rate-multiplier"); 1265 printf(" %s\n", "--rate-multiplier");
1301 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"));
1302 printf (" %s\n", "--offset=OFFSET"); 1267 printf(" %s\n", "--offset=OFFSET");
1303 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"));
1304 1269
1305 /* Tests Against Strings */ 1270 /* Tests Against Strings */
1306 printf (" %s\n", "-s, --string=STRING"); 1271 printf(" %s\n", "-s, --string=STRING");
1307 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"));
1308 printf (" %s\n", "-r, --ereg=REGEX"); 1273 printf(" %s\n", "-r, --ereg=REGEX");
1309 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"));
1310 printf (" %s\n", "-R, --eregi=REGEX"); 1275 printf(" %s\n", "-R, --eregi=REGEX");
1311 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"));
1312 printf (" %s\n", "--invert-search"); 1277 printf(" %s\n", "--invert-search");
1313 printf (" %s\n", _("Invert search result (CRITICAL if found)")); 1278 printf(" %s\n", _("Invert search result (CRITICAL if found)"));
1314 1279
1315 /* Output Formatting */ 1280 /* Output Formatting */
1316 printf (" %s\n", "-l, --label=STRING"); 1281 printf(" %s\n", "-l, --label=STRING");
1317 printf (" %s\n", _("Prefix label for output from plugin")); 1282 printf(" %s\n", _("Prefix label for output from plugin"));
1318 printf (" %s\n", "-u, --units=STRING"); 1283 printf(" %s\n", "-u, --units=STRING");
1319 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.')."));
1320 printf (" %s\n", "-D, --output-delimiter=STRING"); 1285 printf(" %s\n", "-D, --output-delimiter=STRING");
1321 printf (" %s\n", _("Separates output on multiple OID requests")); 1286 printf(" %s\n", _("Separates output on multiple OID requests"));
1322 printf (" %s\n", "-M, --multiplier=FLOAT"); 1287 printf(" %s\n", "-M, --multiplier=FLOAT");
1323 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"));
1324 printf (" %s\n", "-f, --fmtstr=STRING"); 1289 printf(" %s\n", "-f, --fmtstr=STRING");
1325 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)"));
1326 1291
1327 printf (UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); 1292 printf(UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
1328 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"));
1329 printf (" %s\n", "-e, --retries=INTEGER"); 1294 printf(" %s\n", "-e, --retries=INTEGER");
1330 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);
1331 1296
1332 printf (" %s\n", "-O, --perf-oids"); 1297 printf(" %s\n", "-O, --perf-oids");
1333 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"));
1334 1299
1335 printf (" %s\n", "--ignore-mib-parsing-errors"); 1300 printf(" %s\n", "--ignore-mib-parsing-errors");
1336 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"));
1337 1302
1338 printf (UT_VERBOSE); 1303 printf(UT_VERBOSE);
1339 1304
1340 printf ("\n"); 1305 printf("\n");
1341 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."));
1342 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"));
1343 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."));
1344 1309
1345 printf ("\n"); 1310 printf("\n");
1346 printf ("%s\n", _("Notes:")); 1311 printf("%s\n", _("Notes:"));
1347 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 "));
1348 printf (" %s\n", _("list (lists with internal spaces must be quoted).")); 1313 printf(" %s\n", _("list (lists with internal spaces must be quoted)."));
1349 1314
1350 printf(" -%s", UT_THRESHOLDS_NOTES); 1315 printf(" -%s", UT_THRESHOLDS_NOTES);
1351 1316
1352 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'"));
1353 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"));
1354 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"));
1355 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."));
1356 1321
1357 printf("\n"); 1322 printf("\n");
1358 printf("%s\n", _("Rate Calculation:")); 1323 printf("%s\n", _("Rate Calculation:"));
@@ -1364,19 +1329,15 @@ print_help (void)
1364 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"));
1365 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."));
1366 1331
1367 printf (UT_SUPPORT); 1332 printf(UT_SUPPORT);
1368} 1333}
1369 1334
1370 1335void print_usage(void) {
1371 1336 printf("%s\n", _("Usage:"));
1372void 1337 printf("%s -H <ip_address> -o <OID> [-w warn_range] [-c crit_range]\n", progname);
1373print_usage (void) 1338 printf("[-C community] [-s string] [-r regex] [-R regexi] [-t timeout] [-e retries]\n");
1374{ 1339 printf("[-l label] [-u units] [-p port-number] [-d delimiter] [-D output-delimiter]\n");
1375 printf ("%s\n", _("Usage:")); 1340 printf("[-m miblist] [-P snmp version] [-N context] [-L seclevel] [-U secname]\n");
1376 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");
1377 printf ("[-C community] [-s string] [-r regex] [-R regexi] [-t timeout] [-e retries]\n"); 1342 printf("[-M multiplier [-f format]]\n");
1378 printf ("[-l label] [-u units] [-p port-number] [-d delimiter] [-D output-delimiter]\n");
1379 printf ("[-m miblist] [-P snmp version] [-N context] [-L seclevel] [-U secname]\n");
1380 printf ("[-a authproto] [-A authpasswd] [-x privproto] [-X privpasswd] [-4|6]\n");
1381 printf ("[-M multiplier [-f format]]\n");
1382} 1343}
diff --git a/plugins/check_ssh.c b/plugins/check_ssh.c
index 34ef37b..42a88cf 100644
--- a/plugins/check_ssh.c
+++ b/plugins/check_ssh.c
@@ -1,35 +1,35 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring check_ssh plugin 3 * Monitoring check_ssh plugin
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 2000-2007 Monitoring Plugins Development Team 6 * Copyright (c) 2000-2024 Monitoring Plugins Development Team
7* 7 *
8* Description: 8 * Description:
9* 9 *
10* This file contains the check_ssh plugin 10 * This file contains the check_ssh plugin
11* 11 *
12* Try to connect to an SSH server at specified server and port 12 * Try to connect to an SSH server at specified server and port
13* 13 *
14* 14 *
15* This program is free software: you can redistribute it and/or modify 15 * This program is free software: you can redistribute it and/or modify
16* it under the terms of the GNU General Public License as published by 16 * it under the terms of the GNU General Public License as published by
17* the Free Software Foundation, either version 3 of the License, or 17 * the Free Software Foundation, either version 3 of the License, or
18* (at your option) any later version. 18 * (at your option) any later version.
19* 19 *
20* This program is distributed in the hope that it will be useful, 20 * This program is distributed in the hope that it will be useful,
21* but WITHOUT ANY WARRANTY; without even the implied warranty of 21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23* GNU General Public License for more details. 23 * GNU General Public License for more details.
24* 24 *
25* You should have received a copy of the GNU General Public License 25 * You should have received a copy of the GNU General Public License
26* along with this program. If not, see <http://www.gnu.org/licenses/>. 26 * along with this program. If not, see <http://www.gnu.org/licenses/>.
27* 27 *
28* 28 *
29*****************************************************************************/ 29 *****************************************************************************/
30 30
31const char *progname = "check_ssh"; 31const char *progname = "check_ssh";
32const char *copyright = "2000-2007"; 32const char *copyright = "2000-2024";
33const char *email = "devel@monitoring-plugins.org"; 33const char *email = "devel@monitoring-plugins.org";
34 34
35#include "./common.h" 35#include "./common.h"
@@ -37,108 +37,96 @@ const char *email = "devel@monitoring-plugins.org";
37#include "utils.h" 37#include "utils.h"
38 38
39#ifndef MSG_DONTWAIT 39#ifndef MSG_DONTWAIT
40#define MSG_DONTWAIT 0 40# define MSG_DONTWAIT 0
41#endif 41#endif
42 42
43#define SSH_DFL_PORT 22 43#define SSH_DFL_PORT 22
44#define BUFF_SZ 256 44#define BUFF_SZ 256
45 45
46int port = -1; 46static int port = -1;
47char *server_name = NULL; 47static char *server_name = NULL;
48char *remote_version = NULL; 48static char *remote_version = NULL;
49char *remote_protocol = NULL; 49static char *remote_protocol = NULL;
50bool verbose = false; 50static bool verbose = false;
51 51
52int process_arguments (int, char **); 52static int process_arguments(int /*argc*/, char ** /*argv*/);
53int validate_arguments (void); 53static int validate_arguments(void);
54void print_help (void); 54static void print_help(void);
55void print_usage (void); 55void print_usage(void);
56 56
57int ssh_connect (char *haddr, int hport, char *remote_version, char *remote_protocol); 57static int ssh_connect(char *haddr, int hport, char *remote_version, char *remote_protocol);
58 58
59 59int main(int argc, char **argv) {
60int 60 setlocale(LC_ALL, "");
61main (int argc, char **argv) 61 bindtextdomain(PACKAGE, LOCALEDIR);
62{ 62 textdomain(PACKAGE);
63 int result = STATE_UNKNOWN;
64
65 setlocale (LC_ALL, "");
66 bindtextdomain (PACKAGE, LOCALEDIR);
67 textdomain (PACKAGE);
68 63
69 /* Parse extra opts if any */ 64 /* Parse extra opts if any */
70 argv=np_extra_opts (&argc, argv, progname); 65 argv = np_extra_opts(&argc, argv, progname);
71 66
72 if (process_arguments (argc, argv) == ERROR) 67 if (process_arguments(argc, argv) == ERROR)
73 usage4 (_("Could not parse arguments")); 68 usage4(_("Could not parse arguments"));
74 69
75 /* initialize alarm signal handling */ 70 /* initialize alarm signal handling */
76 signal (SIGALRM, socket_timeout_alarm_handler); 71 signal(SIGALRM, socket_timeout_alarm_handler);
77 72
78 alarm (socket_timeout); 73 alarm(socket_timeout);
79 74
80 /* ssh_connect exits if error is found */ 75 /* ssh_connect exits if error is found */
81 result = ssh_connect (server_name, port, remote_version, remote_protocol); 76 int result = ssh_connect(server_name, port, remote_version, remote_protocol);
82 77
83 alarm (0); 78 alarm(0);
84 79
85 return (result); 80 return (result);
86} 81}
87 82
88
89
90/* process command-line arguments */ 83/* process command-line arguments */
91int 84int process_arguments(int argc, char **argv) {
92process_arguments (int argc, char **argv) 85 static struct option longopts[] = {{"help", no_argument, 0, 'h'},
93{ 86 {"version", no_argument, 0, 'V'},
94 int c; 87 {"host", required_argument, 0, 'H'}, /* backward compatibility */
95 88 {"hostname", required_argument, 0, 'H'},
96 int option = 0; 89 {"port", required_argument, 0, 'p'},
97 static struct option longopts[] = { 90 {"use-ipv4", no_argument, 0, '4'},
98 {"help", no_argument, 0, 'h'}, 91 {"use-ipv6", no_argument, 0, '6'},
99 {"version", no_argument, 0, 'V'}, 92 {"timeout", required_argument, 0, 't'},
100 {"host", required_argument, 0, 'H'}, /* backward compatibility */ 93 {"verbose", no_argument, 0, 'v'},
101 {"hostname", required_argument, 0, 'H'}, 94 {"remote-version", required_argument, 0, 'r'},
102 {"port", required_argument, 0, 'p'}, 95 {"remote-protocol", required_argument, 0, 'P'},
103 {"use-ipv4", no_argument, 0, '4'}, 96 {0, 0, 0, 0}};
104 {"use-ipv6", no_argument, 0, '6'},
105 {"timeout", required_argument, 0, 't'},
106 {"verbose", no_argument, 0, 'v'},
107 {"remote-version", required_argument, 0, 'r'},
108 {"remote-protocol", required_argument, 0, 'P'},
109 {0, 0, 0, 0}
110 };
111 97
112 if (argc < 2) 98 if (argc < 2)
113 return ERROR; 99 return ERROR;
114 100
115 for (c = 1; c < argc; c++) 101 for (int i = 1; i < argc; i++)
116 if (strcmp ("-to", argv[c]) == 0) 102 if (strcmp("-to", argv[i]) == 0)
117 strcpy (argv[c], "-t"); 103 strcpy(argv[i], "-t");
118 104
119 while (1) { 105 int option_char;
120 c = getopt_long (argc, argv, "+Vhv46t:r:H:p:P:", longopts, &option); 106 while (true) {
107 int option = 0;
108 option_char = getopt_long(argc, argv, "+Vhv46t:r:H:p:P:", longopts, &option);
121 109
122 if (c == -1 || c == EOF) 110 if (option_char == -1 || option_char == EOF)
123 break; 111 break;
124 112
125 switch (c) { 113 switch (option_char) {
126 case '?': /* help */ 114 case '?': /* help */
127 usage5 (); 115 usage5();
128 case 'V': /* version */ 116 case 'V': /* version */
129 print_revision (progname, NP_VERSION); 117 print_revision(progname, NP_VERSION);
130 exit (STATE_UNKNOWN); 118 exit(STATE_UNKNOWN);
131 case 'h': /* help */ 119 case 'h': /* help */
132 print_help (); 120 print_help();
133 exit (STATE_UNKNOWN); 121 exit(STATE_UNKNOWN);
134 case 'v': /* verbose */ 122 case 'v': /* verbose */
135 verbose = true; 123 verbose = true;
136 break; 124 break;
137 case 't': /* timeout period */ 125 case 't': /* timeout period */
138 if (!is_integer (optarg)) 126 if (!is_integer(optarg))
139 usage2 (_("Timeout interval must be a positive integer"), optarg); 127 usage2(_("Timeout interval must be a positive integer"), optarg);
140 else 128 else
141 socket_timeout = atoi (optarg); 129 socket_timeout = atoi(optarg);
142 break; 130 break;
143 case '4': 131 case '4':
144 address_family = AF_INET; 132 address_family = AF_INET;
@@ -147,121 +135,104 @@ process_arguments (int argc, char **argv)
147#ifdef USE_IPV6 135#ifdef USE_IPV6
148 address_family = AF_INET6; 136 address_family = AF_INET6;
149#else 137#else
150 usage4 (_("IPv6 support not available")); 138 usage4(_("IPv6 support not available"));
151#endif 139#endif
152 break; 140 break;
153 case 'r': /* remote version */ 141 case 'r': /* remote version */
154 remote_version = optarg; 142 remote_version = optarg;
155 break; 143 break;
156 case 'P': /* remote version */ 144 case 'P': /* remote version */
157 remote_protocol = optarg; 145 remote_protocol = optarg;
158 break; 146 break;
159 case 'H': /* host */ 147 case 'H': /* host */
160 if (!is_host (optarg)) 148 if (!is_host(optarg))
161 usage2 (_("Invalid hostname/address"), optarg); 149 usage2(_("Invalid hostname/address"), optarg);
162 server_name = optarg; 150 server_name = optarg;
163 break; 151 break;
164 case 'p': /* port */ 152 case 'p': /* port */
165 if (is_intpos (optarg)) { 153 if (is_intpos(optarg)) {
166 port = atoi (optarg); 154 port = atoi(optarg);
167 } 155 } else {
168 else { 156 usage2(_("Port number must be a positive integer"), optarg);
169 usage2 (_("Port number must be a positive integer"), optarg);
170 } 157 }
171 } 158 }
172 } 159 }
173 160
174 c = optind; 161 option_char = optind;
175 if (server_name == NULL && c < argc) { 162 if (server_name == NULL && option_char < argc) {
176 if (is_host (argv[c])) { 163 if (is_host(argv[option_char])) {
177 server_name = argv[c++]; 164 server_name = argv[option_char++];
178 } 165 }
179 } 166 }
180 167
181 if (port == -1 && c < argc) { 168 if (port == -1 && option_char < argc) {
182 if (is_intpos (argv[c])) { 169 if (is_intpos(argv[option_char])) {
183 port = atoi (argv[c++]); 170 port = atoi(argv[option_char++]);
184 } 171 } else {
185 else { 172 print_usage();
186 print_usage (); 173 exit(STATE_UNKNOWN);
187 exit (STATE_UNKNOWN);
188 } 174 }
189 } 175 }
190 176
191 return validate_arguments (); 177 return validate_arguments();
192} 178}
193 179
194int 180int validate_arguments(void) {
195validate_arguments (void)
196{
197 if (server_name == NULL) 181 if (server_name == NULL)
198 return ERROR; 182 return ERROR;
199 if (port == -1) /* funky, but allows -p to override stray integer in args */ 183 if (port == -1) /* funky, but allows -p to override stray integer in args */
200 port = SSH_DFL_PORT; 184 port = SSH_DFL_PORT;
201 return OK; 185 return OK;
202} 186}
203 187
204
205/************************************************************************ 188/************************************************************************
206* 189 *
207* Try to connect to SSH server at specified server and port 190 * Try to connect to SSH server at specified server and port
208* 191 *
209*-----------------------------------------------------------------------*/ 192 *-----------------------------------------------------------------------*/
210
211
212int
213ssh_connect (char *haddr, int hport, char *remote_version, char *remote_protocol)
214{
215 int sd;
216 int result;
217 int len = 0;
218 ssize_t recv_ret = 0;
219 char *version_control_string = NULL;
220 char *buffer = NULL;
221 char *ssh_proto = NULL;
222 char *ssh_server = NULL;
223 static char *rev_no = VERSION;
224 struct timeval tv;
225 double elapsed_time;
226 193
194int ssh_connect(char *haddr, int hport, char *remote_version, char *remote_protocol) {
195 struct timeval tv;
227 gettimeofday(&tv, NULL); 196 gettimeofday(&tv, NULL);
228 197
229 result = my_tcp_connect (haddr, hport, &sd); 198 int socket;
199 int result = my_tcp_connect(haddr, hport, &socket);
230 200
231 if (result != STATE_OK) 201 if (result != STATE_OK)
232 return result; 202 return result;
233 203
234 char *output = (char *) calloc (BUFF_SZ + 1, sizeof(char)); 204 char *output = (char *)calloc(BUFF_SZ + 1, sizeof(char));
235 205 char *buffer = NULL;
236 unsigned int iteration = 0; 206 ssize_t recv_ret = 0;
207 char *version_control_string = NULL;
237 ssize_t byte_offset = 0; 208 ssize_t byte_offset = 0;
238 209 while ((version_control_string == NULL) && (recv_ret = recv(socket, output + byte_offset, BUFF_SZ - byte_offset, 0) > 0)) {
239 while ((version_control_string == NULL) && (recv_ret = recv(sd, output+byte_offset, BUFF_SZ - byte_offset, 0) > 0)) {
240 210
241 if (strchr(output, '\n')) { /* we've got at least one full line, start parsing*/ 211 if (strchr(output, '\n')) { /* we've got at least one full line, start parsing*/
242 byte_offset = 0; 212 byte_offset = 0;
243 213
244 char *index = NULL; 214 char *index = NULL;
245 while ((index = strchr(output+byte_offset, '\n')) != NULL) { 215 int len = 0;
216 while ((index = strchr(output + byte_offset, '\n')) != NULL) {
246 /*Partition the buffer so that this line is a separate string, 217 /*Partition the buffer so that this line is a separate string,
247 * by replacing the newline with NUL*/ 218 * by replacing the newline with NUL*/
248 output[(index - output)] = '\0'; 219 output[(index - output)] = '\0';
249 len = strlen(output + byte_offset); 220 len = strlen(output + byte_offset);
250 221
251 if ((len >= 4) && (strncmp (output+byte_offset, "SSH-", 4) == 0)) { 222 if ((len >= 4) && (strncmp(output + byte_offset, "SSH-", 4) == 0)) {
252 /*if the string starts with SSH-, this _should_ be a valid version control string*/ 223 /*if the string starts with SSH-, this _should_ be a valid version control string*/
253 version_control_string = output+byte_offset; 224 version_control_string = output + byte_offset;
254 break; 225 break;
255 } 226 }
256 227
257 /*the start of the next line (if one exists) will be after the current one (+ NUL)*/ 228 /*the start of the next line (if one exists) will be after the current one (+ NUL)*/
258 byte_offset += (len + 1); 229 byte_offset += (len + 1);
259 } 230 }
260 231
261 if(version_control_string == NULL) { 232 if (version_control_string == NULL) {
262 /* move unconsumed data to beginning of buffer, null rest */ 233 /* move unconsumed data to beginning of buffer, null rest */
263 memmove((void *)output, (void *)output+byte_offset+1, BUFF_SZ - len+1); 234 memmove((void *)output, (void *)(output + byte_offset + 1), BUFF_SZ - len + 1);
264 memset(output+byte_offset+1, 0, BUFF_SZ-byte_offset+1); 235 memset(output + byte_offset + 1, 0, BUFF_SZ - byte_offset + 1);
265 236
266 /*start reading from end of current line chunk on next recv*/ 237 /*start reading from end of current line chunk on next recv*/
267 byte_offset = strlen(output); 238 byte_offset = strlen(output);
@@ -287,10 +258,11 @@ ssh_connect (char *haddr, int hport, char *remote_version, char *remote_protocol
287 * SSH-protoversion-softwareversion SP comments CR LF" 258 * SSH-protoversion-softwareversion SP comments CR LF"
288 * - RFC 4253:4.2 259 * - RFC 4253:4.2
289 */ 260 */
290 strip (version_control_string); 261 strip(version_control_string);
291 if (verbose) 262 if (verbose)
292 printf ("%s\n", version_control_string); 263 printf("%s\n", version_control_string);
293 ssh_proto = version_control_string + 4; 264
265 char *ssh_proto = version_control_string + 4;
294 266
295 /* 267 /*
296 * We assume the protoversion is of the form Major.Minor, although 268 * We assume the protoversion is of the form Major.Minor, although
@@ -308,7 +280,7 @@ ssh_connect (char *haddr, int hport, char *remote_version, char *remote_protocol
308 * "1.x" (e.g., "1.5" or "1.3")." 280 * "1.x" (e.g., "1.5" or "1.3")."
309 * - RFC 4253:5 281 * - RFC 4253:5
310 */ 282 */
311 ssh_server = ssh_proto + strspn (ssh_proto, "0123456789.") + 1; /* (+1 for the '-' separating protoversion from softwareversion) */ 283 char *ssh_server = ssh_proto + strspn(ssh_proto, "0123456789.") + 1; /* (+1 for the '-' separating protoversion from softwareversion) */
312 284
313 /* If there's a space in the version string, whatever's after the space is a comment 285 /* If there's a space in the version string, whatever's after the space is a comment
314 * (which is NOT part of the server name/version)*/ 286 * (which is NOT part of the server name/version)*/
@@ -318,86 +290,72 @@ ssh_connect (char *haddr, int hport, char *remote_version, char *remote_protocol
318 } 290 }
319 if (strlen(ssh_proto) == 0 || strlen(ssh_server) == 0) { 291 if (strlen(ssh_proto) == 0 || strlen(ssh_server) == 0) {
320 printf(_("SSH CRITICAL - Invalid protocol version control string %s\n"), version_control_string); 292 printf(_("SSH CRITICAL - Invalid protocol version control string %s\n"), version_control_string);
321 exit (STATE_CRITICAL); 293 exit(STATE_CRITICAL);
322 } 294 }
323 ssh_proto[strspn (ssh_proto, "0123456789. ")] = 0; 295 ssh_proto[strspn(ssh_proto, "0123456789. ")] = 0;
324 296
325 xasprintf (&buffer, "SSH-%s-check_ssh_%s\r\n", ssh_proto, rev_no); 297 static char *rev_no = VERSION;
326 send (sd, buffer, strlen (buffer), MSG_DONTWAIT); 298 xasprintf(&buffer, "SSH-%s-check_ssh_%s\r\n", ssh_proto, rev_no);
299 send(socket, buffer, strlen(buffer), MSG_DONTWAIT);
327 if (verbose) 300 if (verbose)
328 printf ("%s\n", buffer); 301 printf("%s\n", buffer);
329 302
330 if (remote_version && strcmp(remote_version, ssh_server)) { 303 if (remote_version && strcmp(remote_version, ssh_server)) {
331 printf 304 printf(_("SSH CRITICAL - %s (protocol %s) version mismatch, expected '%s'\n"), ssh_server, ssh_proto, remote_version);
332 (_("SSH CRITICAL - %s (protocol %s) version mismatch, expected '%s'\n"), 305 close(socket);
333 ssh_server, ssh_proto, remote_version); 306 exit(STATE_CRITICAL);
334 close(sd);
335 exit (STATE_CRITICAL);
336 } 307 }
337 308
309 double elapsed_time = (double)deltime(tv) / 1.0e6;
338 if (remote_protocol && strcmp(remote_protocol, ssh_proto)) { 310 if (remote_protocol && strcmp(remote_protocol, ssh_proto)) {
339 printf 311 printf(_("SSH CRITICAL - %s (protocol %s) protocol version mismatch, expected '%s' | %s\n"), ssh_server, ssh_proto, remote_protocol,
340 (_("SSH CRITICAL - %s (protocol %s) protocol version mismatch, expected '%s' | %s\n"), 312 fperfdata("time", elapsed_time, "s", false, 0, false, 0, true, 0, true, (int)socket_timeout));
341 ssh_server, ssh_proto, remote_protocol, fperfdata("time", elapsed_time, "s", 313 close(socket);
342 false, 0, false, 0, true, 0, true, (int)socket_timeout)); 314 exit(STATE_CRITICAL);
343 close(sd);
344 exit (STATE_CRITICAL);
345 } 315 }
346 elapsed_time = (double)deltime(tv) / 1.0e6;
347
348 printf
349 (_("SSH OK - %s (protocol %s) | %s\n"),
350 ssh_server, ssh_proto, fperfdata("time", elapsed_time, "s",
351 false, 0, false, 0, true, 0, true, (int)socket_timeout));
352 close(sd);
353 exit (STATE_OK);
354}
355
356 316
317 printf(_("SSH OK - %s (protocol %s) | %s\n"), ssh_server, ssh_proto,
318 fperfdata("time", elapsed_time, "s", false, 0, false, 0, true, 0, true, (int)socket_timeout));
319 close(socket);
320 exit(STATE_OK);
321}
357 322
358void 323void print_help(void) {
359print_help (void)
360{
361 char *myport; 324 char *myport;
362 xasprintf (&myport, "%d", SSH_DFL_PORT); 325 xasprintf(&myport, "%d", SSH_DFL_PORT);
363 326
364 print_revision (progname, NP_VERSION); 327 print_revision(progname, NP_VERSION);
365 328
366 printf ("Copyright (c) 1999 Remi Paulmier <remi@sinfomic.fr>\n"); 329 printf("Copyright (c) 1999 Remi Paulmier <remi@sinfomic.fr>\n");
367 printf (COPYRIGHT, copyright, email); 330 printf(COPYRIGHT, copyright, email);
368 331
369 printf ("%s\n", _("Try to connect to an SSH server at specified server and port")); 332 printf("%s\n", _("Try to connect to an SSH server at specified server and port"));
370 333
371 printf ("\n\n"); 334 printf("\n\n");
372 335
373 print_usage (); 336 print_usage();
374 337
375 printf (UT_HELP_VRSN); 338 printf(UT_HELP_VRSN);
376 printf (UT_EXTRA_OPTS); 339 printf(UT_EXTRA_OPTS);
377 340
378 printf (UT_HOST_PORT, 'p', myport); 341 printf(UT_HOST_PORT, 'p', myport);
379 342
380 printf (UT_IPv46); 343 printf(UT_IPv46);
381 344
382 printf (UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); 345 printf(UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
383 346
384 printf (" %s\n", "-r, --remote-version=STRING"); 347 printf(" %s\n", "-r, --remote-version=STRING");
385 printf (" %s\n", _("Alert if string doesn't match expected server version (ex: OpenSSH_3.9p1)")); 348 printf(" %s\n", _("Alert if string doesn't match expected server version (ex: OpenSSH_3.9p1)"));
386 349
387 printf (" %s\n", "-P, --remote-protocol=STRING"); 350 printf(" %s\n", "-P, --remote-protocol=STRING");
388 printf (" %s\n", _("Alert if protocol doesn't match expected protocol version (ex: 2.0)")); 351 printf(" %s\n", _("Alert if protocol doesn't match expected protocol version (ex: 2.0)"));
389 352
390 printf (UT_VERBOSE); 353 printf(UT_VERBOSE);
391 354
392 printf (UT_SUPPORT); 355 printf(UT_SUPPORT);
393} 356}
394 357
395 358void print_usage(void) {
396 359 printf("%s\n", _("Usage:"));
397void 360 printf("%s [-4|-6] [-t <timeout>] [-r <remote version>] [-p <port>] <host>\n", progname);
398print_usage (void)
399{
400 printf ("%s\n", _("Usage:"));
401 printf ("%s [-4|-6] [-t <timeout>] [-r <remote version>] [-p <port>] <host>\n", progname);
402} 361}
403
diff --git a/plugins/check_tcp.c b/plugins/check_tcp.c
index 01dd35e..49ad096 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,65 +91,52 @@ 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
129 /* set up a reasonable buffer at first (will be realloc()'ed if 120 /* set up a reasonable buffer at first (will be realloc()'ed if
130 * user specifies other options) */ 121 * user specifies other options) */
131 server_expect = calloc(sizeof(char *), 2); 122 server_expect = calloc(2, sizeof(char *));
132 123
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 380ff3b..526a29d 100644
--- a/plugins/check_ups.c
+++ b/plugins/check_ups.c
@@ -6,7 +6,7 @@
6 * Copyright (c) 2000 Tom Shields 6 * Copyright (c) 2000 Tom Shields
7 * 2004 Alain Richard <alain.richard@equation.fr> 7 * 2004 Alain Richard <alain.richard@equation.fr>
8 * 2004 Arnaud Quette <arnaud.quette@mgeups.com> 8 * 2004 Arnaud Quette <arnaud.quette@mgeups.com>
9 * Copyright (c) 2002-2023 Monitoring Plugins Development Team 9 * Copyright (c) 2002-2024 Monitoring Plugins Development Team
10 * 10 *
11 * Description: 11 * Description:
12 * 12 *
@@ -33,14 +33,16 @@
33 *****************************************************************************/ 33 *****************************************************************************/
34 34
35const char *progname = "check_ups"; 35const char *progname = "check_ups";
36const char *copyright = "2000-2023"; 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"
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;
@@ -93,12 +97,12 @@ ups_config ups_config_init(void) {
93} 97}
94 98
95// Forward declarations 99// Forward declarations
96int determine_status(ups_config *, int *supported_options); 100static int determine_status(ups_config * /*config*/, int *supported_options);
97int get_ups_variable(const char *, char *, const ups_config config); 101static int get_ups_variable(const char * /*varname*/, char * /*buf*/, ups_config config);
98 102
99int process_arguments(int, char **, ups_config *); 103static int process_arguments(int /*argc*/, char ** /*argv*/, ups_config * /*config*/);
100int validate_arguments(ups_config); 104static int validate_arguments(ups_config /*config*/);
101void print_help(void); 105static void print_help(void);
102void print_usage(void); 106void print_usage(void);
103 107
104int main(int argc, char **argv) { 108int main(int argc, char **argv) {
@@ -141,7 +145,6 @@ int main(int argc, char **argv) {
141 return STATE_CRITICAL; 145 return STATE_CRITICAL;
142 } 146 }
143 147
144
145 if (supported_options & UPS_STATUS) { 148 if (supported_options & UPS_STATUS) {
146 149
147 ups_status = strdup(""); 150 ups_status = strdup("");
@@ -151,8 +154,7 @@ int main(int argc, char **argv) {
151 if (config.status & UPSSTATUS_OFF) { 154 if (config.status & UPSSTATUS_OFF) {
152 xasprintf(&ups_status, "Off"); 155 xasprintf(&ups_status, "Off");
153 result = STATE_CRITICAL; 156 result = STATE_CRITICAL;
154 } else if ((config.status & (UPSSTATUS_OB | UPSSTATUS_LB)) == 157 } else if ((config.status & (UPSSTATUS_OB | UPSSTATUS_LB)) == (UPSSTATUS_OB | UPSSTATUS_LB)) {
155 (UPSSTATUS_OB | UPSSTATUS_LB)) {
156 xasprintf(&ups_status, _("On Battery, Low Battery")); 158 xasprintf(&ups_status, _("On Battery, Low Battery"));
157 result = STATE_CRITICAL; 159 result = STATE_CRITICAL;
158 } else { 160 } else {
@@ -171,8 +173,7 @@ int main(int argc, char **argv) {
171 xasprintf(&ups_status, "%s%s", ups_status, _(", Calibrating")); 173 xasprintf(&ups_status, "%s%s", ups_status, _(", Calibrating"));
172 } 174 }
173 if (config.status & UPSSTATUS_RB) { 175 if (config.status & UPSSTATUS_RB) {
174 xasprintf(&ups_status, "%s%s", ups_status, 176 xasprintf(&ups_status, "%s%s", ups_status, _(", Replace Battery"));
175 _(", Replace Battery"));
176 result = max_state(result, STATE_WARNING); 177 result = max_state(result, STATE_WARNING);
177 } 178 }
178 if (config.status & UPSSTATUS_BYPASS) { 179 if (config.status & UPSSTATUS_BYPASS) {
@@ -233,24 +234,16 @@ int main(int argc, char **argv) {
233 } 234 }
234 235
235 if (config.check_variable == UPS_UTILITY) { 236 if (config.check_variable == UPS_UTILITY) {
236 if (config.check_crit && 237 if (config.check_crit && ups_utility_deviation >= config.critical_value) {
237 ups_utility_deviation >= config.critical_value) {
238 result = STATE_CRITICAL; 238 result = STATE_CRITICAL;
239 } else if (config.check_warn && 239 } else if (config.check_warn && ups_utility_deviation >= config.warning_value) {
240 ups_utility_deviation >= config.warning_value) {
241 result = max_state(result, STATE_WARNING); 240 result = max_state(result, STATE_WARNING);
242 } 241 }
243 xasprintf(&data, "%s", 242 xasprintf(&data, "%s",
244 perfdata("voltage", (long)(1000 * ups_utility_voltage), 243 perfdata("voltage", (long)(1000 * ups_utility_voltage), "mV", config.check_warn, (long)(1000 * config.warning_value),
245 "mV", config.check_warn, 244 config.check_crit, (long)(1000 * config.critical_value), true, 0, false, 0));
246 (long)(1000 * config.warning_value),
247 config.check_crit,
248 (long)(1000 * config.critical_value), true, 0,
249 false, 0));
250 } else { 245 } else {
251 xasprintf(&data, "%s", 246 xasprintf(&data, "%s", perfdata("voltage", (long)(1000 * ups_utility_voltage), "mV", false, 0, false, 0, true, 0, false, 0));
252 perfdata("voltage", (long)(1000 * ups_utility_voltage),
253 "mV", false, 0, false, 0, true, 0, false, 0));
254 } 247 }
255 } 248 }
256 249
@@ -268,22 +261,16 @@ int main(int argc, char **argv) {
268 xasprintf(&message, "%sBatt=%3.1f%% ", message, ups_battery_percent); 261 xasprintf(&message, "%sBatt=%3.1f%% ", message, ups_battery_percent);
269 262
270 if (config.check_variable == UPS_BATTPCT) { 263 if (config.check_variable == UPS_BATTPCT) {
271 if (config.check_crit && 264 if (config.check_crit && ups_battery_percent <= config.critical_value) {
272 ups_battery_percent <= config.critical_value) {
273 result = STATE_CRITICAL; 265 result = STATE_CRITICAL;
274 } else if (config.check_warn && 266 } else if (config.check_warn && ups_battery_percent <= config.warning_value) {
275 ups_battery_percent <= config.warning_value) {
276 result = max_state(result, STATE_WARNING); 267 result = max_state(result, STATE_WARNING);
277 } 268 }
278 xasprintf(&data, "%s %s", data, 269 xasprintf(&data, "%s %s", data,
279 perfdata("battery", (long)ups_battery_percent, "%", 270 perfdata("battery", (long)ups_battery_percent, "%", config.check_warn, (long)(config.warning_value),
280 config.check_warn, (long)(config.warning_value), 271 config.check_crit, (long)(config.critical_value), true, 0, true, 100));
281 config.check_crit, (long)(config.critical_value),
282 true, 0, true, 100));
283 } else { 272 } else {
284 xasprintf(&data, "%s %s", data, 273 xasprintf(&data, "%s %s", data, perfdata("battery", (long)ups_battery_percent, "%", false, 0, false, 0, true, 0, true, 100));
285 perfdata("battery", (long)ups_battery_percent, "%", false,
286 0, false, 0, true, 0, true, 100));
287 } 274 }
288 } 275 }
289 276
@@ -301,22 +288,16 @@ int main(int argc, char **argv) {
301 xasprintf(&message, "%sLoad=%3.1f%% ", message, ups_load_percent); 288 xasprintf(&message, "%sLoad=%3.1f%% ", message, ups_load_percent);
302 289
303 if (config.check_variable == UPS_LOADPCT) { 290 if (config.check_variable == UPS_LOADPCT) {
304 if (config.check_crit && 291 if (config.check_crit && ups_load_percent >= config.critical_value) {
305 ups_load_percent >= config.critical_value) {
306 result = STATE_CRITICAL; 292 result = STATE_CRITICAL;
307 } else if (config.check_warn && 293 } else if (config.check_warn && ups_load_percent >= config.warning_value) {
308 ups_load_percent >= config.warning_value) {
309 result = max_state(result, STATE_WARNING); 294 result = max_state(result, STATE_WARNING);
310 } 295 }
311 xasprintf(&data, "%s %s", data, 296 xasprintf(&data, "%s %s", data,
312 perfdata("load", (long)ups_load_percent, "%", 297 perfdata("load", (long)ups_load_percent, "%", config.check_warn, (long)(config.warning_value), config.check_crit,
313 config.check_warn, (long)(config.warning_value), 298 (long)(config.critical_value), true, 0, true, 100));
314 config.check_crit, (long)(config.critical_value),
315 true, 0, true, 100));
316 } else { 299 } else {
317 xasprintf(&data, "%s %s", data, 300 xasprintf(&data, "%s %s", data, perfdata("load", (long)ups_load_percent, "%", false, 0, false, 0, true, 0, true, 100));
318 perfdata("load", (long)ups_load_percent, "%", false, 0,
319 false, 0, true, 0, true, 100));
320 } 301 }
321 } 302 }
322 303
@@ -345,19 +326,14 @@ int main(int argc, char **argv) {
345 if (config.check_variable == UPS_TEMP) { 326 if (config.check_variable == UPS_TEMP) {
346 if (config.check_crit && ups_temperature >= config.critical_value) { 327 if (config.check_crit && ups_temperature >= config.critical_value) {
347 result = STATE_CRITICAL; 328 result = STATE_CRITICAL;
348 } else if (config.check_warn && 329 } else if (config.check_warn && ups_temperature >= config.warning_value) {
349 ups_temperature >= config.warning_value) {
350 result = max_state(result, STATE_WARNING); 330 result = max_state(result, STATE_WARNING);
351 } 331 }
352 xasprintf(&data, "%s %s", data, 332 xasprintf(&data, "%s %s", data,
353 perfdata("temp", (long)ups_temperature, tunits, 333 perfdata("temp", (long)ups_temperature, tunits, config.check_warn, (long)(config.warning_value), config.check_crit,
354 config.check_warn, (long)(config.warning_value), 334 (long)(config.critical_value), true, 0, false, 0));
355 config.check_crit, (long)(config.critical_value),
356 true, 0, false, 0));
357 } else { 335 } else {
358 xasprintf(&data, "%s %s", data, 336 xasprintf(&data, "%s %s", data, perfdata("temp", (long)ups_temperature, tunits, false, 0, false, 0, true, 0, false, 0));
359 perfdata("temp", (long)ups_temperature, tunits, false, 0,
360 false, 0, true, 0, false, 0));
361 } 337 }
362 } 338 }
363 339
@@ -376,19 +352,14 @@ int main(int argc, char **argv) {
376 if (config.check_variable == UPS_REALPOWER) { 352 if (config.check_variable == UPS_REALPOWER) {
377 if (config.check_crit && ups_realpower >= config.critical_value) { 353 if (config.check_crit && ups_realpower >= config.critical_value) {
378 result = STATE_CRITICAL; 354 result = STATE_CRITICAL;
379 } else if (config.check_warn && 355 } else if (config.check_warn && ups_realpower >= config.warning_value) {
380 ups_realpower >= config.warning_value) {
381 result = max_state(result, STATE_WARNING); 356 result = max_state(result, STATE_WARNING);
382 } 357 }
383 xasprintf(&data, "%s %s", data, 358 xasprintf(&data, "%s %s", data,
384 perfdata("realpower", (long)ups_realpower, "W", 359 perfdata("realpower", (long)ups_realpower, "W", config.check_warn, (long)(config.warning_value), config.check_crit,
385 config.check_warn, (long)(config.warning_value), 360 (long)(config.critical_value), true, 0, false, 0));
386 config.check_crit, (long)(config.critical_value),
387 true, 0, false, 0));
388 } else { 361 } else {
389 xasprintf(&data, "%s %s", data, 362 xasprintf(&data, "%s %s", data, perfdata("realpower", (long)ups_realpower, "W", false, 0, false, 0, true, 0, false, 0));
390 perfdata("realpower", (long)ups_realpower, "W", false, 0,
391 false, 0, true, 0, false, 0));
392 } 363 }
393 } 364 }
394 365
@@ -425,8 +396,7 @@ int determine_status(ups_config *config, int *supported_options) {
425 char temp_buffer[MAX_INPUT_BUFFER]; 396 char temp_buffer[MAX_INPUT_BUFFER];
426 397
427 strcpy(temp_buffer, recv_buffer); 398 strcpy(temp_buffer, recv_buffer);
428 for (char *ptr = (char *)strtok(temp_buffer, " "); ptr != NULL; 399 for (char *ptr = (char *)strtok(temp_buffer, " "); ptr != NULL; ptr = (char *)strtok(NULL, " ")) {
429 ptr = (char *)strtok(NULL, " ")) {
430 if (!strcmp(ptr, "OFF")) { 400 if (!strcmp(ptr, "OFF")) {
431 config->status |= UPSSTATUS_OFF; 401 config->status |= UPSSTATUS_OFF;
432 } else if (!strcmp(ptr, "OL")) { 402 } else if (!strcmp(ptr, "OL")) {
@@ -467,8 +437,7 @@ int get_ups_variable(const char *varname, char *buf, const ups_config config) {
467 437
468 /* create the command string to send to the UPS daemon */ 438 /* create the command string to send to the UPS daemon */
469 /* Add LOGOUT to avoid read failure logs */ 439 /* Add LOGOUT to avoid read failure logs */
470 int res = snprintf(send_buffer, sizeof(send_buffer), 440 int res = snprintf(send_buffer, sizeof(send_buffer), "GET VAR %s %s\nLOGOUT\n", config.ups_name, varname);
471 "GET VAR %s %s\nLOGOUT\n", config.ups_name, varname);
472 if ((res > 0) && ((size_t)res >= sizeof(send_buffer))) { 441 if ((res > 0) && ((size_t)res >= sizeof(send_buffer))) {
473 printf("%s\n", _("UPS name to long for buffer")); 442 printf("%s\n", _("UPS name to long for buffer"));
474 return ERROR; 443 return ERROR;
@@ -477,9 +446,7 @@ int get_ups_variable(const char *varname, char *buf, const ups_config config) {
477 char temp_buffer[MAX_INPUT_BUFFER]; 446 char temp_buffer[MAX_INPUT_BUFFER];
478 447
479 /* send the command to the daemon and get a response back */ 448 /* send the command to the daemon and get a response back */
480 if (process_tcp_request(config.server_address, config.server_port, 449 if (process_tcp_request(config.server_address, config.server_port, send_buffer, temp_buffer, sizeof(temp_buffer)) != STATE_OK) {
481 send_buffer, temp_buffer,
482 sizeof(temp_buffer)) != STATE_OK) {
483 printf("%s\n", _("Invalid response received from host")); 450 printf("%s\n", _("Invalid response received from host"));
484 return ERROR; 451 return ERROR;
485 } 452 }
@@ -496,8 +463,7 @@ int get_ups_variable(const char *varname, char *buf, const ups_config config) {
496 ptr[len - 1] = 0; 463 ptr[len - 1] = 0;
497 } 464 }
498 if (strcmp(ptr, "ERR UNKNOWN-UPS") == 0) { 465 if (strcmp(ptr, "ERR UNKNOWN-UPS") == 0) {
499 printf(_("CRITICAL - no such UPS '%s' on that host\n"), 466 printf(_("CRITICAL - no such UPS '%s' on that host\n"), config.ups_name);
500 config.ups_name);
501 return ERROR; 467 return ERROR;
502 } 468 }
503 469
@@ -694,8 +660,7 @@ void print_help(void) {
694 printf(" %s\n", "-T, --temperature"); 660 printf(" %s\n", "-T, --temperature");
695 printf(" %s\n", _("Output of temperatures in Celsius")); 661 printf(" %s\n", _("Output of temperatures in Celsius"));
696 printf(" %s\n", "-v, --variable=STRING"); 662 printf(" %s\n", "-v, --variable=STRING");
697 printf(" %s %s\n", _("Valid values for STRING are"), 663 printf(" %s %s\n", _("Valid values for STRING are"), "LINE, TEMP, BATTPCT, LOADPCT or REALPOWER");
698 "LINE, TEMP, BATTPCT, LOADPCT or REALPOWER");
699 664
700 printf(UT_WARN_CRIT); 665 printf(UT_WARN_CRIT);
701 666
@@ -731,8 +696,7 @@ void print_help(void) {
731 "with Russell Kroll's")); 696 "with Russell Kroll's"));
732 printf(" %s\n", _("Network UPS Tools be installed on the remote host. If " 697 printf(" %s\n", _("Network UPS Tools be installed on the remote host. If "
733 "you do not have the")); 698 "you do not have the"));
734 printf(" %s\n", 699 printf(" %s\n", _("package installed on your system, you can download it from"));
735 _("package installed on your system, you can download it from"));
736 printf(" %s\n", _("http://www.networkupstools.org")); 700 printf(" %s\n", _("http://www.networkupstools.org"));
737 701
738 printf(UT_SUPPORT); 702 printf(UT_SUPPORT);
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..7484314 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,49 +114,50 @@ 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
135 * of (len / 2) + 1. We add 1 extra to the mix for NULL termination */ 131 * of (len / 2) + 1. We add 1 extra to the mix for NULL termination */
136 argc = (cmdlen >> 1) + 2; 132 argc = (cmdlen >> 1) + 2;
137 argv = calloc(sizeof(char *), argc); 133 argv = calloc(argc, sizeof(char *));
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..6d366e3 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(len + 1, sizeof(char));
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;