diff options
author | Nick Mathewson <nickm@torproject.org> | 2005-09-02 18:53:31 +0000 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2005-09-02 18:53:31 +0000 |
commit | a6a45b771381e1fb091ce0f8767f262f2a09f8e2 (patch) | |
tree | 34ee340c03706e48b782ed8a50d57d95a0c69530 | |
parent | 93179f4e7e68332e7316e40edcb14b584b8c712c (diff) | |
download | tor-a6a45b771381e1fb091ce0f8767f262f2a09f8e2.tar.gz tor-a6a45b771381e1fb091ce0f8767f262f2a09f8e2.zip |
Add TTLs to RESOLVED, CONNECTED, and END_REASON_EXITPOLICY cells. Also, add a missing ntohl in connection_ap_handshake_socks_resolved.
svn:r4894
-rw-r--r-- | doc/tor-spec.txt | 16 | ||||
-rw-r--r-- | src/or/connection_edge.c | 46 | ||||
-rw-r--r-- | src/or/dns.c | 17 | ||||
-rw-r--r-- | src/or/relay.c | 26 |
4 files changed, 76 insertions, 29 deletions
diff --git a/doc/tor-spec.txt b/doc/tor-spec.txt index 502384b456..5b035dbd3f 100644 --- a/doc/tor-spec.txt +++ b/doc/tor-spec.txt @@ -469,8 +469,16 @@ TODO: (very soon) address cannot be resolved, or a connection can't be established, the exit node replies with a RELAY_END cell. (See 5.4 below.) Otherwise, the exit node replies with a RELAY_CONNECTED cell, whose - payload is the 4-byte IPv4 address or the 16-byte IPv6 address to which - the connection was made. + payload is in one of the following formats: + The IPv4 address to which the connection was made [4 octets] + A number of seconds (TTL) for which the address may be cached [4 octets] + or + Four zero-valued octets [4 octets] + An address type (6) [1 octet] + The IPv6 address to which the connection was made [16 octets] + A number of seconds (TTL) for which the address may be cached [4 octets] + [XXXX Versions of Tor before 0.1.1.6 ignore and do not generate the TTL + field. No version of Tor currently generates the IPv6 format.] The OP waits for a RELAY_CONNECTED cell before sending any data. Once a connection has been established, the OP and exit node @@ -511,7 +519,8 @@ TODO: (very soon) Tor protocol violations.) (With REASON_EXITPOLICY, the 4-byte IPv4 address or 16-byte IPv6 address - forms the optional data; no other reason currently has extra data.) + forms the optional data; no other reason currently has extra data. + As of 0.1.1.6, the body also contains a 4-byte TTL.) OPs and ORs MUST accept reasons not on the above list, since future versions of Tor may provide more fine-grained reasons. @@ -558,6 +567,7 @@ TODO: (very soon) Type (1 octet) Length (1 octet) Value (variable-width) + TTL (4 octets) "Length" is the length of the Value field. "Type" is one of: 0x00 -- Hostname diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c index 8f1b93d3e2..e6d3705df6 100644 --- a/src/or/connection_edge.c +++ b/src/or/connection_edge.c @@ -48,7 +48,7 @@ _connection_mark_unattached_ap(connection_t *conn, int endreason, if (conn->socks_request->command == SOCKS_COMMAND_CONNECT) connection_ap_handshake_socks_reply(conn, NULL, 0, socksreason); else - connection_ap_handshake_socks_resolved(conn,RESOLVED_TYPE_ERROR,0,NULL); + connection_ap_handshake_socks_resolved(conn,RESOLVED_TYPE_ERROR,0,NULL,-1); } _connection_mark_for_close(conn, line, file); @@ -194,7 +194,8 @@ connection_edge_end(connection_t *conn, char reason, crypt_path_t *cpath_layer) /* this is safe even for rend circs, because they never fail * because of exitpolicy */ set_uint32(payload+1, htonl(conn->addr)); - payload_len += 4; + set_uint32(payload+5, htonl(MAX_DNS_ENTRY_AGE)); /* XXXXfill with a real TTL*/ + payload_len += 8; } circ = circuit_get_by_edge_conn(conn); @@ -266,7 +267,6 @@ connection_edge_finished_flushing(connection_t *conn) int connection_edge_finished_connecting(connection_t *conn) { - char connected_payload[4]; char valbuf[INET_NTOA_BUF_LEN]; struct in_addr in; @@ -289,9 +289,12 @@ connection_edge_finished_connecting(connection_t *conn) RELAY_COMMAND_CONNECTED, NULL, 0, conn->cpath_layer) < 0) return 0; /* circuit is closed, don't continue */ } else { - *(uint32_t*)connected_payload = htonl(conn->addr); + char connected_payload[8]; + set_uint32(connected_payload, htonl(htonl(conn->addr))); + set_uint32(connected_payload+4, + htonl(MAX_DNS_ENTRY_AGE)); /* XXXX fill with a real TTL */ if (connection_edge_send_command(conn, circuit_get_by_edge_conn(conn), - RELAY_COMMAND_CONNECTED, connected_payload, 4, conn->cpath_layer) < 0) + RELAY_COMMAND_CONNECTED, connected_payload, 8, conn->cpath_layer) < 0) return 0; /* circuit is closed, don't continue */ } tor_assert(conn->package_window > 0); @@ -683,9 +686,13 @@ client_dns_clear_failures(const char *address) * * If <b>exitname</b> is defined, then append the addresses with * ".exitname.exit" before registering the mapping. + * + * If <b>ttl</b> is nonnegative, the mapping will be valid for + * <b>ttl</b>seconds. */ void -client_dns_set_addressmap(const char *address, uint32_t val, const char *exitname) +client_dns_set_addressmap(const char *address, uint32_t val, const char *exitname, + int ttl) { struct in_addr in; char extendedaddress[MAX_SOCKS_ADDR_LEN+MAX_HEX_NICKNAME_LEN+10]; @@ -694,6 +701,9 @@ client_dns_set_addressmap(const char *address, uint32_t val, const char *exitnam tor_assert(address); tor_assert(val); + if (ttl<0 || ttl>MAX_DNS_ENTRY_AGE) + ttl = MAX_DNS_ENTRY_AGE; + if (tor_inet_aton(address, &in)) return; /* If address was an IP address already, don't add a mapping. */ in.s_addr = htonl(val); @@ -709,8 +719,7 @@ client_dns_set_addressmap(const char *address, uint32_t val, const char *exitnam tor_snprintf(extendedval, sizeof(extendedval), "%s", valbuf); } - addressmap_register(extendedaddress, tor_strdup(extendedval), - time(NULL) + MAX_DNS_ENTRY_AGE); + addressmap_register(extendedaddress, tor_strdup(extendedval), time(NULL) + ttl); } /* Currently, we hand out 127.192.0.1 through 127.254.254.254. @@ -1019,14 +1028,14 @@ connection_ap_handshake_process_socks(connection_t *conn) /* Reply to resolves immediately if we can. */ if (strlen(socks->address) > RELAY_PAYLOAD_SIZE) { log_fn(LOG_WARN,"Address to be resolved is too large. Failing."); - connection_ap_handshake_socks_resolved(conn,RESOLVED_TYPE_ERROR,0,NULL); + connection_ap_handshake_socks_resolved(conn,RESOLVED_TYPE_ERROR,0,NULL,-1); connection_mark_unattached_ap(conn, END_STREAM_REASON_ALREADY_SOCKS_REPLIED); return -1; } if (tor_inet_aton(socks->address, &in)) { /* see if it's an IP already */ answer = in.s_addr; /* leave it in network order */ connection_ap_handshake_socks_resolved(conn,RESOLVED_TYPE_IPV4,4, - (char*)&answer); + (char*)&answer,-1); connection_mark_unattached_ap(conn, END_STREAM_REASON_ALREADY_SOCKS_REPLIED); return 0; } @@ -1075,7 +1084,7 @@ connection_ap_handshake_process_socks(connection_t *conn) /* if it's a resolve request, fail it right now, rather than * building all the circuits and then realizing it won't work. */ log_fn(LOG_WARN,"Resolve requests to hidden services not allowed. Failing."); - connection_ap_handshake_socks_resolved(conn,RESOLVED_TYPE_ERROR,0,NULL); + connection_ap_handshake_socks_resolved(conn,RESOLVED_TYPE_ERROR,0,NULL,-1); connection_mark_unattached_ap(conn, END_STREAM_REASON_ALREADY_SOCKS_REPLIED); return -1; } @@ -1299,16 +1308,17 @@ void connection_ap_handshake_socks_resolved(connection_t *conn, int answer_type, size_t answer_len, - const char *answer) + const char *answer, + int ttl) { char buf[256]; size_t replylen; if (answer_type == RESOLVED_TYPE_IPV4) { - uint32_t a = get_uint32(answer); + uint32_t a = ntohl(get_uint32(answer)); if (a) client_dns_set_addressmap(conn->socks_request->address, ntohl(a), - conn->chosen_exit_name); + conn->chosen_exit_name, ttl); } if (conn->socks_request->socks_version == 4) { @@ -1581,7 +1591,6 @@ connection_exit_begin_resolve(cell_t *cell, circuit_t *circ) void connection_exit_connect(connection_t *conn) { - char connected_payload[4]; uint32_t addr; uint16_t port; @@ -1649,10 +1658,13 @@ connection_exit_connect(connection_t *conn) NULL, 0, conn->cpath_layer); } else { /* normal stream */ /* This must be the original address, not the redirected address. */ - *(uint32_t*)connected_payload = htonl(conn->addr); + char connected_payload[8]; + set_uint32(connected_payload, htonl(htonl(conn->addr))); + set_uint32(connected_payload+4, + htonl(MAX_DNS_ENTRY_AGE)); /* XXXX fill with a real TTL */ connection_edge_send_command(conn, circuit_get_by_edge_conn(conn), RELAY_COMMAND_CONNECTED, - connected_payload, 4, conn->cpath_layer); + connected_payload, 8, conn->cpath_layer); } } diff --git a/src/or/dns.c b/src/or/dns.c index 39ce5ff1c4..87a3baaa5f 100644 --- a/src/or/dns.c +++ b/src/or/dns.c @@ -192,14 +192,21 @@ send_resolved_cell(connection_t *conn, uint8_t answer_type) case RESOLVED_TYPE_IPV4: buf[1] = 4; set_uint32(buf+2, htonl(conn->addr)); - buflen = 6; + set_uint32(buf+6, htonl(MAX_DNS_ENTRY_AGE)); /*XXXX send a real TTL*/ + buflen = 10; break; case RESOLVED_TYPE_ERROR_TRANSIENT: case RESOLVED_TYPE_ERROR: - buf[1] = 24; /* length of "error resolving hostname" */ - strlcpy(buf+2, "error resolving hostname", sizeof(buf)-2); - buflen = 26; - break; + { + const char *errmsg = "Error resolving hostname"; + int msglen = strlen(errmsg); + int ttl = (answer_type == RESOLVED_TYPE_ERROR ? MAX_DNS_ENTRY_AGE : 0); + buf[1] = msglen; + strlcpy(buf+2, errmsg, sizeof(buf)-2); + set_uint32(buf+2+msglen, htonl((uint32_t)ttl)); + buflen = 6+msglen; + break; + } default: tor_assert(0); } diff --git a/src/or/relay.c b/src/or/relay.c index c2dada534b..60e895903c 100644 --- a/src/or/relay.c +++ b/src/or/relay.c @@ -640,14 +640,19 @@ connection_edge_process_end_not_open( case END_STREAM_REASON_EXITPOLICY: if (rh->length >= 5) { uint32_t addr = ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE+1)); + int ttl; if (!addr) { log_fn(LOG_INFO,"Address '%s' resolved to 0.0.0.0. Closing,", safe_str(conn->socks_request->address)); connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL); return 0; } + if (rh->length >= 9) + ttl = (int)ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE+5)); + else + ttl = -1; client_dns_set_addressmap(conn->socks_request->address, addr, - conn->chosen_exit_name); + conn->chosen_exit_name, ttl); } /* check if he *ought* to have allowed it */ if (exitrouter && @@ -735,14 +740,19 @@ connection_edge_process_relay_cell_not_open( (int)(time(NULL) - conn->timestamp_lastread)); if (rh->length >= 4) { uint32_t addr = ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE)); + int ttl; if (!addr) { log_fn(LOG_INFO,"...but it claims the IP address was 0.0.0.0. Closing."); connection_edge_end(conn, END_STREAM_REASON_TORPROTOCOL, conn->cpath_layer); connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL); return 0; } + if (rh->length >= 8) + ttl = (int)ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE+8)); + else + ttl = -1; client_dns_set_addressmap(conn->socks_request->address, addr, - conn->chosen_exit_name); + conn->chosen_exit_name, ttl); } circuit_log_path(LOG_INFO,circ); connection_ap_handshake_socks_reply(conn, NULL, 0, SOCKS5_SUCCEEDED); @@ -755,20 +765,28 @@ connection_edge_process_relay_cell_not_open( return 0; } if (conn->type == CONN_TYPE_AP && rh->command == RELAY_COMMAND_RESOLVED) { + int ttl; + int answer_len; if (conn->state != AP_CONN_STATE_RESOLVE_WAIT) { log_fn(LOG_WARN,"Got a 'resolved' cell while not in state resolve_wait. Dropping."); return 0; } tor_assert(conn->socks_request->command == SOCKS_COMMAND_RESOLVE); - if (rh->length < 2 || cell->payload[RELAY_HEADER_SIZE+1]+2>rh->length) { + answer_len = cell->payload[RELAY_HEADER_SIZE+1]; + if (rh->length < 2 || answer_len+2>rh->length) { log_fn(LOG_WARN, "Dropping malformed 'resolved' cell"); connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL); return 0; } + if (rh->length >= answer_len+6) + ttl = (int)ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE+6)); + else + ttl = -1; connection_ap_handshake_socks_resolved(conn, cell->payload[RELAY_HEADER_SIZE], /*answer_type*/ cell->payload[RELAY_HEADER_SIZE+1], /*answer_len*/ - cell->payload+RELAY_HEADER_SIZE+2); /* answer */ + cell->payload+RELAY_HEADER_SIZE+2, + ttl); /* answer */ connection_mark_unattached_ap(conn, END_STREAM_REASON_ALREADY_SOCKS_REPLIED); return 0; } |