From 1419de285fdacde2dc9683b701ee2d71090eade3 Mon Sep 17 00:00:00 2001 From: Simon Kelley Date: Wed, 17 May 2023 23:19:30 +0100 Subject: [PATCH] Log truncated DNS replies. --- src/cache.c | 17 +++++++++++------ src/forward.c | 30 ++++++++++++++++++++---------- src/rfc1035.c | 5 ++++- 3 files changed, 35 insertions(+), 17 deletions(-) diff --git a/src/cache.c b/src/cache.c index ccbb9cd..1c0e250 100644 --- a/src/cache.c +++ b/src/cache.c @@ -2049,9 +2049,10 @@ static char *edestr(int ede) void log_query(unsigned int flags, char *name, union all_addr *addr, char *arg, unsigned short type) { - char *source, *dest = arg; + char *source, *dest; char *verb = "is"; char *extra = ""; + char *gap = " "; char portstring[7]; /* space for # */ if (!option_bool(OPT_LOG)) @@ -2061,6 +2062,8 @@ void log_query(unsigned int flags, char *name, union all_addr *addr, char *arg, if (!(flags & (F_SERVER | F_IPSET)) && type > 0) arg = querystr(arg, type); + dest = arg; + #ifdef HAVE_DNSSEC if ((flags & F_DNSSECOK) && option_bool(OPT_EXTRALOG)) extra = " (DNSSEC signed)"; @@ -2186,19 +2189,21 @@ void log_query(unsigned int flags, char *name, union all_addr *addr, char *arg, else source = "cached"; - if (name && !name[0]) + if (!name) + gap = name = ""; + else if (!name[0]) name = "."; - + if (option_bool(OPT_EXTRALOG)) { if (flags & F_NOEXTRA) - my_syslog(LOG_INFO, "%u %s %s %s %s%s", daemon->log_display_id, source, name, verb, dest, extra); + my_syslog(LOG_INFO, "%u %s %s%s%s %s%s", daemon->log_display_id, source, name, gap, verb, dest, extra); else { int port = prettyprint_addr(daemon->log_source_addr, daemon->addrbuff2); - my_syslog(LOG_INFO, "%u %s/%u %s %s %s %s%s", daemon->log_display_id, daemon->addrbuff2, port, source, name, verb, dest, extra); + my_syslog(LOG_INFO, "%u %s/%u %s %s%s%s %s%s", daemon->log_display_id, daemon->addrbuff2, port, source, name, gap, verb, dest, extra); } } else - my_syslog(LOG_INFO, "%s %s %s %s%s", source, name, verb, dest, extra); + my_syslog(LOG_INFO, "%s %s%s%s %s%s", source, name, gap, verb, dest, extra); } diff --git a/src/forward.c b/src/forward.c index 18fb092..40501df 100644 --- a/src/forward.c +++ b/src/forward.c @@ -894,17 +894,24 @@ static void dnssec_validate(struct frec *forward, struct dns_header *header, if (forward->blocking_query) return; - /* Truncated answer can't be validated. - If this is an answer to a DNSSEC-generated query, we still - need to get the client to retry over TCP, so return - an answer with the TC bit set, even if the actual answer fits. - */ - if (header->hb3 & HB3_TC) - status = STAT_TRUNCATED; - /* If all replies to a query are REFUSED, give up. */ if (RCODE(header) == REFUSED) status = STAT_ABANDONED; + else if (header->hb3 & HB3_TC) + { + /* Truncated answer can't be validated. + If this is an answer to a DNSSEC-generated query, we still + need to get the client to retry over TCP, so return + an answer with the TC bit set, even if the actual answer fits. + */ + status = STAT_TRUNCATED; + if (forward->flags & (FREC_DNSKEY_QUERY | FREC_DS_QUERY)) + { + unsigned char *p = (unsigned char *)(header+1); + if (extract_name(header, plen, &p, daemon->namebuff, 0, 4) == 1) + log_query(F_UPSTREAM | F_NOEXTRA, daemon->namebuff, NULL, "truncated", (forward->flags & FREC_DNSKEY_QUERY) ? T_DNSKEY : T_DS); + } + } /* As soon as anything returns BOGUS, we stop and unwind, to do otherwise would invite infinite loops, since the answers to DNSKEY and DS queries @@ -1293,7 +1300,10 @@ static void return_reply(time_t now, struct frec *forward, struct dns_header *he no_cache_dnssec = 0; if (STAT_ISEQUAL(status, STAT_TRUNCATED)) - header->hb3 |= HB3_TC; + { + header->hb3 |= HB3_TC; + log_query(F_SECSTAT, "result", NULL, "TRUNCATED", 0); + } else { char *result, *domain = "result"; @@ -1319,7 +1329,7 @@ static void return_reply(time_t now, struct frec *forward, struct dns_header *he if (extract_request(header, n, daemon->namebuff, NULL)) domain = daemon->namebuff; } - + log_query(F_SECSTAT, domain, &a, result, 0); } } diff --git a/src/rfc1035.c b/src/rfc1035.c index 55319e9..56b65bb 100644 --- a/src/rfc1035.c +++ b/src/rfc1035.c @@ -980,7 +980,10 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t } } } - + + if (header->hb3 & HB3_TC) + log_query(F_UPSTREAM, NULL, NULL, "truncated", 0); + /* Don't put stuff from a truncated packet into the cache. Don't cache replies from non-recursive nameservers, since we may get a reply containing a CNAME but not its target, even though the target