|
@@ -145,6 +145,78 @@ evdns_server_callback(struct evdns_server_request *req, void *_data)
|
|
|
tor_free(q_name);
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+ * controller. We need to eventually answer the request <b>req</b>.
|
|
|
+ */
|
|
|
+void
|
|
|
+dnsserv_launch_request(const char *name)
|
|
|
+{
|
|
|
+ edge_connection_t *conn;
|
|
|
+ struct evdns_server_request *server_req;
|
|
|
+ struct in_addr in;
|
|
|
+ char *q_name;
|
|
|
+ int i;
|
|
|
+ int is_ip_address;
|
|
|
+
|
|
|
+
|
|
|
+ conn = TO_EDGE_CONN(connection_new(CONN_TYPE_AP, AF_INET));
|
|
|
+ conn->_base.state = AP_CONN_STATE_RESOLVE_WAIT;
|
|
|
+
|
|
|
+ is_ip_address = tor_inet_aton(name, &in);
|
|
|
+
|
|
|
+ if (!is_ip_address)
|
|
|
+ conn->socks_request->command = SOCKS_COMMAND_RESOLVE_CONTROL;
|
|
|
+ else
|
|
|
+ conn->socks_request->command = SOCKS_COMMAND_RESOLVE_PTR_CONTROL;
|
|
|
+
|
|
|
+ strlcpy(conn->socks_request->address, name,
|
|
|
+ sizeof(conn->socks_request->address));
|
|
|
+
|
|
|
+ server_req = malloc(sizeof(struct evdns_server_request));
|
|
|
+ if (server_req == NULL) return;
|
|
|
+ memset(server_req, 0, sizeof(struct evdns_server_request));
|
|
|
+
|
|
|
+ server_req->flags = 0;
|
|
|
+ server_req->nquestions = 0;
|
|
|
+
|
|
|
+ server_req->questions = malloc(sizeof(struct evdns_server_question *) * 1);
|
|
|
+ if (server_req->questions == NULL)
|
|
|
+ return;
|
|
|
+
|
|
|
+ for ( i = 0; i < 1; ++i) {
|
|
|
+ struct evdns_server_question *q;
|
|
|
+ int namelen;
|
|
|
+ namelen = strlen(name);
|
|
|
+ q = malloc(sizeof(struct evdns_server_question) + namelen);
|
|
|
+ if (!q)
|
|
|
+ return;
|
|
|
+ if (!is_ip_address)
|
|
|
+ q->type = EVDNS_TYPE_A;
|
|
|
+ else
|
|
|
+ q->type = EVDNS_TYPE_PTR;
|
|
|
+ q->class = EVDNS_CLASS_INET;
|
|
|
+ memcpy(q->name, name, namelen+1);
|
|
|
+ server_req->questions[server_req->nquestions++] = q;
|
|
|
+ }
|
|
|
+
|
|
|
+ conn->dns_server_request = server_req;
|
|
|
+
|
|
|
+ connection_add(TO_CONN(conn));
|
|
|
+
|
|
|
+
|
|
|
+ * 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(name));
|
|
|
+ q_name = tor_strdup(name);
|
|
|
+ connection_ap_handshake_rewrite_and_attach(conn, NULL, NULL);
|
|
|
+
|
|
|
+
|
|
|
+ log_info(LD_APP, "Passed request for %s to rewrite_and_attach.",
|
|
|
+ escaped_safe_str(q_name));
|
|
|
+ tor_free(q_name);
|
|
|
+}
|
|
|
+
|
|
|
|
|
|
* send back an error and free the request. */
|
|
|
void
|
|
@@ -181,27 +253,49 @@ dnsserv_resolved(edge_connection_t *conn,
|
|
|
* 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;
|
|
|
+ if (SOCKS_COMMAND_IS_RESOLVE_CONTROL(conn->socks_request->command))
|
|
|
+ handle_control_resolve_response(req->questions[0]->name,
|
|
|
+ "IPv6 not implemented");
|
|
|
+ else {
|
|
|
+ log_info(LD_APP, "Got an IPv6 answer; that's not implemented.");
|
|
|
+ err = DNS_ERR_NOTIMPL;
|
|
|
+ }
|
|
|
} else if (answer_type == RESOLVED_TYPE_IPV4 && answer_len == 4 &&
|
|
|
conn->socks_request->command == SOCKS_COMMAND_RESOLVE) {
|
|
|
- evdns_server_request_add_a_reply(req,
|
|
|
- conn->socks_request->address,
|
|
|
- 1, (char*)answer, ttl);
|
|
|
+ if (SOCKS_COMMAND_IS_RESOLVE_CONTROL(conn->socks_request->command))
|
|
|
+ handle_control_resolve_response(req->questions[0]->name,
|
|
|
+ tor_dup_addr(ntohl(get_uint32(answer))));
|
|
|
+ else
|
|
|
+ evdns_server_request_add_a_reply(req,
|
|
|
+ conn->socks_request->address,
|
|
|
+ 1, (char*)answer, ttl);
|
|
|
} else if (answer_type == RESOLVED_TYPE_HOSTNAME &&
|
|
|
conn->socks_request->command == SOCKS_COMMAND_RESOLVE_PTR) {
|
|
|
- char *ans = tor_strndup(answer, answer_len);
|
|
|
- evdns_server_request_add_ptr_reply(req, NULL,
|
|
|
+ if (SOCKS_COMMAND_IS_RESOLVE_CONTROL(conn->socks_request->command))
|
|
|
+ handle_control_resolve_response(req->questions[0]->name, answer);
|
|
|
+ else {
|
|
|
+ char *ans = tor_strndup(answer, answer_len);
|
|
|
+ evdns_server_request_add_ptr_reply(req, NULL,
|
|
|
conn->socks_request->address,
|
|
|
(char*)answer, ttl);
|
|
|
- tor_free(ans);
|
|
|
+ tor_free(ans);
|
|
|
+ }
|
|
|
} else if (answer_type == RESOLVED_TYPE_ERROR) {
|
|
|
- err = DNS_ERR_NOTEXIST;
|
|
|
+ if (SOCKS_COMMAND_IS_RESOLVE_CONTROL(conn->socks_request->command))
|
|
|
+ handle_control_resolve_response(req->questions[0]->name, "Unknown Host");
|
|
|
+ else
|
|
|
+ err = DNS_ERR_NOTEXIST;
|
|
|
} else {
|
|
|
- err = DNS_ERR_SERVERFAILED;
|
|
|
+ if (SOCKS_COMMAND_IS_RESOLVE_CONTROL(conn->socks_request->command))
|
|
|
+ handle_control_resolve_response(req->questions[0]->name,
|
|
|
+ "Temporary Error");
|
|
|
+ else
|
|
|
+ err = DNS_ERR_SERVERFAILED;
|
|
|
}
|
|
|
|
|
|
- evdns_server_request_respond(req, err);
|
|
|
+ if (!SOCKS_COMMAND_IS_RESOLVE_CONTROL(conn->socks_request->command))
|
|
|
+ evdns_server_request_respond(req, err);
|
|
|
+
|
|
|
conn->dns_server_request = NULL;
|
|
|
}
|
|
|
|