From: Henrik Nordstrom Date: Tue, 24 Aug 2010 21:04:22 +0000 (+0200) Subject: Strengthen the internal DNS client somewhat by making sure to keep X-Git-Tag: take1~331 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=bd6a0c8f30de2268141020d182fcfd8763b67bb3;p=thirdparty%2Fsquid.git Strengthen the internal DNS client somewhat by making sure to keep the receive queue drained. Also avoid parsing messages unless we have a pending query. --- diff --git a/src/dns_internal.cc b/src/dns_internal.cc index f31609168c..4e0e86098a 100644 --- a/src/dns_internal.cc +++ b/src/dns_internal.cc @@ -827,7 +827,7 @@ idnsSendQuery(idns_query * q) } else { if (DnsSocketB >= 0 && nameservers[ns].S.IsIPv6()) y = comm_udp_sendto(DnsSocketB, nameservers[ns].S, q->buf, q->sz); - else + else if (DnsSocketA) x = comm_udp_sendto(DnsSocketA, nameservers[ns].S, q->buf, q->sz); } @@ -842,16 +842,11 @@ idnsSendQuery(idns_query * q) } while ( (x<0 && y<0) && q->nsends % nns != 0); - if (!q->need_vc) { - if (y >= 0) { - fd_bytes(DnsSocketB, y, FD_WRITE); - commSetSelect(DnsSocketB, COMM_SELECT_READ, idnsRead, NULL, 0); - } - - if (x >= 0) { - fd_bytes(DnsSocketA, x, FD_WRITE); - commSetSelect(DnsSocketA, COMM_SELECT_READ, idnsRead, NULL, 0); - } + if (y > 0) { + fd_bytes(DnsSocketB, y, FD_WRITE); + } + if (x > 0) { + fd_bytes(DnsSocketA, x, FD_WRITE); } nameservers[ns].nqueries++; @@ -1135,6 +1130,10 @@ idnsRead(int fd, void *data) debugs(78, 3, "idnsRead: starting with FD " << fd); + // Always keep reading. This stops (or at least makes harder) several + // attacks on the DNS client. + commSetSelect(fd, COMM_SELECT_READ, idnsRead, NULL, 0); + /* BUG (UNRESOLVED) * two code lines after returning from comm_udprecvfrom() * something overwrites the memory behind the from parameter. @@ -1181,7 +1180,14 @@ idnsRead(int fd, void *data) if (ns >= 0) { nameservers[ns].nreplies++; - } else if (Config.onoff.ignore_unknown_nameservers) { + } + + // Before unknown_nameservers check to avoid flooding cache.log on attacks, + // but after the ++ above to keep statistics right. + if (!lru_list.head) + continue; // Don't process replies if there is no pending query. + + if (ns < 0 && Config.onoff.ignore_unknown_nameservers) { static time_t last_warning = 0; if (squid_curtime - last_warning > 60) { @@ -1195,10 +1201,6 @@ idnsRead(int fd, void *data) idnsGrokReply(rbuf, len); } - - if (lru_list.head) { - commSetSelect(fd, COMM_SELECT_READ, idnsRead, NULL, 0); - } } static void @@ -1266,7 +1268,7 @@ idnsReadVC(int fd, char *buf, size_t len, comm_err_t flag, int xerrno, void *dat return; } - vc->msg->size += len; // XXX should not access -> size directly + vc->msg->size += len; // XXX should not access -> size directly if (vc->msg->contentSize() < vc->msglen) { comm_read(fd, buf + len, vc->msglen - vc->msg->contentSize(), idnsReadVC, vc); @@ -1385,10 +1387,12 @@ idnsInit(void) if (DnsSocketB >= 0) { port = comm_local_port(DnsSocketB); debugs(78, 1, "DNS Socket created at " << addrB << ", FD " << DnsSocketB); + commSetSelect(DnsSocketB, COMM_SELECT_READ, idnsRead, NULL, 0); } if (DnsSocketA >= 0) { port = comm_local_port(DnsSocketA); debugs(78, 1, "DNS Socket created at " << addrA << ", FD " << DnsSocketA); + commSetSelect(DnsSocketA, COMM_SELECT_READ, idnsRead, NULL, 0); } }