From d32f5bf90638a7ba2aa6cf8ff6c6ae2b313a9bc1 Mon Sep 17 00:00:00 2001 From: Laurent Bercot Date: Tue, 19 Jan 2021 22:34:30 +0000 Subject: Fix bugs in aux query management --- src/dnsfunnel/dnsfunneld.h | 6 +++--- src/dnsfunnel/dnsfunneld_answer.c | 32 ++++++++++++++++++++++++-------- src/dnsfunnel/dnsfunneld_process.c | 17 ++++++++--------- 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 #include #include @@ -13,6 +11,7 @@ #include #include +#include #include #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)) ; -- cgit 1.4.1