Merge branch '2785-resconf-timeout-retry.conf' into 'main'

Parse timeout and attempts from resolv.conf

Closes #2785

See merge request isc-projects/bind9!5273
This commit is contained in:
Evan Hunt 2021-08-12 17:19:15 +00:00
commit 5f9d312868
7 changed files with 145 additions and 17 deletions

View file

@ -1,3 +1,10 @@
5693. [func] Restore support for reading 'timeout' and 'attempts'
options from /etc/resolv.conf, and use their values
in dig, host and nslookup. (Previously this was
supported by liblwres, and was still mentioned
in man pages, but had stopped working after liblwres
was deprecated in favor of libirs.) [GL #2785]
5692. [bug] Fix a rare crash in the DoH code caused by
detaching from an HTTP/2 session handle too early when
sending data. [GL #2851]

View file

@ -114,7 +114,7 @@ isc_sockaddr_t localaddr;
isc_refcount_t sendcount = ATOMIC_VAR_INIT(0);
isc_refcount_t recvcount = ATOMIC_VAR_INIT(0);
int ndots = -1;
int tries = 3;
int tries = -1;
int lookup_counter = 0;
static char servercookie[256];
@ -1276,6 +1276,17 @@ setup_system(bool ipv4only, bool ipv6only) {
ndots = irs_resconf_getndots(resconf);
debug("ndots is %d.", ndots);
}
if (timeout == 0) {
timeout = irs_resconf_gettimeout(resconf);
debug("timeout is %d.", timeout);
}
if (tries == -1) {
tries = irs_resconf_getattempts(resconf);
if (tries == 0) {
tries = 3;
}
debug("retries is %d.", tries);
}
/* If user doesn't specify server use nameservers from resolv.conf. */
if (ISC_LIST_EMPTY(server_list)) {

View file

@ -115,4 +115,24 @@ irs_resconf_getndots(irs_resconf_t *conf);
*\li 'conf' is a valid resconf object.
*/
unsigned int
irs_resconf_getattempts(irs_resconf_t *conf);
/*%<
* Return the 'attempts' value stored in 'conf'.
*
* Requires:
*
*\li 'conf' is a valid resconf object.
*/
unsigned int
irs_resconf_gettimeout(irs_resconf_t *conf);
/*%<
* Return the 'timeout' value stored in 'conf'.
*
* Requires:
*
*\li 'conf' is a valid resconf object.
*/
ISC_LANG_ENDDECLS

View file

@ -74,6 +74,13 @@
#define RESCONFMAXLINELEN 256U /*%< max size of a line */
#define RESCONFMAXSORTLIST 10U /*%< max 10 */
#define CHECK(op) \
do { \
result = (op); \
if (result != ISC_R_SUCCESS) \
goto cleanup; \
} while (0)
/*!
* configuration data structure
*/
@ -108,6 +115,10 @@ struct irs_resconf {
uint8_t resdebug;
/*%< set to n in 'options ndots:n' */
uint8_t ndots;
/*%< set to n in 'options attempts:n' */
uint8_t attempts;
/*%< set to n in 'options timeout:n' */
uint8_t timeout;
};
static isc_result_t
@ -165,8 +176,8 @@ eatwhite(FILE *fp) {
*/
static int
getword(FILE *fp, char *buffer, size_t size) {
char *p = NULL;
int ch;
char *p;
REQUIRE(buffer != NULL);
REQUIRE(size > 0U);
@ -446,11 +457,26 @@ resconf_parsesortlist(irs_resconf_t *conf, FILE *fp) {
return (ISC_R_SUCCESS);
}
static isc_result_t
resconf_optionnumber(const char *word, uint8_t *number) {
char *p;
long n;
n = strtol(word, &p, 10);
if (*p != '\0') { /* Bad string. */
return (ISC_R_UNEXPECTEDTOKEN);
}
if (n < 0 || n > 0xff) { /* Out of range. */
return (ISC_R_RANGE);
}
*number = n;
return (ISC_R_SUCCESS);
}
static isc_result_t
resconf_parseoption(irs_resconf_t *conf, FILE *fp) {
int delim;
long ndots;
char *p;
isc_result_t result = ISC_R_SUCCESS;
char word[RESCONFMAXLINELEN];
delim = getword(fp, word, sizeof(word));
@ -462,14 +488,11 @@ resconf_parseoption(irs_resconf_t *conf, FILE *fp) {
if (strcmp("debug", word) == 0) {
conf->resdebug = 1;
} else if (strncmp("ndots:", word, 6) == 0) {
ndots = strtol(word + 6, &p, 10);
if (*p != '\0') { /* Bad string. */
return (ISC_R_UNEXPECTEDTOKEN);
}
if (ndots < 0 || ndots > 0xff) { /* Out of range. */
return (ISC_R_RANGE);
}
conf->ndots = (uint8_t)ndots;
CHECK(resconf_optionnumber(word + 6, &conf->ndots));
} else if (strncmp("attempts:", word, 9) == 0) {
CHECK(resconf_optionnumber(word + 9, &conf->attempts));
} else if (strncmp("timeout:", word, 8) == 0) {
CHECK(resconf_optionnumber(word + 8, &conf->timeout));
}
if (delim == EOF || delim == '\n') {
@ -479,7 +502,8 @@ resconf_parseoption(irs_resconf_t *conf, FILE *fp) {
}
}
return (ISC_R_SUCCESS);
cleanup:
return (result);
}
static isc_result_t
@ -521,6 +545,8 @@ irs_resconf_load(isc_mem_t *mctx, const char *filename, irs_resconf_t **confp) {
conf->sortlistnxt = 0;
conf->resdebug = 0;
conf->ndots = 1;
conf->attempts = 3;
conf->timeout = 0;
for (i = 0; i < RESCONFMAXSEARCH; i++) {
conf->search[i] = NULL;
}
@ -669,3 +695,17 @@ irs_resconf_getndots(irs_resconf_t *conf) {
return ((unsigned int)conf->ndots);
}
unsigned int
irs_resconf_getattempts(irs_resconf_t *conf) {
REQUIRE(IRS_RESCONF_VALID(conf));
return ((unsigned int)conf->attempts);
}
unsigned int
irs_resconf_gettimeout(irs_resconf_t *conf) {
REQUIRE(IRS_RESCONF_VALID(conf));
return ((unsigned int)conf->timeout);
}

View file

@ -42,6 +42,43 @@ setup_test(void) {
assert_return_code(chdir(TESTS_DIR), 0);
}
static isc_result_t
check_number(unsigned int n, unsigned int expected) {
return ((n == expected) ? ISC_R_SUCCESS : ISC_R_BADNUMBER);
}
static isc_result_t
check_attempts(irs_resconf_t *resconf) {
return (check_number(irs_resconf_getattempts(resconf), 4));
}
static isc_result_t
check_timeout(irs_resconf_t *resconf) {
return (check_number(irs_resconf_gettimeout(resconf), 1));
}
static isc_result_t
check_ndots(irs_resconf_t *resconf) {
return (check_number(irs_resconf_getndots(resconf), 2));
}
static isc_result_t
check_options(irs_resconf_t *resconf) {
if (irs_resconf_getattempts(resconf) != 3) {
return ISC_R_BADNUMBER; /* default value only */
}
if (irs_resconf_getndots(resconf) != 2) {
return ISC_R_BADNUMBER;
}
if (irs_resconf_gettimeout(resconf) != 1) {
return ISC_R_BADNUMBER;
}
return (ISC_R_SUCCESS);
}
/* test irs_resconf_load() */
static void
irs_resconf_load_test(void **state) {
@ -61,15 +98,18 @@ irs_resconf_load_test(void **state) {
ISC_R_SUCCESS },
{ "testdata/nameserver-v6-scoped.conf", ISC_R_SUCCESS, NULL,
ISC_R_SUCCESS },
{ "testdata/options-attempts.conf", ISC_R_SUCCESS,
check_attempts, ISC_R_SUCCESS },
{ "testdata/options-debug.conf", ISC_R_SUCCESS, NULL,
ISC_R_SUCCESS },
{ "testdata/options-ndots.conf", ISC_R_SUCCESS, NULL,
{ "testdata/options-ndots.conf", ISC_R_SUCCESS, check_ndots,
ISC_R_SUCCESS },
{ "testdata/options-timeout.conf", ISC_R_SUCCESS, NULL,
{ "testdata/options-timeout.conf", ISC_R_SUCCESS, check_timeout,
ISC_R_SUCCESS },
{ "testdata/options-unknown.conf", ISC_R_SUCCESS, NULL,
ISC_R_SUCCESS },
{ "testdata/options.conf", ISC_R_SUCCESS, NULL, ISC_R_SUCCESS },
{ "testdata/options.conf", ISC_R_SUCCESS, check_options,
ISC_R_SUCCESS },
{ "testdata/options-bad-ndots.conf", ISC_R_RANGE, NULL,
ISC_R_SUCCESS },
{ "testdata/options-empty.conf", ISC_R_UNEXPECTEDEND, NULL,

View file

@ -0,0 +1,10 @@
# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, you can obtain one at https://mozilla.org/MPL/2.0/.
#
# See the COPYRIGHT file distributed with this work for additional
# information regarding copyright ownership.
options attempts:4

View file

@ -7,4 +7,4 @@
# See the COPYRIGHT file distributed with this work for additional
# information regarding copyright ownership.
option ndots:2
options ndots:2