summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/dnsfunneld.html10
-rw-r--r--src/dnsfunnel/dnsfunneld.c35
-rw-r--r--src/dnsfunnel/dnsfunneld_answer.c15
3 files changed, 36 insertions, 24 deletions
diff --git a/doc/dnsfunneld.html b/doc/dnsfunneld.html
index 5181db1..7fde21f 100644
--- a/doc/dnsfunneld.html
+++ b/doc/dnsfunneld.html
@@ -29,7 +29,7 @@ queries, the responses, or both.
<h2> Interface </h2>
<pre>
- dnsfunneld [ -v <em>verbosity</em> ] [ -1 ] [ -U | -u <em>uid</em> -g <em>gid</em> ] [ -i <em>ip</em>:<em>port</em> ] [ -R <em>root</em> ] [ -b <em>bufsize</em> ] [ -T | -t ] [ -N | -n ]
+ dnsfunneld [ -v <em>verbosity</em> ] [ -1 ] [ -U | -u <em>uid</em> -g <em>gid</em> ] [ -i <em>ip</em>:<em>port</em> ] [ -R <em>root</em> ] [ -b <em>bufsize</em> ] [ -t <em>globaltimeout</em> ] [ -X | -x ] [ -N | -n ]
</pre>
<ul>
@@ -97,6 +97,10 @@ to <tt>-R</tt>. </li>
<li> <tt>-b&nbsp;<em>bufsize</em></tt>&nbsp;: try and reserve a kernel buffer
size of <em>bufsize</em> bytes for the socket. The default is whatever the
default is for your kernel. </li>
+ <li> <tt>-t&nbsp;<em>globaltimeout</em></tt>&nbsp;: maximum resolution time.
+If a query takes more than <em>globaltimeout</em> milliseconds to resolve,
+abandon it and return a SERVFAIL to the client. Default is 0, meaning infinite:
+no global timeout is set. </li>
</ul>
<p>
@@ -105,9 +109,9 @@ features. See below for the detail of operations.
</p>
<ul>
- <li> <tt>-T</tt>&nbsp;: Do not activate truncation of responses. This is
+ <li> <tt>-X</tt>&nbsp;: Do not activate truncation of responses. This is
the default. </li>
- <li> <tt>-t</tt>&nbsp;: If a DNS response is bigger than 510 bytes,
+ <li> <tt>-x</tt>&nbsp;: If a DNS response is bigger than 510 bytes,
truncate its last resource records until it fits into 510 bytes and can
be sent in a UDP packet. </li>
<li> <tt>-N</tt>&nbsp;: Do not activate NXDOMAIN workaround. This is the
diff --git a/src/dnsfunnel/dnsfunneld.c b/src/dnsfunnel/dnsfunneld.c
index d65cb7c..48965f1 100644
--- a/src/dnsfunnel/dnsfunneld.c
+++ b/src/dnsfunnel/dnsfunneld.c
@@ -36,13 +36,13 @@
#include "dnsfunneld.h"
-#define USAGE "dnsfunneld [ -v verbosity ] [ -1 ] [ -U | -u uid -g gid ] [ -i ip:port ] [ -R root ] [ -b bufsize ] [ -T | -t ] [ -N | -n ]"
+#define USAGE "dnsfunneld [ -v verbosity ] [ -1 ] [ -U | -u uid -g gid ] [ -i ip:port ] [ -R root ] [ -b bufsize ] [ -t globaltimeout ] [ -X | -x ] [ -N | -n ]"
#define dieusage() strerr_dieusage(100, USAGE)
#define DNSFUNNELD_INPUT_MAX 64
unsigned int verbosity = 1 ;
-static tain_t globaltto = TAIN_INFINITE_RELATIVE ;
+static tain_t globaltto ;
static int cont = 1 ;
static s6dns_ip46list_t cachelist ;
static uint32_t ops = 0 ;
@@ -169,12 +169,13 @@ int main (int argc, char const *const *argv)
int fd ;
char ip[4] ;
size_t pos ;
+ unsigned int t = 0 ;
uint16_t port ;
subgetopt_t l = SUBGETOPT_ZERO ;
for (;;)
{
- int opt = subgetopt_r(argc, argv, "v:1Uu:g:i:R:b:TtNn", &l) ;
+ int opt = subgetopt_r(argc, argv, "v:1Uu:g:i:R:b:t:XxNn", &l) ;
if (opt == -1) break ;
switch (opt)
{
@@ -186,8 +187,9 @@ int main (int argc, char const *const *argv)
case 'i' : ipport = l.arg ; break ;
case 'R' : root = l.arg ; break ;
case 'b' : if (!uint0_scan(l.arg, &bufsize)) dieusage() ; break ;
- case 'T' : ops &= ~1 ; break ;
- case 't' : ops |= 1 ; break ;
+ case 't' : if (!uint0_scan(l.arg, &t)) dieusage() ; break ;
+ case 'X' : ops &= ~1 ; break ;
+ case 'x' : ops |= 1 ; break ;
case 'N' : ops &= ~2 ; break ;
case 'n' : ops |= 2 ; break ;
default : dieusage() ;
@@ -195,6 +197,8 @@ int main (int argc, char const *const *argv)
}
argc -= l.ind ; argv += l.ind ;
+ if (t) tain_from_millisecs(&globaltto, t) ;
+ else globaltto = tain_infinite_relative ;
pos = ip4_scan(ipport, ip) ;
if (!pos) dieusage() ;
if (ipport[pos] != ':') dieusage() ;
@@ -352,17 +356,20 @@ int main (int argc, char const *const *argv)
{
dfquery_t *q = QUERY(i) ;
uint32_t k = q->next ;
- int r = s6dns_engine_event_g(&q->dt) ;
- if (r)
+ if (x[q->xindex].events && x[q->xindex].revents)
{
- if (r > 0) query_process_response_success(ops, q) ;
- else query_process_response_failure(ops, q) ;
- QUERY(j)->next = k ;
- if (r > 0) s6dns_engine_free(&q->dt) ;
- else stralloc_free(&q->dt.sa) ;
- gensetdyn_delete(&queries, i) ;
+ int r = s6dns_engine_event_g(&q->dt) ;
+ if (r)
+ {
+ if (r > 0) query_process_response_success(ops, q) ;
+ else query_process_response_failure(ops, q) ;
+ QUERY(j)->next = k ;
+ if (r > 0) s6dns_engine_free(&q->dt) ;
+ else stralloc_free(&q->dt.sa) ;
+ gensetdyn_delete(&queries, i) ;
+ }
+ else j = i ;
}
- else j = i ;
i = k ;
}
diff --git a/src/dnsfunnel/dnsfunneld_answer.c b/src/dnsfunnel/dnsfunneld_answer.c
index a6ee526..c06637f 100644
--- a/src/dnsfunnel/dnsfunneld_answer.c
+++ b/src/dnsfunnel/dnsfunneld_answer.c
@@ -20,16 +20,15 @@ struct dfanswer_s
{
char buf[512] ;
char ip[4] ;
- uint16_t len ;
uint16_t port ;
} ;
-#define DFANSWER_ZERO { .buf = { 0 }, .ip = "\0\0\0", .len = 0, .port = 0 }
+#define DFANSWER_ZERO { .buf = { 0 }, .ip = "\0\0\0", .port = 0 }
static genqdyn dfanswers = GENQDYN_INIT(dfanswer_t, 1, 8) ;
size_t dfanswer_pending ()
{
- return genqdyn_n(&dfanswers) ;
+ return (dfanswers.queue.len - dfanswers.head) / dfanswers.esize ;
}
static void dfanswer_push (char const *s, size_t len, uint32_t ip, uint16_t port)
@@ -41,9 +40,9 @@ static void dfanswer_push (char const *s, size_t len, uint32_t ip, uint16_t port
}
else
{
- dfanswer_t ans = { .len = len, .port = port } ;
- uint16_pack_big(ans.buf, ans.len) ;
- memcpy(ans.buf, s+2, len) ;
+ dfanswer_t ans = { .port = port } ;
+ uint16_pack_big(ans.buf, len) ;
+ memcpy(ans.buf + 2, s+2, len) ;
uint32_pack_big(ans.ip, ip) ;
if (!genqdyn_push(&dfanswers, &ans))
strerr_diefu1sys(111, "queue answer to client") ;
@@ -55,7 +54,9 @@ int dfanswer_flush ()
while (dfanswer_pending())
{
dfanswer_t *ans = GENQDYN_PEEK(dfanswer_t, &dfanswers) ;
- if (socket_send4(0, ans->buf, ans->len, ans->ip, ans->port) < 0)
+ uint16_t len ;
+ uint16_unpack_big(ans->buf, &len) ;
+ if (socket_send4(0, ans->buf, len, ans->ip, ans->port) < 0)
return error_isagain(errno) ? (errno = 0, 0) : -1 ;
genqdyn_pop(&dfanswers) ;
}