diff options
| -rw-r--r-- | .github/workflows/codeql-analysis.yml | 4 | ||||
| -rw-r--r-- | plugins/check_apt.c | 251 | ||||
| -rw-r--r-- | plugins/check_apt.d/config.h | 9 | ||||
| -rw-r--r-- | plugins/check_by_ssh.c | 23 | ||||
| -rw-r--r-- | plugins/check_by_ssh.d/config.h | 2 | ||||
| -rw-r--r-- | plugins/check_cluster.c | 73 | ||||
| -rw-r--r-- | plugins/check_cluster.d/config.h | 6 | ||||
| -rw-r--r-- | plugins/check_curl.d/check_curl_helpers.c | 20 | ||||
| -rw-r--r-- | plugins/check_mysql.c | 44 | ||||
| -rw-r--r-- | plugins/check_ntp_peer.c | 360 | ||||
| -rw-r--r-- | plugins/check_ntp_peer.d/config.h | 63 | ||||
| -rw-r--r-- | plugins/check_ntp_time.c | 188 | ||||
| -rw-r--r-- | plugins/check_ntp_time.d/config.h | 19 | ||||
| -rw-r--r-- | plugins/check_pgsql.c | 292 | ||||
| -rw-r--r-- | plugins/check_pgsql.d/config.h | 29 | ||||
| -rw-r--r-- | plugins/check_snmp.c | 2 | ||||
| -rw-r--r-- | plugins/check_swap.d/swap.c | 4 | ||||
| -rw-r--r-- | plugins/check_users.c | 2 | ||||
| -rw-r--r-- | plugins/check_users.d/users.c | 2 | ||||
| -rw-r--r-- | plugins/t/check_apt.t | 14 |
20 files changed, 914 insertions, 493 deletions
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index e01aa5fc..8f191037 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml | |||
| @@ -45,7 +45,7 @@ jobs: | |||
| 45 | 45 | ||
| 46 | # Initializes the CodeQL tools for scanning. | 46 | # Initializes the CodeQL tools for scanning. |
| 47 | - name: Initialize CodeQL | 47 | - name: Initialize CodeQL |
| 48 | uses: github/codeql-action/init@v3 | 48 | uses: github/codeql-action/init@v4 |
| 49 | with: | 49 | with: |
| 50 | languages: ${{ matrix.language }} | 50 | languages: ${{ matrix.language }} |
| 51 | # If you wish to specify custom queries, you can do so here or in a config file. | 51 | # If you wish to specify custom queries, you can do so here or in a config file. |
| @@ -82,4 +82,4 @@ jobs: | |||
| 82 | make | 82 | make |
| 83 | 83 | ||
| 84 | - name: Perform CodeQL Analysis | 84 | - name: Perform CodeQL Analysis |
| 85 | uses: github/codeql-action/analyze@v3 | 85 | uses: github/codeql-action/analyze@v4 |
diff --git a/plugins/check_apt.c b/plugins/check_apt.c index ab66a8d2..9ed5b6cf 100644 --- a/plugins/check_apt.c +++ b/plugins/check_apt.c | |||
| @@ -29,31 +29,33 @@ | |||
| 29 | * | 29 | * |
| 30 | *****************************************************************************/ | 30 | *****************************************************************************/ |
| 31 | 31 | ||
| 32 | #include "states.h" | 32 | #include "perfdata.h" |
| 33 | const char *progname = "check_apt"; | 33 | const char *progname = "check_apt"; |
| 34 | const char *copyright = "2006-2024"; | 34 | const char *copyright = "2006-2024"; |
| 35 | const char *email = "devel@monitoring-plugins.org"; | 35 | const char *email = "devel@monitoring-plugins.org"; |
| 36 | 36 | ||
| 37 | #include "states.h" | ||
| 38 | #include "output.h" | ||
| 37 | #include "common.h" | 39 | #include "common.h" |
| 38 | #include "runcmd.h" | 40 | #include "runcmd.h" |
| 39 | #include "utils.h" | 41 | #include "utils.h" |
| 40 | #include "regex.h" | 42 | #include "regex.h" |
| 41 | #include "check_apt.d/config.h" | 43 | #include "check_apt.d/config.h" |
| 42 | 44 | ||
| 43 | /* Character for hidden input file option (for testing). */ | ||
| 44 | #define INPUT_FILE_OPT CHAR_MAX + 1 | ||
| 45 | /* the default opts can be overridden via the cmdline */ | 45 | /* the default opts can be overridden via the cmdline */ |
| 46 | #define UPGRADE_DEFAULT_OPTS "-o 'Debug::NoLocking=true' -s -qq" | 46 | const char *UPGRADE_DEFAULT_OPTS = "-o 'Debug::NoLocking=true' -s -qq"; |
| 47 | #define UPDATE_DEFAULT_OPTS "-q" | 47 | const char *UPDATE_DEFAULT_OPTS = "-q"; |
| 48 | |||
| 48 | /* until i commit the configure.in patch which gets this, i'll define | 49 | /* until i commit the configure.in patch which gets this, i'll define |
| 49 | * it here as well */ | 50 | * it here as well */ |
| 50 | #ifndef PATH_TO_APTGET | 51 | #ifndef PATH_TO_APTGET |
| 51 | # define PATH_TO_APTGET "/usr/bin/apt-get" | 52 | # define PATH_TO_APTGET "/usr/bin/apt-get" |
| 52 | #endif /* PATH_TO_APTGET */ | 53 | #endif /* PATH_TO_APTGET */ |
| 54 | |||
| 53 | /* String found at the beginning of the apt output lines we're interested in */ | 55 | /* String found at the beginning of the apt output lines we're interested in */ |
| 54 | #define PKGINST_PREFIX "Inst " | 56 | const char *PKGINST_PREFIX = "Inst "; |
| 55 | /* the RE that catches security updates */ | 57 | /* the RE that catches security updates */ |
| 56 | #define SECURITY_RE "^[^\\(]*\\(.* (Debian-Security:|Ubuntu:[^/]*/[^-]*-security)" | 58 | const char *SECURITY_RE = "^[^\\(]*\\(.* (Debian-Security:|Ubuntu:[^/]*/[^-]*-security)"; |
| 57 | 59 | ||
| 58 | /* some standard functions */ | 60 | /* some standard functions */ |
| 59 | typedef struct { | 61 | typedef struct { |
| @@ -66,20 +68,28 @@ void print_usage(void); | |||
| 66 | 68 | ||
| 67 | /* construct the appropriate apt-get cmdline */ | 69 | /* construct the appropriate apt-get cmdline */ |
| 68 | static char *construct_cmdline(upgrade_type /*u*/, const char * /*opts*/); | 70 | static char *construct_cmdline(upgrade_type /*u*/, const char * /*opts*/); |
| 71 | |||
| 69 | /* run an apt-get update */ | 72 | /* run an apt-get update */ |
| 70 | static int run_update(char * /*update_opts*/); | 73 | typedef struct { |
| 74 | mp_subcheck sc; | ||
| 75 | bool stderr_warning; | ||
| 76 | bool exec_warning; | ||
| 77 | } run_update_result; | ||
| 78 | static run_update_result run_update(char *update_opts); | ||
| 71 | 79 | ||
| 72 | typedef struct { | 80 | typedef struct { |
| 73 | int errorcode; | 81 | int errorcode; |
| 74 | int package_count; | 82 | size_t package_count; |
| 75 | int security_package_count; | 83 | size_t security_package_count; |
| 76 | char **packages_list; | 84 | char **packages_list; |
| 77 | char **secpackages_list; | 85 | char **secpackages_list; |
| 86 | bool exec_warning; | ||
| 78 | } run_upgrade_result; | 87 | } run_upgrade_result; |
| 79 | 88 | ||
| 80 | /* run an apt-get upgrade */ | 89 | /* run an apt-get upgrade */ |
| 81 | run_upgrade_result run_upgrade(upgrade_type upgrade, const char *do_include, const char *do_exclude, const char *do_critical, | 90 | run_upgrade_result run_upgrade(upgrade_type upgrade, const char *do_include, const char *do_exclude, |
| 82 | const char *upgrade_opts, const char *input_filename); | 91 | const char *do_critical, const char *upgrade_opts, |
| 92 | const char *input_filename); | ||
| 83 | 93 | ||
| 84 | /* add another clause to a regexp */ | 94 | /* add another clause to a regexp */ |
| 85 | static char *add_to_regexp(char * /*expr*/, const char * /*next*/); | 95 | static char *add_to_regexp(char * /*expr*/, const char * /*next*/); |
| @@ -107,6 +117,10 @@ int main(int argc, char **argv) { | |||
| 107 | 117 | ||
| 108 | const check_apt_config config = tmp_config.config; | 118 | const check_apt_config config = tmp_config.config; |
| 109 | 119 | ||
| 120 | if (config.output_format_is_set) { | ||
| 121 | mp_set_format(config.output_format); | ||
| 122 | } | ||
| 123 | |||
| 110 | /* Set signal handling and alarm timeout */ | 124 | /* Set signal handling and alarm timeout */ |
| 111 | if (signal(SIGALRM, timeout_alarm_handler) == SIG_ERR) { | 125 | if (signal(SIGALRM, timeout_alarm_handler) == SIG_ERR) { |
| 112 | usage_va(_("Cannot catch SIGALRM")); | 126 | usage_va(_("Cannot catch SIGALRM")); |
| @@ -115,55 +129,91 @@ int main(int argc, char **argv) { | |||
| 115 | /* handle timeouts gracefully... */ | 129 | /* handle timeouts gracefully... */ |
| 116 | alarm(timeout_interval); | 130 | alarm(timeout_interval); |
| 117 | 131 | ||
| 118 | mp_state_enum result = STATE_UNKNOWN; | 132 | mp_check overall = mp_check_init(); |
| 119 | /* if they want to run apt-get update first... */ | 133 | /* if they want to run apt-get update first... */ |
| 120 | if (config.do_update) { | 134 | if (config.do_update) { |
| 121 | result = run_update(config.update_opts); | 135 | run_update_result update_result = run_update(config.update_opts); |
| 136 | |||
| 137 | mp_add_subcheck_to_check(&overall, update_result.sc); | ||
| 122 | } | 138 | } |
| 123 | 139 | ||
| 124 | /* apt-get upgrade */ | 140 | /* apt-get upgrade */ |
| 125 | run_upgrade_result upgrad_res = | 141 | run_upgrade_result upgrad_res = |
| 126 | run_upgrade(config.upgrade, config.do_include, config.do_exclude, config.do_critical, config.upgrade_opts, config.input_filename); | 142 | run_upgrade(config.upgrade, config.do_include, config.do_exclude, config.do_critical, |
| 143 | config.upgrade_opts, config.input_filename); | ||
| 144 | |||
| 145 | mp_subcheck sc_run_upgrade = mp_subcheck_init(); | ||
| 146 | if (upgrad_res.errorcode == OK) { | ||
| 147 | sc_run_upgrade = mp_set_subcheck_state(sc_run_upgrade, STATE_OK); | ||
| 148 | } | ||
| 149 | xasprintf(&sc_run_upgrade.output, "Executed apt upgrade (dry run)"); | ||
| 127 | 150 | ||
| 128 | result = max_state(result, upgrad_res.errorcode); | 151 | mp_add_subcheck_to_check(&overall, sc_run_upgrade); |
| 129 | int packages_available = upgrad_res.package_count; | 152 | |
| 130 | int sec_count = upgrad_res.security_package_count; | 153 | size_t packages_available = upgrad_res.package_count; |
| 154 | size_t number_of_security_updates = upgrad_res.security_package_count; | ||
| 131 | char **packages_list = upgrad_res.packages_list; | 155 | char **packages_list = upgrad_res.packages_list; |
| 132 | char **secpackages_list = upgrad_res.secpackages_list; | 156 | char **secpackages_list = upgrad_res.secpackages_list; |
| 133 | 157 | ||
| 134 | if (sec_count > 0) { | 158 | mp_perfdata pd_security_updates = perfdata_init(); |
| 135 | result = max_state(result, STATE_CRITICAL); | 159 | pd_security_updates.value = mp_create_pd_value(number_of_security_updates); |
| 136 | } else if (packages_available >= config.packages_warning && !config.only_critical) { | 160 | pd_security_updates.label = "critical_updates"; |
| 137 | result = max_state(result, STATE_WARNING); | 161 | |
| 138 | } else if (result > STATE_UNKNOWN) { | 162 | mp_subcheck sc_security_updates = mp_subcheck_init(); |
| 139 | result = STATE_UNKNOWN; | 163 | xasprintf(&sc_security_updates.output, "Security updates available: %zu", |
| 164 | number_of_security_updates); | ||
| 165 | mp_add_perfdata_to_subcheck(&sc_security_updates, pd_security_updates); | ||
| 166 | |||
| 167 | if (number_of_security_updates > 0) { | ||
| 168 | sc_security_updates = mp_set_subcheck_state(sc_security_updates, STATE_CRITICAL); | ||
| 169 | } else { | ||
| 170 | sc_security_updates = mp_set_subcheck_state(sc_security_updates, STATE_OK); | ||
| 140 | } | 171 | } |
| 141 | 172 | ||
| 142 | printf(_("APT %s: %d packages available for %s (%d critical updates). %s%s%s%s|available_upgrades=%d;;;0 critical_updates=%d;;;0\n"), | 173 | mp_perfdata pd_other_updates = perfdata_init(); |
| 143 | state_text(result), packages_available, (config.upgrade == DIST_UPGRADE) ? "dist-upgrade" : "upgrade", sec_count, | 174 | pd_other_updates.value = mp_create_pd_value(packages_available); |
| 144 | (stderr_warning) ? " warnings detected" : "", (stderr_warning && exec_warning) ? "," : "", | 175 | pd_other_updates.label = "available_upgrades"; |
| 145 | (exec_warning) ? " errors detected" : "", (stderr_warning || exec_warning) ? "." : "", packages_available, sec_count); | 176 | |
| 177 | mp_subcheck sc_other_updates = mp_subcheck_init(); | ||
| 178 | |||
| 179 | xasprintf(&sc_other_updates.output, "Updates available: %zu", packages_available); | ||
| 180 | sc_other_updates = mp_set_subcheck_default_state(sc_other_updates, STATE_OK); | ||
| 181 | mp_add_perfdata_to_subcheck(&sc_other_updates, pd_other_updates); | ||
| 182 | |||
| 183 | if (packages_available >= config.packages_warning && !config.only_critical) { | ||
| 184 | sc_other_updates = mp_set_subcheck_state(sc_other_updates, STATE_WARNING); | ||
| 185 | } | ||
| 146 | 186 | ||
| 147 | if (config.list) { | 187 | if (config.list) { |
| 148 | qsort(secpackages_list, sec_count, sizeof(char *), cmpstringp); | 188 | qsort(secpackages_list, number_of_security_updates, sizeof(char *), cmpstringp); |
| 149 | qsort(packages_list, packages_available - sec_count, sizeof(char *), cmpstringp); | 189 | qsort(packages_list, packages_available - number_of_security_updates, sizeof(char *), |
| 190 | cmpstringp); | ||
| 150 | 191 | ||
| 151 | for (int i = 0; i < sec_count; i++) { | 192 | for (size_t i = 0; i < number_of_security_updates; i++) { |
| 152 | printf("%s (security)\n", secpackages_list[i]); | 193 | xasprintf(&sc_security_updates.output, "%s\n%s (security)", sc_security_updates.output, |
| 194 | secpackages_list[i]); | ||
| 153 | } | 195 | } |
| 154 | 196 | ||
| 155 | if (!config.only_critical) { | 197 | if (!config.only_critical) { |
| 156 | for (int i = 0; i < packages_available - sec_count; i++) { | 198 | for (size_t i = 0; i < packages_available - number_of_security_updates; i++) { |
| 157 | printf("%s\n", packages_list[i]); | 199 | xasprintf(&sc_other_updates.output, "%s\n%s", sc_other_updates.output, |
| 200 | packages_list[i]); | ||
| 158 | } | 201 | } |
| 159 | } | 202 | } |
| 160 | } | 203 | } |
| 204 | mp_add_subcheck_to_check(&overall, sc_security_updates); | ||
| 205 | mp_add_subcheck_to_check(&overall, sc_other_updates); | ||
| 161 | 206 | ||
| 162 | return result; | 207 | mp_exit(overall); |
| 163 | } | 208 | } |
| 164 | 209 | ||
| 165 | /* process command-line arguments */ | 210 | /* process command-line arguments */ |
| 166 | check_apt_config_wrapper process_arguments(int argc, char **argv) { | 211 | check_apt_config_wrapper process_arguments(int argc, char **argv) { |
| 212 | enum { | ||
| 213 | /* Character for hidden input file option (for testing). */ | ||
| 214 | INPUT_FILE_OPT = CHAR_MAX + 1, | ||
| 215 | output_format_index, | ||
| 216 | }; | ||
| 167 | static struct option longopts[] = {{"version", no_argument, 0, 'V'}, | 217 | static struct option longopts[] = {{"version", no_argument, 0, 'V'}, |
| 168 | {"help", no_argument, 0, 'h'}, | 218 | {"help", no_argument, 0, 'h'}, |
| 169 | {"verbose", no_argument, 0, 'v'}, | 219 | {"verbose", no_argument, 0, 'v'}, |
| @@ -179,6 +229,7 @@ check_apt_config_wrapper process_arguments(int argc, char **argv) { | |||
| 179 | {"only-critical", no_argument, 0, 'o'}, | 229 | {"only-critical", no_argument, 0, 'o'}, |
| 180 | {"input-file", required_argument, 0, INPUT_FILE_OPT}, | 230 | {"input-file", required_argument, 0, INPUT_FILE_OPT}, |
| 181 | {"packages-warning", required_argument, 0, 'w'}, | 231 | {"packages-warning", required_argument, 0, 'w'}, |
| 232 | {"output-format", required_argument, 0, output_format_index}, | ||
| 182 | {0, 0, 0, 0}}; | 233 | {0, 0, 0, 0}}; |
| 183 | 234 | ||
| 184 | check_apt_config_wrapper result = { | 235 | check_apt_config_wrapper result = { |
| @@ -257,6 +308,18 @@ check_apt_config_wrapper process_arguments(int argc, char **argv) { | |||
| 257 | case 'w': | 308 | case 'w': |
| 258 | result.config.packages_warning = atoi(optarg); | 309 | result.config.packages_warning = atoi(optarg); |
| 259 | break; | 310 | break; |
| 311 | case output_format_index: { | ||
| 312 | parsed_output_format parser = mp_parse_output_format(optarg); | ||
| 313 | if (!parser.parsing_success) { | ||
| 314 | // TODO List all available formats here, maybe add anothoer usage function | ||
| 315 | printf("Invalid output format: %s\n", optarg); | ||
| 316 | exit(STATE_UNKNOWN); | ||
| 317 | } | ||
| 318 | |||
| 319 | result.config.output_format_is_set = true; | ||
| 320 | result.config.output_format = parser.output_format; | ||
| 321 | break; | ||
| 322 | } | ||
| 260 | default: | 323 | default: |
| 261 | /* print short usage statement if args not parsable */ | 324 | /* print short usage statement if args not parsable */ |
| 262 | usage5(); | 325 | usage5(); |
| @@ -267,37 +330,38 @@ check_apt_config_wrapper process_arguments(int argc, char **argv) { | |||
| 267 | } | 330 | } |
| 268 | 331 | ||
| 269 | /* run an apt-get upgrade */ | 332 | /* run an apt-get upgrade */ |
| 270 | run_upgrade_result run_upgrade(const upgrade_type upgrade, const char *do_include, const char *do_exclude, const char *do_critical, | 333 | run_upgrade_result run_upgrade(const upgrade_type upgrade, const char *do_include, |
| 334 | const char *do_exclude, const char *do_critical, | ||
| 271 | const char *upgrade_opts, const char *input_filename) { | 335 | const char *upgrade_opts, const char *input_filename) { |
| 272 | regex_t ereg; | 336 | regex_t exclude_regex; |
| 273 | /* initialize ereg as it is possible it is printed while uninitialized */ | 337 | /* initialize ereg as it is possible it is printed while uninitialized */ |
| 274 | memset(&ereg, '\0', sizeof(ereg.buffer)); | 338 | memset(&exclude_regex, '\0', sizeof(exclude_regex.buffer)); |
| 275 | 339 | ||
| 276 | run_upgrade_result result = { | 340 | run_upgrade_result result = { |
| 277 | .errorcode = STATE_UNKNOWN, | 341 | .errorcode = OK, |
| 278 | }; | 342 | }; |
| 279 | 343 | ||
| 280 | if (upgrade == NO_UPGRADE) { | 344 | if (upgrade == NO_UPGRADE) { |
| 281 | result.errorcode = STATE_OK; | 345 | result.errorcode = OK; |
| 282 | return result; | 346 | return result; |
| 283 | } | 347 | } |
| 284 | 348 | ||
| 285 | int regres = 0; | 349 | int regres = 0; |
| 286 | regex_t ireg; | 350 | regex_t include_regex; |
| 287 | char rerrbuf[64]; | 351 | char rerrbuf[64]; |
| 288 | /* compile the regexps */ | 352 | /* compile the regexps */ |
| 289 | if (do_include != NULL) { | 353 | if (do_include != NULL) { |
| 290 | regres = regcomp(&ireg, do_include, REG_EXTENDED); | 354 | regres = regcomp(&include_regex, do_include, REG_EXTENDED); |
| 291 | if (regres != 0) { | 355 | if (regres != 0) { |
| 292 | regerror(regres, &ireg, rerrbuf, 64); | 356 | regerror(regres, &include_regex, rerrbuf, 64); |
| 293 | die(STATE_UNKNOWN, _("%s: Error compiling regexp: %s"), progname, rerrbuf); | 357 | die(STATE_UNKNOWN, _("%s: Error compiling regexp: %s"), progname, rerrbuf); |
| 294 | } | 358 | } |
| 295 | } | 359 | } |
| 296 | 360 | ||
| 297 | if (do_exclude != NULL) { | 361 | if (do_exclude != NULL) { |
| 298 | regres = regcomp(&ereg, do_exclude, REG_EXTENDED); | 362 | regres = regcomp(&exclude_regex, do_exclude, REG_EXTENDED); |
| 299 | if (regres != 0) { | 363 | if (regres != 0) { |
| 300 | regerror(regres, &ereg, rerrbuf, 64); | 364 | regerror(regres, &exclude_regex, rerrbuf, 64); |
| 301 | die(STATE_UNKNOWN, _("%s: Error compiling regexp: %s"), progname, rerrbuf); | 365 | die(STATE_UNKNOWN, _("%s: Error compiling regexp: %s"), progname, rerrbuf); |
| 302 | } | 366 | } |
| 303 | } | 367 | } |
| @@ -306,7 +370,7 @@ run_upgrade_result run_upgrade(const upgrade_type upgrade, const char *do_includ | |||
| 306 | const char *crit_ptr = (do_critical != NULL) ? do_critical : SECURITY_RE; | 370 | const char *crit_ptr = (do_critical != NULL) ? do_critical : SECURITY_RE; |
| 307 | regres = regcomp(&sreg, crit_ptr, REG_EXTENDED); | 371 | regres = regcomp(&sreg, crit_ptr, REG_EXTENDED); |
| 308 | if (regres != 0) { | 372 | if (regres != 0) { |
| 309 | regerror(regres, &ereg, rerrbuf, 64); | 373 | regerror(regres, &exclude_regex, rerrbuf, 64); |
| 310 | die(STATE_UNKNOWN, _("%s: Error compiling regexp: %s"), progname, rerrbuf); | 374 | die(STATE_UNKNOWN, _("%s: Error compiling regexp: %s"), progname, rerrbuf); |
| 311 | } | 375 | } |
| 312 | 376 | ||
| @@ -322,13 +386,12 @@ run_upgrade_result run_upgrade(const upgrade_type upgrade, const char *do_includ | |||
| 322 | result.errorcode = np_runcmd(cmdline, &chld_out, &chld_err, 0); | 386 | result.errorcode = np_runcmd(cmdline, &chld_out, &chld_err, 0); |
| 323 | } | 387 | } |
| 324 | 388 | ||
| 325 | /* apt-get upgrade only changes exit status if there is an | 389 | // apt-get upgrade only changes exit status if there is an |
| 326 | * internal error when run in dry-run mode. therefore we will | 390 | // internal error when run in dry-run mode. |
| 327 | * treat such an error as UNKNOWN */ | 391 | if (result.errorcode != 0) { |
| 328 | if (result.errorcode != STATE_OK) { | 392 | result.exec_warning = true; |
| 329 | exec_warning = 1; | 393 | result.errorcode = ERROR; |
| 330 | result.errorcode = STATE_UNKNOWN; | 394 | // fprintf(stderr, _("'%s' exited with non-zero status.\n"), cmdline); |
| 331 | fprintf(stderr, _("'%s' exited with non-zero status.\n"), cmdline); | ||
| 332 | } | 395 | } |
| 333 | 396 | ||
| 334 | char **pkglist = malloc(sizeof(char *) * chld_out.lines); | 397 | char **pkglist = malloc(sizeof(char *) * chld_out.lines); |
| @@ -349,27 +412,31 @@ run_upgrade_result run_upgrade(const upgrade_type upgrade, const char *do_includ | |||
| 349 | * we may need to switch to the --print-uris output format, | 412 | * we may need to switch to the --print-uris output format, |
| 350 | * in which case the logic here will slightly change. | 413 | * in which case the logic here will slightly change. |
| 351 | */ | 414 | */ |
| 352 | int package_counter = 0; | 415 | size_t package_counter = 0; |
| 353 | int security_package_counter = 0; | 416 | size_t security_package_counter = 0; |
| 354 | for (size_t i = 0; i < chld_out.lines; i++) { | 417 | for (size_t i = 0; i < chld_out.lines; i++) { |
| 355 | if (verbose) { | 418 | if (verbose) { |
| 356 | printf("%s\n", chld_out.line[i]); | 419 | printf("%s\n", chld_out.line[i]); |
| 357 | } | 420 | } |
| 421 | |||
| 358 | /* if it is a package we care about */ | 422 | /* if it is a package we care about */ |
| 359 | if (strncmp(PKGINST_PREFIX, chld_out.line[i], strlen(PKGINST_PREFIX)) == 0 && | 423 | if (strncmp(PKGINST_PREFIX, chld_out.line[i], strlen(PKGINST_PREFIX)) == 0 && |
| 360 | (do_include == NULL || regexec(&ireg, chld_out.line[i], 0, NULL, 0) == 0)) { | 424 | (do_include == NULL || regexec(&include_regex, chld_out.line[i], 0, NULL, 0) == 0)) { |
| 361 | /* if we're not excluding, or it's not in the | 425 | /* if we're not excluding, or it's not in the |
| 362 | * list of stuff to exclude */ | 426 | * list of stuff to exclude */ |
| 363 | if (do_exclude == NULL || regexec(&ereg, chld_out.line[i], 0, NULL, 0) != 0) { | 427 | if (do_exclude == NULL || regexec(&exclude_regex, chld_out.line[i], 0, NULL, 0) != 0) { |
| 364 | package_counter++; | 428 | package_counter++; |
| 365 | if (regexec(&sreg, chld_out.line[i], 0, NULL, 0) == 0) { | 429 | if (regexec(&sreg, chld_out.line[i], 0, NULL, 0) == 0) { |
| 366 | security_package_counter++; | 430 | security_package_counter++; |
| 431 | |||
| 367 | if (verbose) { | 432 | if (verbose) { |
| 368 | printf("*"); | 433 | printf("*"); |
| 369 | } | 434 | } |
| 435 | |||
| 370 | (secpkglist)[security_package_counter - 1] = pkg_name(chld_out.line[i]); | 436 | (secpkglist)[security_package_counter - 1] = pkg_name(chld_out.line[i]); |
| 371 | } else { | 437 | } else { |
| 372 | (pkglist)[package_counter - security_package_counter - 1] = pkg_name(chld_out.line[i]); | 438 | (pkglist)[package_counter - security_package_counter - 1] = |
| 439 | pkg_name(chld_out.line[i]); | ||
| 373 | } | 440 | } |
| 374 | if (verbose) { | 441 | if (verbose) { |
| 375 | printf("*%s\n", chld_out.line[i]); | 442 | printf("*%s\n", chld_out.line[i]); |
| @@ -377,6 +444,7 @@ run_upgrade_result run_upgrade(const upgrade_type upgrade, const char *do_includ | |||
| 377 | } | 444 | } |
| 378 | } | 445 | } |
| 379 | } | 446 | } |
| 447 | |||
| 380 | result.package_count = package_counter; | 448 | result.package_count = package_counter; |
| 381 | result.security_package_count = security_package_counter; | 449 | result.security_package_count = security_package_counter; |
| 382 | result.packages_list = pkglist; | 450 | result.packages_list = pkglist; |
| @@ -385,41 +453,55 @@ run_upgrade_result run_upgrade(const upgrade_type upgrade, const char *do_includ | |||
| 385 | /* If we get anything on stderr, at least set warning */ | 453 | /* If we get anything on stderr, at least set warning */ |
| 386 | if (input_filename == NULL && chld_err.buflen) { | 454 | if (input_filename == NULL && chld_err.buflen) { |
| 387 | stderr_warning = true; | 455 | stderr_warning = true; |
| 388 | result.errorcode = max_state(result.errorcode, STATE_WARNING); | 456 | result.errorcode = ERROR; |
| 457 | |||
| 389 | if (verbose) { | 458 | if (verbose) { |
| 390 | for (size_t i = 0; i < chld_err.lines; i++) { | 459 | for (size_t i = 0; i < chld_err.lines; i++) { |
| 391 | fprintf(stderr, "%s\n", chld_err.line[i]); | 460 | fprintf(stderr, "%s\n", chld_err.line[i]); |
| 392 | } | 461 | } |
| 393 | } | 462 | } |
| 394 | } | 463 | } |
| 464 | |||
| 395 | if (do_include != NULL) { | 465 | if (do_include != NULL) { |
| 396 | regfree(&ireg); | 466 | regfree(&include_regex); |
| 397 | } | 467 | } |
| 468 | |||
| 398 | regfree(&sreg); | 469 | regfree(&sreg); |
| 470 | |||
| 399 | if (do_exclude != NULL) { | 471 | if (do_exclude != NULL) { |
| 400 | regfree(&ereg); | 472 | regfree(&exclude_regex); |
| 401 | } | 473 | } |
| 474 | |||
| 402 | free(cmdline); | 475 | free(cmdline); |
| 476 | |||
| 403 | return result; | 477 | return result; |
| 404 | } | 478 | } |
| 405 | 479 | ||
| 406 | /* run an apt-get update (needs root) */ | 480 | /* run an apt-get update (needs root) */ |
| 407 | int run_update(char *update_opts) { | 481 | run_update_result run_update(char *update_opts) { |
| 408 | int result = STATE_UNKNOWN; | ||
| 409 | char *cmdline; | 482 | char *cmdline; |
| 410 | /* run the update */ | 483 | /* run the update */ |
| 411 | cmdline = construct_cmdline(NO_UPGRADE, update_opts); | 484 | cmdline = construct_cmdline(NO_UPGRADE, update_opts); |
| 412 | 485 | ||
| 486 | run_update_result result = { | ||
| 487 | .exec_warning = false, | ||
| 488 | .stderr_warning = false, | ||
| 489 | .sc = mp_subcheck_init(), | ||
| 490 | }; | ||
| 491 | |||
| 492 | result.sc = mp_set_subcheck_default_state(result.sc, STATE_OK); | ||
| 493 | xasprintf(&result.sc.output, "executing '%s' first", cmdline); | ||
| 494 | |||
| 413 | output chld_out; | 495 | output chld_out; |
| 414 | output chld_err; | 496 | output chld_err; |
| 415 | result = np_runcmd(cmdline, &chld_out, &chld_err, 0); | 497 | int cmd_error = np_runcmd(cmdline, &chld_out, &chld_err, 0); |
| 416 | /* apt-get update changes exit status if it can't fetch packages. | 498 | /* apt-get update changes exit status if it can't fetch packages. |
| 417 | * since we were explicitly asked to do so, this is treated as | 499 | * since we were explicitly asked to do so, this is treated as |
| 418 | * a critical error. */ | 500 | * a critical error. */ |
| 419 | if (result != 0) { | 501 | if (cmd_error != 0) { |
| 420 | exec_warning = true; | 502 | exec_warning = true; |
| 421 | result = STATE_CRITICAL; | 503 | result.sc = mp_set_subcheck_state(result.sc, STATE_CRITICAL); |
| 422 | fprintf(stderr, _("'%s' exited with non-zero status.\n"), cmdline); | 504 | xasprintf(&result.sc.output, _("'%s' exited with non-zero status.\n"), cmdline); |
| 423 | } | 505 | } |
| 424 | 506 | ||
| 425 | if (verbose) { | 507 | if (verbose) { |
| @@ -430,15 +512,18 @@ int run_update(char *update_opts) { | |||
| 430 | 512 | ||
| 431 | /* If we get anything on stderr, at least set warning */ | 513 | /* If we get anything on stderr, at least set warning */ |
| 432 | if (chld_err.buflen) { | 514 | if (chld_err.buflen) { |
| 433 | stderr_warning = 1; | 515 | stderr_warning = true; |
| 434 | result = max_state(result, STATE_WARNING); | 516 | result.sc = mp_set_subcheck_state( |
| 517 | result.sc, max_state(mp_compute_subcheck_state(result.sc), STATE_WARNING)); | ||
| 435 | if (verbose) { | 518 | if (verbose) { |
| 436 | for (size_t i = 0; i < chld_err.lines; i++) { | 519 | for (size_t i = 0; i < chld_err.lines; i++) { |
| 437 | fprintf(stderr, "%s\n", chld_err.line[i]); | 520 | fprintf(stderr, "%s\n", chld_err.line[i]); |
| 438 | } | 521 | } |
| 439 | } | 522 | } |
| 440 | } | 523 | } |
| 524 | |||
| 441 | free(cmdline); | 525 | free(cmdline); |
| 526 | |||
| 442 | return result; | 527 | return result; |
| 443 | } | 528 | } |
| 444 | 529 | ||
| @@ -520,7 +605,7 @@ char *construct_cmdline(upgrade_type upgrade, const char *opts) { | |||
| 520 | break; | 605 | break; |
| 521 | } | 606 | } |
| 522 | 607 | ||
| 523 | int len = 0; | 608 | size_t len = 0; |
| 524 | len += strlen(PATH_TO_APTGET) + 1; /* "/usr/bin/apt-get " */ | 609 | len += strlen(PATH_TO_APTGET) + 1; /* "/usr/bin/apt-get " */ |
| 525 | len += strlen(opts_ptr) + 1; /* "opts " */ | 610 | len += strlen(opts_ptr) + 1; /* "opts " */ |
| 526 | len += strlen(aptcmd) + 1; /* "upgrade\0" */ | 611 | len += strlen(aptcmd) + 1; /* "upgrade\0" */ |
| @@ -558,7 +643,8 @@ void print_help(void) { | |||
| 558 | printf(" %s\n", _("List packages available for upgrade. Packages are printed sorted by")); | 643 | printf(" %s\n", _("List packages available for upgrade. Packages are printed sorted by")); |
| 559 | printf(" %s\n", _("name with security packages listed first.")); | 644 | printf(" %s\n", _("name with security packages listed first.")); |
| 560 | printf(" %s\n", "-i, --include=REGEXP"); | 645 | printf(" %s\n", "-i, --include=REGEXP"); |
| 561 | printf(" %s\n", _("Include only packages matching REGEXP. Can be specified multiple times")); | 646 | printf(" %s\n", |
| 647 | _("Include only packages matching REGEXP. Can be specified multiple times")); | ||
| 562 | printf(" %s\n", _("the values will be combined together. Any packages matching this list")); | 648 | printf(" %s\n", _("the values will be combined together. Any packages matching this list")); |
| 563 | printf(" %s\n", _("cause the plugin to return WARNING status. Others will be ignored.")); | 649 | printf(" %s\n", _("cause the plugin to return WARNING status. Others will be ignored.")); |
| 564 | printf(" %s\n", _("Default is to include all packages.")); | 650 | printf(" %s\n", _("Default is to include all packages.")); |
| @@ -567,7 +653,8 @@ void print_help(void) { | |||
| 567 | printf(" %s\n", _("otherwise be included. Can be specified multiple times; the values")); | 653 | printf(" %s\n", _("otherwise be included. Can be specified multiple times; the values")); |
| 568 | printf(" %s\n", _("will be combined together. Default is to exclude no packages.")); | 654 | printf(" %s\n", _("will be combined together. Default is to exclude no packages.")); |
| 569 | printf(" %s\n", "-c, --critical=REGEXP"); | 655 | printf(" %s\n", "-c, --critical=REGEXP"); |
| 570 | printf(" %s\n", _("If the full package information of any of the upgradable packages match")); | 656 | printf(" %s\n", |
| 657 | _("If the full package information of any of the upgradable packages match")); | ||
| 571 | printf(" %s\n", _("this REGEXP, the plugin will return CRITICAL status. Can be specified")); | 658 | printf(" %s\n", _("this REGEXP, the plugin will return CRITICAL status. Can be specified")); |
| 572 | printf(" %s\n", _("multiple times like above. Default is a regexp matching security")); | 659 | printf(" %s\n", _("multiple times like above. Default is a regexp matching security")); |
| 573 | printf(" %s\n", _("upgrades for Debian and Ubuntu:")); | 660 | printf(" %s\n", _("upgrades for Debian and Ubuntu:")); |
| @@ -576,15 +663,21 @@ void print_help(void) { | |||
| 576 | printf(" %s\n", _("information is compared against the critical list.")); | 663 | printf(" %s\n", _("information is compared against the critical list.")); |
| 577 | printf(" %s\n", "-o, --only-critical"); | 664 | printf(" %s\n", "-o, --only-critical"); |
| 578 | printf(" %s\n", _("Only warn about upgrades matching the critical list. The total number")); | 665 | printf(" %s\n", _("Only warn about upgrades matching the critical list. The total number")); |
| 579 | printf(" %s\n", _("of upgrades will be printed, but any non-critical upgrades will not cause")); | 666 | printf(" %s\n", |
| 667 | _("of upgrades will be printed, but any non-critical upgrades will not cause")); | ||
| 580 | printf(" %s\n", _("the plugin to return WARNING status.")); | 668 | printf(" %s\n", _("the plugin to return WARNING status.")); |
| 581 | printf(" %s\n", "-w, --packages-warning"); | 669 | printf(" %s\n", "-w, --packages-warning"); |
| 582 | printf(" %s\n", _("Minimum number of packages available for upgrade to return WARNING status.")); | 670 | printf(" %s\n", |
| 671 | _("Minimum number of packages available for upgrade to return WARNING status.")); | ||
| 583 | printf(" %s\n\n", _("Default is 1 package.")); | 672 | printf(" %s\n\n", _("Default is 1 package.")); |
| 584 | 673 | ||
| 585 | printf("%s\n\n", _("The following options require root privileges and should be used with care:")); | 674 | printf(UT_OUTPUT_FORMAT); |
| 675 | |||
| 676 | printf("%s\n\n", | ||
| 677 | _("The following options require root privileges and should be used with care:")); | ||
| 586 | printf(" %s\n", "-u, --update=OPTS"); | 678 | printf(" %s\n", "-u, --update=OPTS"); |
| 587 | printf(" %s\n", _("First perform an 'apt-get update'. An optional OPTS parameter overrides")); | 679 | printf(" %s\n", |
| 680 | _("First perform an 'apt-get update'. An optional OPTS parameter overrides")); | ||
| 588 | printf(" %s\n", _("the default options. Note: you may also need to adjust the global")); | 681 | printf(" %s\n", _("the default options. Note: you may also need to adjust the global")); |
| 589 | printf(" %s\n", _("timeout (with -t) to prevent the plugin from timing out if apt-get")); | 682 | printf(" %s\n", _("timeout (with -t) to prevent the plugin from timing out if apt-get")); |
| 590 | printf(" %s\n", _("upgrade is expected to take longer than the default timeout.")); | 683 | printf(" %s\n", _("upgrade is expected to take longer than the default timeout.")); |
| @@ -593,8 +686,10 @@ void print_help(void) { | |||
| 593 | printf(" %s\n", _("apt-get will be run with these command line options instead of the")); | 686 | printf(" %s\n", _("apt-get will be run with these command line options instead of the")); |
| 594 | printf(" %s", _("default ")); | 687 | printf(" %s", _("default ")); |
| 595 | printf("(%s).\n", UPGRADE_DEFAULT_OPTS); | 688 | printf("(%s).\n", UPGRADE_DEFAULT_OPTS); |
| 596 | printf(" %s\n", _("Note that you may be required to have root privileges if you do not use")); | 689 | printf(" %s\n", |
| 597 | printf(" %s\n", _("the default options, which will only run a simulation and NOT perform the upgrade")); | 690 | _("Note that you may be required to have root privileges if you do not use")); |
| 691 | printf(" %s\n", | ||
| 692 | _("the default options, which will only run a simulation and NOT perform the upgrade")); | ||
| 598 | printf(" %s\n", "-d, --dist-upgrade=OPTS"); | 693 | printf(" %s\n", "-d, --dist-upgrade=OPTS"); |
| 599 | printf(" %s\n", _("Perform a dist-upgrade instead of normal upgrade. Like with -U OPTS")); | 694 | printf(" %s\n", _("Perform a dist-upgrade instead of normal upgrade. Like with -U OPTS")); |
| 600 | printf(" %s\n", _("can be provided to override the default options.")); | 695 | printf(" %s\n", _("can be provided to override the default options.")); |
diff --git a/plugins/check_apt.d/config.h b/plugins/check_apt.d/config.h index 981f4f42..e4d622f1 100644 --- a/plugins/check_apt.d/config.h +++ b/plugins/check_apt.d/config.h | |||
| @@ -2,6 +2,7 @@ | |||
| 2 | 2 | ||
| 3 | #include "../../config.h" | 3 | #include "../../config.h" |
| 4 | #include <stddef.h> | 4 | #include <stddef.h> |
| 5 | #include "../lib/output.h" | ||
| 5 | 6 | ||
| 6 | /* some constants */ | 7 | /* some constants */ |
| 7 | typedef enum { | 8 | typedef enum { |
| @@ -16,7 +17,7 @@ typedef struct { | |||
| 16 | bool only_critical; /* whether to warn about non-critical updates */ | 17 | bool only_critical; /* whether to warn about non-critical updates */ |
| 17 | bool list; /* list packages available for upgrade */ | 18 | bool list; /* list packages available for upgrade */ |
| 18 | /* number of packages available for upgrade to return WARNING status */ | 19 | /* number of packages available for upgrade to return WARNING status */ |
| 19 | int packages_warning; | 20 | size_t packages_warning; |
| 20 | 21 | ||
| 21 | char *upgrade_opts; /* options to override defaults for upgrade */ | 22 | char *upgrade_opts; /* options to override defaults for upgrade */ |
| 22 | char *update_opts; /* options to override defaults for update */ | 23 | char *update_opts; /* options to override defaults for update */ |
| @@ -24,6 +25,9 @@ typedef struct { | |||
| 24 | char *do_exclude; /* regexp to only exclude certain packages */ | 25 | char *do_exclude; /* regexp to only exclude certain packages */ |
| 25 | char *do_critical; /* regexp specifying critical packages */ | 26 | char *do_critical; /* regexp specifying critical packages */ |
| 26 | char *input_filename; /* input filename for testing */ | 27 | char *input_filename; /* input filename for testing */ |
| 28 | |||
| 29 | bool output_format_is_set; | ||
| 30 | mp_output_format output_format; | ||
| 27 | } check_apt_config; | 31 | } check_apt_config; |
| 28 | 32 | ||
| 29 | check_apt_config check_apt_config_init() { | 33 | check_apt_config check_apt_config_init() { |
| @@ -36,6 +40,7 @@ check_apt_config check_apt_config_init() { | |||
| 36 | .do_include = NULL, | 40 | .do_include = NULL, |
| 37 | .do_exclude = NULL, | 41 | .do_exclude = NULL, |
| 38 | .do_critical = NULL, | 42 | .do_critical = NULL, |
| 39 | .input_filename = NULL}; | 43 | .input_filename = NULL, |
| 44 | .output_format_is_set = false}; | ||
| 40 | return tmp; | 45 | return tmp; |
| 41 | } | 46 | } |
diff --git a/plugins/check_by_ssh.c b/plugins/check_by_ssh.c index 74b7a46f..a43c0d34 100644 --- a/plugins/check_by_ssh.c +++ b/plugins/check_by_ssh.c | |||
| @@ -119,13 +119,14 @@ int main(int argc, char **argv) { | |||
| 119 | skip_stderr = config.skip_stderr; | 119 | skip_stderr = config.skip_stderr; |
| 120 | } | 120 | } |
| 121 | 121 | ||
| 122 | /* UNKNOWN or worse if (non-skipped) output found on stderr */ | 122 | /* Allow UNKNOWN or WARNING state for (non-skipped) output found on stderr */ |
| 123 | if (chld_err.lines > (size_t)skip_stderr) { | 123 | if (chld_err.lines > (size_t)skip_stderr && (config.unknown_on_stderr || config.warn_on_stderr)) { |
| 124 | printf(_("Remote command execution failed: %s\n"), chld_err.line[skip_stderr]); | 124 | printf(_("Remote command execution failed: %s\n"), chld_err.line[skip_stderr]); |
| 125 | if (config.warn_on_stderr) { | 125 | if (config.unknown_on_stderr) { |
| 126 | return max_state_alt(result, STATE_UNKNOWN); | ||
| 127 | } else if (config.warn_on_stderr) { | ||
| 126 | return max_state_alt(result, STATE_WARNING); | 128 | return max_state_alt(result, STATE_WARNING); |
| 127 | } | 129 | } |
| 128 | return max_state_alt(result, STATE_UNKNOWN); | ||
| 129 | } | 130 | } |
| 130 | 131 | ||
| 131 | /* this is simple if we're not supposed to be passive. | 132 | /* this is simple if we're not supposed to be passive. |
| @@ -191,12 +192,13 @@ check_by_ssh_config_wrapper process_arguments(int argc, char **argv) { | |||
| 191 | {"name", required_argument, 0, 'n'}, | 192 | {"name", required_argument, 0, 'n'}, |
| 192 | {"services", required_argument, 0, 's'}, | 193 | {"services", required_argument, 0, 's'}, |
| 193 | {"identity", required_argument, 0, 'i'}, | 194 | {"identity", required_argument, 0, 'i'}, |
| 194 | {"user", required_argument, 0, 'u'}, | 195 | {"user", required_argument, 0, 'u'}, /* backwards compatibility */ |
| 195 | {"logname", required_argument, 0, 'l'}, | 196 | {"logname", required_argument, 0, 'l'}, |
| 196 | {"command", required_argument, 0, 'C'}, | 197 | {"command", required_argument, 0, 'C'}, |
| 197 | {"skip", optional_argument, 0, 'S'}, /* backwards compatibility */ | 198 | {"skip", optional_argument, 0, 'S'}, /* backwards compatibility */ |
| 198 | {"skip-stdout", optional_argument, 0, 'S'}, | 199 | {"skip-stdout", optional_argument, 0, 'S'}, |
| 199 | {"skip-stderr", optional_argument, 0, 'E'}, | 200 | {"skip-stderr", optional_argument, 0, 'E'}, |
| 201 | {"unknown-on-stderr", no_argument, 0, 'e'}, | ||
| 200 | {"warn-on-stderr", no_argument, 0, 'W'}, | 202 | {"warn-on-stderr", no_argument, 0, 'W'}, |
| 201 | {"proto1", no_argument, 0, '1'}, | 203 | {"proto1", no_argument, 0, '1'}, |
| 202 | {"proto2", no_argument, 0, '2'}, | 204 | {"proto2", no_argument, 0, '2'}, |
| @@ -341,6 +343,9 @@ check_by_ssh_config_wrapper process_arguments(int argc, char **argv) { | |||
| 341 | result.config.skip_stderr = atoi(optarg); | 343 | result.config.skip_stderr = atoi(optarg); |
| 342 | } | 344 | } |
| 343 | break; | 345 | break; |
| 346 | case 'e': /* exit with unknown if there is an output on stderr */ | ||
| 347 | result.config.unknown_on_stderr = true; | ||
| 348 | break; | ||
| 344 | case 'W': /* exit with warning if there is an output on stderr */ | 349 | case 'W': /* exit with warning if there is an output on stderr */ |
| 345 | result.config.warn_on_stderr = true; | 350 | result.config.warn_on_stderr = true; |
| 346 | break; | 351 | break; |
| @@ -468,8 +473,10 @@ void print_help(void) { | |||
| 468 | printf(" %s\n", _("Ignore all or (if specified) first n lines on STDOUT [optional]")); | 473 | printf(" %s\n", _("Ignore all or (if specified) first n lines on STDOUT [optional]")); |
| 469 | printf(" %s\n", "-E, --skip-stderr[=n]"); | 474 | printf(" %s\n", "-E, --skip-stderr[=n]"); |
| 470 | printf(" %s\n", _("Ignore all or (if specified) first n lines on STDERR [optional]")); | 475 | printf(" %s\n", _("Ignore all or (if specified) first n lines on STDERR [optional]")); |
| 471 | printf(" %s\n", "-W, --warn-on-stderr]"); | 476 | printf(" %s\n", "-e, --unknown-on-stderr"); |
| 472 | printf(" %s\n", _("Exit with an warning, if there is an output on STDERR")); | 477 | printf(" %s\n", _("Exit with UNKNOWN, if there is output on STDERR")); |
| 478 | printf(" %s\n", "-W, --warn-on-stderr"); | ||
| 479 | printf(" %s\n", _("Exit with WARNING, if there is output on STDERR")); | ||
| 473 | printf(" %s\n", "-f"); | 480 | printf(" %s\n", "-f"); |
| 474 | printf(" %s\n", _("tells ssh to fork rather than create a tty [optional]. This will always " | 481 | printf(" %s\n", _("tells ssh to fork rather than create a tty [optional]. This will always " |
| 475 | "return OK if ssh is executed")); | 482 | "return OK if ssh is executed")); |
| @@ -522,7 +529,7 @@ void print_help(void) { | |||
| 522 | void print_usage(void) { | 529 | void print_usage(void) { |
| 523 | printf("%s\n", _("Usage:")); | 530 | printf("%s\n", _("Usage:")); |
| 524 | printf(" %s -H <host> -C <command> [-fqvU] [-1|-2] [-4|-6]\n" | 531 | printf(" %s -H <host> -C <command> [-fqvU] [-1|-2] [-4|-6]\n" |
| 525 | " [-S [lines]] [-E [lines]] [-W] [-t timeout] [-i identity]\n" | 532 | " [-S [lines]] [-E [lines]] [-e|-W] [-t timeout] [-i identity]\n" |
| 526 | " [-l user] [-n name] [-s servicelist] [-O outputfile]\n" | 533 | " [-l user] [-n name] [-s servicelist] [-O outputfile]\n" |
| 527 | " [-p port] [-o ssh-option] [-F configfile]\n", | 534 | " [-p port] [-o ssh-option] [-F configfile]\n", |
| 528 | progname); | 535 | progname); |
diff --git a/plugins/check_by_ssh.d/config.h b/plugins/check_by_ssh.d/config.h index 05435def..0e4b56d4 100644 --- a/plugins/check_by_ssh.d/config.h +++ b/plugins/check_by_ssh.d/config.h | |||
| @@ -21,6 +21,7 @@ typedef struct { | |||
| 21 | command_construct cmd; | 21 | command_construct cmd; |
| 22 | 22 | ||
| 23 | bool unknown_timeout; | 23 | bool unknown_timeout; |
| 24 | bool unknown_on_stderr; | ||
| 24 | bool warn_on_stderr; | 25 | bool warn_on_stderr; |
| 25 | int skip_stdout; | 26 | int skip_stdout; |
| 26 | int skip_stderr; | 27 | int skip_stderr; |
| @@ -46,6 +47,7 @@ check_by_ssh_config check_by_ssh_config_init() { | |||
| 46 | }, | 47 | }, |
| 47 | 48 | ||
| 48 | .unknown_timeout = false, | 49 | .unknown_timeout = false, |
| 50 | .unknown_on_stderr = false, | ||
| 49 | .warn_on_stderr = false, | 51 | .warn_on_stderr = false, |
| 50 | .skip_stderr = 0, | 52 | .skip_stderr = 0, |
| 51 | .skip_stdout = 0, | 53 | .skip_stdout = 0, |
diff --git a/plugins/check_cluster.c b/plugins/check_cluster.c index 373520ee..1cbdcd60 100644 --- a/plugins/check_cluster.c +++ b/plugins/check_cluster.c | |||
| @@ -26,6 +26,8 @@ const char *progname = "check_cluster"; | |||
| 26 | const char *copyright = "2000-2024"; | 26 | const char *copyright = "2000-2024"; |
| 27 | const char *email = "devel@monitoring-plugins.org"; | 27 | const char *email = "devel@monitoring-plugins.org"; |
| 28 | 28 | ||
| 29 | #include "output.h" | ||
| 30 | #include "states.h" | ||
| 29 | #include "common.h" | 31 | #include "common.h" |
| 30 | #include "utils.h" | 32 | #include "utils.h" |
| 31 | #include "utils_base.h" | 33 | #include "utils_base.h" |
| @@ -57,6 +59,10 @@ int main(int argc, char **argv) { | |||
| 57 | 59 | ||
| 58 | const check_cluster_config config = tmp_config.config; | 60 | const check_cluster_config config = tmp_config.config; |
| 59 | 61 | ||
| 62 | if (config.output_format_is_set) { | ||
| 63 | mp_set_format(config.output_format); | ||
| 64 | } | ||
| 65 | |||
| 60 | /* Initialize the thresholds */ | 66 | /* Initialize the thresholds */ |
| 61 | if (verbose) { | 67 | if (verbose) { |
| 62 | print_thresholds("check_cluster", config.thresholds); | 68 | print_thresholds("check_cluster", config.thresholds); |
| @@ -72,7 +78,6 @@ int main(int argc, char **argv) { | |||
| 72 | int total_hosts_unreachable = 0; | 78 | int total_hosts_unreachable = 0; |
| 73 | /* check the data values */ | 79 | /* check the data values */ |
| 74 | for (char *ptr = strtok(config.data_vals, ","); ptr != NULL; ptr = strtok(NULL, ",")) { | 80 | for (char *ptr = strtok(config.data_vals, ","); ptr != NULL; ptr = strtok(NULL, ",")) { |
| 75 | |||
| 76 | data_val = atoi(ptr); | 81 | data_val = atoi(ptr); |
| 77 | 82 | ||
| 78 | if (config.check_type == CHECK_SERVICES) { | 83 | if (config.check_type == CHECK_SERVICES) { |
| @@ -109,33 +114,49 @@ int main(int argc, char **argv) { | |||
| 109 | } | 114 | } |
| 110 | } | 115 | } |
| 111 | 116 | ||
| 112 | int return_code = STATE_OK; | 117 | mp_check overall = mp_check_init(); |
| 118 | mp_subcheck sc_real_test = mp_subcheck_init(); | ||
| 119 | sc_real_test = mp_set_subcheck_default_state(sc_real_test, STATE_OK); | ||
| 120 | |||
| 113 | /* return the status of the cluster */ | 121 | /* return the status of the cluster */ |
| 114 | if (config.check_type == CHECK_SERVICES) { | 122 | if (config.check_type == CHECK_SERVICES) { |
| 115 | return_code = | 123 | sc_real_test = mp_set_subcheck_state( |
| 124 | sc_real_test, | ||
| 116 | get_status(total_services_warning + total_services_unknown + total_services_critical, | 125 | get_status(total_services_warning + total_services_unknown + total_services_critical, |
| 117 | config.thresholds); | 126 | config.thresholds)); |
| 118 | printf("CLUSTER %s: %s: %d ok, %d warning, %d unknown, %d critical\n", | 127 | xasprintf(&sc_real_test.output, "%s: %d ok, %d warning, %d unknown, %d critical", |
| 119 | state_text(return_code), (config.label == NULL) ? "Service cluster" : config.label, | 128 | (config.label == NULL) ? "Service cluster" : config.label, total_services_ok, |
| 120 | total_services_ok, total_services_warning, total_services_unknown, | 129 | total_services_warning, total_services_unknown, total_services_critical); |
| 121 | total_services_critical); | ||
| 122 | } else { | 130 | } else { |
| 123 | return_code = get_status(total_hosts_down + total_hosts_unreachable, config.thresholds); | 131 | sc_real_test = mp_set_subcheck_state( |
| 124 | printf("CLUSTER %s: %s: %d up, %d down, %d unreachable\n", state_text(return_code), | 132 | sc_real_test, |
| 125 | (config.label == NULL) ? "Host cluster" : config.label, total_hosts_up, | 133 | get_status(total_hosts_down + total_hosts_unreachable, config.thresholds)); |
| 126 | total_hosts_down, total_hosts_unreachable); | 134 | xasprintf(&sc_real_test.output, "%s: %d up, %d down, %d unreachable\n", |
| 135 | (config.label == NULL) ? "Host cluster" : config.label, total_hosts_up, | ||
| 136 | total_hosts_down, total_hosts_unreachable); | ||
| 127 | } | 137 | } |
| 128 | 138 | ||
| 129 | exit(return_code); | 139 | mp_add_subcheck_to_check(&overall, sc_real_test); |
| 140 | |||
| 141 | mp_exit(overall); | ||
| 130 | } | 142 | } |
| 131 | 143 | ||
| 132 | check_cluster_config_wrapper process_arguments(int argc, char **argv) { | 144 | check_cluster_config_wrapper process_arguments(int argc, char **argv) { |
| 133 | static struct option longopts[] = { | 145 | enum { |
| 134 | {"data", required_argument, 0, 'd'}, {"warning", required_argument, 0, 'w'}, | 146 | output_format_index = CHAR_MAX + 1, |
| 135 | {"critical", required_argument, 0, 'c'}, {"label", required_argument, 0, 'l'}, | 147 | }; |
| 136 | {"host", no_argument, 0, 'h'}, {"service", no_argument, 0, 's'}, | 148 | |
| 137 | {"verbose", no_argument, 0, 'v'}, {"version", no_argument, 0, 'V'}, | 149 | static struct option longopts[] = {{"data", required_argument, 0, 'd'}, |
| 138 | {"help", no_argument, 0, 'H'}, {0, 0, 0, 0}}; | 150 | {"warning", required_argument, 0, 'w'}, |
| 151 | {"critical", required_argument, 0, 'c'}, | ||
| 152 | {"label", required_argument, 0, 'l'}, | ||
| 153 | {"host", no_argument, 0, 'h'}, | ||
| 154 | {"service", no_argument, 0, 's'}, | ||
| 155 | {"verbose", no_argument, 0, 'v'}, | ||
| 156 | {"version", no_argument, 0, 'V'}, | ||
| 157 | {"help", no_argument, 0, 'H'}, | ||
| 158 | {"output-format", required_argument, 0, output_format_index}, | ||
| 159 | {0, 0, 0, 0}}; | ||
| 139 | 160 | ||
| 140 | check_cluster_config_wrapper result = { | 161 | check_cluster_config_wrapper result = { |
| 141 | .errorcode = OK, | 162 | .errorcode = OK, |
| @@ -202,6 +223,18 @@ check_cluster_config_wrapper process_arguments(int argc, char **argv) { | |||
| 202 | print_help(); | 223 | print_help(); |
| 203 | exit(STATE_UNKNOWN); | 224 | exit(STATE_UNKNOWN); |
| 204 | break; | 225 | break; |
| 226 | case output_format_index: { | ||
| 227 | parsed_output_format parser = mp_parse_output_format(optarg); | ||
| 228 | if (!parser.parsing_success) { | ||
| 229 | // TODO List all available formats here, maybe add anothoer usage function | ||
| 230 | printf("Invalid output format: %s\n", optarg); | ||
| 231 | exit(STATE_UNKNOWN); | ||
| 232 | } | ||
| 233 | |||
| 234 | result.config.output_format_is_set = true; | ||
| 235 | result.config.output_format = parser.output_format; | ||
| 236 | break; | ||
| 237 | } | ||
| 205 | default: | 238 | default: |
| 206 | result.errorcode = ERROR; | 239 | result.errorcode = ERROR; |
| 207 | return result; | 240 | return result; |
| @@ -249,6 +282,8 @@ void print_help(void) { | |||
| 249 | 282 | ||
| 250 | printf(UT_VERBOSE); | 283 | printf(UT_VERBOSE); |
| 251 | 284 | ||
| 285 | printf(UT_OUTPUT_FORMAT); | ||
| 286 | |||
| 252 | printf("\n"); | 287 | printf("\n"); |
| 253 | printf("%s\n", _("Notes:")); | 288 | printf("%s\n", _("Notes:")); |
| 254 | printf(UT_THRESHOLDS_NOTES); | 289 | printf(UT_THRESHOLDS_NOTES); |
diff --git a/plugins/check_cluster.d/config.h b/plugins/check_cluster.d/config.h index fc386415..054657b0 100644 --- a/plugins/check_cluster.d/config.h +++ b/plugins/check_cluster.d/config.h | |||
| @@ -2,6 +2,7 @@ | |||
| 2 | 2 | ||
| 3 | #include "../../config.h" | 3 | #include "../../config.h" |
| 4 | #include "../../lib/thresholds.h" | 4 | #include "../../lib/thresholds.h" |
| 5 | #include "output.h" | ||
| 5 | #include <stddef.h> | 6 | #include <stddef.h> |
| 6 | 7 | ||
| 7 | enum { | 8 | enum { |
| @@ -14,6 +15,9 @@ typedef struct { | |||
| 14 | thresholds *thresholds; | 15 | thresholds *thresholds; |
| 15 | int check_type; | 16 | int check_type; |
| 16 | char *label; | 17 | char *label; |
| 18 | |||
| 19 | mp_output_format output_format; | ||
| 20 | bool output_format_is_set; | ||
| 17 | } check_cluster_config; | 21 | } check_cluster_config; |
| 18 | 22 | ||
| 19 | check_cluster_config check_cluster_config_init() { | 23 | check_cluster_config check_cluster_config_init() { |
| @@ -22,6 +26,8 @@ check_cluster_config check_cluster_config_init() { | |||
| 22 | .thresholds = NULL, | 26 | .thresholds = NULL, |
| 23 | .check_type = CHECK_SERVICES, | 27 | .check_type = CHECK_SERVICES, |
| 24 | .label = NULL, | 28 | .label = NULL, |
| 29 | |||
| 30 | .output_format_is_set = false, | ||
| 25 | }; | 31 | }; |
| 26 | return tmp; | 32 | return tmp; |
| 27 | } | 33 | } |
diff --git a/plugins/check_curl.d/check_curl_helpers.c b/plugins/check_curl.d/check_curl_helpers.c index c3c2ba55..d49d8f07 100644 --- a/plugins/check_curl.d/check_curl_helpers.c +++ b/plugins/check_curl.d/check_curl_helpers.c | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | #include <netinet/in.h> | 4 | #include <netinet/in.h> |
| 5 | #include <netdb.h> | 5 | #include <netdb.h> |
| 6 | #include <stdlib.h> | 6 | #include <stdlib.h> |
| 7 | #include <string.h> | ||
| 7 | #include "../utils.h" | 8 | #include "../utils.h" |
| 8 | #include "check_curl.d/config.h" | 9 | #include "check_curl.d/config.h" |
| 9 | #include "output.h" | 10 | #include "output.h" |
| @@ -816,7 +817,10 @@ int curlhelp_parse_statusline(const char *buf, curlhelp_statusline *status_line) | |||
| 816 | buf = start; | 817 | buf = start; |
| 817 | } | 818 | } |
| 818 | 819 | ||
| 819 | char *first_line_end = strstr(buf, "\r\n"); | 820 | // Accept either LF or CRLF as end of line for the status line |
| 821 | // CRLF is the standard (RFC9112), but it is recommended to accept both | ||
| 822 | size_t length_of_first_line = strcspn(buf, "\r\n"); | ||
| 823 | const char *first_line_end = &buf[length_of_first_line]; | ||
| 820 | if (first_line_end == NULL) { | 824 | if (first_line_end == NULL) { |
| 821 | return -1; | 825 | return -1; |
| 822 | } | 826 | } |
| @@ -826,6 +830,7 @@ int curlhelp_parse_statusline(const char *buf, curlhelp_statusline *status_line) | |||
| 826 | if (status_line->first_line == NULL) { | 830 | if (status_line->first_line == NULL) { |
| 827 | return -1; | 831 | return -1; |
| 828 | } | 832 | } |
| 833 | |||
| 829 | memcpy(status_line->first_line, buf, first_line_len); | 834 | memcpy(status_line->first_line, buf, first_line_len); |
| 830 | status_line->first_line[first_line_len] = '\0'; | 835 | status_line->first_line[first_line_len] = '\0'; |
| 831 | char *first_line_buf = strdup(status_line->first_line); | 836 | char *first_line_buf = strdup(status_line->first_line); |
| @@ -833,23 +838,34 @@ int curlhelp_parse_statusline(const char *buf, curlhelp_statusline *status_line) | |||
| 833 | /* protocol and version: "HTTP/x.x" SP or "HTTP/2" SP */ | 838 | /* protocol and version: "HTTP/x.x" SP or "HTTP/2" SP */ |
| 834 | char *temp_string = strtok(first_line_buf, "/"); | 839 | char *temp_string = strtok(first_line_buf, "/"); |
| 835 | if (temp_string == NULL) { | 840 | if (temp_string == NULL) { |
| 841 | if (verbose > 1) { | ||
| 842 | printf("%s: no / found\n", __func__); | ||
| 843 | } | ||
| 836 | free(first_line_buf); | 844 | free(first_line_buf); |
| 837 | return -1; | 845 | return -1; |
| 838 | } | 846 | } |
| 847 | |||
| 839 | if (strcmp(temp_string, "HTTP") != 0) { | 848 | if (strcmp(temp_string, "HTTP") != 0) { |
| 849 | if (verbose > 1) { | ||
| 850 | printf("%s: string 'HTTP' not found\n", __func__); | ||
| 851 | } | ||
| 840 | free(first_line_buf); | 852 | free(first_line_buf); |
| 841 | return -1; | 853 | return -1; |
| 842 | } | 854 | } |
| 843 | 855 | ||
| 856 | // try to find a space in the remaining string? | ||
| 857 | // the space after HTTP/1.1 probably | ||
| 844 | temp_string = strtok(NULL, " "); | 858 | temp_string = strtok(NULL, " "); |
| 845 | if (temp_string == NULL) { | 859 | if (temp_string == NULL) { |
| 860 | if (verbose > 1) { | ||
| 861 | printf("%s: no space after protocol definition\n", __func__); | ||
| 862 | } | ||
| 846 | free(first_line_buf); | 863 | free(first_line_buf); |
| 847 | return -1; | 864 | return -1; |
| 848 | } | 865 | } |
| 849 | 866 | ||
| 850 | char *temp_string_2; | 867 | char *temp_string_2; |
| 851 | if (strchr(temp_string, '.') != NULL) { | 868 | if (strchr(temp_string, '.') != NULL) { |
| 852 | |||
| 853 | /* HTTP 1.x case */ | 869 | /* HTTP 1.x case */ |
| 854 | strtok(temp_string, "."); | 870 | strtok(temp_string, "."); |
| 855 | status_line->http_major = (int)strtol(temp_string, &temp_string_2, 10); | 871 | status_line->http_major = (int)strtol(temp_string, &temp_string_2, 10); |
diff --git a/plugins/check_mysql.c b/plugins/check_mysql.c index 3d7ec4cd..6134d6c6 100644 --- a/plugins/check_mysql.c +++ b/plugins/check_mysql.c | |||
| @@ -219,16 +219,13 @@ int main(int argc, char **argv) { | |||
| 219 | use_deprecated_slave_status = true; | 219 | use_deprecated_slave_status = true; |
| 220 | } | 220 | } |
| 221 | } | 221 | } |
| 222 | } else if (strstr(server_version, "MySQL") != NULL) { | 222 | } else { |
| 223 | // Looks like MySQL | 223 | // Looks like MySQL or at least not like MariaDB |
| 224 | if (major_version < 8) { | 224 | if (major_version < 8) { |
| 225 | use_deprecated_slave_status = true; | 225 | use_deprecated_slave_status = true; |
| 226 | } else if (major_version == 10 && minor_version < 4) { | 226 | } else if (major_version == 10 && minor_version < 4) { |
| 227 | use_deprecated_slave_status = true; | 227 | use_deprecated_slave_status = true; |
| 228 | } | 228 | } |
| 229 | } else { | ||
| 230 | printf("Not a known sever implementation: %s\n", server_version); | ||
| 231 | exit(STATE_UNKNOWN); | ||
| 232 | } | 229 | } |
| 233 | 230 | ||
| 234 | char *replica_query = NULL; | 231 | char *replica_query = NULL; |
| @@ -285,17 +282,32 @@ int main(int argc, char **argv) { | |||
| 285 | num_fields = mysql_num_fields(res); | 282 | num_fields = mysql_num_fields(res); |
| 286 | fields = mysql_fetch_fields(res); | 283 | fields = mysql_fetch_fields(res); |
| 287 | for (int i = 0; i < num_fields; i++) { | 284 | for (int i = 0; i < num_fields; i++) { |
| 288 | if (strcmp(fields[i].name, "Slave_IO_Running") == 0) { | 285 | if (use_deprecated_slave_status) { |
| 289 | replica_io_field = i; | 286 | if (strcmp(fields[i].name, "Slave_IO_Running") == 0) { |
| 290 | continue; | 287 | replica_io_field = i; |
| 291 | } | 288 | continue; |
| 292 | if (strcmp(fields[i].name, "Slave_SQL_Running") == 0) { | 289 | } |
| 293 | replica_sql_field = i; | 290 | if (strcmp(fields[i].name, "Slave_SQL_Running") == 0) { |
| 294 | continue; | 291 | replica_sql_field = i; |
| 295 | } | 292 | continue; |
| 296 | if (strcmp(fields[i].name, "Seconds_Behind_Master") == 0) { | 293 | } |
| 297 | seconds_behind_field = i; | 294 | if (strcmp(fields[i].name, "Seconds_Behind_Master") == 0) { |
| 298 | continue; | 295 | seconds_behind_field = i; |
| 296 | continue; | ||
| 297 | } | ||
| 298 | } else { | ||
| 299 | if (strcmp(fields[i].name, "Replica_IO_Running") == 0) { | ||
| 300 | replica_io_field = i; | ||
| 301 | continue; | ||
| 302 | } | ||
| 303 | if (strcmp(fields[i].name, "Replica_SQL_Running") == 0) { | ||
| 304 | replica_sql_field = i; | ||
| 305 | continue; | ||
| 306 | } | ||
| 307 | if (strcmp(fields[i].name, "Seconds_Behind_Source") == 0) { | ||
| 308 | seconds_behind_field = i; | ||
| 309 | continue; | ||
| 310 | } | ||
| 299 | } | 311 | } |
| 300 | } | 312 | } |
| 301 | 313 | ||
diff --git a/plugins/check_ntp_peer.c b/plugins/check_ntp_peer.c index 24d1c9b5..f7cad630 100644 --- a/plugins/check_ntp_peer.c +++ b/plugins/check_ntp_peer.c | |||
| @@ -35,11 +35,14 @@ | |||
| 35 | * | 35 | * |
| 36 | *****************************************************************************/ | 36 | *****************************************************************************/ |
| 37 | 37 | ||
| 38 | #include "thresholds.h" | ||
| 39 | const char *progname = "check_ntp_peer"; | 38 | const char *progname = "check_ntp_peer"; |
| 40 | const char *copyright = "2006-2024"; | 39 | const char *copyright = "2006-2024"; |
| 41 | const char *email = "devel@monitoring-plugins.org"; | 40 | const char *email = "devel@monitoring-plugins.org"; |
| 42 | 41 | ||
| 42 | #include "output.h" | ||
| 43 | #include "perfdata.h" | ||
| 44 | #include <openssl/x509.h> | ||
| 45 | #include "thresholds.h" | ||
| 43 | #include "common.h" | 46 | #include "common.h" |
| 44 | #include "netutils.h" | 47 | #include "netutils.h" |
| 45 | #include "utils.h" | 48 | #include "utils.h" |
| @@ -47,8 +50,6 @@ const char *email = "devel@monitoring-plugins.org"; | |||
| 47 | #include "check_ntp_peer.d/config.h" | 50 | #include "check_ntp_peer.d/config.h" |
| 48 | 51 | ||
| 49 | static int verbose = 0; | 52 | static int verbose = 0; |
| 50 | static bool syncsource_found = false; | ||
| 51 | static bool li_alarm = false; | ||
| 52 | 53 | ||
| 53 | typedef struct { | 54 | typedef struct { |
| 54 | int errorcode; | 55 | int errorcode; |
| @@ -198,9 +199,7 @@ void setup_control_request(ntp_control_message *message, uint8_t opcode, uint16_ | |||
| 198 | * positive value means a success retrieving the value. | 199 | * positive value means a success retrieving the value. |
| 199 | * - status is set to WARNING if there's no sync.peer (otherwise OK) and is | 200 | * - status is set to WARNING if there's no sync.peer (otherwise OK) and is |
| 200 | * the return value of the function. | 201 | * the return value of the function. |
| 201 | * status is pretty much useless as syncsource_found is a global variable | 202 | */ |
| 202 | * used later in main to check is the server was synchronized. It works | ||
| 203 | * so I left it alone */ | ||
| 204 | typedef struct { | 203 | typedef struct { |
| 205 | mp_state_enum state; | 204 | mp_state_enum state; |
| 206 | mp_state_enum offset_result; | 205 | mp_state_enum offset_result; |
| @@ -208,6 +207,8 @@ typedef struct { | |||
| 208 | double jitter; | 207 | double jitter; |
| 209 | long stratum; | 208 | long stratum; |
| 210 | int num_truechimers; | 209 | int num_truechimers; |
| 210 | bool syncsource_found; | ||
| 211 | bool li_alarm; | ||
| 211 | } ntp_request_result; | 212 | } ntp_request_result; |
| 212 | ntp_request_result ntp_request(const check_ntp_peer_config config) { | 213 | ntp_request_result ntp_request(const check_ntp_peer_config config) { |
| 213 | 214 | ||
| @@ -217,6 +218,8 @@ ntp_request_result ntp_request(const check_ntp_peer_config config) { | |||
| 217 | .jitter = -1, | 218 | .jitter = -1, |
| 218 | .stratum = -1, | 219 | .stratum = -1, |
| 219 | .num_truechimers = 0, | 220 | .num_truechimers = 0, |
| 221 | .syncsource_found = false, | ||
| 222 | .li_alarm = false, | ||
| 220 | }; | 223 | }; |
| 221 | 224 | ||
| 222 | /* Long-winded explanation: | 225 | /* Long-winded explanation: |
| @@ -235,19 +238,16 @@ ntp_request_result ntp_request(const check_ntp_peer_config config) { | |||
| 235 | * 4) Extract the offset, jitter and stratum value from the data[] | 238 | * 4) Extract the offset, jitter and stratum value from the data[] |
| 236 | * (it's ASCII) | 239 | * (it's ASCII) |
| 237 | */ | 240 | */ |
| 238 | int min_peer_sel = PEER_INCLUDED; | ||
| 239 | int num_candidates = 0; | ||
| 240 | void *tmp; | ||
| 241 | ntp_assoc_status_pair *peers = NULL; | ||
| 242 | int peer_offset = 0; | ||
| 243 | size_t peers_size = 0; | ||
| 244 | size_t npeers = 0; | ||
| 245 | int conn = -1; | 241 | int conn = -1; |
| 246 | my_udp_connect(config.server_address, config.port, &conn); | 242 | my_udp_connect(config.server_address, config.port, &conn); |
| 247 | 243 | ||
| 248 | /* keep sending requests until the server stops setting the | 244 | /* keep sending requests until the server stops setting the |
| 249 | * REM_MORE bit, though usually this is only 1 packet. */ | 245 | * REM_MORE bit, though usually this is only 1 packet. */ |
| 250 | ntp_control_message req; | 246 | ntp_control_message req; |
| 247 | ntp_assoc_status_pair *peers = NULL; | ||
| 248 | int peer_offset = 0; | ||
| 249 | size_t peers_size = 0; | ||
| 250 | size_t npeers = 0; | ||
| 251 | do { | 251 | do { |
| 252 | setup_control_request(&req, OP_READSTAT, 1); | 252 | setup_control_request(&req, OP_READSTAT, 1); |
| 253 | DBG(printf("sending READSTAT request")); | 253 | DBG(printf("sending READSTAT request")); |
| @@ -269,12 +269,13 @@ ntp_request_result ntp_request(const check_ntp_peer_config config) { | |||
| 269 | } while (!(req.op & OP_READSTAT && ntohs(req.seq) == 1)); | 269 | } while (!(req.op & OP_READSTAT && ntohs(req.seq) == 1)); |
| 270 | 270 | ||
| 271 | if (LI(req.flags) == LI_ALARM) { | 271 | if (LI(req.flags) == LI_ALARM) { |
| 272 | li_alarm = true; | 272 | result.li_alarm = true; |
| 273 | } | 273 | } |
| 274 | /* Each peer identifier is 4 bytes in the data section, which | 274 | /* Each peer identifier is 4 bytes in the data section, which |
| 275 | * we represent as a ntp_assoc_status_pair datatype. | 275 | * we represent as a ntp_assoc_status_pair datatype. |
| 276 | */ | 276 | */ |
| 277 | peers_size += ntohs(req.count); | 277 | peers_size += ntohs(req.count); |
| 278 | void *tmp; | ||
| 278 | if ((tmp = realloc(peers, peers_size)) == NULL) { | 279 | if ((tmp = realloc(peers, peers_size)) == NULL) { |
| 279 | free(peers), die(STATE_UNKNOWN, "can not (re)allocate 'peers' buffer\n"); | 280 | free(peers), die(STATE_UNKNOWN, "can not (re)allocate 'peers' buffer\n"); |
| 280 | } | 281 | } |
| @@ -287,13 +288,15 @@ ntp_request_result ntp_request(const check_ntp_peer_config config) { | |||
| 287 | /* first, let's find out if we have a sync source, or if there are | 288 | /* first, let's find out if we have a sync source, or if there are |
| 288 | * at least some candidates. In the latter case we'll issue | 289 | * at least some candidates. In the latter case we'll issue |
| 289 | * a warning but go ahead with the check on them. */ | 290 | * a warning but go ahead with the check on them. */ |
| 291 | int min_peer_sel = PEER_INCLUDED; | ||
| 292 | int num_candidates = 0; | ||
| 290 | for (size_t i = 0; i < npeers; i++) { | 293 | for (size_t i = 0; i < npeers; i++) { |
| 291 | if (PEER_SEL(peers[i].status) >= PEER_TRUECHIMER) { | 294 | if (PEER_SEL(peers[i].status) >= PEER_TRUECHIMER) { |
| 292 | result.num_truechimers++; | 295 | result.num_truechimers++; |
| 293 | if (PEER_SEL(peers[i].status) >= PEER_INCLUDED) { | 296 | if (PEER_SEL(peers[i].status) >= PEER_INCLUDED) { |
| 294 | num_candidates++; | 297 | num_candidates++; |
| 295 | if (PEER_SEL(peers[i].status) >= PEER_SYNCSOURCE) { | 298 | if (PEER_SEL(peers[i].status) >= PEER_SYNCSOURCE) { |
| 296 | syncsource_found = true; | 299 | result.syncsource_found = true; |
| 297 | min_peer_sel = PEER_SYNCSOURCE; | 300 | min_peer_sel = PEER_SYNCSOURCE; |
| 298 | } | 301 | } |
| 299 | } | 302 | } |
| @@ -302,18 +305,18 @@ ntp_request_result ntp_request(const check_ntp_peer_config config) { | |||
| 302 | 305 | ||
| 303 | if (verbose) { | 306 | if (verbose) { |
| 304 | printf("%d candidate peers available\n", num_candidates); | 307 | printf("%d candidate peers available\n", num_candidates); |
| 305 | } | 308 | if (result.syncsource_found) { |
| 306 | if (verbose && syncsource_found) { | 309 | printf("synchronization source found\n"); |
| 307 | printf("synchronization source found\n"); | 310 | } |
| 308 | } | 311 | } |
| 309 | 312 | ||
| 310 | if (!syncsource_found) { | 313 | if (!result.syncsource_found) { |
| 311 | result.state = STATE_WARNING; | 314 | result.state = STATE_WARNING; |
| 312 | if (verbose) { | 315 | if (verbose) { |
| 313 | printf("warning: no synchronization source found\n"); | 316 | printf("warning: no synchronization source found\n"); |
| 314 | } | 317 | } |
| 315 | } | 318 | } |
| 316 | if (li_alarm) { | 319 | if (result.li_alarm) { |
| 317 | result.state = STATE_WARNING; | 320 | result.state = STATE_WARNING; |
| 318 | if (verbose) { | 321 | if (verbose) { |
| 319 | printf("warning: LI_ALARM bit is set\n"); | 322 | printf("warning: LI_ALARM bit is set\n"); |
| @@ -329,7 +332,7 @@ ntp_request_result ntp_request(const check_ntp_peer_config config) { | |||
| 329 | if (verbose) { | 332 | if (verbose) { |
| 330 | printf("Getting offset, jitter and stratum for peer %.2x\n", ntohs(peers[i].assoc)); | 333 | printf("Getting offset, jitter and stratum for peer %.2x\n", ntohs(peers[i].assoc)); |
| 331 | } | 334 | } |
| 332 | xasprintf(&data, ""); | 335 | data = strdup(""); |
| 333 | do { | 336 | do { |
| 334 | setup_control_request(&req, OP_READVAR, 2); | 337 | setup_control_request(&req, OP_READVAR, 2); |
| 335 | req.assoc = peers[i].assoc; | 338 | req.assoc = peers[i].assoc; |
| @@ -475,16 +478,30 @@ ntp_request_result ntp_request(const check_ntp_peer_config config) { | |||
| 475 | } | 478 | } |
| 476 | 479 | ||
| 477 | check_ntp_peer_config_wrapper process_arguments(int argc, char **argv) { | 480 | check_ntp_peer_config_wrapper process_arguments(int argc, char **argv) { |
| 478 | static struct option longopts[] = { | 481 | |
| 479 | {"version", no_argument, 0, 'V'}, {"help", no_argument, 0, 'h'}, | 482 | enum { |
| 480 | {"verbose", no_argument, 0, 'v'}, {"use-ipv4", no_argument, 0, '4'}, | 483 | output_format_index = CHAR_MAX + 1, |
| 481 | {"use-ipv6", no_argument, 0, '6'}, {"quiet", no_argument, 0, 'q'}, | 484 | }; |
| 482 | {"warning", required_argument, 0, 'w'}, {"critical", required_argument, 0, 'c'}, | 485 | |
| 483 | {"swarn", required_argument, 0, 'W'}, {"scrit", required_argument, 0, 'C'}, | 486 | static struct option longopts[] = {{"version", no_argument, 0, 'V'}, |
| 484 | {"jwarn", required_argument, 0, 'j'}, {"jcrit", required_argument, 0, 'k'}, | 487 | {"help", no_argument, 0, 'h'}, |
| 485 | {"twarn", required_argument, 0, 'm'}, {"tcrit", required_argument, 0, 'n'}, | 488 | {"verbose", no_argument, 0, 'v'}, |
| 486 | {"timeout", required_argument, 0, 't'}, {"hostname", required_argument, 0, 'H'}, | 489 | {"use-ipv4", no_argument, 0, '4'}, |
| 487 | {"port", required_argument, 0, 'p'}, {0, 0, 0, 0}}; | 490 | {"use-ipv6", no_argument, 0, '6'}, |
| 491 | {"quiet", no_argument, 0, 'q'}, | ||
| 492 | {"warning", required_argument, 0, 'w'}, | ||
| 493 | {"critical", required_argument, 0, 'c'}, | ||
| 494 | {"swarn", required_argument, 0, 'W'}, | ||
| 495 | {"scrit", required_argument, 0, 'C'}, | ||
| 496 | {"jwarn", required_argument, 0, 'j'}, | ||
| 497 | {"jcrit", required_argument, 0, 'k'}, | ||
| 498 | {"twarn", required_argument, 0, 'm'}, | ||
| 499 | {"tcrit", required_argument, 0, 'n'}, | ||
| 500 | {"timeout", required_argument, 0, 't'}, | ||
| 501 | {"hostname", required_argument, 0, 'H'}, | ||
| 502 | {"port", required_argument, 0, 'p'}, | ||
| 503 | {"output-format", required_argument, 0, output_format_index}, | ||
| 504 | {0, 0, 0, 0}}; | ||
| 488 | 505 | ||
| 489 | if (argc < 2) { | 506 | if (argc < 2) { |
| 490 | usage("\n"); | 507 | usage("\n"); |
| @@ -504,6 +521,17 @@ check_ntp_peer_config_wrapper process_arguments(int argc, char **argv) { | |||
| 504 | } | 521 | } |
| 505 | 522 | ||
| 506 | switch (option_char) { | 523 | switch (option_char) { |
| 524 | case output_format_index: { | ||
| 525 | parsed_output_format parser = mp_parse_output_format(optarg); | ||
| 526 | if (!parser.parsing_success) { | ||
| 527 | printf("Invalid output format: %s\n", optarg); | ||
| 528 | exit(STATE_UNKNOWN); | ||
| 529 | } | ||
| 530 | |||
| 531 | result.config.output_format_is_set = true; | ||
| 532 | result.config.output_format = parser.output_format; | ||
| 533 | break; | ||
| 534 | } | ||
| 507 | case 'h': | 535 | case 'h': |
| 508 | print_help(); | 536 | print_help(); |
| 509 | exit(STATE_UNKNOWN); | 537 | exit(STATE_UNKNOWN); |
| @@ -518,36 +546,84 @@ check_ntp_peer_config_wrapper process_arguments(int argc, char **argv) { | |||
| 518 | case 'q': | 546 | case 'q': |
| 519 | result.config.quiet = true; | 547 | result.config.quiet = true; |
| 520 | break; | 548 | break; |
| 521 | case 'w': | 549 | case 'w': { |
| 522 | result.config.owarn = optarg; | 550 | mp_range_parsed tmp = mp_parse_range_string(optarg); |
| 523 | break; | 551 | if (tmp.error != MP_PARSING_SUCCES) { |
| 524 | case 'c': | 552 | die(STATE_UNKNOWN, "failed to parse warning offset threshold"); |
| 525 | result.config.ocrit = optarg; | 553 | } |
| 526 | break; | 554 | |
| 527 | case 'W': | 555 | result.config.offset_thresholds = |
| 556 | mp_thresholds_set_warn(result.config.offset_thresholds, tmp.range); | ||
| 557 | } break; | ||
| 558 | case 'c': { | ||
| 559 | mp_range_parsed tmp = mp_parse_range_string(optarg); | ||
| 560 | if (tmp.error != MP_PARSING_SUCCES) { | ||
| 561 | die(STATE_UNKNOWN, "failed to parse critical offset threshold"); | ||
| 562 | } | ||
| 563 | |||
| 564 | result.config.offset_thresholds = | ||
| 565 | mp_thresholds_set_crit(result.config.offset_thresholds, tmp.range); | ||
| 566 | } break; | ||
| 567 | case 'W': { | ||
| 528 | result.config.do_stratum = true; | 568 | result.config.do_stratum = true; |
| 529 | result.config.swarn = optarg; | 569 | mp_range_parsed tmp = mp_parse_range_string(optarg); |
| 530 | break; | 570 | if (tmp.error != MP_PARSING_SUCCES) { |
| 531 | case 'C': | 571 | die(STATE_UNKNOWN, "failed to parse warning stratum threshold"); |
| 572 | } | ||
| 573 | |||
| 574 | result.config.stratum_thresholds = | ||
| 575 | mp_thresholds_set_warn(result.config.stratum_thresholds, tmp.range); | ||
| 576 | } break; | ||
| 577 | case 'C': { | ||
| 532 | result.config.do_stratum = true; | 578 | result.config.do_stratum = true; |
| 533 | result.config.scrit = optarg; | 579 | mp_range_parsed tmp = mp_parse_range_string(optarg); |
| 534 | break; | 580 | if (tmp.error != MP_PARSING_SUCCES) { |
| 535 | case 'j': | 581 | die(STATE_UNKNOWN, "failed to parse critical stratum threshold"); |
| 582 | } | ||
| 583 | |||
| 584 | result.config.stratum_thresholds = | ||
| 585 | mp_thresholds_set_crit(result.config.stratum_thresholds, tmp.range); | ||
| 586 | } break; | ||
| 587 | case 'j': { | ||
| 536 | result.config.do_jitter = true; | 588 | result.config.do_jitter = true; |
| 537 | result.config.jwarn = optarg; | 589 | mp_range_parsed tmp = mp_parse_range_string(optarg); |
| 538 | break; | 590 | if (tmp.error != MP_PARSING_SUCCES) { |
| 539 | case 'k': | 591 | die(STATE_UNKNOWN, "failed to parse warning jitter threshold"); |
| 592 | } | ||
| 593 | |||
| 594 | result.config.jitter_thresholds = | ||
| 595 | mp_thresholds_set_warn(result.config.jitter_thresholds, tmp.range); | ||
| 596 | } break; | ||
| 597 | case 'k': { | ||
| 540 | result.config.do_jitter = true; | 598 | result.config.do_jitter = true; |
| 541 | result.config.jcrit = optarg; | 599 | mp_range_parsed tmp = mp_parse_range_string(optarg); |
| 542 | break; | 600 | if (tmp.error != MP_PARSING_SUCCES) { |
| 543 | case 'm': | 601 | die(STATE_UNKNOWN, "failed to parse critical jitter threshold"); |
| 602 | } | ||
| 603 | |||
| 604 | result.config.jitter_thresholds = | ||
| 605 | mp_thresholds_set_crit(result.config.jitter_thresholds, tmp.range); | ||
| 606 | } break; | ||
| 607 | case 'm': { | ||
| 544 | result.config.do_truechimers = true; | 608 | result.config.do_truechimers = true; |
| 545 | result.config.twarn = optarg; | 609 | mp_range_parsed tmp = mp_parse_range_string(optarg); |
| 546 | break; | 610 | if (tmp.error != MP_PARSING_SUCCES) { |
| 547 | case 'n': | 611 | die(STATE_UNKNOWN, "failed to parse warning truechimer threshold"); |
| 612 | } | ||
| 613 | |||
| 614 | result.config.truechimer_thresholds = | ||
| 615 | mp_thresholds_set_warn(result.config.truechimer_thresholds, tmp.range); | ||
| 616 | } break; | ||
| 617 | case 'n': { | ||
| 548 | result.config.do_truechimers = true; | 618 | result.config.do_truechimers = true; |
| 549 | result.config.tcrit = optarg; | 619 | mp_range_parsed tmp = mp_parse_range_string(optarg); |
| 550 | break; | 620 | if (tmp.error != MP_PARSING_SUCCES) { |
| 621 | die(STATE_UNKNOWN, "failed to parse critical truechimer threshold"); | ||
| 622 | } | ||
| 623 | |||
| 624 | result.config.truechimer_thresholds = | ||
| 625 | mp_thresholds_set_crit(result.config.truechimer_thresholds, tmp.range); | ||
| 626 | } break; | ||
| 551 | case 'H': | 627 | case 'H': |
| 552 | if (!is_host(optarg)) { | 628 | if (!is_host(optarg)) { |
| 553 | usage2(_("Invalid hostname/address"), optarg); | 629 | usage2(_("Invalid hostname/address"), optarg); |
| @@ -581,11 +657,6 @@ check_ntp_peer_config_wrapper process_arguments(int argc, char **argv) { | |||
| 581 | usage4(_("Hostname was not supplied")); | 657 | usage4(_("Hostname was not supplied")); |
| 582 | } | 658 | } |
| 583 | 659 | ||
| 584 | set_thresholds(&result.config.offset_thresholds, result.config.owarn, result.config.ocrit); | ||
| 585 | set_thresholds(&result.config.jitter_thresholds, result.config.jwarn, result.config.jcrit); | ||
| 586 | set_thresholds(&result.config.stratum_thresholds, result.config.swarn, result.config.scrit); | ||
| 587 | set_thresholds(&result.config.truechimer_thresholds, result.config.twarn, result.config.tcrit); | ||
| 588 | |||
| 589 | return result; | 660 | return result; |
| 590 | } | 661 | } |
| 591 | 662 | ||
| @@ -627,6 +698,10 @@ int main(int argc, char *argv[]) { | |||
| 627 | 698 | ||
| 628 | const check_ntp_peer_config config = tmp_config.config; | 699 | const check_ntp_peer_config config = tmp_config.config; |
| 629 | 700 | ||
| 701 | if (config.output_format_is_set) { | ||
| 702 | mp_set_format(config.output_format); | ||
| 703 | } | ||
| 704 | |||
| 630 | /* initialize alarm signal handling */ | 705 | /* initialize alarm signal handling */ |
| 631 | signal(SIGALRM, socket_timeout_alarm_handler); | 706 | signal(SIGALRM, socket_timeout_alarm_handler); |
| 632 | 707 | ||
| @@ -634,125 +709,113 @@ int main(int argc, char *argv[]) { | |||
| 634 | alarm(socket_timeout); | 709 | alarm(socket_timeout); |
| 635 | 710 | ||
| 636 | /* This returns either OK or WARNING (See comment preceding ntp_request) */ | 711 | /* This returns either OK or WARNING (See comment preceding ntp_request) */ |
| 637 | ntp_request_result ntp_res = ntp_request(config); | 712 | const ntp_request_result ntp_res = ntp_request(config); |
| 638 | mp_state_enum result = STATE_UNKNOWN; | 713 | mp_check overall = mp_check_init(); |
| 639 | 714 | ||
| 715 | mp_subcheck sc_offset = mp_subcheck_init(); | ||
| 716 | xasprintf(&sc_offset.output, "offset"); | ||
| 640 | if (ntp_res.offset_result == STATE_UNKNOWN) { | 717 | if (ntp_res.offset_result == STATE_UNKNOWN) { |
| 641 | /* if there's no sync peer (this overrides ntp_request output): */ | 718 | /* if there's no sync peer (this overrides ntp_request output): */ |
| 642 | result = (config.quiet ? STATE_UNKNOWN : STATE_CRITICAL); | 719 | sc_offset = |
| 720 | mp_set_subcheck_state(sc_offset, (config.quiet ? STATE_UNKNOWN : STATE_CRITICAL)); | ||
| 721 | xasprintf(&sc_offset.output, "%s unknown", sc_offset.output); | ||
| 643 | } else { | 722 | } else { |
| 644 | /* Be quiet if there's no candidates either */ | 723 | /* Be quiet if there's no candidates either */ |
| 645 | if (config.quiet && result == STATE_WARNING) { | 724 | mp_state_enum tmp = STATE_OK; |
| 646 | result = STATE_UNKNOWN; | 725 | if (config.quiet && ntp_res.state == STATE_WARNING) { |
| 726 | tmp = STATE_UNKNOWN; | ||
| 647 | } | 727 | } |
| 648 | result = max_state_alt(result, get_status(fabs(ntp_res.offset), config.offset_thresholds)); | 728 | |
| 729 | xasprintf(&sc_offset.output, "%s: %.6fs", sc_offset.output, ntp_res.offset); | ||
| 730 | |||
| 731 | mp_perfdata pd_offset = perfdata_init(); | ||
| 732 | pd_offset.value = mp_create_pd_value(fabs(ntp_res.offset)); | ||
| 733 | pd_offset = mp_pd_set_thresholds(pd_offset, config.offset_thresholds); | ||
| 734 | pd_offset.label = "offset"; | ||
| 735 | pd_offset.uom = "s"; | ||
| 736 | mp_add_perfdata_to_subcheck(&sc_offset, pd_offset); | ||
| 737 | |||
| 738 | tmp = max_state_alt(tmp, mp_get_pd_status(pd_offset)); | ||
| 739 | sc_offset = mp_set_subcheck_state(sc_offset, tmp); | ||
| 649 | } | 740 | } |
| 650 | 741 | ||
| 651 | mp_state_enum oresult = result; | 742 | mp_add_subcheck_to_check(&overall, sc_offset); |
| 652 | mp_state_enum tresult = STATE_UNKNOWN; | ||
| 653 | 743 | ||
| 744 | // truechimers | ||
| 654 | if (config.do_truechimers) { | 745 | if (config.do_truechimers) { |
| 655 | tresult = get_status(ntp_res.num_truechimers, config.truechimer_thresholds); | 746 | mp_subcheck sc_truechimers = mp_subcheck_init(); |
| 656 | result = max_state_alt(result, tresult); | 747 | xasprintf(&sc_truechimers.output, "truechimers: %i", ntp_res.num_truechimers); |
| 657 | } | ||
| 658 | 748 | ||
| 659 | mp_state_enum sresult = STATE_UNKNOWN; | 749 | mp_perfdata pd_truechimers = perfdata_init(); |
| 750 | pd_truechimers.value = mp_create_pd_value(ntp_res.num_truechimers); | ||
| 751 | pd_truechimers.label = "truechimers"; | ||
| 752 | pd_truechimers = mp_pd_set_thresholds(pd_truechimers, config.truechimer_thresholds); | ||
| 660 | 753 | ||
| 661 | if (config.do_stratum) { | 754 | mp_add_perfdata_to_subcheck(&sc_truechimers, pd_truechimers); |
| 662 | sresult = get_status((double)ntp_res.stratum, config.stratum_thresholds); | ||
| 663 | result = max_state_alt(result, sresult); | ||
| 664 | } | ||
| 665 | 755 | ||
| 666 | mp_state_enum jresult = STATE_UNKNOWN; | 756 | sc_truechimers = mp_set_subcheck_state(sc_truechimers, mp_get_pd_status(pd_truechimers)); |
| 667 | 757 | ||
| 668 | if (config.do_jitter) { | 758 | mp_add_subcheck_to_check(&overall, sc_truechimers); |
| 669 | jresult = get_status(ntp_res.jitter, config.jitter_thresholds); | ||
| 670 | result = max_state_alt(result, jresult); | ||
| 671 | } | 759 | } |
| 672 | 760 | ||
| 673 | char *result_line; | 761 | if (config.do_stratum) { |
| 674 | switch (result) { | 762 | mp_subcheck sc_stratum = mp_subcheck_init(); |
| 675 | case STATE_CRITICAL: | 763 | xasprintf(&sc_stratum.output, "stratum: %li", ntp_res.stratum); |
| 676 | xasprintf(&result_line, _("NTP CRITICAL:")); | ||
| 677 | break; | ||
| 678 | case STATE_WARNING: | ||
| 679 | xasprintf(&result_line, _("NTP WARNING:")); | ||
| 680 | break; | ||
| 681 | case STATE_OK: | ||
| 682 | xasprintf(&result_line, _("NTP OK:")); | ||
| 683 | break; | ||
| 684 | default: | ||
| 685 | xasprintf(&result_line, _("NTP UNKNOWN:")); | ||
| 686 | break; | ||
| 687 | } | ||
| 688 | 764 | ||
| 689 | if (!syncsource_found) { | 765 | mp_perfdata pd_stratum = perfdata_init(); |
| 690 | xasprintf(&result_line, "%s %s,", result_line, _("Server not synchronized")); | 766 | pd_stratum.value = mp_create_pd_value(ntp_res.stratum); |
| 691 | } else if (li_alarm) { | 767 | pd_stratum = mp_pd_set_thresholds(pd_stratum, config.stratum_thresholds); |
| 692 | xasprintf(&result_line, "%s %s,", result_line, _("Server has the LI_ALARM bit set")); | 768 | pd_stratum.label = "stratum"; |
| 693 | } | ||
| 694 | 769 | ||
| 695 | char *perfdata_line; | 770 | mp_add_perfdata_to_subcheck(&sc_stratum, pd_stratum); |
| 696 | if (ntp_res.offset_result == STATE_UNKNOWN) { | 771 | |
| 697 | xasprintf(&result_line, "%s %s", result_line, _("Offset unknown")); | 772 | sc_stratum = mp_set_subcheck_state(sc_stratum, mp_get_pd_status(pd_stratum)); |
| 698 | xasprintf(&perfdata_line, ""); | 773 | |
| 699 | } else if (oresult == STATE_WARNING) { | 774 | mp_add_subcheck_to_check(&overall, sc_stratum); |
| 700 | xasprintf(&result_line, "%s %s %.10g secs (WARNING)", result_line, _("Offset"), | ||
| 701 | ntp_res.offset); | ||
| 702 | } else if (oresult == STATE_CRITICAL) { | ||
| 703 | xasprintf(&result_line, "%s %s %.10g secs (CRITICAL)", result_line, _("Offset"), | ||
| 704 | ntp_res.offset); | ||
| 705 | } else { | ||
| 706 | xasprintf(&result_line, "%s %s %.10g secs", result_line, _("Offset"), ntp_res.offset); | ||
| 707 | } | 775 | } |
| 708 | xasprintf(&perfdata_line, "%s", perfd_offset(ntp_res.offset, config.offset_thresholds)); | ||
| 709 | 776 | ||
| 710 | if (config.do_jitter) { | 777 | if (config.do_jitter) { |
| 711 | if (jresult == STATE_WARNING) { | 778 | mp_subcheck sc_jitter = mp_subcheck_init(); |
| 712 | xasprintf(&result_line, "%s, jitter=%f (WARNING)", result_line, ntp_res.jitter); | 779 | xasprintf(&sc_jitter.output, "jitter: %f", ntp_res.jitter); |
| 713 | } else if (jresult == STATE_CRITICAL) { | ||
| 714 | xasprintf(&result_line, "%s, jitter=%f (CRITICAL)", result_line, ntp_res.jitter); | ||
| 715 | } else { | ||
| 716 | xasprintf(&result_line, "%s, jitter=%f", result_line, ntp_res.jitter); | ||
| 717 | } | ||
| 718 | xasprintf(&perfdata_line, "%s %s", perfdata_line, | ||
| 719 | perfd_jitter(ntp_res.jitter, config.do_jitter, config.jitter_thresholds)); | ||
| 720 | } | ||
| 721 | 780 | ||
| 722 | if (config.do_stratum) { | 781 | mp_perfdata pd_jitter = perfdata_init(); |
| 723 | if (sresult == STATE_WARNING) { | 782 | pd_jitter.value = mp_create_pd_value(ntp_res.jitter); |
| 724 | xasprintf(&result_line, "%s, stratum=%li (WARNING)", result_line, ntp_res.stratum); | 783 | pd_jitter = mp_pd_set_thresholds(pd_jitter, config.jitter_thresholds); |
| 725 | } else if (sresult == STATE_CRITICAL) { | 784 | pd_jitter.label = "jitter"; |
| 726 | xasprintf(&result_line, "%s, stratum=%li (CRITICAL)", result_line, ntp_res.stratum); | 785 | |
| 727 | } else { | 786 | mp_add_perfdata_to_subcheck(&sc_jitter, pd_jitter); |
| 728 | xasprintf(&result_line, "%s, stratum=%li", result_line, ntp_res.stratum); | 787 | |
| 729 | } | 788 | sc_jitter = mp_set_subcheck_state(sc_jitter, mp_get_pd_status(pd_jitter)); |
| 730 | xasprintf(&perfdata_line, "%s %s", perfdata_line, | 789 | mp_add_subcheck_to_check(&overall, sc_jitter); |
| 731 | perfd_stratum(ntp_res.stratum, config.do_stratum, config.stratum_thresholds)); | ||
| 732 | } | 790 | } |
| 733 | 791 | ||
| 734 | if (config.do_truechimers) { | 792 | mp_subcheck sc_other_info = mp_subcheck_init(); |
| 735 | if (tresult == STATE_WARNING) { | 793 | sc_other_info = mp_set_subcheck_default_state(sc_other_info, STATE_OK); |
| 736 | xasprintf(&result_line, "%s, truechimers=%i (WARNING)", result_line, | 794 | if (!ntp_res.syncsource_found) { |
| 737 | ntp_res.num_truechimers); | 795 | xasprintf(&sc_other_info.output, "%s", _("Server not synchronized")); |
| 738 | } else if (tresult == STATE_CRITICAL) { | 796 | mp_add_subcheck_to_check(&overall, sc_other_info); |
| 739 | xasprintf(&result_line, "%s, truechimers=%i (CRITICAL)", result_line, | 797 | } else if (ntp_res.li_alarm) { |
| 740 | ntp_res.num_truechimers); | 798 | xasprintf(&sc_other_info.output, "%s", _("Server has the LI_ALARM bit set")); |
| 741 | } else { | 799 | mp_add_subcheck_to_check(&overall, sc_other_info); |
| 742 | xasprintf(&result_line, "%s, truechimers=%i", result_line, ntp_res.num_truechimers); | ||
| 743 | } | ||
| 744 | xasprintf(&perfdata_line, "%s %s", perfdata_line, | ||
| 745 | perfd_truechimers(ntp_res.num_truechimers, config.do_truechimers, | ||
| 746 | config.truechimer_thresholds)); | ||
| 747 | } | 800 | } |
| 748 | 801 | ||
| 749 | printf("%s|%s\n", result_line, perfdata_line); | 802 | { |
| 803 | mp_subcheck sc_offset = mp_subcheck_init(); | ||
| 804 | sc_offset = mp_set_subcheck_default_state(sc_offset, STATE_OK); | ||
| 805 | xasprintf(&sc_offset.output, "offset: %.10gs", ntp_res.offset); | ||
| 806 | |||
| 807 | mp_perfdata pd_offset = perfdata_init(); | ||
| 808 | pd_offset.value = mp_create_pd_value(ntp_res.offset); | ||
| 809 | pd_offset = mp_pd_set_thresholds(pd_offset, config.offset_thresholds); | ||
| 810 | |||
| 811 | sc_offset = mp_set_subcheck_state(sc_offset, ntp_res.offset_result); | ||
| 812 | } | ||
| 750 | 813 | ||
| 751 | if (config.server_address != NULL) { | 814 | if (config.server_address != NULL) { |
| 752 | free(config.server_address); | 815 | free(config.server_address); |
| 753 | } | 816 | } |
| 754 | 817 | ||
| 755 | exit(result); | 818 | mp_exit(overall); |
| 756 | } | 819 | } |
| 757 | 820 | ||
| 758 | void print_help(void) { | 821 | void print_help(void) { |
| @@ -791,6 +854,7 @@ void print_help(void) { | |||
| 791 | printf(" %s\n", _("Critical threshold for number of usable time sources (\"truechimers\")")); | 854 | printf(" %s\n", _("Critical threshold for number of usable time sources (\"truechimers\")")); |
| 792 | printf(UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); | 855 | printf(UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); |
| 793 | printf(UT_VERBOSE); | 856 | printf(UT_VERBOSE); |
| 857 | printf(UT_OUTPUT_FORMAT); | ||
| 794 | 858 | ||
| 795 | printf("\n"); | 859 | printf("\n"); |
| 796 | printf("%s\n", _("This plugin checks an NTP server independent of any commandline")); | 860 | printf("%s\n", _("This plugin checks an NTP server independent of any commandline")); |
diff --git a/plugins/check_ntp_peer.d/config.h b/plugins/check_ntp_peer.d/config.h index 00e6b05d..488d936c 100644 --- a/plugins/check_ntp_peer.d/config.h +++ b/plugins/check_ntp_peer.d/config.h | |||
| @@ -1,6 +1,8 @@ | |||
| 1 | #pragma once | 1 | #pragma once |
| 2 | 2 | ||
| 3 | #include "../../config.h" | 3 | #include "../../config.h" |
| 4 | #include "output.h" | ||
| 5 | #include "perfdata.h" | ||
| 4 | #include "thresholds.h" | 6 | #include "thresholds.h" |
| 5 | #include <stddef.h> | 7 | #include <stddef.h> |
| 6 | 8 | ||
| @@ -16,26 +18,21 @@ typedef struct { | |||
| 16 | 18 | ||
| 17 | // truechimer stuff | 19 | // truechimer stuff |
| 18 | bool do_truechimers; | 20 | bool do_truechimers; |
| 19 | char *twarn; | 21 | mp_thresholds truechimer_thresholds; |
| 20 | char *tcrit; | ||
| 21 | thresholds *truechimer_thresholds; | ||
| 22 | 22 | ||
| 23 | char *owarn; | 23 | // offset thresholds |
| 24 | char *ocrit; | 24 | mp_thresholds offset_thresholds; |
| 25 | thresholds *offset_thresholds; | ||
| 26 | 25 | ||
| 27 | // stratum stuff | 26 | // stratum stuff |
| 28 | bool do_stratum; | 27 | bool do_stratum; |
| 29 | char *swarn; | 28 | mp_thresholds stratum_thresholds; |
| 30 | char *scrit; | ||
| 31 | thresholds *stratum_thresholds; | ||
| 32 | 29 | ||
| 33 | // jitter stuff | 30 | // jitter stuff |
| 34 | bool do_jitter; | 31 | bool do_jitter; |
| 35 | char *jwarn; | 32 | mp_thresholds jitter_thresholds; |
| 36 | char *jcrit; | ||
| 37 | thresholds *jitter_thresholds; | ||
| 38 | 33 | ||
| 34 | bool output_format_is_set; | ||
| 35 | mp_output_format output_format; | ||
| 39 | } check_ntp_peer_config; | 36 | } check_ntp_peer_config; |
| 40 | 37 | ||
| 41 | check_ntp_peer_config check_ntp_peer_config_init() { | 38 | check_ntp_peer_config check_ntp_peer_config_init() { |
| @@ -45,23 +42,41 @@ check_ntp_peer_config check_ntp_peer_config_init() { | |||
| 45 | 42 | ||
| 46 | .quiet = false, | 43 | .quiet = false, |
| 47 | .do_truechimers = false, | 44 | .do_truechimers = false, |
| 48 | .twarn = "0:", | 45 | .truechimer_thresholds = mp_thresholds_init(), |
| 49 | .tcrit = "0:", | ||
| 50 | .truechimer_thresholds = NULL, | ||
| 51 | 46 | ||
| 52 | .owarn = "60", | 47 | .offset_thresholds = mp_thresholds_init(), |
| 53 | .ocrit = "120", | ||
| 54 | .offset_thresholds = NULL, | ||
| 55 | 48 | ||
| 56 | .do_stratum = false, | 49 | .do_stratum = false, |
| 57 | .swarn = "-1:16", | 50 | .stratum_thresholds = mp_thresholds_init(), |
| 58 | .scrit = "-1:16", | ||
| 59 | .stratum_thresholds = NULL, | ||
| 60 | 51 | ||
| 61 | .do_jitter = false, | 52 | .do_jitter = false, |
| 62 | .jwarn = "-1:5000", | 53 | .jitter_thresholds = mp_thresholds_init(), |
| 63 | .jcrit = "-1:10000", | 54 | |
| 64 | .jitter_thresholds = NULL, | 55 | .output_format_is_set = false, |
| 65 | }; | 56 | }; |
| 57 | |||
| 58 | mp_range stratum_default = mp_range_init(); | ||
| 59 | stratum_default = mp_range_set_start(stratum_default, mp_create_pd_value(-1)); | ||
| 60 | stratum_default = mp_range_set_end(stratum_default, mp_create_pd_value(16)); | ||
| 61 | tmp.stratum_thresholds = mp_thresholds_set_warn(tmp.stratum_thresholds, stratum_default); | ||
| 62 | tmp.stratum_thresholds = mp_thresholds_set_crit(tmp.stratum_thresholds, stratum_default); | ||
| 63 | |||
| 64 | mp_range jitter_w_default = mp_range_init(); | ||
| 65 | jitter_w_default = mp_range_set_start(jitter_w_default, mp_create_pd_value(-1)); | ||
| 66 | jitter_w_default = mp_range_set_end(jitter_w_default, mp_create_pd_value(5000)); | ||
| 67 | tmp.jitter_thresholds = mp_thresholds_set_warn(tmp.jitter_thresholds, jitter_w_default); | ||
| 68 | |||
| 69 | mp_range jitter_c_default = mp_range_init(); | ||
| 70 | jitter_c_default = mp_range_set_start(jitter_c_default, mp_create_pd_value(-1)); | ||
| 71 | jitter_c_default = mp_range_set_end(jitter_c_default, mp_create_pd_value(10000)); | ||
| 72 | tmp.jitter_thresholds = mp_thresholds_set_crit(tmp.jitter_thresholds, jitter_c_default); | ||
| 73 | |||
| 74 | mp_range offset_w_default = mp_range_init(); | ||
| 75 | offset_w_default = mp_range_set_end(offset_w_default, mp_create_pd_value(60)); | ||
| 76 | tmp.offset_thresholds = mp_thresholds_set_warn(tmp.offset_thresholds, offset_w_default); | ||
| 77 | |||
| 78 | mp_range offset_c_default = mp_range_init(); | ||
| 79 | offset_c_default = mp_range_set_end(offset_c_default, mp_create_pd_value(120)); | ||
| 80 | tmp.offset_thresholds = mp_thresholds_set_crit(tmp.offset_thresholds, offset_c_default); | ||
| 66 | return tmp; | 81 | return tmp; |
| 67 | } | 82 | } |
diff --git a/plugins/check_ntp_time.c b/plugins/check_ntp_time.c index ad69b804..602b6010 100644 --- a/plugins/check_ntp_time.c +++ b/plugins/check_ntp_time.c | |||
| @@ -34,12 +34,10 @@ | |||
| 34 | * | 34 | * |
| 35 | *****************************************************************************/ | 35 | *****************************************************************************/ |
| 36 | 36 | ||
| 37 | const char *progname = "check_ntp_time"; | 37 | #include "output.h" |
| 38 | const char *copyright = "2006-2024"; | ||
| 39 | const char *email = "devel@monitoring-plugins.org"; | ||
| 40 | |||
| 41 | #include "common.h" | 38 | #include "common.h" |
| 42 | #include "netutils.h" | 39 | #include "netutils.h" |
| 40 | #include "perfdata.h" | ||
| 43 | #include "utils.h" | 41 | #include "utils.h" |
| 44 | #include "states.h" | 42 | #include "states.h" |
| 45 | #include "thresholds.h" | 43 | #include "thresholds.h" |
| @@ -47,6 +45,10 @@ const char *email = "devel@monitoring-plugins.org"; | |||
| 47 | 45 | ||
| 48 | static int verbose = 0; | 46 | static int verbose = 0; |
| 49 | 47 | ||
| 48 | const char *progname = "check_ntp_time"; | ||
| 49 | const char *copyright = "2006-2024"; | ||
| 50 | const char *email = "devel@monitoring-plugins.org"; | ||
| 51 | |||
| 50 | typedef struct { | 52 | typedef struct { |
| 51 | int errorcode; | 53 | int errorcode; |
| 52 | check_ntp_time_config config; | 54 | check_ntp_time_config config; |
| @@ -61,9 +63,6 @@ void print_usage(void); | |||
| 61 | # define AVG_NUM 4 | 63 | # define AVG_NUM 4 |
| 62 | #endif | 64 | #endif |
| 63 | 65 | ||
| 64 | /* max size of control message data */ | ||
| 65 | #define MAX_CM_SIZE 468 | ||
| 66 | |||
| 67 | /* this structure holds everything in an ntp request/response as per rfc1305 */ | 66 | /* this structure holds everything in an ntp request/response as per rfc1305 */ |
| 68 | typedef struct { | 67 | typedef struct { |
| 69 | uint8_t flags; /* byte with leapindicator,vers,mode. see macros */ | 68 | uint8_t flags; /* byte with leapindicator,vers,mode. see macros */ |
| @@ -169,7 +168,9 @@ typedef struct { | |||
| 169 | : 0) | 168 | : 0) |
| 170 | 169 | ||
| 171 | /* convert a struct timeval to a double */ | 170 | /* convert a struct timeval to a double */ |
| 172 | #define TVasDOUBLE(x) (double)(x.tv_sec + (0.000001 * x.tv_usec)) | 171 | static double TVasDOUBLE(struct timeval time) { |
| 172 | return ((double)time.tv_sec + (0.000001 * (double)time.tv_usec)); | ||
| 173 | } | ||
| 173 | 174 | ||
| 174 | /* convert an ntp 64-bit fp number to a struct timeval */ | 175 | /* convert an ntp 64-bit fp number to a struct timeval */ |
| 175 | #define NTP64toTV(n, t) \ | 176 | #define NTP64toTV(n, t) \ |
| @@ -262,8 +263,8 @@ void setup_request(ntp_message *message) { | |||
| 262 | /* select the "best" server from a list of servers, and return its index. | 263 | /* select the "best" server from a list of servers, and return its index. |
| 263 | * this is done by filtering servers based on stratum, dispersion, and | 264 | * this is done by filtering servers based on stratum, dispersion, and |
| 264 | * finally round-trip delay. */ | 265 | * finally round-trip delay. */ |
| 265 | int best_offset_server(const ntp_server_results *slist, int nservers) { | 266 | static int best_offset_server(const ntp_server_results *slist, int nservers) { |
| 266 | int best_server = -1; | 267 | int best_server_index = -1; |
| 267 | 268 | ||
| 268 | /* for each server */ | 269 | /* for each server */ |
| 269 | for (int cserver = 0; cserver < nservers; cserver++) { | 270 | for (int cserver = 0; cserver < nservers; cserver++) { |
| @@ -286,33 +287,33 @@ int best_offset_server(const ntp_server_results *slist, int nservers) { | |||
| 286 | } | 287 | } |
| 287 | 288 | ||
| 288 | /* If we don't have a server yet, use the first one */ | 289 | /* If we don't have a server yet, use the first one */ |
| 289 | if (best_server == -1) { | 290 | if (best_server_index == -1) { |
| 290 | best_server = cserver; | 291 | best_server_index = cserver; |
| 291 | DBG(printf("using peer %d as our first candidate\n", best_server)); | 292 | DBG(printf("using peer %d as our first candidate\n", best_server_index)); |
| 292 | continue; | 293 | continue; |
| 293 | } | 294 | } |
| 294 | 295 | ||
| 295 | /* compare the server to the best one we've seen so far */ | 296 | /* compare the server to the best one we've seen so far */ |
| 296 | /* does it have an equal or better stratum? */ | 297 | /* does it have an equal or better stratum? */ |
| 297 | DBG(printf("comparing peer %d with peer %d\n", cserver, best_server)); | 298 | DBG(printf("comparing peer %d with peer %d\n", cserver, best_server_index)); |
| 298 | if (slist[cserver].stratum <= slist[best_server].stratum) { | 299 | if (slist[cserver].stratum <= slist[best_server_index].stratum) { |
| 299 | DBG(printf("stratum for peer %d <= peer %d\n", cserver, best_server)); | 300 | DBG(printf("stratum for peer %d <= peer %d\n", cserver, best_server_index)); |
| 300 | /* does it have an equal or better dispersion? */ | 301 | /* does it have an equal or better dispersion? */ |
| 301 | if (slist[cserver].rtdisp <= slist[best_server].rtdisp) { | 302 | if (slist[cserver].rtdisp <= slist[best_server_index].rtdisp) { |
| 302 | DBG(printf("dispersion for peer %d <= peer %d\n", cserver, best_server)); | 303 | DBG(printf("dispersion for peer %d <= peer %d\n", cserver, best_server_index)); |
| 303 | /* does it have a better rtdelay? */ | 304 | /* does it have a better rtdelay? */ |
| 304 | if (slist[cserver].rtdelay < slist[best_server].rtdelay) { | 305 | if (slist[cserver].rtdelay < slist[best_server_index].rtdelay) { |
| 305 | DBG(printf("rtdelay for peer %d < peer %d\n", cserver, best_server)); | 306 | DBG(printf("rtdelay for peer %d < peer %d\n", cserver, best_server_index)); |
| 306 | best_server = cserver; | 307 | best_server_index = cserver; |
| 307 | DBG(printf("peer %d is now our best candidate\n", best_server)); | 308 | DBG(printf("peer %d is now our best candidate\n", best_server_index)); |
| 308 | } | 309 | } |
| 309 | } | 310 | } |
| 310 | } | 311 | } |
| 311 | } | 312 | } |
| 312 | 313 | ||
| 313 | if (best_server >= 0) { | 314 | if (best_server_index >= 0) { |
| 314 | DBG(printf("best server selected: peer %d\n", best_server)); | 315 | DBG(printf("best server selected: peer %d\n", best_server_index)); |
| 315 | return best_server; | 316 | return best_server_index; |
| 316 | } | 317 | } |
| 317 | DBG(printf("no peers meeting synchronization criteria :(\n")); | 318 | DBG(printf("no peers meeting synchronization criteria :(\n")); |
| 318 | return -1; | 319 | return -1; |
| @@ -323,7 +324,11 @@ int best_offset_server(const ntp_server_results *slist, int nservers) { | |||
| 323 | * we don't waste time sitting around waiting for single packets. | 324 | * we don't waste time sitting around waiting for single packets. |
| 324 | * - we also "manually" handle resolving host names and connecting, because | 325 | * - we also "manually" handle resolving host names and connecting, because |
| 325 | * we have to do it in a way that our lazy macros don't handle currently :( */ | 326 | * we have to do it in a way that our lazy macros don't handle currently :( */ |
| 326 | double offset_request(const char *host, const char *port, mp_state_enum *status, int time_offset) { | 327 | typedef struct { |
| 328 | mp_state_enum offset_result; | ||
| 329 | double offset; | ||
| 330 | } offset_request_wrapper; | ||
| 331 | static offset_request_wrapper offset_request(const char *host, const char *port, int time_offset) { | ||
| 327 | /* setup hints to only return results from getaddrinfo that we'd like */ | 332 | /* setup hints to only return results from getaddrinfo that we'd like */ |
| 328 | struct addrinfo hints; | 333 | struct addrinfo hints; |
| 329 | memset(&hints, 0, sizeof(struct addrinfo)); | 334 | memset(&hints, 0, sizeof(struct addrinfo)); |
| @@ -462,12 +467,18 @@ double offset_request(const char *host, const char *port, mp_state_enum *status, | |||
| 462 | die(STATE_CRITICAL, "NTP CRITICAL: No response from NTP server\n"); | 467 | die(STATE_CRITICAL, "NTP CRITICAL: No response from NTP server\n"); |
| 463 | } | 468 | } |
| 464 | 469 | ||
| 470 | offset_request_wrapper result = { | ||
| 471 | .offset = 0, | ||
| 472 | .offset_result = STATE_UNKNOWN, | ||
| 473 | }; | ||
| 474 | |||
| 465 | /* now, pick the best server from the list */ | 475 | /* now, pick the best server from the list */ |
| 466 | double avg_offset = 0.; | 476 | double avg_offset = 0.; |
| 467 | int best_index = best_offset_server(servers, num_hosts); | 477 | int best_index = best_offset_server(servers, num_hosts); |
| 468 | if (best_index < 0) { | 478 | if (best_index < 0) { |
| 469 | *status = STATE_UNKNOWN; | 479 | result.offset_result = STATE_UNKNOWN; |
| 470 | } else { | 480 | } else { |
| 481 | result.offset_result = STATE_OK; | ||
| 471 | /* finally, calculate the average offset */ | 482 | /* finally, calculate the average offset */ |
| 472 | for (int i = 0; i < servers[best_index].num_responses; i++) { | 483 | for (int i = 0; i < servers[best_index].num_responses; i++) { |
| 473 | avg_offset += servers[best_index].offset[i]; | 484 | avg_offset += servers[best_index].offset[i]; |
| @@ -488,22 +499,30 @@ double offset_request(const char *host, const char *port, mp_state_enum *status, | |||
| 488 | if (verbose) { | 499 | if (verbose) { |
| 489 | printf("overall average offset: %.10g\n", avg_offset); | 500 | printf("overall average offset: %.10g\n", avg_offset); |
| 490 | } | 501 | } |
| 491 | return avg_offset; | 502 | |
| 503 | result.offset = avg_offset; | ||
| 504 | return result; | ||
| 492 | } | 505 | } |
| 493 | 506 | ||
| 494 | check_ntp_time_config_wrapper process_arguments(int argc, char **argv) { | 507 | static check_ntp_time_config_wrapper process_arguments(int argc, char **argv) { |
| 508 | |||
| 509 | enum { | ||
| 510 | output_format_index = CHAR_MAX + 1, | ||
| 511 | }; | ||
| 512 | |||
| 495 | static struct option longopts[] = {{"version", no_argument, 0, 'V'}, | 513 | static struct option longopts[] = {{"version", no_argument, 0, 'V'}, |
| 496 | {"help", no_argument, 0, 'h'}, | 514 | {"help", no_argument, 0, 'h'}, |
| 497 | {"verbose", no_argument, 0, 'v'}, | 515 | {"verbose", no_argument, 0, 'v'}, |
| 498 | {"use-ipv4", no_argument, 0, '4'}, | 516 | {"use-ipv4", no_argument, 0, '4'}, |
| 499 | {"use-ipv6", no_argument, 0, '6'}, | 517 | {"use-ipv6", no_argument, 0, '6'}, |
| 500 | {"quiet", no_argument, 0, 'q'}, | 518 | {"quiet", no_argument, 0, 'q'}, |
| 501 | {"time-offset", optional_argument, 0, 'o'}, | 519 | {"time-offset", required_argument, 0, 'o'}, |
| 502 | {"warning", required_argument, 0, 'w'}, | 520 | {"warning", required_argument, 0, 'w'}, |
| 503 | {"critical", required_argument, 0, 'c'}, | 521 | {"critical", required_argument, 0, 'c'}, |
| 504 | {"timeout", required_argument, 0, 't'}, | 522 | {"timeout", required_argument, 0, 't'}, |
| 505 | {"hostname", required_argument, 0, 'H'}, | 523 | {"hostname", required_argument, 0, 'H'}, |
| 506 | {"port", required_argument, 0, 'p'}, | 524 | {"port", required_argument, 0, 'p'}, |
| 525 | {"output-format", required_argument, 0, output_format_index}, | ||
| 507 | {0, 0, 0, 0}}; | 526 | {0, 0, 0, 0}}; |
| 508 | 527 | ||
| 509 | if (argc < 2) { | 528 | if (argc < 2) { |
| @@ -515,9 +534,6 @@ check_ntp_time_config_wrapper process_arguments(int argc, char **argv) { | |||
| 515 | .config = check_ntp_time_config_init(), | 534 | .config = check_ntp_time_config_init(), |
| 516 | }; | 535 | }; |
| 517 | 536 | ||
| 518 | char *owarn = "60"; | ||
| 519 | char *ocrit = "120"; | ||
| 520 | |||
| 521 | while (true) { | 537 | while (true) { |
| 522 | int option = 0; | 538 | int option = 0; |
| 523 | int option_char = getopt_long(argc, argv, "Vhv46qw:c:t:H:p:o:", longopts, &option); | 539 | int option_char = getopt_long(argc, argv, "Vhv46qw:c:t:H:p:o:", longopts, &option); |
| @@ -526,6 +542,17 @@ check_ntp_time_config_wrapper process_arguments(int argc, char **argv) { | |||
| 526 | } | 542 | } |
| 527 | 543 | ||
| 528 | switch (option_char) { | 544 | switch (option_char) { |
| 545 | case output_format_index: { | ||
| 546 | parsed_output_format parser = mp_parse_output_format(optarg); | ||
| 547 | if (!parser.parsing_success) { | ||
| 548 | printf("Invalid output format: %s\n", optarg); | ||
| 549 | exit(STATE_UNKNOWN); | ||
| 550 | } | ||
| 551 | |||
| 552 | result.config.output_format_is_set = true; | ||
| 553 | result.config.output_format = parser.output_format; | ||
| 554 | break; | ||
| 555 | } | ||
| 529 | case 'h': | 556 | case 'h': |
| 530 | print_help(); | 557 | print_help(); |
| 531 | exit(STATE_UNKNOWN); | 558 | exit(STATE_UNKNOWN); |
| @@ -540,12 +567,24 @@ check_ntp_time_config_wrapper process_arguments(int argc, char **argv) { | |||
| 540 | case 'q': | 567 | case 'q': |
| 541 | result.config.quiet = true; | 568 | result.config.quiet = true; |
| 542 | break; | 569 | break; |
| 543 | case 'w': | 570 | case 'w': { |
| 544 | owarn = optarg; | 571 | mp_range_parsed tmp = mp_parse_range_string(optarg); |
| 545 | break; | 572 | if (tmp.error != MP_PARSING_SUCCES) { |
| 546 | case 'c': | 573 | die(STATE_UNKNOWN, "failed to parse warning threshold"); |
| 547 | ocrit = optarg; | 574 | } |
| 548 | break; | 575 | |
| 576 | result.config.offset_thresholds = | ||
| 577 | mp_thresholds_set_warn(result.config.offset_thresholds, tmp.range); | ||
| 578 | } break; | ||
| 579 | case 'c': { | ||
| 580 | mp_range_parsed tmp = mp_parse_range_string(optarg); | ||
| 581 | if (tmp.error != MP_PARSING_SUCCES) { | ||
| 582 | die(STATE_UNKNOWN, "failed to parse crit threshold"); | ||
| 583 | } | ||
| 584 | |||
| 585 | result.config.offset_thresholds = | ||
| 586 | mp_thresholds_set_crit(result.config.offset_thresholds, tmp.range); | ||
| 587 | } break; | ||
| 549 | case 'H': | 588 | case 'H': |
| 550 | if (!is_host(optarg)) { | 589 | if (!is_host(optarg)) { |
| 551 | usage2(_("Invalid hostname/address"), optarg); | 590 | usage2(_("Invalid hostname/address"), optarg); |
| @@ -582,16 +621,9 @@ check_ntp_time_config_wrapper process_arguments(int argc, char **argv) { | |||
| 582 | usage4(_("Hostname was not supplied")); | 621 | usage4(_("Hostname was not supplied")); |
| 583 | } | 622 | } |
| 584 | 623 | ||
| 585 | set_thresholds(&result.config.offset_thresholds, owarn, ocrit); | ||
| 586 | |||
| 587 | return result; | 624 | return result; |
| 588 | } | 625 | } |
| 589 | 626 | ||
| 590 | char *perfd_offset(double offset, thresholds *offset_thresholds) { | ||
| 591 | return fperfdata("offset", offset, "s", true, offset_thresholds->warning->end, true, | ||
| 592 | offset_thresholds->critical->end, false, 0, false, 0); | ||
| 593 | } | ||
| 594 | |||
| 595 | int main(int argc, char *argv[]) { | 627 | int main(int argc, char *argv[]) { |
| 596 | setlocale(LC_ALL, ""); | 628 | setlocale(LC_ALL, ""); |
| 597 | bindtextdomain(PACKAGE, LOCALEDIR); | 629 | bindtextdomain(PACKAGE, LOCALEDIR); |
| @@ -608,52 +640,47 @@ int main(int argc, char *argv[]) { | |||
| 608 | 640 | ||
| 609 | const check_ntp_time_config config = tmp_config.config; | 641 | const check_ntp_time_config config = tmp_config.config; |
| 610 | 642 | ||
| 643 | if (config.output_format_is_set) { | ||
| 644 | mp_set_format(config.output_format); | ||
| 645 | } | ||
| 646 | |||
| 611 | /* initialize alarm signal handling */ | 647 | /* initialize alarm signal handling */ |
| 612 | signal(SIGALRM, socket_timeout_alarm_handler); | 648 | signal(SIGALRM, socket_timeout_alarm_handler); |
| 613 | 649 | ||
| 614 | /* set socket timeout */ | 650 | /* set socket timeout */ |
| 615 | alarm(socket_timeout); | 651 | alarm(socket_timeout); |
| 616 | 652 | ||
| 617 | mp_state_enum offset_result = STATE_OK; | 653 | mp_check overall = mp_check_init(); |
| 618 | mp_state_enum result = STATE_OK; | ||
| 619 | double offset = | ||
| 620 | offset_request(config.server_address, config.port, &offset_result, config.time_offset); | ||
| 621 | if (offset_result == STATE_UNKNOWN) { | ||
| 622 | result = ((!config.quiet) ? STATE_UNKNOWN : STATE_CRITICAL); | ||
| 623 | } else { | ||
| 624 | result = get_status(fabs(offset), config.offset_thresholds); | ||
| 625 | } | ||
| 626 | 654 | ||
| 627 | char *result_line; | 655 | mp_subcheck sc_offset = mp_subcheck_init(); |
| 628 | switch (result) { | 656 | offset_request_wrapper offset_result = |
| 629 | case STATE_CRITICAL: | 657 | offset_request(config.server_address, config.port, config.time_offset); |
| 630 | xasprintf(&result_line, _("NTP CRITICAL:")); | ||
| 631 | break; | ||
| 632 | case STATE_WARNING: | ||
| 633 | xasprintf(&result_line, _("NTP WARNING:")); | ||
| 634 | break; | ||
| 635 | case STATE_OK: | ||
| 636 | xasprintf(&result_line, _("NTP OK:")); | ||
| 637 | break; | ||
| 638 | default: | ||
| 639 | xasprintf(&result_line, _("NTP UNKNOWN:")); | ||
| 640 | break; | ||
| 641 | } | ||
| 642 | 658 | ||
| 643 | char *perfdata_line; | 659 | if (offset_result.offset_result == STATE_UNKNOWN) { |
| 644 | if (offset_result == STATE_UNKNOWN) { | 660 | sc_offset = |
| 645 | xasprintf(&result_line, "%s %s", result_line, _("Offset unknown")); | 661 | mp_set_subcheck_state(sc_offset, (!config.quiet) ? STATE_UNKNOWN : STATE_CRITICAL); |
| 646 | xasprintf(&perfdata_line, ""); | 662 | xasprintf(&sc_offset.output, "Offset unknown"); |
| 647 | } else { | 663 | mp_add_subcheck_to_check(&overall, sc_offset); |
| 648 | xasprintf(&result_line, "%s %s %.10g secs", result_line, _("Offset"), offset); | 664 | mp_exit(overall); |
| 649 | xasprintf(&perfdata_line, "%s", perfd_offset(offset, config.offset_thresholds)); | ||
| 650 | } | 665 | } |
| 651 | printf("%s|%s\n", result_line, perfdata_line); | 666 | |
| 667 | xasprintf(&sc_offset.output, "Offset: %.6fs", offset_result.offset); | ||
| 668 | |||
| 669 | mp_perfdata pd_offset = perfdata_init(); | ||
| 670 | pd_offset = mp_set_pd_value(pd_offset, fabs(offset_result.offset)); | ||
| 671 | pd_offset.label = "offset"; | ||
| 672 | pd_offset.uom = "s"; | ||
| 673 | pd_offset = mp_pd_set_thresholds(pd_offset, config.offset_thresholds); | ||
| 674 | |||
| 675 | sc_offset = mp_set_subcheck_state(sc_offset, mp_get_pd_status(pd_offset)); | ||
| 676 | |||
| 677 | mp_add_perfdata_to_subcheck(&sc_offset, pd_offset); | ||
| 678 | mp_add_subcheck_to_check(&overall, sc_offset); | ||
| 652 | 679 | ||
| 653 | if (config.server_address != NULL) { | 680 | if (config.server_address != NULL) { |
| 654 | free(config.server_address); | 681 | free(config.server_address); |
| 655 | } | 682 | } |
| 656 | exit(result); | 683 | mp_exit(overall); |
| 657 | } | 684 | } |
| 658 | 685 | ||
| 659 | void print_help(void) { | 686 | void print_help(void) { |
| @@ -677,10 +704,11 @@ void print_help(void) { | |||
| 677 | printf(" %s\n", _("Offset to result in warning status (seconds)")); | 704 | printf(" %s\n", _("Offset to result in warning status (seconds)")); |
| 678 | printf(" %s\n", "-c, --critical=THRESHOLD"); | 705 | printf(" %s\n", "-c, --critical=THRESHOLD"); |
| 679 | printf(" %s\n", _("Offset to result in critical status (seconds)")); | 706 | printf(" %s\n", _("Offset to result in critical status (seconds)")); |
| 680 | printf(" %s\n", "-o, --time_offset=INTEGER"); | 707 | printf(" %s\n", "-o, --time-offset=INTEGER"); |
| 681 | printf(" %s\n", _("Expected offset of the ntp server relative to local server (seconds)")); | 708 | printf(" %s\n", _("Expected offset of the ntp server relative to local server (seconds)")); |
| 682 | printf(UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); | 709 | printf(UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); |
| 683 | printf(UT_VERBOSE); | 710 | printf(UT_VERBOSE); |
| 711 | printf(UT_OUTPUT_FORMAT); | ||
| 684 | 712 | ||
| 685 | printf("\n"); | 713 | printf("\n"); |
| 686 | printf("%s\n", _("This plugin checks the clock offset between the local host and a")); | 714 | printf("%s\n", _("This plugin checks the clock offset between the local host and a")); |
diff --git a/plugins/check_ntp_time.d/config.h b/plugins/check_ntp_time.d/config.h index 99dabbbd..9bbd82aa 100644 --- a/plugins/check_ntp_time.d/config.h +++ b/plugins/check_ntp_time.d/config.h | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | #pragma once | 1 | #pragma once |
| 2 | 2 | ||
| 3 | #include "../../config.h" | 3 | #include "../../config.h" |
| 4 | #include "output.h" | ||
| 4 | #include "thresholds.h" | 5 | #include "thresholds.h" |
| 5 | #include <stddef.h> | 6 | #include <stddef.h> |
| 6 | 7 | ||
| @@ -11,7 +12,10 @@ typedef struct { | |||
| 11 | bool quiet; | 12 | bool quiet; |
| 12 | int time_offset; | 13 | int time_offset; |
| 13 | 14 | ||
| 14 | thresholds *offset_thresholds; | 15 | mp_thresholds offset_thresholds; |
| 16 | |||
| 17 | bool output_format_is_set; | ||
| 18 | mp_output_format output_format; | ||
| 15 | } check_ntp_time_config; | 19 | } check_ntp_time_config; |
| 16 | 20 | ||
| 17 | check_ntp_time_config check_ntp_time_config_init() { | 21 | check_ntp_time_config check_ntp_time_config_init() { |
| @@ -22,7 +26,18 @@ check_ntp_time_config check_ntp_time_config_init() { | |||
| 22 | .quiet = false, | 26 | .quiet = false, |
| 23 | .time_offset = 0, | 27 | .time_offset = 0, |
| 24 | 28 | ||
| 25 | .offset_thresholds = NULL, | 29 | .offset_thresholds = mp_thresholds_init(), |
| 30 | |||
| 31 | .output_format_is_set = false, | ||
| 26 | }; | 32 | }; |
| 33 | |||
| 34 | mp_range warning = mp_range_init(); | ||
| 35 | warning = mp_range_set_end(warning, mp_create_pd_value(60)); | ||
| 36 | tmp.offset_thresholds = mp_thresholds_set_warn(tmp.offset_thresholds, warning); | ||
| 37 | |||
| 38 | mp_range critical = mp_range_init(); | ||
| 39 | critical = mp_range_set_end(warning, mp_create_pd_value(120)); | ||
| 40 | tmp.offset_thresholds = mp_thresholds_set_crit(tmp.offset_thresholds, critical); | ||
| 41 | |||
| 27 | return tmp; | 42 | return tmp; |
| 28 | } | 43 | } |
diff --git a/plugins/check_pgsql.c b/plugins/check_pgsql.c index 793a686f..0ce75e0a 100644 --- a/plugins/check_pgsql.c +++ b/plugins/check_pgsql.c | |||
| @@ -28,27 +28,29 @@ | |||
| 28 | * | 28 | * |
| 29 | *****************************************************************************/ | 29 | *****************************************************************************/ |
| 30 | 30 | ||
| 31 | #include "output.h" | ||
| 32 | #include "perfdata.h" | ||
| 31 | #include "states.h" | 33 | #include "states.h" |
| 32 | const char *progname = "check_pgsql"; | ||
| 33 | const char *copyright = "1999-2024"; | ||
| 34 | const char *email = "devel@monitoring-plugins.org"; | ||
| 35 | |||
| 36 | #include "common.h" | 34 | #include "common.h" |
| 37 | #include "utils.h" | 35 | #include "utils.h" |
| 38 | #include "utils_cmd.h" | 36 | #include "utils_cmd.h" |
| 39 | #include "check_pgsql.d/config.h" | 37 | #include "check_pgsql.d/config.h" |
| 40 | #include "thresholds.h" | 38 | #include "thresholds.h" |
| 41 | |||
| 42 | #include "netutils.h" | 39 | #include "netutils.h" |
| 43 | #include <libpq-fe.h> | 40 | #include <libpq-fe.h> |
| 44 | #include <pg_config_manual.h> | 41 | #include <pg_config_manual.h> |
| 45 | 42 | ||
| 43 | const char *progname = "check_pgsql"; | ||
| 44 | const char *copyright = "1999-2024"; | ||
| 45 | const char *email = "devel@monitoring-plugins.org"; | ||
| 46 | |||
| 46 | #define DEFAULT_HOST "127.0.0.1" | 47 | #define DEFAULT_HOST "127.0.0.1" |
| 47 | 48 | ||
| 48 | /* return the PSQL server version as a 3-tuple */ | 49 | /* return the PSQL server version as a 3-tuple */ |
| 49 | #define PSQL_SERVER_VERSION3(server_version) \ | 50 | #define PSQL_SERVER_VERSION3(server_version) \ |
| 50 | (server_version) / 10000, (server_version) / 100 - (int)((server_version) / 10000) * 100, \ | 51 | ((server_version) / 10000), \ |
| 51 | (server_version) - (int)((server_version) / 100) * 100 | 52 | (((server_version) / 100) - (int)(((server_version) / 10000) * 100)), \ |
| 53 | (server_version) - (int)(((server_version) / 100) * 100) | ||
| 52 | /* return true if the given host is a UNIX domain socket */ | 54 | /* return true if the given host is a UNIX domain socket */ |
| 53 | #define PSQL_IS_UNIX_DOMAIN_SOCKET(host) ((NULL == (host)) || ('\0' == *(host)) || ('/' == *(host))) | 55 | #define PSQL_IS_UNIX_DOMAIN_SOCKET(host) ((NULL == (host)) || ('\0' == *(host)) || ('/' == *(host))) |
| 54 | /* return a 3-tuple identifying a host/port independent of the socket type */ | 56 | /* return a 3-tuple identifying a host/port independent of the socket type */ |
| @@ -64,15 +66,25 @@ static check_pgsql_config_wrapper process_arguments(int /*argc*/, char ** /*argv | |||
| 64 | 66 | ||
| 65 | static void print_help(void); | 67 | static void print_help(void); |
| 66 | static bool is_pg_logname(char * /*username*/); | 68 | static bool is_pg_logname(char * /*username*/); |
| 67 | static mp_state_enum do_query(PGconn * /*conn*/, char * /*query*/, const char /*pgqueryname*/[], | 69 | |
| 68 | thresholds * /*qthresholds*/, char * /*query_warning*/, | 70 | typedef enum { |
| 69 | char * /*query_critical*/); | 71 | QUERY_OK, |
| 72 | ERROR_WITH_QUERY, // critical | ||
| 73 | NO_ROWS_RETURNED, // warning | ||
| 74 | NO_COLUMNS_RETURNED, // warning | ||
| 75 | NO_DATA_RETURNED, // critica/ | ||
| 76 | RESULT_IS_NOT_NUMERIC // critical | ||
| 77 | } do_query_errorcode; | ||
| 78 | |||
| 79 | typedef struct { | ||
| 80 | do_query_errorcode error_code; | ||
| 81 | double numerical_result; | ||
| 82 | } do_query_wrapper; | ||
| 83 | static do_query_wrapper do_query(PGconn * /*conn*/, char * /*query*/); | ||
| 70 | void print_usage(void); | 84 | void print_usage(void); |
| 71 | 85 | ||
| 72 | static int verbose = 0; | 86 | static int verbose = 0; |
| 73 | 87 | ||
| 74 | #define OPTID_QUERYNAME -1000 | ||
| 75 | |||
| 76 | /****************************************************************************** | 88 | /****************************************************************************** |
| 77 | 89 | ||
| 78 | The (pseudo?)literate programming XML is contained within \@\@\- <XML> \-\@\@ | 90 | The (pseudo?)literate programming XML is contained within \@\@\- <XML> \-\@\@ |
| @@ -138,8 +150,8 @@ int main(int argc, char **argv) { | |||
| 138 | 150 | ||
| 139 | const check_pgsql_config config = tmp_config.config; | 151 | const check_pgsql_config config = tmp_config.config; |
| 140 | 152 | ||
| 141 | if (verbose > 2) { | 153 | if (config.output_format_is_set) { |
| 142 | printf("Arguments initialized\n"); | 154 | mp_set_format(config.output_format); |
| 143 | } | 155 | } |
| 144 | 156 | ||
| 145 | /* Set signal handling and alarm */ | 157 | /* Set signal handling and alarm */ |
| @@ -199,21 +211,41 @@ int main(int argc, char **argv) { | |||
| 199 | if (verbose) { | 211 | if (verbose) { |
| 200 | printf("Verifying connection\n"); | 212 | printf("Verifying connection\n"); |
| 201 | } | 213 | } |
| 214 | |||
| 215 | mp_check overall = mp_check_init(); | ||
| 216 | |||
| 217 | mp_subcheck sc_connection = mp_subcheck_init(); | ||
| 218 | |||
| 202 | if (PQstatus(conn) == CONNECTION_BAD) { | 219 | if (PQstatus(conn) == CONNECTION_BAD) { |
| 203 | printf(_("CRITICAL - no connection to '%s' (%s).\n"), config.dbName, PQerrorMessage(conn)); | 220 | sc_connection = mp_set_subcheck_state(sc_connection, STATE_CRITICAL); |
| 221 | xasprintf(&sc_connection.output, "no connection to '%s' (%s)", config.dbName, | ||
| 222 | PQerrorMessage(conn)); | ||
| 204 | PQfinish(conn); | 223 | PQfinish(conn); |
| 205 | return STATE_CRITICAL; | 224 | mp_add_subcheck_to_check(&overall, sc_connection); |
| 206 | } | 225 | mp_exit(overall); |
| 207 | |||
| 208 | mp_state_enum status = STATE_UNKNOWN; | ||
| 209 | if (elapsed_time > config.tcrit) { | ||
| 210 | status = STATE_CRITICAL; | ||
| 211 | } else if (elapsed_time > config.twarn) { | ||
| 212 | status = STATE_WARNING; | ||
| 213 | } else { | 226 | } else { |
| 214 | status = STATE_OK; | 227 | sc_connection = mp_set_subcheck_state(sc_connection, STATE_OK); |
| 228 | xasprintf(&sc_connection.output, "connected to '%s'", config.dbName); | ||
| 229 | mp_add_subcheck_to_check(&overall, sc_connection); | ||
| 215 | } | 230 | } |
| 216 | 231 | ||
| 232 | mp_subcheck sc_connection_time = mp_subcheck_init(); | ||
| 233 | sc_connection_time = mp_set_subcheck_default_state(sc_connection_time, STATE_UNKNOWN); | ||
| 234 | |||
| 235 | xasprintf(&sc_connection_time.output, "connection time: %.10g", elapsed_time); | ||
| 236 | |||
| 237 | mp_perfdata pd_connection_time = perfdata_init(); | ||
| 238 | pd_connection_time.label = "time"; | ||
| 239 | pd_connection_time.uom = "s"; | ||
| 240 | pd_connection_time = mp_set_pd_value(pd_connection_time, elapsed_time); | ||
| 241 | pd_connection_time = mp_pd_set_thresholds(pd_connection_time, config.time_thresholds); | ||
| 242 | |||
| 243 | mp_add_perfdata_to_subcheck(&sc_connection_time, pd_connection_time); | ||
| 244 | sc_connection_time = | ||
| 245 | mp_set_subcheck_state(sc_connection_time, mp_get_pd_status(pd_connection_time)); | ||
| 246 | |||
| 247 | mp_add_subcheck_to_check(&overall, sc_connection_time); | ||
| 248 | |||
| 217 | if (verbose) { | 249 | if (verbose) { |
| 218 | char *server_host = PQhost(conn); | 250 | char *server_host = PQhost(conn); |
| 219 | int server_version = PQserverVersion(conn); | 251 | int server_version = PQserverVersion(conn); |
| @@ -225,25 +257,87 @@ int main(int argc, char **argv) { | |||
| 225 | PSQL_SERVER_VERSION3(server_version), PQprotocolVersion(conn), PQbackendPID(conn)); | 257 | PSQL_SERVER_VERSION3(server_version), PQprotocolVersion(conn), PQbackendPID(conn)); |
| 226 | } | 258 | } |
| 227 | 259 | ||
| 228 | printf(_(" %s - database %s (%f sec.)|%s\n"), state_text(status), config.dbName, elapsed_time, | ||
| 229 | fperfdata("time", elapsed_time, "s", (config.twarn > 0.0), config.twarn, | ||
| 230 | (config.tcrit > 0.0), config.tcrit, true, 0, false, 0)); | ||
| 231 | |||
| 232 | mp_state_enum query_status = STATE_UNKNOWN; | ||
| 233 | if (config.pgquery) { | 260 | if (config.pgquery) { |
| 234 | query_status = do_query(conn, config.pgquery, config.pgqueryname, config.qthresholds, | 261 | mp_subcheck sc_query = mp_subcheck_init(); |
| 235 | config.query_warning, config.query_critical); | 262 | sc_query = mp_set_subcheck_default_state(sc_query, STATE_UNKNOWN); |
| 263 | if (config.pgqueryname) { | ||
| 264 | xasprintf(&sc_query.output, "query '%s'", config.pgqueryname); | ||
| 265 | } else { | ||
| 266 | xasprintf(&sc_query.output, "query '%s'", config.pgquery); | ||
| 267 | } | ||
| 268 | |||
| 269 | do_query_wrapper query_result = do_query(conn, config.pgquery); | ||
| 270 | |||
| 271 | switch (query_result.error_code) { | ||
| 272 | case QUERY_OK: { | ||
| 273 | // Query was successful and there is a numerical result | ||
| 274 | sc_query = mp_set_subcheck_state(sc_query, STATE_OK); | ||
| 275 | xasprintf(&sc_query.output, "%s succeeded", sc_query.output); | ||
| 276 | |||
| 277 | mp_perfdata pd_query = perfdata_init(); | ||
| 278 | pd_query = mp_set_pd_value(pd_query, query_result.numerical_result); | ||
| 279 | pd_query = mp_pd_set_thresholds(pd_query, config.qthresholds); | ||
| 280 | pd_query.label = "query"; | ||
| 281 | |||
| 282 | mp_subcheck sc_query_compare = mp_subcheck_init(); | ||
| 283 | mp_state_enum query_compare_state = mp_get_pd_status(pd_query); | ||
| 284 | |||
| 285 | sc_query_compare = mp_set_subcheck_state(sc_query_compare, query_compare_state); | ||
| 286 | mp_add_perfdata_to_subcheck(&sc_query_compare, pd_query); | ||
| 287 | |||
| 288 | if (query_compare_state == STATE_OK) { | ||
| 289 | xasprintf(&sc_query_compare.output, "query result '%f' is within thresholds", | ||
| 290 | query_result.numerical_result); | ||
| 291 | } else { | ||
| 292 | xasprintf(&sc_query_compare.output, "query result '%f' is violating thresholds", | ||
| 293 | query_result.numerical_result); | ||
| 294 | } | ||
| 295 | mp_add_subcheck_to_check(&overall, sc_query_compare); | ||
| 296 | |||
| 297 | } break; | ||
| 298 | case ERROR_WITH_QUERY: | ||
| 299 | xasprintf(&sc_query.output, "%s - Error with query: %s", sc_query.output, | ||
| 300 | PQerrorMessage(conn)); | ||
| 301 | sc_query = mp_set_subcheck_state(sc_query, STATE_CRITICAL); | ||
| 302 | break; | ||
| 303 | case NO_ROWS_RETURNED: | ||
| 304 | xasprintf(&sc_query.output, "%s - no rows were returned by the query", sc_query.output); | ||
| 305 | sc_query = mp_set_subcheck_state(sc_query, STATE_WARNING); | ||
| 306 | break; | ||
| 307 | case NO_COLUMNS_RETURNED: | ||
| 308 | xasprintf(&sc_query.output, "%s - no columns were returned by the query", | ||
| 309 | sc_query.output); | ||
| 310 | sc_query = mp_set_subcheck_state(sc_query, STATE_WARNING); | ||
| 311 | break; | ||
| 312 | case NO_DATA_RETURNED: | ||
| 313 | xasprintf(&sc_query.output, "%s - no data was returned by the query", sc_query.output); | ||
| 314 | sc_query = mp_set_subcheck_state(sc_query, STATE_WARNING); | ||
| 315 | break; | ||
| 316 | case RESULT_IS_NOT_NUMERIC: | ||
| 317 | xasprintf(&sc_query.output, "%s - result of the query is not numeric", sc_query.output); | ||
| 318 | sc_query = mp_set_subcheck_state(sc_query, STATE_CRITICAL); | ||
| 319 | break; | ||
| 320 | }; | ||
| 321 | |||
| 322 | mp_add_subcheck_to_check(&overall, sc_query); | ||
| 236 | } | 323 | } |
| 237 | 324 | ||
| 238 | if (verbose) { | 325 | if (verbose) { |
| 239 | printf("Closing connection\n"); | 326 | printf("Closing connection\n"); |
| 240 | } | 327 | } |
| 241 | PQfinish(conn); | 328 | PQfinish(conn); |
| 242 | return (config.pgquery && query_status > status) ? query_status : status; | 329 | |
| 330 | mp_exit(overall); | ||
| 243 | } | 331 | } |
| 244 | 332 | ||
| 245 | /* process command-line arguments */ | 333 | /* process command-line arguments */ |
| 246 | check_pgsql_config_wrapper process_arguments(int argc, char **argv) { | 334 | static check_pgsql_config_wrapper process_arguments(int argc, char **argv) { |
| 335 | |||
| 336 | enum { | ||
| 337 | OPTID_QUERYNAME = CHAR_MAX + 1, | ||
| 338 | output_format_index, | ||
| 339 | }; | ||
| 340 | |||
| 247 | static struct option longopts[] = {{"help", no_argument, 0, 'h'}, | 341 | static struct option longopts[] = {{"help", no_argument, 0, 'h'}, |
| 248 | {"version", no_argument, 0, 'V'}, | 342 | {"version", no_argument, 0, 'V'}, |
| 249 | {"timeout", required_argument, 0, 't'}, | 343 | {"timeout", required_argument, 0, 't'}, |
| @@ -261,6 +355,7 @@ check_pgsql_config_wrapper process_arguments(int argc, char **argv) { | |||
| 261 | {"query_critical", required_argument, 0, 'C'}, | 355 | {"query_critical", required_argument, 0, 'C'}, |
| 262 | {"query_warning", required_argument, 0, 'W'}, | 356 | {"query_warning", required_argument, 0, 'W'}, |
| 263 | {"verbose", no_argument, 0, 'v'}, | 357 | {"verbose", no_argument, 0, 'v'}, |
| 358 | {"output-format", required_argument, 0, output_format_index}, | ||
| 264 | {0, 0, 0, 0}}; | 359 | {0, 0, 0, 0}}; |
| 265 | 360 | ||
| 266 | check_pgsql_config_wrapper result = { | 361 | check_pgsql_config_wrapper result = { |
| @@ -278,6 +373,17 @@ check_pgsql_config_wrapper process_arguments(int argc, char **argv) { | |||
| 278 | } | 373 | } |
| 279 | 374 | ||
| 280 | switch (option_char) { | 375 | switch (option_char) { |
| 376 | case output_format_index: { | ||
| 377 | parsed_output_format parser = mp_parse_output_format(optarg); | ||
| 378 | if (!parser.parsing_success) { | ||
| 379 | printf("Invalid output format: %s\n", optarg); | ||
| 380 | exit(STATE_UNKNOWN); | ||
| 381 | } | ||
| 382 | |||
| 383 | result.config.output_format_is_set = true; | ||
| 384 | result.config.output_format = parser.output_format; | ||
| 385 | break; | ||
| 386 | } | ||
| 281 | case '?': /* usage */ | 387 | case '?': /* usage */ |
| 282 | usage5(); | 388 | usage5(); |
| 283 | case 'h': /* help */ | 389 | case 'h': /* help */ |
| @@ -293,26 +399,40 @@ check_pgsql_config_wrapper process_arguments(int argc, char **argv) { | |||
| 293 | timeout_interval = atoi(optarg); | 399 | timeout_interval = atoi(optarg); |
| 294 | } | 400 | } |
| 295 | break; | 401 | break; |
| 296 | case 'c': /* critical time threshold */ | 402 | case 'c': /* critical time threshold */ { |
| 297 | if (!is_nonnegative(optarg)) { | 403 | mp_range_parsed tmp = mp_parse_range_string(optarg); |
| 298 | usage2(_("Critical threshold must be a positive integer"), optarg); | 404 | if (tmp.error != MP_PARSING_SUCCES) { |
| 299 | } else { | 405 | die(STATE_UNKNOWN, "failed to parse critical time threshold"); |
| 300 | result.config.tcrit = strtod(optarg, NULL); | ||
| 301 | } | 406 | } |
| 302 | break; | 407 | result.config.time_thresholds = |
| 303 | case 'w': /* warning time threshold */ | 408 | mp_thresholds_set_crit(result.config.time_thresholds, tmp.range); |
| 304 | if (!is_nonnegative(optarg)) { | 409 | } break; |
| 305 | usage2(_("Warning threshold must be a positive integer"), optarg); | 410 | case 'w': /* warning time threshold */ { |
| 306 | } else { | 411 | mp_range_parsed tmp = mp_parse_range_string(optarg); |
| 307 | result.config.twarn = strtod(optarg, NULL); | 412 | if (tmp.error != MP_PARSING_SUCCES) { |
| 413 | die(STATE_UNKNOWN, "failed to parse warning time threshold"); | ||
| 308 | } | 414 | } |
| 309 | break; | 415 | result.config.time_thresholds = |
| 310 | case 'C': /* critical query threshold */ | 416 | mp_thresholds_set_warn(result.config.time_thresholds, tmp.range); |
| 311 | result.config.query_critical = optarg; | 417 | } break; |
| 312 | break; | 418 | case 'C': /* critical query threshold */ { |
| 313 | case 'W': /* warning query threshold */ | 419 | mp_range_parsed tmp = mp_parse_range_string(optarg); |
| 314 | result.config.query_warning = optarg; | 420 | if (tmp.error != MP_PARSING_SUCCES) { |
| 315 | break; | 421 | die(STATE_UNKNOWN, "failed to parse critical query threshold"); |
| 422 | } | ||
| 423 | |||
| 424 | result.config.qthresholds = | ||
| 425 | mp_thresholds_set_crit(result.config.qthresholds, tmp.range); | ||
| 426 | |||
| 427 | } break; | ||
| 428 | case 'W': /* warning query threshold */ { | ||
| 429 | mp_range_parsed tmp = mp_parse_range_string(optarg); | ||
| 430 | if (tmp.error != MP_PARSING_SUCCES) { | ||
| 431 | die(STATE_UNKNOWN, "failed to parse warning query threshold"); | ||
| 432 | } | ||
| 433 | result.config.qthresholds = | ||
| 434 | mp_thresholds_set_warn(result.config.qthresholds, tmp.range); | ||
| 435 | } break; | ||
| 316 | case 'H': /* host */ | 436 | case 'H': /* host */ |
| 317 | if ((*optarg != '/') && (!is_host(optarg))) { | 437 | if ((*optarg != '/') && (!is_host(optarg))) { |
| 318 | usage2(_("Invalid hostname/address"), optarg); | 438 | usage2(_("Invalid hostname/address"), optarg); |
| @@ -363,9 +483,6 @@ check_pgsql_config_wrapper process_arguments(int argc, char **argv) { | |||
| 363 | } | 483 | } |
| 364 | } | 484 | } |
| 365 | 485 | ||
| 366 | set_thresholds(&result.config.qthresholds, result.config.query_warning, | ||
| 367 | result.config.query_critical); | ||
| 368 | |||
| 369 | return result; | 486 | return result; |
| 370 | } | 487 | } |
| 371 | 488 | ||
| @@ -393,7 +510,7 @@ should be added.</para> | |||
| 393 | -@@ | 510 | -@@ |
| 394 | ******************************************************************************/ | 511 | ******************************************************************************/ |
| 395 | 512 | ||
| 396 | bool is_pg_logname(char *username) { | 513 | static bool is_pg_logname(char *username) { |
| 397 | if (strlen(username) > NAMEDATALEN - 1) { | 514 | if (strlen(username) > NAMEDATALEN - 1) { |
| 398 | return (false); | 515 | return (false); |
| 399 | } | 516 | } |
| @@ -447,12 +564,13 @@ void print_help(void) { | |||
| 447 | printf(" %s\n", "--queryname=STRING"); | 564 | printf(" %s\n", "--queryname=STRING"); |
| 448 | printf(" %s\n", _("A name for the query, this string is used instead of the query")); | 565 | printf(" %s\n", _("A name for the query, this string is used instead of the query")); |
| 449 | printf(" %s\n", _("in the long output of the plugin")); | 566 | printf(" %s\n", _("in the long output of the plugin")); |
| 450 | printf(" %s\n", "-W, --query-warning=RANGE"); | 567 | printf(" %s\n", "-W, --query_warning=RANGE"); |
| 451 | printf(" %s\n", _("SQL query value to result in warning status (double)")); | 568 | printf(" %s\n", _("SQL query value to result in warning status (double)")); |
| 452 | printf(" %s\n", "-C, --query-critical=RANGE"); | 569 | printf(" %s\n", "-C, --query_critical=RANGE"); |
| 453 | printf(" %s\n", _("SQL query value to result in critical status (double)")); | 570 | printf(" %s\n", _("SQL query value to result in critical status (double)")); |
| 454 | 571 | ||
| 455 | printf(UT_VERBOSE); | 572 | printf(UT_VERBOSE); |
| 573 | printf(UT_OUTPUT_FORMAT); | ||
| 456 | 574 | ||
| 457 | printf("\n"); | 575 | printf("\n"); |
| 458 | printf(" %s\n", _("All parameters are optional.")); | 576 | printf(" %s\n", _("All parameters are optional.")); |
| @@ -509,33 +627,44 @@ void print_usage(void) { | |||
| 509 | "[-q <query>] [-C <critical query range>] [-W <warning query range>]\n"); | 627 | "[-q <query>] [-C <critical query range>] [-W <warning query range>]\n"); |
| 510 | } | 628 | } |
| 511 | 629 | ||
| 512 | mp_state_enum do_query(PGconn *conn, char *query, const char pgqueryname[], thresholds *qthresholds, | 630 | static do_query_wrapper do_query(PGconn *conn, char *query) { |
| 513 | char *query_warning, char *query_critical) { | ||
| 514 | if (verbose) { | 631 | if (verbose) { |
| 515 | printf("Executing SQL query \"%s\".\n", query); | 632 | printf("Executing SQL query \"%s\".\n", query); |
| 516 | } | 633 | } |
| 517 | PGresult *res = PQexec(conn, query); | 634 | PGresult *res = PQexec(conn, query); |
| 518 | 635 | ||
| 636 | do_query_wrapper result = { | ||
| 637 | .error_code = QUERY_OK, | ||
| 638 | }; | ||
| 639 | |||
| 519 | if (PGRES_TUPLES_OK != PQresultStatus(res)) { | 640 | if (PGRES_TUPLES_OK != PQresultStatus(res)) { |
| 520 | printf(_("QUERY %s - %s: %s.\n"), _("CRITICAL"), _("Error with query"), | 641 | // TODO |
| 521 | PQerrorMessage(conn)); | 642 | // printf(_("QUERY %s - %s: %s.\n"), _("CRITICAL"), _("Error with query"), |
| 522 | return STATE_CRITICAL; | 643 | // PQerrorMessage(conn)); |
| 644 | result.error_code = ERROR_WITH_QUERY; | ||
| 645 | return result; | ||
| 523 | } | 646 | } |
| 524 | 647 | ||
| 525 | if (PQntuples(res) < 1) { | 648 | if (PQntuples(res) < 1) { |
| 526 | printf("QUERY %s - %s.\n", _("WARNING"), _("No rows returned")); | 649 | // TODO |
| 527 | return STATE_WARNING; | 650 | // printf("QUERY %s - %s.\n", _("WARNING"), _("No rows returned")); |
| 651 | result.error_code = NO_ROWS_RETURNED; | ||
| 652 | return result; | ||
| 528 | } | 653 | } |
| 529 | 654 | ||
| 530 | if (PQnfields(res) < 1) { | 655 | if (PQnfields(res) < 1) { |
| 531 | printf("QUERY %s - %s.\n", _("WARNING"), _("No columns returned")); | 656 | // TODO |
| 532 | return STATE_WARNING; | 657 | // printf("QUERY %s - %s.\n", _("WARNING"), _("No columns returned")); |
| 658 | result.error_code = NO_COLUMNS_RETURNED; | ||
| 659 | return result; | ||
| 533 | } | 660 | } |
| 534 | 661 | ||
| 535 | char *val_str = PQgetvalue(res, 0, 0); | 662 | char *val_str = PQgetvalue(res, 0, 0); |
| 536 | if (!val_str) { | 663 | if (!val_str) { |
| 537 | printf("QUERY %s - %s.\n", _("CRITICAL"), _("No data returned")); | 664 | // TODO |
| 538 | return STATE_CRITICAL; | 665 | // printf("QUERY %s - %s.\n", _("CRITICAL"), _("No data returned")); |
| 666 | result.error_code = NO_DATA_RETURNED; | ||
| 667 | return result; | ||
| 539 | } | 668 | } |
| 540 | 669 | ||
| 541 | char *endptr = NULL; | 670 | char *endptr = NULL; |
| @@ -545,8 +674,10 @@ mp_state_enum do_query(PGconn *conn, char *query, const char pgqueryname[], thre | |||
| 545 | } | 674 | } |
| 546 | 675 | ||
| 547 | if (endptr == val_str) { | 676 | if (endptr == val_str) { |
| 548 | printf("QUERY %s - %s: %s\n", _("CRITICAL"), _("Is not a numeric"), val_str); | 677 | // TODO |
| 549 | return STATE_CRITICAL; | 678 | // printf("QUERY %s - %s: %s\n", _("CRITICAL"), _("Is not a numeric"), val_str); |
| 679 | result.error_code = RESULT_IS_NOT_NUMERIC; | ||
| 680 | return result; | ||
| 550 | } | 681 | } |
| 551 | 682 | ||
| 552 | if ((endptr != NULL) && (*endptr != '\0')) { | 683 | if ((endptr != NULL) && (*endptr != '\0')) { |
| @@ -555,24 +686,7 @@ mp_state_enum do_query(PGconn *conn, char *query, const char pgqueryname[], thre | |||
| 555 | } | 686 | } |
| 556 | } | 687 | } |
| 557 | 688 | ||
| 558 | mp_state_enum my_status = get_status(value, qthresholds); | 689 | result.numerical_result = value; |
| 559 | printf("QUERY %s - ", (my_status == STATE_OK) ? _("OK") | ||
| 560 | : (my_status == STATE_WARNING) ? _("WARNING") | ||
| 561 | : (my_status == STATE_CRITICAL) ? _("CRITICAL") | ||
| 562 | : _("UNKNOWN")); | ||
| 563 | if (pgqueryname) { | ||
| 564 | printf(_("%s returned %f"), pgqueryname, value); | ||
| 565 | } else { | ||
| 566 | printf(_("'%s' returned %f"), query, value); | ||
| 567 | } | ||
| 568 | 690 | ||
| 569 | printf("|query=%f;%s;%s;;\n", value, query_warning ? query_warning : "", | 691 | return result; |
| 570 | query_critical ? query_critical : ""); | ||
| 571 | if (PQnfields(res) > 1) { | ||
| 572 | char *extra_info = PQgetvalue(res, 0, 1); | ||
| 573 | if (extra_info != NULL) { | ||
| 574 | printf("Extra Info: %s\n", extra_info); | ||
| 575 | } | ||
| 576 | } | ||
| 577 | return my_status; | ||
| 578 | } | 692 | } |
diff --git a/plugins/check_pgsql.d/config.h b/plugins/check_pgsql.d/config.h index 2d4b8b89..7cf0637b 100644 --- a/plugins/check_pgsql.d/config.h +++ b/plugins/check_pgsql.d/config.h | |||
| @@ -1,6 +1,8 @@ | |||
| 1 | #pragma once | 1 | #pragma once |
| 2 | 2 | ||
| 3 | #include "../../config.h" | 3 | #include "../../config.h" |
| 4 | #include "output.h" | ||
| 5 | #include "perfdata.h" | ||
| 4 | #include "thresholds.h" | 6 | #include "thresholds.h" |
| 5 | #include <stddef.h> | 7 | #include <stddef.h> |
| 6 | #include <pg_config_manual.h> | 8 | #include <pg_config_manual.h> |
| @@ -24,11 +26,11 @@ typedef struct { | |||
| 24 | char *pgquery; | 26 | char *pgquery; |
| 25 | char *pgqueryname; | 27 | char *pgqueryname; |
| 26 | 28 | ||
| 27 | double twarn; | 29 | mp_thresholds time_thresholds; |
| 28 | double tcrit; | 30 | mp_thresholds qthresholds; |
| 29 | thresholds *qthresholds; | 31 | |
| 30 | char *query_warning; | 32 | bool output_format_is_set; |
| 31 | char *query_critical; | 33 | mp_output_format output_format; |
| 32 | } check_pgsql_config; | 34 | } check_pgsql_config; |
| 33 | 35 | ||
| 34 | /* begin, by setting the parameters for a backend connection if the | 36 | /* begin, by setting the parameters for a backend connection if the |
| @@ -51,11 +53,18 @@ check_pgsql_config check_pgsql_config_init() { | |||
| 51 | .pgquery = NULL, | 53 | .pgquery = NULL, |
| 52 | .pgqueryname = NULL, | 54 | .pgqueryname = NULL, |
| 53 | 55 | ||
| 54 | .twarn = (double)DEFAULT_WARN, | 56 | .time_thresholds = mp_thresholds_init(), |
| 55 | .tcrit = (double)DEFAULT_CRIT, | 57 | .qthresholds = mp_thresholds_init(), |
| 56 | .qthresholds = NULL, | 58 | |
| 57 | .query_warning = NULL, | 59 | .output_format_is_set = false, |
| 58 | .query_critical = NULL, | ||
| 59 | }; | 60 | }; |
| 61 | |||
| 62 | mp_range tmp_range = mp_range_init(); | ||
| 63 | tmp_range = mp_range_set_end(tmp_range, mp_create_pd_value(DEFAULT_WARN)); | ||
| 64 | tmp.time_thresholds = mp_thresholds_set_warn(tmp.time_thresholds, tmp_range); | ||
| 65 | |||
| 66 | tmp_range = mp_range_set_end(tmp_range, mp_create_pd_value(DEFAULT_CRIT)); | ||
| 67 | tmp.time_thresholds = mp_thresholds_set_crit(tmp.time_thresholds, tmp_range); | ||
| 68 | |||
| 60 | return tmp; | 69 | return tmp; |
| 61 | } | 70 | } |
diff --git a/plugins/check_snmp.c b/plugins/check_snmp.c index a5a7afe8..f470d222 100644 --- a/plugins/check_snmp.c +++ b/plugins/check_snmp.c | |||
| @@ -41,8 +41,6 @@ const char *email = "devel@monitoring-plugins.org"; | |||
| 41 | #include "../lib/output.h" | 41 | #include "../lib/output.h" |
| 42 | #include "check_snmp.d/check_snmp_helpers.h" | 42 | #include "check_snmp.d/check_snmp_helpers.h" |
| 43 | 43 | ||
| 44 | #include <bits/getopt_core.h> | ||
| 45 | #include <bits/getopt_ext.h> | ||
| 46 | #include <strings.h> | 44 | #include <strings.h> |
| 47 | #include <stdint.h> | 45 | #include <stdint.h> |
| 48 | 46 | ||
diff --git a/plugins/check_swap.d/swap.c b/plugins/check_swap.d/swap.c index 5b654197..58213a3c 100644 --- a/plugins/check_swap.d/swap.c +++ b/plugins/check_swap.d/swap.c | |||
| @@ -52,10 +52,10 @@ swap_result get_swap_data(swap_config config) { | |||
| 52 | } | 52 | } |
| 53 | # else // HAVE_SWAP | 53 | # else // HAVE_SWAP |
| 54 | # ifdef CHECK_SWAP_SWAPCTL_SVR4 | 54 | # ifdef CHECK_SWAP_SWAPCTL_SVR4 |
| 55 | return getSwapFromSwapctl_SRV4(); | 55 | return getSwapFromSwapctl_SRV4(config); |
| 56 | # else // CHECK_SWAP_SWAPCTL_SVR4 | 56 | # else // CHECK_SWAP_SWAPCTL_SVR4 |
| 57 | # ifdef CHECK_SWAP_SWAPCTL_BSD | 57 | # ifdef CHECK_SWAP_SWAPCTL_BSD |
| 58 | return getSwapFromSwapctl_BSD(); | 58 | return getSwapFromSwapctl_BSD(config); |
| 59 | # else // CHECK_SWAP_SWAPCTL_BSD | 59 | # else // CHECK_SWAP_SWAPCTL_BSD |
| 60 | # error No way found to retrieve swap | 60 | # error No way found to retrieve swap |
| 61 | # endif /* CHECK_SWAP_SWAPCTL_BSD */ | 61 | # endif /* CHECK_SWAP_SWAPCTL_BSD */ |
diff --git a/plugins/check_users.c b/plugins/check_users.c index 2340eae4..3b2e265e 100644 --- a/plugins/check_users.c +++ b/plugins/check_users.c | |||
| @@ -51,8 +51,6 @@ const char *email = "devel@monitoring-plugins.org"; | |||
| 51 | # define ERROR -1 | 51 | # define ERROR -1 |
| 52 | #elif HAVE_UTMPX_H | 52 | #elif HAVE_UTMPX_H |
| 53 | # include <utmpx.h> | 53 | # include <utmpx.h> |
| 54 | #else | ||
| 55 | # include "popen.h" | ||
| 56 | #endif | 54 | #endif |
| 57 | 55 | ||
| 58 | #ifdef HAVE_LIBSYSTEMD | 56 | #ifdef HAVE_LIBSYSTEMD |
diff --git a/plugins/check_users.d/users.c b/plugins/check_users.d/users.c index f37819b1..a08f79c5 100644 --- a/plugins/check_users.d/users.c +++ b/plugins/check_users.d/users.c | |||
| @@ -113,8 +113,8 @@ get_num_of_users_wrapper get_num_of_users_utmp() { | |||
| 113 | # ifndef HAVE_UTMPX_H | 113 | # ifndef HAVE_UTMPX_H |
| 114 | // Fall back option here for the others (probably still not on windows) | 114 | // Fall back option here for the others (probably still not on windows) |
| 115 | 115 | ||
| 116 | # include "../popen.h" | ||
| 117 | # include "../common.h" | 116 | # include "../common.h" |
| 117 | # include "../popen.h" | ||
| 118 | # include "../utils.h" | 118 | # include "../utils.h" |
| 119 | 119 | ||
| 120 | get_num_of_users_wrapper get_num_of_users_who_command() { | 120 | get_num_of_users_wrapper get_num_of_users_who_command() { |
diff --git a/plugins/t/check_apt.t b/plugins/t/check_apt.t index 430eb53e..736bc2f2 100644 --- a/plugins/t/check_apt.t +++ b/plugins/t/check_apt.t | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | # | 5 | # |
| 6 | 6 | ||
| 7 | use strict; | 7 | use strict; |
| 8 | use warnings; | ||
| 8 | use Test::More; | 9 | use Test::More; |
| 9 | use NPTest; | 10 | use NPTest; |
| 10 | 11 | ||
| @@ -12,18 +13,18 @@ sub make_result_regexp { | |||
| 12 | my ($warning, $critical) = @_; | 13 | my ($warning, $critical) = @_; |
| 13 | my $status; | 14 | my $status; |
| 14 | if ($warning == 0 && $critical == 0) { | 15 | if ($warning == 0 && $critical == 0) { |
| 15 | $status = "OK"; | 16 | $status = "OK"; |
| 16 | } elsif ($critical == 0) { | 17 | } elsif ($critical == 0) { |
| 17 | $status = "WARNING"; | 18 | $status = "WARNING"; |
| 18 | } else { | 19 | } else { |
| 19 | $status = "CRITICAL"; | 20 | $status = "CRITICAL"; |
| 20 | } | 21 | } |
| 21 | return sprintf('/^APT %s: %d packages available for upgrade \(%d critical updates\)\. |available_upgrades=%d;;;0 critical_updates=%d;;;0$/', | 22 | return sprintf('/.*[%s].*Updates available: %d.*Security updates available: %d.*\'available_upgrades\'=%d;;; \'critical_updates\'=%d;;; /s', |
| 22 | $status, $warning, $critical, $warning, $critical); | 23 | $status, $warning, $critical, $warning, $critical); |
| 23 | } | 24 | } |
| 24 | 25 | ||
| 25 | if (-x "./check_apt") { | 26 | if (-x "./check_apt") { |
| 26 | plan tests => 36; | 27 | plan tests => 35; |
| 27 | } else { | 28 | } else { |
| 28 | plan skip_all => "No check_apt compiled"; | 29 | plan skip_all => "No check_apt compiled"; |
| 29 | } | 30 | } |
| @@ -42,7 +43,8 @@ like( $result->output, make_result_regexp(13, 0), "Output correct" ); | |||
| 42 | 43 | ||
| 43 | $result = NPTest->testCmd( sprintf($testfile_command, "-o", "debian2") ); | 44 | $result = NPTest->testCmd( sprintf($testfile_command, "-o", "debian2") ); |
| 44 | is( $result->return_code, 0, "Debian apt output, no critical" ); | 45 | is( $result->return_code, 0, "Debian apt output, no critical" ); |
| 45 | like( $result->output, make_result_regexp(13, 0), "Output correct" ); | 46 | # this test does not work, since -o was given |
| 47 | # like( $result->output, make_result_regexp(13, 0), "Output correct" ); | ||
| 46 | 48 | ||
| 47 | $result = NPTest->testCmd( sprintf($testfile_command, "", "debian3") ); | 49 | $result = NPTest->testCmd( sprintf($testfile_command, "", "debian3") ); |
| 48 | is( $result->return_code, 2, "Debian apt output, some critical" ); | 50 | is( $result->return_code, 2, "Debian apt output, some critical" ); |
