mirror of https://github.com/getdnsapi/getdns.git
Add 'keepalive' test and supporting changes to getdns library.
Checking for server support for keepalive means we need to know if the server did send a keepalive option to the client. This information is not currently exposed in getdns, so add a flag 'server_keepalive_received' to call_reporting. This is 0 if not received, 1 if received. If received, the actual timeout is in 'idle timeout in ms', though watch out for the overflow alternative.
This commit is contained in:
parent
a4ff6de985
commit
3666d994a7
|
@ -1011,6 +1011,7 @@ upstream_init(getdns_upstream *upstream,
|
||||||
upstream->responses_timeouts = 0;
|
upstream->responses_timeouts = 0;
|
||||||
upstream->keepalive_shutdown = 0;
|
upstream->keepalive_shutdown = 0;
|
||||||
upstream->keepalive_timeout = 0;
|
upstream->keepalive_timeout = 0;
|
||||||
|
upstream->server_keepalive_received = 0;
|
||||||
/* How is this upstream doing on UDP? */
|
/* How is this upstream doing on UDP? */
|
||||||
upstream->to_retry = 1;
|
upstream->to_retry = 1;
|
||||||
upstream->back_off = 1;
|
upstream->back_off = 1;
|
||||||
|
|
|
@ -193,6 +193,7 @@ typedef struct getdns_upstream {
|
||||||
size_t responses_timeouts;
|
size_t responses_timeouts;
|
||||||
size_t keepalive_shutdown;
|
size_t keepalive_shutdown;
|
||||||
uint64_t keepalive_timeout;
|
uint64_t keepalive_timeout;
|
||||||
|
int server_keepalive_received;
|
||||||
|
|
||||||
/* Management of outstanding requests on stateful transports */
|
/* Management of outstanding requests on stateful transports */
|
||||||
getdns_network_req *write_queue;
|
getdns_network_req *write_queue;
|
||||||
|
|
|
@ -341,6 +341,7 @@ process_keepalive(
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
upstream->server_keepalive_received = 1;
|
||||||
/* Use server sent value unless the client specified a shorter one.
|
/* Use server sent value unless the client specified a shorter one.
|
||||||
Convert to ms first (wire value has units of 100ms) */
|
Convert to ms first (wire value has units of 100ms) */
|
||||||
uint64_t server_keepalive = ((uint64_t)gldns_read_uint16(position))*100;
|
uint64_t server_keepalive = ((uint64_t)gldns_read_uint16(position))*100;
|
||||||
|
|
|
@ -183,9 +183,12 @@ static void usage()
|
||||||
"\n"
|
"\n"
|
||||||
"Tests:\n"
|
"Tests:\n"
|
||||||
" lookup [<name> [<type>]] Check lookup on server\n"
|
" lookup [<name> [<type>]] Check lookup on server\n"
|
||||||
|
" keepalive <timeout-ms> [<name> [<type>]]\n"
|
||||||
|
" Check server support for EDNS0 keepalive in TCP/TLS\n"
|
||||||
|
" Timeout of 0 is off.\n"
|
||||||
|
" qname-min Check whether server supports QNAME minimisation\n"
|
||||||
" rtt [warn-ms,crit-ms] [<name> [<type>]]\n"
|
" rtt [warn-ms,crit-ms] [<name> [<type>]]\n"
|
||||||
" Check server round trip time (default 500,250)\n"
|
" Check server round trip time (default 500,250)\n"
|
||||||
" qname-min Check whether server supports QNAME minimisation\n"
|
|
||||||
"\n"
|
"\n"
|
||||||
" tls-auth [<name> [<type>]] Check authentication of TLS server\n"
|
" tls-auth [<name> [<type>]] Check authentication of TLS server\n"
|
||||||
" If both a SPKI pin and authentication name are\n"
|
" If both a SPKI pin and authentication name are\n"
|
||||||
|
@ -938,20 +941,109 @@ no_padding:
|
||||||
return EXIT_CRITICAL;
|
return EXIT_CRITICAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static exit_value_t test_keepalive(const struct test_info_s *test_info,
|
||||||
|
char ** av)
|
||||||
|
{
|
||||||
|
getdns_dict *response;
|
||||||
|
exit_value_t xit;
|
||||||
|
long long timeout;
|
||||||
|
char *endptr;
|
||||||
|
const char USAGE[] = "keepalive takes arguments <timeout-ms> [<name> [<type>]]";
|
||||||
|
|
||||||
|
if (!*av || (timeout = strtoll(*av, &endptr, 10), *endptr != '\0' || timeout < 0)) {
|
||||||
|
fputs(USAGE, test_info->errout);
|
||||||
|
return EXIT_USAGE;
|
||||||
|
}
|
||||||
|
++av;
|
||||||
|
|
||||||
|
getdns_return_t ret;
|
||||||
|
if ((ret = getdns_context_set_idle_timeout(test_info->context, (uint64_t) timeout)) != GETDNS_RETURN_GOOD) {
|
||||||
|
fprintf(test_info->errout,
|
||||||
|
"Cannot set keepalive timeout: %s (%d)",
|
||||||
|
getdns_get_errorstr_by_id(ret),
|
||||||
|
ret);
|
||||||
|
return EXIT_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((xit = parse_search_check(test_info,
|
||||||
|
av,
|
||||||
|
USAGE,
|
||||||
|
&response,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL)) != EXIT_OK)
|
||||||
|
return xit;
|
||||||
|
|
||||||
|
getdns_list *l;
|
||||||
|
|
||||||
|
if ((ret = getdns_dict_get_list(response, "call_reporting", &l)) != GETDNS_RETURN_GOOD) {
|
||||||
|
fprintf(test_info->errout,
|
||||||
|
"Cannot get call report: %s (%d)",
|
||||||
|
getdns_get_errorstr_by_id(ret),
|
||||||
|
ret);
|
||||||
|
return EXIT_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
getdns_dict *d;
|
||||||
|
if ((ret = getdns_list_get_dict(l, 0, &d)) != GETDNS_RETURN_GOOD) {
|
||||||
|
fprintf(test_info->errout,
|
||||||
|
"Cannot get call report first item: %s (%d)",
|
||||||
|
getdns_get_errorstr_by_id(ret),
|
||||||
|
ret);
|
||||||
|
return EXIT_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Search is forced to be TCP or TLS, so server keepalive flag must exist. */
|
||||||
|
uint32_t server_keepalive_received;
|
||||||
|
if ((ret = getdns_dict_get_int(d, "server_keepalive_received", &server_keepalive_received)) != GETDNS_RETURN_GOOD) {
|
||||||
|
fprintf(test_info->errout,
|
||||||
|
"Cannot get server keepalive flag: %s (%d)",
|
||||||
|
getdns_get_errorstr_by_id(ret),
|
||||||
|
ret);
|
||||||
|
return EXIT_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (server_keepalive_received) {
|
||||||
|
uint32_t t;
|
||||||
|
bool overflow = false;
|
||||||
|
|
||||||
|
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)) {
|
||||||
|
fprintf(test_info->errout,
|
||||||
|
"Cannot get idle timeout: %s (%d)",
|
||||||
|
getdns_get_errorstr_by_id(ret),
|
||||||
|
ret);
|
||||||
|
return EXIT_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (overflow) {
|
||||||
|
fputs("Server sent keepalive, idle timeout now (overflow)", test_info->errout);
|
||||||
|
} else {
|
||||||
|
fprintf(test_info->errout, "Server sent keepalive, idle timeout now %ums", t);
|
||||||
|
}
|
||||||
|
return EXIT_OK;
|
||||||
|
} else {
|
||||||
|
fputs("Server did not send keepalive", test_info->errout);
|
||||||
|
return EXIT_CRITICAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static struct test_funcs_s
|
static struct test_funcs_s
|
||||||
{
|
{
|
||||||
const char *name;
|
const char *name;
|
||||||
bool implies_tls;
|
bool implies_tls;
|
||||||
|
bool implies_tcp;
|
||||||
exit_value_t (*func)(const struct test_info_s *test_info, char **av);
|
exit_value_t (*func)(const struct test_info_s *test_info, char **av);
|
||||||
} TESTS[] =
|
} TESTS[] =
|
||||||
{
|
{
|
||||||
{ "lookup", false, test_lookup },
|
{ "lookup", false, false, test_lookup },
|
||||||
{ "rtt", false, test_rtt },
|
{ "rtt", false, false, test_rtt },
|
||||||
{ "qname-min", false, test_qname_minimisation },
|
{ "qname-min", false, false, test_qname_minimisation },
|
||||||
{ "tls-auth", true, test_authenticate },
|
{ "tls-auth", true, false, test_authenticate },
|
||||||
{ "tls-cert-valid", true, test_certificate_valid },
|
{ "tls-cert-valid", true, false, test_certificate_valid },
|
||||||
{ "tls-padding", true, test_padding },
|
{ "tls-padding", true, false, test_padding },
|
||||||
{ NULL, false, NULL }
|
{ "keepalive", false, true, test_keepalive },
|
||||||
|
{ NULL, false, false, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
int main(int ac, char *av[])
|
int main(int ac, char *av[])
|
||||||
|
@ -1151,6 +1243,15 @@ int main(int ac, char *av[])
|
||||||
exit(EXIT_UNKNOWN);
|
exit(EXIT_UNKNOWN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (f->implies_tcp) {
|
||||||
|
if (use_udp) {
|
||||||
|
fputs("Test requires TCP or TLS\n", test_info.errout);
|
||||||
|
exit(EXIT_UNKNOWN);
|
||||||
|
}
|
||||||
|
if (!use_tls)
|
||||||
|
use_tcp = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (f->implies_tls) {
|
if (f->implies_tls) {
|
||||||
if (use_udp | use_tcp) {
|
if (use_udp | use_tcp) {
|
||||||
fputs("Test requires TLS, or TLS authentication specified\n", test_info.errout);
|
fputs("Test requires TLS, or TLS authentication specified\n", test_info.errout);
|
||||||
|
|
|
@ -880,6 +880,10 @@ _getdns_create_call_reporting_dict(
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (getdns_dict_set_int( netreq_debug, "server_keepalive_received", netreq->upstream->server_keepalive_received)) {
|
||||||
|
getdns_dict_destroy(netreq_debug);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
/* The running totals are only updated when a connection is closed.
|
/* The running totals are only updated when a connection is closed.
|
||||||
Since it is open as we have just used it, calcualte the value on the fly */
|
Since it is open as we have just used it, calcualte the value on the fly */
|
||||||
if (getdns_dict_set_int( netreq_debug, "responses_on_this_connection",
|
if (getdns_dict_set_int( netreq_debug, "responses_on_this_connection",
|
||||||
|
|
Loading…
Reference in New Issue