mirror of
git://git.9front.org/plan9front/plan9front
synced 2025-01-12 11:10:06 +00:00
ndb/dns: DoT support
This commit is contained in:
parent
917d0fa9b4
commit
6b0574e27e
8 changed files with 276 additions and 72 deletions
|
@ -232,7 +232,13 @@ There may be multiple
|
||||||
pairs.
|
pairs.
|
||||||
.TP
|
.TP
|
||||||
.B dns
|
.B dns
|
||||||
a DNS server to use (for DNS and DHCP)
|
a DNS server to use for resolving (for DNS and DHCP)
|
||||||
|
.TP
|
||||||
|
.B dot
|
||||||
|
a DNS over TLS server to use for resolving (for DNS).
|
||||||
|
If found,
|
||||||
|
.B dns
|
||||||
|
entries are ignored.
|
||||||
.TP
|
.TP
|
||||||
.B ntp
|
.B ntp
|
||||||
an NTP server to use (for DHCP)
|
an NTP server to use (for DHCP)
|
||||||
|
|
|
@ -62,6 +62,9 @@ query, ipquery, mkhash, mkdb, mkhosts, cs, csquery, dns, dnsquery, dnsdebug, dns
|
||||||
.B -a
|
.B -a
|
||||||
.I maxage
|
.I maxage
|
||||||
] [
|
] [
|
||||||
|
.B -c
|
||||||
|
.I cert.pem
|
||||||
|
] [
|
||||||
.B -f
|
.B -f
|
||||||
.I dbfile
|
.I dbfile
|
||||||
] [
|
] [
|
||||||
|
@ -393,11 +396,18 @@ send `recursive' queries, asking the other servers
|
||||||
to complete lookups.
|
to complete lookups.
|
||||||
If present,
|
If present,
|
||||||
.B /env/DNSSERVER
|
.B /env/DNSSERVER
|
||||||
must be a space-separated list of such DNS servers' IP addresses,
|
or
|
||||||
|
.B /env/DOTSERVER
|
||||||
|
must be a space-separated list of such DNS (or DoT) servers' IP addresses,
|
||||||
otherwise optional
|
otherwise optional
|
||||||
.IR ndb (6)
|
.IR ndb (6)
|
||||||
.B dns
|
.B dns
|
||||||
attributes name DNS servers to forward queries to.
|
attributes name DNS servers to forward queries to.
|
||||||
|
Note that when
|
||||||
|
.B DOTSERVER
|
||||||
|
is specified,
|
||||||
|
.B DNSSERVER
|
||||||
|
are ignored.
|
||||||
.TP
|
.TP
|
||||||
.B -R
|
.B -R
|
||||||
ignore the `recursive' bit on all incoming requests.
|
ignore the `recursive' bit on all incoming requests.
|
||||||
|
@ -422,6 +432,12 @@ are given,
|
||||||
listen on any interface on network mount point
|
listen on any interface on network mount point
|
||||||
.IR netmtpt .
|
.IR netmtpt .
|
||||||
.TP
|
.TP
|
||||||
|
.B -c
|
||||||
|
When a certificate
|
||||||
|
.I cert.pem
|
||||||
|
is specified, also listen on TCP port 853 and handle
|
||||||
|
DNS requests over TLS.
|
||||||
|
.TP
|
||||||
.B -x
|
.B -x
|
||||||
specifies the mount point of the network.
|
specifies the mount point of the network.
|
||||||
.PD
|
.PD
|
||||||
|
|
|
@ -916,7 +916,7 @@ addlocaldnsserver(DN *dp, int class, char *addr, int i)
|
||||||
|
|
||||||
/* check duplicate ip */
|
/* check duplicate ip */
|
||||||
for(n = 0; n < i; n++){
|
for(n = 0; n < i; n++){
|
||||||
snprint(buf, sizeof buf, "local#dns#server%d", n);
|
snprint(buf, sizeof buf, "%s#%d", dp->name, n);
|
||||||
nsdp = dnlookup(buf, class, 0);
|
nsdp = dnlookup(buf, class, 0);
|
||||||
if(nsdp == nil)
|
if(nsdp == nil)
|
||||||
continue;
|
continue;
|
||||||
|
@ -931,7 +931,7 @@ addlocaldnsserver(DN *dp, int class, char *addr, int i)
|
||||||
rrfreelist(rp);
|
rrfreelist(rp);
|
||||||
}
|
}
|
||||||
|
|
||||||
snprint(buf, sizeof buf, "local#dns#server%d", i);
|
snprint(buf, sizeof buf, "%s#%d", dp->name, i);
|
||||||
nsdp = dnlookup(buf, class, 1);
|
nsdp = dnlookup(buf, class, 1);
|
||||||
|
|
||||||
/* ns record for name server, make up an impossible name */
|
/* ns record for name server, make up an impossible name */
|
||||||
|
@ -967,6 +967,33 @@ dnsservers(int class)
|
||||||
RR *nsrp;
|
RR *nsrp;
|
||||||
DN *dp;
|
DN *dp;
|
||||||
|
|
||||||
|
/* try first DoT servers */
|
||||||
|
dp = dnlookup("local#dot#servers", class, 1);
|
||||||
|
nsrp = rrlookup(dp, Tns, NOneg);
|
||||||
|
if(nsrp != nil)
|
||||||
|
return nsrp;
|
||||||
|
|
||||||
|
p = getenv("DOTSERVER"); /* list of ip addresses */
|
||||||
|
if(p != nil && (n = tokenize(p, args, nelem(args))) > 0){
|
||||||
|
for(i = 0; i < n; i++)
|
||||||
|
addlocaldnsserver(dp, class, args[i], i);
|
||||||
|
} else {
|
||||||
|
t = lookupinfo("@dot"); /* @dot=ip1 ... */
|
||||||
|
if(t == nil)
|
||||||
|
return nil;
|
||||||
|
i = 0;
|
||||||
|
for(nt = t; nt != nil; nt = nt->entry){
|
||||||
|
addlocaldnsserver(dp, class, nt->val, i);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
ndbfree(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
nsrp = rrlookup(dp, Tns, NOneg);
|
||||||
|
if(nsrp != nil)
|
||||||
|
return nsrp;
|
||||||
|
|
||||||
|
/* try regular local DNS servers */
|
||||||
dp = dnlookup("local#dns#servers", class, 1);
|
dp = dnlookup("local#dns#servers", class, 1);
|
||||||
nsrp = rrlookup(dp, Tns, NOneg);
|
nsrp = rrlookup(dp, Tns, NOneg);
|
||||||
if(nsrp != nil)
|
if(nsrp != nil)
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
#include <libc.h>
|
#include <libc.h>
|
||||||
#include <ip.h>
|
#include <ip.h>
|
||||||
#include <bio.h>
|
#include <bio.h>
|
||||||
|
#include <mp.h>
|
||||||
|
#include <libsec.h>
|
||||||
#include <ndb.h>
|
#include <ndb.h>
|
||||||
#include "dns.h"
|
#include "dns.h"
|
||||||
|
|
||||||
|
@ -79,7 +81,7 @@ procgetname(void)
|
||||||
return strdup(lp+1);
|
return strdup(lp+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
rrfreelistptr(RR **rpp)
|
rrfreelistptr(RR **rpp)
|
||||||
{
|
{
|
||||||
RR *rp;
|
RR *rp;
|
||||||
|
@ -267,9 +269,13 @@ issuequery(Query *qp, char *name, int class, int recurse)
|
||||||
*/
|
*/
|
||||||
if(cfg.resolver){
|
if(cfg.resolver){
|
||||||
nsrp = randomize(getdnsservers(class));
|
nsrp = randomize(getdnsservers(class));
|
||||||
if(nsrp != nil)
|
if(nsrp != nil){
|
||||||
|
int dot = strncmp(nsrp->owner->name, "local#dot#server", 16) == 0;
|
||||||
if(netqueryns(qp, nsrp) > Answnone)
|
if(netqueryns(qp, nsrp) > Answnone)
|
||||||
return rrlookup(qp->dp, qp->type, OKneg);
|
return rrlookup(qp->dp, qp->type, OKneg);
|
||||||
|
else if(dot)
|
||||||
|
return nil; /* do not fall-back for DoT */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -733,7 +739,7 @@ readreply(Query *qp, int medium, int fd, uvlong endms,
|
||||||
/*
|
/*
|
||||||
* return non-0 if first list includes second list
|
* return non-0 if first list includes second list
|
||||||
*/
|
*/
|
||||||
int
|
static int
|
||||||
contains(RR *rp1, RR *rp2)
|
contains(RR *rp1, RR *rp2)
|
||||||
{
|
{
|
||||||
RR *trp1, *trp2;
|
RR *trp1, *trp2;
|
||||||
|
@ -753,7 +759,7 @@ contains(RR *rp1, RR *rp2)
|
||||||
/*
|
/*
|
||||||
* return multicast version if any
|
* return multicast version if any
|
||||||
*/
|
*/
|
||||||
int
|
static int
|
||||||
ipisbm(uchar *ip)
|
ipisbm(uchar *ip)
|
||||||
{
|
{
|
||||||
if(isv4(ip)){
|
if(isv4(ip)){
|
||||||
|
@ -1166,16 +1172,31 @@ writenet(Query *qp, int medium, int fd, uchar *pkt, int len, Dest *p)
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum {
|
||||||
|
Maxfree = 4,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct {
|
||||||
|
QLock lk;
|
||||||
|
struct {
|
||||||
|
uvlong when;
|
||||||
|
char *dest;
|
||||||
|
int fd;
|
||||||
|
} l[Maxfree];
|
||||||
|
} tcpfree;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* send a query via tcp to a single address
|
* send a query via tcp to a single address
|
||||||
* and read the answer(s) into mp->an.
|
* and read the answer(s) into mp->an.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
tcpquery(Query *qp, uchar *pkt, int len, Dest *p, uvlong endms, DNSmsg *mp)
|
tcpquery(Query *qp, uchar *pkt, int len, Dest *p, uvlong endms, DNSmsg *mp, int tls)
|
||||||
{
|
{
|
||||||
char buf[NETPATHLEN];
|
char buf[NETPATHLEN];
|
||||||
int fd, rv;
|
int fd, rv, i, retry;
|
||||||
long ms;
|
long ms;
|
||||||
|
TLSconn conn;
|
||||||
|
Thumbprint *thumb;
|
||||||
|
|
||||||
memset(mp, 0, sizeof *mp);
|
memset(mp, 0, sizeof *mp);
|
||||||
|
|
||||||
|
@ -1185,57 +1206,139 @@ tcpquery(Query *qp, uchar *pkt, int len, Dest *p, uvlong endms, DNSmsg *mp)
|
||||||
if(ms > Maxtcpdialtm)
|
if(ms > Maxtcpdialtm)
|
||||||
ms = Maxtcpdialtm;
|
ms = Maxtcpdialtm;
|
||||||
|
|
||||||
procsetname("tcp query to %I/%s for %s %s", p->a, p->s->name,
|
procsetname("%s query to %I/%s for %s %s", tls ? "tls" : "tcp", p->a, p->s->name,
|
||||||
qp->dp->name, rrname(qp->type, buf, sizeof buf));
|
qp->dp->name, rrname(qp->type, buf, sizeof buf));
|
||||||
|
|
||||||
snprint(buf, sizeof buf, "%s/tcp!%I!53", mntpt, p->a);
|
snprint(buf, sizeof buf, "%s/tcp!%I!%s", mntpt, p->a, tls ? "853" : "53");
|
||||||
|
|
||||||
|
fd = -1;
|
||||||
|
retry = 0;
|
||||||
|
qlock(&tcpfree.lk);
|
||||||
|
for(i = 0; i < nelem(tcpfree.l); i++){
|
||||||
|
if(tcpfree.l[i].dest == nil || tcpfree.l[i].fd == -1)
|
||||||
|
continue;
|
||||||
|
if(strcmp(tcpfree.l[i].dest, buf) != 0)
|
||||||
|
continue;
|
||||||
|
/* RFC does not specify connection reuse timeout */
|
||||||
|
if(nowms - tcpfree.l[i].when < 5000){
|
||||||
|
fd = tcpfree.l[i].fd;
|
||||||
|
tcpfree.l[i].fd = -1;
|
||||||
|
retry++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
qunlock(&tcpfree.lk);
|
||||||
|
if(fd != -1)
|
||||||
|
goto Found;
|
||||||
|
|
||||||
|
Retry:
|
||||||
alarm(ms);
|
alarm(ms);
|
||||||
fd = dial(buf, nil, nil, nil);
|
fd = dial(buf, nil, nil, nil);
|
||||||
alarm(0);
|
if(fd < 0){
|
||||||
if (fd < 0) {
|
alarm(0);
|
||||||
dnslog("%d: can't dial %s for %I/%s: %r",
|
dnslog("%d: can't dial %s for %I/%s: %r",
|
||||||
qp->req->id, buf, p->a, p->s->name);
|
qp->req->id, buf, p->a, p->s->name);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
if(tls){
|
||||||
|
memset(&conn, 0, sizeof conn);
|
||||||
|
rv = tlsClient(fd, &conn);
|
||||||
|
alarm(0);
|
||||||
|
if(rv >= 0){
|
||||||
|
fd = rv;
|
||||||
|
thumb = initThumbprints("/sys/lib/tls/dns", nil, "x509");
|
||||||
|
if(thumb == nil || !okCertificate(conn.cert, conn.certlen, thumb)){
|
||||||
|
dnslog("%d: invalid fingerprint for %s; echo 'x509 %r' >>/sys/lib/tls/dns",
|
||||||
|
qp->req->id, buf);
|
||||||
|
rv = -1;
|
||||||
|
}
|
||||||
|
free(conn.cert);
|
||||||
|
free(conn.sessionID);
|
||||||
|
freeThumbprints(thumb);
|
||||||
|
}
|
||||||
|
if(rv < 0){
|
||||||
|
close(fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
alarm(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
Found:
|
||||||
rv = writenet(qp, Tcp, fd, pkt, len, p);
|
rv = writenet(qp, Tcp, fd, pkt, len, p);
|
||||||
if(rv == 0){
|
if(rv == 0){
|
||||||
timems(); /* account for time dialing and sending */
|
timems(); /* account for time dialing and sending */
|
||||||
rv = readreply(qp, Tcp, fd, endms, mp, pkt);
|
rv = readreply(qp, Tcp, fd, endms, mp, pkt);
|
||||||
}
|
}
|
||||||
close(fd);
|
|
||||||
|
if(rv < 0){
|
||||||
|
close(fd);
|
||||||
|
if(retry){
|
||||||
|
retry = 0;
|
||||||
|
goto Retry;
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
qlock(&tcpfree.lk);
|
||||||
|
if(tcpfree.l[nelem(tcpfree.l)-1].dest != nil){
|
||||||
|
close(tcpfree.l[nelem(tcpfree.l)-1].fd);
|
||||||
|
free(tcpfree.l[nelem(tcpfree.l)-1].dest);
|
||||||
|
}
|
||||||
|
memmove(tcpfree.l + 1, tcpfree.l, sizeof(tcpfree.l[0])*(nelem(tcpfree.l)-1));
|
||||||
|
tcpfree.l[0].when = nowms;
|
||||||
|
tcpfree.l[0].fd = fd;
|
||||||
|
tcpfree.l[0].dest = estrdup(buf);
|
||||||
|
qunlock(&tcpfree.lk);
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
tlsqueryns(Query *qp, uchar *pkt, int len)
|
||||||
|
{
|
||||||
|
Dest dest[Maxdest], *p;
|
||||||
|
int rv, n;
|
||||||
|
uvlong endms;
|
||||||
|
DNSmsg m;
|
||||||
|
|
||||||
|
/* populates dest with v4 and v6 addresses. */
|
||||||
|
n = 0;
|
||||||
|
n = serveraddrs(qp, dest, n, Ta);
|
||||||
|
n = serveraddrs(qp, dest, n, Taaaa);
|
||||||
|
endms = nowms + 500;
|
||||||
|
for(p = dest; p < dest+n; p++){
|
||||||
|
if(tcpquery(qp, pkt, len, p, endms, &m, 1) == 0){
|
||||||
|
/* free or incorporate RRs in m */
|
||||||
|
rv = procansw(qp, p, &m);
|
||||||
|
if(rv > Answnone)
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if all servers returned failure, propagate it */
|
||||||
|
qp->dp->respcode = Rserver;
|
||||||
|
for(p = dest; p < dest+n; p++)
|
||||||
|
if(p->code != Rserver)
|
||||||
|
qp->dp->respcode = Rok;
|
||||||
|
|
||||||
|
return Answnone;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* query name servers. fill in pkt with on-the-wire representation of a
|
* query name servers. fill in pkt with on-the-wire representation of a
|
||||||
* DNSmsg derived from qp. if the name server returns a pointer to another
|
* DNSmsg derived from qp. if the name server returns a pointer to another
|
||||||
* name server, recurse.
|
* name server, recurse.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
udpqueryns(Query *qp, int fd, uchar *pkt)
|
udpqueryns(Query *qp, int fd, uchar *pkt, int len)
|
||||||
{
|
{
|
||||||
Dest dest[Maxdest], *edest, *p, *np;
|
Dest dest[Maxdest], *edest, *p, *np;
|
||||||
int ndest, replywaits, len, flag, rv, n;
|
int ndest, replywaits, rv, n;
|
||||||
uchar srcip[IPaddrlen];
|
uchar srcip[IPaddrlen];
|
||||||
char buf[32];
|
char buf[32];
|
||||||
uvlong endms;
|
uvlong endms;
|
||||||
DNSmsg m;
|
DNSmsg m;
|
||||||
RR *rp;
|
|
||||||
|
|
||||||
/* prepare server RR's for incremental lookup */
|
|
||||||
for(rp = qp->nsrp; rp; rp = rp->next)
|
|
||||||
rp->marker = 0;
|
|
||||||
|
|
||||||
/* request recursion only for local/override dns servers */
|
|
||||||
flag = Oquery;
|
|
||||||
if(strncmp(qp->nsrp->owner->name, "local#", 6) == 0
|
|
||||||
|| strncmp(qp->nsrp->owner->name, "override#", 9) == 0)
|
|
||||||
flag |= Frecurse;
|
|
||||||
|
|
||||||
/* pack request into a udp message */
|
|
||||||
qp->id = rand();
|
|
||||||
len = mkreq(qp->dp, qp->type, pkt, flag, qp->id);
|
|
||||||
|
|
||||||
/* no destination yet */
|
/* no destination yet */
|
||||||
edest = dest;
|
edest = dest;
|
||||||
|
@ -1307,7 +1410,7 @@ udpqueryns(Query *qp, int fd, uchar *pkt)
|
||||||
/* if response was truncated, try tcp */
|
/* if response was truncated, try tcp */
|
||||||
if(m.flags & Ftrunc){
|
if(m.flags & Ftrunc){
|
||||||
freeanswers(&m);
|
freeanswers(&m);
|
||||||
if(tcpquery(qp, pkt, len, p, endms, &m) < 0)
|
if(tcpquery(qp, pkt, len, p, endms, &m, 0) < 0)
|
||||||
break; /* failed via tcp too */
|
break; /* failed via tcp too */
|
||||||
if(m.flags & Ftrunc){
|
if(m.flags & Ftrunc){
|
||||||
freeanswers(&m);
|
freeanswers(&m);
|
||||||
|
@ -1336,27 +1439,44 @@ udpqueryns(Query *qp, int fd, uchar *pkt)
|
||||||
return Answnone;
|
return Answnone;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* in principle we could use a single descriptor for a udp port
|
|
||||||
* to send all queries and receive all the answers to them,
|
|
||||||
* but we'd have to sort out the answers by dns-query id.
|
|
||||||
*/
|
|
||||||
static int
|
static int
|
||||||
udpquery(Query *qp)
|
doquery(Query *qp)
|
||||||
{
|
{
|
||||||
int fd, rv;
|
int fd, rv, len, flag;
|
||||||
uchar *pkt;
|
uchar *pkt;
|
||||||
|
RR *rp;
|
||||||
|
|
||||||
pkt = emalloc(Maxudp+Udphdrsize);
|
pkt = emalloc(Maxudp+Udphdrsize);
|
||||||
fd = udpport(mntpt);
|
/* prepare server RR's for incremental lookup */
|
||||||
if (fd < 0) {
|
for(rp = qp->nsrp; rp; rp = rp->next)
|
||||||
dnslog("%d: can't get udpport for %s query of name %s: %r",
|
rp->marker = 0;
|
||||||
qp->req->id, mntpt, qp->dp->name);
|
/* request recursion only for local/override dns servers */
|
||||||
rv = -1;
|
flag = Oquery;
|
||||||
goto Out;
|
if(strncmp(qp->nsrp->owner->name, "local#", 6) == 0
|
||||||
|
|| strncmp(qp->nsrp->owner->name, "override#", 9) == 0)
|
||||||
|
flag |= Frecurse;
|
||||||
|
/* pack request into a udp message */
|
||||||
|
qp->id = rand();
|
||||||
|
len = mkreq(qp->dp, qp->type, pkt, flag, qp->id);
|
||||||
|
if(strncmp(qp->nsrp->owner->name, "local#dot#server", 16) == 0
|
||||||
|
|| strncmp(qp->nsrp->owner->name, "override#dot#server", 16) == 0){
|
||||||
|
rv = tlsqueryns(qp, pkt, len);
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* in principle we could use a single descriptor for a udp port
|
||||||
|
* to send all queries and receive all the answers to them,
|
||||||
|
* but we'd have to sort out the answers by dns-query id.
|
||||||
|
*/
|
||||||
|
fd = udpport(mntpt);
|
||||||
|
if (fd < 0) {
|
||||||
|
dnslog("%d: can't get udpport for %s query of name %s: %r",
|
||||||
|
qp->req->id, mntpt, qp->dp->name);
|
||||||
|
rv = -1;
|
||||||
|
goto Out;
|
||||||
|
}
|
||||||
|
rv = udpqueryns(qp, fd, pkt, len);
|
||||||
|
close(fd);
|
||||||
}
|
}
|
||||||
rv = udpqueryns(qp, fd, pkt);
|
|
||||||
close(fd);
|
|
||||||
Out:
|
Out:
|
||||||
free(pkt);
|
free(pkt);
|
||||||
return rv;
|
return rv;
|
||||||
|
@ -1383,5 +1503,5 @@ netquery(Query *qp)
|
||||||
if(!qp->req->isslave && strcmp(qp->req->from, "9p") == 0)
|
if(!qp->req->isslave && strcmp(qp->req->from, "9p") == 0)
|
||||||
return Answnone;
|
return Answnone;
|
||||||
|
|
||||||
return udpquery(qp);
|
return doquery(qp);
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,7 +92,7 @@ static char *respond(Job*, Mfile*, RR*, char*, int, int);
|
||||||
void
|
void
|
||||||
usage(void)
|
usage(void)
|
||||||
{
|
{
|
||||||
fprint(2, "usage: %s [-FnrLR] [-a maxage] [-f ndb-file] [-N target] "
|
fprint(2, "usage: %s [-FnrLR] [-a maxage] [-c cert.pem] [-f ndb-file] [-N target] "
|
||||||
"[-x netmtpt] [-s [addrs...]]\n", argv0);
|
"[-x netmtpt] [-s [addrs...]]\n", argv0);
|
||||||
exits("usage");
|
exits("usage");
|
||||||
}
|
}
|
||||||
|
@ -101,10 +101,12 @@ void
|
||||||
main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
char ext[Maxpath], servefile[Maxpath];
|
char ext[Maxpath], servefile[Maxpath];
|
||||||
|
char *cert;
|
||||||
Dir *dir;
|
Dir *dir;
|
||||||
|
|
||||||
setnetmtpt(mntpt, sizeof mntpt, nil);
|
setnetmtpt(mntpt, sizeof mntpt, nil);
|
||||||
ext[0] = 0;
|
ext[0] = 0;
|
||||||
|
cert = nil;
|
||||||
ARGBEGIN{
|
ARGBEGIN{
|
||||||
case 'a':
|
case 'a':
|
||||||
maxage = atol(EARGF(usage()));
|
maxage = atol(EARGF(usage()));
|
||||||
|
@ -141,6 +143,9 @@ main(int argc, char *argv[])
|
||||||
cfg.serve = 1; /* serve network */
|
cfg.serve = 1; /* serve network */
|
||||||
cfg.cachedb = 1;
|
cfg.cachedb = 1;
|
||||||
break;
|
break;
|
||||||
|
case 'c':
|
||||||
|
cert = EARGF(usage());
|
||||||
|
break;
|
||||||
case 'x':
|
case 'x':
|
||||||
setnetmtpt(mntpt, sizeof mntpt, EARGF(usage()));
|
setnetmtpt(mntpt, sizeof mntpt, EARGF(usage()));
|
||||||
setext(ext, sizeof ext, mntpt);
|
setext(ext, sizeof ext, mntpt);
|
||||||
|
@ -181,11 +186,15 @@ main(int argc, char *argv[])
|
||||||
if(cfg.serve){
|
if(cfg.serve){
|
||||||
if(argc == 0) {
|
if(argc == 0) {
|
||||||
dnudpserver(mntpt, "*");
|
dnudpserver(mntpt, "*");
|
||||||
dntcpserver(mntpt, "*");
|
dntcpserver(mntpt, "*", nil);
|
||||||
|
if(cert != nil)
|
||||||
|
dntcpserver(mntpt, "*", cert);
|
||||||
} else {
|
} else {
|
||||||
while(argc-- > 0){
|
while(argc-- > 0){
|
||||||
dnudpserver(mntpt, *argv);
|
dnudpserver(mntpt, *argv);
|
||||||
dntcpserver(mntpt, *argv);
|
dntcpserver(mntpt, *argv, nil);
|
||||||
|
if(cert != nil)
|
||||||
|
dntcpserver(mntpt, *argv, cert);
|
||||||
argv++;
|
argv++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -522,7 +522,7 @@ void dnserver(DNSmsg*, DNSmsg*, Request*, uchar *, int);
|
||||||
void dnudpserver(char*, char*);
|
void dnudpserver(char*, char*);
|
||||||
|
|
||||||
/* dntcpserver.c */
|
/* dntcpserver.c */
|
||||||
void dntcpserver(char*, char*);
|
void dntcpserver(char*, char*, char*);
|
||||||
|
|
||||||
/* dnnotify.c */
|
/* dnnotify.c */
|
||||||
void dnnotify(DNSmsg*, DNSmsg*, Request*);
|
void dnnotify(DNSmsg*, DNSmsg*, Request*);
|
||||||
|
|
|
@ -172,14 +172,18 @@ getdnsservers(int class)
|
||||||
{
|
{
|
||||||
uchar ip[IPaddrlen];
|
uchar ip[IPaddrlen];
|
||||||
DN *nsdp;
|
DN *nsdp;
|
||||||
RR *rp;
|
RR *rp, *ns;
|
||||||
|
char name[64];
|
||||||
|
|
||||||
if(servername == nil)
|
if(servername == nil)
|
||||||
return dnsservers(class);
|
return dnsservers(class);
|
||||||
if(parseip(ip, servername) == -1){
|
|
||||||
nsdp = idnlookup(servername, class, 1);
|
snprint(name, sizeof name, "override#%s#server", servername[0] == '!' ? "dot" : "dns");
|
||||||
|
ns = rralloc(Tns);
|
||||||
|
if(parseip(ip, servername+1) == -1){
|
||||||
|
nsdp = idnlookup(servername+1, class, 1);
|
||||||
} else {
|
} else {
|
||||||
nsdp = dnlookup("local#dns#server", class, 1);
|
nsdp = dnlookup(name, class, 1);
|
||||||
rp = rralloc(isv4(ip) ? Ta : Taaaa);
|
rp = rralloc(isv4(ip) ? Ta : Taaaa);
|
||||||
rp->owner = nsdp;
|
rp->owner = nsdp;
|
||||||
rp->ip = ipalookup(ip, class, 1);
|
rp->ip = ipalookup(ip, class, 1);
|
||||||
|
@ -187,10 +191,9 @@ getdnsservers(int class)
|
||||||
rp->ttl = 10*Min;
|
rp->ttl = 10*Min;
|
||||||
rrattach(rp, Authoritative);
|
rrattach(rp, Authoritative);
|
||||||
}
|
}
|
||||||
rp = rralloc(Tns);
|
ns->owner = dnlookup(name, class, 1);
|
||||||
rp->owner = dnlookup("override#dns#servers", class, 1);
|
ns->host = nsdp;
|
||||||
rp->host = nsdp;
|
return ns;
|
||||||
return rp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -201,7 +204,7 @@ setserver(char *server)
|
||||||
servername = nil;
|
servername = nil;
|
||||||
cfg.resolver = 0;
|
cfg.resolver = 0;
|
||||||
}
|
}
|
||||||
if(server == nil || *server == 0)
|
if(server == nil || server[0] == 0 || server[1] == 0)
|
||||||
return 0;
|
return 0;
|
||||||
servername = estrdup(server);
|
servername = estrdup(server);
|
||||||
cfg.resolver = 1;
|
cfg.resolver = 1;
|
||||||
|
@ -276,8 +279,8 @@ docmd(int n, char **f)
|
||||||
name = type = nil;
|
name = type = nil;
|
||||||
tmpsrv = 0;
|
tmpsrv = 0;
|
||||||
|
|
||||||
if(*f[0] == '@') {
|
if(*f[0] == '@' || *f[0] == '!') {
|
||||||
if(setserver(f[0]+1) < 0)
|
if(setserver(f[0]) < 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
switch(n){
|
switch(n){
|
||||||
|
@ -306,5 +309,5 @@ docmd(int n, char **f)
|
||||||
doquery(name, type);
|
doquery(name, type);
|
||||||
|
|
||||||
if(tmpsrv)
|
if(tmpsrv)
|
||||||
setserver("");
|
setserver("@");
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
#include <bio.h>
|
#include <bio.h>
|
||||||
#include <ndb.h>
|
#include <ndb.h>
|
||||||
#include <ip.h>
|
#include <ip.h>
|
||||||
|
#include <mp.h>
|
||||||
|
#include <libsec.h>
|
||||||
#include "dns.h"
|
#include "dns.h"
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
|
@ -12,10 +14,10 @@ enum {
|
||||||
static int readmsg(int, uchar*, int);
|
static int readmsg(int, uchar*, int);
|
||||||
static int reply(int, uchar *, DNSmsg*, Request*, uchar*);
|
static int reply(int, uchar *, DNSmsg*, Request*, uchar*);
|
||||||
static int dnzone(int, uchar *, DNSmsg*, DNSmsg*, Request*, uchar*);
|
static int dnzone(int, uchar *, DNSmsg*, DNSmsg*, Request*, uchar*);
|
||||||
static int tcpannounce(char *mntpt, char *addr, char caller[128]);
|
static int tcpannounce(char *mntpt, char *addr, char caller[128], char *cert);
|
||||||
|
|
||||||
void
|
void
|
||||||
dntcpserver(char *mntpt, char *addr)
|
dntcpserver(char *mntpt, char *addr, char *cert)
|
||||||
{
|
{
|
||||||
volatile int fd, len, rcode, rv;
|
volatile int fd, len, rcode, rv;
|
||||||
volatile long ms;
|
volatile long ms;
|
||||||
|
@ -40,7 +42,7 @@ dntcpserver(char *mntpt, char *addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
procsetname("%s: tcp server %s", mntpt, addr);
|
procsetname("%s: tcp server %s", mntpt, addr);
|
||||||
if((fd = tcpannounce(mntpt, addr, caller)) < 0){
|
if((fd = tcpannounce(mntpt, addr, caller, cert)) < 0){
|
||||||
warning("can't announce %s on %s: %r", addr, mntpt);
|
warning("can't announce %s on %s: %r", addr, mntpt);
|
||||||
_exits(0);
|
_exits(0);
|
||||||
}
|
}
|
||||||
|
@ -259,13 +261,20 @@ out:
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
tcpannounce(char *mntpt, char *addr, char caller[128])
|
tcpannounce(char *mntpt, char *addr, char caller[128], char *cert)
|
||||||
{
|
{
|
||||||
char adir[NETPATHLEN], ldir[NETPATHLEN], buf[128];
|
char adir[NETPATHLEN], ldir[NETPATHLEN], buf[128];
|
||||||
int acfd, lcfd, dfd, wfd, rfd, procs;
|
int acfd, lcfd, dfd, wfd, rfd, procs;
|
||||||
|
PEMChain *chain = nil;
|
||||||
|
|
||||||
|
if(cert != nil){
|
||||||
|
chain = readcertchain(cert);
|
||||||
|
if(chain == nil)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* announce tcp dns port */
|
/* announce tcp dns port */
|
||||||
snprint(buf, sizeof(buf), "%s/tcp!%s!53", mntpt, addr);
|
snprint(buf, sizeof(buf), "%s/tcp!%s!%s", mntpt, addr, cert == nil ? "53" : "853");
|
||||||
acfd = announce(buf, adir);
|
acfd = announce(buf, adir);
|
||||||
if(acfd < 0)
|
if(acfd < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -277,7 +286,6 @@ tcpannounce(char *mntpt, char *addr, char caller[128])
|
||||||
close(acfd);
|
close(acfd);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
procs = 0;
|
procs = 0;
|
||||||
for(;;) {
|
for(;;) {
|
||||||
if(procs >= Maxprocs || (procs % 8) == 0){
|
if(procs >= Maxprocs || (procs % 8) == 0){
|
||||||
|
@ -314,7 +322,23 @@ tcpannounce(char *mntpt, char *addr, char caller[128])
|
||||||
close(lcfd);
|
close(lcfd);
|
||||||
if(dfd < 0)
|
if(dfd < 0)
|
||||||
_exits(0);
|
_exits(0);
|
||||||
|
if(chain != nil){
|
||||||
|
TLSconn conn;
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
memset(&conn, 0, sizeof conn);
|
||||||
|
conn.cert = emalloc(conn.certlen = chain->pemlen);
|
||||||
|
memmove(conn.cert, chain->pem, conn.certlen);
|
||||||
|
conn.chain = chain->next;
|
||||||
|
fd = tlsServer(dfd, &conn);
|
||||||
|
if(fd < 0){
|
||||||
|
close(dfd);
|
||||||
|
_exits(0);
|
||||||
|
}
|
||||||
|
free(conn.cert);
|
||||||
|
free(conn.sessionID);
|
||||||
|
dfd = fd;
|
||||||
|
}
|
||||||
/* get the callers ip!port */
|
/* get the callers ip!port */
|
||||||
memset(caller, 0, 128);
|
memset(caller, 0, 128);
|
||||||
snprint(buf, sizeof(buf), "%s/remote", ldir);
|
snprint(buf, sizeof(buf), "%s/remote", ldir);
|
||||||
|
@ -322,7 +346,6 @@ tcpannounce(char *mntpt, char *addr, char caller[128])
|
||||||
read(rfd, caller, 128-1);
|
read(rfd, caller, 128-1);
|
||||||
close(rfd);
|
close(rfd);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* child returns */
|
/* child returns */
|
||||||
return dfd;
|
return dfd;
|
||||||
default:
|
default:
|
||||||
|
|
Loading…
Reference in a new issue