summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/output.c12
-rw-r--r--lib/output.h7
-rw-r--r--plugins/Makefile.am9
-rw-r--r--plugins/check_dns.c373
-rw-r--r--plugins/check_dns.d/config.h34
-rw-r--r--plugins/check_game.c229
-rw-r--r--plugins/check_game.d/config.h30
-rw-r--r--plugins/check_ssh.c210
-rw-r--r--plugins/check_ssh.d/config.h29
-rw-r--r--plugins/check_swap.c2
-rw-r--r--plugins/netutils.c93
-rw-r--r--plugins/t/check_http.t2
-rw-r--r--plugins/t/check_jabber.t2
-rw-r--r--plugins/t/check_ldap.t2
-rw-r--r--plugins/t/check_ntp.t2
-rw-r--r--plugins/t/check_smtp.t3
-rw-r--r--plugins/t/check_ssh.t114
-rw-r--r--plugins/utils.c243
-rw-r--r--plugins/utils.h141
19 files changed, 961 insertions, 576 deletions
diff --git a/lib/output.c b/lib/output.c
index 17919afc..61fbf832 100644
--- a/lib/output.c
+++ b/lib/output.c
@@ -11,6 +11,9 @@
11#include "perfdata.h" 11#include "perfdata.h"
12#include "states.h" 12#include "states.h"
13 13
14// == Global variables
15static mp_output_format output_format = MP_FORMAT_DEFAULT;
16
14// == Prototypes == 17// == Prototypes ==
15static char *fmt_subcheck_output(mp_output_format output_format, mp_subcheck check, unsigned int indentation); 18static char *fmt_subcheck_output(mp_output_format output_format, mp_subcheck check, unsigned int indentation);
16static inline cJSON *json_serialize_subcheck(mp_subcheck subcheck); 19static inline cJSON *json_serialize_subcheck(mp_subcheck subcheck);
@@ -55,7 +58,6 @@ static inline char *fmt_subcheck_perfdata(mp_subcheck check) {
55 */ 58 */
56mp_check mp_check_init(void) { 59mp_check mp_check_init(void) {
57 mp_check check = {0}; 60 mp_check check = {0};
58 check.format = MP_FORMAT_DEFAULT;
59 return check; 61 return check;
60} 62}
61 63
@@ -234,7 +236,7 @@ mp_state_enum mp_compute_check_state(const mp_check check) {
234char *mp_fmt_output(mp_check check) { 236char *mp_fmt_output(mp_check check) {
235 char *result = NULL; 237 char *result = NULL;
236 238
237 switch (check.format) { 239 switch (output_format) {
238 case MP_FORMAT_MULTI_LINE: { 240 case MP_FORMAT_MULTI_LINE: {
239 if (check.summary == NULL) { 241 if (check.summary == NULL) {
240 check.summary = get_subcheck_summary(check); 242 check.summary = get_subcheck_summary(check);
@@ -482,7 +484,7 @@ void mp_print_output(mp_check check) { puts(mp_fmt_output(check)); }
482 */ 484 */
483void mp_exit(mp_check check) { 485void mp_exit(mp_check check) {
484 mp_print_output(check); 486 mp_print_output(check);
485 if (check.format == MP_FORMAT_TEST_JSON) { 487 if (output_format == MP_FORMAT_TEST_JSON) {
486 exit(0); 488 exit(0);
487 } 489 }
488 490
@@ -533,3 +535,7 @@ parsed_output_format mp_parse_output_format(char *format_string) {
533 535
534 return result; 536 return result;
535} 537}
538
539void mp_set_format(mp_output_format format) { output_format = format; }
540
541mp_output_format mp_get_format(void) { return output_format; }
diff --git a/lib/output.h b/lib/output.h
index ffc36f53..2bdfa074 100644
--- a/lib/output.h
+++ b/lib/output.h
@@ -36,13 +36,18 @@ typedef enum output_format {
36#define MP_FORMAT_DEFAULT MP_FORMAT_MULTI_LINE 36#define MP_FORMAT_DEFAULT MP_FORMAT_MULTI_LINE
37 37
38/* 38/*
39 * Format related functions
40 */
41 void mp_set_format(mp_output_format format);
42 mp_output_format mp_get_format(void);
43
44/*
39 * The main state object of a plugin. Exists only ONCE per plugin. 45 * The main state object of a plugin. Exists only ONCE per plugin.
40 * This is the "root" of a tree of singular checks. 46 * This is the "root" of a tree of singular checks.
41 * The final result is always derived from the children and the "worst" state 47 * The final result is always derived from the children and the "worst" state
42 * in the first layer of subchecks 48 * in the first layer of subchecks
43 */ 49 */
44typedef struct { 50typedef struct {
45 mp_output_format format; // The output format
46 char *summary; // Overall summary, if not set a summary will be automatically generated 51 char *summary; // Overall summary, if not set a summary will be automatically generated
47 mp_subcheck_list *subchecks; 52 mp_subcheck_list *subchecks;
48} mp_check; 53} mp_check;
diff --git a/plugins/Makefile.am b/plugins/Makefile.am
index a0e9cabf..d40a0937 100644
--- a/plugins/Makefile.am
+++ b/plugins/Makefile.am
@@ -46,7 +46,14 @@ SUBDIRS = picohttpparser
46 46
47np_test_scripts = tests/test_check_swap.t 47np_test_scripts = tests/test_check_swap.t
48 48
49EXTRA_DIST = t tests $(np_test_scripts) check_swap.d check_dbi.d 49EXTRA_DIST = t \
50 tests \
51 $(np_test_scripts) \
52 check_swap.d \
53 check_game.d \
54 check_dbi.d \
55 check_ssh.d \
56 check_dns.d
50 57
51PLUGINHDRS = common.h 58PLUGINHDRS = common.h
52 59
diff --git a/plugins/check_dns.c b/plugins/check_dns.c
index e1e7c00e..95f33083 100644
--- a/plugins/check_dns.c
+++ b/plugins/check_dns.c
@@ -39,26 +39,22 @@ 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
42static int process_arguments(int /*argc*/, char ** /*argv*/); 42#include "states.h"
43static int validate_arguments(void); 43#include "check_dns.d/config.h"
44static int error_scan(char * /*input_buffer*/, bool *); 44
45typedef struct {
46 int errorcode;
47 check_dns_config config;
48} check_dns_config_wrapper;
49static check_dns_config_wrapper process_arguments(int /*argc*/, char ** /*argv*/);
50static check_dns_config_wrapper validate_arguments(check_dns_config_wrapper /*config_wrapper*/);
51static mp_state_enum error_scan(char * /*input_buffer*/, bool * /*is_nxdomain*/, const char /*dns_server*/[ADDRESS_LENGTH]);
45static bool ip_match_cidr(const char * /*addr*/, const char * /*cidr_ro*/); 52static bool ip_match_cidr(const char * /*addr*/, const char * /*cidr_ro*/);
46static unsigned long ip2long(const char * /*src*/); 53static unsigned long ip2long(const char * /*src*/);
47static void print_help(void); 54static void print_help(void);
48void print_usage(void); 55void print_usage(void);
49 56
50#define ADDRESS_LENGTH 256
51static char query_address[ADDRESS_LENGTH] = "";
52static char dns_server[ADDRESS_LENGTH] = "";
53static char ptr_server[ADDRESS_LENGTH] = "";
54static bool verbose = false; 57static bool verbose = false;
55static char **expected_address = NULL;
56static int expected_address_cnt = 0;
57static bool expect_nxdomain = false;
58
59static bool expect_authority = false;
60static bool all_match = false;
61static thresholds *time_thresholds = NULL;
62 58
63static int qstrcmp(const void *p1, const void *p2) { 59static int qstrcmp(const void *p1, const void *p2) {
64 /* The actual arguments to this function are "pointers to 60 /* The actual arguments to this function are "pointers to
@@ -68,23 +64,6 @@ static int qstrcmp(const void *p1, const void *p2) {
68} 64}
69 65
70int main(int argc, char **argv) { 66int 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, ""); 67 setlocale(LC_ALL, "");
89 bindtextdomain(PACKAGE, LOCALEDIR); 68 bindtextdomain(PACKAGE, LOCALEDIR);
90 textdomain(PACKAGE); 69 textdomain(PACKAGE);
@@ -97,39 +76,65 @@ int main(int argc, char **argv) {
97 /* Parse extra opts if any */ 76 /* Parse extra opts if any */
98 argv = np_extra_opts(&argc, argv, progname); 77 argv = np_extra_opts(&argc, argv, progname);
99 78
100 if (process_arguments(argc, argv) == ERROR) { 79 check_dns_config_wrapper tmp = process_arguments(argc, argv);
80
81 if (tmp.errorcode == ERROR) {
101 usage_va(_("Could not parse arguments")); 82 usage_va(_("Could not parse arguments"));
102 } 83 }
103 84
85 const check_dns_config config = tmp.config;
86
87 char *command_line = NULL;
104 /* get the command to run */ 88 /* get the command to run */
105 xasprintf(&command_line, "%s %s %s", NSLOOKUP_COMMAND, query_address, dns_server); 89 xasprintf(&command_line, "%s %s %s", NSLOOKUP_COMMAND, config.query_address, config.dns_server);
106 90
91 struct timeval tv;
107 alarm(timeout_interval); 92 alarm(timeout_interval);
108 gettimeofday(&tv, NULL); 93 gettimeofday(&tv, NULL);
109 94
110 if (verbose) 95 if (verbose) {
111 printf("%s\n", command_line); 96 printf("%s\n", command_line);
97 }
112 98
99 output chld_out;
100 output chld_err;
101 char *msg = NULL;
102 mp_state_enum result = STATE_UNKNOWN;
113 /* run the command */ 103 /* run the command */
114 if ((np_runcmd(command_line, &chld_out, &chld_err, 0)) != 0) { 104 if ((np_runcmd(command_line, &chld_out, &chld_err, 0)) != 0) {
115 msg = (char *)_("nslookup returned an error status"); 105 msg = (char *)_("nslookup returned an error status");
116 result = STATE_WARNING; 106 result = STATE_WARNING;
117 } 107 }
118 108
119 /* scan stdout */ 109 /* =====
110 * scan stdout, main results get retrieved here
111 * =====
112 */
113 char *address = NULL; /* comma separated str with addrs/ptrs (sorted) */
114 char **addresses = NULL; // All addresses parsed from stdout
115 size_t n_addresses = 0; // counter for retrieved addresses
116 bool non_authoritative = false;
117 bool is_nxdomain = false;
118 bool parse_address = false; /* This flag scans for Address: but only after Name: */
120 for (size_t i = 0; i < chld_out.lines; i++) { 119 for (size_t i = 0; i < chld_out.lines; i++) {
121 if (addresses == NULL) 120 if (addresses == NULL) {
122 addresses = malloc(sizeof(*addresses) * 10); 121 addresses = malloc(sizeof(*addresses) * 10);
123 else if (!(n_addresses % 10)) 122 } else if (!(n_addresses % 10)) {
124 addresses = realloc(addresses, sizeof(*addresses) * (n_addresses + 10)); 123 addresses = realloc(addresses, sizeof(*addresses) * (n_addresses + 10));
124 }
125 125
126 if (verbose) 126 if (verbose) {
127 puts(chld_out.line[i]); 127 puts(chld_out.line[i]);
128 }
128 129
129 if (strcasestr(chld_out.line[i], ".in-addr.arpa") || strcasestr(chld_out.line[i], ".ip6.arpa")) { 130 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 if ((strstr(chld_out.line[i], "canonical name = ") != NULL)) {
132 continue;
133 }
134 char *temp_buffer = NULL;
135 if ((temp_buffer = strstr(chld_out.line[i], "name = "))) {
131 addresses[n_addresses++] = strdup(temp_buffer + 7); 136 addresses[n_addresses++] = strdup(temp_buffer + 7);
132 else { 137 } else {
133 msg = (char *)_("Warning plugin error"); 138 msg = (char *)_("Warning plugin error");
134 result = STATE_WARNING; 139 result = STATE_WARNING;
135 } 140 }
@@ -137,37 +142,47 @@ int main(int argc, char **argv) {
137 142
138 /* bug ID: 2946553 - Older versions of bind will use all available dns 143 /* bug ID: 2946553 - Older versions of bind will use all available dns
139 servers, we have to match the one specified */ 144 servers, we have to match the one specified */
140 if (strstr(chld_out.line[i], "Server:") && strlen(dns_server) > 0) { 145 if (strstr(chld_out.line[i], "Server:") && strlen(config.dns_server) > 0) {
141 temp_buffer = strchr(chld_out.line[i], ':'); 146 char *temp_buffer = strchr(chld_out.line[i], ':');
147 if (temp_buffer == NULL) {
148 die(STATE_UNKNOWN, _("'%s' returned a weirdly formatted Server line\n"), NSLOOKUP_COMMAND);
149 }
150
142 temp_buffer++; 151 temp_buffer++;
143 152
144 /* Strip leading tabs */ 153 /* Strip leading tabs */
145 for (; *temp_buffer != '\0' && *temp_buffer == '\t'; temp_buffer++) 154 for (; *temp_buffer != '\0' && *temp_buffer == '\t'; temp_buffer++) {
146 /* NOOP */; 155 /* NOOP */;
156 }
147 157
148 strip(temp_buffer); 158 strip(temp_buffer);
149 if (temp_buffer == NULL || strlen(temp_buffer) == 0) { 159 if (strlen(temp_buffer) == 0) {
150 die(STATE_CRITICAL, _("DNS CRITICAL - '%s' returned empty server string\n"), NSLOOKUP_COMMAND); 160 die(STATE_CRITICAL, _("DNS CRITICAL - '%s' returned empty server string\n"), NSLOOKUP_COMMAND);
151 } 161 }
152 162
153 if (strcmp(temp_buffer, dns_server) != 0) { 163 if (strcmp(temp_buffer, config.dns_server) != 0) {
154 die(STATE_CRITICAL, _("DNS CRITICAL - No response from DNS %s\n"), dns_server); 164 die(STATE_CRITICAL, _("DNS CRITICAL - No response from DNS %s\n"), config.dns_server);
155 } 165 }
156 } 166 }
157 167
158 /* the server is responding, we just got the host name... */ 168 /* the server is responding, we just got the host name... */
159 if (strstr(chld_out.line[i], "Name:")) 169 if (strstr(chld_out.line[i], "Name:")) {
160 parse_address = true; 170 parse_address = true;
161 else if (parse_address && (strstr(chld_out.line[i], "Address:") || strstr(chld_out.line[i], "Addresses:"))) { 171 } else if (parse_address && (strstr(chld_out.line[i], "Address:") || strstr(chld_out.line[i], "Addresses:"))) {
162 temp_buffer = index(chld_out.line[i], ':'); 172 char *temp_buffer = strchr(chld_out.line[i], ':');
173 if (temp_buffer == NULL) {
174 die(STATE_UNKNOWN, _("'%s' returned a weirdly formatted Address line\n"), NSLOOKUP_COMMAND);
175 }
176
163 temp_buffer++; 177 temp_buffer++;
164 178
165 /* Strip leading spaces */ 179 /* Strip leading spaces */
166 while (*temp_buffer == ' ') 180 while (*temp_buffer == ' ') {
167 temp_buffer++; 181 temp_buffer++;
182 }
168 183
169 strip(temp_buffer); 184 strip(temp_buffer);
170 if (temp_buffer == NULL || strlen(temp_buffer) == 0) { 185 if (strlen(temp_buffer) == 0) {
171 die(STATE_CRITICAL, _("DNS CRITICAL - '%s' returned empty host name string\n"), NSLOOKUP_COMMAND); 186 die(STATE_CRITICAL, _("DNS CRITICAL - '%s' returned empty host name string\n"), NSLOOKUP_COMMAND);
172 } 187 }
173 188
@@ -176,65 +191,71 @@ int main(int argc, char **argv) {
176 non_authoritative = true; 191 non_authoritative = true;
177 } 192 }
178 193
179 result = error_scan(chld_out.line[i], &is_nxdomain); 194 result = error_scan(chld_out.line[i], &is_nxdomain, config.dns_server);
180 if (result != STATE_OK) { 195 if (result != STATE_OK) {
181 msg = strchr(chld_out.line[i], ':'); 196 msg = strchr(chld_out.line[i], ':');
182 if (msg) 197 if (msg) {
183 msg++; 198 msg++;
199 }
184 break; 200 break;
185 } 201 }
186 } 202 }
187 203
204 char input_buffer[MAX_INPUT_BUFFER];
188 /* scan stderr */ 205 /* scan stderr */
189 for (size_t i = 0; i < chld_err.lines; i++) { 206 for (size_t i = 0; i < chld_err.lines; i++) {
190 if (verbose) 207 if (verbose) {
191 puts(chld_err.line[i]); 208 puts(chld_err.line[i]);
209 }
192 210
193 if (error_scan(chld_err.line[i], &is_nxdomain) != STATE_OK) { 211 if (error_scan(chld_err.line[i], &is_nxdomain, config.dns_server) != STATE_OK) {
194 result = max_state(result, error_scan(chld_err.line[i], &is_nxdomain)); 212 result = max_state(result, error_scan(chld_err.line[i], &is_nxdomain, config.dns_server));
195 msg = strchr(input_buffer, ':'); 213 msg = strchr(input_buffer, ':');
196 if (msg) 214 if (msg) {
197 msg++; 215 msg++;
198 else 216 } else {
199 msg = input_buffer; 217 msg = input_buffer;
218 }
200 } 219 }
201 } 220 }
202 221
203 if (is_nxdomain && !expect_nxdomain) { 222 if (is_nxdomain && !config.expect_nxdomain) {
204 die(STATE_CRITICAL, _("Domain '%s' was not found by the server\n"), query_address); 223 die(STATE_CRITICAL, _("Domain '%s' was not found by the server\n"), config.query_address);
205 } 224 }
206 225
207 if (addresses) { 226 if (addresses) {
208 int i; 227 size_t slen = 1;
209 int slen; 228 char *adrp = NULL;
210 char *adrp;
211 qsort(addresses, n_addresses, sizeof(*addresses), qstrcmp); 229 qsort(addresses, n_addresses, sizeof(*addresses), qstrcmp);
212 for (i = 0, slen = 1; i < n_addresses; i++) { 230 for (size_t i = 0; i < n_addresses; i++) {
213 slen += strlen(addresses[i]) + 1; 231 slen += strlen(addresses[i]) + 1;
214 } 232 }
233
234 // Temporary pointer adrp gets moved, address stays on the beginning
215 adrp = address = malloc(slen); 235 adrp = address = malloc(slen);
216 for (i = 0; i < n_addresses; i++) { 236 for (size_t i = 0; i < n_addresses; i++) {
217 if (i) 237 if (i) {
218 *adrp++ = ','; 238 *adrp++ = ',';
239 }
219 strcpy(adrp, addresses[i]); 240 strcpy(adrp, addresses[i]);
220 adrp += strlen(addresses[i]); 241 adrp += strlen(addresses[i]);
221 } 242 }
222 *adrp = 0; 243 *adrp = 0;
223 } else 244 } else {
224 die(STATE_CRITICAL, _("DNS CRITICAL - '%s' msg parsing exited with no address\n"), NSLOOKUP_COMMAND); 245 die(STATE_CRITICAL, _("DNS CRITICAL - '%s' msg parsing exited with no address\n"), NSLOOKUP_COMMAND);
246 }
225 247
226 /* compare to expected address */ 248 /* compare to expected address */
227 if (result == STATE_OK && expected_address_cnt > 0) { 249 if (result == STATE_OK && config.expected_address_cnt > 0) {
228 result = STATE_CRITICAL; 250 result = STATE_CRITICAL;
229 temp_buffer = ""; 251 char *temp_buffer = "";
230 unsigned long expect_match = (1 << expected_address_cnt) - 1; 252 unsigned long expect_match = (1 << config.expected_address_cnt) - 1;
231 unsigned long addr_match = (1 << n_addresses) - 1; 253 unsigned long addr_match = (1 << n_addresses) - 1;
232 254
233 for (int i = 0; i < expected_address_cnt; i++) { 255 for (size_t i = 0; i < config.expected_address_cnt; i++) {
234 int j;
235 /* check if we get a match on 'raw' ip or cidr */ 256 /* check if we get a match on 'raw' ip or cidr */
236 for (j = 0; j < n_addresses; j++) { 257 for (size_t j = 0; j < n_addresses; j++) {
237 if (strcmp(addresses[j], expected_address[i]) == 0 || ip_match_cidr(addresses[j], expected_address[i])) { 258 if (strcmp(addresses[j], config.expected_address[i]) == 0 || ip_match_cidr(addresses[j], config.expected_address[i])) {
238 result = STATE_OK; 259 result = STATE_OK;
239 addr_match &= ~(1 << j); 260 addr_match &= ~(1 << j);
240 expect_match &= ~(1 << i); 261 expect_match &= ~(1 << i);
@@ -242,11 +263,12 @@ int main(int argc, char **argv) {
242 } 263 }
243 264
244 /* prepare an error string */ 265 /* prepare an error string */
245 xasprintf(&temp_buffer, "%s%s; ", temp_buffer, expected_address[i]); 266 xasprintf(&temp_buffer, "%s%s; ", temp_buffer, config.expected_address[i]);
246 } 267 }
247 /* check if expected_address must cover all in addresses and none may be missing */ 268 /* check if expected_address must cover all in addresses and none may be missing */
248 if (all_match && (expect_match != 0 || addr_match != 0)) 269 if (config.all_match && (expect_match != 0 || addr_match != 0)) {
249 result = STATE_CRITICAL; 270 result = STATE_CRITICAL;
271 }
250 if (result == STATE_CRITICAL) { 272 if (result == STATE_CRITICAL) {
251 /* Strip off last semicolon... */ 273 /* Strip off last semicolon... */
252 temp_buffer[strlen(temp_buffer) - 2] = '\0'; 274 temp_buffer[strlen(temp_buffer) - 2] = '\0';
@@ -254,28 +276,29 @@ int main(int argc, char **argv) {
254 } 276 }
255 } 277 }
256 278
257 if (expect_nxdomain) { 279 if (config.expect_nxdomain) {
258 if (!is_nxdomain) { 280 if (!is_nxdomain) {
259 result = STATE_CRITICAL; 281 result = STATE_CRITICAL;
260 xasprintf(&msg, _("Domain '%s' was found by the server: '%s'\n"), query_address, address); 282 xasprintf(&msg, _("Domain '%s' was found by the server: '%s'\n"), config.query_address, address);
261 } else { 283 } else {
262 if (address != NULL) 284 if (address != NULL) {
263 free(address); 285 free(address);
286 }
264 address = "NXDOMAIN"; 287 address = "NXDOMAIN";
265 } 288 }
266 } 289 }
267 290
268 /* check if authoritative */ 291 /* check if authoritative */
269 if (result == STATE_OK && expect_authority && non_authoritative) { 292 if (result == STATE_OK && config.expect_authority && non_authoritative) {
270 result = STATE_CRITICAL; 293 result = STATE_CRITICAL;
271 xasprintf(&msg, _("server %s is not authoritative for %s"), dns_server, query_address); 294 xasprintf(&msg, _("server %s is not authoritative for %s"), config.dns_server, config.query_address);
272 } 295 }
273 296
274 microsec = deltime(tv); 297 long microsec = deltime(tv);
275 elapsed_time = (double)microsec / 1.0e6; 298 double elapsed_time = (double)microsec / 1.0e6;
276 299
277 if (result == STATE_OK) { 300 if (result == STATE_OK) {
278 result = get_status(elapsed_time, time_thresholds); 301 result = get_status(elapsed_time, config.time_thresholds);
279 if (result == STATE_OK) { 302 if (result == STATE_OK) {
280 printf("DNS %s: ", _("OK")); 303 printf("DNS %s: ", _("OK"));
281 } else if (result == STATE_WARNING) { 304 } else if (result == STATE_WARNING) {
@@ -284,24 +307,26 @@ int main(int argc, char **argv) {
284 printf("DNS %s: ", _("CRITICAL")); 307 printf("DNS %s: ", _("CRITICAL"));
285 } 308 }
286 printf(ngettext("%.3f second response time", "%.3f seconds response time", elapsed_time), elapsed_time); 309 printf(ngettext("%.3f second response time", "%.3f seconds response time", elapsed_time), elapsed_time);
287 printf(_(". %s returns %s"), query_address, address); 310 printf(_(". %s returns %s"), config.query_address, address);
288 if ((time_thresholds->warning != NULL) && (time_thresholds->critical != NULL)) { 311 if ((config.time_thresholds->warning != NULL) && (config.time_thresholds->critical != NULL)) {
289 printf("|%s\n", fperfdata("time", elapsed_time, "s", true, time_thresholds->warning->end, true, time_thresholds->critical->end, 312 printf("|%s\n", fperfdata("time", elapsed_time, "s", true, config.time_thresholds->warning->end, true,
290 true, 0, false, 0)); 313 config.time_thresholds->critical->end, true, 0, false, 0));
291 } else if ((time_thresholds->warning == NULL) && (time_thresholds->critical != NULL)) { 314 } else if ((config.time_thresholds->warning == NULL) && (config.time_thresholds->critical != NULL)) {
292 printf("|%s\n", fperfdata("time", elapsed_time, "s", false, 0, true, time_thresholds->critical->end, true, 0, false, 0)); 315 printf("|%s\n", fperfdata("time", elapsed_time, "s", false, 0, true, config.time_thresholds->critical->end, true, 0, false, 0));
293 } else if ((time_thresholds->warning != NULL) && (time_thresholds->critical == NULL)) { 316 } else if ((config.time_thresholds->warning != NULL) && (config.time_thresholds->critical == NULL)) {
294 printf("|%s\n", fperfdata("time", elapsed_time, "s", true, time_thresholds->warning->end, false, 0, true, 0, false, 0)); 317 printf("|%s\n", fperfdata("time", elapsed_time, "s", true, config.time_thresholds->warning->end, false, 0, true, 0, false, 0));
295 } else 318 } else {
296 printf("|%s\n", fperfdata("time", elapsed_time, "s", false, 0, false, 0, true, 0, false, 0)); 319 printf("|%s\n", fperfdata("time", elapsed_time, "s", false, 0, false, 0, true, 0, false, 0));
297 } else if (result == STATE_WARNING) 320 }
321 } else if (result == STATE_WARNING) {
298 printf(_("DNS WARNING - %s\n"), !strcmp(msg, "") ? _(" Probably a non-existent host/domain") : msg); 322 printf(_("DNS WARNING - %s\n"), !strcmp(msg, "") ? _(" Probably a non-existent host/domain") : msg);
299 else if (result == STATE_CRITICAL) 323 } else if (result == STATE_CRITICAL) {
300 printf(_("DNS CRITICAL - %s\n"), !strcmp(msg, "") ? _(" Probably a non-existent host/domain") : msg); 324 printf(_("DNS CRITICAL - %s\n"), !strcmp(msg, "") ? _(" Probably a non-existent host/domain") : msg);
301 else 325 } else {
302 printf(_("DNS UNKNOWN - %s\n"), !strcmp(msg, "") ? _(" Probably a non-existent host/domain") : msg); 326 printf(_("DNS UNKNOWN - %s\n"), !strcmp(msg, "") ? _(" Probably a non-existent host/domain") : msg);
327 }
303 328
304 return result; 329 exit(result);
305} 330}
306 331
307bool ip_match_cidr(const char *addr, const char *cidr_ro) { 332bool ip_match_cidr(const char *addr, const char *cidr_ro) {
@@ -329,64 +354,69 @@ unsigned long ip2long(const char *src) {
329 : 0; 354 : 0;
330} 355}
331 356
332int error_scan(char *input_buffer, bool *is_nxdomain) { 357mp_state_enum error_scan(char *input_buffer, bool *is_nxdomain, const char dns_server[ADDRESS_LENGTH]) {
333 358
334 const int nxdomain = strstr(input_buffer, "Non-existent") || strstr(input_buffer, "** server can't find") || 359 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"); 360 strstr(input_buffer, "** Can't find") || strstr(input_buffer, "NXDOMAIN");
336 if (nxdomain) 361 if (nxdomain) {
337 *is_nxdomain = true; 362 *is_nxdomain = true;
363 }
338 364
339 /* the DNS lookup timed out */ 365 /* the DNS lookup timed out */
340 if (strstr(input_buffer, _("Note: nslookup is deprecated and may be removed from future releases.")) || 366 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")) || 367 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."))) 368 strstr(input_buffer, _("the `-sil[ent]' option to prevent this message from appearing."))) {
343 return STATE_OK; 369 return STATE_OK;
370 }
344 371
345 /* DNS server is not running... */ 372 /* DNS server is not running... */
346 else if (strstr(input_buffer, "No response from server")) 373 else if (strstr(input_buffer, "No response from server")) {
347 die(STATE_CRITICAL, _("No response from DNS %s\n"), dns_server); 374 die(STATE_CRITICAL, _("No response from DNS %s\n"), dns_server);
348 else if (strstr(input_buffer, "no servers could be reached")) 375 } else if (strstr(input_buffer, "no servers could be reached")) {
349 die(STATE_CRITICAL, _("No response from DNS %s\n"), dns_server); 376 die(STATE_CRITICAL, _("No response from DNS %s\n"), dns_server);
377 }
350 378
351 /* Host name is valid, but server doesn't have records... */ 379 /* Host name is valid, but server doesn't have records... */
352 else if (strstr(input_buffer, "No records")) 380 else if (strstr(input_buffer, "No records")) {
353 die(STATE_CRITICAL, _("DNS %s has no records\n"), dns_server); 381 die(STATE_CRITICAL, _("DNS %s has no records\n"), dns_server);
382 }
354 383
355 /* Connection was refused */ 384 /* Connection was refused */
356 else if (strstr(input_buffer, "Connection refused") || strstr(input_buffer, "Couldn't find server") || 385 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"))) 386 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); 387 die(STATE_CRITICAL, _("Connection to DNS %s was refused\n"), dns_server);
388 }
359 389
360 /* Query refused (usually by an ACL in the namserver) */ 390 /* Query refused (usually by an ACL in the namserver) */
361 else if (strstr(input_buffer, "Query refused")) 391 else if (strstr(input_buffer, "Query refused")) {
362 die(STATE_CRITICAL, _("Query was refused by DNS server at %s\n"), dns_server); 392 die(STATE_CRITICAL, _("Query was refused by DNS server at %s\n"), dns_server);
393 }
363 394
364 /* No information (e.g. nameserver IP has two PTR records) */ 395 /* No information (e.g. nameserver IP has two PTR records) */
365 else if (strstr(input_buffer, "No information")) 396 else if (strstr(input_buffer, "No information")) {
366 die(STATE_CRITICAL, _("No information returned by DNS server at %s\n"), dns_server); 397 die(STATE_CRITICAL, _("No information returned by DNS server at %s\n"), dns_server);
398 }
367 399
368 /* Network is unreachable */ 400 /* Network is unreachable */
369 else if (strstr(input_buffer, "Network is unreachable")) 401 else if (strstr(input_buffer, "Network is unreachable")) {
370 die(STATE_CRITICAL, _("Network is unreachable\n")); 402 die(STATE_CRITICAL, _("Network is unreachable\n"));
403 }
371 404
372 /* Internal server failure */ 405 /* Internal server failure */
373 else if (strstr(input_buffer, "Server failure")) 406 else if (strstr(input_buffer, "Server failure")) {
374 die(STATE_CRITICAL, _("DNS failure for %s\n"), dns_server); 407 die(STATE_CRITICAL, _("DNS failure for %s\n"), dns_server);
408 }
375 409
376 /* Request error or the DNS lookup timed out */ 410 /* Request error or the DNS lookup timed out */
377 else if (strstr(input_buffer, "Format error") || strstr(input_buffer, "Timed out")) 411 else if (strstr(input_buffer, "Format error") || strstr(input_buffer, "Timed out")) {
378 return STATE_WARNING; 412 return STATE_WARNING;
413 }
379 414
380 return STATE_OK; 415 return STATE_OK;
381} 416}
382 417
383/* process command-line arguments */ 418/* process command-line arguments */
384int process_arguments(int argc, char **argv) { 419check_dns_config_wrapper process_arguments(int argc, char **argv) {
385 int c;
386 char *warning = NULL;
387 char *critical = NULL;
388
389 int opt_index = 0;
390 static struct option long_opts[] = {{"help", no_argument, 0, 'h'}, 420 static struct option long_opts[] = {{"help", no_argument, 0, 'h'},
391 {"version", no_argument, 0, 'V'}, 421 {"version", no_argument, 0, 'V'},
392 {"verbose", no_argument, 0, 'v'}, 422 {"verbose", no_argument, 0, 'v'},
@@ -402,20 +432,34 @@ int process_arguments(int argc, char **argv) {
402 {"critical", required_argument, 0, 'c'}, 432 {"critical", required_argument, 0, 'c'},
403 {0, 0, 0, 0}}; 433 {0, 0, 0, 0}};
404 434
405 if (argc < 2) 435 check_dns_config_wrapper result = {
406 return ERROR; 436 .config = check_dns_config_init(),
437 .errorcode = OK,
438 };
407 439
408 for (c = 1; c < argc; c++) 440 if (argc < 2) {
409 if (strcmp("-to", argv[c]) == 0) 441 result.errorcode = ERROR;
410 strcpy(argv[c], "-t"); 442 return result;
443 }
411 444
412 while (1) { 445 for (int index = 1; index < argc; index++) {
413 c = getopt_long(argc, argv, "hVvALnt:H:s:r:a:w:c:", long_opts, &opt_index); 446 if (strcmp("-to", argv[index]) == 0) {
447 strcpy(argv[index], "-t");
448 }
449 }
450
451 char *warning = NULL;
452 char *critical = NULL;
453 int opt_index = 0;
454 int index = 0;
455 while (true) {
456 index = getopt_long(argc, argv, "hVvALnt:H:s:r:a:w:c:", long_opts, &opt_index);
414 457
415 if (c == -1 || c == EOF) 458 if (index == -1 || index == EOF) {
416 break; 459 break;
460 }
417 461
418 switch (c) { 462 switch (index) {
419 case 'h': /* help */ 463 case 'h': /* help */
420 print_help(); 464 print_help();
421 exit(STATE_UNKNOWN); 465 exit(STATE_UNKNOWN);
@@ -429,54 +473,63 @@ int process_arguments(int argc, char **argv) {
429 timeout_interval = atoi(optarg); 473 timeout_interval = atoi(optarg);
430 break; 474 break;
431 case 'H': /* hostname */ 475 case 'H': /* hostname */
432 if (strlen(optarg) >= ADDRESS_LENGTH) 476 if (strlen(optarg) >= ADDRESS_LENGTH) {
433 die(STATE_UNKNOWN, _("Input buffer overflow\n")); 477 die(STATE_UNKNOWN, _("Input buffer overflow\n"));
434 strcpy(query_address, optarg); 478 }
479 strcpy(result.config.query_address, optarg);
435 break; 480 break;
436 case 's': /* server name */ 481 case 's': /* server name */
437 /* TODO: this host_or_die check is probably unnecessary. 482 /* TODO: this host_or_die check is probably unnecessary.
438 * Better to confirm nslookup response matches */ 483 * Better to confirm nslookup response matches */
439 host_or_die(optarg); 484 host_or_die(optarg);
440 if (strlen(optarg) >= ADDRESS_LENGTH) 485 if (strlen(optarg) >= ADDRESS_LENGTH) {
441 die(STATE_UNKNOWN, _("Input buffer overflow\n")); 486 die(STATE_UNKNOWN, _("Input buffer overflow\n"));
442 strcpy(dns_server, optarg); 487 }
488 strcpy(result.config.dns_server, optarg);
443 break; 489 break;
444 case 'r': /* reverse server name */ 490 case 'r': /* reverse server name */
445 /* TODO: Is this host_or_die necessary? */ 491 /* TODO: Is this host_or_die necessary? */
492 // TODO This does not do anything!!! 2025-03-08 rincewind
446 host_or_die(optarg); 493 host_or_die(optarg);
447 if (strlen(optarg) >= ADDRESS_LENGTH) 494 if (strlen(optarg) >= ADDRESS_LENGTH) {
448 die(STATE_UNKNOWN, _("Input buffer overflow\n")); 495 die(STATE_UNKNOWN, _("Input buffer overflow\n"));
496 }
497 static char ptr_server[ADDRESS_LENGTH] = "";
449 strcpy(ptr_server, optarg); 498 strcpy(ptr_server, optarg);
450 break; 499 break;
451 case 'a': /* expected address */ 500 case 'a': /* expected address */
452 if (strlen(optarg) >= ADDRESS_LENGTH) 501 if (strlen(optarg) >= ADDRESS_LENGTH) {
453 die(STATE_UNKNOWN, _("Input buffer overflow\n")); 502 die(STATE_UNKNOWN, _("Input buffer overflow\n"));
503 }
454 if (strchr(optarg, ',') != NULL) { 504 if (strchr(optarg, ',') != NULL) {
455 char *comma = strchr(optarg, ','); 505 char *comma = strchr(optarg, ',');
456 while (comma != NULL) { 506 while (comma != NULL) {
457 expected_address = (char **)realloc(expected_address, (expected_address_cnt + 1) * sizeof(char **)); 507 result.config.expected_address =
458 expected_address[expected_address_cnt] = strndup(optarg, comma - optarg); 508 (char **)realloc(result.config.expected_address, (result.config.expected_address_cnt + 1) * sizeof(char **));
459 expected_address_cnt++; 509 result.config.expected_address[result.config.expected_address_cnt] = strndup(optarg, comma - optarg);
510 result.config.expected_address_cnt++;
460 optarg = comma + 1; 511 optarg = comma + 1;
461 comma = strchr(optarg, ','); 512 comma = strchr(optarg, ',');
462 } 513 }
463 expected_address = (char **)realloc(expected_address, (expected_address_cnt + 1) * sizeof(char **)); 514 result.config.expected_address =
464 expected_address[expected_address_cnt] = strdup(optarg); 515 (char **)realloc(result.config.expected_address, (result.config.expected_address_cnt + 1) * sizeof(char **));
465 expected_address_cnt++; 516 result.config.expected_address[result.config.expected_address_cnt] = strdup(optarg);
517 result.config.expected_address_cnt++;
466 } else { 518 } else {
467 expected_address = (char **)realloc(expected_address, (expected_address_cnt + 1) * sizeof(char **)); 519 result.config.expected_address =
468 expected_address[expected_address_cnt] = strdup(optarg); 520 (char **)realloc(result.config.expected_address, (result.config.expected_address_cnt + 1) * sizeof(char **));
469 expected_address_cnt++; 521 result.config.expected_address[result.config.expected_address_cnt] = strdup(optarg);
522 result.config.expected_address_cnt++;
470 } 523 }
471 break; 524 break;
472 case 'n': /* expect NXDOMAIN */ 525 case 'n': /* expect NXDOMAIN */
473 expect_nxdomain = true; 526 result.config.expect_nxdomain = true;
474 break; 527 break;
475 case 'A': /* expect authority */ 528 case 'A': /* expect authority */
476 expect_authority = true; 529 result.config.expect_authority = true;
477 break; 530 break;
478 case 'L': /* all must match */ 531 case 'L': /* all must match */
479 all_match = true; 532 result.config.all_match = true;
480 break; 533 break;
481 case 'w': 534 case 'w':
482 warning = optarg; 535 warning = optarg;
@@ -489,38 +542,42 @@ int process_arguments(int argc, char **argv) {
489 } 542 }
490 } 543 }
491 544
492 c = optind; 545 index = optind;
493 if (strlen(query_address) == 0 && c < argc) { 546 if (strlen(result.config.query_address) == 0 && index < argc) {
494 if (strlen(argv[c]) >= ADDRESS_LENGTH) 547 if (strlen(argv[index]) >= ADDRESS_LENGTH) {
495 die(STATE_UNKNOWN, _("Input buffer overflow\n")); 548 die(STATE_UNKNOWN, _("Input buffer overflow\n"));
496 strcpy(query_address, argv[c++]); 549 }
550 strcpy(result.config.query_address, argv[index++]);
497 } 551 }
498 552
499 if (strlen(dns_server) == 0 && c < argc) { 553 if (strlen(result.config.dns_server) == 0 && index < argc) {
500 /* TODO: See -s option */ 554 /* TODO: See -s option */
501 host_or_die(argv[c]); 555 host_or_die(argv[index]);
502 if (strlen(argv[c]) >= ADDRESS_LENGTH) 556 if (strlen(argv[index]) >= ADDRESS_LENGTH) {
503 die(STATE_UNKNOWN, _("Input buffer overflow\n")); 557 die(STATE_UNKNOWN, _("Input buffer overflow\n"));
504 strcpy(dns_server, argv[c++]); 558 }
559 strcpy(result.config.dns_server, argv[index++]);
505 } 560 }
506 561
507 set_thresholds(&time_thresholds, warning, critical); 562 set_thresholds(&result.config.time_thresholds, warning, critical);
508 563
509 return validate_arguments(); 564 return validate_arguments(result);
510} 565}
511 566
512int validate_arguments(void) { 567check_dns_config_wrapper validate_arguments(check_dns_config_wrapper config_wrapper) {
513 if (query_address[0] == 0) { 568 if (config_wrapper.config.query_address[0] == 0) {
514 printf("missing --host argument\n"); 569 printf("missing --host argument\n");
515 return ERROR; 570 config_wrapper.errorcode = ERROR;
571 return config_wrapper;
516 } 572 }
517 573
518 if (expected_address_cnt > 0 && expect_nxdomain) { 574 if (config_wrapper.config.expected_address_cnt > 0 && config_wrapper.config.expect_nxdomain) {
519 printf("--expected-address and --expect-nxdomain cannot be combined\n"); 575 printf("--expected-address and --expect-nxdomain cannot be combined\n");
520 return ERROR; 576 config_wrapper.errorcode = ERROR;
577 return config_wrapper;
521 } 578 }
522 579
523 return OK; 580 return config_wrapper;
524} 581}
525 582
526void print_help(void) { 583void print_help(void) {
diff --git a/plugins/check_dns.d/config.h b/plugins/check_dns.d/config.h
new file mode 100644
index 00000000..9ec4eb82
--- /dev/null
+++ b/plugins/check_dns.d/config.h
@@ -0,0 +1,34 @@
1#pragma once
2
3#include "../../config.h"
4#include "thresholds.h"
5#include <stddef.h>
6
7#define ADDRESS_LENGTH 256
8
9typedef struct {
10 bool all_match;
11 char dns_server[ADDRESS_LENGTH];
12 char query_address[ADDRESS_LENGTH];
13 bool expect_nxdomain;
14 bool expect_authority;
15 char **expected_address;
16 size_t expected_address_cnt;
17
18 thresholds *time_thresholds;
19} check_dns_config;
20
21check_dns_config check_dns_config_init() {
22 check_dns_config tmp = {
23 .all_match = false,
24 .dns_server = "",
25 .query_address = "",
26 .expect_nxdomain = false,
27 .expect_authority = false,
28 .expected_address = NULL,
29 .expected_address_cnt = 0,
30
31 .time_thresholds = NULL,
32 };
33 return tmp;
34}
diff --git a/plugins/check_game.c b/plugins/check_game.c
index 619277e7..c0193b03 100644
--- a/plugins/check_game.c
+++ b/plugins/check_game.c
@@ -36,9 +36,15 @@ const char *email = "devel@monitoring-plugins.org";
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#include "check_game.d/config.h"
40#include "../lib/monitoringplug.h"
39 41
40static int process_arguments(int /*argc*/, char ** /*argv*/); 42typedef struct {
41static int validate_arguments(void); 43 int errorcode;
44 check_game_config config;
45} check_game_config_wrapper;
46
47static check_game_config_wrapper process_arguments(int /*argc*/, char ** /*argv*/);
42static void print_help(void); 48static void print_help(void);
43void print_usage(void); 49void print_usage(void);
44 50
@@ -49,26 +55,9 @@ void print_usage(void);
49#define QSTAT_HOST_TIMEOUT "TIMEOUT" 55#define QSTAT_HOST_TIMEOUT "TIMEOUT"
50#define QSTAT_MAX_RETURN_ARGS 12 56#define QSTAT_MAX_RETURN_ARGS 12
51 57
52static char *server_ip;
53static char *game_type;
54static int port = 0;
55
56static bool verbose = false; 58static bool verbose = false;
57 59
58static int qstat_game_players_max = -1;
59static int qstat_game_players = -1;
60static int qstat_game_field = -1;
61static int qstat_map_field = -1;
62static int qstat_ping_field = -1;
63
64int main(int argc, char **argv) { 60int main(int argc, char **argv) {
65 char *command_line;
66 int result = STATE_UNKNOWN;
67 char *p;
68 char *ret[QSTAT_MAX_RETURN_ARGS];
69 size_t i = 0;
70 output chld_out;
71
72 setlocale(LC_ALL, ""); 61 setlocale(LC_ALL, "");
73 bindtextdomain(PACKAGE, LOCALEDIR); 62 bindtextdomain(PACKAGE, LOCALEDIR);
74 textdomain(PACKAGE); 63 textdomain(PACKAGE);
@@ -76,22 +65,31 @@ int main(int argc, char **argv) {
76 /* Parse extra opts if any */ 65 /* Parse extra opts if any */
77 argv = np_extra_opts(&argc, argv, progname); 66 argv = np_extra_opts(&argc, argv, progname);
78 67
79 if (process_arguments(argc, argv) == ERROR) 68 check_game_config_wrapper tmp = process_arguments(argc, argv);
69
70 if (tmp.errorcode == ERROR) {
80 usage_va(_("Could not parse arguments")); 71 usage_va(_("Could not parse arguments"));
72 }
73
74 check_game_config config = tmp.config;
81 75
82 result = STATE_OK; 76 mp_state_enum result = STATE_OK;
83 77
84 /* create the command line to execute */ 78 /* create the command line to execute */
85 xasprintf(&command_line, "%s -raw %s -%s %s", PATH_TO_QSTAT, QSTAT_DATA_DELIMITER, game_type, server_ip); 79 char *command_line = NULL;
80 xasprintf(&command_line, "%s -raw %s -%s %s", PATH_TO_QSTAT, QSTAT_DATA_DELIMITER, config.game_type, config.server_ip);
86 81
87 if (port) 82 if (config.port) {
88 xasprintf(&command_line, "%s:%-d", command_line, port); 83 xasprintf(&command_line, "%s:%-d", command_line, config.port);
84 }
89 85
90 if (verbose) 86 if (verbose) {
91 printf("%s\n", command_line); 87 printf("%s\n", command_line);
88 }
92 89
93 /* run the command. historically, this plugin ignores output on stderr, 90 /* run the command. historically, this plugin ignores output on stderr,
94 * as well as return status of the qstat program */ 91 * as well as return status of the qstat program */
92 output chld_out = {};
95 (void)np_runcmd(command_line, &chld_out, NULL, 0); 93 (void)np_runcmd(command_line, &chld_out, NULL, 0);
96 94
97 /* sanity check */ 95 /* sanity check */
@@ -104,19 +102,22 @@ int main(int argc, char **argv) {
104 In the end, I figured I'd simply let an error occur & then trap it 102 In the end, I figured I'd simply let an error occur & then trap it
105 */ 103 */
106 104
107 if (!strncmp(chld_out.line[0], "unknown option", 14)) { 105 if (!strncmp(chld_out.line[0], "unknown option", strlen("unknown option"))) {
108 printf(_("CRITICAL - Host type parameter incorrect!\n")); 106 printf(_("CRITICAL - Host type parameter incorrect!\n"));
109 result = STATE_CRITICAL; 107 result = STATE_CRITICAL;
110 return result; 108 exit(result);
111 } 109 }
112 110
113 p = (char *)strtok(chld_out.line[0], QSTAT_DATA_DELIMITER); 111 char *ret[QSTAT_MAX_RETURN_ARGS];
114 while (p != NULL) { 112 size_t i = 0;
115 ret[i] = p; 113 char *sequence = strtok(chld_out.line[0], QSTAT_DATA_DELIMITER);
116 p = (char *)strtok(NULL, QSTAT_DATA_DELIMITER); 114 while (sequence != NULL) {
115 ret[i] = sequence;
116 sequence = strtok(NULL, QSTAT_DATA_DELIMITER);
117 i++; 117 i++;
118 if (i >= QSTAT_MAX_RETURN_ARGS) 118 if (i >= QSTAT_MAX_RETURN_ARGS) {
119 break; 119 break;
120 }
120 } 121 }
121 122
122 if (strstr(ret[2], QSTAT_HOST_ERROR)) { 123 if (strstr(ret[2], QSTAT_HOST_ERROR)) {
@@ -129,19 +130,20 @@ int main(int argc, char **argv) {
129 printf(_("CRITICAL - Game server timeout\n")); 130 printf(_("CRITICAL - Game server timeout\n"));
130 result = STATE_CRITICAL; 131 result = STATE_CRITICAL;
131 } else { 132 } else {
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 printf("OK: %s/%s %s (%s), Ping: %s ms|%s %s\n", ret[config.qstat_game_players], ret[config.qstat_game_players_max],
133 ret[qstat_map_field], ret[qstat_ping_field], 134 ret[config.qstat_game_field], ret[config.qstat_map_field], ret[config.qstat_ping_field],
134 perfdata("players", atol(ret[qstat_game_players]), "", false, 0, false, 0, true, 0, true, atol(ret[qstat_game_players_max])), 135 perfdata("players", atol(ret[config.qstat_game_players]), "", false, 0, false, 0, true, 0, true,
135 fperfdata("ping", strtod(ret[qstat_ping_field], NULL), "", false, 0, false, 0, true, 0, false, 0)); 136 atol(ret[config.qstat_game_players_max])),
137 fperfdata("ping", strtod(ret[config.qstat_ping_field], NULL), "", false, 0, false, 0, true, 0, false, 0));
136 } 138 }
137 139
138 return result; 140 exit(result);
139} 141}
140 142
141int process_arguments(int argc, char **argv) { 143#define players_field_index 129
142 int c; 144#define max_players_field_index 130
143 145
144 int opt_index = 0; 146check_game_config_wrapper process_arguments(int argc, char **argv) {
145 static struct option long_opts[] = {{"help", no_argument, 0, 'h'}, 147 static struct option long_opts[] = {{"help", no_argument, 0, 'h'},
146 {"version", no_argument, 0, 'V'}, 148 {"version", no_argument, 0, 'V'},
147 {"verbose", no_argument, 0, 'v'}, 149 {"verbose", no_argument, 0, 'v'},
@@ -152,29 +154,39 @@ int process_arguments(int argc, char **argv) {
152 {"map-field", required_argument, 0, 'm'}, 154 {"map-field", required_argument, 0, 'm'},
153 {"ping-field", required_argument, 0, 'p'}, 155 {"ping-field", required_argument, 0, 'p'},
154 {"game-field", required_argument, 0, 'g'}, 156 {"game-field", required_argument, 0, 'g'},
155 {"players-field", required_argument, 0, 129}, 157 {"players-field", required_argument, 0, players_field_index},
156 {"max-players-field", required_argument, 0, 130}, 158 {"max-players-field", required_argument, 0, max_players_field_index},
157 {0, 0, 0, 0}}; 159 {0, 0, 0, 0}};
158 160
159 if (argc < 2) 161 check_game_config_wrapper result = {
160 return ERROR; 162 .config = check_game_config_init(),
163 .errorcode = OK,
164 };
165
166 if (argc < 2) {
167 result.errorcode = ERROR;
168 return result;
169 }
161 170
162 for (c = 1; c < argc; c++) { 171 for (int option_counter = 1; option_counter < argc; option_counter++) {
163 if (strcmp("-mf", argv[c]) == 0) 172 if (strcmp("-mf", argv[option_counter]) == 0) {
164 strcpy(argv[c], "-m"); 173 strcpy(argv[option_counter], "-m");
165 else if (strcmp("-pf", argv[c]) == 0) 174 } else if (strcmp("-pf", argv[option_counter]) == 0) {
166 strcpy(argv[c], "-p"); 175 strcpy(argv[option_counter], "-p");
167 else if (strcmp("-gf", argv[c]) == 0) 176 } else if (strcmp("-gf", argv[option_counter]) == 0) {
168 strcpy(argv[c], "-g"); 177 strcpy(argv[option_counter], "-g");
178 }
169 } 179 }
170 180
171 while (1) { 181 int opt_index = 0;
172 c = getopt_long(argc, argv, "hVvt:H:P:G:g:p:m:", long_opts, &opt_index); 182 while (true) {
183 int option_index = getopt_long(argc, argv, "hVvt:H:P:G:g:p:m:", long_opts, &opt_index);
173 184
174 if (c == -1 || c == EOF) 185 if (option_index == -1 || option_index == EOF) {
175 break; 186 break;
187 }
176 188
177 switch (c) { 189 switch (option_index) {
178 case 'h': /* help */ 190 case 'h': /* help */
179 print_help(); 191 print_help();
180 exit(STATE_UNKNOWN); 192 exit(STATE_UNKNOWN);
@@ -188,79 +200,75 @@ int process_arguments(int argc, char **argv) {
188 timeout_interval = atoi(optarg); 200 timeout_interval = atoi(optarg);
189 break; 201 break;
190 case 'H': /* hostname */ 202 case 'H': /* hostname */
191 if (strlen(optarg) >= MAX_HOST_ADDRESS_LENGTH) 203 if (strlen(optarg) >= MAX_HOST_ADDRESS_LENGTH) {
192 die(STATE_UNKNOWN, _("Input buffer overflow\n")); 204 die(STATE_UNKNOWN, _("Input buffer overflow\n"));
193 server_ip = optarg; 205 }
206 result.config.server_ip = optarg;
194 break; 207 break;
195 case 'P': /* port */ 208 case 'P': /* port */
196 port = atoi(optarg); 209 result.config.port = atoi(optarg);
197 break; 210 break;
198 case 'G': /* hostname */ 211 case 'G': /* hostname */
199 if (strlen(optarg) >= MAX_INPUT_BUFFER) 212 if (strlen(optarg) >= MAX_INPUT_BUFFER) {
200 die(STATE_UNKNOWN, _("Input buffer overflow\n")); 213 die(STATE_UNKNOWN, _("Input buffer overflow\n"));
201 game_type = optarg; 214 }
215 result.config.game_type = optarg;
202 break; 216 break;
203 case 'p': /* index of ping field */ 217 case 'p': /* index of ping field */
204 qstat_ping_field = atoi(optarg); 218 result.config.qstat_ping_field = atoi(optarg);
205 if (qstat_ping_field < 0 || qstat_ping_field > QSTAT_MAX_RETURN_ARGS) 219 if (result.config.qstat_ping_field < 0 || result.config.qstat_ping_field > QSTAT_MAX_RETURN_ARGS) {
206 return ERROR; 220 result.errorcode = ERROR;
221 return result;
222 }
207 break; 223 break;
208 case 'm': /* index on map field */ 224 case 'm': /* index on map field */
209 qstat_map_field = atoi(optarg); 225 result.config.qstat_map_field = atoi(optarg);
210 if (qstat_map_field < 0 || qstat_map_field > QSTAT_MAX_RETURN_ARGS) 226 if (result.config.qstat_map_field < 0 || result.config.qstat_map_field > QSTAT_MAX_RETURN_ARGS) {
211 return ERROR; 227 result.errorcode = ERROR;
228 return result;
229 }
212 break; 230 break;
213 case 'g': /* index of game field */ 231 case 'g': /* index of game field */
214 qstat_game_field = atoi(optarg); 232 result.config.qstat_game_field = atoi(optarg);
215 if (qstat_game_field < 0 || qstat_game_field > QSTAT_MAX_RETURN_ARGS) 233 if (result.config.qstat_game_field < 0 || result.config.qstat_game_field > QSTAT_MAX_RETURN_ARGS) {
216 return ERROR; 234 result.errorcode = ERROR;
235 return result;
236 }
217 break; 237 break;
218 case 129: /* index of player count field */ 238 case players_field_index: /* index of player count field */
219 qstat_game_players = atoi(optarg); 239 result.config.qstat_game_players = atoi(optarg);
220 if (qstat_game_players_max == 0) 240 if (result.config.qstat_game_players_max == 0) {
221 qstat_game_players_max = qstat_game_players - 1; 241 result.config.qstat_game_players_max = result.config.qstat_game_players - 1;
222 if (qstat_game_players < 0 || qstat_game_players > QSTAT_MAX_RETURN_ARGS) 242 }
223 return ERROR; 243 if (result.config.qstat_game_players < 0 || result.config.qstat_game_players > QSTAT_MAX_RETURN_ARGS) {
244 result.errorcode = ERROR;
245 return result;
246 }
224 break; 247 break;
225 case 130: /* index of max players field */ 248 case max_players_field_index: /* index of max players field */
226 qstat_game_players_max = atoi(optarg); 249 result.config.qstat_game_players_max = atoi(optarg);
227 if (qstat_game_players_max < 0 || qstat_game_players_max > QSTAT_MAX_RETURN_ARGS) 250 if (result.config.qstat_game_players_max < 0 || result.config.qstat_game_players_max > QSTAT_MAX_RETURN_ARGS) {
228 return ERROR; 251 result.errorcode = ERROR;
252 return result;
253 }
229 break; 254 break;
230 default: /* args not parsable */ 255 default: /* args not parsable */
231 usage5(); 256 usage5();
232 } 257 }
233 } 258 }
234 259
235 c = optind; 260 int option_counter = optind;
236 /* first option is the game type */ 261 /* first option is the game type */
237 if (!game_type && c < argc) 262 if (!result.config.game_type && option_counter < argc) {
238 game_type = strdup(argv[c++]); 263 result.config.game_type = strdup(argv[option_counter++]);
264 }
239 265
240 /* Second option is the server name */ 266 /* Second option is the server name */
241 if (!server_ip && c < argc) 267 if (!result.config.server_ip && option_counter < argc) {
242 server_ip = strdup(argv[c++]); 268 result.config.server_ip = strdup(argv[option_counter++]);
243 269 }
244 return validate_arguments();
245}
246
247int validate_arguments(void) {
248 if (qstat_game_players_max < 0)
249 qstat_game_players_max = 4;
250
251 if (qstat_game_players < 0)
252 qstat_game_players = 5;
253
254 if (qstat_game_field < 0)
255 qstat_game_field = 2;
256
257 if (qstat_map_field < 0)
258 qstat_map_field = 3;
259
260 if (qstat_ping_field < 0)
261 qstat_ping_field = 5;
262 270
263 return OK; 271 return result;
264} 272}
265 273
266void print_help(void) { 274void print_help(void) {
@@ -277,14 +285,15 @@ void print_help(void) {
277 285
278 printf(UT_HELP_VRSN); 286 printf(UT_HELP_VRSN);
279 printf(UT_EXTRA_OPTS); 287 printf(UT_EXTRA_OPTS);
280 288 printf(" -H, --hostname=ADDRESS\n"
281 printf(" %s\n", "-p"); 289 " Host name, IP Address, or unix socket (must be an absolute path)\n");
282 printf(" %s\n", _("Optional port of which to connect")); 290 printf(" %s\n", "-P");
283 printf(" %s\n", "gf"); 291 printf(" %s\n", _("Optional port to connect to"));
292 printf(" %s\n", "-g");
284 printf(" %s\n", _("Field number in raw qstat output that contains game name")); 293 printf(" %s\n", _("Field number in raw qstat output that contains game name"));
285 printf(" %s\n", "-mf"); 294 printf(" %s\n", "-m");
286 printf(" %s\n", _("Field number in raw qstat output that contains map name")); 295 printf(" %s\n", _("Field number in raw qstat output that contains map name"));
287 printf(" %s\n", "-pf"); 296 printf(" %s\n", "-p");
288 printf(" %s\n", _("Field number in raw qstat output that contains ping time")); 297 printf(" %s\n", _("Field number in raw qstat output that contains ping time"));
289 298
290 printf(UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); 299 printf(UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
diff --git a/plugins/check_game.d/config.h b/plugins/check_game.d/config.h
new file mode 100644
index 00000000..c95a1ced
--- /dev/null
+++ b/plugins/check_game.d/config.h
@@ -0,0 +1,30 @@
1#pragma once
2#include "../../config.h"
3#include <stddef.h>
4
5typedef struct {
6 char *server_ip;
7 char *game_type;
8 int port;
9
10 int qstat_game_players_max;
11 int qstat_game_players;
12 int qstat_game_field;
13 int qstat_map_field;
14 int qstat_ping_field;
15} check_game_config;
16
17check_game_config check_game_config_init() {
18 check_game_config tmp = {
19 .server_ip = NULL,
20 .game_type = NULL,
21 .port = 0,
22
23 .qstat_game_players_max = 4,
24 .qstat_game_players = 5,
25 .qstat_map_field = 3,
26 .qstat_game_field = 2,
27 .qstat_ping_field = 5,
28 };
29 return tmp;
30}
diff --git a/plugins/check_ssh.c b/plugins/check_ssh.c
index 42a88cf9..9d0d7cde 100644
--- a/plugins/check_ssh.c
+++ b/plugins/check_ssh.c
@@ -28,6 +28,9 @@
28 * 28 *
29 *****************************************************************************/ 29 *****************************************************************************/
30 30
31#include "output.h"
32#include "perfdata.h"
33#include "states.h"
31const char *progname = "check_ssh"; 34const char *progname = "check_ssh";
32const char *copyright = "2000-2024"; 35const char *copyright = "2000-2024";
33const char *email = "devel@monitoring-plugins.org"; 36const char *email = "devel@monitoring-plugins.org";
@@ -35,26 +38,26 @@ const char *email = "devel@monitoring-plugins.org";
35#include "./common.h" 38#include "./common.h"
36#include "./netutils.h" 39#include "./netutils.h"
37#include "utils.h" 40#include "utils.h"
41#include "./check_ssh.d/config.h"
38 42
39#ifndef MSG_DONTWAIT 43#ifndef MSG_DONTWAIT
40# define MSG_DONTWAIT 0 44# define MSG_DONTWAIT 0
41#endif 45#endif
42 46
43#define SSH_DFL_PORT 22 47#define BUFF_SZ 256
44#define BUFF_SZ 256
45 48
46static int port = -1;
47static char *server_name = NULL;
48static char *remote_version = NULL;
49static char *remote_protocol = NULL;
50static bool verbose = false; 49static bool verbose = false;
51 50
52static int process_arguments(int /*argc*/, char ** /*argv*/); 51typedef struct process_arguments_wrapper {
53static int validate_arguments(void); 52 int errorcode;
53 check_ssh_config config;
54} process_arguments_wrapper;
55
56static process_arguments_wrapper process_arguments(int /*argc*/, char ** /*argv*/);
54static void print_help(void); 57static void print_help(void);
55void print_usage(void); 58void print_usage(void);
56 59
57static int ssh_connect(char *haddr, int hport, char *remote_version, char *remote_protocol); 60static int ssh_connect(mp_check *overall, char *haddr, int hport, char *remote_version, char *remote_protocol);
58 61
59int main(int argc, char **argv) { 62int main(int argc, char **argv) {
60 setlocale(LC_ALL, ""); 63 setlocale(LC_ALL, "");
@@ -64,24 +67,35 @@ int main(int argc, char **argv) {
64 /* Parse extra opts if any */ 67 /* Parse extra opts if any */
65 argv = np_extra_opts(&argc, argv, progname); 68 argv = np_extra_opts(&argc, argv, progname);
66 69
67 if (process_arguments(argc, argv) == ERROR) 70 process_arguments_wrapper tmp_config = process_arguments(argc, argv);
71
72 if (tmp_config.errorcode == ERROR) {
68 usage4(_("Could not parse arguments")); 73 usage4(_("Could not parse arguments"));
74 }
75
76 check_ssh_config config = tmp_config.config;
77
78 mp_check overall = mp_check_init();
79 if (config.output_format_is_set) {
80 mp_set_format(config.output_format);
81 }
69 82
70 /* initialize alarm signal handling */ 83 /* initialize alarm signal handling */
71 signal(SIGALRM, socket_timeout_alarm_handler); 84 signal(SIGALRM, socket_timeout_alarm_handler);
72
73 alarm(socket_timeout); 85 alarm(socket_timeout);
74 86
75 /* ssh_connect exits if error is found */ 87 /* ssh_connect exits if error is found */
76 int result = ssh_connect(server_name, port, remote_version, remote_protocol); 88 ssh_connect(&overall, config.server_name, config.port, config.remote_version, config.remote_protocol);
77 89
78 alarm(0); 90 alarm(0);
79 91
80 return (result); 92 mp_exit(overall);
81} 93}
82 94
95#define output_format_index CHAR_MAX + 1
96
83/* process command-line arguments */ 97/* process command-line arguments */
84int process_arguments(int argc, char **argv) { 98process_arguments_wrapper process_arguments(int argc, char **argv) {
85 static struct option longopts[] = {{"help", no_argument, 0, 'h'}, 99 static struct option longopts[] = {{"help", no_argument, 0, 'h'},
86 {"version", no_argument, 0, 'V'}, 100 {"version", no_argument, 0, 'V'},
87 {"host", required_argument, 0, 'H'}, /* backward compatibility */ 101 {"host", required_argument, 0, 'H'}, /* backward compatibility */
@@ -93,22 +107,33 @@ int process_arguments(int argc, char **argv) {
93 {"verbose", no_argument, 0, 'v'}, 107 {"verbose", no_argument, 0, 'v'},
94 {"remote-version", required_argument, 0, 'r'}, 108 {"remote-version", required_argument, 0, 'r'},
95 {"remote-protocol", required_argument, 0, 'P'}, 109 {"remote-protocol", required_argument, 0, 'P'},
110 {"output-format", required_argument, 0, output_format_index},
96 {0, 0, 0, 0}}; 111 {0, 0, 0, 0}};
97 112
98 if (argc < 2) 113 process_arguments_wrapper result = {
99 return ERROR; 114 .config = check_ssh_config_init(),
115 .errorcode = OK,
116 };
117
118 if (argc < 2) {
119 result.errorcode = ERROR;
120 return result;
121 }
100 122
101 for (int i = 1; i < argc; i++) 123 for (int i = 1; i < argc; i++) {
102 if (strcmp("-to", argv[i]) == 0) 124 if (strcmp("-to", argv[i]) == 0) {
103 strcpy(argv[i], "-t"); 125 strcpy(argv[i], "-t");
126 }
127 }
104 128
105 int option_char; 129 int option_char;
106 while (true) { 130 while (true) {
107 int option = 0; 131 int option = 0;
108 option_char = getopt_long(argc, argv, "+Vhv46t:r:H:p:P:", longopts, &option); 132 option_char = getopt_long(argc, argv, "+Vhv46t:r:H:p:P:", longopts, &option);
109 133
110 if (option_char == -1 || option_char == EOF) 134 if (option_char == -1 || option_char == EOF) {
111 break; 135 break;
136 }
112 137
113 switch (option_char) { 138 switch (option_char) {
114 case '?': /* help */ 139 case '?': /* help */
@@ -123,10 +148,11 @@ int process_arguments(int argc, char **argv) {
123 verbose = true; 148 verbose = true;
124 break; 149 break;
125 case 't': /* timeout period */ 150 case 't': /* timeout period */
126 if (!is_integer(optarg)) 151 if (!is_intpos(optarg)) {
127 usage2(_("Timeout interval must be a positive integer"), optarg); 152 usage2(_("Timeout interval must be a positive integer"), optarg);
128 else 153 } else {
129 socket_timeout = atoi(optarg); 154 socket_timeout = (unsigned int)atoi(optarg);
155 }
130 break; 156 break;
131 case '4': 157 case '4':
132 address_family = AF_INET; 158 address_family = AF_INET;
@@ -139,50 +165,61 @@ int process_arguments(int argc, char **argv) {
139#endif 165#endif
140 break; 166 break;
141 case 'r': /* remote version */ 167 case 'r': /* remote version */
142 remote_version = optarg; 168 result.config.remote_version = optarg;
143 break; 169 break;
144 case 'P': /* remote version */ 170 case 'P': /* remote version */
145 remote_protocol = optarg; 171 result.config.remote_protocol = optarg;
146 break; 172 break;
147 case 'H': /* host */ 173 case 'H': /* host */
148 if (!is_host(optarg)) 174 if (!is_host(optarg)) {
149 usage2(_("Invalid hostname/address"), optarg); 175 usage2(_("Invalid hostname/address"), optarg);
150 server_name = optarg; 176 }
177 result.config.server_name = optarg;
151 break; 178 break;
152 case 'p': /* port */ 179 case 'p': /* port */
153 if (is_intpos(optarg)) { 180 if (is_intpos(optarg)) {
154 port = atoi(optarg); 181 result.config.port = atoi(optarg);
155 } else { 182 } else {
156 usage2(_("Port number must be a positive integer"), optarg); 183 usage2(_("Port number must be a positive integer"), optarg);
157 } 184 }
185 break;
186 case output_format_index: {
187 parsed_output_format parser = mp_parse_output_format(optarg);
188 if (!parser.parsing_success) {
189 // TODO List all available formats here, maybe add anothoer usage function
190 printf("Invalid output format: %s\n", optarg);
191 exit(STATE_UNKNOWN);
192 }
193
194 result.config.output_format_is_set = true;
195 result.config.output_format = parser.output_format;
196 break;
197 }
158 } 198 }
159 } 199 }
160 200
161 option_char = optind; 201 option_char = optind;
162 if (server_name == NULL && option_char < argc) { 202 if (result.config.server_name == NULL && option_char < argc) {
163 if (is_host(argv[option_char])) { 203 if (is_host(argv[option_char])) {
164 server_name = argv[option_char++]; 204 result.config.server_name = argv[option_char++];
165 } 205 }
166 } 206 }
167 207
168 if (port == -1 && option_char < argc) { 208 if (result.config.port == -1 && option_char < argc) {
169 if (is_intpos(argv[option_char])) { 209 if (is_intpos(argv[option_char])) {
170 port = atoi(argv[option_char++]); 210 result.config.port = atoi(argv[option_char++]);
171 } else { 211 } else {
172 print_usage(); 212 print_usage();
173 exit(STATE_UNKNOWN); 213 exit(STATE_UNKNOWN);
174 } 214 }
175 } 215 }
176 216
177 return validate_arguments(); 217 if (result.config.server_name == NULL) {
178} 218 result.errorcode = ERROR;
219 return result;
220 }
179 221
180int validate_arguments(void) { 222 return result;
181 if (server_name == NULL)
182 return ERROR;
183 if (port == -1) /* funky, but allows -p to override stray integer in args */
184 port = SSH_DFL_PORT;
185 return OK;
186} 223}
187 224
188/************************************************************************ 225/************************************************************************
@@ -191,28 +228,34 @@ int validate_arguments(void) {
191 * 228 *
192 *-----------------------------------------------------------------------*/ 229 *-----------------------------------------------------------------------*/
193 230
194int ssh_connect(char *haddr, int hport, char *remote_version, char *remote_protocol) { 231int ssh_connect(mp_check *overall, char *haddr, int hport, char *desired_remote_version, char *desired_remote_protocol) {
195 struct timeval tv; 232 struct timeval tv;
196 gettimeofday(&tv, NULL); 233 gettimeofday(&tv, NULL);
197 234
198 int socket; 235 int socket;
199 int result = my_tcp_connect(haddr, hport, &socket); 236 int result = my_tcp_connect(haddr, hport, &socket);
200 237
201 if (result != STATE_OK) 238 mp_subcheck connection_sc = mp_subcheck_init();
239 if (result != STATE_OK) {
240 connection_sc = mp_set_subcheck_state(connection_sc, STATE_CRITICAL);
241 xasprintf(&connection_sc.output, "Failed to establish TCP connection to Host %s and Port %d", haddr, hport);
242 mp_add_subcheck_to_check(overall, connection_sc);
202 return result; 243 return result;
244 }
203 245
204 char *output = (char *)calloc(BUFF_SZ + 1, sizeof(char)); 246 char *output = (char *)calloc(BUFF_SZ + 1, sizeof(char));
205 char *buffer = NULL; 247 char *buffer = NULL;
206 ssize_t recv_ret = 0; 248 size_t recv_ret = 0;
207 char *version_control_string = NULL; 249 char *version_control_string = NULL;
208 ssize_t byte_offset = 0; 250 size_t byte_offset = 0;
209 while ((version_control_string == NULL) && (recv_ret = recv(socket, output + byte_offset, BUFF_SZ - byte_offset, 0) > 0)) { 251 while ((version_control_string == NULL) &&
252 (recv_ret = recv(socket, output + byte_offset, (unsigned long)(BUFF_SZ - byte_offset), 0) > 0)) {
210 253
211 if (strchr(output, '\n')) { /* we've got at least one full line, start parsing*/ 254 if (strchr(output, '\n')) { /* we've got at least one full line, start parsing*/
212 byte_offset = 0; 255 byte_offset = 0;
213 256
214 char *index = NULL; 257 char *index = NULL;
215 int len = 0; 258 unsigned long len = 0;
216 while ((index = strchr(output + byte_offset, '\n')) != NULL) { 259 while ((index = strchr(output + byte_offset, '\n')) != NULL) {
217 /*Partition the buffer so that this line is a separate string, 260 /*Partition the buffer so that this line is a separate string,
218 * by replacing the newline with NUL*/ 261 * by replacing the newline with NUL*/
@@ -243,14 +286,23 @@ int ssh_connect(char *haddr, int hport, char *remote_version, char *remote_proto
243 } 286 }
244 287
245 if (recv_ret < 0) { 288 if (recv_ret < 0) {
246 printf("SSH CRITICAL - %s", strerror(errno)); 289 connection_sc = mp_set_subcheck_state(connection_sc, STATE_CRITICAL);
247 exit(STATE_CRITICAL); 290 xasprintf(&connection_sc.output, "%s", "SSH CRITICAL - %s", strerror(errno));
291 mp_add_subcheck_to_check(overall, connection_sc);
292 return OK;
248 } 293 }
249 294
250 if (version_control_string == NULL) { 295 if (version_control_string == NULL) {
251 printf("SSH CRITICAL - No version control string received"); 296 connection_sc = mp_set_subcheck_state(connection_sc, STATE_CRITICAL);
252 exit(STATE_CRITICAL); 297 xasprintf(&connection_sc.output, "%s", "SSH CRITICAL - No version control string received");
298 mp_add_subcheck_to_check(overall, connection_sc);
299 return OK;
253 } 300 }
301
302 connection_sc = mp_set_subcheck_state(connection_sc, STATE_OK);
303 xasprintf(&connection_sc.output, "%s", "Initial connection succeeded");
304 mp_add_subcheck_to_check(overall, connection_sc);
305
254 /* 306 /*
255 * "When the connection has been established, both sides MUST send an 307 * "When the connection has been established, both sides MUST send an
256 * identification string. This identification string MUST be 308 * identification string. This identification string MUST be
@@ -259,8 +311,9 @@ int ssh_connect(char *haddr, int hport, char *remote_version, char *remote_proto
259 * - RFC 4253:4.2 311 * - RFC 4253:4.2
260 */ 312 */
261 strip(version_control_string); 313 strip(version_control_string);
262 if (verbose) 314 if (verbose) {
263 printf("%s\n", version_control_string); 315 printf("%s\n", version_control_string);
316 }
264 317
265 char *ssh_proto = version_control_string + 4; 318 char *ssh_proto = version_control_string + 4;
266 319
@@ -288,41 +341,65 @@ int ssh_connect(char *haddr, int hport, char *remote_version, char *remote_proto
288 if (tmp) { 341 if (tmp) {
289 ssh_server[tmp - ssh_server] = '\0'; 342 ssh_server[tmp - ssh_server] = '\0';
290 } 343 }
344
345 mp_subcheck protocol_validity_sc = mp_subcheck_init();
291 if (strlen(ssh_proto) == 0 || strlen(ssh_server) == 0) { 346 if (strlen(ssh_proto) == 0 || strlen(ssh_server) == 0) {
292 printf(_("SSH CRITICAL - Invalid protocol version control string %s\n"), version_control_string); 347 protocol_validity_sc = mp_set_subcheck_state(protocol_validity_sc, STATE_CRITICAL);
293 exit(STATE_CRITICAL); 348 xasprintf(&protocol_validity_sc.output, "Invalid protocol version control string %s", version_control_string);
349 mp_add_subcheck_to_check(overall, protocol_validity_sc);
350 return OK;
294 } 351 }
352
353 protocol_validity_sc = mp_set_subcheck_state(protocol_validity_sc, STATE_OK);
354 xasprintf(&protocol_validity_sc.output, "Valid protocol version control string %s", version_control_string);
355 mp_add_subcheck_to_check(overall, protocol_validity_sc);
356
295 ssh_proto[strspn(ssh_proto, "0123456789. ")] = 0; 357 ssh_proto[strspn(ssh_proto, "0123456789. ")] = 0;
296 358
297 static char *rev_no = VERSION; 359 static char *rev_no = VERSION;
298 xasprintf(&buffer, "SSH-%s-check_ssh_%s\r\n", ssh_proto, rev_no); 360 xasprintf(&buffer, "SSH-%s-check_ssh_%s\r\n", ssh_proto, rev_no);
299 send(socket, buffer, strlen(buffer), MSG_DONTWAIT); 361 send(socket, buffer, strlen(buffer), MSG_DONTWAIT);
300 if (verbose) 362 if (verbose) {
301 printf("%s\n", buffer); 363 printf("%s\n", buffer);
364 }
302 365
303 if (remote_version && strcmp(remote_version, ssh_server)) { 366 if (desired_remote_version && strcmp(desired_remote_version, ssh_server)) {
304 printf(_("SSH CRITICAL - %s (protocol %s) version mismatch, expected '%s'\n"), ssh_server, ssh_proto, remote_version); 367 mp_subcheck remote_version_sc = mp_subcheck_init();
368 remote_version_sc = mp_set_subcheck_state(remote_version_sc, STATE_CRITICAL);
369 xasprintf(&remote_version_sc.output, _("%s (protocol %s) version mismatch, expected '%s'"), ssh_server, ssh_proto,
370 desired_remote_version);
305 close(socket); 371 close(socket);
306 exit(STATE_CRITICAL); 372 mp_add_subcheck_to_check(overall, remote_version_sc);
373 return OK;
307 } 374 }
308 375
309 double elapsed_time = (double)deltime(tv) / 1.0e6; 376 double elapsed_time = (double)deltime(tv) / 1.0e6;
310 if (remote_protocol && strcmp(remote_protocol, ssh_proto)) { 377 mp_perfdata time_pd = perfdata_init();
311 printf(_("SSH CRITICAL - %s (protocol %s) protocol version mismatch, expected '%s' | %s\n"), ssh_server, ssh_proto, remote_protocol, 378 time_pd.value = mp_create_pd_value(elapsed_time);
312 fperfdata("time", elapsed_time, "s", false, 0, false, 0, true, 0, true, (int)socket_timeout)); 379 time_pd.label = "time";
313 close(socket); 380 time_pd.max_present = true;
314 exit(STATE_CRITICAL); 381 time_pd.max = mp_create_pd_value(socket_timeout);
382
383 mp_subcheck protocol_version_sc = mp_subcheck_init();
384 mp_add_perfdata_to_subcheck(&protocol_version_sc, time_pd);
385
386 if (desired_remote_protocol && strcmp(desired_remote_protocol, ssh_proto)) {
387 protocol_version_sc = mp_set_subcheck_state(protocol_version_sc, STATE_CRITICAL);
388 xasprintf(&protocol_version_sc.output, _("%s (protocol %s) protocol version mismatch, expected '%s'"), ssh_server, ssh_proto,
389 desired_remote_protocol);
390 } else {
391 protocol_version_sc = mp_set_subcheck_state(protocol_version_sc, STATE_OK);
392 xasprintf(&protocol_version_sc.output, "SSH server version: %s (protocol version: %s)", ssh_server, ssh_proto);
315 } 393 }
316 394
317 printf(_("SSH OK - %s (protocol %s) | %s\n"), ssh_server, ssh_proto, 395 mp_add_subcheck_to_check(overall, protocol_version_sc);
318 fperfdata("time", elapsed_time, "s", false, 0, false, 0, true, 0, true, (int)socket_timeout));
319 close(socket); 396 close(socket);
320 exit(STATE_OK); 397 return OK;
321} 398}
322 399
323void print_help(void) { 400void print_help(void) {
324 char *myport; 401 char *myport;
325 xasprintf(&myport, "%d", SSH_DFL_PORT); 402 xasprintf(&myport, "%d", default_ssh_port);
326 403
327 print_revision(progname, NP_VERSION); 404 print_revision(progname, NP_VERSION);
328 405
@@ -349,6 +426,7 @@ void print_help(void) {
349 426
350 printf(" %s\n", "-P, --remote-protocol=STRING"); 427 printf(" %s\n", "-P, --remote-protocol=STRING");
351 printf(" %s\n", _("Alert if protocol doesn't match expected protocol version (ex: 2.0)")); 428 printf(" %s\n", _("Alert if protocol doesn't match expected protocol version (ex: 2.0)"));
429 printf(UT_OUTPUT_FORMAT);
352 430
353 printf(UT_VERBOSE); 431 printf(UT_VERBOSE);
354 432
@@ -357,5 +435,5 @@ void print_help(void) {
357 435
358void print_usage(void) { 436void print_usage(void) {
359 printf("%s\n", _("Usage:")); 437 printf("%s\n", _("Usage:"));
360 printf("%s [-4|-6] [-t <timeout>] [-r <remote version>] [-p <port>] <host>\n", progname); 438 printf("%s [-4|-6] [-t <timeout>] [-r <remote version>] [-p <port>] --hostname <host>\n", progname);
361} 439}
diff --git a/plugins/check_ssh.d/config.h b/plugins/check_ssh.d/config.h
new file mode 100644
index 00000000..c150fd30
--- /dev/null
+++ b/plugins/check_ssh.d/config.h
@@ -0,0 +1,29 @@
1#pragma once
2
3#include <stddef.h>
4#include "../../lib/monitoringplug.h"
5
6const int default_ssh_port = 22;
7
8typedef struct check_ssh_config {
9 int port;
10 char *server_name;
11 char *remote_version;
12 char *remote_protocol;
13
14 bool output_format_is_set;
15 mp_output_format output_format;
16} check_ssh_config;
17
18check_ssh_config check_ssh_config_init(void) {
19 check_ssh_config tmp = {
20 .port = default_ssh_port,
21 .server_name = NULL,
22 .remote_version = NULL,
23 .remote_protocol = NULL,
24
25 .output_format_is_set = false,
26 };
27
28 return tmp;
29}
diff --git a/plugins/check_swap.c b/plugins/check_swap.c
index 4d3b6099..cb95949a 100644
--- a/plugins/check_swap.c
+++ b/plugins/check_swap.c
@@ -93,7 +93,7 @@ int main(int argc, char **argv) {
93 double percent_used; 93 double percent_used;
94 mp_check overall = mp_check_init(); 94 mp_check overall = mp_check_init();
95 if (config.output_format_is_set) { 95 if (config.output_format_is_set) {
96 overall.format = config.output_format; 96 mp_set_format(config.output_format);
97 } 97 }
98 mp_subcheck sc1 = mp_subcheck_init(); 98 mp_subcheck sc1 = mp_subcheck_init();
99 sc1 = mp_set_subcheck_default_state(sc1, STATE_OK); 99 sc1 = mp_set_subcheck_default_state(sc1, STATE_OK);
diff --git a/plugins/netutils.c b/plugins/netutils.c
index ee81912a..e2916c65 100644
--- a/plugins/netutils.c
+++ b/plugins/netutils.c
@@ -28,6 +28,8 @@
28 *****************************************************************************/ 28 *****************************************************************************/
29 29
30#include "common.h" 30#include "common.h"
31#include "output.h"
32#include "states.h"
31#include "netutils.h" 33#include "netutils.h"
32 34
33unsigned int socket_timeout = DEFAULT_SOCKET_TIMEOUT; 35unsigned int socket_timeout = DEFAULT_SOCKET_TIMEOUT;
@@ -43,12 +45,19 @@ int address_family = AF_INET;
43 45
44/* handles socket timeouts */ 46/* handles socket timeouts */
45void socket_timeout_alarm_handler(int sig) { 47void socket_timeout_alarm_handler(int sig) {
46 if (sig == SIGALRM) 48 mp_subcheck timeout_sc = mp_subcheck_init();
47 printf(_("%s - Socket timeout after %d seconds\n"), state_text(socket_timeout_state), socket_timeout); 49 timeout_sc = mp_set_subcheck_state(timeout_sc, socket_timeout_state);
48 else
49 printf(_("%s - Abnormal timeout after %d seconds\n"), state_text(socket_timeout_state), socket_timeout);
50 50
51 exit(socket_timeout_state); 51 if (sig == SIGALRM) {
52 xasprintf(&timeout_sc.output, _("Socket timeout after %d seconds\n"), socket_timeout);
53 } else {
54 xasprintf(&timeout_sc.output, _("Abnormal timeout after %d seconds\n"), socket_timeout);
55 }
56
57 mp_check overall = mp_check_init();
58 mp_add_subcheck_to_check(&overall, timeout_sc);
59
60 mp_exit(overall);
52} 61}
53 62
54/* connects to a host on a specified tcp port, sends a string, and gets a 63/* connects to a host on a specified tcp port, sends a string, and gets a
@@ -65,12 +74,13 @@ int process_tcp_request2(const char *server_address, int server_port, const char
65 int recv_length = 0; 74 int recv_length = 0;
66 75
67 result = np_net_connect(server_address, server_port, &sd, IPPROTO_TCP); 76 result = np_net_connect(server_address, server_port, &sd, IPPROTO_TCP);
68 if (result != STATE_OK) 77 if (result != STATE_OK) {
69 return STATE_CRITICAL; 78 return STATE_CRITICAL;
79 }
70 80
71 send_result = send(sd, send_buffer, strlen(send_buffer), 0); 81 send_result = send(sd, send_buffer, strlen(send_buffer), 0);
72 if (send_result < 0 || (size_t)send_result != strlen(send_buffer)) { 82 if (send_result < 0 || (size_t)send_result != strlen(send_buffer)) {
73 printf("%s\n", _("Send failed")); 83 // printf("%s\n", _("Send failed"));
74 result = STATE_WARNING; 84 result = STATE_WARNING;
75 } 85 }
76 86
@@ -87,7 +97,7 @@ int process_tcp_request2(const char *server_address, int server_port, const char
87 if (!FD_ISSET(sd, &readfds)) { /* it hasn't */ 97 if (!FD_ISSET(sd, &readfds)) { /* it hasn't */
88 if (!recv_length) { 98 if (!recv_length) {
89 strcpy(recv_buffer, ""); 99 strcpy(recv_buffer, "");
90 printf("%s\n", _("No data was received from host!")); 100 // printf("%s\n", _("No data was received from host!"));
91 result = STATE_WARNING; 101 result = STATE_WARNING;
92 } else { /* this one failed, but previous ones worked */ 102 } else { /* this one failed, but previous ones worked */
93 recv_buffer[recv_length] = 0; 103 recv_buffer[recv_length] = 0;
@@ -130,8 +140,9 @@ int process_request(const char *server_address, int server_port, int proto, cons
130 result = STATE_OK; 140 result = STATE_OK;
131 141
132 result = np_net_connect(server_address, server_port, &sd, proto); 142 result = np_net_connect(server_address, server_port, &sd, proto);
133 if (result != STATE_OK) 143 if (result != STATE_OK) {
134 return STATE_CRITICAL; 144 return STATE_CRITICAL;
145 }
135 146
136 result = send_request(sd, proto, send_buffer, recv_buffer, recv_size); 147 result = send_request(sd, proto, send_buffer, recv_buffer, recv_size);
137 148
@@ -169,15 +180,16 @@ int np_net_connect(const char *host_name, int port, int *sd, int proto) {
169 host_name++; 180 host_name++;
170 len -= 2; 181 len -= 2;
171 } 182 }
172 if (len >= sizeof(host)) 183 if (len >= sizeof(host)) {
173 return STATE_UNKNOWN; 184 return STATE_UNKNOWN;
185 }
174 memcpy(host, host_name, len); 186 memcpy(host, host_name, len);
175 host[len] = '\0'; 187 host[len] = '\0';
176 snprintf(port_str, sizeof(port_str), "%d", port); 188 snprintf(port_str, sizeof(port_str), "%d", port);
177 result = getaddrinfo(host, port_str, &hints, &res); 189 result = getaddrinfo(host, port_str, &hints, &res);
178 190
179 if (result != 0) { 191 if (result != 0) {
180 printf("%s\n", gai_strerror(result)); 192 // printf("%s\n", gai_strerror(result));
181 return STATE_UNKNOWN; 193 return STATE_UNKNOWN;
182 } 194 }
183 195
@@ -187,7 +199,7 @@ int np_net_connect(const char *host_name, int port, int *sd, int proto) {
187 *sd = socket(r->ai_family, socktype, r->ai_protocol); 199 *sd = socket(r->ai_family, socktype, r->ai_protocol);
188 200
189 if (*sd < 0) { 201 if (*sd < 0) {
190 printf("%s\n", _("Socket creation failed")); 202 // printf("%s\n", _("Socket creation failed"));
191 freeaddrinfo(r); 203 freeaddrinfo(r);
192 return STATE_UNKNOWN; 204 return STATE_UNKNOWN;
193 } 205 }
@@ -226,21 +238,23 @@ int np_net_connect(const char *host_name, int port, int *sd, int proto) {
226 die(STATE_UNKNOWN, _("Socket creation failed")); 238 die(STATE_UNKNOWN, _("Socket creation failed"));
227 } 239 }
228 result = connect(*sd, (struct sockaddr *)&su, sizeof(su)); 240 result = connect(*sd, (struct sockaddr *)&su, sizeof(su));
229 if (result < 0 && errno == ECONNREFUSED) 241 if (result < 0 && errno == ECONNREFUSED) {
230 was_refused = true; 242 was_refused = true;
243 }
231 } 244 }
232 245
233 if (result == 0) 246 if (result == 0) {
234 return STATE_OK; 247 return STATE_OK;
235 else if (was_refused) { 248 } else if (was_refused) {
236 switch (econn_refuse_state) { /* a user-defined expected outcome */ 249 switch (econn_refuse_state) { /* a user-defined expected outcome */
237 case STATE_OK: 250 case STATE_OK:
238 case STATE_WARNING: /* user wants WARN or OK on refusal, or... */ 251 case STATE_WARNING: /* user wants WARN or OK on refusal, or... */
239 case STATE_CRITICAL: /* user did not set econn_refuse_state, or wanted critical */ 252 case STATE_CRITICAL: /* user did not set econn_refuse_state, or wanted critical */
240 if (is_socket) 253 if (is_socket) {
241 printf("connect to file socket %s: %s\n", host_name, strerror(errno)); 254 // printf("connect to file socket %s: %s\n", host_name, strerror(errno));
242 else 255 } else {
243 printf("connect to address %s and port %d: %s\n", host_name, port, strerror(errno)); 256 // printf("connect to address %s and port %d: %s\n", host_name, port, strerror(errno));
257 }
244 return STATE_CRITICAL; 258 return STATE_CRITICAL;
245 break; 259 break;
246 default: /* it's a logic error if we do not end up in STATE_(OK|WARNING|CRITICAL) */ 260 default: /* it's a logic error if we do not end up in STATE_(OK|WARNING|CRITICAL) */
@@ -248,10 +262,11 @@ int np_net_connect(const char *host_name, int port, int *sd, int proto) {
248 break; 262 break;
249 } 263 }
250 } else { 264 } else {
251 if (is_socket) 265 if (is_socket) {
252 printf("connect to file socket %s: %s\n", host_name, strerror(errno)); 266 // printf("connect to file socket %s: %s\n", host_name, strerror(errno));
253 else 267 } else {
254 printf("connect to address %s and port %d: %s\n", host_name, port, strerror(errno)); 268 // printf("connect to address %s and port %d: %s\n", host_name, port, strerror(errno));
269 }
255 return STATE_CRITICAL; 270 return STATE_CRITICAL;
256 } 271 }
257} 272}
@@ -265,7 +280,7 @@ int send_request(int sd, int proto, const char *send_buffer, char *recv_buffer,
265 280
266 send_result = send(sd, send_buffer, strlen(send_buffer), 0); 281 send_result = send(sd, send_buffer, strlen(send_buffer), 0);
267 if (send_result < 0 || (size_t)send_result != strlen(send_buffer)) { 282 if (send_result < 0 || (size_t)send_result != strlen(send_buffer)) {
268 printf("%s\n", _("Send failed")); 283 // printf("%s\n", _("Send failed"));
269 result = STATE_WARNING; 284 result = STATE_WARNING;
270 } 285 }
271 286
@@ -280,7 +295,7 @@ int send_request(int sd, int proto, const char *send_buffer, char *recv_buffer,
280 /* make sure some data has arrived */ 295 /* make sure some data has arrived */
281 if (!FD_ISSET(sd, &readfds)) { 296 if (!FD_ISSET(sd, &readfds)) {
282 strcpy(recv_buffer, ""); 297 strcpy(recv_buffer, "");
283 printf("%s\n", _("No data was received from host!")); 298 // printf("%s\n", _("No data was received from host!"));
284 result = STATE_WARNING; 299 result = STATE_WARNING;
285 } 300 }
286 301
@@ -288,11 +303,13 @@ int send_request(int sd, int proto, const char *send_buffer, char *recv_buffer,
288 recv_result = recv(sd, recv_buffer, (size_t)recv_size - 1, 0); 303 recv_result = recv(sd, recv_buffer, (size_t)recv_size - 1, 0);
289 if (recv_result == -1) { 304 if (recv_result == -1) {
290 strcpy(recv_buffer, ""); 305 strcpy(recv_buffer, "");
291 if (proto != IPPROTO_TCP) 306 if (proto != IPPROTO_TCP) {
292 printf("%s\n", _("Receive failed")); 307 // printf("%s\n", _("Receive failed"));
308 }
293 result = STATE_WARNING; 309 result = STATE_WARNING;
294 } else 310 } else {
295 recv_buffer[recv_result] = 0; 311 recv_buffer[recv_result] = 0;
312 }
296 313
297 /* die returned string */ 314 /* die returned string */
298 recv_buffer[recv_size - 1] = 0; 315 recv_buffer[recv_size - 1] = 0;
@@ -301,26 +318,30 @@ int send_request(int sd, int proto, const char *send_buffer, char *recv_buffer,
301} 318}
302 319
303bool is_host(const char *address) { 320bool is_host(const char *address) {
304 if (is_addr(address) || is_hostname(address)) 321 if (is_addr(address) || is_hostname(address)) {
305 return (true); 322 return (true);
323 }
306 324
307 return (false); 325 return (false);
308} 326}
309 327
310void host_or_die(const char *str) { 328void host_or_die(const char *str) {
311 if (!str || (!is_addr(str) && !is_hostname(str))) 329 if (!str || (!is_addr(str) && !is_hostname(str))) {
312 usage_va(_("Invalid hostname/address - %s"), str); 330 usage_va(_("Invalid hostname/address - %s"), str);
331 }
313} 332}
314 333
315bool is_addr(const char *address) { 334bool is_addr(const char *address) {
316#ifdef USE_IPV6 335#ifdef USE_IPV6
317 if (address_family == AF_INET && is_inet_addr(address)) 336 if (address_family == AF_INET && is_inet_addr(address)) {
318 return true; 337 return true;
319 else if (address_family == AF_INET6 && is_inet6_addr(address)) 338 } else if (address_family == AF_INET6 && is_inet6_addr(address)) {
320 return true; 339 return true;
340 }
321#else 341#else
322 if (is_inet_addr(address)) 342 if (is_inet_addr(address)) {
323 return (true); 343 return (true);
344 }
324#endif 345#endif
325 346
326 return (false); 347 return (false);
@@ -335,11 +356,13 @@ int dns_lookup(const char *in, struct sockaddr_storage *ss, int family) {
335 hints.ai_family = family; 356 hints.ai_family = family;
336 357
337 retval = getaddrinfo(in, NULL, &hints, &res); 358 retval = getaddrinfo(in, NULL, &hints, &res);
338 if (retval != 0) 359 if (retval != 0) {
339 return false; 360 return false;
361 }
340 362
341 if (ss != NULL) 363 if (ss != NULL) {
342 memcpy(ss, res->ai_addr, res->ai_addrlen); 364 memcpy(ss, res->ai_addr, res->ai_addrlen);
365 }
343 freeaddrinfo(res); 366 freeaddrinfo(res);
344 return true; 367 return true;
345} 368}
diff --git a/plugins/t/check_http.t b/plugins/t/check_http.t
index 6ab4a5b6..bb1fd27d 100644
--- a/plugins/t/check_http.t
+++ b/plugins/t/check_http.t
@@ -45,7 +45,7 @@ $res = NPTest->testCmd(
45 "./$plugin $host_nonresponsive -wt 1 -ct 2 -t 3" 45 "./$plugin $host_nonresponsive -wt 1 -ct 2 -t 3"
46 ); 46 );
47cmp_ok( $res->return_code, '==', 2, "Webserver $host_nonresponsive not responding" ); 47cmp_ok( $res->return_code, '==', 2, "Webserver $host_nonresponsive not responding" );
48cmp_ok( $res->output, 'eq', "CRITICAL - Socket timeout after 3 seconds", "Output OK"); 48like( $res->output, "/Socket timeout after/", "Output OK");
49 49
50$res = NPTest->testCmd( 50$res = NPTest->testCmd(
51 "./$plugin $hostname_invalid -wt 1 -ct 2" 51 "./$plugin $hostname_invalid -wt 1 -ct 2"
diff --git a/plugins/t/check_jabber.t b/plugins/t/check_jabber.t
index fcdae179..08cadcbd 100644
--- a/plugins/t/check_jabber.t
+++ b/plugins/t/check_jabber.t
@@ -17,7 +17,7 @@ my $hostname_invalid = getTestParameter("NP_HOSTNAME_INVALID", "An invalid (no
17 17
18my $jabberOK = '/JABBER OK\s-\s\d+\.\d+\ssecond response time on '.$host_tcp_jabber.' port 5222/'; 18my $jabberOK = '/JABBER OK\s-\s\d+\.\d+\ssecond response time on '.$host_tcp_jabber.' port 5222/';
19 19
20my $jabberUnresponsive = '/CRITICAL\s-\sSocket timeout after\s\d+\sseconds/'; 20my $jabberUnresponsive = '/Socket timeout after\s\d+\sseconds/';
21 21
22my $jabberInvalid = '/JABBER CRITICAL - Invalid hostname, address or socket:\s.+/'; 22my $jabberInvalid = '/JABBER CRITICAL - Invalid hostname, address or socket:\s.+/';
23 23
diff --git a/plugins/t/check_ldap.t b/plugins/t/check_ldap.t
index b8a4a766..fcba0393 100644
--- a/plugins/t/check_ldap.t
+++ b/plugins/t/check_ldap.t
@@ -24,7 +24,7 @@ SKIP: {
24 24
25 $result = NPTest->testCmd("$command -H $host_nonresponsive -b ou=blah -t 2 -w 1 -c 1"); 25 $result = NPTest->testCmd("$command -H $host_nonresponsive -b ou=blah -t 2 -w 1 -c 1");
26 is( $result->return_code, 2, "$command -H $host_nonresponsive -b ou=blah -t 5 -w 2 -c 3" ); 26 is( $result->return_code, 2, "$command -H $host_nonresponsive -b ou=blah -t 5 -w 2 -c 3" );
27 is( $result->output, 'CRITICAL - Socket timeout after 2 seconds', "output ok" ); 27 like($result->output, '/Socket timeout after \d+ seconds/', "output ok" );
28}; 28};
29 29
30SKIP: { 30SKIP: {
diff --git a/plugins/t/check_ntp.t b/plugins/t/check_ntp.t
index b8fc8fdf..a8ac7bb8 100644
--- a/plugins/t/check_ntp.t
+++ b/plugins/t/check_ntp.t
@@ -37,7 +37,7 @@ my $ntp_critmatch1 = '/^NTP\sCRITICAL:\sOffset\s-?[0-9]+(\.[0-9]+)?(e-[0-9]{2})?
37my $ntp_okmatch2 = '/^NTP\sOK:\sOffset\s-?[0-9]+(\.[0-9]+)?(e-[0-9]{2})?\ssecs,\sjitter=[0-9]+\.[0-9]+,\sstratum=[0-9]{1,2},\struechimers=[0-9]+/'; 37my $ntp_okmatch2 = '/^NTP\sOK:\sOffset\s-?[0-9]+(\.[0-9]+)?(e-[0-9]{2})?\ssecs,\sjitter=[0-9]+\.[0-9]+,\sstratum=[0-9]{1,2},\struechimers=[0-9]+/';
38my $ntp_warnmatch2 = '/^NTP\sWARNING:\sOffset\s-?[0-9]+(\.[0-9]+)?(e-[0-9]{2})?\ssecs,\sjitter=[0-9]+\.[0-9]+,\sstratum=[0-9]{1,2}\s\(WARNING\),\struechimers=[0-9]+/'; 38my $ntp_warnmatch2 = '/^NTP\sWARNING:\sOffset\s-?[0-9]+(\.[0-9]+)?(e-[0-9]{2})?\ssecs,\sjitter=[0-9]+\.[0-9]+,\sstratum=[0-9]{1,2}\s\(WARNING\),\struechimers=[0-9]+/';
39my $ntp_critmatch2 = '/^NTP\sCRITICAL:\sOffset\s-?[0-9]+(\.[0-9]+)?(e-[0-9]{2})?\ssecs,\sjitter=[0-9]+\.[0-9]+\s\(CRITICAL\),\sstratum=[0-9]{1,2},\struechimers=[0-9]+/'; 39my $ntp_critmatch2 = '/^NTP\sCRITICAL:\sOffset\s-?[0-9]+(\.[0-9]+)?(e-[0-9]{2})?\ssecs,\sjitter=[0-9]+\.[0-9]+\s\(CRITICAL\),\sstratum=[0-9]{1,2},\struechimers=[0-9]+/';
40my $ntp_noresponse = '/^(CRITICAL - Socket timeout after 3 seconds)|(NTP CRITICAL: No response from NTP server)$/'; 40my $ntp_noresponse = '/(.*Socket timeout after \d+ seconds.*)|(.*No response from NTP server.*)/';
41my $ntp_nosuchhost = '/^check_ntp.*: Invalid hostname/address - ' . $hostname_invalid . '/'; 41my $ntp_nosuchhost = '/^check_ntp.*: Invalid hostname/address - ' . $hostname_invalid . '/';
42 42
43 43
diff --git a/plugins/t/check_smtp.t b/plugins/t/check_smtp.t
index 1a1ebe3e..73b4a1fd 100644
--- a/plugins/t/check_smtp.t
+++ b/plugins/t/check_smtp.t
@@ -24,7 +24,7 @@ my $hostname_invalid = getTestParameter( "NP_HOSTNAME_INVALID",
24 "An invalid (not known to DNS) hostname", "nosuchhost" ); 24 "An invalid (not known to DNS) hostname", "nosuchhost" );
25my $res; 25my $res;
26 26
27plan tests => 16; 27plan tests => 15;
28 28
29SKIP: { 29SKIP: {
30 skip "No SMTP server defined", 4 unless $host_tcp_smtp; 30 skip "No SMTP server defined", 4 unless $host_tcp_smtp;
@@ -73,7 +73,6 @@ SKIP: {
73 my $unused_port = 4465; 73 my $unused_port = 4465;
74 $res = NPTest->testCmd( "./check_smtp -H $host_tcp_smtp_tls -p $unused_port --ssl" ); 74 $res = NPTest->testCmd( "./check_smtp -H $host_tcp_smtp_tls -p $unused_port --ssl" );
75 is ($res->return_code, 2, "Check rc of connecting to $host_tcp_smtp_tls with TLS on unused port $unused_port" ); 75 is ($res->return_code, 2, "Check rc of connecting to $host_tcp_smtp_tls with TLS on unused port $unused_port" );
76 like ($res->output, qr/^connect to address $host_tcp_smtp_tls and port $unused_port: Connection refused/, "Check output of connecting to $host_tcp_smtp_tls with TLS on unused port $unused_port");
77} 76}
78 77
79$res = NPTest->testCmd( "./check_smtp $host_nonresponsive" ); 78$res = NPTest->testCmd( "./check_smtp $host_nonresponsive" );
diff --git a/plugins/t/check_ssh.t b/plugins/t/check_ssh.t
index 907d33a8..8a20782e 100644
--- a/plugins/t/check_ssh.t
+++ b/plugins/t/check_ssh.t
@@ -5,10 +5,10 @@
5# 5#
6 6
7use strict; 7use strict;
8use warnings;
8use Test::More; 9use Test::More;
9use NPTest; 10use NPTest;
10 11use JSON;
11my $res;
12 12
13# Required parameters 13# Required parameters
14my $ssh_host = getTestParameter("NP_SSH_HOST", 14my $ssh_host = getTestParameter("NP_SSH_HOST",
@@ -23,30 +23,38 @@ my $hostname_invalid = getTestParameter("NP_HOSTNAME_INVALID",
23 "An invalid (not known to DNS) hostname", 23 "An invalid (not known to DNS) hostname",
24 "nosuchhost" ); 24 "nosuchhost" );
25 25
26 my $outputFormat = '--output-format mp-test-json';
27
28plan tests => 24;
26 29
27plan tests => 14 + 6; 30my $output;
31my $result;
28 32
29SKIP: { 33SKIP: {
30 skip "SSH_HOST must be defined", 6 unless $ssh_host; 34 skip "SSH_HOST must be defined", 6 unless $ssh_host;
35
36
31 my $result = NPTest->testCmd( 37 my $result = NPTest->testCmd(
32 "./check_ssh -H $ssh_host" 38 "./check_ssh -H $ssh_host" ." ". $outputFormat
33 ); 39 );
34 cmp_ok($result->return_code, '==', 0, "Exit with return code 0 (OK)"); 40 cmp_ok($result->return_code, '==', 0, "Exit with return code 0 (OK)");
35 like($result->output, '/^SSH OK - /', "Status text if command returned none (OK)"); 41 $output = decode_json($result->output);
42 is($output->{'state'}, "OK", "State was correct");
36 43
37 44
38 $result = NPTest->testCmd( 45 $result = NPTest->testCmd(
39 "./check_ssh -H $host_nonresponsive -t 2" 46 "./check_ssh -H $host_nonresponsive -t 2" ." ". $outputFormat
40 ); 47 );
41 cmp_ok($result->return_code, '==', 2, "Exit with return code 0 (OK)"); 48 cmp_ok($result->return_code, '==', 0, "Exit with return code 0 (OK)");
42 like($result->output, '/^CRITICAL - Socket timeout after 2 seconds/', "Status text if command returned none (OK)"); 49 $output = decode_json($result->output);
50 is($output->{'state'}, "CRITICAL", "State was correct");
43 51
44 52
45 53
46 $result = NPTest->testCmd( 54 $result = NPTest->testCmd(
47 "./check_ssh -H $hostname_invalid -t 2" 55 "./check_ssh -H $hostname_invalid -t 2" ." ". $outputFormat
48 ); 56 );
49 cmp_ok($result->return_code, '==', 3, "Exit with return code 0 (OK)"); 57 cmp_ok($result->return_code, '==', 3, "Exit with return code 3 (UNKNOWN)");
50 like($result->output, '/^check_ssh: Invalid hostname/', "Status text if command returned none (OK)"); 58 like($result->output, '/^check_ssh: Invalid hostname/', "Status text if command returned none (OK)");
51 59
52 60
@@ -63,46 +71,80 @@ SKIP: {
63 # 71 #
64 # where `comments` is optional, protoversion is the SSH protocol version and 72 # where `comments` is optional, protoversion is the SSH protocol version and
65 # softwareversion is an arbitrary string representing the server software version 73 # softwareversion is an arbitrary string representing the server software version
74
75 my $found_version = 0;
76
66 open(NC, "echo 'SSH-2.0-nagiosplug.ssh.0.1' | nc ${nc_flags}|"); 77 open(NC, "echo 'SSH-2.0-nagiosplug.ssh.0.1' | nc ${nc_flags}|");
67 sleep 0.1; 78 sleep 0.1;
68 $res = NPTest->testCmd( "./check_ssh -H localhost -p 5003" ); 79 $result = NPTest->testCmd( "./check_ssh -H localhost -p 5003" ." ". $outputFormat);
69 cmp_ok( $res->return_code, '==', 0, "Got SSH protocol version control string"); 80 cmp_ok($result->return_code, '==', 0, "Exit with return code 0 (OK)");
70 like( $res->output, '/^SSH OK - nagiosplug.ssh.0.1 \(protocol 2.0\)/', "Output OK"); 81 $output = decode_json($result->output);
82 is($output->{'state'}, "OK", "State was correct");
83
84 # looking for the version
85 for my $subcheck (@{$output->{'checks'}}) {
86 if ($subcheck->{'output'} =~ /.*nagiosplug.ssh.0.1 \(protocol version: 2.0\).*/ ){
87 $found_version = 1;
88 }
89 }
90 cmp_ok($found_version, '==', 1, "Output OK");
71 close NC; 91 close NC;
72 92
73 open(NC, "echo 'SSH-2.0-3.2.9.1' | nc ${nc_flags}|"); 93 open(NC, "echo 'SSH-2.0-3.2.9.1' | nc ${nc_flags}|");
74 sleep 0.1; 94 sleep 0.1;
75 $res = NPTest->testCmd( "./check_ssh -H localhost -p 5003" ); 95 $result = NPTest->testCmd( "./check_ssh -H localhost -p 5003" ." ". $outputFormat);
76 cmp_ok( $res->return_code, "==", 0, "Got SSH protocol version control string with non-alpha softwareversion string"); 96 cmp_ok($result->return_code, '==', 0, "Exit with return code 0 (OK)");
77 like( $res->output, '/^SSH OK - 3.2.9.1 \(protocol 2.0\)/', "Output OK for non-alpha softwareversion string"); 97 $output = decode_json($result->output);
98 is($output->{'state'}, "OK", "State was correct");
99
100 $found_version = 0;
101 for my $subcheck (@{$output->{'checks'}}) {
102 if ($subcheck->{'output'} =~ /3.2.9.1 \(protocol version: 2.0\)/ ){
103 $found_version = 1;
104 }
105 }
106 cmp_ok($found_version, '==', 1, "Output OK");
78 close NC; 107 close NC;
79 108
80 open(NC, "echo 'SSH-2.0-nagiosplug.ssh.0.1 this is a comment' | nc ${nc_flags} |"); 109 open(NC, "echo 'SSH-2.0-nagiosplug.ssh.0.1 this is a comment' | nc ${nc_flags} |");
81 sleep 0.1; 110 sleep 0.1;
82 $res = NPTest->testCmd( "./check_ssh -H localhost -p 5003 -r nagiosplug.ssh.0.1" ); 111 $result = NPTest->testCmd( "./check_ssh -H localhost -p 5003 -r nagiosplug.ssh.0.1" ." ". $outputFormat);
83 cmp_ok( $res->return_code, '==', 0, "Got SSH protocol version control string, and parsed comment appropriately"); 112 cmp_ok($result->return_code, '==', 0, "Exit with return code 0 (OK)");
84 like( $res->output, '/^SSH OK - nagiosplug.ssh.0.1 \(protocol 2.0\)/', "Output OK"); 113 $output = decode_json($result->output);
114 is($output->{'state'}, "OK", "State was correct");
115
116 # looking for the version
117 $found_version = 0;
118 for my $subcheck (@{$output->{'checks'}}) {
119 if ($subcheck->{'output'} =~ /nagiosplug.ssh.0.1 \(protocol version: 2.0\)/ ){
120 $found_version = 1;
121 }
122 }
123 cmp_ok($found_version, '==', 1, "Output OK");
85 close NC; 124 close NC;
86 125
87 open(NC, "echo 'SSH-' | nc ${nc_flags}|"); 126 open(NC, "echo 'SSH-' | nc ${nc_flags}|");
88 sleep 0.1; 127 sleep 0.1;
89 $res = NPTest->testCmd( "./check_ssh -H localhost -p 5003" ); 128 $result = NPTest->testCmd( "./check_ssh -H localhost -p 5003" ." ". $outputFormat);
90 cmp_ok( $res->return_code, '==', 2, "Got invalid SSH protocol version control string"); 129 cmp_ok($result->return_code, '==', 0, "Exit with return code 0 (OK)");
91 like( $res->output, '/^SSH CRITICAL/', "Output OK"); 130 $output = decode_json($result->output);
131 is($output->{'state'}, "CRITICAL", "Got invalid SSH protocol version control string");
92 close NC; 132 close NC;
93 133
94 open(NC, "echo '' | nc ${nc_flags}|"); 134 open(NC, "echo '' | nc ${nc_flags}|");
95 sleep 0.1; 135 sleep 0.1;
96 $res = NPTest->testCmd( "./check_ssh -H localhost -p 5003" ); 136 $result = NPTest->testCmd( "./check_ssh -H localhost -p 5003" ." ". $outputFormat);
97 cmp_ok( $res->return_code, '==', 2, "No version control string received"); 137 cmp_ok($result->return_code, '==', 0, "Exit with return code 0 (OK)");
98 like( $res->output, '/^SSH CRITICAL - No version control string received/', "Output OK"); 138 $output = decode_json($result->output);
139 is($output->{'state'}, "CRITICAL", "No version control string received");
99 close NC; 140 close NC;
100 141
101 open(NC, "echo 'Not a version control string' | nc ${nc_flags}|"); 142 open(NC, "echo 'Not a version control string' | nc ${nc_flags}|");
102 sleep 0.1; 143 sleep 0.1;
103 $res = NPTest->testCmd( "./check_ssh -H localhost -p 5003" ); 144 $result = NPTest->testCmd( "./check_ssh -H localhost -p 5003" ." ". $outputFormat);
104 cmp_ok( $res->return_code, '==', 2, "No version control string received"); 145 cmp_ok($result->return_code, '==', 0, "Exit with return code 0 (OK)");
105 like( $res->output, '/^SSH CRITICAL - No version control string received/', "Output OK"); 146 $output = decode_json($result->output);
147 is($output->{'state'}, "CRITICAL", "No version control string received");
106 close NC; 148 close NC;
107 149
108 150
@@ -116,8 +158,18 @@ SKIP: {
116 echo 'Some\nPrepended\nData\nLines\n'; sleep 0.2; 158 echo 'Some\nPrepended\nData\nLines\n'; sleep 0.2;
117 echo 'SSH-2.0-nagiosplug.ssh.0.2';} | nc ${nc_flags}|"); 159 echo 'SSH-2.0-nagiosplug.ssh.0.2';} | nc ${nc_flags}|");
118 sleep 0.1; 160 sleep 0.1;
119 $res = NPTest->testCmd( "./check_ssh -H localhost -p 5003" ); 161 $result = NPTest->testCmd( "./check_ssh -H localhost -p 5003" ." ". $outputFormat);
120 cmp_ok( $res->return_code, '==', 0, "Got delayed SSH protocol version control string"); 162 cmp_ok($result->return_code, '==', 0, "Exit with return code 0 (OK)");
121 like( $res->output, '/^SSH OK - nagiosplug.ssh.0.2 \(protocol 2.0\)/', "Output OK"); 163 $output = decode_json($result->output);
164 is($output->{'state'}, "OK", "State was correct");
165
166 # looking for the version
167 $found_version = 0;
168 for my $subcheck (@{$output->{'checks'}}) {
169 if ($subcheck->{'output'} =~ /nagiosplug.ssh.0.2 \(protocol version: 2.0\)/ ){
170 $found_version = 1;
171 }
172 }
173 cmp_ok($found_version, '==', 1, "Output OK");
122 close NC; 174 close NC;
123} 175}
diff --git a/plugins/utils.c b/plugins/utils.c
index 09649429..34335c89 100644
--- a/plugins/utils.c
+++ b/plugins/utils.c
@@ -89,41 +89,46 @@ bool is_numeric(char *number) {
89 char tmp[1]; 89 char tmp[1];
90 float x; 90 float x;
91 91
92 if (!number) 92 if (!number) {
93 return false; 93 return false;
94 else if (sscanf(number, "%f%c", &x, tmp) == 1) 94 } else if (sscanf(number, "%f%c", &x, tmp) == 1) {
95 return true; 95 return true;
96 else 96 } else {
97 return false; 97 return false;
98 }
98} 99}
99 100
100bool is_positive(char *number) { 101bool is_positive(char *number) {
101 if (is_numeric(number) && atof(number) > 0.0) 102 if (is_numeric(number) && atof(number) > 0.0) {
102 return true; 103 return true;
103 else 104 } else {
104 return false; 105 return false;
106 }
105} 107}
106 108
107bool is_negative(char *number) { 109bool is_negative(char *number) {
108 if (is_numeric(number) && atof(number) < 0.0) 110 if (is_numeric(number) && atof(number) < 0.0) {
109 return true; 111 return true;
110 else 112 } else {
111 return false; 113 return false;
114 }
112} 115}
113 116
114bool is_nonnegative(char *number) { 117bool is_nonnegative(char *number) {
115 if (is_numeric(number) && atof(number) >= 0.0) 118 if (is_numeric(number) && atof(number) >= 0.0) {
116 return true; 119 return true;
117 else 120 } else {
118 return false; 121 return false;
122 }
119} 123}
120 124
121bool is_percentage(char *number) { 125bool is_percentage(char *number) {
122 int x; 126 int x;
123 if (is_numeric(number) && (x = atof(number)) >= 0 && x <= 100) 127 if (is_numeric(number) && (x = atof(number)) >= 0 && x <= 100) {
124 return true; 128 return true;
125 else 129 } else {
126 return false; 130 return false;
131 }
127} 132}
128 133
129bool is_percentage_expression(const char str[]) { 134bool is_percentage_expression(const char str[]) {
@@ -156,36 +161,41 @@ bool is_percentage_expression(const char str[]) {
156bool is_integer(char *number) { 161bool is_integer(char *number) {
157 long int n; 162 long int n;
158 163
159 if (!number || (strspn(number, "-0123456789 ") != strlen(number))) 164 if (!number || (strspn(number, "-0123456789 ") != strlen(number))) {
160 return false; 165 return false;
166 }
161 167
162 n = strtol(number, NULL, 10); 168 n = strtol(number, NULL, 10);
163 169
164 if (errno != ERANGE && n >= INT_MIN && n <= INT_MAX) 170 if (errno != ERANGE && n >= INT_MIN && n <= INT_MAX) {
165 return true; 171 return true;
166 else 172 } else {
167 return false; 173 return false;
174 }
168} 175}
169 176
170bool is_intpos(char *number) { 177bool is_intpos(char *number) {
171 if (is_integer(number) && atoi(number) > 0) 178 if (is_integer(number) && atoi(number) > 0) {
172 return true; 179 return true;
173 else 180 } else {
174 return false; 181 return false;
182 }
175} 183}
176 184
177bool is_intneg(char *number) { 185bool is_intneg(char *number) {
178 if (is_integer(number) && atoi(number) < 0) 186 if (is_integer(number) && atoi(number) < 0) {
179 return true; 187 return true;
180 else 188 } else {
181 return false; 189 return false;
190 }
182} 191}
183 192
184bool is_intnonneg(char *number) { 193bool is_intnonneg(char *number) {
185 if (is_integer(number) && atoi(number) >= 0) 194 if (is_integer(number) && atoi(number) >= 0) {
186 return true; 195 return true;
187 else 196 } else {
188 return false; 197 return false;
198 }
189} 199}
190 200
191/* 201/*
@@ -247,19 +257,21 @@ bool is_uint64(char *number, uint64_t *target) {
247 257
248bool is_intpercent(char *number) { 258bool is_intpercent(char *number) {
249 int i; 259 int i;
250 if (is_integer(number) && (i = atoi(number)) >= 0 && i <= 100) 260 if (is_integer(number) && (i = atoi(number)) >= 0 && i <= 100) {
251 return true; 261 return true;
252 else 262 } else {
253 return false; 263 return false;
264 }
254} 265}
255 266
256bool is_option(char *str) { 267bool is_option(char *str) {
257 if (!str) 268 if (!str) {
258 return false; 269 return false;
259 else if (strspn(str, "-") == 1 || strspn(str, "-") == 2) 270 } else if (strspn(str, "-") == 1 || strspn(str, "-") == 2) {
260 return true; 271 return true;
261 else 272 } else {
262 return false; 273 return false;
274 }
263} 275}
264 276
265#ifdef NEED_GETTIMEOFDAY 277#ifdef NEED_GETTIMEOFDAY
@@ -288,10 +300,11 @@ void strip(char *buffer) {
288 300
289 for (x = strlen(buffer); x >= 1; x--) { 301 for (x = strlen(buffer); x >= 1; x--) {
290 i = x - 1; 302 i = x - 1;
291 if (buffer[i] == ' ' || buffer[i] == '\r' || buffer[i] == '\n' || buffer[i] == '\t') 303 if (buffer[i] == ' ' || buffer[i] == '\r' || buffer[i] == '\n' || buffer[i] == '\t') {
292 buffer[i] = '\0'; 304 buffer[i] = '\0';
293 else 305 } else {
294 break; 306 break;
307 }
295 } 308 }
296 return; 309 return;
297} 310}
@@ -309,8 +322,9 @@ void strip(char *buffer) {
309 *****************************************************************************/ 322 *****************************************************************************/
310 323
311char *strscpy(char *dest, const char *src) { 324char *strscpy(char *dest, const char *src) {
312 if (src == NULL) 325 if (src == NULL) {
313 return NULL; 326 return NULL;
327 }
314 328
315 xasprintf(&dest, "%s", src); 329 xasprintf(&dest, "%s", src);
316 330
@@ -369,17 +383,21 @@ char *strscpy(char *dest, const char *src) {
369 383
370char *strnl(char *str) { 384char *strnl(char *str) {
371 size_t len; 385 size_t len;
372 if (str == NULL) 386 if (str == NULL) {
373 return NULL; 387 return NULL;
388 }
374 str = strpbrk(str, "\r\n"); 389 str = strpbrk(str, "\r\n");
375 if (str == NULL) 390 if (str == NULL) {
376 return NULL; 391 return NULL;
392 }
377 len = strspn(str, "\r\n"); 393 len = strspn(str, "\r\n");
378 if (str[len] == '\0') 394 if (str[len] == '\0') {
379 return NULL; 395 return NULL;
396 }
380 str += len; 397 str += len;
381 if (strlen(str) == 0) 398 if (strlen(str) == 0) {
382 return NULL; 399 return NULL;
400 }
383 return str; 401 return str;
384} 402}
385 403
@@ -402,15 +420,18 @@ char *strnl(char *str) {
402char *strpcpy(char *dest, const char *src, const char *str) { 420char *strpcpy(char *dest, const char *src, const char *str) {
403 size_t len; 421 size_t len;
404 422
405 if (src) 423 if (src) {
406 len = strcspn(src, str); 424 len = strcspn(src, str);
407 else 425 } else {
408 return NULL; 426 return NULL;
427 }
409 428
410 if (dest == NULL || strlen(dest) < len) 429 if (dest == NULL || strlen(dest) < len) {
411 dest = realloc(dest, len + 1); 430 dest = realloc(dest, len + 1);
412 if (dest == NULL) 431 }
432 if (dest == NULL) {
413 die(STATE_UNKNOWN, _("failed realloc in strpcpy\n")); 433 die(STATE_UNKNOWN, _("failed realloc in strpcpy\n"));
434 }
414 435
415 strncpy(dest, src, len); 436 strncpy(dest, src, len);
416 dest[len] = '\0'; 437 dest[len] = '\0';
@@ -434,10 +455,11 @@ char *strpcpy(char *dest, const char *src, const char *str) {
434char *strpcat(char *dest, const char *src, const char *str) { 455char *strpcat(char *dest, const char *src, const char *str) {
435 size_t len, l2; 456 size_t len, l2;
436 457
437 if (dest) 458 if (dest) {
438 len = strlen(dest); 459 len = strlen(dest);
439 else 460 } else {
440 len = 0; 461 len = 0;
462 }
441 463
442 if (src) { 464 if (src) {
443 l2 = strcspn(src, str); 465 l2 = strcspn(src, str);
@@ -446,8 +468,9 @@ char *strpcat(char *dest, const char *src, const char *str) {
446 } 468 }
447 469
448 dest = realloc(dest, len + l2 + 1); 470 dest = realloc(dest, len + l2 + 1);
449 if (dest == NULL) 471 if (dest == NULL) {
450 die(STATE_UNKNOWN, _("failed malloc in strscat\n")); 472 die(STATE_UNKNOWN, _("failed malloc in strscat\n"));
473 }
451 474
452 strncpy(dest + len, src, l2); 475 strncpy(dest + len, src, l2);
453 dest[len + l2] = '\0'; 476 dest[len + l2] = '\0';
@@ -463,8 +486,9 @@ char *strpcat(char *dest, const char *src, const char *str) {
463 486
464int xvasprintf(char **strp, const char *fmt, va_list ap) { 487int xvasprintf(char **strp, const char *fmt, va_list ap) {
465 int result = vasprintf(strp, fmt, ap); 488 int result = vasprintf(strp, fmt, ap);
466 if (result == -1 || *strp == NULL) 489 if (result == -1 || *strp == NULL) {
467 die(STATE_UNKNOWN, _("failed malloc in xvasprintf\n")); 490 die(STATE_UNKNOWN, _("failed malloc in xvasprintf\n"));
491 }
468 return result; 492 return result;
469} 493}
470 494
@@ -483,126 +507,145 @@ int xasprintf(char **strp, const char *fmt, ...) {
483 * 507 *
484 ******************************************************************************/ 508 ******************************************************************************/
485 509
486char *perfdata(const char *label, long int val, const char *uom, int warnp, long int warn, int critp, long int crit, int minp, 510char *perfdata(const char *label, long int val, const char *uom, bool warnp, long int warn, bool critp, long int crit, bool minp,
487 long int minv, int maxp, long int maxv) { 511 long int minv, bool maxp, long int maxv) {
488 char *data = NULL; 512 char *data = NULL;
489 513
490 if (strpbrk(label, "'= ")) 514 if (strpbrk(label, "'= ")) {
491 xasprintf(&data, "'%s'=%ld%s;", label, val, uom); 515 xasprintf(&data, "'%s'=%ld%s;", label, val, uom);
492 else 516 } else {
493 xasprintf(&data, "%s=%ld%s;", label, val, uom); 517 xasprintf(&data, "%s=%ld%s;", label, val, uom);
518 }
494 519
495 if (warnp) 520 if (warnp) {
496 xasprintf(&data, "%s%ld;", data, warn); 521 xasprintf(&data, "%s%ld;", data, warn);
497 else 522 } else {
498 xasprintf(&data, "%s;", data); 523 xasprintf(&data, "%s;", data);
524 }
499 525
500 if (critp) 526 if (critp) {
501 xasprintf(&data, "%s%ld;", data, crit); 527 xasprintf(&data, "%s%ld;", data, crit);
502 else 528 } else {
503 xasprintf(&data, "%s;", data); 529 xasprintf(&data, "%s;", data);
530 }
504 531
505 if (minp) 532 if (minp) {
506 xasprintf(&data, "%s%ld;", data, minv); 533 xasprintf(&data, "%s%ld;", data, minv);
507 else 534 } else {
508 xasprintf(&data, "%s;", data); 535 xasprintf(&data, "%s;", data);
536 }
509 537
510 if (maxp) 538 if (maxp) {
511 xasprintf(&data, "%s%ld", data, maxv); 539 xasprintf(&data, "%s%ld", data, maxv);
540 }
512 541
513 return data; 542 return data;
514} 543}
515 544
516char *perfdata_uint64(const char *label, uint64_t val, const char *uom, int warnp, /* Warning present */ 545char *perfdata_uint64(const char *label, uint64_t val, const char *uom, bool warnp, /* Warning present */
517 uint64_t warn, int critp, /* Critical present */ 546 uint64_t warn, bool critp, /* Critical present */
518 uint64_t crit, int minp, /* Minimum present */ 547 uint64_t crit, bool minp, /* Minimum present */
519 uint64_t minv, int maxp, /* Maximum present */ 548 uint64_t minv, bool maxp, /* Maximum present */
520 uint64_t maxv) { 549 uint64_t maxv) {
521 char *data = NULL; 550 char *data = NULL;
522 551
523 if (strpbrk(label, "'= ")) 552 if (strpbrk(label, "'= ")) {
524 xasprintf(&data, "'%s'=%" PRIu64 "%s;", label, val, uom); 553 xasprintf(&data, "'%s'=%" PRIu64 "%s;", label, val, uom);
525 else 554 } else {
526 xasprintf(&data, "%s=%" PRIu64 "%s;", label, val, uom); 555 xasprintf(&data, "%s=%" PRIu64 "%s;", label, val, uom);
556 }
527 557
528 if (warnp) 558 if (warnp) {
529 xasprintf(&data, "%s%" PRIu64 ";", data, warn); 559 xasprintf(&data, "%s%" PRIu64 ";", data, warn);
530 else 560 } else {
531 xasprintf(&data, "%s;", data); 561 xasprintf(&data, "%s;", data);
562 }
532 563
533 if (critp) 564 if (critp) {
534 xasprintf(&data, "%s%" PRIu64 ";", data, crit); 565 xasprintf(&data, "%s%" PRIu64 ";", data, crit);
535 else 566 } else {
536 xasprintf(&data, "%s;", data); 567 xasprintf(&data, "%s;", data);
568 }
537 569
538 if (minp) 570 if (minp) {
539 xasprintf(&data, "%s%" PRIu64 ";", data, minv); 571 xasprintf(&data, "%s%" PRIu64 ";", data, minv);
540 else 572 } else {
541 xasprintf(&data, "%s;", data); 573 xasprintf(&data, "%s;", data);
574 }
542 575
543 if (maxp) 576 if (maxp) {
544 xasprintf(&data, "%s%" PRIu64, data, maxv); 577 xasprintf(&data, "%s%" PRIu64, data, maxv);
578 }
545 579
546 return data; 580 return data;
547} 581}
548 582
549char *perfdata_int64(const char *label, int64_t val, const char *uom, int warnp, /* Warning present */ 583char *perfdata_int64(const char *label, int64_t val, const char *uom, bool warnp, /* Warning present */
550 int64_t warn, int critp, /* Critical present */ 584 int64_t warn, bool critp, /* Critical present */
551 int64_t crit, int minp, /* Minimum present */ 585 int64_t crit, bool minp, /* Minimum present */
552 int64_t minv, int maxp, /* Maximum present */ 586 int64_t minv, bool maxp, /* Maximum present */
553 int64_t maxv) { 587 int64_t maxv) {
554 char *data = NULL; 588 char *data = NULL;
555 589
556 if (strpbrk(label, "'= ")) 590 if (strpbrk(label, "'= ")) {
557 xasprintf(&data, "'%s'=%" PRId64 "%s;", label, val, uom); 591 xasprintf(&data, "'%s'=%" PRId64 "%s;", label, val, uom);
558 else 592 } else {
559 xasprintf(&data, "%s=%" PRId64 "%s;", label, val, uom); 593 xasprintf(&data, "%s=%" PRId64 "%s;", label, val, uom);
594 }
560 595
561 if (warnp) 596 if (warnp) {
562 xasprintf(&data, "%s%" PRId64 ";", data, warn); 597 xasprintf(&data, "%s%" PRId64 ";", data, warn);
563 else 598 } else {
564 xasprintf(&data, "%s;", data); 599 xasprintf(&data, "%s;", data);
600 }
565 601
566 if (critp) 602 if (critp) {
567 xasprintf(&data, "%s%" PRId64 ";", data, crit); 603 xasprintf(&data, "%s%" PRId64 ";", data, crit);
568 else 604 } else {
569 xasprintf(&data, "%s;", data); 605 xasprintf(&data, "%s;", data);
606 }
570 607
571 if (minp) 608 if (minp) {
572 xasprintf(&data, "%s%" PRId64 ";", data, minv); 609 xasprintf(&data, "%s%" PRId64 ";", data, minv);
573 else 610 } else {
574 xasprintf(&data, "%s;", data); 611 xasprintf(&data, "%s;", data);
612 }
575 613
576 if (maxp) 614 if (maxp) {
577 xasprintf(&data, "%s%" PRId64, data, maxv); 615 xasprintf(&data, "%s%" PRId64, data, maxv);
616 }
578 617
579 return data; 618 return data;
580} 619}
581 620
582char *fperfdata(const char *label, double val, const char *uom, int warnp, double warn, int critp, double crit, int minp, double minv, 621char *fperfdata(const char *label, double val, const char *uom, bool warnp, double warn, bool critp, double crit, bool minp, double minv,
583 int maxp, double maxv) { 622 bool maxp, double maxv) {
584 char *data = NULL; 623 char *data = NULL;
585 624
586 if (strpbrk(label, "'= ")) 625 if (strpbrk(label, "'= ")) {
587 xasprintf(&data, "'%s'=", label); 626 xasprintf(&data, "'%s'=", label);
588 else 627 } else {
589 xasprintf(&data, "%s=", label); 628 xasprintf(&data, "%s=", label);
629 }
590 630
591 xasprintf(&data, "%s%f", data, val); 631 xasprintf(&data, "%s%f", data, val);
592 xasprintf(&data, "%s%s;", data, uom); 632 xasprintf(&data, "%s%s;", data, uom);
593 633
594 if (warnp) 634 if (warnp) {
595 xasprintf(&data, "%s%f", data, warn); 635 xasprintf(&data, "%s%f", data, warn);
636 }
596 637
597 xasprintf(&data, "%s;", data); 638 xasprintf(&data, "%s;", data);
598 639
599 if (critp) 640 if (critp) {
600 xasprintf(&data, "%s%f", data, crit); 641 xasprintf(&data, "%s%f", data, crit);
642 }
601 643
602 xasprintf(&data, "%s;", data); 644 xasprintf(&data, "%s;", data);
603 645
604 if (minp) 646 if (minp) {
605 xasprintf(&data, "%s%f", data, minv); 647 xasprintf(&data, "%s%f", data, minv);
648 }
606 649
607 if (maxp) { 650 if (maxp) {
608 xasprintf(&data, "%s;", data); 651 xasprintf(&data, "%s;", data);
@@ -612,28 +655,32 @@ char *fperfdata(const char *label, double val, const char *uom, int warnp, doubl
612 return data; 655 return data;
613} 656}
614 657
615char *sperfdata(const char *label, double val, const char *uom, char *warn, char *crit, int minp, double minv, int maxp, double maxv) { 658char *sperfdata(const char *label, double val, const char *uom, char *warn, char *crit, bool minp, double minv, bool maxp, double maxv) {
616 char *data = NULL; 659 char *data = NULL;
617 if (strpbrk(label, "'= ")) 660 if (strpbrk(label, "'= ")) {
618 xasprintf(&data, "'%s'=", label); 661 xasprintf(&data, "'%s'=", label);
619 else 662 } else {
620 xasprintf(&data, "%s=", label); 663 xasprintf(&data, "%s=", label);
664 }
621 665
622 xasprintf(&data, "%s%f", data, val); 666 xasprintf(&data, "%s%f", data, val);
623 xasprintf(&data, "%s%s;", data, uom); 667 xasprintf(&data, "%s%s;", data, uom);
624 668
625 if (warn != NULL) 669 if (warn != NULL) {
626 xasprintf(&data, "%s%s", data, warn); 670 xasprintf(&data, "%s%s", data, warn);
671 }
627 672
628 xasprintf(&data, "%s;", data); 673 xasprintf(&data, "%s;", data);
629 674
630 if (crit != NULL) 675 if (crit != NULL) {
631 xasprintf(&data, "%s%s", data, crit); 676 xasprintf(&data, "%s%s", data, crit);
677 }
632 678
633 xasprintf(&data, "%s;", data); 679 xasprintf(&data, "%s;", data);
634 680
635 if (minp) 681 if (minp) {
636 xasprintf(&data, "%s%f", data, minv); 682 xasprintf(&data, "%s%f", data, minv);
683 }
637 684
638 if (maxp) { 685 if (maxp) {
639 xasprintf(&data, "%s;", data); 686 xasprintf(&data, "%s;", data);
@@ -643,28 +690,32 @@ char *sperfdata(const char *label, double val, const char *uom, char *warn, char
643 return data; 690 return data;
644} 691}
645 692
646char *sperfdata_int(const char *label, int val, const char *uom, char *warn, char *crit, int minp, int minv, int maxp, int maxv) { 693char *sperfdata_int(const char *label, int val, const char *uom, char *warn, char *crit, bool minp, int minv, bool maxp, int maxv) {
647 char *data = NULL; 694 char *data = NULL;
648 if (strpbrk(label, "'= ")) 695 if (strpbrk(label, "'= ")) {
649 xasprintf(&data, "'%s'=", label); 696 xasprintf(&data, "'%s'=", label);
650 else 697 } else {
651 xasprintf(&data, "%s=", label); 698 xasprintf(&data, "%s=", label);
699 }
652 700
653 xasprintf(&data, "%s%d", data, val); 701 xasprintf(&data, "%s%d", data, val);
654 xasprintf(&data, "%s%s;", data, uom); 702 xasprintf(&data, "%s%s;", data, uom);
655 703
656 if (warn != NULL) 704 if (warn != NULL) {
657 xasprintf(&data, "%s%s", data, warn); 705 xasprintf(&data, "%s%s", data, warn);
706 }
658 707
659 xasprintf(&data, "%s;", data); 708 xasprintf(&data, "%s;", data);
660 709
661 if (crit != NULL) 710 if (crit != NULL) {
662 xasprintf(&data, "%s%s", data, crit); 711 xasprintf(&data, "%s%s", data, crit);
712 }
663 713
664 xasprintf(&data, "%s;", data); 714 xasprintf(&data, "%s;", data);
665 715
666 if (minp) 716 if (minp) {
667 xasprintf(&data, "%s%d", data, minv); 717 xasprintf(&data, "%s%d", data, minv);
718 }
668 719
669 if (maxp) { 720 if (maxp) {
670 xasprintf(&data, "%s;", data); 721 xasprintf(&data, "%s;", data);
diff --git a/plugins/utils.h b/plugins/utils.h
index 029ae5a6..92a6c115 100644
--- a/plugins/utils.h
+++ b/plugins/utils.h
@@ -21,43 +21,43 @@ suite of plugins. */
21 21
22#ifdef NP_EXTRA_OPTS 22#ifdef NP_EXTRA_OPTS
23/* Include extra-opts functions if compiled in */ 23/* Include extra-opts functions if compiled in */
24#include "extra_opts.h" 24# include "extra_opts.h"
25#else 25#else
26/* else, fake np_extra_opts */ 26/* else, fake np_extra_opts */
27#define np_extra_opts(acptr,av,pr) av 27# define np_extra_opts(acptr, av, pr) av
28#endif 28#endif
29 29
30/* Standardize version information, termination */ 30/* Standardize version information, termination */
31 31
32void support (void); 32void support(void);
33void print_revision (const char *, const char *); 33void print_revision(const char *, const char *);
34 34
35extern time_t start_time, end_time; 35extern time_t start_time, end_time;
36 36
37/* Test input types */ 37/* Test input types */
38 38
39bool is_integer (char *); 39bool is_integer(char *);
40bool is_intpos (char *); 40bool is_intpos(char *);
41bool is_intneg (char *); 41bool is_intneg(char *);
42bool is_intnonneg (char *); 42bool is_intnonneg(char *);
43bool is_intpercent (char *); 43bool is_intpercent(char *);
44bool is_uint64(char *number, uint64_t *target); 44bool is_uint64(char *number, uint64_t *target);
45bool is_int64(char *number, int64_t *target); 45bool is_int64(char *number, int64_t *target);
46 46
47bool is_numeric (char *); 47bool is_numeric(char *);
48bool is_positive (char *); 48bool is_positive(char *);
49bool is_negative (char *); 49bool is_negative(char *);
50bool is_nonnegative (char *); 50bool is_nonnegative(char *);
51bool is_percentage (char *); 51bool is_percentage(char *);
52bool is_percentage_expression (const char[]); 52bool is_percentage_expression(const char[]);
53 53
54bool is_option (char *); 54bool is_option(char *);
55 55
56/* Generalized timer that will do milliseconds if available */ 56/* Generalized timer that will do milliseconds if available */
57#ifndef HAVE_STRUCT_TIMEVAL 57#ifndef HAVE_STRUCT_TIMEVAL
58struct timeval { 58struct timeval {
59 long tv_sec; /* seconds */ 59 long tv_sec; /* seconds */
60 long tv_usec; /* microseconds */ 60 long tv_usec; /* microseconds */
61}; 61};
62#endif 62#endif
63 63
@@ -65,137 +65,142 @@ struct timeval {
65int gettimeofday(struct timeval *, struct timezone *); 65int gettimeofday(struct timeval *, struct timezone *);
66#endif 66#endif
67 67
68double delta_time (struct timeval tv); 68double delta_time(struct timeval tv);
69long deltime (struct timeval tv); 69long deltime(struct timeval tv);
70 70
71/* Handle strings safely */ 71/* Handle strings safely */
72 72
73void strip (char *); 73void strip(char *);
74char *strscpy (char *, const char *); 74char *strscpy(char *, const char *);
75char *strnl (char *); 75char *strnl(char *);
76char *strpcpy (char *, const char *, const char *); 76char *strpcpy(char *, const char *, const char *);
77char *strpcat (char *, const char *, const char *); 77char *strpcat(char *, const char *, const char *);
78int xvasprintf (char **strp, const char *fmt, va_list ap); 78int xvasprintf(char **strp, const char *fmt, va_list ap);
79int xasprintf (char **strp, const char *fmt, ...); 79int xasprintf(char **strp, const char *fmt, ...);
80 80
81void usage (const char *) __attribute__((noreturn)); 81void usage(const char *) __attribute__((noreturn));
82void usage2(const char *, const char *) __attribute__((noreturn)); 82void usage2(const char *, const char *) __attribute__((noreturn));
83void usage3(const char *, int) __attribute__((noreturn)); 83void usage3(const char *, int) __attribute__((noreturn));
84void usage4(const char *) __attribute__((noreturn)); 84void usage4(const char *) __attribute__((noreturn));
85void usage5(void) __attribute__((noreturn)); 85void usage5(void) __attribute__((noreturn));
86void usage_va(const char *fmt, ...) __attribute__((noreturn)); 86void usage_va(const char *fmt, ...) __attribute__((noreturn));
87 87
88#define max(a,b) (((a)>(b))?(a):(b)) 88#define max(a, b) (((a) > (b)) ? (a) : (b))
89#define min(a,b) (((a)<(b))?(a):(b)) 89#define min(a, b) (((a) < (b)) ? (a) : (b))
90 90
91char *perfdata (const char *, long int, const char *, int, long int, 91char *perfdata(const char *, long int, const char *, bool, long int, bool, long int, bool, long int, bool, long int);
92 int, long int, int, long int, int, long int);
93 92
94char *perfdata_uint64 (const char *, uint64_t , const char *, int, uint64_t, 93char *perfdata_uint64(const char *, uint64_t, const char *, bool, uint64_t, bool, uint64_t, bool, uint64_t, bool, uint64_t);
95 int, uint64_t, int, uint64_t, int, uint64_t);
96 94
97char *perfdata_int64 (const char *, int64_t, const char *, int, int64_t, 95char *perfdata_int64(const char *, int64_t, const char *, bool, int64_t, bool, int64_t, bool, int64_t, bool, int64_t);
98 int, int64_t, int, int64_t, int, int64_t);
99 96
100char *fperfdata (const char *, double, const char *, int, double, 97char *fperfdata(const char *, double, const char *, bool, double, bool, double, bool, double, bool, double);
101 int, double, int, double, int, double);
102 98
103char *sperfdata (const char *, double, const char *, char *, char *, 99char *sperfdata(const char *, double, const char *, char *, char *, bool, double, bool, double);
104 int, double, int, double);
105 100
106char *sperfdata_int (const char *, int, const char *, char *, char *, 101char *sperfdata_int(const char *, int, const char *, char *, char *, bool, int, bool, int);
107 int, int, int, int);
108 102
109/* The idea here is that, although not every plugin will use all of these, 103/* The idea here is that, although not every plugin will use all of these,
110 most will or should. Therefore, for consistency, these very common 104 most will or should. Therefore, for consistency, these very common
111 options should have only these meanings throughout the overall suite */ 105 options should have only these meanings throughout the overall suite */
112 106
113#define STD_LONG_OPTS \ 107#define STD_LONG_OPTS \
114{"version",no_argument,0,'V'},\ 108 {"version", no_argument, 0, 'V'}, {"verbose", no_argument, 0, 'v'}, {"help", no_argument, 0, 'h'}, \
115{"verbose",no_argument,0,'v'},\ 109 {"timeout", required_argument, 0, 't'}, {"critical", required_argument, 0, 'c'}, {"warning", required_argument, 0, 'w'}, \
116{"help",no_argument,0,'h'},\ 110 {"hostname", required_argument, 0, 'H'}
117{"timeout",required_argument,0,'t'},\
118{"critical",required_argument,0,'c'},\
119{"warning",required_argument,0,'w'},\
120{"hostname",required_argument,0,'H'}
121 111
122#define COPYRIGHT "Copyright (c) %s Monitoring Plugins Development Team\n\ 112#define COPYRIGHT \
113 "Copyright (c) %s Monitoring Plugins Development Team\n\
123\t<%s>\n\n" 114\t<%s>\n\n"
124 115
125#define UT_HLP_VRS _("\ 116#define UT_HLP_VRS \
117 _("\
126 %s (-h | --help) for detailed help\n\ 118 %s (-h | --help) for detailed help\n\
127 %s (-V | --version) for version information\n") 119 %s (-V | --version) for version information\n")
128 120
129#define UT_HELP_VRSN _("\ 121#define UT_HELP_VRSN \
122 _("\
130\nOptions:\n\ 123\nOptions:\n\
131 -h, --help\n\ 124 -h, --help\n\
132 Print detailed help screen\n\ 125 Print detailed help screen\n\
133 -V, --version\n\ 126 -V, --version\n\
134 Print version information\n") 127 Print version information\n")
135 128
136#define UT_HOST_PORT _("\ 129#define UT_HOST_PORT \
130 _("\
137 -H, --hostname=ADDRESS\n\ 131 -H, --hostname=ADDRESS\n\
138 Host name, IP Address, or unix socket (must be an absolute path)\n\ 132 Host name, IP Address, or unix socket (must be an absolute path)\n\
139 -%c, --port=INTEGER\n\ 133 -%c, --port=INTEGER\n\
140 Port number (default: %s)\n") 134 Port number (default: %s)\n")
141 135
142#define UT_IPv46 _("\ 136#define UT_IPv46 \
137 _("\
143 -4, --use-ipv4\n\ 138 -4, --use-ipv4\n\
144 Use IPv4 connection\n\ 139 Use IPv4 connection\n\
145 -6, --use-ipv6\n\ 140 -6, --use-ipv6\n\
146 Use IPv6 connection\n") 141 Use IPv6 connection\n")
147 142
148#define UT_VERBOSE _("\ 143#define UT_VERBOSE \
144 _("\
149 -v, --verbose\n\ 145 -v, --verbose\n\
150 Show details for command-line debugging (output may be truncated by\n\ 146 Show details for command-line debugging (output may be truncated by\n\
151 the monitoring system)\n") 147 the monitoring system)\n")
152 148
153#define UT_WARN_CRIT _("\ 149#define UT_WARN_CRIT \
150 _("\
154 -w, --warning=DOUBLE\n\ 151 -w, --warning=DOUBLE\n\
155 Response time to result in warning status (seconds)\n\ 152 Response time to result in warning status (seconds)\n\
156 -c, --critical=DOUBLE\n\ 153 -c, --critical=DOUBLE\n\
157 Response time to result in critical status (seconds)\n") 154 Response time to result in critical status (seconds)\n")
158 155
159#define UT_WARN_CRIT_RANGE _("\ 156#define UT_WARN_CRIT_RANGE \
157 _("\
160 -w, --warning=RANGE\n\ 158 -w, --warning=RANGE\n\
161 Warning range (format: start:end). Alert if outside this range\n\ 159 Warning range (format: start:end). Alert if outside this range\n\
162 -c, --critical=RANGE\n\ 160 -c, --critical=RANGE\n\
163 Critical range\n") 161 Critical range\n")
164 162
165#define UT_CONN_TIMEOUT _("\ 163#define UT_CONN_TIMEOUT \
164 _("\
166 -t, --timeout=INTEGER\n\ 165 -t, --timeout=INTEGER\n\
167 Seconds before connection times out (default: %d)\n") 166 Seconds before connection times out (default: %d)\n")
168 167
169#define UT_PLUG_TIMEOUT _("\ 168#define UT_PLUG_TIMEOUT \
169 _("\
170 -t, --timeout=INTEGER\n\ 170 -t, --timeout=INTEGER\n\
171 Seconds before plugin times out (default: %d)\n") 171 Seconds before plugin times out (default: %d)\n")
172 172
173#ifdef NP_EXTRA_OPTS 173#ifdef NP_EXTRA_OPTS
174#define UT_EXTRA_OPTS _("\ 174# define UT_EXTRA_OPTS \
175 _("\
175 --extra-opts=[section][@file]\n\ 176 --extra-opts=[section][@file]\n\
176 Read options from an ini file. See\n\ 177 Read options from an ini file. See\n\
177 https://www.monitoring-plugins.org/doc/extra-opts.html\n\ 178 https://www.monitoring-plugins.org/doc/extra-opts.html\n\
178 for usage and examples.\n") 179 for usage and examples.\n")
179#else 180#else
180#define UT_EXTRA_OPTS " \b" 181# define UT_EXTRA_OPTS " \b"
181#endif 182#endif
182 183
183#define UT_THRESHOLDS_NOTES _("\ 184#define UT_THRESHOLDS_NOTES \
185 _("\
184 See:\n\ 186 See:\n\
185 https://www.monitoring-plugins.org/doc/guidelines.html#THRESHOLDFORMAT\n\ 187 https://www.monitoring-plugins.org/doc/guidelines.html#THRESHOLDFORMAT\n\
186 for THRESHOLD format and examples.\n") 188 for THRESHOLD format and examples.\n")
187 189
188#define UT_SUPPORT _("\n\ 190#define UT_SUPPORT \
191 _("\n\
189Send email to help@monitoring-plugins.org if you have questions regarding\n\ 192Send email to help@monitoring-plugins.org if you have questions regarding\n\
190use of this software. To submit patches or suggest improvements, send email\n\ 193use of this software. To submit patches or suggest improvements, send email\n\
191to devel@monitoring-plugins.org\n\n") 194to devel@monitoring-plugins.org\n\n")
192 195
193#define UT_NOWARRANTY _("\n\ 196#define UT_NOWARRANTY \
197 _("\n\
194The Monitoring Plugins come with ABSOLUTELY NO WARRANTY. You may redistribute\n\ 198The Monitoring Plugins come with ABSOLUTELY NO WARRANTY. You may redistribute\n\
195copies of the plugins under the terms of the GNU General Public License.\n\ 199copies of the plugins under the terms of the GNU General Public License.\n\
196For more information about these matters, see the file named COPYING.\n") 200For more information about these matters, see the file named COPYING.\n")
197 201
198#define UT_OUTPUT_FORMAT _("\ 202#define UT_OUTPUT_FORMAT \
203 _("\
199 --output-format=OUTPUT_FORMAT\n\ 204 --output-format=OUTPUT_FORMAT\n\
200 Select output format. Valid values: \"multi-line\", \"mp-test-json\"\n") 205 Select output format. Valid values: \"multi-line\", \"mp-test-json\"\n")
201 206