r13637@catbus: nickm | 2007-07-06 14:24:27 -0400

fix copy-paste error in config message src/or/config.c .  Apply
 initial (but pared-down) version of launch-resolve-via-controller
 patch from Robert Hogan.
 


svn:r10780
This commit is contained in:
Nick Mathewson 2007-07-10 17:13:24 +00:00
parent ef246793d3
commit 7705314777
4 changed files with 141 additions and 12 deletions

View File

@ -2445,7 +2445,7 @@ options_validate(or_options_t *old_options, or_options_t *options,
REJECT("DirPort must be defined if DirListenAddress is defined.");
if (options->DNSPort == 0 && options->DNSListenAddress != NULL)
REJECT("DirPort must be defined if DirListenAddress is defined.");
REJECT("DNSPort must be defined if DNSListenAddress is defined.");
if (options->ControlPort == 0 && options->ControlListenAddress != NULL)
REJECT("ControlPort must be defined if ControlListenAddress is defined.");

View File

@ -133,6 +133,8 @@ static int handle_control_closestream(control_connection_t *conn, uint32_t len,
static int handle_control_closecircuit(control_connection_t *conn,
uint32_t len,
const char *body);
static int handle_control_resolve(control_connection_t *conn, uint32_t len,
const char *body);
static int handle_control_usefeature(control_connection_t *conn,
uint32_t len,
const char *body);
@ -894,6 +896,8 @@ handle_control_setevents(control_connection_t *conn, uint32_t len,
event_code = EVENT_GUARD;
} else if (!strcasecmp(ev, "STREAM_BW"))
event_code = EVENT_STREAM_BANDWIDTH_USED;
else if (!strcasecmp(ev, "RESOLVED"))
event_code = EVENT_RESOLVED;
else {
connection_printf_to_buf(conn, "552 Unrecognized event \"%s\"\r\n",
ev);
@ -2212,6 +2216,32 @@ handle_control_closecircuit(control_connection_t *conn, uint32_t len,
return 0;
}
static int
handle_control_resolve(control_connection_t *conn, uint32_t len,
const char *body)
{
smartlist_t *args;
(void) len; /* body is nul-terminated; it's safe to ignore the length */
if (!(conn->event_mask & EVENT_ADDRMAP)) {
log_warn(LD_CONTROL, "Controller asked us to resolve an address, but "
"isn't listening for ADDRMAP events. It probably won't see "
"the answer.");
}
args = smartlist_create();
smartlist_split_string(args, body, " ",
SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
SMARTLIST_FOREACH(args, const char *, arg, {
evdns_server_control(arg);
});
SMARTLIST_FOREACH(args, char *, cp, tor_free(cp));
smartlist_free(args);
send_control_done(conn);
return 0;
}
/** Called when we get a USEFEATURE command: parse the feature list, and
* set up the control_connection's options properly. */
static int
@ -2442,6 +2472,9 @@ connection_control_process_inbuf(control_connection_t *conn)
} else if (!strcasecmp(conn->incoming_cmd, "USEFEATURE")) {
if (handle_control_usefeature(conn, data_len, args))
return -1;
} else if (!strcasecmp(conn->incoming_cmd, "RESOLVE")) {
if (handle_control_resolve(conn, data_len, args))
return -1;
} else {
connection_printf_to_buf(conn, "510 Unrecognized command \"%s\"\r\n",
conn->incoming_cmd);

View File

@ -145,6 +145,78 @@ evdns_server_callback(struct evdns_server_request *req, void *_data)
tor_free(q_name);
}
/* Helper function: called whenever the client sends a resolve request to our
* 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;
/* Make a new dummy AP connection, and attach the request to it. */
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));
/* 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(name));
q_name = tor_strdup(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. */
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
@ -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 { /* answer_type == RESOLVED_TYPE_ERROR_TRANSIENT */
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;
}

View File

@ -2095,6 +2095,7 @@ static INLINE void or_state_mark_dirty(or_state_t *state, time_t when)
#define SOCKS_COMMAND_RESOLVE 0xF0
/** Please turn this IP address into an FQDN, privately. */
#define SOCKS_COMMAND_RESOLVE_PTR 0xF1
/** Please open an encrypted direct TCP connection to the directory port
* of the Tor server specified by address:port. (In this case address:port
* specifies the ORPort of the server.) */
@ -2800,6 +2801,7 @@ void dnsserv_resolved(edge_connection_t *conn,
const char *answer,
int ttl);
void dnsserv_reject_request(edge_connection_t *conn);
void dnsserv_launch_request(const char *name);
/********************************* hibernate.c **********************/