Commit c1a4e257 authored by Simon Kelley's avatar Simon Kelley

Try to be a little more clever at falling back to smaller DNS packet sizes.

parent 4fe6744a
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#define TIMEOUT 10 /* drop UDP queries after TIMEOUT seconds */ #define TIMEOUT 10 /* drop UDP queries after TIMEOUT seconds */
#define FORWARD_TEST 50 /* try all servers every 50 queries */ #define FORWARD_TEST 50 /* try all servers every 50 queries */
#define FORWARD_TIME 20 /* or 20 seconds */ #define FORWARD_TIME 20 /* or 20 seconds */
#define UDP_TEST_TIME 60 /* How often to reset our idea of max packet size. */
#define SERVERS_LOGGED 30 /* Only log this many servers when logging state */ #define SERVERS_LOGGED 30 /* Only log this many servers when logging state */
#define LOCALS_LOGGED 8 /* Only log this many local addresses when logging state */ #define LOCALS_LOGGED 8 /* Only log this many local addresses when logging state */
#define RANDOM_SOCKS 64 /* max simultaneous random ports */ #define RANDOM_SOCKS 64 /* max simultaneous random ports */
......
...@@ -520,6 +520,7 @@ struct server { ...@@ -520,6 +520,7 @@ struct server {
struct serverfd *sfd; struct serverfd *sfd;
char *domain; /* set if this server only handles a domain. */ char *domain; /* set if this server only handles a domain. */
int flags, tcpfd, edns_pktsz; int flags, tcpfd, edns_pktsz;
time_t pktsz_reduced;
unsigned int queries, failed_queries; unsigned int queries, failed_queries;
#ifdef HAVE_LOOP #ifdef HAVE_LOOP
u32 uid; u32 uid;
......
...@@ -272,11 +272,10 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr, ...@@ -272,11 +272,10 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
while (forward->blocking_query) while (forward->blocking_query)
forward = forward->blocking_query; forward = forward->blocking_query;
forward->flags |= FREC_TEST_PKTSZ;
blockdata_retrieve(forward->stash, forward->stash_len, (void *)header); blockdata_retrieve(forward->stash, forward->stash_len, (void *)header);
plen = forward->stash_len; plen = forward->stash_len;
forward->flags |= FREC_TEST_PKTSZ;
if (find_pseudoheader(header, plen, NULL, &pheader, &is_sign, NULL) && !is_sign) if (find_pseudoheader(header, plen, NULL, &pheader, &is_sign, NULL) && !is_sign)
PUTSHORT(SAFE_PKTSZ, pheader); PUTSHORT(SAFE_PKTSZ, pheader);
...@@ -401,6 +400,7 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr, ...@@ -401,6 +400,7 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
int subnet, forwarded = 0; int subnet, forwarded = 0;
size_t edns0_len; size_t edns0_len;
unsigned char *oph = find_pseudoheader(header, plen, NULL, NULL, NULL, NULL); unsigned char *oph = find_pseudoheader(header, plen, NULL, NULL, NULL, NULL);
unsigned char *pheader;
/* If a query is retried, use the log_id for the retry when logging the answer. */ /* If a query is retried, use the log_id for the retry when logging the answer. */
forward->log_id = daemon->log_id; forward->log_id = daemon->log_id;
...@@ -423,7 +423,7 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr, ...@@ -423,7 +423,7 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
} }
#endif #endif
if (find_pseudoheader(header, plen, &edns0_len, NULL, NULL, NULL)) if (find_pseudoheader(header, plen, &edns0_len, &pheader, NULL, NULL))
{ {
/* If there wasn't a PH before, and there is now, we added it. */ /* If there wasn't a PH before, and there is now, we added it. */
if (!oph) if (!oph)
...@@ -432,6 +432,10 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr, ...@@ -432,6 +432,10 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
/* If we're sending an EDNS0 with any options, we can't recreate the query from a reply. */ /* If we're sending an EDNS0 with any options, we can't recreate the query from a reply. */
if (edns0_len > 11) if (edns0_len > 11)
forward->flags |= FREC_HAS_EXTRADATA; forward->flags |= FREC_HAS_EXTRADATA;
/* Reduce udp size on retransmits. */
if (forward->flags & FREC_TEST_PKTSZ)
PUTSHORT(SAFE_PKTSZ, pheader);
} }
while (1) while (1)
...@@ -765,6 +769,10 @@ void reply_query(int fd, int family, time_t now) ...@@ -765,6 +769,10 @@ void reply_query(int fd, int family, time_t now)
if (!server) if (!server)
return; return;
/* If sufficient time has elapsed, try and expand UDP buffer size again. */
if (difftime(now, server->pktsz_reduced) > UDP_TEST_TIME)
server->edns_pktsz = daemon->edns_pktsz;
#ifdef HAVE_DNSSEC #ifdef HAVE_DNSSEC
hash = hash_questions(header, n, daemon->namebuff); hash = hash_questions(header, n, daemon->namebuff);
#else #else
...@@ -853,14 +861,16 @@ void reply_query(int fd, int family, time_t now) ...@@ -853,14 +861,16 @@ void reply_query(int fd, int family, time_t now)
/* We tried resending to this server with a smaller maximum size and got an answer. /* We tried resending to this server with a smaller maximum size and got an answer.
Make that permanent. To avoid reduxing the packet size for a single dropped packet, Make that permanent. To avoid reduxing the packet size for a single dropped packet,
only do this when we get a truncated answer, or one larger than the safe size. */ only do this when we get a truncated answer, or one larger than the safe size. */
if (server && (forward->flags & FREC_TEST_PKTSZ) && if (server && server->edns_pktsz > SAFE_PKTSZ && (forward->flags & FREC_TEST_PKTSZ) &&
((header->hb3 & HB3_TC) || n >= SAFE_PKTSZ)) ((header->hb3 & HB3_TC) || n >= SAFE_PKTSZ))
{ {
server->edns_pktsz = SAFE_PKTSZ; server->edns_pktsz = SAFE_PKTSZ;
server->pktsz_reduced = now;
prettyprint_addr(&server->addr, daemon->addrbuff); prettyprint_addr(&server->addr, daemon->addrbuff);
my_syslog(LOG_WARNING, _("reducing DNS packet size for nameserver %s to %d"), daemon->addrbuff, SAFE_PKTSZ); my_syslog(LOG_WARNING, _("reducing DNS packet size for nameserver %s to %d"), daemon->addrbuff, SAFE_PKTSZ);
} }
/* If the answer is an error, keep the forward record in place in case /* If the answer is an error, keep the forward record in place in case
we get a good reply from another server. Kill it when we've we get a good reply from another server. Kill it when we've
had replies from all to avoid filling the forwarding table when had replies from all to avoid filling the forwarding table when
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment