mirror of https://github.com/getdnsapi/getdns.git
Revise output.
If in monitoring mode, make output conform to Nagios norms. This starts with the probe type and result, so we need to save output generated during the operation and print it at the end. If not in monitoring mode, make the formatting more expansive.
This commit is contained in:
parent
0291e205fd
commit
f9e4c9f853
|
@ -26,6 +26,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
#include <stdarg.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -80,19 +81,39 @@ typedef enum {
|
||||||
VERBOSITY_DEBUG
|
VERBOSITY_DEBUG
|
||||||
} plugin_verbosity;
|
} plugin_verbosity;
|
||||||
|
|
||||||
|
#define MAX_BASE_OUTPUT_LEN 256
|
||||||
|
#define MAX_PERF_OUTPUT_LEN 256
|
||||||
|
|
||||||
static struct test_info_s
|
static struct test_info_s
|
||||||
{
|
{
|
||||||
getdns_context *context;
|
getdns_context *context;
|
||||||
|
|
||||||
/* Output control */
|
/* Output */
|
||||||
bool monitoring;
|
bool monitoring;
|
||||||
FILE *errout;
|
FILE *errout;
|
||||||
plugin_verbosity verbosity;
|
plugin_verbosity verbosity;
|
||||||
|
bool debug_output;
|
||||||
|
char base_output[MAX_BASE_OUTPUT_LEN + 1];
|
||||||
|
char perf_output[MAX_PERF_OUTPUT_LEN + 1];
|
||||||
|
|
||||||
/* Test config info */
|
/* Test config info */
|
||||||
bool fail_on_dns_errors;
|
bool fail_on_dns_errors;
|
||||||
} test_info;
|
} test_info;
|
||||||
|
|
||||||
|
static void snprintcat(char *buf, size_t buflen, const char *format, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
int l = strlen(buf);
|
||||||
|
|
||||||
|
buf += l;
|
||||||
|
buflen -= l;
|
||||||
|
|
||||||
|
va_start(ap, format);
|
||||||
|
vsnprintf(buf, buflen, format, ap);
|
||||||
|
va_end(ap);
|
||||||
|
buf[buflen] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
static int get_rrtype(const char *t)
|
static int get_rrtype(const char *t)
|
||||||
{
|
{
|
||||||
char buf[1024] = "GETDNS_RRTYPE_";
|
char buf[1024] = "GETDNS_RRTYPE_";
|
||||||
|
@ -263,7 +284,7 @@ static void usage()
|
||||||
{
|
{
|
||||||
fputs(
|
fputs(
|
||||||
"Usage: " APP_NAME " [-M] [-E] [(-u|-t|-T)] [-S] [-K <spki-pin>]\n"
|
"Usage: " APP_NAME " [-M] [-E] [(-u|-t|-T)] [-S] [-K <spki-pin>]\n"
|
||||||
" [-v [-v [-v]]] [-V] @upstream testname [<name>] [<type>]\n"
|
" [-v [-v [-v]]] [-V] @upstream testname [<test args>]\n"
|
||||||
" -M|--monitoring Make output suitable for monitoring tools\n"
|
" -M|--monitoring Make output suitable for monitoring tools\n"
|
||||||
" -E|--fail-on-dns-errors Fail on DNS error (NXDOMAIN, SERVFAIL)\n"
|
" -E|--fail-on-dns-errors Fail on DNS error (NXDOMAIN, SERVFAIL)\n"
|
||||||
" -u|--udp Use UDP transport\n"
|
" -u|--udp Use UDP transport\n"
|
||||||
|
@ -272,6 +293,7 @@ static void usage()
|
||||||
" -S|--strict-usage-profile Use strict profile (require authentication)\n"
|
" -S|--strict-usage-profile Use strict profile (require authentication)\n"
|
||||||
" -K|--spki-pin <spki-pin> SPKI pin for TLS connections (can repeat)\n"
|
" -K|--spki-pin <spki-pin> SPKI pin for TLS connections (can repeat)\n"
|
||||||
" -v|--verbose Increase output verbosity\n"
|
" -v|--verbose Increase output verbosity\n"
|
||||||
|
" -D|--debug Enable debugging output\n"
|
||||||
" -V|--version Report GetDNS version\n"
|
" -V|--version Report GetDNS version\n"
|
||||||
"\n"
|
"\n"
|
||||||
"spki-pin: Should look like '" EXAMPLE_PIN "'\n"
|
"spki-pin: Should look like '" EXAMPLE_PIN "'\n"
|
||||||
|
@ -364,7 +386,7 @@ static void get_thresholds(char ***av,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static exit_value get_name_type_args(const struct test_info_s *test_info,
|
static exit_value get_name_type_args(struct test_info_s *test_info,
|
||||||
char ***av,
|
char ***av,
|
||||||
const char **lookup_name,
|
const char **lookup_name,
|
||||||
uint32_t *lookup_type)
|
uint32_t *lookup_type)
|
||||||
|
@ -373,7 +395,7 @@ static exit_value get_name_type_args(const struct test_info_s *test_info,
|
||||||
if (strlen(**av) > 0) {
|
if (strlen(**av) > 0) {
|
||||||
*lookup_name = **av;
|
*lookup_name = **av;
|
||||||
} else {
|
} else {
|
||||||
fputs("Empty name not valid", test_info->errout);
|
strcpy(test_info->base_output, "Empty name not valid");
|
||||||
return EXIT_UNKNOWN;
|
return EXIT_UNKNOWN;
|
||||||
}
|
}
|
||||||
++*av;
|
++*av;
|
||||||
|
@ -390,7 +412,7 @@ static exit_value get_name_type_args(const struct test_info_s *test_info,
|
||||||
return EXIT_OK;
|
return EXIT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static exit_value search(const struct test_info_s *test_info,
|
static exit_value search(struct test_info_s *test_info,
|
||||||
const char *name,
|
const char *name,
|
||||||
uint16_t type,
|
uint16_t type,
|
||||||
getdns_dict *extensions,
|
getdns_dict *extensions,
|
||||||
|
@ -405,7 +427,8 @@ static exit_value search(const struct test_info_s *test_info,
|
||||||
if ((ret = getdns_dict_set_int(search_extensions, "return_call_reporting", GETDNS_EXTENSION_TRUE)) != GETDNS_RETURN_GOOD) {
|
if ((ret = getdns_dict_set_int(search_extensions, "return_call_reporting", GETDNS_EXTENSION_TRUE)) != GETDNS_RETURN_GOOD) {
|
||||||
if (getdns_return)
|
if (getdns_return)
|
||||||
*getdns_return = ret;
|
*getdns_return = ret;
|
||||||
fprintf(test_info->errout,
|
snprintf(test_info->base_output,
|
||||||
|
MAX_BASE_OUTPUT_LEN,
|
||||||
"Cannot set return call reporting: %s (%d)",
|
"Cannot set return call reporting: %s (%d)",
|
||||||
getdns_get_errorstr_by_id(ret),
|
getdns_get_errorstr_by_id(ret),
|
||||||
ret);
|
ret);
|
||||||
|
@ -414,9 +437,13 @@ static exit_value search(const struct test_info_s *test_info,
|
||||||
return EXIT_UNKNOWN;
|
return EXIT_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (test_info->verbosity >= VERBOSITY_DEBUG) {
|
if (test_info->verbosity >= VERBOSITY_ADDITIONAL &&
|
||||||
fprintf(test_info->errout,
|
!test_info->monitoring) {
|
||||||
"Context: %s\n",
|
printf("Lookup:\t\t\t%s %u\n", name, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (test_info->debug_output) {
|
||||||
|
printf("Context: %s\n",
|
||||||
getdns_pretty_print_dict(getdns_context_get_api_information(test_info->context)));
|
getdns_pretty_print_dict(getdns_context_get_api_information(test_info->context)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -431,7 +458,8 @@ static exit_value search(const struct test_info_s *test_info,
|
||||||
if (getdns_return) {
|
if (getdns_return) {
|
||||||
*getdns_return = ret;
|
*getdns_return = ret;
|
||||||
} else {
|
} else {
|
||||||
fprintf(test_info->errout,
|
snprintf(test_info->base_output,
|
||||||
|
MAX_BASE_OUTPUT_LEN,
|
||||||
"Error resolving '%s': %s (%d)",
|
"Error resolving '%s': %s (%d)",
|
||||||
name,
|
name,
|
||||||
getdns_get_errorstr_by_id(ret),
|
getdns_get_errorstr_by_id(ret),
|
||||||
|
@ -440,9 +468,8 @@ static exit_value search(const struct test_info_s *test_info,
|
||||||
return EXIT_CRITICAL;
|
return EXIT_CRITICAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (test_info->verbosity >= VERBOSITY_DEBUG) {
|
if (test_info->debug_output) {
|
||||||
fprintf(test_info->errout,
|
printf("Response: %s\n",
|
||||||
"Response: %s\n",
|
|
||||||
getdns_pretty_print_dict(*response));
|
getdns_pretty_print_dict(*response));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -451,7 +478,7 @@ static exit_value search(const struct test_info_s *test_info,
|
||||||
return EXIT_OK;
|
return EXIT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static exit_value get_result(const struct test_info_s *test_info,
|
static exit_value get_result(struct test_info_s *test_info,
|
||||||
const getdns_dict *response,
|
const getdns_dict *response,
|
||||||
uint32_t *error_id,
|
uint32_t *error_id,
|
||||||
uint32_t *rcode)
|
uint32_t *rcode)
|
||||||
|
@ -459,7 +486,8 @@ static exit_value get_result(const struct test_info_s *test_info,
|
||||||
getdns_return_t ret;
|
getdns_return_t ret;
|
||||||
|
|
||||||
if ((ret = getdns_dict_get_int(response, "status", error_id)) != GETDNS_RETURN_GOOD) {
|
if ((ret = getdns_dict_get_int(response, "status", error_id)) != GETDNS_RETURN_GOOD) {
|
||||||
fprintf(test_info->errout,
|
snprintf(test_info->base_output,
|
||||||
|
MAX_BASE_OUTPUT_LEN,
|
||||||
"Cannot get result status: %s (%d)",
|
"Cannot get result status: %s (%d)",
|
||||||
getdns_get_errorstr_by_id(ret),
|
getdns_get_errorstr_by_id(ret),
|
||||||
ret);
|
ret);
|
||||||
|
@ -472,7 +500,8 @@ static exit_value get_result(const struct test_info_s *test_info,
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ret = getdns_dict_get_int(response, "/replies_tree/0/header/rcode", rcode)) != GETDNS_RETURN_GOOD) {
|
if ((ret = getdns_dict_get_int(response, "/replies_tree/0/header/rcode", rcode)) != GETDNS_RETURN_GOOD) {
|
||||||
fprintf(test_info->errout,
|
snprintf(test_info->base_output,
|
||||||
|
MAX_BASE_OUTPUT_LEN,
|
||||||
"Cannot get DNS return code: %s (%d)",
|
"Cannot get DNS return code: %s (%d)",
|
||||||
getdns_get_errorstr_by_id(ret),
|
getdns_get_errorstr_by_id(ret),
|
||||||
ret);
|
ret);
|
||||||
|
@ -482,7 +511,7 @@ static exit_value get_result(const struct test_info_s *test_info,
|
||||||
return EXIT_OK;
|
return EXIT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static exit_value check_result(const struct test_info_s *test_info,
|
static exit_value check_result(struct test_info_s *test_info,
|
||||||
const getdns_dict *response)
|
const getdns_dict *response)
|
||||||
{
|
{
|
||||||
exit_value xit;
|
exit_value xit;
|
||||||
|
@ -493,15 +522,15 @@ static exit_value check_result(const struct test_info_s *test_info,
|
||||||
|
|
||||||
switch(error_id) {
|
switch(error_id) {
|
||||||
case GETDNS_RESPSTATUS_ALL_TIMEOUT:
|
case GETDNS_RESPSTATUS_ALL_TIMEOUT:
|
||||||
fputs("Search timed out", test_info->errout);
|
strcpy(test_info->base_output, "Search timed out");
|
||||||
return EXIT_CRITICAL;
|
return EXIT_CRITICAL;
|
||||||
|
|
||||||
case GETDNS_RESPSTATUS_NO_SECURE_ANSWERS:
|
case GETDNS_RESPSTATUS_NO_SECURE_ANSWERS:
|
||||||
fputs("No secure answers", test_info->errout);
|
strcpy(test_info->base_output, "No secure answers");
|
||||||
return EXIT_CRITICAL;
|
return EXIT_CRITICAL;
|
||||||
|
|
||||||
case GETDNS_RESPSTATUS_ALL_BOGUS_ANSWERS:
|
case GETDNS_RESPSTATUS_ALL_BOGUS_ANSWERS:
|
||||||
fputs("All answers are bogus", test_info->errout);
|
strcpy(test_info->base_output, "All answers are bogus");
|
||||||
return EXIT_CRITICAL;
|
return EXIT_CRITICAL;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -509,14 +538,21 @@ static exit_value check_result(const struct test_info_s *test_info,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (test_info->verbosity >= VERBOSITY_ADDITIONAL){
|
if (test_info->verbosity >= VERBOSITY_ADDITIONAL){
|
||||||
fprintf(test_info->errout,
|
if (test_info->monitoring) {
|
||||||
"result: %s (%d), ",
|
snprintcat(test_info->perf_output,
|
||||||
|
MAX_PERF_OUTPUT_LEN,
|
||||||
|
"result=%d;",
|
||||||
|
error_id);
|
||||||
|
} else {
|
||||||
|
printf("DNS result:\t\t%s (%d)\n",
|
||||||
getdns_get_errorstr_by_id(error_id),
|
getdns_get_errorstr_by_id(error_id),
|
||||||
error_id);
|
error_id);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (test_info->fail_on_dns_errors && rcode > 0) {
|
if (test_info->fail_on_dns_errors && rcode > 0) {
|
||||||
fprintf(test_info->errout,
|
snprintf(test_info->base_output,
|
||||||
|
MAX_BASE_OUTPUT_LEN,
|
||||||
"DNS error %s (%d)",
|
"DNS error %s (%d)",
|
||||||
rcode_text(rcode),
|
rcode_text(rcode),
|
||||||
rcode);
|
rcode);
|
||||||
|
@ -526,7 +562,7 @@ static exit_value check_result(const struct test_info_s *test_info,
|
||||||
return EXIT_OK;
|
return EXIT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static exit_value get_report_info(const struct test_info_s *test_info,
|
static exit_value get_report_info(struct test_info_s *test_info,
|
||||||
const getdns_dict *response,
|
const getdns_dict *response,
|
||||||
uint32_t *rtt,
|
uint32_t *rtt,
|
||||||
getdns_bindata **auth_status,
|
getdns_bindata **auth_status,
|
||||||
|
@ -539,7 +575,8 @@ static exit_value get_report_info(const struct test_info_s *test_info,
|
||||||
time_t cert_expire_time_val = 0;
|
time_t cert_expire_time_val = 0;
|
||||||
|
|
||||||
if ((ret = getdns_dict_get_list(response, "call_reporting", &l)) != GETDNS_RETURN_GOOD) {
|
if ((ret = getdns_dict_get_list(response, "call_reporting", &l)) != GETDNS_RETURN_GOOD) {
|
||||||
fprintf(test_info->errout,
|
snprintf(test_info->base_output,
|
||||||
|
MAX_BASE_OUTPUT_LEN,
|
||||||
"Cannot get call report: %s (%d)",
|
"Cannot get call report: %s (%d)",
|
||||||
getdns_get_errorstr_by_id(ret),
|
getdns_get_errorstr_by_id(ret),
|
||||||
ret);
|
ret);
|
||||||
|
@ -547,8 +584,10 @@ static exit_value get_report_info(const struct test_info_s *test_info,
|
||||||
}
|
}
|
||||||
|
|
||||||
getdns_dict *d;
|
getdns_dict *d;
|
||||||
|
|
||||||
if ((ret = getdns_list_get_dict(l, 0, &d)) != GETDNS_RETURN_GOOD) {
|
if ((ret = getdns_list_get_dict(l, 0, &d)) != GETDNS_RETURN_GOOD) {
|
||||||
fprintf(test_info->errout,
|
snprintf(test_info->base_output,
|
||||||
|
MAX_BASE_OUTPUT_LEN,
|
||||||
"Cannot get call report first item: %s (%d)",
|
"Cannot get call report first item: %s (%d)",
|
||||||
getdns_get_errorstr_by_id(ret),
|
getdns_get_errorstr_by_id(ret),
|
||||||
ret);
|
ret);
|
||||||
|
@ -556,33 +595,44 @@ static exit_value get_report_info(const struct test_info_s *test_info,
|
||||||
}
|
}
|
||||||
if (test_info->verbosity >= VERBOSITY_ADDITIONAL) {
|
if (test_info->verbosity >= VERBOSITY_ADDITIONAL) {
|
||||||
uint32_t transport;
|
uint32_t transport;
|
||||||
|
const char *transport_text = "???";
|
||||||
|
|
||||||
if ((ret = getdns_dict_get_int(d, "transport", &transport)) != GETDNS_RETURN_GOOD) {
|
if ((ret = getdns_dict_get_int(d, "transport", &transport)) != GETDNS_RETURN_GOOD) {
|
||||||
fprintf(test_info->errout,
|
snprintf(test_info->base_output,
|
||||||
|
MAX_BASE_OUTPUT_LEN,
|
||||||
"Cannot get transport: %s (%d)",
|
"Cannot get transport: %s (%d)",
|
||||||
getdns_get_errorstr_by_id(ret),
|
getdns_get_errorstr_by_id(ret),
|
||||||
ret);
|
ret);
|
||||||
return EXIT_UNKNOWN;
|
return EXIT_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(transport) {
|
switch(transport) {
|
||||||
case GETDNS_TRANSPORT_UDP:
|
case GETDNS_TRANSPORT_UDP:
|
||||||
fputs("UDP, ", test_info->errout);
|
transport_text = "UDP";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GETDNS_TRANSPORT_TCP:
|
case GETDNS_TRANSPORT_TCP:
|
||||||
fputs("TCP, ", test_info->errout);
|
transport_text = "TCP";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GETDNS_TRANSPORT_TLS:
|
case GETDNS_TRANSPORT_TLS:
|
||||||
fputs("TLS, ", test_info->errout);
|
transport_text = "TLS";
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
if (test_info->monitoring) {
|
||||||
fputs("???, ", test_info->errout);
|
snprintcat(test_info->perf_output,
|
||||||
break;
|
MAX_PERF_OUTPUT_LEN,
|
||||||
|
"transport=%s;",
|
||||||
|
transport_text);
|
||||||
|
} else {
|
||||||
|
printf("Transport:\t\t%s\n", transport_text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ret = getdns_dict_get_int(d, "run_time/ms", &rtt_val)) != GETDNS_RETURN_GOOD) {
|
if ((ret = getdns_dict_get_int(d, "run_time/ms", &rtt_val)) != GETDNS_RETURN_GOOD) {
|
||||||
fprintf(test_info->errout,
|
snprintf(test_info->base_output,
|
||||||
|
MAX_BASE_OUTPUT_LEN,
|
||||||
"Cannot get RTT: %s (%d)",
|
"Cannot get RTT: %s (%d)",
|
||||||
getdns_get_errorstr_by_id(ret),
|
getdns_get_errorstr_by_id(ret),
|
||||||
ret);
|
ret);
|
||||||
|
@ -590,29 +640,55 @@ static exit_value get_report_info(const struct test_info_s *test_info,
|
||||||
}
|
}
|
||||||
if (rtt)
|
if (rtt)
|
||||||
*rtt = rtt_val;
|
*rtt = rtt_val;
|
||||||
if (test_info->verbosity >= VERBOSITY_ADDITIONAL)
|
if (test_info->verbosity >= VERBOSITY_ADDITIONAL) {
|
||||||
fprintf(test_info->errout, "RTT %dms, ", rtt_val);
|
if (test_info->monitoring) {
|
||||||
|
snprintcat(test_info->perf_output,
|
||||||
|
MAX_PERF_OUTPUT_LEN,
|
||||||
|
"rtt=%dms;",
|
||||||
|
rtt_val);
|
||||||
|
} else {
|
||||||
|
printf("RTT:\t\t\t%dms\n", rtt_val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (getdns_dict_get_bindata(d, "tls_auth_status", &auth_status_val) == GETDNS_RETURN_GOOD) {
|
if (getdns_dict_get_bindata(d, "tls_auth_status", &auth_status_val) == GETDNS_RETURN_GOOD) {
|
||||||
|
const char *auth_status_text = (char *) auth_status_val->data;
|
||||||
|
|
||||||
/* Just in case - not sure this is necessary */
|
/* Just in case - not sure this is necessary */
|
||||||
auth_status_val->data[auth_status_val->size] = '\0';
|
auth_status_val->data[auth_status_val->size] = '\0';
|
||||||
if (test_info->verbosity >= VERBOSITY_ADDITIONAL)
|
if (test_info->verbosity >= VERBOSITY_ADDITIONAL) {
|
||||||
fprintf(test_info->errout, "auth. %s, ", (char *) auth_status_val->data);
|
if (test_info->monitoring) {
|
||||||
|
snprintcat(test_info->perf_output,
|
||||||
|
MAX_PERF_OUTPUT_LEN,
|
||||||
|
"auth=%s;",
|
||||||
|
auth_status_text);
|
||||||
|
} else {
|
||||||
|
printf("Authentication:\t\t%s\n", auth_status_text);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (auth_status)
|
if (auth_status)
|
||||||
*auth_status = auth_status_val;
|
*auth_status = auth_status_val;
|
||||||
|
|
||||||
getdns_bindata *cert;
|
getdns_bindata *cert;
|
||||||
|
|
||||||
if (getdns_dict_get_bindata(d, "tls_peer_cert", &cert) == GETDNS_RETURN_GOOD) {
|
if (getdns_dict_get_bindata(d, "tls_peer_cert", &cert) == GETDNS_RETURN_GOOD) {
|
||||||
if (!extract_cert_expiry(cert->data, cert->size, &cert_expire_time_val)) {
|
if (!extract_cert_expiry(cert->data, cert->size, &cert_expire_time_val)) {
|
||||||
fputs("Cannot parse PKIX certificate", test_info->errout);
|
strcpy(test_info->base_output, "Cannot parse PKIX certificate");
|
||||||
return EXIT_UNKNOWN;
|
return EXIT_UNKNOWN;
|
||||||
}
|
}
|
||||||
if (test_info->verbosity >= VERBOSITY_ADDITIONAL) {
|
if (test_info->verbosity >= VERBOSITY_ADDITIONAL) {
|
||||||
struct tm *tm = gmtime(&cert_expire_time_val);
|
struct tm *tm = gmtime(&cert_expire_time_val);
|
||||||
char buf[25];
|
char buf[25];
|
||||||
strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S UTC", tm);
|
strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", tm);
|
||||||
fprintf(test_info->errout, "cert expiry %s, ", buf);
|
if (test_info->monitoring) {
|
||||||
|
snprintcat(test_info->perf_output,
|
||||||
|
MAX_PERF_OUTPUT_LEN,
|
||||||
|
"expire=%s;",
|
||||||
|
buf);
|
||||||
|
} else {
|
||||||
|
printf("Certicate expires:\t%s UTC\n", buf);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (cert_expire_time)
|
if (cert_expire_time)
|
||||||
|
@ -621,7 +697,7 @@ static exit_value get_report_info(const struct test_info_s *test_info,
|
||||||
return EXIT_OK;
|
return EXIT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static exit_value get_answers(const struct test_info_s *test_info,
|
static exit_value get_answers(struct test_info_s *test_info,
|
||||||
const getdns_dict *response,
|
const getdns_dict *response,
|
||||||
const char *section,
|
const char *section,
|
||||||
getdns_list **answers,
|
getdns_list **answers,
|
||||||
|
@ -633,7 +709,8 @@ static exit_value get_answers(const struct test_info_s *test_info,
|
||||||
snprintf(buf, sizeof(buf), "/replies_tree/0/%s", section);
|
snprintf(buf, sizeof(buf), "/replies_tree/0/%s", section);
|
||||||
|
|
||||||
if ((ret = getdns_dict_get_list(response, buf, answers)) != GETDNS_RETURN_GOOD) {
|
if ((ret = getdns_dict_get_list(response, buf, answers)) != GETDNS_RETURN_GOOD) {
|
||||||
fprintf(test_info->errout,
|
snprintf(test_info->base_output,
|
||||||
|
MAX_BASE_OUTPUT_LEN,
|
||||||
"Cannot get section '%s': %s (%d)",
|
"Cannot get section '%s': %s (%d)",
|
||||||
section,
|
section,
|
||||||
getdns_get_errorstr_by_id(ret),
|
getdns_get_errorstr_by_id(ret),
|
||||||
|
@ -642,7 +719,8 @@ static exit_value get_answers(const struct test_info_s *test_info,
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ret = getdns_list_get_length(*answers, no_answers)) != GETDNS_RETURN_GOOD) {
|
if ((ret = getdns_list_get_length(*answers, no_answers)) != GETDNS_RETURN_GOOD) {
|
||||||
fprintf(test_info->errout,
|
snprintf(test_info->base_output,
|
||||||
|
MAX_BASE_OUTPUT_LEN,
|
||||||
"Cannot get number of items in '%s': %s (%d)",
|
"Cannot get number of items in '%s': %s (%d)",
|
||||||
section,
|
section,
|
||||||
getdns_get_errorstr_by_id(ret),
|
getdns_get_errorstr_by_id(ret),
|
||||||
|
@ -650,7 +728,8 @@ static exit_value get_answers(const struct test_info_s *test_info,
|
||||||
return EXIT_UNKNOWN;
|
return EXIT_UNKNOWN;
|
||||||
}
|
}
|
||||||
if (*no_answers <= 0) {
|
if (*no_answers <= 0) {
|
||||||
fprintf(test_info->errout,
|
snprintf(test_info->base_output,
|
||||||
|
MAX_BASE_OUTPUT_LEN,
|
||||||
"Zero entries in '%s'",
|
"Zero entries in '%s'",
|
||||||
section);
|
section);
|
||||||
return EXIT_WARNING;
|
return EXIT_WARNING;
|
||||||
|
@ -659,7 +738,7 @@ static exit_value get_answers(const struct test_info_s *test_info,
|
||||||
return EXIT_OK;
|
return EXIT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static exit_value check_answer_type(const struct test_info_s *test_info,
|
static exit_value check_answer_type(struct test_info_s *test_info,
|
||||||
const getdns_dict *response,
|
const getdns_dict *response,
|
||||||
uint32_t rrtype)
|
uint32_t rrtype)
|
||||||
{
|
{
|
||||||
|
@ -675,7 +754,8 @@ static exit_value check_answer_type(const struct test_info_s *test_info,
|
||||||
getdns_return_t ret;
|
getdns_return_t ret;
|
||||||
|
|
||||||
if ((ret = getdns_list_get_dict(answers, i, &answer)) != GETDNS_RETURN_GOOD) {
|
if ((ret = getdns_list_get_dict(answers, i, &answer)) != GETDNS_RETURN_GOOD) {
|
||||||
fprintf(test_info->errout,
|
snprintf(test_info->base_output,
|
||||||
|
MAX_BASE_OUTPUT_LEN,
|
||||||
"Cannot get answer number %zu: %s (%d)",
|
"Cannot get answer number %zu: %s (%d)",
|
||||||
i,
|
i,
|
||||||
getdns_get_errorstr_by_id(ret),
|
getdns_get_errorstr_by_id(ret),
|
||||||
|
@ -686,7 +766,8 @@ static exit_value check_answer_type(const struct test_info_s *test_info,
|
||||||
uint32_t rtype;
|
uint32_t rtype;
|
||||||
|
|
||||||
if ((ret = getdns_dict_get_int(answer, "type", &rtype)) != GETDNS_RETURN_GOOD) {
|
if ((ret = getdns_dict_get_int(answer, "type", &rtype)) != GETDNS_RETURN_GOOD) {
|
||||||
fprintf(test_info->errout,
|
snprintf(test_info->base_output,
|
||||||
|
MAX_BASE_OUTPUT_LEN,
|
||||||
"Cannot get answer type: %s (%d)",
|
"Cannot get answer type: %s (%d)",
|
||||||
getdns_get_errorstr_by_id(ret),
|
getdns_get_errorstr_by_id(ret),
|
||||||
ret);
|
ret);
|
||||||
|
@ -696,11 +777,11 @@ static exit_value check_answer_type(const struct test_info_s *test_info,
|
||||||
return EXIT_OK;
|
return EXIT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
fputs("Answer does not contain expected type", test_info->errout);
|
strcpy(test_info->base_output, "Answer does not contain expected type");
|
||||||
return EXIT_UNKNOWN;
|
return EXIT_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
static exit_value search_check(const struct test_info_s *test_info,
|
static exit_value search_check(struct test_info_s *test_info,
|
||||||
const char *lookup_name,
|
const char *lookup_name,
|
||||||
uint16_t lookup_type,
|
uint16_t lookup_type,
|
||||||
getdns_dict **response,
|
getdns_dict **response,
|
||||||
|
@ -728,7 +809,7 @@ static exit_value search_check(const struct test_info_s *test_info,
|
||||||
return xit;
|
return xit;
|
||||||
}
|
}
|
||||||
|
|
||||||
static exit_value parse_search_check(const struct test_info_s *test_info,
|
static exit_value parse_search_check(struct test_info_s *test_info,
|
||||||
char **av,
|
char **av,
|
||||||
const char *usage,
|
const char *usage,
|
||||||
getdns_dict **response,
|
getdns_dict **response,
|
||||||
|
@ -744,7 +825,7 @@ static exit_value parse_search_check(const struct test_info_s *test_info,
|
||||||
return xit;
|
return xit;
|
||||||
|
|
||||||
if (*av) {
|
if (*av) {
|
||||||
fputs(usage, test_info->errout);
|
strcpy(test_info->base_output, usage);
|
||||||
return EXIT_USAGE;
|
return EXIT_USAGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -758,7 +839,7 @@ static exit_value parse_search_check(const struct test_info_s *test_info,
|
||||||
** Test routines.
|
** Test routines.
|
||||||
**/
|
**/
|
||||||
|
|
||||||
static exit_value test_lookup(const struct test_info_s *test_info,
|
static exit_value test_lookup(struct test_info_s *test_info,
|
||||||
char ** av)
|
char ** av)
|
||||||
{
|
{
|
||||||
exit_value xit;
|
exit_value xit;
|
||||||
|
@ -772,11 +853,11 @@ static exit_value test_lookup(const struct test_info_s *test_info,
|
||||||
NULL)) != EXIT_OK)
|
NULL)) != EXIT_OK)
|
||||||
return xit;
|
return xit;
|
||||||
|
|
||||||
fputs("Lookup succeeded", test_info->errout);
|
strcpy(test_info->base_output, "Lookup succeeded");
|
||||||
return EXIT_OK;
|
return EXIT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static exit_value test_rtt(const struct test_info_s *test_info,
|
static exit_value test_rtt(struct test_info_s *test_info,
|
||||||
char ** av)
|
char ** av)
|
||||||
{
|
{
|
||||||
exit_value xit;
|
exit_value xit;
|
||||||
|
@ -795,7 +876,10 @@ static exit_value test_rtt(const struct test_info_s *test_info,
|
||||||
NULL)) != EXIT_OK)
|
NULL)) != EXIT_OK)
|
||||||
return xit;
|
return xit;
|
||||||
|
|
||||||
fputs("RTT lookup succeeded", test_info->errout);
|
snprintf(test_info->base_output,
|
||||||
|
MAX_BASE_OUTPUT_LEN,
|
||||||
|
"RTT lookup succeeded in %dms",
|
||||||
|
rtt_val);
|
||||||
|
|
||||||
if ((int) rtt_val > critical_ms)
|
if ((int) rtt_val > critical_ms)
|
||||||
return EXIT_CRITICAL;
|
return EXIT_CRITICAL;
|
||||||
|
@ -804,7 +888,7 @@ static exit_value test_rtt(const struct test_info_s *test_info,
|
||||||
return EXIT_OK;
|
return EXIT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static exit_value test_authenticate(const struct test_info_s *test_info,
|
static exit_value test_authenticate(struct test_info_s *test_info,
|
||||||
char ** av)
|
char ** av)
|
||||||
{
|
{
|
||||||
exit_value xit;
|
exit_value xit;
|
||||||
|
@ -820,15 +904,15 @@ static exit_value test_authenticate(const struct test_info_s *test_info,
|
||||||
return xit;
|
return xit;
|
||||||
|
|
||||||
if (!auth_status || strcmp((char *) auth_status->data, "Success") != 0) {
|
if (!auth_status || strcmp((char *) auth_status->data, "Success") != 0) {
|
||||||
fputs("Authentication failed", test_info->errout);
|
strcpy(test_info->base_output, "Authentication failed");
|
||||||
return EXIT_CRITICAL;
|
return EXIT_CRITICAL;
|
||||||
} else {
|
} else {
|
||||||
fputs("Authentication succeeded", test_info->errout);
|
strcpy(test_info->base_output, "Authentication succeeded");
|
||||||
return EXIT_OK;
|
return EXIT_OK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static exit_value test_certificate_valid(const struct test_info_s *test_info,
|
static exit_value test_certificate_valid(struct test_info_s *test_info,
|
||||||
char **av)
|
char **av)
|
||||||
{
|
{
|
||||||
exit_value xit;
|
exit_value xit;
|
||||||
|
@ -849,7 +933,7 @@ static exit_value test_certificate_valid(const struct test_info_s *test_info,
|
||||||
|
|
||||||
|
|
||||||
if (expire_time == 0) {
|
if (expire_time == 0) {
|
||||||
fputs("No PKIX certificate", test_info->errout);
|
strcpy(test_info->base_output, "No PKIX certificate");
|
||||||
return EXIT_CRITICAL;
|
return EXIT_CRITICAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -857,16 +941,18 @@ static exit_value test_certificate_valid(const struct test_info_s *test_info,
|
||||||
int days_to_expiry = (expire_time - now) / 86400;
|
int days_to_expiry = (expire_time - now) / 86400;
|
||||||
|
|
||||||
if (days_to_expiry < 0) {
|
if (days_to_expiry < 0) {
|
||||||
fprintf(test_info->errout,
|
snprintf(test_info->base_output,
|
||||||
|
MAX_BASE_OUTPUT_LEN,
|
||||||
"Certificate expired %d day%s ago",
|
"Certificate expired %d day%s ago",
|
||||||
-days_to_expiry,
|
-days_to_expiry,
|
||||||
(days_to_expiry < -1) ? "s" : "");
|
(days_to_expiry < -1) ? "s" : "");
|
||||||
return EXIT_CRITICAL;
|
return EXIT_CRITICAL;
|
||||||
}
|
}
|
||||||
if (days_to_expiry == 0) {
|
if (days_to_expiry == 0) {
|
||||||
fputs("Certificate expires today", test_info->errout);
|
strcpy(test_info->base_output, "Certificate expires today");
|
||||||
} else {
|
} else {
|
||||||
fprintf(test_info->errout,
|
snprintf(test_info->base_output,
|
||||||
|
MAX_BASE_OUTPUT_LEN,
|
||||||
"Certificate will expire in %d day%s",
|
"Certificate will expire in %d day%s",
|
||||||
days_to_expiry,
|
days_to_expiry,
|
||||||
(days_to_expiry > 1) ? "s" : "");
|
(days_to_expiry > 1) ? "s" : "");
|
||||||
|
@ -880,12 +966,11 @@ static exit_value test_certificate_valid(const struct test_info_s *test_info,
|
||||||
return EXIT_OK;
|
return EXIT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static exit_value test_qname_minimisation(const struct test_info_s *test_info,
|
static exit_value test_qname_minimisation(struct test_info_s *test_info,
|
||||||
char ** av)
|
char ** av)
|
||||||
{
|
{
|
||||||
if (*av) {
|
if (*av) {
|
||||||
fputs("qname-min takes no arguments",
|
strcpy(test_info->base_output, "qname-min takes no arguments");
|
||||||
test_info->errout);
|
|
||||||
return EXIT_USAGE;
|
return EXIT_USAGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -912,7 +997,8 @@ static exit_value test_qname_minimisation(const struct test_info_s *test_info,
|
||||||
getdns_return_t ret;
|
getdns_return_t ret;
|
||||||
|
|
||||||
if ((ret = getdns_list_get_dict(answers, i, &answer)) != GETDNS_RETURN_GOOD) {
|
if ((ret = getdns_list_get_dict(answers, i, &answer)) != GETDNS_RETURN_GOOD) {
|
||||||
fprintf(test_info->errout,
|
snprintf(test_info->base_output,
|
||||||
|
MAX_BASE_OUTPUT_LEN,
|
||||||
"Cannot get answer number %zu: %s (%d)",
|
"Cannot get answer number %zu: %s (%d)",
|
||||||
i,
|
i,
|
||||||
getdns_get_errorstr_by_id(ret),
|
getdns_get_errorstr_by_id(ret),
|
||||||
|
@ -923,7 +1009,8 @@ static exit_value test_qname_minimisation(const struct test_info_s *test_info,
|
||||||
uint32_t rtype;
|
uint32_t rtype;
|
||||||
|
|
||||||
if ((ret = getdns_dict_get_int(answer, "type", &rtype)) != GETDNS_RETURN_GOOD) {
|
if ((ret = getdns_dict_get_int(answer, "type", &rtype)) != GETDNS_RETURN_GOOD) {
|
||||||
fprintf(test_info->errout,
|
snprintf(test_info->base_output,
|
||||||
|
MAX_BASE_OUTPUT_LEN,
|
||||||
"Cannot get answer type: %s (%d)",
|
"Cannot get answer type: %s (%d)",
|
||||||
getdns_get_errorstr_by_id(ret),
|
getdns_get_errorstr_by_id(ret),
|
||||||
ret);
|
ret);
|
||||||
|
@ -935,19 +1022,19 @@ static exit_value test_qname_minimisation(const struct test_info_s *test_info,
|
||||||
getdns_bindata *rtxt;
|
getdns_bindata *rtxt;
|
||||||
|
|
||||||
if ((ret = getdns_dict_get_bindata(answer, "/rdata/txt_strings/0", &rtxt)) != GETDNS_RETURN_GOOD) {
|
if ((ret = getdns_dict_get_bindata(answer, "/rdata/txt_strings/0", &rtxt)) != GETDNS_RETURN_GOOD) {
|
||||||
fputs("No answer text", test_info->errout);
|
strcpy(test_info->base_output, "No answer text");
|
||||||
return EXIT_UNKNOWN;
|
return EXIT_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rtxt->size > 0 ) {
|
if (rtxt->size > 0 ) {
|
||||||
switch(rtxt->data[0]) {
|
switch(rtxt->data[0]) {
|
||||||
case 'H':
|
case 'H':
|
||||||
fputs("QNAME minimisation ON", test_info->errout);
|
strcpy(test_info->base_output, "QNAME minimisation ON");
|
||||||
return EXIT_OK;
|
return EXIT_OK;
|
||||||
|
|
||||||
case 'N':
|
case 'N':
|
||||||
fputs("QNAME minimisation OFF", test_info->errout);
|
strcpy(test_info->base_output, "QNAME minimisation OFF");
|
||||||
return EXIT_WARNING;
|
return EXIT_CRITICAL;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
/* Unrecognised message. */
|
/* Unrecognised message. */
|
||||||
|
@ -956,11 +1043,11 @@ static exit_value test_qname_minimisation(const struct test_info_s *test_info,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fputs("No valid QNAME minimisation data", test_info->errout);
|
strcpy(test_info->base_output, "No valid QNAME minimisation data");
|
||||||
return EXIT_UNKNOWN;
|
return EXIT_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
static exit_value test_padding(const struct test_info_s *test_info,
|
static exit_value test_padding(struct test_info_s *test_info,
|
||||||
char ** av)
|
char ** av)
|
||||||
{
|
{
|
||||||
getdns_dict *response;
|
getdns_dict *response;
|
||||||
|
@ -970,14 +1057,15 @@ static exit_value test_padding(const struct test_info_s *test_info,
|
||||||
const char USAGE[] = "padding takes arguments <blocksize> [<name> [<type>]]";
|
const char USAGE[] = "padding takes arguments <blocksize> [<name> [<type>]]";
|
||||||
|
|
||||||
if (!*av || (blocksize = strtol(*av, &endptr, 10), *endptr != '\0' || blocksize < 0)) {
|
if (!*av || (blocksize = strtol(*av, &endptr, 10), *endptr != '\0' || blocksize < 0)) {
|
||||||
fputs(USAGE, test_info->errout);
|
strcpy(test_info->base_output, USAGE);
|
||||||
return EXIT_USAGE;
|
return EXIT_USAGE;
|
||||||
}
|
}
|
||||||
++av;
|
++av;
|
||||||
|
|
||||||
getdns_return_t ret;
|
getdns_return_t ret;
|
||||||
if ((ret = getdns_context_set_tls_query_padding_blocksize(test_info->context, (uint16_t) blocksize)) != GETDNS_RETURN_GOOD) {
|
if ((ret = getdns_context_set_tls_query_padding_blocksize(test_info->context, (uint16_t) blocksize)) != GETDNS_RETURN_GOOD) {
|
||||||
fprintf(test_info->errout,
|
snprintf(test_info->base_output,
|
||||||
|
MAX_BASE_OUTPUT_LEN,
|
||||||
"Cannot set padding blocksize: %s (%d)",
|
"Cannot set padding blocksize: %s (%d)",
|
||||||
getdns_get_errorstr_by_id(ret),
|
getdns_get_errorstr_by_id(ret),
|
||||||
ret);
|
ret);
|
||||||
|
@ -1004,7 +1092,8 @@ static exit_value test_padding(const struct test_info_s *test_info,
|
||||||
getdns_return_t ret;
|
getdns_return_t ret;
|
||||||
|
|
||||||
if ((ret = getdns_list_get_dict(answers, i, &answer)) != GETDNS_RETURN_GOOD) {
|
if ((ret = getdns_list_get_dict(answers, i, &answer)) != GETDNS_RETURN_GOOD) {
|
||||||
fprintf(test_info->errout,
|
snprintf(test_info->base_output,
|
||||||
|
MAX_BASE_OUTPUT_LEN,
|
||||||
"Cannot get answer number %zu: %s (%d)",
|
"Cannot get answer number %zu: %s (%d)",
|
||||||
i,
|
i,
|
||||||
getdns_get_errorstr_by_id(ret),
|
getdns_get_errorstr_by_id(ret),
|
||||||
|
@ -1015,7 +1104,8 @@ static exit_value test_padding(const struct test_info_s *test_info,
|
||||||
uint32_t rtype;
|
uint32_t rtype;
|
||||||
|
|
||||||
if ((ret = getdns_dict_get_int(answer, "type", &rtype)) != GETDNS_RETURN_GOOD) {
|
if ((ret = getdns_dict_get_int(answer, "type", &rtype)) != GETDNS_RETURN_GOOD) {
|
||||||
fprintf(test_info->errout,
|
snprintf(test_info->base_output,
|
||||||
|
MAX_BASE_OUTPUT_LEN,
|
||||||
"Cannot get answer type: %s (%d)",
|
"Cannot get answer type: %s (%d)",
|
||||||
getdns_get_errorstr_by_id(ret),
|
getdns_get_errorstr_by_id(ret),
|
||||||
ret);
|
ret);
|
||||||
|
@ -1031,7 +1121,8 @@ static exit_value test_padding(const struct test_info_s *test_info,
|
||||||
goto no_padding;
|
goto no_padding;
|
||||||
}
|
}
|
||||||
if ((ret = getdns_list_get_length(options, &no_options)) != GETDNS_RETURN_GOOD) {
|
if ((ret = getdns_list_get_length(options, &no_options)) != GETDNS_RETURN_GOOD) {
|
||||||
fprintf(test_info->errout,
|
snprintf(test_info->base_output,
|
||||||
|
MAX_BASE_OUTPUT_LEN,
|
||||||
"Cannot get number of options: %s (%d)",
|
"Cannot get number of options: %s (%d)",
|
||||||
getdns_get_errorstr_by_id(ret),
|
getdns_get_errorstr_by_id(ret),
|
||||||
ret);
|
ret);
|
||||||
|
@ -1043,7 +1134,8 @@ static exit_value test_padding(const struct test_info_s *test_info,
|
||||||
uint32_t code;
|
uint32_t code;
|
||||||
|
|
||||||
if ((ret = getdns_list_get_dict(options, j, &option)) != GETDNS_RETURN_GOOD) {
|
if ((ret = getdns_list_get_dict(options, j, &option)) != GETDNS_RETURN_GOOD) {
|
||||||
fprintf(test_info->errout,
|
snprintf(test_info->base_output,
|
||||||
|
MAX_BASE_OUTPUT_LEN,
|
||||||
"Cannot get option number %zu: %s (%d)",
|
"Cannot get option number %zu: %s (%d)",
|
||||||
j,
|
j,
|
||||||
getdns_get_errorstr_by_id(ret),
|
getdns_get_errorstr_by_id(ret),
|
||||||
|
@ -1051,7 +1143,8 @@ static exit_value test_padding(const struct test_info_s *test_info,
|
||||||
return EXIT_UNKNOWN;
|
return EXIT_UNKNOWN;
|
||||||
}
|
}
|
||||||
if ((ret = getdns_dict_get_int(option, "option_code", &code)) != GETDNS_RETURN_GOOD) {
|
if ((ret = getdns_dict_get_int(option, "option_code", &code)) != GETDNS_RETURN_GOOD) {
|
||||||
fprintf(test_info->errout,
|
snprintf(test_info->base_output,
|
||||||
|
MAX_BASE_OUTPUT_LEN,
|
||||||
"Cannot get option code: %s (%d)",
|
"Cannot get option code: %s (%d)",
|
||||||
getdns_get_errorstr_by_id(ret),
|
getdns_get_errorstr_by_id(ret),
|
||||||
ret);
|
ret);
|
||||||
|
@ -1065,14 +1158,16 @@ static exit_value test_padding(const struct test_info_s *test_info,
|
||||||
getdns_bindata *data;
|
getdns_bindata *data;
|
||||||
|
|
||||||
if ((ret = getdns_dict_get_bindata(option, "option_data", &data)) != GETDNS_RETURN_GOOD) {
|
if ((ret = getdns_dict_get_bindata(option, "option_data", &data)) != GETDNS_RETURN_GOOD) {
|
||||||
fprintf(test_info->errout,
|
snprintf(test_info->base_output,
|
||||||
|
MAX_BASE_OUTPUT_LEN,
|
||||||
"Cannot get option code: %s (%d)",
|
"Cannot get option code: %s (%d)",
|
||||||
getdns_get_errorstr_by_id(ret),
|
getdns_get_errorstr_by_id(ret),
|
||||||
ret);
|
ret);
|
||||||
return EXIT_UNKNOWN;
|
return EXIT_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(test_info->errout,
|
snprintf(test_info->base_output,
|
||||||
|
MAX_BASE_OUTPUT_LEN,
|
||||||
"Padding found, length %zu",
|
"Padding found, length %zu",
|
||||||
data->size);
|
data->size);
|
||||||
return EXIT_OK;
|
return EXIT_OK;
|
||||||
|
@ -1080,11 +1175,11 @@ static exit_value test_padding(const struct test_info_s *test_info,
|
||||||
}
|
}
|
||||||
|
|
||||||
no_padding:
|
no_padding:
|
||||||
fputs("No padding found", test_info->errout);
|
strcpy(test_info->base_output, "No padding found");
|
||||||
return EXIT_CRITICAL;
|
return EXIT_CRITICAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static exit_value test_keepalive(const struct test_info_s *test_info,
|
static exit_value test_keepalive(struct test_info_s *test_info,
|
||||||
char ** av)
|
char ** av)
|
||||||
{
|
{
|
||||||
getdns_dict *response;
|
getdns_dict *response;
|
||||||
|
@ -1094,14 +1189,15 @@ static exit_value test_keepalive(const struct test_info_s *test_info,
|
||||||
const char USAGE[] = "keepalive takes arguments <timeout-ms> [<name> [<type>]]";
|
const char USAGE[] = "keepalive takes arguments <timeout-ms> [<name> [<type>]]";
|
||||||
|
|
||||||
if (!*av || (timeout = strtoll(*av, &endptr, 10), *endptr != '\0' || timeout < 0)) {
|
if (!*av || (timeout = strtoll(*av, &endptr, 10), *endptr != '\0' || timeout < 0)) {
|
||||||
fputs(USAGE, test_info->errout);
|
strcpy(test_info->base_output, USAGE);
|
||||||
return EXIT_USAGE;
|
return EXIT_USAGE;
|
||||||
}
|
}
|
||||||
++av;
|
++av;
|
||||||
|
|
||||||
getdns_return_t ret;
|
getdns_return_t ret;
|
||||||
if ((ret = getdns_context_set_idle_timeout(test_info->context, (uint64_t) timeout)) != GETDNS_RETURN_GOOD) {
|
if ((ret = getdns_context_set_idle_timeout(test_info->context, (uint64_t) timeout)) != GETDNS_RETURN_GOOD) {
|
||||||
fprintf(test_info->errout,
|
snprintf(test_info->base_output,
|
||||||
|
MAX_BASE_OUTPUT_LEN,
|
||||||
"Cannot set keepalive timeout: %s (%d)",
|
"Cannot set keepalive timeout: %s (%d)",
|
||||||
getdns_get_errorstr_by_id(ret),
|
getdns_get_errorstr_by_id(ret),
|
||||||
ret);
|
ret);
|
||||||
|
@ -1120,7 +1216,8 @@ static exit_value test_keepalive(const struct test_info_s *test_info,
|
||||||
getdns_list *l;
|
getdns_list *l;
|
||||||
|
|
||||||
if ((ret = getdns_dict_get_list(response, "call_reporting", &l)) != GETDNS_RETURN_GOOD) {
|
if ((ret = getdns_dict_get_list(response, "call_reporting", &l)) != GETDNS_RETURN_GOOD) {
|
||||||
fprintf(test_info->errout,
|
snprintf(test_info->base_output,
|
||||||
|
MAX_BASE_OUTPUT_LEN,
|
||||||
"Cannot get call report: %s (%d)",
|
"Cannot get call report: %s (%d)",
|
||||||
getdns_get_errorstr_by_id(ret),
|
getdns_get_errorstr_by_id(ret),
|
||||||
ret);
|
ret);
|
||||||
|
@ -1129,7 +1226,8 @@ static exit_value test_keepalive(const struct test_info_s *test_info,
|
||||||
|
|
||||||
getdns_dict *d;
|
getdns_dict *d;
|
||||||
if ((ret = getdns_list_get_dict(l, 0, &d)) != GETDNS_RETURN_GOOD) {
|
if ((ret = getdns_list_get_dict(l, 0, &d)) != GETDNS_RETURN_GOOD) {
|
||||||
fprintf(test_info->errout,
|
snprintf(test_info->base_output,
|
||||||
|
MAX_BASE_OUTPUT_LEN,
|
||||||
"Cannot get call report first item: %s (%d)",
|
"Cannot get call report first item: %s (%d)",
|
||||||
getdns_get_errorstr_by_id(ret),
|
getdns_get_errorstr_by_id(ret),
|
||||||
ret);
|
ret);
|
||||||
|
@ -1139,7 +1237,8 @@ static exit_value test_keepalive(const struct test_info_s *test_info,
|
||||||
/* Search is forced to be TCP or TLS, so server keepalive flag must exist. */
|
/* Search is forced to be TCP or TLS, so server keepalive flag must exist. */
|
||||||
uint32_t server_keepalive_received;
|
uint32_t server_keepalive_received;
|
||||||
if ((ret = getdns_dict_get_int(d, "server_keepalive_received", &server_keepalive_received)) != GETDNS_RETURN_GOOD) {
|
if ((ret = getdns_dict_get_int(d, "server_keepalive_received", &server_keepalive_received)) != GETDNS_RETURN_GOOD) {
|
||||||
fprintf(test_info->errout,
|
snprintf(test_info->base_output,
|
||||||
|
MAX_BASE_OUTPUT_LEN,
|
||||||
"Cannot get server keepalive flag: %s (%d)",
|
"Cannot get server keepalive flag: %s (%d)",
|
||||||
getdns_get_errorstr_by_id(ret),
|
getdns_get_errorstr_by_id(ret),
|
||||||
ret);
|
ret);
|
||||||
|
@ -1152,7 +1251,8 @@ static exit_value test_keepalive(const struct test_info_s *test_info,
|
||||||
|
|
||||||
if (!((ret = getdns_dict_get_int(d, "idle timeout in ms", &t)) == GETDNS_RETURN_GOOD ||
|
if (!((ret = getdns_dict_get_int(d, "idle timeout in ms", &t)) == GETDNS_RETURN_GOOD ||
|
||||||
(overflow = true, ret = getdns_dict_get_int(d, "idle timeout in ms (overflow)", &t)) == GETDNS_RETURN_GOOD)) {
|
(overflow = true, ret = getdns_dict_get_int(d, "idle timeout in ms (overflow)", &t)) == GETDNS_RETURN_GOOD)) {
|
||||||
fprintf(test_info->errout,
|
snprintf(test_info->base_output,
|
||||||
|
MAX_BASE_OUTPUT_LEN,
|
||||||
"Cannot get idle timeout: %s (%d)",
|
"Cannot get idle timeout: %s (%d)",
|
||||||
getdns_get_errorstr_by_id(ret),
|
getdns_get_errorstr_by_id(ret),
|
||||||
ret);
|
ret);
|
||||||
|
@ -1160,23 +1260,25 @@ static exit_value test_keepalive(const struct test_info_s *test_info,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (overflow) {
|
if (overflow) {
|
||||||
fputs("Server sent keepalive, idle timeout now (overflow)", test_info->errout);
|
strcpy(test_info->base_output, "Server sent keepalive, idle timeout now (overflow)");
|
||||||
} else {
|
} else {
|
||||||
fprintf(test_info->errout, "Server sent keepalive, idle timeout now %ums", t);
|
snprintf(test_info->base_output,
|
||||||
|
MAX_BASE_OUTPUT_LEN,
|
||||||
|
"Server sent keepalive, idle timeout now %ums",
|
||||||
|
t);
|
||||||
}
|
}
|
||||||
return EXIT_OK;
|
return EXIT_OK;
|
||||||
} else {
|
} else {
|
||||||
fputs("Server did not send keepalive", test_info->errout);
|
strcpy(test_info->base_output, "Server did not send keepalive");
|
||||||
return EXIT_CRITICAL;
|
return EXIT_CRITICAL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static exit_value test_dnssec_validate(const struct test_info_s *test_info,
|
static exit_value test_dnssec_validate(struct test_info_s *test_info,
|
||||||
char ** av)
|
char ** av)
|
||||||
{
|
{
|
||||||
if (*av) {
|
if (*av) {
|
||||||
fputs("dnssec-validate takes no arguments",
|
strcpy(test_info->base_output, "dnssec-validate takes no arguments");
|
||||||
test_info->errout);
|
|
||||||
return EXIT_USAGE;
|
return EXIT_USAGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1197,12 +1299,12 @@ static exit_value test_dnssec_validate(const struct test_info_s *test_info,
|
||||||
return xit;
|
return xit;
|
||||||
|
|
||||||
if (error_id == GETDNS_RESPSTATUS_ALL_TIMEOUT) {
|
if (error_id == GETDNS_RESPSTATUS_ALL_TIMEOUT) {
|
||||||
fputs("Search timed out", test_info->errout);
|
strcpy(test_info->base_output, "Search timed out");
|
||||||
return EXIT_CRITICAL;
|
return EXIT_CRITICAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rcode != GETDNS_RCODE_SERVFAIL) {
|
if (rcode != GETDNS_RCODE_SERVFAIL) {
|
||||||
fputs("Server does NOT validate DNSSEC", test_info->errout);
|
strcpy(test_info->base_output, "Server does NOT validate DNSSEC");
|
||||||
return EXIT_CRITICAL;
|
return EXIT_CRITICAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1215,7 +1317,8 @@ static exit_value test_dnssec_validate(const struct test_info_s *test_info,
|
||||||
getdns_dict *extensions = getdns_dict_create();
|
getdns_dict *extensions = getdns_dict_create();
|
||||||
|
|
||||||
if ((ret = getdns_dict_set_int(extensions, "/header/cd", 1)) != GETDNS_RETURN_GOOD) {
|
if ((ret = getdns_dict_set_int(extensions, "/header/cd", 1)) != GETDNS_RETURN_GOOD) {
|
||||||
fprintf(test_info->errout,
|
snprintf(test_info->base_output,
|
||||||
|
MAX_BASE_OUTPUT_LEN,
|
||||||
"Cannot set CD bit: %s (%d)",
|
"Cannot set CD bit: %s (%d)",
|
||||||
getdns_get_errorstr_by_id(ret),
|
getdns_get_errorstr_by_id(ret),
|
||||||
ret);
|
ret);
|
||||||
|
@ -1244,27 +1347,27 @@ static exit_value test_dnssec_validate(const struct test_info_s *test_info,
|
||||||
return xit;
|
return xit;
|
||||||
|
|
||||||
if (error_id == GETDNS_RESPSTATUS_ALL_TIMEOUT) {
|
if (error_id == GETDNS_RESPSTATUS_ALL_TIMEOUT) {
|
||||||
fputs("Search timed out", test_info->errout);
|
strcpy(test_info->base_output, "Search timed out");
|
||||||
return EXIT_CRITICAL;
|
return EXIT_CRITICAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (error_id != GETDNS_RESPSTATUS_GOOD || rcode != GETDNS_RCODE_NOERROR) {
|
if (error_id != GETDNS_RESPSTATUS_GOOD || rcode != GETDNS_RCODE_NOERROR) {
|
||||||
fputs("Server error - cannot determine DNSSEC status", test_info->errout);
|
strcpy(test_info->base_output, "Server error - cannot determine DNSSEC status");
|
||||||
return EXIT_UNKNOWN;
|
return EXIT_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
fputs("Server validates DNSSEC", test_info->errout);
|
strcpy(test_info->base_output, "Server validates DNSSEC");
|
||||||
return EXIT_OK;
|
return EXIT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static exit_value test_tls13(const struct test_info_s *test_info,
|
static exit_value test_tls13(struct test_info_s *test_info,
|
||||||
char ** av)
|
char ** av)
|
||||||
{
|
{
|
||||||
exit_value xit;
|
exit_value xit;
|
||||||
getdns_return_t ret;
|
getdns_return_t ret;
|
||||||
|
|
||||||
if (*av) {
|
if (*av) {
|
||||||
fputs("tls-1.3 takes no arguments", test_info->errout);
|
strcpy(test_info->base_output, "tls-1.3 takes no arguments");
|
||||||
return EXIT_USAGE;
|
return EXIT_USAGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1274,10 +1377,12 @@ static exit_value test_tls13(const struct test_info_s *test_info,
|
||||||
* a Bad Context error on the lookup.
|
* a Bad Context error on the lookup.
|
||||||
*/
|
*/
|
||||||
if ((ret = getdns_context_set_tls_cipher_list(test_info->context, TLS13_CIPHER_SUITE)) != GETDNS_RETURN_GOOD) {
|
if ((ret = getdns_context_set_tls_cipher_list(test_info->context, TLS13_CIPHER_SUITE)) != GETDNS_RETURN_GOOD) {
|
||||||
fprintf(test_info->errout,
|
snprintf(test_info->base_output,
|
||||||
|
MAX_BASE_OUTPUT_LEN,
|
||||||
"Cannot set TLS 1.3 cipher list: %s (%d)",
|
"Cannot set TLS 1.3 cipher list: %s (%d)",
|
||||||
getdns_get_errorstr_by_id(ret),
|
getdns_get_errorstr_by_id(ret),
|
||||||
ret);
|
ret);
|
||||||
|
return EXIT_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
getdns_dict *response;
|
getdns_dict *response;
|
||||||
|
@ -1290,12 +1395,10 @@ static exit_value test_tls13(const struct test_info_s *test_info,
|
||||||
&ret)) != EXIT_OK) {
|
&ret)) != EXIT_OK) {
|
||||||
if (xit == EXIT_CRITICAL) {
|
if (xit == EXIT_CRITICAL) {
|
||||||
if (ret == GETDNS_RETURN_BAD_CONTEXT) {
|
if (ret == GETDNS_RETURN_BAD_CONTEXT) {
|
||||||
fputs("Your version of OpenSSL does not support TLS 1.3 ciphers. You need at least OpenSSL 1.1.1.",
|
strcpy(test_info->base_output, "Your version of OpenSSL does not support TLS 1.3 ciphers. You need at least OpenSSL 1.1.1.");
|
||||||
test_info->errout);
|
|
||||||
return EXIT_UNKNOWN;
|
return EXIT_UNKNOWN;
|
||||||
} else {
|
} else {
|
||||||
fputs("Cannot establish TLS 1.3 connection.",
|
strcpy(test_info->base_output, "Cannot establish TLS 1.3 connection.");
|
||||||
test_info->errout);
|
|
||||||
return EXIT_CRITICAL;
|
return EXIT_CRITICAL;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1309,7 +1412,8 @@ static exit_value test_tls13(const struct test_info_s *test_info,
|
||||||
getdns_list *l;
|
getdns_list *l;
|
||||||
|
|
||||||
if ((ret = getdns_dict_get_list(response, "call_reporting", &l)) != GETDNS_RETURN_GOOD) {
|
if ((ret = getdns_dict_get_list(response, "call_reporting", &l)) != GETDNS_RETURN_GOOD) {
|
||||||
fprintf(test_info->errout,
|
snprintf(test_info->base_output,
|
||||||
|
MAX_BASE_OUTPUT_LEN,
|
||||||
"Cannot get call report: %s (%d)",
|
"Cannot get call report: %s (%d)",
|
||||||
getdns_get_errorstr_by_id(ret),
|
getdns_get_errorstr_by_id(ret),
|
||||||
ret);
|
ret);
|
||||||
|
@ -1319,7 +1423,8 @@ static exit_value test_tls13(const struct test_info_s *test_info,
|
||||||
getdns_dict *d;
|
getdns_dict *d;
|
||||||
|
|
||||||
if ((ret = getdns_list_get_dict(l, 0, &d)) != GETDNS_RETURN_GOOD) {
|
if ((ret = getdns_list_get_dict(l, 0, &d)) != GETDNS_RETURN_GOOD) {
|
||||||
fprintf(test_info->errout,
|
snprintf(test_info->base_output,
|
||||||
|
MAX_BASE_OUTPUT_LEN,
|
||||||
"Cannot get call report first item: %s (%d)",
|
"Cannot get call report first item: %s (%d)",
|
||||||
getdns_get_errorstr_by_id(ret),
|
getdns_get_errorstr_by_id(ret),
|
||||||
ret);
|
ret);
|
||||||
|
@ -1330,7 +1435,8 @@ static exit_value test_tls13(const struct test_info_s *test_info,
|
||||||
getdns_bindata *version;
|
getdns_bindata *version;
|
||||||
|
|
||||||
if ((ret = getdns_dict_get_bindata(d, "tls_version", &version)) != GETDNS_RETURN_GOOD) {
|
if ((ret = getdns_dict_get_bindata(d, "tls_version", &version)) != GETDNS_RETURN_GOOD) {
|
||||||
fprintf(test_info->errout,
|
snprintf(test_info->base_output,
|
||||||
|
MAX_BASE_OUTPUT_LEN,
|
||||||
"Cannot get TLS version: %s (%d)",
|
"Cannot get TLS version: %s (%d)",
|
||||||
getdns_get_errorstr_by_id(ret),
|
getdns_get_errorstr_by_id(ret),
|
||||||
ret);
|
ret);
|
||||||
|
@ -1340,14 +1446,14 @@ static exit_value test_tls13(const struct test_info_s *test_info,
|
||||||
const char TLS_1_3_SIG[] = "TLSv1.3";
|
const char TLS_1_3_SIG[] = "TLSv1.3";
|
||||||
|
|
||||||
if (strncmp((const char *)version->data, TLS_1_3_SIG, sizeof(TLS_1_3_SIG) - 1) != 0) {
|
if (strncmp((const char *)version->data, TLS_1_3_SIG, sizeof(TLS_1_3_SIG) - 1) != 0) {
|
||||||
fputs("Server does not support TLS 1.3", test_info->errout);
|
strcpy(test_info->base_output, "Server does not support TLS 1.3");
|
||||||
return EXIT_CRITICAL;
|
return EXIT_CRITICAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((xit = check_result(test_info, response)) != EXIT_OK)
|
if ((xit = check_result(test_info, response)) != EXIT_OK)
|
||||||
return xit;
|
return xit;
|
||||||
|
|
||||||
fputs("Server supports TLS 1.3", test_info->errout);
|
strcpy(test_info->base_output, "Server supports TLS 1.3");
|
||||||
return EXIT_OK;
|
return EXIT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1356,7 +1462,7 @@ static struct test_funcs_s
|
||||||
const char *name;
|
const char *name;
|
||||||
bool implies_tls;
|
bool implies_tls;
|
||||||
bool implies_tcp;
|
bool implies_tcp;
|
||||||
exit_value (*func)(const struct test_info_s *test_info, char **av);
|
exit_value (*func)(struct test_info_s *test_info, char **av);
|
||||||
} TESTS[] =
|
} TESTS[] =
|
||||||
{
|
{
|
||||||
{ "lookup", false, false, test_lookup },
|
{ "lookup", false, false, test_lookup },
|
||||||
|
@ -1398,6 +1504,9 @@ int main(int ac, char *av[])
|
||||||
strcmp(*av, "--monitoring") == 0) {
|
strcmp(*av, "--monitoring") == 0) {
|
||||||
test_info.monitoring = true;
|
test_info.monitoring = true;
|
||||||
test_info.errout = stdout;
|
test_info.errout = stdout;
|
||||||
|
} else if (strcmp(*av, "-D") == 0 ||
|
||||||
|
strcmp(*av, "--debug") == 0) {
|
||||||
|
test_info.debug_output = true;
|
||||||
} else if (strcmp(*av, "-E") == 0 ||
|
} else if (strcmp(*av, "-E") == 0 ||
|
||||||
strcmp(*av, "--fail-on-dns-errors") == 0) {
|
strcmp(*av, "--fail-on-dns-errors") == 0) {
|
||||||
test_info.fail_on_dns_errors = true;
|
test_info.fail_on_dns_errors = true;
|
||||||
|
@ -1607,32 +1716,40 @@ int main(int ac, char *av[])
|
||||||
}
|
}
|
||||||
|
|
||||||
exit_value xit = f->func(&test_info, av);
|
exit_value xit = f->func(&test_info, av);
|
||||||
|
const char *xit_text = "(\?\?\?)";
|
||||||
|
FILE *out = stdout;
|
||||||
|
|
||||||
switch(xit) {
|
switch(xit) {
|
||||||
case EXIT_OK:
|
case EXIT_OK:
|
||||||
fputs(" (OK)", test_info.errout);
|
xit_text = "OK";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EXIT_WARNING:
|
case EXIT_WARNING:
|
||||||
fputs(" (WARNING)", test_info.errout);
|
xit_text = "WARNING";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EXIT_CRITICAL:
|
case EXIT_CRITICAL:
|
||||||
fputs(" (CRITICAL)", test_info.errout);
|
xit_text = "CRITICAL";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EXIT_UNKNOWN:
|
case EXIT_UNKNOWN:
|
||||||
fputs(" (UNKNOWN)", test_info.errout);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case EXIT_USAGE:
|
case EXIT_USAGE:
|
||||||
xit = EXIT_UNKNOWN;
|
xit = EXIT_UNKNOWN;
|
||||||
break;
|
xit_text = "UNKNOWN";
|
||||||
|
out = test_info.errout;
|
||||||
default:
|
|
||||||
/* ??? is a trigraph... */
|
|
||||||
fputs(" (\?\?\?)", test_info.errout);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
fputc('\n', test_info.errout);
|
|
||||||
|
if (test_info.monitoring)
|
||||||
|
fprintf(out, "DNS SERVER %s - ", xit_text);
|
||||||
|
fputs(test_info.base_output, out);
|
||||||
|
|
||||||
|
if (test_info.verbosity >= VERBOSITY_ADDITIONAL &&
|
||||||
|
test_info.monitoring &&
|
||||||
|
strlen(test_info.perf_output) > 0) {
|
||||||
|
fprintf(out, "|%s", test_info.perf_output);
|
||||||
|
}
|
||||||
|
|
||||||
|
fputc('\n', out);
|
||||||
exit(xit);
|
exit(xit);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue