about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorLaurent Bercot <ska-skaware@skarnet.org>2021-01-15 02:04:18 +0000
committerLaurent Bercot <ska-skaware@skarnet.org>2021-01-15 02:04:18 +0000
commitc47e30d38e6815174ddfc0fa0d718da18849db75 (patch)
tree9009dd8417d575c608e7c56b3cd4e2f2c1a0d2e1 /src
parent066056c64a7fee4ecf1f442e80984523aa7d600a (diff)
downloaddnsfunnel-c47e30d38e6815174ddfc0fa0d718da18849db75.tar.gz
dnsfunnel-c47e30d38e6815174ddfc0fa0d718da18849db75.tar.xz
dnsfunnel-c47e30d38e6815174ddfc0fa0d718da18849db75.zip
Bugfixes. Store less empty space in dfanswer.
Diffstat (limited to 'src')
-rw-r--r--src/dnsfunnel/dnsfunneld.c4
-rw-r--r--src/dnsfunnel/dnsfunneld_answer.c53
-rw-r--r--src/dnsfunnel/dnsfunneld_process.c4
3 files changed, 31 insertions, 30 deletions
diff --git a/src/dnsfunnel/dnsfunneld.c b/src/dnsfunnel/dnsfunneld.c
index 48965f1..2beef07 100644
--- a/src/dnsfunnel/dnsfunneld.c
+++ b/src/dnsfunnel/dnsfunneld.c
@@ -122,12 +122,14 @@ void query_new (s6dns_domain_t const *d, uint16_t qtype, uint16_t id, uint32_t i
     .id = id,
     .dt = S6DNS_ENGINE_ZERO
   } ;
+  s6dns_domain_t dd = *d ;
   tain_t deadline ;
   uint32_t i ;
   if (!gensetdyn_new(&queries, &i))
     strerr_diefu1sys(111, "create new query") ;
+  s6dns_domain_encode(&dd) ;
   tain_add_g(&deadline, &globaltto) ;
-  if (!s6dns_engine_init_g(&q.dt, &cachelist, S6DNS_O_RECURSIVE, d->s, d->len, qtype, &deadline))
+  if (!s6dns_engine_init_g(&q.dt, &cachelist, S6DNS_O_RECURSIVE, dd.s, dd.len, qtype, &deadline))
     strerr_diefu1sys(111, "start new query") ;
   *QUERY(i) = q ;
   QUERY(sentinel)->next = i ;
diff --git a/src/dnsfunnel/dnsfunneld_answer.c b/src/dnsfunnel/dnsfunneld_answer.c
index c06637f..e0fed6e 100644
--- a/src/dnsfunnel/dnsfunneld_answer.c
+++ b/src/dnsfunnel/dnsfunneld_answer.c
@@ -1,5 +1,7 @@
 /* ISC license. */
 
+#define DEBUG
+
 #include <errno.h>
 #include <stdint.h>
 #include <string.h>
@@ -8,44 +10,35 @@
 #include <skalibs/uint32.h>
 #include <skalibs/error.h>
 #include <skalibs/strerr2.h>
-#include <skalibs/genqdyn.h>
+#include <skalibs/stralloc.h>
 #include <skalibs/socket.h>
 
 #include <s6-dns/s6dns-message.h>
 
 #include "dnsfunneld.h"
 
-typedef struct dfanswer_s dfanswer_t, *dfanswer_t_ref ;
-struct dfanswer_s
-{
-  char buf[512] ;
-  char ip[4] ;
-  uint16_t port ;
-} ;
-#define DFANSWER_ZERO { .buf = { 0 }, .ip = "\0\0\0", .port = 0 }
-
-static genqdyn dfanswers = GENQDYN_INIT(dfanswer_t, 1, 8) ;
+static stralloc q = STRALLOC_ZERO ;
+static size_t head = 0 ;
 
 size_t dfanswer_pending ()
 {
-  return (dfanswers.queue.len - dfanswers.head) / dfanswers.esize ;
+  return q.len - head ;
 }
 
 static void dfanswer_push (char const *s, size_t len, uint32_t ip, uint16_t port)
 {
-  if (len > 510)
+  if (len > 512)
   {
     if (verbosity)
       strerr_warnw1x("answer too big, dropping - enable truncation to avoid this") ;
   }
   else
   {
-    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") ;
+    if (!stralloc_readyplus(&q, len + 8)) strerr_diefu1sys(111, "queue answer to client") ;
+    uint32_pack_big(q.s + q.len, ip) ; q.len += 4 ;
+    uint16_pack_big(q.s + q.len, port) ; q.len += 2 ;
+    uint16_pack_big(q.s + q.len, len) ; q.len += 2 ;
+    memcpy(q.s + q.len, s, len) ; q.len += len ;
   }
 }
 
