Print DNS errors only when requested packet has an error

This commit is contained in:
Erik Ekman 2009-09-21 20:06:30 +00:00
parent c9debed450
commit 3614a96417
3 changed files with 57 additions and 56 deletions

View File

@ -339,6 +339,36 @@ send_ping(int fd)
}
}
static void
write_dns_error(struct query *q)
{
if (!q) return;
switch (q->rcode) {
case NOERROR: /* 0 */
warnx("Got reply without error, but also without question and/or answer");
break;
case FORMERR: /* 1 */
warnx("Got FORMERR as reply: server does not understand our request");
break;
case SERVFAIL: /* 2 */
warnx("Got SERVFAIL as reply: server failed or recursion timeout");
break;
case NXDOMAIN: /* 3 */
warnx("Got NXDOMAIN as reply: domain does not exist");
break;
case NOTIMP: /* 4 */
warnx("Got NOTIMP as reply: server does not support our request");
break;
case REFUSED: /* 5 */
warnx("Got REFUSED as reply");
break;
default:
warnx("Got RCODE %u as reply", q->rcode);
break;
}
}
static int
read_dns_withq(int dns_fd, int tun_fd, char *buf, int buflen, struct query *q) /* FIXME: tun_fd needed for raw handling */
{
@ -479,9 +509,15 @@ read_dns_namecheck(int dns_fd, int tun_fd, char *buf, int buflen, char c1, char
rv = read_dns_withq(dns_fd, tun_fd, buf, buflen, &q);
if (rv > 0 && q.name[0] != c1 && q.name[0] != c2)
/* Filter out any other replies */
if (q.name[0] != c1 && q.name[0] != c2)
return 0;
/* Print rcode errors */
if (rv < 0) {
write_dns_error(&q);
}
return rv; /* may also be 0 = useless or -1 = error (printed) */
}
@ -540,30 +576,32 @@ tunnel_dns(int tun_fd, int dns_fd)
int read;
int send_something_now = 0;
if ((read = read_dns_withq(dns_fd, tun_fd, buf, sizeof(buf), &q)) < 2) {
/* Maybe SERVFAIL etc. Send ping to get things back in order,
but wait a bit to prevent fast ping-pong loops. */
send_ping_soon = 900;
return -1; /* nothing done */
}
memset(q.name, 0, sizeof(q.name));
read = read_dns_withq(dns_fd, tun_fd, buf, sizeof(buf), &q);
/* Don't process anything that isn't data; already checked read>=2 */
/* Don't process anything that isn't data for us */
if (q.name[0] != 'P' && q.name[0] != 'p' &&
q.name[0] != userid_char && q.name[0] != userid_char2)
return -1; /* nothing done */
if (read < 2) {
/* Maybe SERVFAIL etc. Send ping to get things back in order,
but wait a bit to prevent fast ping-pong loops. */
write_dns_error(&q);
send_ping_soon = 900;
return -1; /* nothing done */
}
if (read == 5 && !strncmp("BADIP", buf, 5)) {
warnx("BADIP: Server rejected sender IP address (maybe iodined -c will help), or server kicked us due to timeout. Will exit if no downstream data is received in 60 seconds.");
return -1; /* nothing done */
}
if (send_ping_soon) {
send_something_now = 1;
send_ping_soon = 0;
}
/* Decode the data header, update seqno and frag;
already checked read>=2
Note that buf[] gets overwritten when down-pkt complete */

View File

@ -87,6 +87,7 @@ struct packet
struct query {
char name[QUERY_NAME_SIZE];
unsigned short type;
unsigned short rcode;
unsigned short id;
unsigned short iddupe; /* only used for dupe checking */
struct in_addr destination;

View File

@ -297,54 +297,13 @@ dns_decode(char *buf, size_t buflen, struct query *q, qr_t qr, char *packet, siz
rlen = 0;
if (q != NULL)
q->rcode = header->rcode;
switch (qr) {
case QR_ANSWER:
if(qdcount < 1 || ancount < 1) {
/* We may get both CNAME and A, then ancount=2 */
switch (header->rcode) {
case NOERROR: /* 0 */
if (header->tc)
warnx("Got TRUNCATION as reply: response too long for DNS path");
else
warnx("Got reply without error, but also without question and/or answer");
break;
case FORMERR: /* 1 */
warnx("Got FORMERR as reply: server does not understand our request");
break;
case SERVFAIL: /* 2 */
if (qdcount >= 1
&& packetlen >= sizeof(HEADER) + 2
&& (data[1] == 'r' || data[1] == 'R'))
warnx("Got SERVFAIL as reply on earlier fragsize autoprobe");
else if (qdcount >= 1
&& packetlen >= sizeof(HEADER) + 2
&& (data[1] < '0' || data[1] > '9')
&& (data[1] < 'a' || data[1] > 'f')
&& (data[1] < 'A' || data[1] > 'F')
&& data[1] != 'p' && data[1] != 'P')
warnx("Got SERVFAIL as reply on earlier config setting");
else
warnx("Got SERVFAIL as reply: server failed or recursion timeout");
break;
case NXDOMAIN: /* 3 */
warnx("Got NXDOMAIN as reply: domain does not exist");
break;
case NOTIMP: /* 4 */
warnx("Got NOTIMP as reply: server does not support our request");
break;
case REFUSED: /* 5 */
warnx("Got REFUSED as reply");
break;
default:
warnx("Got RCODE %u as reply", (unsigned int) header->rcode);
break;
}
return -1;
}
@ -377,8 +336,9 @@ dns_decode(char *buf, size_t buflen, struct query *q, qr_t qr, char *packet, siz
if (rv >= 2 && buf) {
rv = MIN(rv, buflen);
memcpy(buf, rdata, rv);
} else {
rv = 0;
}
/* "else rv=0;" here? */
}
if ((type == T_CNAME || type == T_MX) && buf) {
if (type == T_MX)
@ -395,6 +355,8 @@ dns_decode(char *buf, size_t buflen, struct query *q, qr_t qr, char *packet, siz
if (rv >= 1) {
rv = MIN(rv, buflen);
memcpy(buf, rdata, rv);
} else {
rv = 0;
}
}
if (q != NULL)