summaryrefslogtreecommitdiffstats
path: root/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'plugins')
-rw-r--r--plugins/check_curl.c153
-rw-r--r--plugins/check_curl.d/check_curl_helpers.c457
-rw-r--r--plugins/check_curl.d/check_curl_helpers.h9
-rw-r--r--plugins/check_curl.d/config.h7
-rw-r--r--plugins/check_dbi.c4
-rw-r--r--plugins/check_disk.c4
-rw-r--r--plugins/check_http.c4
-rw-r--r--plugins/check_ldap.c12
-rw-r--r--plugins/check_mrtg.c8
-rw-r--r--plugins/check_mysql.c4
-rw-r--r--plugins/check_mysql_query.c4
-rw-r--r--plugins/check_ntp_peer.c20
-rw-r--r--plugins/check_ntp_time.c20
-rw-r--r--plugins/check_pgsql.c8
-rw-r--r--plugins/check_ping.c4
-rw-r--r--plugins/check_procs.c2
-rw-r--r--plugins/check_real.c4
-rw-r--r--plugins/check_smtp.c20
-rw-r--r--plugins/check_snmp.d/check_snmp_helpers.c4
-rw-r--r--plugins/check_ssh.c16
-rw-r--r--plugins/check_tcp.c16
-rw-r--r--plugins/check_users.c4
-rw-r--r--plugins/netutils.c10
-rw-r--r--plugins/netutils.h4
-rw-r--r--plugins/t/check_curl.t115
-rwxr-xr-xplugins/tests/check_curl.t135
26 files changed, 919 insertions, 129 deletions
diff --git a/plugins/check_curl.c b/plugins/check_curl.c
index 1dec8a2a..f63cdea2 100644
--- a/plugins/check_curl.c
+++ b/plugins/check_curl.c
@@ -120,6 +120,14 @@ mp_state_enum np_net_ssl_check_certificate(X509 *certificate, int days_till_exp_
120#endif /* defined(HAVE_SSL) && defined(USE_OPENSSL) */ 120#endif /* defined(HAVE_SSL) && defined(USE_OPENSSL) */
121 121
122int main(int argc, char **argv) { 122int main(int argc, char **argv) {
123#ifdef __OpenBSD__
124 /* - rpath is required to read --extra-opts, CA and/or client certs
125 * - wpath is required to write --cookie-jar (possibly given up later)
126 * - inet is required for sockets
127 * - dns is required for name lookups */
128 pledge("stdio rpath wpath inet dns", NULL);
129#endif // __OpenBSD__
130
123 setlocale(LC_ALL, ""); 131 setlocale(LC_ALL, "");
124 bindtextdomain(PACKAGE, LOCALEDIR); 132 bindtextdomain(PACKAGE, LOCALEDIR);
125 textdomain(PACKAGE); 133 textdomain(PACKAGE);
@@ -135,6 +143,15 @@ int main(int argc, char **argv) {
135 143
136 const check_curl_config config = tmp_config.config; 144 const check_curl_config config = tmp_config.config;
137 145
146#ifdef __OpenBSD__
147 if (!config.curl_config.cookie_jar_file) {
148 if (verbose >= 2) {
149 printf(_("* No \"--cookie-jar\" is used, giving up \"wpath\" pledge(2)\n"));
150 }
151 pledge("stdio rpath inet dns", NULL);
152 }
153#endif // __OpenBSD__
154
138 if (config.output_format_is_set) { 155 if (config.output_format_is_set) {
139 mp_set_format(config.output_format); 156 mp_set_format(config.output_format);
140 } 157 }
@@ -222,10 +239,35 @@ mp_subcheck check_http(const check_curl_config config, check_curl_working_state
222 // ============== 239 // ==============
223 CURLcode res = curl_easy_perform(curl_state.curl); 240 CURLcode res = curl_easy_perform(curl_state.curl);
224 241
242 if (verbose > 1) {
243 printf("* curl_easy_perform returned: %s\n", curl_easy_strerror(res));
244 }
245
225 if (verbose >= 2 && workingState.http_post_data) { 246 if (verbose >= 2 && workingState.http_post_data) {
226 printf("**** REQUEST CONTENT ****\n%s\n", workingState.http_post_data); 247 printf("**** REQUEST CONTENT ****\n%s\n", workingState.http_post_data);
227 } 248 }
228 249
250 // curl_state is updated after curl_easy_perform, and with updated curl_state certificate checks can be done
251 // Check_http tries to check certs as early as possible, and exits with certificate check result by default. Behave similarly.
252#ifdef LIBCURL_FEATURE_SSL
253 if (workingState.use_ssl && config.check_cert) {
254 if (verbose > 1) {
255 printf("* adding a subcheck for the certificate\n");
256 }
257 mp_subcheck sc_certificate = check_curl_certificate_checks(
258 curl_state.curl, cert, config.days_till_exp_warn, config.days_till_exp_crit);
259
260 mp_add_subcheck_to_subcheck(&sc_result, sc_certificate);
261 if (!config.continue_after_check_cert) {
262 if (verbose > 1) {
263 printf("* returning after adding the subcheck for certificate, continuing after "
264 "checking the certificate is turned off\n");
265 }
266 return sc_result;
267 }
268 }
269#endif
270
229 mp_subcheck sc_curl = mp_subcheck_init(); 271 mp_subcheck sc_curl = mp_subcheck_init();
230 272
231 /* Curl errors, result in critical Nagios state */ 273 /* Curl errors, result in critical Nagios state */
@@ -266,18 +308,6 @@ mp_subcheck check_http(const check_curl_config config, check_curl_working_state
266 // Evaluation 308 // Evaluation
267 // ========== 309 // ==========
268 310
269#ifdef LIBCURL_FEATURE_SSL
270 if (workingState.use_ssl && config.check_cert) {
271 mp_subcheck sc_certificate = check_curl_certificate_checks(
272 curl_state.curl, cert, config.days_till_exp_warn, config.days_till_exp_crit);
273
274 mp_add_subcheck_to_subcheck(&sc_result, sc_certificate);
275 if (!config.continue_after_check_cert) {
276 return sc_result;
277 }
278 }
279#endif
280
281 /* we got the data and we executed the request in a given time, so we can append 311 /* we got the data and we executed the request in a given time, so we can append
282 * performance data to the answer always 312 * performance data to the answer always
283 */ 313 */
@@ -857,7 +887,8 @@ check_curl_config_wrapper process_arguments(int argc, char **argv) {
857 COOKIE_JAR, 887 COOKIE_JAR,
858 HAPROXY_PROTOCOL, 888 HAPROXY_PROTOCOL,
859 STATE_REGEX, 889 STATE_REGEX,
860 OUTPUT_FORMAT 890 OUTPUT_FORMAT,
891 NO_PROXY,
861 }; 892 };
862 893
863 static struct option longopts[] = { 894 static struct option longopts[] = {
@@ -872,6 +903,8 @@ check_curl_config_wrapper process_arguments(int argc, char **argv) {
872 {"url", required_argument, 0, 'u'}, 903 {"url", required_argument, 0, 'u'},
873 {"port", required_argument, 0, 'p'}, 904 {"port", required_argument, 0, 'p'},
874 {"authorization", required_argument, 0, 'a'}, 905 {"authorization", required_argument, 0, 'a'},
906 {"proxy", required_argument, 0, 'x'},
907 {"noproxy", required_argument, 0, NO_PROXY},
875 {"proxy-authorization", required_argument, 0, 'b'}, 908 {"proxy-authorization", required_argument, 0, 'b'},
876 {"header-string", required_argument, 0, 'd'}, 909 {"header-string", required_argument, 0, 'd'},
877 {"string", required_argument, 0, 's'}, 910 {"string", required_argument, 0, 's'},
@@ -944,7 +977,7 @@ check_curl_config_wrapper process_arguments(int argc, char **argv) {
944 977
945 while (true) { 978 while (true) {
946 int option_index = getopt_long( 979 int option_index = getopt_long(
947 argc, argv, "Vvh46t:c:w:A:k:H:P:j:T:I:a:b:d:e:p:s:R:r:u:f:C:J:K:DnlLS::m:M:NEB", 980 argc, argv, "Vvh46t:c:w:A:k:H:P:j:T:I:a:x:b:d:e:p:s:R:r:u:f:C:J:K:DnlLS::m:M:NEB",
948 longopts, &option); 981 longopts, &option);
949 if (option_index == -1 || option_index == EOF || option_index == 1) { 982 if (option_index == -1 || option_index == EOF || option_index == 1) {
950 break; 983 break;
@@ -973,7 +1006,7 @@ check_curl_config_wrapper process_arguments(int argc, char **argv) {
973 case 'c': /* critical time threshold */ 1006 case 'c': /* critical time threshold */
974 { 1007 {
975 mp_range_parsed critical_range = mp_parse_range_string(optarg); 1008 mp_range_parsed critical_range = mp_parse_range_string(optarg);
976 if (critical_range.error != MP_PARSING_SUCCES) { 1009 if (critical_range.error != MP_PARSING_SUCCESS) {
977 die(STATE_UNKNOWN, "failed to parse critical threshold: %s", optarg); 1010 die(STATE_UNKNOWN, "failed to parse critical threshold: %s", optarg);
978 } 1011 }
979 result.config.thlds = mp_thresholds_set_crit(result.config.thlds, critical_range.range); 1012 result.config.thlds = mp_thresholds_set_crit(result.config.thlds, critical_range.range);
@@ -982,7 +1015,7 @@ check_curl_config_wrapper process_arguments(int argc, char **argv) {
982 { 1015 {
983 mp_range_parsed warning_range = mp_parse_range_string(optarg); 1016 mp_range_parsed warning_range = mp_parse_range_string(optarg);
984 1017
985 if (warning_range.error != MP_PARSING_SUCCES) { 1018 if (warning_range.error != MP_PARSING_SUCCESS) {
986 die(STATE_UNKNOWN, "failed to parse warning threshold: %s", optarg); 1019 die(STATE_UNKNOWN, "failed to parse warning threshold: %s", optarg);
987 } 1020 }
988 result.config.thlds = mp_thresholds_set_warn(result.config.thlds, warning_range.range); 1021 result.config.thlds = mp_thresholds_set_warn(result.config.thlds, warning_range.range);
@@ -1032,6 +1065,10 @@ check_curl_config_wrapper process_arguments(int argc, char **argv) {
1032 strncpy(result.config.curl_config.user_auth, optarg, MAX_INPUT_BUFFER - 1); 1065 strncpy(result.config.curl_config.user_auth, optarg, MAX_INPUT_BUFFER - 1);
1033 result.config.curl_config.user_auth[MAX_INPUT_BUFFER - 1] = 0; 1066 result.config.curl_config.user_auth[MAX_INPUT_BUFFER - 1] = 0;
1034 break; 1067 break;
1068 case 'x': /* proxy info */
1069 strncpy(result.config.curl_config.proxy, optarg, DEFAULT_BUFFER_SIZE - 1);
1070 result.config.curl_config.proxy[DEFAULT_BUFFER_SIZE - 1] = 0;
1071 break;
1035 case 'b': /* proxy-authorization info */ 1072 case 'b': /* proxy-authorization info */
1036 strncpy(result.config.curl_config.proxy_auth, optarg, MAX_INPUT_BUFFER - 1); 1073 strncpy(result.config.curl_config.proxy_auth, optarg, MAX_INPUT_BUFFER - 1);
1037 result.config.curl_config.proxy_auth[MAX_INPUT_BUFFER - 1] = 0; 1074 result.config.curl_config.proxy_auth[MAX_INPUT_BUFFER - 1] = 0;
@@ -1248,7 +1285,7 @@ check_curl_config_wrapper process_arguments(int argc, char **argv) {
1248 result.config.curl_config.sin_family = AF_INET; 1285 result.config.curl_config.sin_family = AF_INET;
1249 break; 1286 break;
1250 case '6': 1287 case '6':
1251#if defined(USE_IPV6) && defined(LIBCURL_FEATURE_IPV6) 1288#if defined(LIBCURL_FEATURE_IPV6)
1252 result.config.curl_config.sin_family = AF_INET6; 1289 result.config.curl_config.sin_family = AF_INET6;
1253#else 1290#else
1254 usage4(_("IPv6 support not available")); 1291 usage4(_("IPv6 support not available"));
@@ -1258,7 +1295,7 @@ check_curl_config_wrapper process_arguments(int argc, char **argv) {
1258 { 1295 {
1259 mp_range_parsed foo = mp_parse_range_string(optarg); 1296 mp_range_parsed foo = mp_parse_range_string(optarg);
1260 1297
1261 if (foo.error != MP_PARSING_SUCCES) { 1298 if (foo.error != MP_PARSING_SUCCESS) {
1262 die(STATE_CRITICAL, "failed to parse page size limits: %s", optarg); 1299 die(STATE_CRITICAL, "failed to parse page size limits: %s", optarg);
1263 } 1300 }
1264 1301
@@ -1327,6 +1364,10 @@ check_curl_config_wrapper process_arguments(int argc, char **argv) {
1327 case HAPROXY_PROTOCOL: 1364 case HAPROXY_PROTOCOL:
1328 result.config.curl_config.haproxy_protocol = true; 1365 result.config.curl_config.haproxy_protocol = true;
1329 break; 1366 break;
1367 case NO_PROXY:
1368 strncpy(result.config.curl_config.no_proxy, optarg, DEFAULT_BUFFER_SIZE - 1);
1369 result.config.curl_config.no_proxy[DEFAULT_BUFFER_SIZE - 1] = 0;
1370 break;
1330 case '?': 1371 case '?':
1331 /* print short usage statement if args not parsable */ 1372 /* print short usage statement if args not parsable */
1332 usage5(); 1373 usage5();
@@ -1354,35 +1395,35 @@ check_curl_config_wrapper process_arguments(int argc, char **argv) {
1354 * parameters, like -S and -C combinations */ 1395 * parameters, like -S and -C combinations */
1355 result.config.curl_config.ssl_version = CURL_SSLVERSION_DEFAULT; 1396 result.config.curl_config.ssl_version = CURL_SSLVERSION_DEFAULT;
1356 if (tls_option_optarg != NULL) { 1397 if (tls_option_optarg != NULL) {
1357 char *plus_ptr = strchr(optarg, '+'); 1398 char *plus_ptr = strchr(tls_option_optarg, '+');
1358 if (plus_ptr) { 1399 if (plus_ptr) {
1359 got_plus = true; 1400 got_plus = true;
1360 *plus_ptr = '\0'; 1401 *plus_ptr = '\0';
1361 } 1402 }
1362 1403
1363 if (optarg[0] == '2') { 1404 if (tls_option_optarg[0] == '2') {
1364 result.config.curl_config.ssl_version = CURL_SSLVERSION_SSLv2; 1405 result.config.curl_config.ssl_version = CURL_SSLVERSION_SSLv2;
1365 } else if (optarg[0] == '3') { 1406 } else if (tls_option_optarg[0] == '3') {
1366 result.config.curl_config.ssl_version = CURL_SSLVERSION_SSLv3; 1407 result.config.curl_config.ssl_version = CURL_SSLVERSION_SSLv3;
1367 } else if (!strcmp(optarg, "1") || !strcmp(optarg, "1.0")) { 1408 } else if (!strcmp(tls_option_optarg, "1") || !strcmp(tls_option_optarg, "1.0")) {
1368#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) 1409#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0)
1369 result.config.curl_config.ssl_version = CURL_SSLVERSION_TLSv1_0; 1410 result.config.curl_config.ssl_version = CURL_SSLVERSION_TLSv1_0;
1370#else 1411#else
1371 result.config.ssl_version = CURL_SSLVERSION_DEFAULT; 1412 result.config.ssl_version = CURL_SSLVERSION_DEFAULT;
1372#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) */ 1413#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) */
1373 } else if (!strcmp(optarg, "1.1")) { 1414 } else if (!strcmp(tls_option_optarg, "1.1")) {
1374#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) 1415#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0)
1375 result.config.curl_config.ssl_version = CURL_SSLVERSION_TLSv1_1; 1416 result.config.curl_config.ssl_version = CURL_SSLVERSION_TLSv1_1;
1376#else 1417#else
1377 result.config.ssl_version = CURL_SSLVERSION_DEFAULT; 1418 result.config.ssl_version = CURL_SSLVERSION_DEFAULT;
1378#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) */ 1419#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) */
1379 } else if (!strcmp(optarg, "1.2")) { 1420 } else if (!strcmp(tls_option_optarg, "1.2")) {
1380#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) 1421#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0)
1381 result.config.curl_config.ssl_version = CURL_SSLVERSION_TLSv1_2; 1422 result.config.curl_config.ssl_version = CURL_SSLVERSION_TLSv1_2;
1382#else 1423#else
1383 result.config.ssl_version = CURL_SSLVERSION_DEFAULT; 1424 result.config.ssl_version = CURL_SSLVERSION_DEFAULT;
1384#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) */ 1425#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) */
1385 } else if (!strcmp(optarg, "1.3")) { 1426 } else if (!strcmp(tls_option_optarg, "1.3")) {
1386#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 52, 0) 1427#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 52, 0)
1387 result.config.curl_config.ssl_version = CURL_SSLVERSION_TLSv1_3; 1428 result.config.curl_config.ssl_version = CURL_SSLVERSION_TLSv1_3;
1388#else 1429#else
@@ -1505,8 +1546,8 @@ void print_help(void) {
1505 printf(" %s\n", "-I, --IP-address=ADDRESS"); 1546 printf(" %s\n", "-I, --IP-address=ADDRESS");
1506 printf(" %s\n", 1547 printf(" %s\n",
1507 "IP address or name (use numeric address if possible to bypass DNS lookup)."); 1548 "IP address or name (use numeric address if possible to bypass DNS lookup).");
1508 printf(" %s\n", "This overwrites the network address of the target while leaving everything " 1549 printf(" %s\n",
1509 "else (HTTP headers) as they are"); 1550 "This overwrites the network address of the target while leaving everything else (HTTP headers) as they are");
1510 printf(" %s\n", "-p, --port=INTEGER"); 1551 printf(" %s\n", "-p, --port=INTEGER");
1511 printf(" %s", _("Port number (default: ")); 1552 printf(" %s", _("Port number (default: "));
1512 printf("%d)\n", HTTP_PORT); 1553 printf("%d)\n", HTTP_PORT);
@@ -1570,8 +1611,7 @@ void print_help(void) {
1570 printf(" %s\n", _("String to expect in the content")); 1611 printf(" %s\n", _("String to expect in the content"));
1571 printf(" %s\n", "-u, --url=PATH"); 1612 printf(" %s\n", "-u, --url=PATH");
1572 printf(" %s\n", _("URL to GET or POST (default: /)")); 1613 printf(" %s\n", _("URL to GET or POST (default: /)"));
1573 printf(" %s\n", _("This is the part after the address in a URL, so for " 1614 printf(" %s\n", _("This is the part after the address in a URL, so for \"https://example.com/index.html\" it would be '-u /index.html'"));
1574 "\"https://example.com/index.html\" it would be '-u /index.html'"));
1575 printf(" %s\n", "-P, --post=STRING"); 1615 printf(" %s\n", "-P, --post=STRING");
1576 printf(" %s\n", _("URL decoded http POST data")); 1616 printf(" %s\n", _("URL decoded http POST data"));
1577 printf(" %s\n", 1617 printf(" %s\n",
@@ -1597,6 +1637,18 @@ void print_help(void) {
1597 printf(" %s\n", "--state-regex=STATE"); 1637 printf(" %s\n", "--state-regex=STATE");
1598 printf(" %s\n", _("Return STATE if regex is found, OK if not. STATE can be one of " 1638 printf(" %s\n", _("Return STATE if regex is found, OK if not. STATE can be one of "
1599 "\"critical\",\"warning\"")); 1639 "\"critical\",\"warning\""));
1640 printf(" %s\n", "-x, --proxy=PROXY_SERVER");
1641 printf(" %s\n", _("Specify the proxy in form of <scheme>://<host(name)>:<port>"));
1642 printf(" %s\n", _("Available schemes are http, https, socks4, socks4a, socks5, socks5h"));
1643 printf(" %s\n", _("If port is not specified, libcurl defaults to 1080"));
1644 printf(" %s\n", _("This value will be set as CURLOPT_PROXY"));
1645 printf(" %s\n", "--noproxy=COMMA_SEPARATED_LIST");
1646 printf(" %s\n", _("Specify hostnames, addresses and subnets where proxy should not be used"));
1647 printf(" %s\n", _("Example usage: \"example.com,::1,1.1.1.1,localhost,192.168.0.0/16\""));
1648 printf(" %s\n", _("Do not use brackets when specifying IPv6 addresses"));
1649 printf(" %s\n", _("Special case when an item is '*' : matches all hosts/addresses "
1650 "and effectively disables proxy."));
1651 printf(" %s\n", _("This value will be set as CURLOPT_NOPROXY"));
1600 printf(" %s\n", "-a, --authorization=AUTH_PAIR"); 1652 printf(" %s\n", "-a, --authorization=AUTH_PAIR");
1601 printf(" %s\n", _("Username:password on sites with basic authentication")); 1653 printf(" %s\n", _("Username:password on sites with basic authentication"));
1602 printf(" %s\n", "-b, --proxy-authorization=AUTH_PAIR"); 1654 printf(" %s\n", "-b, --proxy-authorization=AUTH_PAIR");
@@ -1705,10 +1757,39 @@ void print_help(void) {
1705#endif 1757#endif
1706 1758
1707 printf("\n %s\n", "CHECK WEBSERVER CONTENT VIA PROXY:"); 1759 printf("\n %s\n", "CHECK WEBSERVER CONTENT VIA PROXY:");
1708 printf(" %s\n", _("It is recommended to use an environment proxy like:")); 1760 printf(" %s\n", _("Proxies are specified or disabled for certain hosts/addresses using environment variables"
1709 printf(" %s\n", 1761 " or -x/--proxy and --noproxy arguments:"));
1710 _("http_proxy=http://192.168.100.35:3128 ./check_curl -H www.monitoring-plugins.org")); 1762 printf(" %s\n", _("Checked environment variables: all_proxy, http_proxy, https_proxy, no_proxy"));
1711 printf(" %s\n", _("legacy proxy requests in check_http style still work:")); 1763 printf(" %s\n", _("Environment variables can also be given in uppercase, but the lowercase ones will "
1764 "take predence if both are defined."));
1765 printf(" %s\n", _("The environment variables are overwritten by -x/--proxy and --noproxy arguments:"));
1766 printf(" %s\n", _("all_proxy/ALL_PROXY environment variables are read first, but protocol "
1767 "specific environment variables override them."));
1768 printf(" %s\n", _("If SSL is enabled and used, https_proxy/HTTPS_PROXY will be checked and overwrite "
1769 "http_proxy/HTTPS_PROXY."));
1770 printf(" %s\n", _("Curl accepts proxies using http, https, socks4, socks4a, socks5 and socks5h schemes."));
1771 printf(" %s\n", _("http_proxy=http://192.168.100.35:3128 ./check_curl -H www.monitoring-plugins.org"));
1772 printf(" %s\n", _("http_proxy=http://used.proxy.com HTTP_PROXY=http://ignored.proxy.com ./check_curl -H www.monitoring-plugins.org"));
1773 printf(" %s\n", _(" Lowercase http_proxy takes predence over uppercase HTTP_PROXY"));
1774 printf(" %s\n", _("./check_curl -H www.monitoring-plugins.org -x http://192.168.100.35:3128"));
1775 printf(" %s\n", _("http_proxy=http://unused.proxy1.com HTTP_PROXY=http://unused.proxy2.com ./check_curl "
1776 "-H www.monitoring-plugins.org --proxy http://used.proxy"));
1777 printf(" %s\n", _(" Proxy specified by --proxy overrides any proxy specified by environment variable."));
1778 printf(" %s\n", _(" Curl uses port 1080 by default as port is not specified"));
1779 printf(" %s\n", _("HTTPS_PROXY=http://192.168.100.35:3128 ./check_curl -H www.monitoring-plugins.org --ssl"));
1780 printf(" %s\n", _(" HTTPS_PROXY is read as --ssl is toggled"));
1781 printf(" %s\n", _("./check_curl -H www.monitoring-plugins.org --proxy socks5h://192.168.122.21"));
1782 printf(" %s\n", _("./check_curl -H www.monitoring-plugins.org -x http://unused.proxy.com --noproxy '*'"));
1783 printf(" %s\n", _(" Disabled proxy for all hosts by using '*' in no_proxy ."));
1784 printf(" %s\n", _("NO_PROXY=www.monitoring-plugins.org ./check_curl -H www.monitoring-plugins.org -x http://unused.proxy.com"));
1785 printf(" %s\n", _(" Exact matches with the hostname/address work."));
1786 printf(" %s\n", _("no_proxy=192.168.178.0/24 ./check_curl -I 192.168.178.10 -x http://proxy.acme.org"));
1787 printf(" %s\n", _("no_proxy=acme.org ./check_curl -H nonpublic.internalwebapp.acme.org -x http://proxy.acme.org"));
1788 printf(" %s\n", _(" Do not use proxy when accessing internal domains/addresses, but use a default proxy when accessing public web."));
1789 printf(" %s\n", _(" IMPORTANT: Check_curl can not always determine whether itself or the proxy will "
1790 "resolve a hostname before sending a request and getting an answer."
1791 "This can lead to DNS resolvation issues if hostname is only resolvable over proxy."));
1792 printf(" %s\n", _("Legacy proxy requests in check_http style still work:"));
1712 printf(" %s\n", _("check_curl -I 192.168.100.35 -p 3128 -u http://www.monitoring-plugins.org/ " 1793 printf(" %s\n", _("check_curl -I 192.168.100.35 -p 3128 -u http://www.monitoring-plugins.org/ "
1713 "-H www.monitoring-plugins.org")); 1794 "-H www.monitoring-plugins.org"));
1714 1795
@@ -1739,13 +1820,15 @@ void print_usage(void) {
1739 printf(" %s -H <vhost> | -I <IP-address> [-u <uri>] [-p <port>]\n", progname); 1820 printf(" %s -H <vhost> | -I <IP-address> [-u <uri>] [-p <port>]\n", progname);
1740 printf(" [-J <client certificate file>] [-K <private key>] [--ca-cert <CA certificate " 1821 printf(" [-J <client certificate file>] [-K <private key>] [--ca-cert <CA certificate "
1741 "file>] [-D]\n"); 1822 "file>] [-D]\n");
1742 printf(" [-w <warn time>] [-c <critical time>] [-t <timeout>] [-L] [-E] [-a auth]\n"); 1823 printf(" [-w <warn time>] [-c <critical time>] [-t <timeout>] [-L] [-E] [-x <proxy>]\n");
1743 printf(" [-b proxy_auth] [-f <ok|warning|critical|follow|sticky|stickyport|curl>]\n"); 1824 printf(" [-a auth] [-b proxy_auth] [-f "
1825 "<ok|warning|critical|follow|sticky|stickyport|curl>]\n");
1744 printf(" [-e <expect>] [-d string] [-s string] [-l] [-r <regex> | -R <case-insensitive " 1826 printf(" [-e <expect>] [-d string] [-s string] [-l] [-r <regex> | -R <case-insensitive "
1745 "regex>]\n"); 1827 "regex>]\n");
1746 printf(" [-P string] [-m <min_pg_size>:<max_pg_size>] [-4|-6] [-N] [-M <age>]\n"); 1828 printf(" [-P string] [-m <min_pg_size>:<max_pg_size>] [-4|-6] [-N] [-M <age>]\n");
1747 printf(" [-A string] [-k string] [-S <version>] [--sni] [--haproxy-protocol]\n"); 1829 printf(" [-A string] [-k string] [-S <version>] [--sni] [--haproxy-protocol]\n");
1748 printf(" [-T <content-type>] [-j method]\n"); 1830 printf(" [-T <content-type>] [-j method]\n");
1831 printf(" [--noproxy=<comma separated list of hosts, IP addresses, IP CIDR subnets>\n");
1749 printf(" [--http-version=<version>] [--enable-automatic-decompression]\n"); 1832 printf(" [--http-version=<version>] [--enable-automatic-decompression]\n");
1750 printf(" [--cookie-jar=<cookie jar file>\n"); 1833 printf(" [--cookie-jar=<cookie jar file>\n");
1751 printf(" %s -H <vhost> | -I <IP-address> -C <warn_age>[,<crit_age>]\n", progname); 1834 printf(" %s -H <vhost> | -I <IP-address> -C <warn_age>[,<crit_age>]\n", progname);
diff --git a/plugins/check_curl.d/check_curl_helpers.c b/plugins/check_curl.d/check_curl_helpers.c
index 5af00973..4372dc0b 100644
--- a/plugins/check_curl.d/check_curl_helpers.c
+++ b/plugins/check_curl.d/check_curl_helpers.c
@@ -3,8 +3,11 @@
3#include <arpa/inet.h> 3#include <arpa/inet.h>
4#include <netinet/in.h> 4#include <netinet/in.h>
5#include <netdb.h> 5#include <netdb.h>
6#include <stdint.h>
7#include <stdio.h>
6#include <stdlib.h> 8#include <stdlib.h>
7#include <string.h> 9#include <string.h>
10#include <sys/socket.h>
8#include "../utils.h" 11#include "../utils.h"
9#include "check_curl.d/config.h" 12#include "check_curl.d/config.h"
10#include "output.h" 13#include "output.h"
@@ -116,6 +119,107 @@ check_curl_configure_curl(const check_curl_static_curl_config config,
116 curl_easy_setopt(result.curl_state.curl, CURLOPT_TIMEOUT, config.socket_timeout), 119 curl_easy_setopt(result.curl_state.curl, CURLOPT_TIMEOUT, config.socket_timeout),
117 "CURLOPT_TIMEOUT"); 120 "CURLOPT_TIMEOUT");
118 121
122 /* set proxy */
123 /* http(s) proxy can either be given from the command line, or taken from environment variables */
124 /* socks4(a) / socks5(h) proxy should be given using the command line */
125
126 /* first source to check is the environment variables */
127 /* lower case proxy environment variables are almost always accepted, while some programs also checking
128 uppercase ones. discover both, but take the lowercase one if both are present */
129
130 /* extra information: libcurl does not discover the uppercase version HTTP_PROXY due to security reasons */
131 /* https://github.com/curl/curl/blob/d445f2d930ae701039518d695481ee53b8490521/lib/url.c#L1987 */
132
133 /* first environment variable to read is all_proxy. it can be overridden by protocol specific environment variables */
134 char *all_proxy_env, *all_proxy_uppercase_env;
135 all_proxy_env = getenv("all_proxy");
136 all_proxy_uppercase_env = getenv("ALL_PROXY");
137 if (all_proxy_env != NULL && strlen(all_proxy_env)){
138 working_state.curlopt_proxy = strdup(all_proxy_env);
139 if (all_proxy_uppercase_env != NULL && verbose >= 1) {
140 printf("* cURL ignoring environment variable 'ALL_PROXY' as 'all_proxy' is set\n");
141 }
142 } else if (all_proxy_uppercase_env != NULL && strlen(all_proxy_uppercase_env) > 0) {
143 working_state.curlopt_proxy = strdup(all_proxy_uppercase_env);
144 }
145
146 /* second environment variable to read is http_proxy. only set curlopt_proxy if ssl is not toggled */
147 char *http_proxy_env, *http_proxy_uppercase_env;
148 http_proxy_env = getenv("http_proxy");
149 http_proxy_uppercase_env = getenv("HTTP_PROXY");
150 if (!working_state.use_ssl){
151 if (http_proxy_env != NULL && strlen(http_proxy_env) > 0) {
152 working_state.curlopt_proxy = strdup(http_proxy_env);
153 if (http_proxy_uppercase_env != NULL && verbose >= 1) {
154 printf("* cURL ignoring environment variable 'HTTP_PROXY' as 'http_proxy' is set\n");
155 }
156 } else if (http_proxy_uppercase_env != NULL && strlen(http_proxy_uppercase_env) > 0) {
157 working_state.curlopt_proxy = strdup(http_proxy_uppercase_env);
158 }
159 }
160#ifdef LIBCURL_FEATURE_SSL
161 /* optionally read https_proxy environment variable and set curlopt_proxy if ssl is toggled */
162 char *https_proxy_env, *https_proxy_uppercase_env;
163 https_proxy_env = getenv("https_proxy");
164 https_proxy_uppercase_env = getenv("HTTPS_PROXY");
165 if (working_state.use_ssl) {
166 if (https_proxy_env != NULL && strlen(https_proxy_env) > 0) {
167 working_state.curlopt_proxy = strdup(https_proxy_env);
168 if (https_proxy_uppercase_env != NULL && verbose >= 1) {
169 printf("* cURL ignoring environment variable 'HTTPS_PROXY' as 'https_proxy' is set\n");
170 }
171 }
172 else if (https_proxy_uppercase_env != NULL && strlen(https_proxy_uppercase_env) >= 0) {
173 working_state.curlopt_proxy = strdup(https_proxy_uppercase_env);
174 }
175 }
176#endif /* LIBCURL_FEATURE_SSL */
177
178 /* second source to check for proxies is command line argument, overwriting the environment variables */
179 if (strlen(config.proxy) > 0) {
180 working_state.curlopt_proxy = strdup(config.proxy);
181 }
182
183 if (working_state.curlopt_proxy != NULL && strlen(working_state.curlopt_proxy)){
184 handle_curl_option_return_code(
185 curl_easy_setopt(result.curl_state.curl, CURLOPT_PROXY, working_state.curlopt_proxy), "CURLOPT_PROXY");
186 if (verbose >= 1) {
187 printf("* curl CURLOPT_PROXY: %s\n", working_state.curlopt_proxy);
188 }
189 }
190
191 /* set no_proxy */
192 /* first source to check is environment variables */
193 char *no_proxy_env, *no_proxy_uppercase_env;
194 no_proxy_env = getenv("no_proxy");
195 no_proxy_uppercase_env = getenv("NO_PROXY");
196 if (no_proxy_env != NULL && strlen(no_proxy_env)){
197 working_state.curlopt_noproxy = strdup(no_proxy_env);
198 if (no_proxy_uppercase_env != NULL && verbose >= 1){
199 printf("* cURL ignoring environment variable 'NO_PROXY' as 'no_proxy' is set\n");
200 }
201 }else if (no_proxy_uppercase_env != NULL && strlen(no_proxy_uppercase_env) > 0){
202 working_state.curlopt_noproxy = strdup(no_proxy_uppercase_env);
203 }
204
205 /* second source to check for no_proxy is command line argument, overwriting the environment variables */
206 if (strlen(config.no_proxy) > 0) {
207 working_state.curlopt_noproxy = strdup(config.no_proxy);
208 }
209
210 if ( working_state.curlopt_noproxy != NULL && strlen(working_state.curlopt_noproxy)){
211 handle_curl_option_return_code(
212 curl_easy_setopt(result.curl_state.curl, CURLOPT_NOPROXY, working_state.curlopt_noproxy), "CURLOPT_NOPROXY");
213 if (verbose >= 1) {
214 printf("* curl CURLOPT_NOPROXY: %s\n", working_state.curlopt_noproxy);
215 }
216 }
217
218 int proxy_resolves_hostname = determine_hostname_resolver(working_state, config);
219 if (verbose >= 1) {
220 printf("* proxy_resolves_hostname: %d\n", proxy_resolves_hostname);
221 }
222
119 /* enable haproxy protocol */ 223 /* enable haproxy protocol */
120 if (config.haproxy_protocol) { 224 if (config.haproxy_protocol) {
121 handle_curl_option_return_code( 225 handle_curl_option_return_code(
@@ -123,11 +227,11 @@ check_curl_configure_curl(const check_curl_static_curl_config config,
123 "CURLOPT_HAPROXYPROTOCOL"); 227 "CURLOPT_HAPROXYPROTOCOL");
124 } 228 }
125 229
126 // fill dns resolve cache to make curl connect to the given server_address instead of the 230 /* fill dns resolve cache to make curl connect to the given server_address instead of the */
127 // host_name, only required for ssl, because we use the host_name later on to make SNI happy 231 /* host_name, only required for ssl, because we use the host_name later on to make SNI happy */
128 char dnscache[DEFAULT_BUFFER_SIZE]; 232 char dnscache[DEFAULT_BUFFER_SIZE];
129 char addrstr[DEFAULT_BUFFER_SIZE / 2]; 233 char addrstr[DEFAULT_BUFFER_SIZE / 2];
130 if (working_state.use_ssl && working_state.host_name != NULL) { 234 if (working_state.use_ssl && working_state.host_name != NULL && !proxy_resolves_hostname ) {
131 char *tmp_mod_address; 235 char *tmp_mod_address;
132 236
133 /* lookup_host() requires an IPv6 address without the brackets. */ 237 /* lookup_host() requires an IPv6 address without the brackets. */
@@ -488,7 +592,7 @@ check_curl_configure_curl(const check_curl_static_curl_config config,
488 curl_easy_setopt(result.curl_state.curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4), 592 curl_easy_setopt(result.curl_state.curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4),
489 "CURLOPT_IPRESOLVE(CURL_IPRESOLVE_V4)"); 593 "CURLOPT_IPRESOLVE(CURL_IPRESOLVE_V4)");
490 } 594 }
491#if defined(USE_IPV6) && defined(LIBCURL_FEATURE_IPV6) 595#if defined(LIBCURL_FEATURE_IPV6)
492 else if (config.sin_family == AF_INET6) { 596 else if (config.sin_family == AF_INET6) {
493 handle_curl_option_return_code( 597 handle_curl_option_return_code(
494 curl_easy_setopt(result.curl_state.curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V6), 598 curl_easy_setopt(result.curl_state.curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V6),
@@ -562,7 +666,7 @@ check_curl_configure_curl(const check_curl_static_curl_config config,
562 666
563void handle_curl_option_return_code(CURLcode res, const char *option) { 667void handle_curl_option_return_code(CURLcode res, const char *option) {
564 if (res != CURLE_OK) { 668 if (res != CURLE_OK) {
565 die(STATE_CRITICAL, _("Error while setting cURL option '%s': cURL returned %d - %s"), 669 die(STATE_CRITICAL, _("Error while setting cURL option '%s': cURL returned %d - %s\n"),
566 option, res, curl_easy_strerror(res)); 670 option, res, curl_easy_strerror(res));
567 } 671 }
568} 672}
@@ -589,6 +693,8 @@ check_curl_working_state check_curl_working_state_init() {
589 .serverPort = HTTP_PORT, 693 .serverPort = HTTP_PORT,
590 .use_ssl = false, 694 .use_ssl = false,
591 .no_body = false, 695 .no_body = false,
696 .curlopt_proxy = NULL,
697 .curlopt_noproxy = NULL,
592 }; 698 };
593 return result; 699 return result;
594} 700}
@@ -612,6 +718,8 @@ check_curl_config check_curl_config_init() {
612 .ca_cert = NULL, 718 .ca_cert = NULL,
613 .verify_peer_and_host = false, 719 .verify_peer_and_host = false,
614 .user_agent = {'\0'}, 720 .user_agent = {'\0'},
721 .proxy = "",
722 .no_proxy = "",
615 .proxy_auth = "", 723 .proxy_auth = "",
616 .user_auth = "", 724 .user_auth = "",
617 .http_content_type = NULL, 725 .http_content_type = NULL,
@@ -1295,3 +1403,342 @@ char *fmt_url(check_curl_working_state workingState) {
1295 1403
1296 return url; 1404 return url;
1297} 1405}
1406
1407int determine_hostname_resolver(const check_curl_working_state working_state, const check_curl_static_curl_config config){
1408 char *host_name_display = "NULL";
1409 unsigned long host_name_len = 0;
1410 if( working_state.host_name){
1411 host_name_len = strlen(working_state.host_name);
1412 host_name_display = working_state.host_name;
1413 }
1414
1415 /* IPv4 or IPv6 version of the address */
1416 char *server_address_clean = strdup(working_state.server_address);
1417 /* server address might be a full length ipv6 address encapsulated in square brackets */
1418 if ((strnlen(working_state.server_address, MAX_IPV4_HOSTLENGTH) > 2) && (working_state.server_address[0] == '[') && (working_state.server_address[strlen(working_state.server_address)-1] == ']') ) {
1419 server_address_clean = strndup( working_state.server_address + 1, strlen(working_state.server_address) - 2);
1420 }
1421
1422 /* check curlopt_noproxy option first */
1423 /* https://curl.se/libcurl/c/CURLOPT_NOPROXY.html */
1424
1425 /* curlopt_noproxy is specified as a comma separated list of
1426 direct IPv4 or IPv6 addresses e.g 130.133.8.40, 2001:4860:4802:32::a ,
1427 IPv4 or IPv6 CIDR regions e.g 10.241.0.0/16 , abcd:ef01:2345::/48 ,
1428 direct hostnames e.g example.com, google.de */
1429
1430 if (working_state.curlopt_noproxy != NULL){
1431 char* curlopt_noproxy_copy = strdup( working_state.curlopt_noproxy);
1432 char* noproxy_item = strtok(curlopt_noproxy_copy, ",");
1433 while(noproxy_item != NULL){
1434 unsigned long noproxy_item_len = strlen(noproxy_item);
1435
1436 /* According to the CURLOPT_NOPROXY documentation: */
1437 /* https://curl.se/libcurl/c/CURLOPT_NOPROXY.html */
1438 /* The only wildcard available is a single * character, which matches all hosts, and effectively disables the proxy. */
1439 if ( strlen(noproxy_item) == 1 && noproxy_item[0] == '*'){
1440 if (verbose >= 1){
1441 printf("* noproxy includes '*' which disables proxy for all host name incl. : %s / server address incl. : %s\n", host_name_display , server_address_clean);
1442 }
1443 free(curlopt_noproxy_copy);
1444 free(server_address_clean);
1445 return 0;
1446 }
1447
1448 /* direct comparison with the server_address */
1449 if( server_address_clean != NULL && strlen(server_address_clean) == strlen(noproxy_item) && strcmp(server_address_clean, noproxy_item) == 0){
1450 if (verbose >= 1){
1451 printf("* server_address is in the no_proxy list: %s\n", noproxy_item);
1452 }
1453 free(curlopt_noproxy_copy);
1454 free(server_address_clean);
1455 return 0;
1456 }
1457
1458 /* direct comparison with the host_name */
1459 if( working_state.host_name != NULL && host_name_len == noproxy_item_len && strcmp(working_state.host_name, noproxy_item) == 0){
1460 if (verbose >= 1){
1461 printf("* host_name is in the no_proxy list: %s\n", noproxy_item);
1462 }
1463 free(curlopt_noproxy_copy);
1464 free(server_address_clean);
1465 return 0;
1466 }
1467
1468 /* check if hostname is a subdomain of the item, e.g www.example.com when token is example.com */
1469 /* subdomain1.acme.com will not will use a proxy if you only specify 'acme' in the noproxy */
1470 /* check if noproxy_item is a suffix */
1471 /* check if the character just before the suffix is '.' */
1472 if( working_state.host_name != NULL && host_name_len > noproxy_item_len){
1473 unsigned long suffix_start_idx = host_name_len - noproxy_item_len;
1474 if (strcmp(working_state.host_name + suffix_start_idx, noproxy_item ) == 0 && working_state.host_name[suffix_start_idx-1] == '.' ){
1475 if (verbose >= 1){
1476 printf("* host_name: %s is a subdomain of the no_proxy list item: %s\n", working_state.host_name , noproxy_item);
1477 }
1478 free(curlopt_noproxy_copy);
1479 free(server_address_clean);
1480 return 0;
1481 }
1482 }
1483
1484 // noproxy_item could be a CIDR IP range
1485 if( server_address_clean != NULL && strlen(server_address_clean)){
1486
1487 int ip_addr_inside_cidr_ret = ip_addr_inside_cidr(noproxy_item, server_address_clean);
1488
1489 switch(ip_addr_inside_cidr_ret){
1490 case 1:
1491 return 0;
1492 break;
1493 case 0:
1494 if(verbose >= 1){
1495 printf("server address: %s is not inside IP cidr: %s\n", server_address_clean, noproxy_item);
1496 }
1497 break;
1498 case -1:
1499 if(verbose >= 1){
1500 printf("could not fully determine if server address: %s is inside the IP cidr: %s\n", server_address_clean, noproxy_item);
1501 }
1502 break;
1503 }
1504 }
1505
1506 noproxy_item = strtok(NULL, ",");
1507 }
1508
1509 free(curlopt_noproxy_copy);
1510 }
1511
1512 if (working_state.curlopt_proxy != NULL){
1513 // Libcurl documentation
1514 // Setting the proxy string to "" (an empty string) explicitly disables the use of a proxy, even if there is an environment variable set for it.
1515 if ( strlen(working_state.curlopt_proxy) == 0){
1516 return 0;
1517 }
1518
1519 if ( strncmp( working_state.curlopt_proxy, "http://", 7) == 0){
1520 if (verbose >= 1){
1521 printf("* proxy scheme is http, proxy: %s resolves host: %s or server_address: %s\n", working_state.curlopt_proxy, host_name_display, server_address_clean);
1522 }
1523 free(server_address_clean);
1524 return 1;
1525 }
1526
1527 if ( strncmp( working_state.curlopt_proxy, "https://", 8) == 0){
1528 if (verbose >= 1){
1529 printf("* proxy scheme is https, proxy: %s resolves host: %s or server_address: %s\n", working_state.curlopt_proxy, host_name_display, server_address_clean);
1530 }
1531 free(server_address_clean);
1532 return 1;
1533 }
1534
1535 if ( strncmp( working_state.curlopt_proxy, "socks4://", 9) == 0){
1536 if (verbose >= 1){
1537 printf("* proxy scheme is socks, proxy: %s does not resolve host: %s or server_address: %s\n", working_state.curlopt_proxy, host_name_display, server_address_clean);
1538 }
1539 free(server_address_clean);
1540 return 0;
1541 }
1542
1543 if ( strncmp( working_state.curlopt_proxy, "socks4a://", 10) == 0){
1544 if (verbose >= 1){
1545 printf("* proxy scheme is socks4a, proxy: %s resolves host: %s or server_address: %s\n", working_state.curlopt_proxy, host_name_display, server_address_clean);
1546 }
1547 free(server_address_clean);
1548 return 1;
1549 }
1550
1551 if ( strncmp( working_state.curlopt_proxy, "socks5://", 9) == 0){
1552 if (verbose >= 1){
1553 printf("* proxy scheme is socks5, proxy: %s does not resolve host: %s or server_address: %s\n", working_state.curlopt_proxy, host_name_display, server_address_clean);
1554 }
1555 free(server_address_clean);
1556 return 0;
1557 }
1558
1559 if ( strncmp( working_state.curlopt_proxy, "socks5h://", 10) == 0){
1560 if (verbose >= 1){
1561 printf("* proxy scheme is socks5h, proxy: %s resolves host: %s or server_address: %s\n", working_state.curlopt_proxy, host_name_display, server_address_clean);
1562 }
1563 free(server_address_clean);
1564 return 1;
1565 }
1566
1567 // Libcurl documentation:
1568 // Without a scheme prefix, CURLOPT_PROXYTYPE can be used to specify which kind of proxy the string identifies.
1569 // We do not set this value
1570 // Without a scheme, it is treated as an http proxy
1571
1572 return 1;
1573 }
1574
1575 if (verbose >= 1){
1576 printf("* proxy scheme is unknown/unavailable, no proxy is assumed for host: %s or server_address: %s\n", host_name_display, server_address_clean);
1577 }
1578
1579 free(server_address_clean);
1580 return 0;
1581}
1582
1583int ip_addr_inside_cidr(const char* cidr_region_or_ip_addr, const char* target_ip){
1584 unsigned int slash_count = 0;
1585 unsigned int last_slash_idx = 0;
1586 for(size_t i = 0; i < strlen(cidr_region_or_ip_addr); i++){
1587 if(cidr_region_or_ip_addr[i] == '/'){
1588 slash_count++;
1589 last_slash_idx = (unsigned int)i;
1590 }
1591 }
1592
1593 char *cidr_ip_part = NULL;
1594 int prefix_length = 0;
1595
1596 if (slash_count == 0) {
1597 cidr_ip_part = strdup(cidr_region_or_ip_addr);
1598 if (!cidr_ip_part) return -1;
1599 } else if (slash_count == 1) {
1600 cidr_ip_part = strndup(cidr_region_or_ip_addr, last_slash_idx);
1601 if (!cidr_ip_part) return -1;
1602
1603 errno = 0;
1604 long long tmp = strtoll(cidr_region_or_ip_addr + last_slash_idx + 1, NULL, 10);
1605 if (errno == ERANGE) {
1606 if (verbose >= 1) {
1607 printf("cidr_region_or_ip: %s , could not parse subnet length\n", cidr_region_or_ip_addr);
1608 }
1609 free(cidr_ip_part);
1610 return -1;
1611 }
1612 prefix_length = (int)tmp;
1613 } else {
1614 printf("cidr_region_or_ip: %s , has %d number of '/' characters, is not a valid cidr_region or IP\n", cidr_region_or_ip_addr, slash_count);
1615 return -1;
1616 }
1617
1618 int cidr_addr_family, target_addr_family;
1619 if (strchr(cidr_ip_part, ':')){
1620 cidr_addr_family = AF_INET6;
1621 } else {
1622 cidr_addr_family = AF_INET;
1623 }
1624
1625 if (strchr(target_ip, ':')){
1626 target_addr_family = AF_INET6;
1627 } else {
1628 target_addr_family = AF_INET;
1629 }
1630
1631 if (cidr_addr_family != target_addr_family){
1632 if (verbose >= 1){
1633 printf("cidr address: %s and target ip address: %s have different address families\n", cidr_ip_part, target_ip);
1634 }
1635 free(cidr_ip_part);
1636 return 0;
1637 }
1638
1639 // If no prefix is given, treat the cidr as a single address (full-length prefix)
1640 if (slash_count == 0) {
1641 prefix_length = (cidr_addr_family == AF_INET) ? 32 : 128;
1642 }
1643
1644 int max_bits = (cidr_addr_family == AF_INET) ? 32u : 128u;
1645 if (prefix_length < 0 || prefix_length > max_bits) {
1646 if (verbose >= 1) {
1647 printf("cidr_region_or_ip: %s has invalid prefix length: %u\n", cidr_region_or_ip_addr, prefix_length);
1648 }
1649 free(cidr_ip_part);
1650 return -1;
1651 }
1652
1653 if (verbose >= 1){
1654 printf("cidr_region_or_ip: %s , has prefix length: %u\n", cidr_region_or_ip_addr, prefix_length);
1655 }
1656
1657 int inet_pton_rc;
1658 uint8_t *cidr_bytes = NULL;
1659 uint8_t *target_bytes = NULL;
1660 uint8_t cidr_buf[16];
1661 uint8_t target_buf[16];
1662 size_t total_bytes = 0;
1663
1664 if (cidr_addr_family == AF_INET) {
1665 struct in_addr cidr_ipv4;
1666 struct in_addr target_ipv4;
1667 inet_pton_rc = inet_pton(AF_INET, cidr_ip_part, &cidr_ipv4);
1668 if (inet_pton_rc != 1) {
1669 if (verbose >= 1) {
1670 printf("ip string: %s contains characters not valid for its address family: IPv4\n", cidr_ip_part);
1671 }
1672 free(cidr_ip_part);
1673 return -1;
1674 }
1675 inet_pton_rc = inet_pton(AF_INET, target_ip, &target_ipv4);
1676 if (inet_pton_rc != 1) {
1677 if (verbose >= 1) {
1678 printf("ip string: %s contains characters not valid for its address family: IPv4\n", target_ip);
1679 }
1680 free(cidr_ip_part);
1681 return -1;
1682 }
1683 // copy the addresses in network byte order to a buffer for comparison
1684 memcpy(cidr_buf, &cidr_ipv4.s_addr, 4);
1685 memcpy(target_buf, &target_ipv4.s_addr, 4);
1686 cidr_bytes = cidr_buf;
1687 target_bytes = target_buf;
1688 total_bytes = 4;
1689 } else {
1690 struct in6_addr cidr_ipv6;
1691 struct in6_addr target_ipv6;
1692 inet_pton_rc = inet_pton(AF_INET6, cidr_ip_part, &cidr_ipv6);
1693 if (inet_pton_rc != 1) {
1694 if (verbose >= 1) {
1695 printf("ip string: %s contains characters not valid for its address family: IPv6\n", cidr_ip_part);
1696 }
1697 free(cidr_ip_part);
1698 return -1;
1699 }
1700 inet_pton_rc = inet_pton(AF_INET6, target_ip, &target_ipv6);
1701 if (inet_pton_rc != 1) {
1702 if (verbose >= 1) {
1703 printf("ip string: %s contains characters not valid for its address family: IPv6\n", target_ip);
1704 }
1705 free(cidr_ip_part);
1706 return -1;
1707 }
1708 memcpy(cidr_buf, &cidr_ipv6, 16);
1709 memcpy(target_buf, &target_ipv6, 16);
1710 cidr_bytes = cidr_buf;
1711 target_bytes = target_buf;
1712 total_bytes = 16;
1713 }
1714
1715 int prefix_bytes = prefix_length / 8;
1716 int prefix_bits = prefix_length % 8;
1717
1718 if (prefix_bytes > 0) {
1719 if (memcmp(cidr_bytes, target_bytes, (size_t)prefix_bytes) != 0) {
1720 if (verbose >= 1) {
1721 printf("the first %d bytes of the cidr_region_or_ip: %s and target_ip: %s are different\n", prefix_bytes, cidr_ip_part, target_ip);
1722 }
1723 free(cidr_ip_part);
1724 return 0;
1725 }
1726 }
1727
1728 if (prefix_bits != 0) {
1729 uint8_t cidr_oct = cidr_bytes[prefix_bytes];
1730 uint8_t target_oct = target_bytes[prefix_bytes];
1731 // the mask has first prefix_bits bits 1, the rest as 0
1732 uint8_t mask = (uint8_t)(0xFFu << (8 - prefix_bits));
1733 if ((cidr_oct & mask) != (target_oct & mask)) {
1734 if (verbose >= 1) {
1735 printf("looking at the last %d bits of the prefix, cidr_region_or_ip(%s) byte is: %u and target_ip byte(%s) is: %u, applying bitmask: %02X returns different results\n", prefix_bits, cidr_ip_part, (unsigned)cidr_oct, target_ip, (unsigned)target_oct, mask);
1736 }
1737 free(cidr_ip_part);
1738 return 0;
1739 }
1740 }
1741
1742 free(cidr_ip_part);
1743 return 1;
1744}
diff --git a/plugins/check_curl.d/check_curl_helpers.h b/plugins/check_curl.d/check_curl_helpers.h
index e77b763b..cc47bf9d 100644
--- a/plugins/check_curl.d/check_curl_helpers.h
+++ b/plugins/check_curl.d/check_curl_helpers.h
@@ -126,3 +126,12 @@ void test_file(char *path);
126mp_subcheck check_curl_certificate_checks(CURL *curl, X509 *cert, int warn_days_till_exp, 126mp_subcheck check_curl_certificate_checks(CURL *curl, X509 *cert, int warn_days_till_exp,
127 int crit_days_till_exp); 127 int crit_days_till_exp);
128char *fmt_url(check_curl_working_state workingState); 128char *fmt_url(check_curl_working_state workingState);
129
130
131/* function that will determine if the host or the proxy resolves the target hostname
132returns 0 if requester resolves the hostname locally, 1 if proxy resolves the hostname */
133int determine_hostname_resolver(const check_curl_working_state working_state, const check_curl_static_curl_config config);
134
135/* Checks if an IP is inside given CIDR region. Using /protocol_size or not specifying the prefix length performs an equality check. Supports both IPv4 and IPv6
136returns 1 if the target_ip address is inside the given cidr_region_or_ip_addr, 0 if its out. return codes < 0 mean an error has occurred. */
137int ip_addr_inside_cidr(const char* cidr_region_or_ip_addr, const char* target_ip);
diff --git a/plugins/check_curl.d/config.h b/plugins/check_curl.d/config.h
index 61067d46..bcdf3010 100644
--- a/plugins/check_curl.d/config.h
+++ b/plugins/check_curl.d/config.h
@@ -48,6 +48,11 @@ typedef struct {
48 48
49 bool use_ssl; 49 bool use_ssl;
50 bool no_body; 50 bool no_body;
51
52 /* curl CURLOPT_PROXY option will be set to this value if not NULL */
53 char *curlopt_proxy;
54 /* curl CURLOPT_NOPROXY option will be set to this value if not NULL */
55 char *curlopt_noproxy;
51} check_curl_working_state; 56} check_curl_working_state;
52 57
53check_curl_working_state check_curl_working_state_init(); 58check_curl_working_state check_curl_working_state_init();
@@ -65,6 +70,8 @@ typedef struct {
65 char *client_privkey; 70 char *client_privkey;
66 char *ca_cert; 71 char *ca_cert;
67 bool verify_peer_and_host; 72 bool verify_peer_and_host;
73 char proxy[DEFAULT_BUFFER_SIZE];
74 char no_proxy[DEFAULT_BUFFER_SIZE];
68 char user_agent[DEFAULT_BUFFER_SIZE]; 75 char user_agent[DEFAULT_BUFFER_SIZE];
69 char proxy_auth[MAX_INPUT_BUFFER]; 76 char proxy_auth[MAX_INPUT_BUFFER];
70 char user_auth[MAX_INPUT_BUFFER]; 77 char user_auth[MAX_INPUT_BUFFER];
diff --git a/plugins/check_dbi.c b/plugins/check_dbi.c
index 81d92952..dd466d00 100644
--- a/plugins/check_dbi.c
+++ b/plugins/check_dbi.c
@@ -470,7 +470,7 @@ check_dbi_config_wrapper process_arguments(int argc, char **argv) {
470 470
471 case 'c': /* critical range */ { 471 case 'c': /* critical range */ {
472 mp_range_parsed tmp = mp_parse_range_string(optarg); 472 mp_range_parsed tmp = mp_parse_range_string(optarg);
473 if (tmp.error != MP_PARSING_SUCCES) { 473 if (tmp.error != MP_PARSING_SUCCESS) {
474 die(STATE_UNKNOWN, "failed to parse critical threshold"); 474 die(STATE_UNKNOWN, "failed to parse critical threshold");
475 } 475 }
476 result.config.thresholds = mp_thresholds_set_crit(result.config.thresholds, tmp.range); 476 result.config.thresholds = mp_thresholds_set_crit(result.config.thresholds, tmp.range);
@@ -478,7 +478,7 @@ check_dbi_config_wrapper process_arguments(int argc, char **argv) {
478 } break; 478 } break;
479 case 'w': /* warning range */ { 479 case 'w': /* warning range */ {
480 mp_range_parsed tmp = mp_parse_range_string(optarg); 480 mp_range_parsed tmp = mp_parse_range_string(optarg);
481 if (tmp.error != MP_PARSING_SUCCES) { 481 if (tmp.error != MP_PARSING_SUCCESS) {
482 die(STATE_UNKNOWN, "failed to parse warning threshold"); 482 die(STATE_UNKNOWN, "failed to parse warning threshold");
483 } 483 }
484 result.config.thresholds = mp_thresholds_set_warn(result.config.thresholds, tmp.range); 484 result.config.thresholds = mp_thresholds_set_warn(result.config.thresholds, tmp.range);
diff --git a/plugins/check_disk.c b/plugins/check_disk.c
index e1a2baff..0d941f25 100644
--- a/plugins/check_disk.c
+++ b/plugins/check_disk.c
@@ -838,7 +838,7 @@ check_disk_config_wrapper process_arguments(int argc, char **argv) {
838 } 838 }
839 char *range = argv[index++]; 839 char *range = argv[index++];
840 mp_range_parsed tmp = mp_parse_range_string(range); 840 mp_range_parsed tmp = mp_parse_range_string(range);
841 if (tmp.error != MP_PARSING_SUCCES) { 841 if (tmp.error != MP_PARSING_SUCCESS) {
842 die(STATE_UNKNOWN, "failed to parse warning threshold"); 842 die(STATE_UNKNOWN, "failed to parse warning threshold");
843 } 843 }
844 844
@@ -859,7 +859,7 @@ check_disk_config_wrapper process_arguments(int argc, char **argv) {
859 } 859 }
860 char *range = argv[index++]; 860 char *range = argv[index++];
861 mp_range_parsed tmp = mp_parse_range_string(range); 861 mp_range_parsed tmp = mp_parse_range_string(range);
862 if (tmp.error != MP_PARSING_SUCCES) { 862 if (tmp.error != MP_PARSING_SUCCESS) {
863 die(STATE_UNKNOWN, "failed to parse warning threshold"); 863 die(STATE_UNKNOWN, "failed to parse warning threshold");
864 } 864 }
865 865
diff --git a/plugins/check_http.c b/plugins/check_http.c
index d2f080c7..71f94b91 100644
--- a/plugins/check_http.c
+++ b/plugins/check_http.c
@@ -544,11 +544,7 @@ bool process_arguments(int argc, char **argv) {
544 address_family = AF_INET; 544 address_family = AF_INET;
545 break; 545 break;
546 case '6': 546 case '6':
547#ifdef USE_IPV6
548 address_family = AF_INET6; 547 address_family = AF_INET6;
549#else
550 usage4(_("IPv6 support not available"));
551#endif
552 break; 548 break;
553 case 'v': /* verbose */ 549 case 'v': /* verbose */
554 verbose = true; 550 verbose = true;
diff --git a/plugins/check_ldap.c b/plugins/check_ldap.c
index 1b2e2826..7f8282b4 100644
--- a/plugins/check_ldap.c
+++ b/plugins/check_ldap.c
@@ -400,7 +400,7 @@ check_ldap_config_wrapper process_arguments(int argc, char **argv) {
400 break; 400 break;
401 case 'w': { 401 case 'w': {
402 mp_range_parsed tmp = mp_parse_range_string(optarg); 402 mp_range_parsed tmp = mp_parse_range_string(optarg);
403 if (tmp.error != MP_PARSING_SUCCES) { 403 if (tmp.error != MP_PARSING_SUCCESS) {
404 die(STATE_UNKNOWN, "failed to parse warning connection time threshold"); 404 die(STATE_UNKNOWN, "failed to parse warning connection time threshold");
405 } 405 }
406 result.config.connection_time_threshold = 406 result.config.connection_time_threshold =
@@ -408,7 +408,7 @@ check_ldap_config_wrapper process_arguments(int argc, char **argv) {
408 } break; 408 } break;
409 case 'c': { 409 case 'c': {
410 mp_range_parsed tmp = mp_parse_range_string(optarg); 410 mp_range_parsed tmp = mp_parse_range_string(optarg);
411 if (tmp.error != MP_PARSING_SUCCES) { 411 if (tmp.error != MP_PARSING_SUCCESS) {
412 die(STATE_UNKNOWN, "failed to parse critical connection time threshold"); 412 die(STATE_UNKNOWN, "failed to parse critical connection time threshold");
413 } 413 }
414 result.config.connection_time_threshold = 414 result.config.connection_time_threshold =
@@ -416,7 +416,7 @@ check_ldap_config_wrapper process_arguments(int argc, char **argv) {
416 } break; 416 } break;
417 case 'W': { 417 case 'W': {
418 mp_range_parsed tmp = mp_parse_range_string(optarg); 418 mp_range_parsed tmp = mp_parse_range_string(optarg);
419 if (tmp.error != MP_PARSING_SUCCES) { 419 if (tmp.error != MP_PARSING_SUCCESS) {
420 die(STATE_UNKNOWN, "failed to parse number of entries warning threshold"); 420 die(STATE_UNKNOWN, "failed to parse number of entries warning threshold");
421 } 421 }
422 result.config.entries_thresholds = 422 result.config.entries_thresholds =
@@ -424,7 +424,7 @@ check_ldap_config_wrapper process_arguments(int argc, char **argv) {
424 } break; 424 } break;
425 case 'C': { 425 case 'C': {
426 mp_range_parsed tmp = mp_parse_range_string(optarg); 426 mp_range_parsed tmp = mp_parse_range_string(optarg);
427 if (tmp.error != MP_PARSING_SUCCES) { 427 if (tmp.error != MP_PARSING_SUCCESS) {
428 die(STATE_UNKNOWN, "failed to parse number of entries critical threshold"); 428 die(STATE_UNKNOWN, "failed to parse number of entries critical threshold");
429 } 429 }
430 result.config.entries_thresholds = 430 result.config.entries_thresholds =
@@ -462,11 +462,7 @@ check_ldap_config_wrapper process_arguments(int argc, char **argv) {
462 } 462 }
463 break; 463 break;
464 case '6': 464 case '6':
465#ifdef USE_IPV6
466 address_family = AF_INET6; 465 address_family = AF_INET6;
467#else
468 usage(_("IPv6 support not available\n"));
469#endif
470 break; 466 break;
471 case output_format_index: { 467 case output_format_index: {
472 parsed_output_format parser = mp_parse_output_format(optarg); 468 parsed_output_format parser = mp_parse_output_format(optarg);
diff --git a/plugins/check_mrtg.c b/plugins/check_mrtg.c
index cdc2a035..bb38fcc5 100644
--- a/plugins/check_mrtg.c
+++ b/plugins/check_mrtg.c
@@ -255,7 +255,7 @@ check_mrtg_config_wrapper process_arguments(int argc, char **argv) {
255 break; 255 break;
256 case 'w': /* critical time threshold */ { 256 case 'w': /* critical time threshold */ {
257 mp_range_parsed tmp = mp_parse_range_string(optarg); 257 mp_range_parsed tmp = mp_parse_range_string(optarg);
258 if (tmp.error != MP_PARSING_SUCCES) { 258 if (tmp.error != MP_PARSING_SUCCESS) {
259 die(STATE_UNKNOWN, "failed to parse warning threshold"); 259 die(STATE_UNKNOWN, "failed to parse warning threshold");
260 } 260 }
261 result.config.values_threshold = 261 result.config.values_threshold =
@@ -263,7 +263,7 @@ check_mrtg_config_wrapper process_arguments(int argc, char **argv) {
263 } break; 263 } break;
264 case 'c': /* warning time threshold */ { 264 case 'c': /* warning time threshold */ {
265 mp_range_parsed tmp = mp_parse_range_string(optarg); 265 mp_range_parsed tmp = mp_parse_range_string(optarg);
266 if (tmp.error != MP_PARSING_SUCCES) { 266 if (tmp.error != MP_PARSING_SUCCESS) {
267 die(STATE_UNKNOWN, "failed to parse critical threshold"); 267 die(STATE_UNKNOWN, "failed to parse critical threshold");
268 } 268 }
269 result.config.values_threshold = 269 result.config.values_threshold =
@@ -330,7 +330,7 @@ check_mrtg_config_wrapper process_arguments(int argc, char **argv) {
330 330
331 if (argc > option_char && !result.config.values_threshold.warning_is_set) { 331 if (argc > option_char && !result.config.values_threshold.warning_is_set) {
332 mp_range_parsed tmp = mp_parse_range_string(argv[option_char++]); 332 mp_range_parsed tmp = mp_parse_range_string(argv[option_char++]);
333 if (tmp.error != MP_PARSING_SUCCES) { 333 if (tmp.error != MP_PARSING_SUCCESS) {
334 die(STATE_UNKNOWN, "failed to parse warning threshold"); 334 die(STATE_UNKNOWN, "failed to parse warning threshold");
335 } 335 }
336 result.config.values_threshold = 336 result.config.values_threshold =
@@ -339,7 +339,7 @@ check_mrtg_config_wrapper process_arguments(int argc, char **argv) {
339 339
340 if (argc > option_char && !result.config.values_threshold.critical_is_set) { 340 if (argc > option_char && !result.config.values_threshold.critical_is_set) {
341 mp_range_parsed tmp = mp_parse_range_string(argv[option_char++]); 341 mp_range_parsed tmp = mp_parse_range_string(argv[option_char++]);
342 if (tmp.error != MP_PARSING_SUCCES) { 342 if (tmp.error != MP_PARSING_SUCCESS) {
343 die(STATE_UNKNOWN, "failed to parse critical threshold"); 343 die(STATE_UNKNOWN, "failed to parse critical threshold");
344 } 344 }
345 result.config.values_threshold = 345 result.config.values_threshold =
diff --git a/plugins/check_mysql.c b/plugins/check_mysql.c
index 26730d4c..15005bf5 100644
--- a/plugins/check_mysql.c
+++ b/plugins/check_mysql.c
@@ -572,7 +572,7 @@ check_mysql_config_wrapper process_arguments(int argc, char **argv) {
572 break; 572 break;
573 case 'w': { 573 case 'w': {
574 mp_range_parsed tmp = mp_parse_range_string(optarg); 574 mp_range_parsed tmp = mp_parse_range_string(optarg);
575 if (tmp.error != MP_PARSING_SUCCES) { 575 if (tmp.error != MP_PARSING_SUCCESS) {
576 die(STATE_UNKNOWN, "failed to parse warning time threshold"); 576 die(STATE_UNKNOWN, "failed to parse warning time threshold");
577 } 577 }
578 result.config.replica_thresholds = 578 result.config.replica_thresholds =
@@ -580,7 +580,7 @@ check_mysql_config_wrapper process_arguments(int argc, char **argv) {
580 } break; 580 } break;
581 case 'c': { 581 case 'c': {
582 mp_range_parsed tmp = mp_parse_range_string(optarg); 582 mp_range_parsed tmp = mp_parse_range_string(optarg);
583 if (tmp.error != MP_PARSING_SUCCES) { 583 if (tmp.error != MP_PARSING_SUCCESS) {
584 die(STATE_UNKNOWN, "failed to parse critical time threshold"); 584 die(STATE_UNKNOWN, "failed to parse critical time threshold");
585 } 585 }
586 result.config.replica_thresholds = 586 result.config.replica_thresholds =
diff --git a/plugins/check_mysql_query.c b/plugins/check_mysql_query.c
index ae6cc15d..fc0966d3 100644
--- a/plugins/check_mysql_query.c
+++ b/plugins/check_mysql_query.c
@@ -277,14 +277,14 @@ check_mysql_query_config_wrapper process_arguments(int argc, char **argv) {
277 break; 277 break;
278 case 'w': { 278 case 'w': {
279 mp_range_parsed tmp = mp_parse_range_string(optarg); 279 mp_range_parsed tmp = mp_parse_range_string(optarg);
280 if (tmp.error != MP_PARSING_SUCCES) { 280 if (tmp.error != MP_PARSING_SUCCESS) {
281 die(STATE_UNKNOWN, "failed to parse warning threshold"); 281 die(STATE_UNKNOWN, "failed to parse warning threshold");
282 } 282 }
283 result.config.thresholds = mp_thresholds_set_warn(result.config.thresholds, tmp.range); 283 result.config.thresholds = mp_thresholds_set_warn(result.config.thresholds, tmp.range);
284 } break; 284 } break;
285 case 'c': { 285 case 'c': {
286 mp_range_parsed tmp = mp_parse_range_string(optarg); 286 mp_range_parsed tmp = mp_parse_range_string(optarg);
287 if (tmp.error != MP_PARSING_SUCCES) { 287 if (tmp.error != MP_PARSING_SUCCESS) {
288 die(STATE_UNKNOWN, "failed to parse critical threshold"); 288 die(STATE_UNKNOWN, "failed to parse critical threshold");
289 } 289 }
290 result.config.thresholds = mp_thresholds_set_crit(result.config.thresholds, tmp.range); 290 result.config.thresholds = mp_thresholds_set_crit(result.config.thresholds, tmp.range);
diff --git a/plugins/check_ntp_peer.c b/plugins/check_ntp_peer.c
index 26f74286..b5cfb460 100644
--- a/plugins/check_ntp_peer.c
+++ b/plugins/check_ntp_peer.c
@@ -548,7 +548,7 @@ check_ntp_peer_config_wrapper process_arguments(int argc, char **argv) {
548 break; 548 break;
549 case 'w': { 549 case 'w': {
550 mp_range_parsed tmp = mp_parse_range_string(optarg); 550 mp_range_parsed tmp = mp_parse_range_string(optarg);
551 if (tmp.error != MP_PARSING_SUCCES) { 551 if (tmp.error != MP_PARSING_SUCCESS) {
552 die(STATE_UNKNOWN, "failed to parse warning offset threshold"); 552 die(STATE_UNKNOWN, "failed to parse warning offset threshold");
553 } 553 }
554 554
@@ -557,7 +557,7 @@ check_ntp_peer_config_wrapper process_arguments(int argc, char **argv) {
557 } break; 557 } break;
558 case 'c': { 558 case 'c': {
559 mp_range_parsed tmp = mp_parse_range_string(optarg); 559 mp_range_parsed tmp = mp_parse_range_string(optarg);
560 if (tmp.error != MP_PARSING_SUCCES) { 560 if (tmp.error != MP_PARSING_SUCCESS) {
561 die(STATE_UNKNOWN, "failed to parse critical offset threshold"); 561 die(STATE_UNKNOWN, "failed to parse critical offset threshold");
562 } 562 }
563 563
@@ -567,7 +567,7 @@ check_ntp_peer_config_wrapper process_arguments(int argc, char **argv) {
567 case 'W': { 567 case 'W': {
568 result.config.do_stratum = true; 568 result.config.do_stratum = true;
569 mp_range_parsed tmp = mp_parse_range_string(optarg); 569 mp_range_parsed tmp = mp_parse_range_string(optarg);
570 if (tmp.error != MP_PARSING_SUCCES) { 570 if (tmp.error != MP_PARSING_SUCCESS) {
571 die(STATE_UNKNOWN, "failed to parse warning stratum threshold"); 571 die(STATE_UNKNOWN, "failed to parse warning stratum threshold");
572 } 572 }
573 573
@@ -577,7 +577,7 @@ check_ntp_peer_config_wrapper process_arguments(int argc, char **argv) {
577 case 'C': { 577 case 'C': {
578 result.config.do_stratum = true; 578 result.config.do_stratum = true;
579 mp_range_parsed tmp = mp_parse_range_string(optarg); 579 mp_range_parsed tmp = mp_parse_range_string(optarg);
580 if (tmp.error != MP_PARSING_SUCCES) { 580 if (tmp.error != MP_PARSING_SUCCESS) {
581 die(STATE_UNKNOWN, "failed to parse critical stratum threshold"); 581 die(STATE_UNKNOWN, "failed to parse critical stratum threshold");
582 } 582 }
583 583
@@ -587,7 +587,7 @@ check_ntp_peer_config_wrapper process_arguments(int argc, char **argv) {
587 case 'j': { 587 case 'j': {
588 result.config.do_jitter = true; 588 result.config.do_jitter = true;
589 mp_range_parsed tmp = mp_parse_range_string(optarg); 589 mp_range_parsed tmp = mp_parse_range_string(optarg);
590 if (tmp.error != MP_PARSING_SUCCES) { 590 if (tmp.error != MP_PARSING_SUCCESS) {
591 die(STATE_UNKNOWN, "failed to parse warning jitter threshold"); 591 die(STATE_UNKNOWN, "failed to parse warning jitter threshold");
592 } 592 }
593 593
@@ -597,7 +597,7 @@ check_ntp_peer_config_wrapper process_arguments(int argc, char **argv) {
597 case 'k': { 597 case 'k': {
598 result.config.do_jitter = true; 598 result.config.do_jitter = true;
599 mp_range_parsed tmp = mp_parse_range_string(optarg); 599 mp_range_parsed tmp = mp_parse_range_string(optarg);
600 if (tmp.error != MP_PARSING_SUCCES) { 600 if (tmp.error != MP_PARSING_SUCCESS) {
601 die(STATE_UNKNOWN, "failed to parse critical jitter threshold"); 601 die(STATE_UNKNOWN, "failed to parse critical jitter threshold");
602 } 602 }
603 603
@@ -607,7 +607,7 @@ check_ntp_peer_config_wrapper process_arguments(int argc, char **argv) {
607 case 'm': { 607 case 'm': {
608 result.config.do_truechimers = true; 608 result.config.do_truechimers = true;
609 mp_range_parsed tmp = mp_parse_range_string(optarg); 609 mp_range_parsed tmp = mp_parse_range_string(optarg);
610 if (tmp.error != MP_PARSING_SUCCES) { 610 if (tmp.error != MP_PARSING_SUCCESS) {
611 die(STATE_UNKNOWN, "failed to parse warning truechimer threshold"); 611 die(STATE_UNKNOWN, "failed to parse warning truechimer threshold");
612 } 612 }
613 613
@@ -617,7 +617,7 @@ check_ntp_peer_config_wrapper process_arguments(int argc, char **argv) {
617 case 'n': { 617 case 'n': {
618 result.config.do_truechimers = true; 618 result.config.do_truechimers = true;
619 mp_range_parsed tmp = mp_parse_range_string(optarg); 619 mp_range_parsed tmp = mp_parse_range_string(optarg);
620 if (tmp.error != MP_PARSING_SUCCES) { 620 if (tmp.error != MP_PARSING_SUCCESS) {
621 die(STATE_UNKNOWN, "failed to parse critical truechimer threshold"); 621 die(STATE_UNKNOWN, "failed to parse critical truechimer threshold");
622 } 622 }
623 623
@@ -640,11 +640,7 @@ check_ntp_peer_config_wrapper process_arguments(int argc, char **argv) {
640 address_family = AF_INET; 640 address_family = AF_INET;
641 break; 641 break;
642 case '6': 642 case '6':
643#ifdef USE_IPV6
644 address_family = AF_INET6; 643 address_family = AF_INET6;
645#else
646 usage4(_("IPv6 support not available"));
647#endif
648 break; 644 break;
649 case '?': 645 case '?':
650 /* print short usage statement if args not parsable */ 646 /* print short usage statement if args not parsable */
diff --git a/plugins/check_ntp_time.c b/plugins/check_ntp_time.c
index 9e0beb9c..4e3a55db 100644
--- a/plugins/check_ntp_time.c
+++ b/plugins/check_ntp_time.c
@@ -605,7 +605,7 @@ static check_ntp_time_config_wrapper process_arguments(int argc, char **argv) {
605 break; 605 break;
606 case 'w': { 606 case 'w': {
607 mp_range_parsed tmp = mp_parse_range_string(optarg); 607 mp_range_parsed tmp = mp_parse_range_string(optarg);
608 if (tmp.error != MP_PARSING_SUCCES) { 608 if (tmp.error != MP_PARSING_SUCCESS) {
609 die(STATE_UNKNOWN, "failed to parse warning threshold"); 609 die(STATE_UNKNOWN, "failed to parse warning threshold");
610 } 610 }
611 611
@@ -614,7 +614,7 @@ static check_ntp_time_config_wrapper process_arguments(int argc, char **argv) {
614 } break; 614 } break;
615 case 'c': { 615 case 'c': {
616 mp_range_parsed tmp = mp_parse_range_string(optarg); 616 mp_range_parsed tmp = mp_parse_range_string(optarg);
617 if (tmp.error != MP_PARSING_SUCCES) { 617 if (tmp.error != MP_PARSING_SUCCESS) {
618 die(STATE_UNKNOWN, "failed to parse crit threshold"); 618 die(STATE_UNKNOWN, "failed to parse crit threshold");
619 } 619 }
620 620
@@ -640,11 +640,7 @@ static check_ntp_time_config_wrapper process_arguments(int argc, char **argv) {
640 address_family = AF_INET; 640 address_family = AF_INET;
641 break; 641 break;
642 case '6': 642 case '6':
643#ifdef USE_IPV6
644 address_family = AF_INET6; 643 address_family = AF_INET6;
645#else
646 usage4(_("IPv6 support not available"));
647#endif
648 break; 644 break;
649 case '?': 645 case '?':
650 /* print short usage statement if args not parsable */ 646 /* print short usage statement if args not parsable */
@@ -661,6 +657,14 @@ static check_ntp_time_config_wrapper process_arguments(int argc, char **argv) {
661} 657}
662 658
663int main(int argc, char *argv[]) { 659int main(int argc, char *argv[]) {
660#ifdef __OpenBSD__
661 /* - rpath is required to read --extra-opts (given up later)
662 * - inet is required for sockets
663 * - unix is required for Unix domain sockets
664 * - dns is required for name lookups */
665 pledge("stdio rpath inet unix dns", NULL);
666#endif // __OpenBSD__
667
664 setlocale(LC_ALL, ""); 668 setlocale(LC_ALL, "");
665 bindtextdomain(PACKAGE, LOCALEDIR); 669 bindtextdomain(PACKAGE, LOCALEDIR);
666 textdomain(PACKAGE); 670 textdomain(PACKAGE);
@@ -674,6 +678,10 @@ int main(int argc, char *argv[]) {
674 usage4(_("Could not parse arguments")); 678 usage4(_("Could not parse arguments"));
675 } 679 }
676 680
681#ifdef __OpenBSD__
682 pledge("stdio inet unix dns", NULL);
683#endif // __OpenBSD__
684
677 const check_ntp_time_config config = tmp_config.config; 685 const check_ntp_time_config config = tmp_config.config;
678 686
679 if (config.output_format_is_set) { 687 if (config.output_format_is_set) {
diff --git a/plugins/check_pgsql.c b/plugins/check_pgsql.c
index 0ce75e0a..8cbaaeeb 100644
--- a/plugins/check_pgsql.c
+++ b/plugins/check_pgsql.c
@@ -401,7 +401,7 @@ static check_pgsql_config_wrapper process_arguments(int argc, char **argv) {
401 break; 401 break;
402 case 'c': /* critical time threshold */ { 402 case 'c': /* critical time threshold */ {
403 mp_range_parsed tmp = mp_parse_range_string(optarg); 403 mp_range_parsed tmp = mp_parse_range_string(optarg);
404 if (tmp.error != MP_PARSING_SUCCES) { 404 if (tmp.error != MP_PARSING_SUCCESS) {
405 die(STATE_UNKNOWN, "failed to parse critical time threshold"); 405 die(STATE_UNKNOWN, "failed to parse critical time threshold");
406 } 406 }
407 result.config.time_thresholds = 407 result.config.time_thresholds =
@@ -409,7 +409,7 @@ static check_pgsql_config_wrapper process_arguments(int argc, char **argv) {
409 } break; 409 } break;
410 case 'w': /* warning time threshold */ { 410 case 'w': /* warning time threshold */ {
411 mp_range_parsed tmp = mp_parse_range_string(optarg); 411 mp_range_parsed tmp = mp_parse_range_string(optarg);
412 if (tmp.error != MP_PARSING_SUCCES) { 412 if (tmp.error != MP_PARSING_SUCCESS) {
413 die(STATE_UNKNOWN, "failed to parse warning time threshold"); 413 die(STATE_UNKNOWN, "failed to parse warning time threshold");
414 } 414 }
415 result.config.time_thresholds = 415 result.config.time_thresholds =
@@ -417,7 +417,7 @@ static check_pgsql_config_wrapper process_arguments(int argc, char **argv) {
417 } break; 417 } break;
418 case 'C': /* critical query threshold */ { 418 case 'C': /* critical query threshold */ {
419 mp_range_parsed tmp = mp_parse_range_string(optarg); 419 mp_range_parsed tmp = mp_parse_range_string(optarg);
420 if (tmp.error != MP_PARSING_SUCCES) { 420 if (tmp.error != MP_PARSING_SUCCESS) {
421 die(STATE_UNKNOWN, "failed to parse critical query threshold"); 421 die(STATE_UNKNOWN, "failed to parse critical query threshold");
422 } 422 }
423 423
@@ -427,7 +427,7 @@ static check_pgsql_config_wrapper process_arguments(int argc, char **argv) {
427 } break; 427 } break;
428 case 'W': /* warning query threshold */ { 428 case 'W': /* warning query threshold */ {
429 mp_range_parsed tmp = mp_parse_range_string(optarg); 429 mp_range_parsed tmp = mp_parse_range_string(optarg);
430 if (tmp.error != MP_PARSING_SUCCES) { 430 if (tmp.error != MP_PARSING_SUCCESS) {
431 die(STATE_UNKNOWN, "failed to parse warning query threshold"); 431 die(STATE_UNKNOWN, "failed to parse warning query threshold");
432 } 432 }
433 result.config.qthresholds = 433 result.config.qthresholds =
diff --git a/plugins/check_ping.c b/plugins/check_ping.c
index 61feb958..e1ee0f5c 100644
--- a/plugins/check_ping.c
+++ b/plugins/check_ping.c
@@ -246,11 +246,7 @@ check_ping_config_wrapper process_arguments(int argc, char **argv) {
246 address_family = AF_INET; 246 address_family = AF_INET;
247 break; 247 break;
248 case '6': /* IPv6 only */ 248 case '6': /* IPv6 only */
249#ifdef USE_IPV6
250 address_family = AF_INET6; 249 address_family = AF_INET6;
251#else
252 usage(_("IPv6 support not available\n"));
253#endif
254 break; 250 break;
255 case 'H': /* hostname */ { 251 case 'H': /* hostname */ {
256 char *ptr = optarg; 252 char *ptr = optarg;
diff --git a/plugins/check_procs.c b/plugins/check_procs.c
index ae6e9c23..50837cb4 100644
--- a/plugins/check_procs.c
+++ b/plugins/check_procs.c
@@ -430,7 +430,7 @@ check_procs_config_wrapper process_arguments(int argc, char **argv) {
430 while (true) { 430 while (true) {
431 int option = 0; 431 int option = 0;
432 int option_index = 432 int option_index =
433 getopt_long(argc, argv, "Vvhkt:c:w:p:s:u:C:a:z:r:m:P:T:X:", longopts, &option); 433 getopt_long(argc, argv, "Vvhkt:c:w:p:s:u:C:a:z:r:m:P:TX:", longopts, &option);
434 434
435 if (option_index == -1 || option_index == EOF) { 435 if (option_index == -1 || option_index == EOF) {
436 break; 436 break;
diff --git a/plugins/check_real.c b/plugins/check_real.c
index 15c8a20c..b415578f 100644
--- a/plugins/check_real.c
+++ b/plugins/check_real.c
@@ -409,7 +409,7 @@ check_real_config_wrapper process_arguments(int argc, char **argv) {
409 case 'w': /* warning time threshold */ 409 case 'w': /* warning time threshold */
410 { 410 {
411 mp_range_parsed critical_range = mp_parse_range_string(optarg); 411 mp_range_parsed critical_range = mp_parse_range_string(optarg);
412 if (critical_range.error != MP_PARSING_SUCCES) { 412 if (critical_range.error != MP_PARSING_SUCCESS) {
413 die(STATE_UNKNOWN, "failed to parse warning threshold: %s", optarg); 413 die(STATE_UNKNOWN, "failed to parse warning threshold: %s", optarg);
414 } 414 }
415 result.config.time_thresholds = 415 result.config.time_thresholds =
@@ -418,7 +418,7 @@ check_real_config_wrapper process_arguments(int argc, char **argv) {
418 case 'c': /* critical time threshold */ 418 case 'c': /* critical time threshold */
419 { 419 {
420 mp_range_parsed critical_range = mp_parse_range_string(optarg); 420 mp_range_parsed critical_range = mp_parse_range_string(optarg);
421 if (critical_range.error != MP_PARSING_SUCCES) { 421 if (critical_range.error != MP_PARSING_SUCCESS) {
422 die(STATE_UNKNOWN, "failed to parse critical threshold: %s", optarg); 422 die(STATE_UNKNOWN, "failed to parse critical threshold: %s", optarg);
423 } 423 }
424 result.config.time_thresholds = 424 result.config.time_thresholds =
diff --git a/plugins/check_smtp.c b/plugins/check_smtp.c
index e8c35f58..24883fd8 100644
--- a/plugins/check_smtp.c
+++ b/plugins/check_smtp.c
@@ -100,6 +100,14 @@ static int my_close(int /*socket_descriptor*/);
100static int verbose = 0; 100static int verbose = 0;
101 101
102int main(int argc, char **argv) { 102int main(int argc, char **argv) {
103#ifdef __OpenBSD__
104 /* - rpath is required to read --extra-opts (given up later)
105 * - inet is required for sockets
106 * - unix is required for Unix domain sockets
107 * - dns is required for name lookups */
108 pledge("stdio rpath inet unix dns", NULL);
109#endif // __OpenBSD__
110
103 setlocale(LC_ALL, ""); 111 setlocale(LC_ALL, "");
104 bindtextdomain(PACKAGE, LOCALEDIR); 112 bindtextdomain(PACKAGE, LOCALEDIR);
105 textdomain(PACKAGE); 113 textdomain(PACKAGE);
@@ -113,6 +121,10 @@ int main(int argc, char **argv) {
113 usage4(_("Could not parse arguments")); 121 usage4(_("Could not parse arguments"));
114 } 122 }
115 123
124#ifdef __OpenBSD__
125 pledge("stdio inet unix dns", NULL);
126#endif // __OpenBSD__
127
116 const check_smtp_config config = tmp_config.config; 128 const check_smtp_config config = tmp_config.config;
117 129
118 if (config.output_format_is_set) { 130 if (config.output_format_is_set) {
@@ -723,7 +735,7 @@ check_smtp_config_wrapper process_arguments(int argc, char **argv) {
723 break; 735 break;
724 case 'c': /* critical time threshold */ { 736 case 'c': /* critical time threshold */ {
725 mp_range_parsed tmp = mp_parse_range_string(optarg); 737 mp_range_parsed tmp = mp_parse_range_string(optarg);
726 if (tmp.error != MP_PARSING_SUCCES) { 738 if (tmp.error != MP_PARSING_SUCCESS) {
727 die(STATE_UNKNOWN, "failed to parse critical time threshold"); 739 die(STATE_UNKNOWN, "failed to parse critical time threshold");
728 } 740 }
729 result.config.connection_time = 741 result.config.connection_time =
@@ -731,7 +743,7 @@ check_smtp_config_wrapper process_arguments(int argc, char **argv) {
731 } break; 743 } break;
732 case 'w': /* warning time threshold */ { 744 case 'w': /* warning time threshold */ {
733 mp_range_parsed tmp = mp_parse_range_string(optarg); 745 mp_range_parsed tmp = mp_parse_range_string(optarg);
734 if (tmp.error != MP_PARSING_SUCCES) { 746 if (tmp.error != MP_PARSING_SUCCESS) {
735 die(STATE_UNKNOWN, "failed to parse warning time threshold"); 747 die(STATE_UNKNOWN, "failed to parse warning time threshold");
736 } 748 }
737 result.config.connection_time = 749 result.config.connection_time =
@@ -807,11 +819,7 @@ check_smtp_config_wrapper process_arguments(int argc, char **argv) {
807 address_family = AF_INET; 819 address_family = AF_INET;
808 break; 820 break;
809 case '6': 821 case '6':
810#ifdef USE_IPV6
811 address_family = AF_INET6; 822 address_family = AF_INET6;
812#else
813 usage4(_("IPv6 support not available"));
814#endif
815 break; 823 break;
816 case 'V': /* version */ 824 case 'V': /* version */
817 print_revision(progname, NP_VERSION); 825 print_revision(progname, NP_VERSION);
diff --git a/plugins/check_snmp.d/check_snmp_helpers.c b/plugins/check_snmp.d/check_snmp_helpers.c
index 2dfc88b5..83e94a34 100644
--- a/plugins/check_snmp.d/check_snmp_helpers.c
+++ b/plugins/check_snmp.d/check_snmp_helpers.c
@@ -52,7 +52,7 @@ int check_snmp_set_thresholds(const char *threshold_string, check_snmp_test_unit
52 } 52 }
53 53
54 mp_range_parsed tmp = mp_parse_range_string(ptr); 54 mp_range_parsed tmp = mp_parse_range_string(ptr);
55 if (tmp.error != MP_PARSING_SUCCES) { 55 if (tmp.error != MP_PARSING_SUCCESS) {
56 die(STATE_UNKNOWN, "Unable to parse critical threshold range: %s", ptr); 56 die(STATE_UNKNOWN, "Unable to parse critical threshold range: %s", ptr);
57 } 57 }
58 58
@@ -70,7 +70,7 @@ int check_snmp_set_thresholds(const char *threshold_string, check_snmp_test_unit
70 // Single value 70 // Single value
71 // only valid for the first test unit 71 // only valid for the first test unit
72 mp_range_parsed tmp = mp_parse_range_string(threshold_string); 72 mp_range_parsed tmp = mp_parse_range_string(threshold_string);
73 if (tmp.error != MP_PARSING_SUCCES) { 73 if (tmp.error != MP_PARSING_SUCCESS) {
74 die(STATE_UNKNOWN, "Unable to parse critical threshold range: %s", threshold_string); 74 die(STATE_UNKNOWN, "Unable to parse critical threshold range: %s", threshold_string);
75 } 75 }
76 76
diff --git a/plugins/check_ssh.c b/plugins/check_ssh.c
index f6c8d551..911f6787 100644
--- a/plugins/check_ssh.c
+++ b/plugins/check_ssh.c
@@ -61,6 +61,14 @@ static int ssh_connect(mp_check *overall, char *haddr, int hport, char *remote_v
61 char *remote_protocol); 61 char *remote_protocol);
62 62
63int main(int argc, char **argv) { 63int main(int argc, char **argv) {
64#ifdef __OpenBSD__
65 /* - rpath is required to read --extra-opts (given up later)
66 * - inet is required for sockets
67 * - unix is required for Unix domain sockets
68 * - dns is required for name lookups */
69 pledge("stdio rpath inet unix dns", NULL);
70#endif // __OpenBSD__
71
64 setlocale(LC_ALL, ""); 72 setlocale(LC_ALL, "");
65 bindtextdomain(PACKAGE, LOCALEDIR); 73 bindtextdomain(PACKAGE, LOCALEDIR);
66 textdomain(PACKAGE); 74 textdomain(PACKAGE);
@@ -74,6 +82,10 @@ int main(int argc, char **argv) {
74 usage4(_("Could not parse arguments")); 82 usage4(_("Could not parse arguments"));
75 } 83 }
76 84
85#ifdef __OpenBSD__
86 pledge("stdio inet unix dns", NULL);
87#endif // __OpenBSD__
88
77 check_ssh_config config = tmp_config.config; 89 check_ssh_config config = tmp_config.config;
78 90
79 mp_check overall = mp_check_init(); 91 mp_check overall = mp_check_init();
@@ -161,11 +173,7 @@ process_arguments_wrapper process_arguments(int argc, char **argv) {
161 address_family = AF_INET; 173 address_family = AF_INET;
162 break; 174 break;
163 case '6': 175 case '6':
164#ifdef USE_IPV6
165 address_family = AF_INET6; 176 address_family = AF_INET6;
166#else
167 usage4(_("IPv6 support not available"));
168#endif
169 break; 177 break;
170 case 'r': /* remote version */ 178 case 'r': /* remote version */
171 result.config.remote_version = optarg; 179 result.config.remote_version = optarg;
diff --git a/plugins/check_tcp.c b/plugins/check_tcp.c
index 09806373..49a8c4c1 100644
--- a/plugins/check_tcp.c
+++ b/plugins/check_tcp.c
@@ -89,6 +89,14 @@ const int DEFAULT_NNTPS_PORT = 563;
89const int DEFAULT_CLAMD_PORT = 3310; 89const int DEFAULT_CLAMD_PORT = 3310;
90 90
91int main(int argc, char **argv) { 91int main(int argc, char **argv) {
92#ifdef __OpenBSD__
93 /* - rpath is required to read --extra-opts (given up later)
94 * - inet is required for sockets
95 * - unix is required for Unix domain sockets
96 * - dns is required for name lookups */
97 pledge("stdio rpath inet unix dns", NULL);
98#endif // __OpenBSD__
99
92 setlocale(LC_ALL, ""); 100 setlocale(LC_ALL, "");
93 bindtextdomain(PACKAGE, LOCALEDIR); 101 bindtextdomain(PACKAGE, LOCALEDIR);
94 textdomain(PACKAGE); 102 textdomain(PACKAGE);
@@ -216,6 +224,10 @@ int main(int argc, char **argv) {
216 usage4(_("Could not parse arguments")); 224 usage4(_("Could not parse arguments"));
217 } 225 }
218 226
227#ifdef __OpenBSD__
228 pledge("stdio inet unix dns", NULL);
229#endif // __OpenBSD__
230
219 config = paw.config; 231 config = paw.config;
220 232
221 if (verbosity > 0) { 233 if (verbosity > 0) {
@@ -571,11 +583,7 @@ static check_tcp_config_wrapper process_arguments(int argc, char **argv, check_t
571 address_family = AF_INET; 583 address_family = AF_INET;
572 break; 584 break;
573 case '6': // Apparently unused TODO 585 case '6': // Apparently unused TODO
574#ifdef USE_IPV6
575 address_family = AF_INET6; 586 address_family = AF_INET6;
576#else
577 usage4(_("IPv6 support not available"));
578#endif
579 break; 587 break;
580 case 'H': /* hostname */ 588 case 'H': /* hostname */
581 config.host_specified = true; 589 config.host_specified = true;
diff --git a/plugins/check_users.c b/plugins/check_users.c
index 3b2e265e..4027d21a 100644
--- a/plugins/check_users.c
+++ b/plugins/check_users.c
@@ -222,7 +222,7 @@ check_users_config_wrapper process_arguments(int argc, char **argv) {
222 exit(STATE_UNKNOWN); 222 exit(STATE_UNKNOWN);
223 } 223 }
224 224
225 if (tmp.error == MP_PARSING_SUCCES) { 225 if (tmp.error == MP_PARSING_SUCCESS) {
226 result.config.thresholds.warning = tmp.range; 226 result.config.thresholds.warning = tmp.range;
227 result.config.thresholds.warning_is_set = true; 227 result.config.thresholds.warning_is_set = true;
228 } else { 228 } else {
@@ -238,7 +238,7 @@ check_users_config_wrapper process_arguments(int argc, char **argv) {
238 exit(STATE_UNKNOWN); 238 exit(STATE_UNKNOWN);
239 } 239 }
240 240
241 if (tmp.error == MP_PARSING_SUCCES) { 241 if (tmp.error == MP_PARSING_SUCCESS) {
242 result.config.thresholds.critical = tmp.range; 242 result.config.thresholds.critical = tmp.range;
243 result.config.thresholds.critical_is_set = true; 243 result.config.thresholds.critical_is_set = true;
244 } else { 244 } else {
diff --git a/plugins/netutils.c b/plugins/netutils.c
index b4c6ff0a..f9933ebd 100644
--- a/plugins/netutils.c
+++ b/plugins/netutils.c
@@ -38,11 +38,7 @@ mp_state_enum socket_timeout_state = STATE_CRITICAL;
38mp_state_enum econn_refuse_state = STATE_CRITICAL; 38mp_state_enum econn_refuse_state = STATE_CRITICAL;
39bool was_refused = false; 39bool was_refused = false;
40 40
41#if USE_IPV6
42int address_family = AF_UNSPEC; 41int address_family = AF_UNSPEC;
43#else
44int address_family = AF_INET;
45#endif
46 42
47/* handles socket timeouts */ 43/* handles socket timeouts */
48void socket_timeout_alarm_handler(int sig) { 44void socket_timeout_alarm_handler(int sig) {
@@ -348,7 +344,6 @@ void host_or_die(const char *str) {
348} 344}
349 345
350bool is_addr(const char *address) { 346bool is_addr(const char *address) {
351#ifdef USE_IPV6
352 if (address_family == AF_INET && is_inet_addr(address)) { 347 if (address_family == AF_INET && is_inet_addr(address)) {
353 return true; 348 return true;
354 } 349 }
@@ -356,11 +351,6 @@ bool is_addr(const char *address) {
356 if (address_family == AF_INET6 && is_inet6_addr(address)) { 351 if (address_family == AF_INET6 && is_inet6_addr(address)) {
357 return true; 352 return true;
358 } 353 }
359#else
360 if (is_inet_addr(address)) {
361 return true;
362 }
363#endif
364 354
365 return false; 355 return false;
366} 356}
diff --git a/plugins/netutils.h b/plugins/netutils.h
index dbd22398..f3d046c3 100644
--- a/plugins/netutils.h
+++ b/plugins/netutils.h
@@ -78,12 +78,8 @@ bool dns_lookup(const char *, struct sockaddr_storage *, int);
78void host_or_die(const char *str); 78void host_or_die(const char *str);
79#define resolve_host_or_addr(addr, family) dns_lookup(addr, NULL, family) 79#define resolve_host_or_addr(addr, family) dns_lookup(addr, NULL, family)
80#define is_inet_addr(addr) resolve_host_or_addr(addr, AF_INET) 80#define is_inet_addr(addr) resolve_host_or_addr(addr, AF_INET)
81#ifdef USE_IPV6
82# define is_inet6_addr(addr) resolve_host_or_addr(addr, AF_INET6) 81# define is_inet6_addr(addr) resolve_host_or_addr(addr, AF_INET6)
83# define is_hostname(addr) resolve_host_or_addr(addr, address_family) 82# define is_hostname(addr) resolve_host_or_addr(addr, address_family)
84#else
85# define is_hostname(addr) resolve_host_or_addr(addr, AF_INET)
86#endif
87 83
88extern unsigned int socket_timeout; 84extern unsigned int socket_timeout;
89extern mp_state_enum socket_timeout_state; 85extern mp_state_enum socket_timeout_state;
diff --git a/plugins/t/check_curl.t b/plugins/t/check_curl.t
index 2c2fafde..a8326f12 100644
--- a/plugins/t/check_curl.t
+++ b/plugins/t/check_curl.t
@@ -13,7 +13,7 @@ use vars qw($tests $has_ipv6);
13BEGIN { 13BEGIN {
14 use NPTest; 14 use NPTest;
15 $has_ipv6 = NPTest::has_ipv6(); 15 $has_ipv6 = NPTest::has_ipv6();
16 $tests = $has_ipv6 ? 55 : 53; 16 $tests = $has_ipv6 ? 57 : 92;
17 plan tests => $tests; 17 plan tests => $tests;
18} 18}
19 19
@@ -25,7 +25,13 @@ my $plugin = 'check_http';
25$plugin = 'check_curl' if $0 =~ m/check_curl/mx; 25$plugin = 'check_curl' if $0 =~ m/check_curl/mx;
26 26
27my $host_tcp_http = getTestParameter("NP_HOST_TCP_HTTP", "A host providing the HTTP Service (a web server)", "localhost"); 27my $host_tcp_http = getTestParameter("NP_HOST_TCP_HTTP", "A host providing the HTTP Service (a web server)", "localhost");
28my $host_tcp_http_subdomain = getTestParameter("NP_HOST_TCP_HTTP_SUBDOMAIN", "A host that is served under a subdomain name", "subdomain1.localhost.com");
29my $host_tcp_http_ipv4 = getTestParameter("NP_HOST_TCP_HTTP_IPV4", "An IPv6 address providing a HTTP Service (a web server)", "127.0.0.1");
30my $host_tcp_http_ipv4_cidr_1 = getTestParameter("NP_HOST_TCP_HTTP_IPV4_CIDR_1", "A CIDR that the provided IPv4 address is in.");
31my $host_tcp_http_ipv4_cidr_2 = getTestParameter("NP_HOST_TCP_HTTP_IPV4_CIDR_2", "A CIDR that the provided IPv4 address is in.");
28my $host_tcp_http_ipv6 = getTestParameter("NP_HOST_TCP_HTTP_IPV6", "An IPv6 address providing a HTTP Service (a web server)", "::1"); 32my $host_tcp_http_ipv6 = getTestParameter("NP_HOST_TCP_HTTP_IPV6", "An IPv6 address providing a HTTP Service (a web server)", "::1");
33my $host_tcp_http_ipv6_cidr_1 = getTestParameter("NP_HOST_TCP_HTTP_IPV6_CIDR_1", "A CIDR that the provided IPv6 address is in.");
34my $host_tcp_http_ipv6_cidr_2 = getTestParameter("NP_HOST_TCP_HTTP_IPV6_CIDR_2", "A CIDR that the provided IPv6 address is in.");
29my $host_tls_http = getTestParameter("NP_HOST_TLS_HTTP", "A host providing the HTTPS Service (a tls web server)", "localhost"); 35my $host_tls_http = getTestParameter("NP_HOST_TLS_HTTP", "A host providing the HTTPS Service (a tls web server)", "localhost");
30my $host_tls_cert = getTestParameter("NP_HOST_TLS_CERT", "the common name of the certificate.", "localhost"); 36my $host_tls_cert = getTestParameter("NP_HOST_TLS_CERT", "the common name of the certificate.", "localhost");
31my $host_nonresponsive = getTestParameter("NP_HOST_NONRESPONSIVE", "The hostname of system not responsive to network requests", "10.0.0.1"); 37my $host_nonresponsive = getTestParameter("NP_HOST_NONRESPONSIVE", "The hostname of system not responsive to network requests", "10.0.0.1");
@@ -222,3 +228,110 @@ SKIP: {
222 $res = NPTest->testCmd( "./$plugin -H monitoring-plugins.org --extended-perfdata" ); 228 $res = NPTest->testCmd( "./$plugin -H monitoring-plugins.org --extended-perfdata" );
223 like ( $res->output, '/\'time_connect\'=[\d\.]+/', 'Extended Performance Data Output OK' ); 229 like ( $res->output, '/\'time_connect\'=[\d\.]+/', 'Extended Performance Data Output OK' );
224} 230}
231SKIP: {
232 skip "No internet access", 2 if $internet_access eq "no";
233
234 # Proxy tests
235 # These are the proxy tests that require a working proxy server
236 # The debian container in the github workflow runs a squid proxy server at port 3128
237 # Test that dont require one, like argument/environment variable parsing are in plugins/tests/check_curl.t
238
239 # Test if proxy works
240 $res = NPTest->testCmd( "./$plugin -H $host_tcp_http --proxy http://$host_tcp_proxy:$port_tcp_proxy -v" );
241 like($res->output, qr/^\* proxy_resolves_hostname: 1/m, "proxy is used, there are no preventative measures ");
242 is( $res->return_code, 0, "Using proxy http://$host_tcp_proxy:$port_tcp_proxy to connect to $host_tcp_http works" );
243
244 $res = NPTest->testCmd( "./$plugin -I $host_tcp_http_ipv4 --proxy http://$host_tcp_proxy:$port_tcp_proxy -v" );
245 like($res->output, qr/^\* proxy_resolves_hostname: 1/m, "proxy is used, there are no preventative measures ");
246 is( $res->return_code, 0, "Using proxy http://$host_tcp_proxy:$port_tcp_proxy to connect to $host_tcp_http_ipv4 works" );
247
248 $res = NPTest->testCmd( "./$plugin -I $host_tcp_http_ipv6 --proxy http://$host_tcp_proxy:$port_tcp_proxy -v" );
249 like($res->output, qr/^\* proxy_resolves_hostname: 1/m, "proxy is used, there are no preventative measures ");
250 is( $res->return_code, 0, "Using proxy http://$host_tcp_proxy:$port_tcp_proxy to connect to $host_tcp_http_ipv6 works" );
251
252 $res = NPTest->testCmd( "./$plugin -H $host_tcp_http2 --proxy http://$host_tcp_proxy:$port_tcp_proxy -v" );
253 like($res->output, qr/^\* proxy_resolves_hostname: 1/m, "proxy is used, there are no preventative measures ");
254 is( $res->return_code, 0, "Using proxy http://$host_tcp_proxy:$port_tcp_proxy to connect to $host_tcp_http2 works" );
255
256 $res = NPTest->testCmd( "./$plugin -H $host_tcp_http_subdomain --proxy http://$host_tcp_proxy:$port_tcp_proxy -v" );
257 like($res->output, qr/^\* proxy_resolves_hostname: 1/m, "proxy is used, there are no preventative measures ");
258 is( $res->return_code, 0, "Using proxy http://$host_tcp_proxy:$port_tcp_proxy to connect to $host_tcp_http_subdomain works" );
259
260 $res = NPTest->testCmd( "./$plugin -H $host_tls_http --proxy http://$host_tcp_proxy:$port_tcp_proxy -v" );
261 like($res->output, qr/^\* proxy_resolves_hostname: 1/m, "proxy is used, there are no preventative measures ");
262 is( $res->return_code, 0, "Using proxy http://$host_tcp_proxy:$port_tcp_proxy to connect to $host_tls_http works" );
263
264 # Noproxy '*' should prevent using proxy in any setting, even if its specified
265 $res = NPTest->testCmd( "./$plugin -H $host_tcp_http_subdomain --proxy http://$host_tcp_proxy:$port_tcp_proxy --noproxy \"\*\" -v" );
266 like($res->output, qr/^\* proxy_resolves_hostname: 0/m, "proxy is not used since noproxy has \"\*\" ");
267 is( $res->return_code, 0, "Should reach $host_tcp_http_subdomain with or without proxy." );
268
269 $res = NPTest->testCmd( "./$plugin -I $host_tcp_http_ipv4 --proxy http://$host_tcp_proxy:$port_tcp_proxy --noproxy \"\*\" -v" );
270 like($res->output, qr/^\* proxy_resolves_hostname: 0/m, "proxy is not used since noproxy has \"\*\" ");
271 is( $res->return_code, 0, "Should reach $host_tcp_http_ipv4 with or without proxy." );
272
273 $res = NPTest->testCmd( "./$plugin -I $host_tcp_http_ipv6 --proxy http://$host_tcp_proxy:$port_tcp_proxy --noproxy \"\*\" -v" );
274 like($res->output, qr/^\* proxy_resolves_hostname: 0/m, "proxy is not used since noproxy has \"\*\" ");
275 is( $res->return_code, 0, "Should reach $host_tcp_http_ipv6 with or without proxy." );
276
277 # Noproxy domain should prevent using proxy for subdomains of that domain
278 $res = NPTest->testCmd( "./$plugin -H $host_tcp_http_subdomain --proxy http://$host_tcp_proxy:$port_tcp_proxy --noproxy $host_tcp_http -v" );
279 like($res->output, qr/^\* proxy_resolves_hostname: 0/m, "proxy is not used since subdomain: $host_tcp_http_subdomain is under a noproxy domain: $host_tcp_http");
280 is( $res->return_code, 0, "Should reach $host_tcp_http_subdomain with or without proxy." );
281
282 # Noproxy should prevent using IP matches if an IP is found directly
283 $res = NPTest->testCmd( "./$plugin -I $host_tcp_http_ipv4 --proxy http://$host_tcp_proxy:$port_tcp_proxy --noproxy $host_tcp_http_ipv4 -v" );
284 like($res->output, qr/^\* proxy_resolves_hostname: 0/m, "proxy is not used since IP address: $host_tcp_http_ipv4 is added into noproxy: $host_tcp_http_ipv4");
285 is( $res->return_code, 0, "Should reach $host_tcp_http_ipv4 with or without proxy." );
286
287 $res = NPTest->testCmd( "./$plugin -I $host_tcp_http_ipv6 --proxy http://$host_tcp_proxy:$port_tcp_proxy --noproxy $host_tcp_http_ipv6 -v" );
288 like($res->output, qr/^\* proxy_resolves_hostname: 0/m, "proxy is not used since IP address: $host_tcp_http_ipv6 is added into noproxy: $host_tcp_http_ipv6");
289 is( $res->return_code, 0, "Should reach $host_tcp_http_ipv6 with or without proxy." );
290
291 # Noproxy should prevent using IP matches if a CIDR region that contains that Ip is used directly.
292 $res = NPTest->testCmd( "./$plugin -I $host_tcp_http_ipv4 --proxy http://$host_tcp_proxy:$port_tcp_proxy --noproxy $host_tcp_http_ipv4_cidr_1 -v" );
293 like($res->output, qr/^\* proxy_resolves_hostname: 0/m, "proxy is not used since IP address: $host_tcp_http_ipv4 is inside CIDR range: $host_tcp_http_ipv4_cidr_1");
294 is( $res->return_code, 0, "Should reach $host_tcp_http_ipv4 with or without proxy." );
295
296 $res = NPTest->testCmd( "./$plugin -I $host_tcp_http_ipv4 --proxy http://$host_tcp_proxy:$port_tcp_proxy --noproxy $host_tcp_http_ipv4_cidr_2 -v" );
297 like($res->output, qr/^\* proxy_resolves_hostname: 0/m, "proxy is not used since IP address: $host_tcp_http_ipv4 is inside CIDR range: $host_tcp_http_ipv4_cidr_2");
298 is( $res->return_code, 0, "Should reach $host_tcp_http_ipv4 with or without proxy." );
299
300 $res = NPTest->testCmd( "./$plugin -I $host_tcp_http_ipv6 --proxy http://$host_tcp_proxy:$port_tcp_proxy --noproxy $host_tcp_http_ipv6_cidr_1 -v " );
301 like($res->output, qr/^\* proxy_resolves_hostname: 0/m, "proxy is not used since IP address: $host_tcp_http_ipv6 is inside CIDR range: $host_tcp_http_ipv6_cidr_1");
302 is( $res->return_code, 0, "Should reach $host_tcp_http_ipv6 with or without proxy." );
303
304 $res = NPTest->testCmd( "./$plugin -I $host_tcp_http_ipv6 --proxy http://$host_tcp_proxy:$port_tcp_proxy --noproxy $host_tcp_http_ipv6_cidr_2 -v" );
305 like($res->output, qr/^\* proxy_resolves_hostname: 0/m, "proxy is not used since IP address: $host_tcp_http_ipv6 is inside CIDR range: $host_tcp_http_ipv6_cidr_2");
306 is( $res->return_code, 0, "Should reach $host_tcp_http_ipv6 with or without proxy." );
307
308 # Noproxy should discern over different types of proxy schemes
309 $res = NPTest->testCmd( "./$plugin -H $host_tcp_http --proxy http://$host_tcp_proxy:$port_tcp_proxy -v" );
310 like($res->output, qr/^\* proxy_resolves_hostname: 1/m, "proxy is used for resolving hostname, and is using scheme http ");
311 is( $res->return_code, 0, "Using proxy http:$host_tcp_proxy:$port_tcp_proxy to connect to $host_tcp_http works" );
312
313 $res = NPTest->testCmd( "./$plugin -H $host_tcp_http --proxy https://$host_tcp_proxy:$port_tcp_proxy -v" );
314 like($res->output, qr/^\* proxy_resolves_hostname: 1/m, "proxy is used for resolving hostname, and is using scheme https");
315 # Squid is not configured for https
316 # is( $res->return_code, 0, "Using proxy https:$host_tcp_proxy:$port_tcp_proxy to connect to $host_tcp_http works" );
317
318 $res = NPTest->testCmd( "./$plugin -H $host_tcp_http --proxy socks4://$host_tcp_proxy:$port_tcp_proxy -v" );
319 like($res->output, qr/^\* proxy_resolves_hostname: 0/m, "proxy is not used for resolving hostname, and is using scheme socks4");
320 # Squid is not configured for socks4
321 # is( $res->return_code, 0, "Using proxy socks4:$host_tcp_proxy:$port_tcp_proxy to connect to $host_tcp_http works" );
322
323 $res = NPTest->testCmd( "./$plugin -H $host_tcp_http --proxy socks4a://$host_tcp_proxy:$port_tcp_proxy -v" );
324 like($res->output, qr/^\* proxy_resolves_hostname: 1/m, "proxy is used for resolving hostname, and is using scheme socks4a");
325 # Squid is not configured for socks4a
326 # is( $res->return_code, 0, "Using proxy socks4a:$host_tcp_proxy:$port_tcp_proxy to connect to $host_tcp_http works" );
327
328 $res = NPTest->testCmd( "./$plugin -H $host_tcp_http --proxy socks5://$host_tcp_proxy:$port_tcp_proxy -v" );
329 like($res->output, qr/^\* proxy_resolves_hostname: 0/m, "proxy is not used for resolving hostname, and is using scheme socks5");
330 # Squid is not configured for socks5
331 # is( $res->return_code, 0, "Using proxy socks5:$host_tcp_proxy:$port_tcp_proxy to connect to $host_tcp_http works" );
332
333 $res = NPTest->testCmd( "./$plugin -H $host_tcp_http --proxy socks5h://$host_tcp_proxy:$port_tcp_proxy -v" );
334 like($res->output, qr/^\* proxy_resolves_hostname: 1/m, "proxy is used for resolving hostname, and is using scheme socks5h");
335 # Squid is not configured for socks5h
336 # is( $res->return_code, 0, "Using proxy socks5h:$host_tcp_proxy:$port_tcp_proxy to connect to $host_tcp_http works" );
337}
diff --git a/plugins/tests/check_curl.t b/plugins/tests/check_curl.t
index 248eb4c5..94058d5b 100755
--- a/plugins/tests/check_curl.t
+++ b/plugins/tests/check_curl.t
@@ -27,8 +27,8 @@ use HTTP::Daemon::SSL;
27 27
28$ENV{'LC_TIME'} = "C"; 28$ENV{'LC_TIME'} = "C";
29 29
30my $common_tests = 95; 30my $common_tests = 111;
31my $ssl_only_tests = 8; 31my $ssl_only_tests = 12;
32# Check that all dependent modules are available 32# Check that all dependent modules are available
33eval "use HTTP::Daemon 6.01;"; 33eval "use HTTP::Daemon 6.01;";
34plan skip_all => 'HTTP::Daemon >= 6.01 required' if $@; 34plan skip_all => 'HTTP::Daemon >= 6.01 required' if $@;
@@ -41,7 +41,7 @@ my $plugin = 'check_http';
41$plugin = 'check_curl' if $0 =~ m/check_curl/mx; 41$plugin = 'check_curl' if $0 =~ m/check_curl/mx;
42 42
43# look for libcurl version to see if some advanced checks are possible (>= 7.49.0) 43# look for libcurl version to see if some advanced checks are possible (>= 7.49.0)
44my $advanced_checks = 12; 44my $advanced_checks = 16;
45my $use_advanced_checks = 0; 45my $use_advanced_checks = 0;
46my $required_version = '7.49.0'; 46my $required_version = '7.49.0';
47my $virtual_host = 'www.somefunnyhost.com'; 47my $virtual_host = 'www.somefunnyhost.com';
@@ -410,6 +410,41 @@ SKIP: {
410 $result = NPTest->testCmd( $cmd ); 410 $result = NPTest->testCmd( $cmd );
411 is( $result->return_code, 0, $cmd); 411 is( $result->return_code, 0, $cmd);
412 like( $result->output, '/.*HTTP/1.1 200 OK - \d+ bytes in [\d\.]+ second.*/', "Output correct: ".$result->output ); 412 like( $result->output, '/.*HTTP/1.1 200 OK - \d+ bytes in [\d\.]+ second.*/', "Output correct: ".$result->output );
413
414 # curlopt proxy/noproxy parsing tests, ssl disabled
415 {
416 # Make a scope and change environment variables here, to not mess them up for other tests using environment variables
417
418 local $ENV{"http_proxy"} = 'http://proxy.example.com:8080';
419 $cmd = "$command -u /statuscode/200 -v";
420 $result = NPTest->testCmd( $cmd );
421 like( $result->output, '/.*CURLOPT_PROXY: http://proxy.example.com:8080 */', "Correctly took 'http_proxy' environment variable: ".$result->output );
422 delete($ENV{"http_proxy"});
423
424 local $ENV{"http_proxy"} = 'http://taken.proxy.example:8080';
425 local $ENV{"HTTP_PROXY"} = 'http://discarded.proxy.example:8080';
426 $cmd = "$command -u /statuscode/200 -v";
427 $result = NPTest->testCmd( $cmd );
428 like( $result->output, '/.*CURLOPT_PROXY: http://taken.proxy.example:8080 */', "Correctly took 'http_proxy' environment variable over 'HTTP_PROXY': ".$result->output );
429 delete(local $ENV{"http_proxy"});
430 delete(local $ENV{"HTTP_PROXY"});
431
432 local $ENV{"http_proxy"} = 'http://discarded1.proxy.example:8080';
433 local $ENV{"HTTP_PROXY"} = 'http://discarded2.proxy.example:8080';
434 $cmd = "$command -u /statuscode/200 -x 'http://taken.proxy.example:8080' -v";
435 $result = NPTest->testCmd( $cmd );
436 like( $result->output, '/.*CURLOPT_PROXY: http://taken.proxy.example:8080 */', "Argument -x overwrote 'http_proxy' and 'HTTP_PROXY' environment variables: ".$result->output );
437 delete(local $ENV{"http_proxy"});
438 delete(local $ENV{"HTTP_PROXY"});
439
440 local $ENV{"http_proxy"} = 'http://discarded1.proxy.example:8080';
441 local $ENV{"HTTP_PROXY"} = 'http://discarded2.proxy.example:8080';
442 $cmd = "$command -u /statuscode/200 --proxy 'http://taken.example.com:8080' -v";
443 $result = NPTest->testCmd( $cmd );
444 like( $result->output, '/.*CURLOPT_PROXY: http://taken.example.com:8080 */', "Argument --proxy overwrote 'http_proxy' and 'HTTP_PROXY' environment variables: ".$result->output );
445 delete(local $ENV{"http_proxy"});
446 delete(local $ENV{"HTTP_PROXY"});
447 }
413} 448}
414 449
415# and the same for SSL 450# and the same for SSL
@@ -432,6 +467,41 @@ SKIP: {
432 $result = NPTest->testCmd( $cmd ); 467 $result = NPTest->testCmd( $cmd );
433 is( $result->return_code, 0, $cmd); 468 is( $result->return_code, 0, $cmd);
434 like( $result->output, '/.*HTTP/1.1 200 OK - \d+ bytes in [\d\.]+ second.*/', "Output correct: ".$result->output ); 469 like( $result->output, '/.*HTTP/1.1 200 OK - \d+ bytes in [\d\.]+ second.*/', "Output correct: ".$result->output );
470
471 # curlopt proxy/noproxy parsing tests, ssl enabled
472 {
473 # Make a scope and change environment variables here, to not mess them up for other tests using environment variables
474
475 local $ENV{"https_proxy"} = 'http://proxy.example.com:8080';
476 $cmd = "$command -u /statuscode/200 --ssl -v";
477 $result = NPTest->testCmd( $cmd );
478 like( $result->output, '/.*CURLOPT_PROXY: http://proxy.example.com:8080 */', "Correctly took 'https_proxy' environment variable: ".$result->output );
479 delete($ENV{"https_proxy"});
480
481 local $ENV{"https_proxy"} = 'http://taken.proxy.example:8080';
482 local $ENV{"HTTPS_PROXY"} = 'http://discarded.proxy.example:8080';
483 $cmd = "$command -u /statuscode/200 --ssl -v";
484 $result = NPTest->testCmd( $cmd );
485 like( $result->output, '/.*CURLOPT_PROXY: http://taken.proxy.example:8080 */', "Correctly took 'https_proxy' environment variable over 'HTTPS_PROXY': ".$result->output );
486 delete(local $ENV{"https_proxy"});
487 delete(local $ENV{"HTTPS_PROXY"});
488
489 local $ENV{"https_proxy"} = 'http://discarded1.proxy.example:8080';
490 local $ENV{"HTTPS_PROXY"} = 'http://discarded2.proxy.example:8080';
491 $cmd = "$command -u /statuscode/200 --ssl -x 'http://taken.example.com:8080' -v";
492 $result = NPTest->testCmd( $cmd );
493 like( $result->output, '/.*CURLOPT_PROXY: http://taken.example.com:8080 */', "Argument -x overwrote environment variables 'https_proxy' and 'HTTPS_PROXY': ".$result->output );
494 delete(local $ENV{"https_proxy"});
495 delete(local $ENV{"HTTPS_PROXY"});
496
497 local $ENV{"https_proxy"} = 'http://discarded1.proxy.example:8080';
498 local $ENV{"HTTPS_PROXY"} = 'http://discarded2.proxy.example:8080';
499 $cmd = "$command -u /statuscode/200 --ssl --proxy 'http://taken.example.com:8080' -v";
500 $result = NPTest->testCmd( $cmd );
501 like( $result->output, '/.*CURLOPT_PROXY: http://taken.example.com:8080 */', "Argument --proxy overwrote environment variables 'https_proxy' and 'HTTPS_PROXY': ".$result->output );
502 delete(local $ENV{"https_proxy"});
503 delete(local $ENV{"HTTPS_PROXY"});
504 }
435} 505}
436 506
437 507
@@ -712,4 +782,63 @@ sub run_common_tests {
712 $result = NPTest->testCmd( $cmd, 5 ); 782 $result = NPTest->testCmd( $cmd, 5 );
713 }; 783 };
714 is( $@, "", $cmd ); 784 is( $@, "", $cmd );
785
786 # curlopt proxy/noproxy parsing tests
787 {
788 # Make a scope and change environment variables here, to not mess them up for other tests using environment variables
789
790 local $ENV{"no_proxy"} = 'internal.acme.org';
791 $cmd = "$command -u /statuscode/200 -v";
792 $result = NPTest->testCmd( $cmd );
793 like( $result->output, '/.* curl CURLOPT_NOPROXY: internal.acme.org */', "Correctly took 'no_proxy' environment variable: ".$result->output );
794 delete($ENV{"no_proxy"});
795
796 local $ENV{"no_proxy"} = 'taken.acme.org';
797 local $ENV{"NO_PROXY"} = 'discarded.acme.org';
798 $cmd = "$command -u /statuscode/200 -v";
799 $result = NPTest->testCmd( $cmd );
800 is( $result->return_code, 0, $cmd);
801 like( $result->output, '/.*CURLOPT_NOPROXY: taken.acme.org*/', "Correctly took 'no_proxy' environment variable over 'NO_PROXY': ".$result->output );
802 delete(local $ENV{"no_proxy"});
803 delete(local $ENV{"NO_PROXY"});
804
805 local $ENV{"no_proxy"} = 'taken.acme.org';
806 local $ENV{"NO_PROXY"} = 'discarded.acme.org';
807 $cmd = "$command -u /statuscode/200 --noproxy 'taken.acme.org' -v";
808 $result = NPTest->testCmd( $cmd );
809 is( $result->return_code, 0, $cmd);
810 like( $result->output, '/.*CURLOPT_NOPROXY: taken.acme.org*/', "Argument --noproxy overwrote environment variables 'no_proxy' and 'NO_PROXY': ".$result->output );
811 delete(local $ENV{"no_proxy"});
812 delete(local $ENV{"NO_PROXY"});
813
814 $cmd = "$command -u /statuscode/200 --noproxy 'internal1.acme.org,internal2.acme.org,internal3.acme.org' -v";
815 $result = NPTest->testCmd( $cmd );
816 is( $result->return_code, 0, $cmd);
817 like( $result->output, '/.*CURLOPT_NOPROXY: internal1.acme.org,internal2.acme.org,internal3.acme.org*/', "Argument --noproxy read multiple noproxy domains: ".$result->output );
818
819 $cmd = "$command -u /statuscode/200 --noproxy '10.11.12.13,256.256.256.256,0.0.0.0,192.156.0.0/22,10.0.0.0/4' -v";
820 $result = NPTest->testCmd( $cmd );
821 is( $result->return_code, 0, $cmd);
822 like( $result->output, '/.*CURLOPT_NOPROXY: 10.11.12.13,256.256.256.256,0.0.0.0,192.156.0.0/22,10.0.0.0/4*/', "Argument --noproxy took multiple noproxy domains: ".$result->output );
823
824 $cmd = "$command -u /statuscode/200 --noproxy '0123:4567:89AB:CDEF:0123:4567:89AB:CDEF,0123::CDEF,0123:4567/96,[::1],::1,[1234::5678:ABCD/4]' -v";
825 $result = NPTest->testCmd( $cmd );
826 is( $result->return_code, 0, $cmd);
827 like( $result->output, '/.*CURLOPT_NOPROXY: 0123:4567:89AB:CDEF:0123:4567:89AB:CDEF,0123::CDEF,0123:4567\/96,\[::1\],::1,\[1234::5678:ABCD\/4\].*/', "Argument --noproxy took multiple noproxy domains: ".$result->output );
828
829 $cmd = "$command -u /statuscode/200 --noproxy '300.400.500.600,1.2.3,XYZD:0123::,1:2:3:4:5:6:7,1::2::3,1.1.1.1/64,::/256' -v";
830 $result = NPTest->testCmd( $cmd );
831 is( $result->return_code, 0, $cmd);
832
833 $cmd = "$command -u /statuscode/200 --proxy http://proxy.example.com:8080 --noproxy '*' -v";
834 $result = NPTest->testCmd( $cmd );
835 is( $result->return_code, 0, $cmd);
836 like( $result->output, '/.*proxy_resolves_hostname: 0.*/', "Proxy will not be used due to '*' in noproxy: ".$result->output );
837
838 $cmd = "$command -u /statuscode/200 --proxy http://proxy.example.com:8080 --noproxy '127.0.0.1' -v";
839 $result = NPTest->testCmd( $cmd );
840 is( $result->return_code, 0, $cmd);
841 like( $result->output, '/.*proxy_resolves_hostname: 0.*/', "Proxy will not be used due to '127.0.0.1' in noproxy: ".$result->output );
842 }
843
715} 844}