resolver: sysresolve, names resolved by the system routines

The command keeps the C library's resolution which a configuration
without nserver had before the system's name servers became the
default: no hosts file imported. nserver lines, if any, are still
there for dnspr to forward to. Of sysresolve and fakeresolve the last
given applies.

Tests: sysdns, with sysresolve dnspr has no hosts file names and a
name is resolved through the system routines.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Vladimir Dubrovin 2026-10-20 19:02:37 +03:00
parent d5e78a0900
commit 994526dbc4
6 changed files with 67 additions and 8 deletions

View File

@ -498,6 +498,15 @@ user), Reply-Message. Use <b>authcache</b> to speedup
authentication. RADIUS feature is currently authentication. RADIUS feature is currently
experimental.</p> experimental.</p>
<p style="margin-left:9%; margin-top: 1em"><b>sysresolve</b>
<br>
Names are resolved by the system routines for name
resolution (the C library), as without <b>nserver</b> before
the system's name servers became the default; the hosts file
is not imported. <b>nserver</b> lines, if any, are still used
by <b>dnspr</b> to forward queries. Of <b>sysresolve</b> and
<b>fakeresolve</b> the last one given applies.</p>
<p style="margin-left:9%; margin-top: 1em"><b>nserver</b> <p style="margin-left:9%; margin-top: 1em"><b>nserver</b>
<i>&lt;ipaddr&gt;</i>[:<i>port</i>][/<i>tcp</i>] <br> <i>&lt;ipaddr&gt;</i>[:<i>port</i>][/<i>tcp</i>] <br>
Nameserver to use for name resolutions; up to 3, asked in Nameserver to use for name resolutions; up to 3, asked in
@ -507,7 +516,8 @@ has to be enclosed in square brackets: <br>
<b>nserver 1.1.1.1</b> <br> <b>nserver 1.1.1.1</b> <br>
<b>nserver [2001:4860:4860::8844]</b> <br> <b>nserver [2001:4860:4860::8844]</b> <br>
<b>nserver [2001:4860:4860::8844]:5353/tcp</b> <br> <b>nserver [2001:4860:4860::8844]:5353/tcp</b> <br>
If none is specified (and there is no <b>fakeresolve</b>), If none is specified (and there is no <b>fakeresolve</b> or
<b>sysresolve</b>),
the system's name servers are used: up to 3 from the system's name servers are used: up to 3 from
<i>/etc/resolv.conf</i>, on Windows from the registry (those <i>/etc/resolv.conf</i>, on Windows from the registry (those
set for the system, those set for an interface, then those set for the system, those set for an interface, then those

View File

@ -555,7 +555,7 @@ An IPv6 address has to be enclosed in square brackets:
.br .br
\fBnserver [2001:4860:4860::8844]:5353/tcp\fR \fBnserver [2001:4860:4860::8844]:5353/tcp\fR
.br .br
If none is specified (and there is no \fBfakeresolve\fR), the system's name If none is specified (and there is no \fBfakeresolve\fR or \fBsysresolve\fR), the system's name
servers are used: up to 3 from \fI/etc/resolv.conf\fR, on Windows from the servers are used: up to 3 from \fI/etc/resolv.conf\fR, on Windows from the
registry (those set for the system, those set for an interface, then those registry (those set for the system, those set for an interface, then those
DHCP gave). Names in the hosts file (\fI/etc/hosts\fR, on Windows DHCP gave). Names in the hosts file (\fI/etc/hosts\fR, on Windows
@ -600,6 +600,15 @@ are never consulted. A static record takes precedence over the hosts file. If 0.
is used as a hostaddr host will never resolve, it can be used to is used as a hostaddr host will never resolve, it can be used to
blacklist something. blacklist something.
.br
.B sysresolve
.br
Names are resolved by the system routines for name resolution (the C
library), as without \fBnserver\fR before the system's name servers became
the default; the hosts file is not imported. \fBnserver\fR lines, if any, are
still used by \fBdnspr\fR to forward queries. Of \fBsysresolve\fR and
\fBfakeresolve\fR the last one given applies.
.br .br
.B fakeresolve .B fakeresolve
.br .br

View File

@ -741,6 +741,8 @@ static int h_flushusers(int argc, unsigned char **argv){
force (the process has one list) once it is committed */ force (the process has one list) once it is committed */
static struct nserver cfgns[MAXNSERVERS]; static struct nserver cfgns[MAXNSERVERS];
static int cfgnsn = 0; static int cfgnsn = 0;
/* sysresolve: names resolved by the system routines */
static int cfgsysresolve = 0;
static int h_nserver(int argc, unsigned char **argv){ static int h_nserver(int argc, unsigned char **argv){
char *str; char *str;
@ -764,13 +766,13 @@ static int h_nserver(int argc, unsigned char **argv){
/* The configuration's name servers, or the system's in their place */ /* The configuration's name servers, or the system's in their place */
void confdnscommit(struct extparam *c){ void confdnscommit(struct extparam *c){
sysdnsapply(c, cfgns, cfgnsn); sysdnsapply(c, cfgns, cfgnsn, cfgsysresolve);
} }
/* Whether names would be resolved slowly: by the C library, or by name /* Whether names would be resolved slowly: by the C library, or by name
servers, the system's taken by default, without a cache */ servers, the system's taken by default, without a cache */
static int noresolver(void){ static int noresolver(void){
if(!conf->resolvfunc && !sysdnscount()) return 1; if(cfgsysresolve || (!conf->resolvfunc && !sysdnscount())) return 1;
return (!conf->resolvfunc || conf->resolvfunc == myresolver) && !dns_table.poolsize; return (!conf->resolvfunc || conf->resolvfunc == myresolver) && !dns_table.poolsize;
} }
@ -790,6 +792,12 @@ static int h_authnserver(int argc, unsigned char **argv){
static int h_fakeresolve(int argc, unsigned char **argv){ static int h_fakeresolve(int argc, unsigned char **argv){
conf->resolvfunc = fakeresolver; conf->resolvfunc = fakeresolver;
cfgsysresolve = 0;
return 0;
}
static int h_sysresolve(int argc, unsigned char **argv){
cfgsysresolve = 1;
return 0; return 0;
} }
@ -2146,6 +2154,7 @@ struct commands commandhandlers[]={
{NULL, "flush", h_flush, 1, 1}, {NULL, "flush", h_flush, 1, 1},
{NULL, "nserver", h_nserver, 2, 2}, {NULL, "nserver", h_nserver, 2, 2},
{NULL, "fakeresolve", h_fakeresolve, 1, 1}, {NULL, "fakeresolve", h_fakeresolve, 1, 1},
{NULL, "sysresolve", h_sysresolve, 1, 1},
{NULL, "nscache", h_nscache, 2, 2}, {NULL, "nscache", h_nscache, 2, 2},
{NULL, "nscache6", h_nscache6, 2, 2}, {NULL, "nscache6", h_nscache6, 2, 2},
{NULL, "nsrecord", h_nsrecord, 3, 3}, {NULL, "nsrecord", h_nsrecord, 3, 3},
@ -2534,6 +2543,7 @@ void confbegin(void){
char * args[] = {"auth", "iponly", NULL}; char * args[] = {"auth", "iponly", NULL};
cfgnsn = 0; cfgnsn = 0;
cfgsysresolve = 0;
h_auth(2, (unsigned char **)args); h_auth(2, (unsigned char **)args);
} }

View File

@ -435,7 +435,7 @@ int nscacheresolv(int af, unsigned char *name, unsigned char *value, uint32_t *t
void setnservers(const struct nserver *ns, int n); void setnservers(const struct nserver *ns, int n);
void sysdnsinit(void); void sysdnsinit(void);
int sysdnscount(void); int sysdnscount(void);
void sysdnsapply(struct extparam *c, const struct nserver *ns, int n); void sysdnsapply(struct extparam *c, const struct nserver *ns, int n, int sysresolve);
void sysdnscheck(void); void sysdnscheck(void);
void confdnscommit(struct extparam *c); void confdnscommit(struct extparam *c);
uint32_t udpresolve(int af, unsigned char * name, unsigned char * value, uint32_t *retttl, struct clientparam* param, int makeauth); uint32_t udpresolve(int af, unsigned char * name, unsigned char * value, uint32_t *retttl, struct clientparam* param, int makeauth);

View File

@ -585,9 +585,16 @@ int sysdnscount(void){
/* A configuration committed: the name servers of its nserver lines, else, /* A configuration committed: the name servers of its nserver lines, else,
with nothing else to resolve names, the system's and its hosts file, read with nothing else to resolve names, the system's and its hosts file, read
again. Until then those in force stay. */ again. Until then those in force stay. With sysresolve the system
void sysdnsapply(struct extparam *c, const struct nserver *ns, int n){ routines resolve names, nserver lines left to dnspr. */
void sysdnsapply(struct extparam *c, const struct nserver *ns, int n, int sysresolve){
sysdns.active = 0; sysdns.active = 0;
if(sysresolve){
c->resolvfunc = NULL;
setnservers(ns, n);
hostsremove();
return;
}
if(n){ if(n){
setnservers(ns, n); setnservers(ns, n);
hostsremove(); hostsremove();

View File

@ -1,6 +1,6 @@
"""The system's name servers and hosts file as the default resolver: with """The system's name servers and hosts file as the default resolver: with
no nserver in a configuration, names in the hosts file are answered from no nserver in a configuration, names in the hosts file are answered from
it, through the name cache; with nserver lines, the file is not used.""" it; with nserver lines, or sysresolve (the system routines), it is not."""
import os import os
import re import re
@ -81,3 +81,26 @@ def run(t):
wait(t, other, "localhost") wait(t, other, "localhost")
t.ne(["127.0.0.1"], t.dns_query(other, "localhost") or [], t.ne(["127.0.0.1"], t.dns_query(other, "localhost") or [],
"with nserver, the hosts file is not used") "with nserver, the hosts file is not used")
# sysresolve: the system routines resolve names, and nothing is imported
# for dnspr to answer from
sysport, proxy, srv = t.free_port(), t.free_port(), t.free_port()
t.start("sysdns_sysresolve", f"""
log
flush
sysresolve
auth iponly
allow *
dnspr -p{sysport}
proxy -p{proxy}
flush
auth iponly
allow *
http echo * /echo**
httpsrv -p{srv}
""", ports=[proxy, srv])
wait(t, sysport, "localhost")
t.ne(["127.0.0.1"], t.dns_query(sysport, "localhost") or [],
"with sysresolve, dnspr has no hosts file names")
t.eq(200, t.http(f"http://localhost:{srv}/echo", proxy=f"127.0.0.1:{proxy}").status,
"and names resolve through the system routines")