summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/dnsfunnel/dnsfunneld.h6
-rw-r--r--src/dnsfunnel/dnsfunneld_answer.c32
-rw-r--r--src/dnsfunnel/dnsfunneld_process.c17
3 files changed, 35 insertions, 20 deletions
diff --git a/src/dnsfunnel/dnsfunneld.h b/src/dnsfunnel/dnsfunneld.h
index 9fc0bbf..4b9acd3 100644
--- a/src/dnsfunnel/dnsfunneld.h
+++ b/src/dnsfunnel/dnsfunneld.h
@@ -27,9 +27,9 @@ struct dfquery_s
extern unsigned int verbosity ;
extern size_t dfanswer_pending (void) ;
extern int dfanswer_flush (void) ;
-extern void dfanswer_fail (dfquery_t const *) ;
-extern void dfanswer_nxdomain (dfquery_t const *) ;
-extern void dfanswer_nodata (dfquery_t const *) ;
+extern void dfanswer_fail (dfquery_t const *, int) ;
+extern void dfanswer_nxdomain (dfquery_t const *, int) ;
+extern void dfanswer_nodata (dfquery_t const *, int) ;
extern void dfanswer_pass (dfquery_t const *, char *, unsigned int) ;
diff --git a/src/dnsfunnel/dnsfunneld_answer.c b/src/dnsfunnel/dnsfunneld_answer.c
index e0fed6e..7793074 100644
--- a/src/dnsfunnel/dnsfunneld_answer.c
+++ b/src/dnsfunnel/dnsfunneld_answer.c
@@ -1,7 +1,5 @@
/* ISC license. */
-#define DEBUG
-
#include <errno.h>
#include <stdint.h>
#include <string.h>
@@ -13,6 +11,7 @@
#include <skalibs/stralloc.h>
#include <skalibs/socket.h>
+#include <s6-dns/s6dns-constants.h>
#include <s6-dns/s6dns-message.h>
#include "dnsfunneld.h"
@@ -62,11 +61,25 @@ int dfanswer_flush ()
return 1 ;
}
-void dfanswer_fail (dfquery_t const *q)
+static void switchaux (char *buf, uint16_t len)
+{
+ uint16_t qtype ;
+ uint16_unpack_big(buf + len - 4, &qtype) ;
+ switch (qtype)
+ {
+ case S6DNS_T_A : qtype = S6DNS_T_AAAA ; break ;
+ case S6DNS_T_AAAA : qtype = S6DNS_T_A ; break ;
+ default : strerr_dief1x(101, "can't happen: invalid qtype in auxiliary query") ;
+ }
+ uint16_pack_big(buf + len - 4, qtype) ;
+}
+
+
+void dfanswer_fail (dfquery_t const *q, int isaux)
{
char buf[512] ;
- uint16_t len ;
s6dns_message_header_t hdr ;
+ uint16_t len ;
uint16_unpack_big(q->dt.sa.s, &len) ;
memcpy(buf, q->dt.sa.s + 2, len) ;
s6dns_message_header_unpack(buf, &hdr) ;
@@ -79,14 +92,15 @@ void dfanswer_fail (dfquery_t const *q)
hdr.z = 0 ;
hdr.rcode = 2 ; /* servfail */
s6dns_message_header_pack(buf, &hdr) ;
+ if (isaux) switchaux(buf, len) ;
dfanswer_push(buf, len, q->ip, q->port) ;
}
-void dfanswer_nxdomain (dfquery_t const *q)
+void dfanswer_nxdomain (dfquery_t const *q, int isaux)
{
char buf[512] ;
- uint16_t len ;
s6dns_message_header_t hdr ;
+ uint16_t len ;
uint16_unpack_big(q->dt.sa.s, &len) ;
memcpy(buf, q->dt.sa.s + 2, len) ;
s6dns_message_header_unpack(buf, &hdr) ;
@@ -99,14 +113,15 @@ void dfanswer_nxdomain (dfquery_t const *q)
hdr.z = 0 ;
hdr.rcode = 3 ; /* nxdomain */
s6dns_message_header_pack(buf, &hdr) ;
+ if (isaux) switchaux(buf, len) ;
dfanswer_push(buf, len, q->ip, q->port) ;
}
-void dfanswer_nodata (dfquery_t const *q)
+void dfanswer_nodata (dfquery_t const *q, int isaux)
{
char buf[512] ;
- uint16_t len ;
s6dns_message_header_t hdr ;
+ uint16_t len ;
uint16_unpack_big(q->dt.sa.s, &len) ;
memcpy(buf, q->dt.sa.s + 2, len) ;
s6dns_message_header_unpack(buf, &hdr) ;
@@ -119,6 +134,7 @@ void dfanswer_nodata (dfquery_t const *q)
hdr.z = 0 ;
hdr.rcode = 0 ; /* success */
s6dns_message_header_pack(buf, &hdr) ;
+ if (isaux) switchaux(buf, len) ;
dfanswer_push(buf, len, q->ip, q->port) ;
}
diff --git a/src/dnsfunnel/dnsfunneld_process.c b/src/dnsfunnel/dnsfunneld_process.c
index 8a0ffe2..f9055ac 100644
--- a/src/dnsfunnel/dnsfunneld_process.c
+++ b/src/dnsfunnel/dnsfunneld_process.c
@@ -104,23 +104,22 @@ static int input_event (dfquery_t const *q, unsigned int ev)
} ;
uint8_t b = *RINFO(q->procid - 1) ;
uint8_t isaux = 3 * (b >> 7 != (extract_qtype(q) == S6DNS_T_AAAA)) ;
- uint8_t state = (b >> isaux) & 7 ;
+ uint8_t state = b & 7 ;
uint8_t c = table[state][ev + isaux] ;
state = c & 7 ;
- *RINFO(q->procid - 1) = (b & ~(7 << isaux)) | (state << isaux) ;
- if (c & 0x10) dfanswer_fail(q) ;
- if (c & 0x20) dfanswer_nxdomain(q) ;
- if (c & 0x40) dfanswer_nodata(q) ;
- if (c & 0x80) dfanswer_pass(q, s6dns_engine_packet(&q->dt), s6dns_engine_packetlen(&q->dt)) ;
+ *RINFO(q->procid - 1) = (b & 0xf8) | state ;
+ if (c & 0x10) dfanswer_fail(q, !!isaux) ;
+ if (c & 0x20) dfanswer_nxdomain(q, !!isaux) ;
+ if (c & 0x40) dfanswer_nodata(q, !!isaux) ;
if (state >= 6) strerr_dief1x(101, "problem in main/aux transition table; please submit a bug-report.") ;
if (state == 5) gensetdyn_delete(&rinfo, q->procid - 1) ;
- return !!(c & 0xf0) ;
+ return !(c & 0x80) ;
}
void query_process_response_failure (uint32_t ops, dfquery_t const *q)
{
if (ops & 2 && q->procid && input_event(q, 0)) return ;
- else dfanswer_fail(q) ;
+ else dfanswer_fail(q, 0) ;
}
void query_process_response_success (uint32_t ops, dfquery_t const *q)
@@ -129,7 +128,7 @@ void query_process_response_success (uint32_t ops, dfquery_t const *q)
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) ;
+ if (!len) dfanswer_fail(q, 0) ;
else dfanswer_pass(q, s6dns_engine_packet(&q->dt), len) ;
}
else dfanswer_pass(q, s6dns_engine_packet(&q->dt), s6dns_engine_packetlen(&q->dt)) ;