diff options
author | Nick Mathewson <nickm@torproject.org> | 2007-05-29 17:31:13 +0000 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2007-05-29 17:31:13 +0000 |
commit | f89a3b14488ddfa5f7c11cb76fc73471835c00cf (patch) | |
tree | 8b7bfaf46afbbd0819ef5fcf850de7b6b0f4b015 /src/or/dnsserv.c | |
parent | 69c712f1899d3e42fd563136e78af4cb62472b56 (diff) | |
download | tor-f89a3b14488ddfa5f7c11cb76fc73471835c00cf.tar.gz tor-f89a3b14488ddfa5f7c11cb76fc73471835c00cf.zip |
r13050@catbus: nickm | 2007-05-29 13:31:11 -0400
Resolve all but 3 DOCDOCs.
svn:r10393
Diffstat (limited to 'src/or/dnsserv.c')
-rw-r--r-- | src/or/dnsserv.c | 62 |
1 files changed, 53 insertions, 9 deletions
diff --git a/src/or/dnsserv.c b/src/or/dnsserv.c index 89077342c5..bda4be56c2 100644 --- a/src/or/dnsserv.c +++ b/src/or/dnsserv.c @@ -12,6 +12,9 @@ const char dnsserv_c_id[] = #include "or.h" #include "eventdns.h" +/* Helper function: called by evdns whenever the client sends a request to our + * DNSPort. We need to eventually answer the request <b>req</b>. + */ static void evdns_server_callback(struct evdns_server_request *req, void *_data) { @@ -23,11 +26,13 @@ evdns_server_callback(struct evdns_server_request *req, void *_data) int addrlen; uint32_t ipaddr; int err = DNS_ERR_NONE; + char *q_name; tor_assert(req); tor_assert(_data == NULL); log_info(LD_APP, "Got a new DNS request!"); + /* First, check whether the requesting address matches our SOCKSPolicy. */ if ((addrlen = evdns_server_request_get_requesting_addr(req, (struct sockaddr*)&addr, sizeof(addr))) < 0) { log_warn(LD_APP, "Couldn't get requesting address."); @@ -49,6 +54,11 @@ evdns_server_callback(struct evdns_server_request *req, void *_data) evdns_server_request_respond(req, DNS_ERR_REFUSED); return; } + + /* Now, let's find the first actual question of a type we can answer in this + * DNS request. It makes us a little noncompliant to act like this; we + * should fix that eventually if it turns out to make a difference for + * anybody. */ if (req->nquestions == 0) { log_info(LD_APP, "No questions in DNS request; sending back nil reply."); evdns_server_request_respond(req, 0); @@ -76,22 +86,27 @@ evdns_server_callback(struct evdns_server_request *req, void *_data) return; } if (q->type == EVDNS_TYPE_A) { + /* Refuse any attempt to resolve a noconnect address, right now. */ if (hostname_is_noconnect_address(q->name)) { err = DNS_ERR_REFUSED; } } else { 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. */ evdns_server_request_respond(req, err); return; } /* XXXX020 Send a stream event to the controller. */ + /* Make a new dummy AP connection, and attach the request to it. */ conn = TO_EDGE_CONN(connection_new(CONN_TYPE_AP)); conn->_base.state = AP_CONN_STATE_RESOLVE_WAIT; if (q->type == EVDNS_TYPE_A) @@ -104,20 +119,36 @@ evdns_server_callback(struct evdns_server_request *req, void *_data) conn->dns_server_request = req; - log_info(LD_APP, "Passing request for %s to rewrite_and_attach.", q->name); + /* Now, throw the connection over to get rewritten (which will answer it + * immediately if it's in the cache, or completely bogus, or automapped), + * and then attached to a circuit. */ + log_info(LD_APP, "Passing request for %s to rewrite_and_attach.", + escaped_safe_str(q->name)); + q_name = tor_strdup(q->name); /* q could be freed in rewrite_and_attach */ connection_ap_handshake_rewrite_and_attach(conn, NULL, NULL); - /* Now the connection is marked if it was bad. */ + /* Now, the connection is marked if it was bad. */ - log_info(LD_APP, "Passed request for %s to rewrite_and_attach.", q->name); + log_info(LD_APP, "Passed request for %s to rewrite_and_attach.", + escaped_safe_str(q_name)); + tor_free(q_name); } +/** If there is a pending request on <b>conn</b> that's waiting for an answer, + * send back an error and free the request. */ void dnsserv_reject_request(edge_connection_t *conn) { - evdns_server_request_respond(conn->dns_server_request, DNS_ERR_SERVERFAILED); - conn->dns_server_request = NULL; + if (conn->dns_server_request) { + evdns_server_request_respond(conn->dns_server_request, + DNS_ERR_SERVERFAILED); + conn->dns_server_request = NULL; + } } +/** Tell the dns request waiting for an answer on <b>conn</b> that we have an + * answer of type <b>answer_type</b> (RESOLVE_TYPE_IPV4/IPV6/ERR), of length + * <b>answer_len</b>, in <b>answer</b>, with TTL <b>ttl</b>. Doesn't do + * any caching; that's handled elsewhere. */ void dnsserv_resolved(edge_connection_t *conn, int answer_type, @@ -130,10 +161,13 @@ dnsserv_resolved(edge_connection_t *conn, if (!req) return; - /* XXXX Re-do. */ + /* XXXX020 Re-do; this is dumb. */ if (ttl < 60) ttl = 60; + /* The evdns interface is: add a bunch of reply items (corresponding to one + * or more of the questions in the request); then, call + * evdns_server_request_respond. */ if (answer_type == RESOLVED_TYPE_IPV6) { log_info(LD_APP, "Got an IPv6 answer; that's not implemented."); err = DNS_ERR_NOTIMPL; @@ -150,26 +184,36 @@ dnsserv_resolved(edge_connection_t *conn, (char*)answer, ttl); tor_free(ans); } else { - err = DNS_ERR_SERVERFAILED; + err = DNS_ERR_SERVERFAILED; /* Really? Not noent? */ } evdns_server_request_respond(req, err); conn->dns_server_request = NULL; } +/* Set up the evdns server port for the UDP socket on <b>conn</b>, which + * must be an AP_DNS_LISTENER */ void dnsserv_configure_listener(connection_t *conn) { tor_assert(conn); tor_assert(conn->s); + tor_assert(conn->type == CONN_TYPE_AP_DNS_LISTENER); evdns_add_server_port(conn->s, 0, evdns_server_callback, NULL); } +/** Free the evdns server port for <b>conn</b>, which must be an + * AP_DNS_LISTENER. */ void dnsserv_close_listener(connection_t *conn) { - evdns_close_server_port(conn->dns_server_port); - conn->dns_server_port = NULL; + tor_assert(conn); + tor_assert(conn->type == CONN_TYPE_AP_DNS_LISTENER); + + if (conn->dns_server_port) { + evdns_close_server_port(conn->dns_server_port); + conn->dns_server_port = NULL; + } } |