@@ -53,19 +46,25 @@ int dfanswer_flush ()
 {
   while (dfanswer_pending())
   {
-    dfanswer_t *ans = GENQDYN_PEEK(dfanswer_t, &dfanswers) ;
-    uint16_t len ;
-    uint16_unpack_big(ans->buf, &len) ;
-    if (socket_send4(0, ans->buf, len, ans->ip, ans->port) < 0)
+    uint16_t port, len ;
+    uint16_unpack_big(q.s + head + 4, &port) ;
+    uint16_unpack_big(q.s + head + 6, &len) ;
+    if (socket_send4(0, q.s + head + 8, len, q.s + head, port) < 0)
       return error_isagain(errno) ? (errno = 0, 0) : -1 ;
-    genqdyn_pop(&dfanswers) ;
+    head += len + 8 ;
+    if ((q.len - head) >> 2 <= q.len)
+    {
+      memmove(q.s, q.s + head, q.len - head) ;
+      q.len -= head ;
+      head = 0 ;
+    }
   }
   return 1 ;
 }
 
 void dfanswer_fail (dfquery_t const *q)
 {
-  char buf[510] ;
+  char buf[512] ;
   uint16_t len ;
   s6dns_message_header_t hdr ;
   uint16_unpack_big(q->dt.sa.s, &len) ;
@@ -85,7 +84,7 @@ void dfanswer_fail (dfquery_t const *q)
 
 void dfanswer_nxdomain (dfquery_t const *q)
 {
-  char buf[510] ;
+  char buf[512] ;
   uint16_t len ;
   s6dns_message_header_t hdr ;
   uint16_unpack_big(q->dt.sa.s, &len) ;
@@ -105,7 +104,7 @@ void dfanswer_nxdomain (dfquery_t const *q)
 
 void dfanswer_nodata (dfquery_t const *q)
 {
-  char buf[510] ;
+  char buf[512] ;
   uint16_t len ;
   s6dns_message_header_t hdr ;
   uint16_unpack_big(q->dt.sa.s, &len) ;
diff --git a/src/dnsfunnel/dnsfunneld_process.c b/src/dnsfunnel/dnsfunneld_process.c
index 9d90289..8a0ffe2 100644
--- a/src/dnsfunnel/dnsfunneld_process.c
+++ b/src/dnsfunnel/dnsfunneld_process.c
@@ -54,7 +54,7 @@ static inline unsigned int truncate_packet (char *s, unsigned int olen)
     unsigned int tmp = pos ;
     if (!s6dns_message_parse_getrr(&rr, s, olen, &tmp)) return 0 ;
     section = s6dns_message_parse_next(&newcounts, &rr, s, olen, &tmp) ;
-    if (tmp > 510)
+    if (tmp > 512)
     {
       hdr.counts.qd -= counts.qd ;
       hdr.counts.an -= counts.an ;
@@ -126,7 +126,7 @@ void query_process_response_failure (uint32_t ops, dfquery_t const *q)
 void query_process_response_success (uint32_t ops, dfquery_t const *q)
 {
   if (ops & 2 && q->procid && input_event(q, 1 + !isnxdomain(q))) return ;
-  if (ops & 1 && s6dns_engine_packetlen(&q->dt) > 510)
+  if (ops & 1 && s6dns_engine_packetlen(&q->dt) > 512)
   {
     unsigned int len = truncate_packet(s6dns_engine_packet(&q->dt), s6dns_engine_packetlen(&q->dt)) ;
     if (!len) dfanswer_fail(q) ;