[BUG] Resolver uses nameserver commented out in /etc/resolv.conf
grembo opened this issue · comments
TL;DR
Comment parsing in /etc/resolv.conf is broken since 889f7c7
How to reproduce
Create a basic resolv.conf containing comments:
cat<<EOF >/etc/resolv.conf
# x
# nameserver 8.8.8.8
EOF
Then run drill on some zone:
drill wikipedia.org
Expected outcome
Since there are no nameservers configured, this outcome would be expected:
Error: error sending query: No (valid) nameservers defined in the resolver
Actual outcome
The commented out nameserver entry is used:
;; ->>HEADER<<- opcode: QUERY, rcode: NOERROR, id: 17996
;; flags: qr rd ra ; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;; wikipedia.org. IN A
;; ANSWER SECTION:
wikipedia.org. 77 IN A 185.15.59.224
;; AUTHORITY SECTION:
;; ADDITIONAL SECTION:
;; Query time: 20 msec
;; SERVER: 8.8.8.8
;; WHEN: Fri May 3 15:40:07 2024
;; MSG SIZE rcvd: 47
Analysis
Commit 889f7c7 introduced this change:
diff --git a/parse.c b/parse.c
index 3c737620..9698ba71 100644
--- a/parse.c
+++ b/parse.c
@@ -187,6 +187,9 @@ ldns_fget_token_l_st(FILE *f, char **token, size_t *limit, bool fixed
if (c != '\0' && c != '\n') {
*t++ = c;
}
+ if (c == '\n' && line_nr) {
+ *line_nr = *line_nr + 1;
+ }
if (c == '\\' && prev_c == '\\')
prev_c = 0;
else prev_c = c;
Which breaks comment handling in resolver.c, which only removes characters until the end of line, in case line_nr doesn't change:
if (word[0] == '#') {
word[0]='x';
if(oldline == *line_nr) {
/* skip until end of line */
int c;
do {
c = fgetc(myfp);
} while(c != EOF && c != '\n');
if(c=='\n') (*line_nr)++;
}
/* and read next to prepare for further parsing */
oldline = *line_nr;
continue;
}
Potential Fixes
The parser isn't necessarily the kind of code one just jumps into and reasons about, yet the three suggestions below worked for my limited use case:
- Rollback 889f7c7 (from the commit it's unclear, if it fixed a cosmetic or a functional issue)
- Make
ldns_fget_token_l_st
understand comments starting with#
(unclear which side-effects this might have)
diff --git a/parse.c b/parse.c
index 9698ba71..a2478f66 100644
--- a/parse.c
+++ b/parse.c
@@ -98,7 +98,7 @@ ldns_fget_token_l_st(FILE *f, char **token, size_t *limit, bool fixed
}
/* do something with comments ; */
- if (c == ';' && quoted == 0) {
+ if ((c == ';' || c == '#') && quoted == 0) {
if (prev_c != '\\') {
com = 1;
}
- Patch resolver.c's comment handling (again, might have unwanted side effects):
diff --git a/resolver.c b/resolver.c
index f9ec65a5..e8921dbc 100644
--- a/resolver.c
+++ b/resolver.c
@@ -815,14 +815,12 @@ ldns_resolver_new_frm_fp_l(ldns_resolver **res, FILE *fp, int *line_nr)
/* check comments */
if (word[0] == '#') {
word[0]='x';
- if(oldline == *line_nr) {
/* skip until end of line */
int c;
do {
c = fgetc(myfp);
} while(c != EOF && c != '\n');
if(c=='\n') (*line_nr)++;
- }
/* and read next to prepare for further parsing */
oldline = *line_nr;
continue;
Real life resolv.conf
This is the configuration where we first encountered issues (it would request a local zone from google DNS and fail with NXDOMAIN, even though we would expect the call to be handled by unbound running locally)
# Generated by resolvconf
# nameserver 192.168.1.1
# nameserver 8.8.8.8
nameserver 127.0.0.1
options edns0
FreeBSD bug tracker: https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=278721
Hopefully found a title that makes more sense now 😄
- Make
ldns_fget_token_l_st
understand comments starting with#
(unclear which side-effects this might have)
Thank you @grembo . I prefer that one, and then remove all comment handling from resolver.c. I just added a bit more (in PR #238) so that zonefile parsing does not accept comments to start with '#' too.
And thank you for reporting!
@dag-erling I've put a bugfix release on the calender for June.