diff options
author | Nick Mathewson <nickm@torproject.org> | 2007-07-10 17:14:51 +0000 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2007-07-10 17:14:51 +0000 |
commit | 74711479eb22faf146b579e1856b37ee4a5afc8b (patch) | |
tree | b7efda701936d0bdc29ade77fb4dd20eef1f085c /src | |
parent | 77053147771164dd53c78bef1d27fb2be180eb5d (diff) | |
download | tor-74711479eb22faf146b579e1856b37ee4a5afc8b.tar.gz tor-74711479eb22faf146b579e1856b37ee4a5afc8b.zip |
r13666@catbus: nickm | 2007-07-10 13:10:00 -0400
Get the RESOLVE controller code working.
svn:r10781
Diffstat (limited to 'src')
-rw-r--r-- | src/or/connection_edge.c | 99 | ||||
-rw-r--r-- | src/or/control.c | 31 | ||||
-rw-r--r-- | src/or/dnsserv.c | 47 | ||||
-rw-r--r-- | src/or/main.c | 2 | ||||
-rw-r--r-- | src/or/or.h | 12 | ||||
-rw-r--r-- | src/or/relay.c | 6 |
6 files changed, 123 insertions, 74 deletions
diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c index e95fd893a5..5eea4a0ff5 100644 --- a/src/or/connection_edge.c +++ b/src/or/connection_edge.c @@ -59,7 +59,7 @@ _connection_mark_unattached_ap(edge_connection_t *conn, int endreason, else if (SOCKS_COMMAND_IS_RESOLVE(conn->socks_request->command)) connection_ap_handshake_socks_resolved(conn, RESOLVED_TYPE_ERROR_TRANSIENT, - 0, NULL, -1); + 0, NULL, -1, -1); else /* unknown or no handshake at all. send no response. */ conn->socks_request->has_finished = 1; } @@ -655,23 +655,30 @@ addressmap_free_all(void) * more rewrites; but don't get into an infinite loop. * Don't write more than maxlen chars into address. Return true if the * address changed; false otherwise. + * DOCDOC expires_out */ int -addressmap_rewrite(char *address, size_t maxlen) +addressmap_rewrite(char *address, size_t maxlen, time_t *expires_out) { addressmap_entry_t *ent; int rewrites; char *cp; + time_t expires = TIME_MAX; for (rewrites = 0; rewrites < 16; rewrites++) { ent = strmap_get(addressmap, address); - if (!ent || !ent->new_address) + if (!ent || !ent->new_address) { + if (expires_out) + *expires_out = expires; return (rewrites > 0); /* done, no rewrite needed */ + } cp = tor_strdup(escaped_safe_str(ent->new_address)); log_info(LD_APP, "Addressmap: rewriting %s to %s", escaped_safe_str(address), cp); + if (ent->expires > 1 && ent->expires < expires) + expires = ent->expires; tor_free(cp); strlcpy(address, ent->new_address, maxlen); } @@ -679,14 +686,17 @@ addressmap_rewrite(char *address, size_t maxlen) "Loop detected: we've rewritten %s 16 times! Using it as-is.", escaped_safe_str(address)); /* it's fine to rewrite a rewrite, but don't loop forever */ + if (expires_out) + *expires_out = TIME_MAX; return 1; } /** If we have a cached reverse DNS entry for the address stored in the * <b>maxlen</b>-byte buffer <b>address</b> (typically, a dotted quad) then - * rewrite to the cached value and return 1. Otherwise return 0. */ + * rewrite to the cached value and return 1. Otherwise return 0. + * DOCDOC expires_out */ static int -addressmap_rewrite_reverse(char *address, size_t maxlen) +addressmap_rewrite_reverse(char *address, size_t maxlen, time_t *expires_out) { size_t len = maxlen + 16; char *s = tor_malloc(len), *cp; @@ -702,6 +712,10 @@ addressmap_rewrite_reverse(char *address, size_t maxlen) strlcpy(address, ent->new_address, maxlen); r = 1; } + + if (expires_out) + *expires_out = (ent && ent->expires > 1) ? ent->expires : TIME_MAX; + tor_free(s); return r; } @@ -765,7 +779,7 @@ addressmap_register(const char *address, char *new_address, time_t expires) log_info(LD_CONFIG, "Addressmap: (re)mapped '%s' to '%s'", safe_str(address), safe_str(ent->new_address)); - control_event_address_mapped(address, ent->new_address, expires); + control_event_address_mapped(address, ent->new_address, expires, NULL); } /** An attempt to resolve <b>address</b> failed at some OR. @@ -1182,6 +1196,7 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn, struct in_addr addr_tmp; int automap = 0; char orig_address[MAX_SOCKS_ADDR_LEN]; + time_t map_expires = TIME_MAX; tor_strlower(socks->address); /* normalize it */ strlcpy(orig_address, socks->address, sizeof(orig_address)); @@ -1209,12 +1224,14 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn, } if (socks->command == SOCKS_COMMAND_RESOLVE_PTR) { - if (addressmap_rewrite_reverse(socks->address, sizeof(socks->address))) { + if (addressmap_rewrite_reverse(socks->address, sizeof(socks->address), + &map_expires)) { char *result = tor_strdup(socks->address); /* remember _what_ is supposed to have been resolved. */ strlcpy(socks->address, orig_address, sizeof(socks->address)); connection_ap_handshake_socks_resolved(conn, RESOLVED_TYPE_HOSTNAME, - strlen(result), result, -1); + strlen(result), result, -1, + map_expires); connection_mark_unattached_ap(conn, END_STREAM_REASON_DONE | END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED); @@ -1222,7 +1239,8 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn, } } else if (!automap) { /* For address map controls, remap the address. */ - if (addressmap_rewrite(socks->address, sizeof(socks->address))) { + if (addressmap_rewrite(socks->address, sizeof(socks->address), + &map_expires)) { control_event_stream_status(conn, STREAM_EVENT_REMAP, REMAP_STREAM_SOURCE_CACHE); } @@ -1309,7 +1327,7 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn, escaped(socks->address)); connection_ap_handshake_socks_resolved(conn, RESOLVED_TYPE_ERROR_TRANSIENT, - 0,NULL,-1); + 0,NULL,-1,TIME_MAX); connection_mark_unattached_ap(conn, END_STREAM_REASON_SOCKSPROTOCOL | END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED); @@ -1321,7 +1339,7 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn, /* remember _what_ is supposed to have been resolved. */ strlcpy(socks->address, orig_address, sizeof(socks->address)); connection_ap_handshake_socks_resolved(conn,RESOLVED_TYPE_IPV4,4, - (char*)&answer,-1); + (char*)&answer,-1,map_expires); connection_mark_unattached_ap(conn, END_STREAM_REASON_DONE | END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED); @@ -1382,7 +1400,7 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn, log_warn(LD_APP, "Resolve requests to hidden services not allowed. Failing."); connection_ap_handshake_socks_resolved(conn,RESOLVED_TYPE_ERROR, - 0,NULL,-1); + 0,NULL,-1,TIME_MAX); connection_mark_unattached_ap(conn, END_STREAM_REASON_SOCKSPROTOCOL | END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED); @@ -1962,17 +1980,52 @@ connection_ap_make_link(char *address, uint16_t port, return conn; } +/** DOCDOC */ +static void +tell_controller_about_resolved_result(edge_connection_t *conn, + int answer_type, + size_t answer_len, + const char *answer, + int ttl, + time_t expires) +{ + + if (ttl >= 0 && (answer_type == RESOLVED_TYPE_IPV4 || + answer_type == RESOLVED_TYPE_HOSTNAME)) { + return; /* we already told the controller. */ + } else if (answer_type == RESOLVED_TYPE_IPV4 && answer_len >= 4) { + struct in_addr in; + char buf[INET_NTOA_BUF_LEN]; + in.s_addr = get_uint32(answer); + tor_inet_ntoa(&in, buf, sizeof(buf)); + control_event_address_mapped(conn->socks_request->address, + buf, expires, NULL); + } else if (answer_type == RESOLVED_TYPE_HOSTNAME && answer_len <256) { + char *cp = tor_strndup(answer, answer_len); + control_event_address_mapped(conn->socks_request->address, + cp, expires, NULL); + tor_free(cp); + } else { + control_event_address_mapped(conn->socks_request->address, + "<error>", + time(NULL)+ttl, + "error=yes"); + } +} + /** Send an answer to an AP connection that has requested a DNS lookup * via SOCKS. The type should be one of RESOLVED_TYPE_(IPV4|IPV6|HOSTNAME) or * -1 for unreachable; the answer should be in the format specified * in the socks extensions document. + * DOCDOC expires **/ void connection_ap_handshake_socks_resolved(edge_connection_t *conn, int answer_type, size_t answer_len, const char *answer, - int ttl) + int ttl, + time_t expires) { char buf[384]; size_t replylen; @@ -1992,11 +2045,21 @@ connection_ap_handshake_socks_resolved(edge_connection_t *conn, } } - if (conn->dns_server_request) { - /* We had a request on our DNS port: answer it. */ - dnsserv_resolved(conn, answer_type, answer_len, answer, ttl); - conn->socks_request->has_finished = 1; - return; + if (conn->is_dns_request) { + if (conn->dns_server_request) { + /* We had a request on our DNS port: answer it. */ + dnsserv_resolved(conn, answer_type, answer_len, answer, ttl); + conn->socks_request->has_finished = 1; + return; + } else { + /* This must be a request from the controller. We already sent + * a mapaddress if there's a ttl. */ + tell_controller_about_resolved_result(conn, answer_type, answer_len, + answer, ttl, expires); + conn->socks_request->has_finished = 1; + return; + } + /* XXXX020 are we freeing conn anywhere? */ } if (conn->socks_request->socks_version == 4) { diff --git a/src/or/control.c b/src/or/control.c index 7cbf372be2..055d278d23 100644 --- a/src/or/control.c +++ b/src/or/control.c @@ -2221,9 +2221,10 @@ handle_control_resolve(control_connection_t *conn, uint32_t len, const char *body) { smartlist_t *args; + int is_reverse = 0; (void) len; /* body is nul-terminated; it's safe to ignore the length */ - if (!(conn->event_mask & EVENT_ADDRMAP)) { + if (!(conn->event_mask & (1L<<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."); @@ -2231,8 +2232,15 @@ handle_control_resolve(control_connection_t *conn, uint32_t len, args = smartlist_create(); smartlist_split_string(args, body, " ", SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); + if (smartlist_len(args) && + !strcasecmp(smartlist_get(args, 0), "mode=reverse")) { + char *cp = smartlist_get(args, 0); + smartlist_del_keeporder(args, 0); + tor_free(cp); + is_reverse = 1; + } SMARTLIST_FOREACH(args, const char *, arg, { - evdns_server_control(arg); + dnsserv_launch_request(arg, is_reverse); }); SMARTLIST_FOREACH(args, char *, cp, tor_free(cp)); @@ -3058,22 +3066,25 @@ control_event_descriptors_changed(smartlist_t *routers) } /** Called whenever an address mapping on <b>from<b> from changes to <b>to</b>. - * <b>expires</b> values less than 3 are special; see connection_edge.c. */ + * <b>expires</b> values less than 3 are special; see connection_edge.c. + * DOCDOC source. */ int -control_event_address_mapped(const char *from, const char *to, time_t expires) +control_event_address_mapped(const char *from, const char *to, time_t expires, + const char *error) { if (!EVENT_IS_INTERESTING(EVENT_ADDRMAP)) return 0; - if (expires < 3) - send_control_event(EVENT_ADDRMAP, ALL_NAMES, - "650 ADDRMAP %s %s NEVER\r\n", from, to); + if (expires < 3 || expires == TIME_MAX) + send_control_event_extended(EVENT_ADDRMAP, ALL_NAMES, + "650 ADDRMAP %s %s NEVER@%s\r\n", from, to, + error); else { char buf[ISO_TIME_LEN+1]; format_local_iso_time(buf,expires); - send_control_event(EVENT_ADDRMAP, ALL_NAMES, - "650 ADDRMAP %s %s \"%s\"\r\n", - from, to, buf); + send_control_event_extended(EVENT_ADDRMAP, ALL_NAMES, + "650 ADDRMAP %s %s \"%s\"@%s\r\n", + from, to, buf, error); } return 0; diff --git a/src/or/dnsserv.c b/src/or/dnsserv.c index b1262cc7c5..9f9ae4ce24 100644 --- a/src/or/dnsserv.c +++ b/src/or/dnsserv.c @@ -112,6 +112,7 @@ evdns_server_callback(struct evdns_server_request *req, void *_data) /* 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; + conn->is_dns_request = 1; TO_CONN(conn)->addr = ntohl(sin->sin_addr.s_addr); TO_CONN(conn)->port = ntohs(sin->sin_port); @@ -149,58 +150,25 @@ evdns_server_callback(struct evdns_server_request *req, void *_data) * controller. We need to eventually answer the request <b>req</b>. */ void -dnsserv_launch_request(const char *name) +dnsserv_launch_request(const char *name, int reverse) { 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; + if (reverse) + conn->socks_request->command = SOCKS_COMMAND_RESOLVE_PTR; else - conn->socks_request->command = SOCKS_COMMAND_RESOLVE_PTR_CONTROL; + conn->socks_request->command = SOCKS_COMMAND_RESOLVE; + + conn->is_dns_request = 1; 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 @@ -296,6 +264,7 @@ dnsserv_resolved(edge_connection_t *conn, if (!SOCKS_COMMAND_IS_RESOLVE_CONTROL(conn->socks_request->command)) evdns_server_request_respond(req, err); + conn->dns_server_request = NULL; } diff --git a/src/or/main.c b/src/or/main.c index 68e476fc4a..7a5ffb84b5 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -165,7 +165,7 @@ connection_add(connection_t *conn) tor_assert(conn->s >= 0 || conn->linked || (conn->type == CONN_TYPE_AP && - TO_EDGE_CONN(conn)->dns_server_request)); + TO_EDGE_CONN(conn)->is_dns_request)); tor_assert(conn->conn_array_index == -1); /* can only connection_add once */ conn->conn_array_index = smartlist_len(connection_array); diff --git a/src/or/or.h b/src/or/or.h index 64fad8ebde..aee3b8bdaf 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -910,6 +910,9 @@ typedef struct edge_connection_t { * already retried several times. */ uint8_t num_socks_retries; + /** True iff this connection is for a dns request only. */ + unsigned int is_dns_request : 1; + /** If this is a DNSPort connection, this field holds the pending DNS * request that we're going to try to answer. */ struct evdns_server_request *dns_server_request; @@ -2465,7 +2468,8 @@ void connection_ap_handshake_socks_resolved(edge_connection_t *conn, int answer_type, size_t answer_len, const char *answer, - int ttl); + int ttl, + time_t expires); int connection_exit_begin_conn(cell_t *cell, circuit_t *circ); int connection_exit_begin_resolve(cell_t *cell, or_circuit_t *circ); @@ -2487,7 +2491,7 @@ void addressmap_clean(time_t now); void addressmap_clear_configured(void); void addressmap_clear_transient(void); void addressmap_free_all(void); -int addressmap_rewrite(char *address, size_t maxlen); +int addressmap_rewrite(char *address, size_t maxlen, time_t *expires_out); int addressmap_have_mapping(const char *address); void addressmap_register(const char *address, char *new_address, time_t expires); @@ -2614,7 +2618,7 @@ int control_event_stream_bandwidth_used(void); void control_event_logmsg(int severity, unsigned int domain, const char *msg); int control_event_descriptors_changed(smartlist_t *routers); int control_event_address_mapped(const char *from, const char *to, - time_t expires); + time_t expires, const char *error); int control_event_or_authdir_new_descriptor(const char *action, const char *desc, size_t desclen, @@ -2801,7 +2805,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); +void dnsserv_launch_request(const char *name, int is_reverse); /********************************* hibernate.c **********************/ diff --git a/src/or/relay.c b/src/or/relay.c index 0a34687d6c..2bcd400453 100644 --- a/src/or/relay.c +++ b/src/or/relay.c @@ -759,7 +759,8 @@ connection_edge_process_end_not_open( } /* rewrite it to an IP if we learned one. */ if (addressmap_rewrite(conn->socks_request->address, - sizeof(conn->socks_request->address))) { + sizeof(conn->socks_request->address), + NULL)) { control_event_stream_status(conn, STREAM_EVENT_REMAP, 0); } if (conn->_base.chosen_exit_optional) { @@ -946,7 +947,8 @@ connection_edge_process_relay_cell_not_open( answer_type, cell->payload[RELAY_HEADER_SIZE+1], /*answer_len*/ cell->payload+RELAY_HEADER_SIZE+2, /*answer*/ - ttl); + ttl, + -1); if (answer_type == RESOLVED_TYPE_IPV4) { uint32_t addr = ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE+2)); remap_event_helper(conn, addr); |