diff options
author | Nick Mathewson <nickm@torproject.org> | 2014-04-07 22:03:19 -0400 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2014-04-07 22:08:41 -0400 |
commit | 6d0991ea0872bf8a7b093709a4c7bf1619433917 (patch) | |
tree | 209d8c13ed1b0ce3366b8558707aaffc67dd32ac | |
parent | bc0882c868c0cb61ade0f8b500c4392c889d6d0e (diff) | |
download | tor-6d0991ea0872bf8a7b093709a4c7bf1619433917.tar tor-6d0991ea0872bf8a7b093709a4c7bf1619433917.tar.gz |
Give no answer, not NOTIMPL, for unsupported DNS query types
According to reports, most programs degrade somewhat gracefully on
getting no answer for an MX or a CERT for www.example.com, but many
flip out completely on a NOTIMPL error.
Also, treat a QTYPE_ALL query as just asking for an A record.
The real fix here is to implement proposal 219 or something like it.
Fixes bug 10268; bugfix on 0.2.0.1-alpha.
Based on a patch from "epoch".
-rw-r--r-- | changes/bug10268 | 6 | ||||
-rw-r--r-- | src/or/dnsserv.c | 29 |
2 files changed, 25 insertions, 10 deletions
diff --git a/changes/bug10268 b/changes/bug10268 new file mode 100644 index 000000000..3035e7636 --- /dev/null +++ b/changes/bug10268 @@ -0,0 +1,6 @@ + o Minor bugfixes: + - When receing a DNS query for an unsupported type, reply with + no answer rather than with a NOTIMPL error. This behavior isn't + correct either, but it will break fewer client programs, we hope. + Fixes bug 10268; bugfix on 0.2.0.1-alpha. Original patch + from "epoch". diff --git a/src/or/dnsserv.c b/src/or/dnsserv.c index 4190e9cc2..ecd45be77 100644 --- a/src/or/dnsserv.c +++ b/src/or/dnsserv.c @@ -35,7 +35,7 @@ evdns_server_callback(struct evdns_server_request *req, void *data_) entry_connection_t *entry_conn; edge_connection_t *conn; int i = 0; - struct evdns_server_question *q = NULL; + struct evdns_server_question *q = NULL, *supported_q = NULL; struct sockaddr_storage addr; struct sockaddr *sa; int addrlen; @@ -87,31 +87,37 @@ evdns_server_callback(struct evdns_server_request *req, void *data_) for (i = 0; i < req->nquestions; ++i) { if (req->questions[i]->dns_question_class != EVDNS_CLASS_INET) continue; + if (! q) + q = req->questions[i]; switch (req->questions[i]->type) { case EVDNS_TYPE_A: case EVDNS_TYPE_AAAA: case EVDNS_TYPE_PTR: - q = req->questions[i]; + /* We always pick the first one of these questions, if there is + one. */ + if (! supported_q) + supported_q = q; + break; default: break; } } + if (supported_q) + q = supported_q; if (!q) { log_info(LD_APP, "None of the questions we got were ones we're willing " "to support. Sending NOTIMPL."); evdns_server_request_respond(req, DNS_ERR_NOTIMPL); return; } - if (q->type != EVDNS_TYPE_A && q->type != EVDNS_TYPE_AAAA) { - tor_assert(q->type == EVDNS_TYPE_PTR); - } /* Make sure the name isn't too long: This should be impossible, I think. */ if (err == DNS_ERR_NONE && strlen(q->name) > MAX_SOCKS_ADDR_LEN-1) err = DNS_ERR_FORMAT; - if (err != DNS_ERR_NONE) { - /* We got an error? Then send back an answer immediately; we're done. */ + if (err != DNS_ERR_NONE || !supported_q) { + /* We got an error? There's no question we're willing to answer? Then + * send back an answer immediately; we're done. */ evdns_server_request_respond(req, err); return; } @@ -126,12 +132,15 @@ evdns_server_callback(struct evdns_server_request *req, void *data_) TO_CONN(conn)->port = port; TO_CONN(conn)->address = tor_dup_addr(&tor_addr); - if (q->type == EVDNS_TYPE_A || q->type == EVDNS_TYPE_AAAA) + if (q->type == EVDNS_TYPE_A || q->type == EVDNS_TYPE_AAAA || + q->type == EVDNS_QTYPE_ALL) { entry_conn->socks_request->command = SOCKS_COMMAND_RESOLVE; - else + } else { + tor_assert(q->type == EVDNS_TYPE_PTR); entry_conn->socks_request->command = SOCKS_COMMAND_RESOLVE_PTR; + } - if (q->type == EVDNS_TYPE_A) { + if (q->type == EVDNS_TYPE_A || q->type == EVDNS_QTYPE_ALL) { entry_conn->ipv4_traffic_ok = 1; entry_conn->ipv6_traffic_ok = 0; entry_conn->prefer_ipv6_traffic = 0; |