diff options
author | Simon Kelley <simon@thekelleys.org.uk> | 2014-03-24 22:04:42 +0000 |
---|---|---|
committer | Simon Kelley <simon@thekelleys.org.uk> | 2014-03-24 22:04:42 +0000 |
commit | 490f90758dba741b10a2af6b70eb561777575e04 (patch) | |
tree | 296259b846641d851e0e0dfc0b906a4db5a9a631 | |
parent | 56618c31f62b0ed8af2c392071af0ca519c64b13 (diff) | |
download | dnsmasq-490f90758dba741b10a2af6b70eb561777575e04.tar.gz |
Reorder sanity checks on UDP packet reception, to cope with failed recvfrom()
-rw-r--r-- | src/forward.c | 18 |
1 files changed, 11 insertions, 7 deletions
diff --git a/src/forward.c b/src/forward.c index 3f4ec62..a607959 100644 --- a/src/forward.c +++ b/src/forward.c @@ -698,14 +698,20 @@ void reply_query(int fd, int family, time_t now) serveraddr.in6.sin6_flowinfo = 0; #endif + header = (struct dns_header *)daemon->packet; + + if (n < (int)sizeof(struct dns_header) || !(header->hb3 & HB3_QR)) + return; + /* spoof check: answer must come from known server, */ for (server = daemon->servers; server; server = server->next) if (!(server->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR)) && sockaddr_isequal(&server->addr, &serveraddr)) break; - - header = (struct dns_header *)daemon->packet; - + + if (!server) + return; + #ifdef HAVE_DNSSEC hash = hash_questions(header, n, daemon->namebuff); #else @@ -713,11 +719,9 @@ void reply_query(int fd, int family, time_t now) crc = questions_crc(header, n, daemon->namebuff); #endif - if (!server || - n < (int)sizeof(struct dns_header) || !(header->hb3 & HB3_QR) || - !(forward = lookup_frec(ntohs(header->id), hash))) + if (!(forward = lookup_frec(ntohs(header->id), hash))) return; - + if ((RCODE(header) == SERVFAIL || RCODE(header) == REFUSED) && !option_bool(OPT_ORDER) && forward->forwardall == 0) |