48bb18
From b0e79979672935ff07bf23703c675ee788940c59 Mon Sep 17 00:00:00 2001
48bb18
From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= <pemensik@redhat.com>
48bb18
Date: Tue, 22 Jun 2021 16:35:46 +0200
48bb18
Subject: [PATCH] Parse 'timeout' and 'attempts' from resolv.conf
48bb18
48bb18
It was supported by lwres in BIND 9.11, and is still mentioned in
48bb18
the manual page. Restore support for it by adding it to libirs.
48bb18
---
48bb18
 bin/dig/dighost.c             | 13 ++++++-
48bb18
 lib/irs/include/irs/resconf.h | 20 +++++++++++
48bb18
 lib/irs/resconf.c             | 64 ++++++++++++++++++++++++++++-------
48bb18
 3 files changed, 84 insertions(+), 13 deletions(-)
48bb18
48bb18
diff --git a/bin/dig/dighost.c b/bin/dig/dighost.c
48bb18
index 0222454..274e894 100644
48bb18
--- a/bin/dig/dighost.c
48bb18
+++ b/bin/dig/dighost.c
48bb18
@@ -133,7 +133,7 @@ int sendcount = 0;
48bb18
 int recvcount = 0;
48bb18
 int sockcount = 0;
48bb18
 int ndots = -1;
48bb18
-int tries = 3;
48bb18
+int tries = -1;
48bb18
 int lookup_counter = 0;
48bb18
 
48bb18
 static char servercookie[256];
48bb18
@@ -1330,6 +1330,17 @@ setup_system(bool ipv4only, bool ipv6only) {
48bb18
 		ndots = irs_resconf_getndots(resconf);
48bb18
 		debug("ndots is %d.", ndots);
48bb18
 	}
48bb18
+	if (timeout == 0) {
48bb18
+		timeout = irs_resconf_gettimeout(resconf);
48bb18
+		debug("timeout is %d.", timeout);
48bb18
+	}
48bb18
+	if (tries == -1) {
48bb18
+		tries = irs_resconf_getattempts(resconf);
48bb18
+		if (tries == 0) {
48bb18
+			tries = 3;
48bb18
+		}
48bb18
+		debug("retries is %d.", tries);
48bb18
+	}
48bb18
 
48bb18
 	/* If user doesn't specify server use nameservers from resolv.conf. */
