summaryrefslogtreecommitdiff
path: root/usr.sbin/rebound/rebound.c
diff options
context:
space:
mode:
authorTed Unangst <tedu@cvs.openbsd.org>2018-12-06 16:51:20 +0000
committerTed Unangst <tedu@cvs.openbsd.org>2018-12-06 16:51:20 +0000
commit60fd556224f9606e4ccc8be299ef73e5458551a4 (patch)
tree672454234cc92626186a262eafe7ce7b4e1754c0 /usr.sbin/rebound/rebound.c
parente441d9f5046bfc459ef3d11f034a1283935e01ec (diff)
add very experimental support for dns over https. (RFC 8484)
performance may be less than great. ok anton
Diffstat (limited to 'usr.sbin/rebound/rebound.c')
-rw-r--r--usr.sbin/rebound/rebound.c64
1 files changed, 55 insertions, 9 deletions
diff --git a/usr.sbin/rebound/rebound.c b/usr.sbin/rebound/rebound.c
index 311607ccd6f..e3b97a16737 100644
--- a/usr.sbin/rebound/rebound.c
+++ b/usr.sbin/rebound/rebound.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rebound.c,v 1.102 2018/11/20 03:42:56 tedu Exp $ */
+/* $OpenBSD: rebound.c,v 1.103 2018/12/06 16:51:19 tedu Exp $ */
/*
* Copyright (c) 2015 Ted Unangst <tedu@openbsd.org>
*
@@ -51,6 +51,14 @@
uint16_t randomid(void);
+int https_init(void);
+int https_connect(const char *ip, const char *name);
+int https_query(uint8_t *query, size_t qlen, uint8_t *resp, size_t *resplen);
+
+static int https;
+static char https_ip[256];
+static char https_name[256];
+
union sockun {
struct sockaddr a;
struct sockaddr_storage s;
@@ -122,7 +130,9 @@ static int connmax;
static uint64_t conntotal;
static int stopaccepting;
-static void
+static void sendreply(struct request *req, uint8_t *buf, size_t r);
+
+void
logmsg(int prio, const char *msg, ...)
{
va_list ap;
@@ -140,7 +150,7 @@ logmsg(int prio, const char *msg, ...)
}
}
-static void __dead
+void __dead
logerr(const char *msg, ...)
{
va_list ap;
@@ -418,6 +428,26 @@ newrequest(int ud, struct sockaddr *remoteaddr)
req->cacheent = hit;
}
+ if (https) {
+ int rv;
+ char resp[65536];
+ size_t resplen;
+
+ rv = https_query(buf, r, resp, &resplen);
+ if (rv != 0) {
+ rv = https_connect(https_ip, https_name);
+ if (rv == 0)
+ rv = https_query(buf, r, buf, &resplen);
+ }
+ if (rv != 0) {
+ logmsg(LOG_NOTICE, "failed to make https query");
+ goto fail;
+ }
+ sendreply(req, resp, resplen);
+ freerequest(req);
+ return NULL;
+ }
+
req->s = socket(remoteaddr->sa_family, SOCK_DGRAM, 0);
if (req->s == -1)
goto fail;
@@ -485,17 +515,13 @@ minttl(struct dnspacket *resp, u_int rlen)
}
static void
-sendreply(struct request *req)
+sendreply(struct request *req, uint8_t *buf, size_t r)
{
- uint8_t buf[65536];
struct dnspacket *resp;
struct dnscache *ent;
- size_t r;
uint32_t ttl;
resp = (struct dnspacket *)buf;
-
- r = recv(req->s, buf, sizeof(buf), 0);
if (r == 0 || r == -1 || r < sizeof(struct dnspacket))
return;
if (resp->id != req->reqid)
@@ -540,6 +566,16 @@ sendreply(struct request *req)
}
}
+static void
+handlereply(struct request *req)
+{
+ uint8_t buf[65536];
+ size_t r;
+
+ r = recv(req->s, buf, sizeof(buf), 0);
+ sendreply(req, buf, r);
+}
+
static struct request *
tcpphasetwo(struct request *req)
{
@@ -743,6 +779,7 @@ readconfig(int conffd, union sockun *remoteaddr)
{
const char ns[] = "nameserver";
const char rc[] = "record";
+ const char doh[] = "https";
char buf[1024];
char *p;
struct sockaddr_in *sin = &remoteaddr->i;
@@ -791,6 +828,13 @@ readconfig(int conffd, union sockun *remoteaddr)
preloadA(name, value);
preloadPTR(value, name);
}
+ } else if (strncmp(buf, doh, strlen(doh)) == 0) {
+ p = buf + strlen(doh) + 1;
+ if (sscanf(p, "%255s %255s", https_ip, https_name) != 2)
+ logerr("do not like https line");
+ https = 1;
+ if (rv == -1)
+ rv = 0;
}
}
fclose(conf);
@@ -934,7 +978,7 @@ workerloop(int conffd, int ud, int ld, int ud6, int ld6)
} else {
req = ke->udata;
if (req->tcp == 0)
- sendreply(req);
+ handlereply(req);
freerequest(req);
}
break;
@@ -1149,6 +1193,8 @@ main(int argc, char **argv)
signal(SIGPIPE, SIG_IGN);
signal(SIGUSR1, SIG_IGN);
+ https_init();
+
while ((ch = getopt(argc, argv, "c:dl:W")) != -1) {
switch (ch) {
case 'c':