mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-10 21:23:58 +01:00
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:
parent
ef246793d3
commit
7705314777
@ -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.");
|
||||
|
@ -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);
|
||||
|
116
src/or/dnsserv.c
116
src/or/dnsserv.c
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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 **********************/
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user