48bb18
 	if (ISC_LIST_EMPTY(server_list)) {
48bb18
diff --git a/lib/irs/include/irs/resconf.h b/lib/irs/include/irs/resconf.h
48bb18
index 424b795..74fc84a 100644
48bb18
--- a/lib/irs/include/irs/resconf.h
48bb18
+++ b/lib/irs/include/irs/resconf.h
48bb18
@@ -113,6 +113,26 @@ irs_resconf_getndots(irs_resconf_t *conf);
48bb18
  *\li	'conf' is a valid resconf object.
48bb18
  */
48bb18
 
48bb18
+unsigned int
48bb18
+irs_resconf_getattempts(irs_resconf_t *conf);
48bb18
+/*%<
48bb18
+ * Return the 'attempts' value stored in 'conf'.
48bb18
+ *
48bb18
+ * Requires:
48bb18
+ *
48bb18
+ *\li	'conf' is a valid resconf object.
48bb18
+ */
48bb18
+
48bb18
+unsigned int
48bb18
+irs_resconf_gettimeout(irs_resconf_t *conf);
48bb18
+/*%<
48bb18
+ * Return the 'timeout' value stored in 'conf'.
48bb18
+ *
48bb18
+ * Requires:
48bb18
+ *
48bb18
+ *\li	'conf' is a valid resconf object.
48bb18
+ */
48bb18
+
48bb18
 ISC_LANG_ENDDECLS
48bb18
 
48bb18
 #endif /* IRS_RESCONF_H */
48bb18
diff --git a/lib/irs/resconf.c b/lib/irs/resconf.c
48bb18
index 096064b..dd51d71 100644
48bb18
--- a/lib/irs/resconf.c
48bb18
+++ b/lib/irs/resconf.c
48bb18
@@ -80,6 +80,13 @@
48bb18
 #define RESCONFMAXLINELEN     256U /*%< max size of a line */
48bb18
 #define RESCONFMAXSORTLIST    10U  /*%< max 10 */
48bb18
 
48bb18
+#define CHECK(op)                            \
48bb18
+	do {                                 \
48bb18
+		result = (op);               \
48bb18
+		if (result != ISC_R_SUCCESS) \
48bb18
+			goto cleanup;        \
48bb18
+	} while (0)
48bb18
+
48bb18
 /*!
48bb18
  * configuration data structure
48bb18
  */
48bb18
@@ -114,6 +121,10 @@ struct irs_resconf {
48bb18
 	uint8_t resdebug;
48bb18
 	/*%< set to n in 'options ndots:n' */
48bb18
 	uint8_t ndots;
48bb18
+	/*%< set to n in 'options attempts:n' */
48bb18
+	uint8_t attempts;
48bb18
+	/*%< set to n in 'options timeout:n' */
48bb18
+	uint8_t timeout;
48bb18
 };
48bb18
 
48bb18
 static isc_result_t
48bb18
@@ -176,8 +187,8 @@ eatwhite(FILE *fp) {
48bb18
  */
48bb18
 static int
48bb18
 getword(FILE *fp, char *buffer, size_t size) {
48bb18
+	char *p = NULL;
48bb18
 	int ch;
48bb18
-	char *p;
48bb18
 
48bb18
 	REQUIRE(buffer != NULL);
48bb18
 	REQUIRE(size > 0U);
48bb18
@@ -457,11 +468,26 @@ resconf_parsesortlist(irs_resconf_t *conf, FILE *fp) {
48bb18
 	return (ISC_R_SUCCESS);
48bb18
 }
48bb18
 
48bb18
+static isc_result_t
48bb18
+resconf_optionnumber(const char *word, uint8_t *number) {
48bb18
+	char *p;
48bb18
+	long n;
48bb18
+
48bb18
+	n = strtol(word, &p, 10);
48bb18
+	if (*p != '\0') { /* Bad string. */
48bb18
+		return (ISC_R_UNEXPECTEDTOKEN);
48bb18
+	}
48bb18
+	if (n < 0 || n > 0xff) { /* Out of range. */
48bb18
+		return (ISC_R_RANGE);
48bb18
+	}
48bb18
+	*number = n;
48bb18
+	return (ISC_R_SUCCESS);
48bb18
+}
48bb18
+
48bb18
 static isc_result_t
48bb18
 resconf_parseoption(irs_resconf_t *conf, FILE *fp) {
48bb18
 	int delim;
48bb18
-	long ndots;
48bb18
-	char *p;
48bb18
+	isc_result_t result = ISC_R_SUCCESS;
48bb18
 	char word[RESCONFMAXLINELEN];
48bb18
 
48bb18
 	delim = getword(fp, word, sizeof(word));
48bb18
@@ -473,14 +499,11 @@ resconf_parseoption(irs_resconf_t *conf, FILE *fp) {
48bb18
 		if (strcmp("debug", word) == 0) {
48bb18
 			conf->resdebug = 1;
48bb18
 		} else if (strncmp("ndots:", word, 6) == 0) {
48bb18
-			ndots = strtol(word + 6, &p, 10);
48bb18
-			if (*p != '\0') { /* Bad string. */
48bb18
-				return (ISC_R_UNEXPECTEDTOKEN);
48bb18
-			}
48bb18
-			if (ndots < 0 || ndots > 0xff) { /* Out of range. */
48bb18
-				return (ISC_R_RANGE);
48bb18
-			}
48bb18
-			conf->ndots = (uint8_t)ndots;
48bb18
+			CHECK(resconf_optionnumber(word + 6, &conf->ndots));
48bb18
+		} else if (strncmp("attempts:", word, 9) == 0) {
48bb18
+			CHECK(resconf_optionnumber(word + 9, &conf->attempts));
48bb18
+		} else if (strncmp("timeout:", word, 8) == 0) {
48bb18
+			CHECK(resconf_optionnumber(word + 8, &conf->timeout));
48bb18
 		}
48bb18
 
48bb18
 		if (delim == EOF || delim == '\n') {
48bb18
@@ -490,7 +513,8 @@ resconf_parseoption(irs_resconf_t *conf, FILE *fp) {
48bb18
 		}
48bb18
 	}
48bb18
 
48bb18
-	return (ISC_R_SUCCESS);
48bb18
+cleanup:
48bb18
+	return (result);
48bb18
 }
48bb18
 
48bb18
 static isc_result_t
48bb18
@@ -532,6 +556,8 @@ irs_resconf_load(isc_mem_t *mctx, const char *filename, irs_resconf_t **confp) {
48bb18
 	conf->sortlistnxt = 0;
48bb18
 	conf->resdebug = 0;
48bb18
 	conf->ndots = 1;
48bb18
+	conf->attempts = 3;
48bb18
+	conf->timeout = 0;
48bb18
 	for (i = 0; i < RESCONFMAXSEARCH; i++) {
48bb18
 		conf->search[i] = NULL;
48bb18
 	}
48bb18
@@ -687,3 +713,17 @@ irs_resconf_getndots(irs_resconf_t *conf) {
48bb18
 
48bb18
 	return ((unsigned int)conf->ndots);
48bb18
 }
48bb18
+
48bb18
+unsigned int
48bb18
+irs_resconf_getattempts(irs_resconf_t *conf) {
48bb18
+	REQUIRE(IRS_RESCONF_VALID(conf));
48bb18
+
48bb18
+	return ((unsigned int)conf->attempts);
48bb18
+}
48bb18
+
48bb18
+unsigned int
48bb18
+irs_resconf_gettimeout(irs_resconf_t *conf) {
48bb18
+	REQUIRE(IRS_RESCONF_VALID(conf));
48bb18
+
48bb18
+	return ((unsigned int)conf->timeout);
48bb18
+}
48bb18
-- 
48bb18
2.35.3
48bb18