r13050@catbus: nickm | 2007-05-29 13:31:11 -0400

Resolve all but 3 DOCDOCs.


svn:r10393
This commit is contained in:
Nick Mathewson 2007-05-29 17:31:13 +00:00
parent 69c712f189
commit f89a3b1448
16 changed files with 289 additions and 142 deletions

View File

@ -22,12 +22,11 @@ Changes in version 0.2.0.1-alpha - 2007-??-??
logging information that would be very useful to an attacker. logging information that would be very useful to an attacker.
- Start work implementing proposal 103: Add a standalone tool to - Start work implementing proposal 103: Add a standalone tool to
generate key certificates. generate key certificates.
- Initial implementation of a client-side DNS proxy feature to replace - A client-side DNS proxy feature to replace the need for dns-proxy-tor:
the need for dns-proxy-tor: Just set "DNSPort 9999", and Tor will Just set "DNSPort 9999", and Tor will now listen for DNS requests on
now listen for DNS requests on port 9999, use the Tor network to port 9999, use the Tor network to resolve them anonymously, and send
resolve them anonymously, and send the reply back like a regular DNS the reply back like a regular DNS server. The code is still only
server. The code is still buggy, undocumented, and only implements implements a subset of DNS.
a subset of DNS.
o Security fixes: o Security fixes:
- Directory authorities now call routers stable if they have an - Directory authorities now call routers stable if they have an

View File

@ -807,7 +807,14 @@ tor_inet_aton(const char *c, struct in_addr* addr)
#endif #endif
} }
/** DOCDOC */ /** Given <b>af</b>==AF_INET and <b>src</b> a struct in_addr, or
* <b>af</b>==AF_INET6 and <b>src</b> a struct in6_addr, try to format the
* address and store it in the <b>len</b>-byte buffer <b>dst</b>. Returns
* <b>dst</b> on success, NULL on failure.
*
* (Like inet_ntop(af,src,dst,len), but works on platforms that don't have it:
* Tor sometimes needs to format ipv6 addresses even on platforms without ipv6
* support.) */
const char * const char *
tor_inet_ntop(int af, const void *src, char *dst, size_t len) tor_inet_ntop(int af, const void *src, char *dst, size_t len)
{ {
@ -881,7 +888,15 @@ tor_inet_ntop(int af, const void *src, char *dst, size_t len)
#endif #endif
} }
/** DOCDOC */ /** Given <b>af</b>==AF_INET or <b>af</b>==AF_INET6, and a string <b>src</b>
* encoding an IPv4 address or IPv6 address correspondingly, try to parse the
* address and store the result in <b>dst</b> (which must have space for a
* struct in_addr or a struct in6_addr, as appropriate). Return 1 on success,
* 0 on a bad parse, and -1 on a bad <b>af</b>.
*
* (Like inet_pton(af,src,dst) but works on platforms that don't have it: Tor
* sometimes needs to format ipv6 addresses even on platforms without ipv6
* support.) */
int int
tor_inet_pton(int af, const char *src, void *dst) tor_inet_pton(int af, const char *src, void *dst)
{ {

View File

@ -78,8 +78,8 @@ extern INLINE void smartlist_set(smartlist_t *sl, int idx, void *val) {
#define smartlist_set(sl, idx, val) ((sl)->list[idx] = (val)) #define smartlist_set(sl, idx, val) ((sl)->list[idx] = (val))
#endif #endif
// void smartlist_swap(smartlist_t *sl, int idx1, int idx2); /** Exchange the elements at indices <b>idx1</b> and <b>idx2</b> of the
/**DOCDOC*/ * smartlist <b>sl</b>. */
static INLINE void smartlist_swap(smartlist_t *sl, int idx1, int idx2) static INLINE void smartlist_swap(smartlist_t *sl, int idx1, int idx2)
{ {
if (idx1 != idx2) { if (idx1 != idx2) {

View File

@ -88,10 +88,15 @@ int _log_global_min_severity = LOG_NOTICE;
static void delete_log(logfile_t *victim); static void delete_log(logfile_t *victim);
static void close_log(logfile_t *victim); static void close_log(logfile_t *victim);
/** DOCDOC */ /** Name of the application: used to generate the message we write at the
* start of each new log. */
static char *appname = NULL; static char *appname = NULL;
/** DOCDOC */ /** Set the "application name" for the logs to <b>name</b>: we'll use this
* name in the message we write when starting up, and at the start of each new
* log.
*
* Tor uses this string to write the version number to the log file. */
void void
log_set_application_name(const char *name) log_set_application_name(const char *name)
{ {

View File

@ -498,8 +498,9 @@ mp_pool_assert_ok(mp_pool_t *pool)
} }
#ifdef TOR #ifdef TOR
/** Dump information about <b>pool</b>'s memory usage to the Tor log at level
* <b>severity</b>. */
/*FFFF uses Tor logging functions. */ /*FFFF uses Tor logging functions. */
/**DOCDOC*/
void void
mp_pool_log_status(mp_pool_t *pool, int severity) mp_pool_log_status(mp_pool_t *pool, int severity)
{ {

View File

@ -2277,7 +2277,12 @@ connection_state_is_connecting(connection_t *conn)
return 0; return 0;
} }
/** DOCDOC */ /* XXXX020 move this into main.c */
/** Return true iff <b>conn</b> is linked conn, and reading from the conn
* linked to it would be good and feasible. (Reading is "feasible" if the
* other conn exists and has data in its outbuf, and is "good" if we have our
* reading_from_linked_conn flag set and the other conn has its
* writing_to_linked_conn flag set.)*/
int int
connection_should_read_from_linked_conn(connection_t *conn) connection_should_read_from_linked_conn(connection_t *conn)
{ {
@ -2630,7 +2635,7 @@ assert_connection_ok(connection_t *conn, time_t now)
tor_assert(edge_conn->socks_request); tor_assert(edge_conn->socks_request);
if (conn->state == AP_CONN_STATE_OPEN) { if (conn->state == AP_CONN_STATE_OPEN) {
tor_assert(edge_conn->socks_request->has_finished); tor_assert(edge_conn->socks_request->has_finished != 0);
if (!conn->marked_for_close) { if (!conn->marked_for_close) {
tor_assert(edge_conn->cpath_layer); tor_assert(edge_conn->cpath_layer);
assert_cpath_layer_ok(edge_conn->cpath_layer); assert_cpath_layer_ok(edge_conn->cpath_layer);

View File

@ -1851,7 +1851,12 @@ connection_ap_handshake_send_resolve(edge_connection_t *ap_conn)
uint32_t a; uint32_t a;
size_t len = strlen(ap_conn->socks_request->address); size_t len = strlen(ap_conn->socks_request->address);
char c = 0; char c = 0;
/* XXXX020 This logic is a little ugly: we check for an in-addr.arpa ending
* on the address. If we have one, the address is already in the right
* order, so we'll leave it alone later. Otherwise, we reverse it and
* turn it into an in-addr.arpa address. */
if (!strcasecmpend(ap_conn->socks_request->address, ".in-addr.arpa")) { if (!strcasecmpend(ap_conn->socks_request->address, ".in-addr.arpa")) {
/* Temporarily truncate the address, so we can give it to inet_aton. */
c = ap_conn->socks_request->address[len-13]; c = ap_conn->socks_request->address[len-13];
ap_conn->socks_request->address[len-13] = '\0'; ap_conn->socks_request->address[len-13] = '\0';
} }
@ -1859,7 +1864,6 @@ connection_ap_handshake_send_resolve(edge_connection_t *ap_conn)
connection_mark_unattached_ap(ap_conn, END_STREAM_REASON_INTERNAL); connection_mark_unattached_ap(ap_conn, END_STREAM_REASON_INTERNAL);
return -1; return -1;
} }
/* DOCDOC */
if (c) { if (c) {
/* this path happens on DNS. Can we unify? XXXX020 */ /* this path happens on DNS. Can we unify? XXXX020 */
ap_conn->socks_request->address[len-13] = c; ap_conn->socks_request->address[len-13] = c;
@ -1893,13 +1897,12 @@ connection_ap_handshake_send_resolve(edge_connection_t *ap_conn)
return 0; return 0;
} }
/** Make an AP connection_t, do a socketpair and attach one side /** Make an AP connection_t, make a new linked connection pair, and attach
* to the conn, connection_add it, initialize it to circuit_wait, * one side to the conn, connection_add it, initialize it to circuit_wait,
* and call connection_ap_handshake_attach_circuit(conn) on it. * and call connection_ap_handshake_attach_circuit(conn) on it.
* *
* Return the other end of the socketpair, or -1 if error. * Return the other end of the linked connection pair, or -1 if error.
* *
* DOCDOC The above is now wrong; we use links.
* DOCDOC start_reading * DOCDOC start_reading
*/ */
edge_connection_t * edge_connection_t *
@ -1982,8 +1985,9 @@ connection_ap_handshake_socks_resolved(edge_connection_t *conn,
} }
if (conn->dns_server_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); dnsserv_resolved(conn, answer_type, answer_len, answer, ttl);
conn->socks_request->has_finished = 1; /* DOCDOC */ conn->socks_request->has_finished = 1;
return; return;
} }
@ -2430,13 +2434,11 @@ connection_exit_connect(edge_connection_t *edge_conn)
} }
/** Given an exit conn that should attach to us as a directory server, open a /** Given an exit conn that should attach to us as a directory server, open a
* bridge connection with a socketpair, create a new directory conn, and join * bridge connection with a linked connection pir, create a new directory
* them together. Return 0 on success (or if there was an error we could send * conn, and join them together. Return 0 on success (or if there was an
* back an end cell for). Return -(some circuit end reason) if the circuit * error we could send back an end cell for). Return -(some circuit end
* needs to be torn down. Either connects <b>exitconn<b/>, frees it, * reason) if the circuit needs to be torn down. Either connects
* or marks it, as appropriate. * <b>exitconn<b/>, frees it, or marks it, as appropriate.
*
* DOCDOC no longer uses socketpair
*/ */
static int static int
connection_exit_connect_dir(edge_connection_t *exitconn) connection_exit_connect_dir(edge_connection_t *exitconn)

View File

@ -108,7 +108,9 @@ authority_type_to_string(authority_type_t auth)
return result; return result;
} }
/* DOCDOC */ /** Return true iff <b>identity_digest</b> is the digest of a router we
* believe to support extrainfo downloads. (If <b>is_authority</b> we do
* additional checking that's only valid for authorities.) */
int int
router_supports_extrainfo(const char *identity_digest, int is_authority) router_supports_extrainfo(const char *identity_digest, int is_authority)
{ {
@ -130,7 +132,7 @@ router_supports_extrainfo(const char *identity_digest, int is_authority)
return 0; return 0;
} }
/** Start a connection to every suitable directory server, using /** Start a connection to every suitable directory authority, using
* connection purpose 'purpose' and uploading the payload 'payload' * connection purpose 'purpose' and uploading the payload 'payload'
* (length 'payload_len'). The purpose should be one of * (length 'payload_len'). The purpose should be one of
* 'DIR_PURPOSE_UPLOAD_DIR' or 'DIR_PURPOSE_UPLOAD_RENDDESC'. * 'DIR_PURPOSE_UPLOAD_DIR' or 'DIR_PURPOSE_UPLOAD_RENDDESC'.
@ -138,7 +140,11 @@ router_supports_extrainfo(const char *identity_digest, int is_authority)
* <b>type</b> specifies what sort of dir authorities (V1, V2, * <b>type</b> specifies what sort of dir authorities (V1, V2,
* HIDSERV, BRIDGE) we should upload to. * HIDSERV, BRIDGE) we should upload to.
* *
* DOCDOC extrainfo_len is in addition to payload_len. * If <b>extrainfo_len</b> is nonzero, the first <b>payload_len</b> bytes of
* <b>payload</b> hold a router descriptor, and the next <b>extrainfo_len</b>
* bytes of <b>payload</b> hold an extra-info document. Upload the descriptor
* to all authorities, and the extra-info document to all authorities that
* support it.
*/ */
void void
directory_post_to_dirservers(uint8_t purpose, authority_type_t type, directory_post_to_dirservers(uint8_t purpose, authority_type_t type,
@ -2118,10 +2124,9 @@ dir_networkstatus_download_failed(smartlist_t *failed, int status_code)
}); });
} }
/** Called when one or more routerdesc fetches have failed (with uppercase /** Called when one or more routerdesc (or extrainfo, if <b>was_extrainfo</b>)
* fingerprints listed in <b>failed</b>). * fetches have failed (with uppercase fingerprints listed in
* * <b>failed</b>). */
* DOCDOC was_extrainfo */
static void static void
dir_routerdesc_download_failed(smartlist_t *failed, int status_code, dir_routerdesc_download_failed(smartlist_t *failed, int status_code,
int was_extrainfo) int was_extrainfo)

View File

@ -557,9 +557,9 @@ dirserv_add_multiple_descriptors(const char *desc, const char **msg)
return r <= 2 ? r : 2; return r <= 2 ? r : 2;
} }
/** Parse the server descriptor at <b>desc</b> and maybe insert it into the /** Examine the parsed server descriptor in <b>ri</b> and maybe insert it into
* list of server descriptors. Set *<b>msg</b> to a message that should be * the list of server descriptors. Set *<b>msg</b> to a message that should be
* passed back to the origin of this descriptor. DOCDOC no longer parses. * passed back to the origin of this descriptor.
* *
* Return 2 if descriptor is well-formed and accepted; * Return 2 if descriptor is well-formed and accepted;
* 1 if well-formed and accepted but origin should hear *msg; * 1 if well-formed and accepted but origin should hear *msg;
@ -616,7 +616,7 @@ dirserv_add_descriptor(routerinfo_t *ri, const char **msg)
} }
} }
/** DOCDOC */ /** As dirserv_add_descriptor, but for an extrainfo_t <b>ei</b>. */
static int static int
dirserv_add_extrainfo(extrainfo_t *ei, const char **msg) dirserv_add_extrainfo(extrainfo_t *ei, const char **msg)
{ {
@ -1575,7 +1575,11 @@ dirserv_compute_performance_thresholds(routerlist_t *rl)
smartlist_free(bandwidths_excluding_exits); smartlist_free(bandwidths_excluding_exits);
} }
/** DOCDOC */ /** Helper: write the router-status information in <b>rs</b> into <b>buf</b>,
* which has at least <b>buf_len</b> free characters. Do NUL-termination.
* Use the same format as in network-status documents. If <b>platform</b> is
* non-NULL, add a "v" line for the platform. Return 0 on success, -1 on
* failure. */
int int
routerstatus_format_entry(char *buf, size_t buf_len, routerstatus_format_entry(char *buf, size_t buf_len,
routerstatus_t *rs, const char *platform) routerstatus_t *rs, const char *platform)
@ -1646,7 +1650,8 @@ routerstatus_format_entry(char *buf, size_t buf_len,
return 0; return 0;
} }
/** DOCDOC */ /** Helper for sorting: compare two routerinfos by their identity
* digest. */
static int static int
_compare_routerinfo_by_id_digest(const void **a, const void **b) _compare_routerinfo_by_id_digest(const void **a, const void **b)
{ {
@ -1656,9 +1661,11 @@ _compare_routerinfo_by_id_digest(const void **a, const void **b)
DIGEST_LEN); DIGEST_LEN);
} }
/** For v2 authoritative directories only: replace the contents of /** For v2 and v3 authoritative directories only: If <b>v2</b> is set, replace
* <b>the_v2_networkstatus</b> with a newly generated network status * the contents of <b>the_v2_networkstatus</b> with a newly generated network
* object. DOCDOC v2*/ * status object. If <b>v2</b> is zero, replace the contents of
* <b>the_v3_networkstatus_vote</b> with a newly generated consensus vote
* object. */
static cached_dir_t * static cached_dir_t *
generate_networkstatus_opinion(int v2) generate_networkstatus_opinion(int v2)
{ {

View File

@ -12,6 +12,9 @@ const char dnsserv_c_id[] =
#include "or.h" #include "or.h"
#include "eventdns.h" #include "eventdns.h"
/* Helper function: called by evdns whenever the client sends a request to our
* DNSPort. We need to eventually answer the request <b>req</b>.
*/
static void static void
evdns_server_callback(struct evdns_server_request *req, void *_data) evdns_server_callback(struct evdns_server_request *req, void *_data)
{ {
@ -23,11 +26,13 @@ evdns_server_callback(struct evdns_server_request *req, void *_data)
int addrlen; int addrlen;
uint32_t ipaddr; uint32_t ipaddr;
int err = DNS_ERR_NONE; int err = DNS_ERR_NONE;
char *q_name;
tor_assert(req); tor_assert(req);
tor_assert(_data == NULL); tor_assert(_data == NULL);
log_info(LD_APP, "Got a new DNS request!"); log_info(LD_APP, "Got a new DNS request!");
/* First, check whether the requesting address matches our SOCKSPolicy. */
if ((addrlen = evdns_server_request_get_requesting_addr(req, if ((addrlen = evdns_server_request_get_requesting_addr(req,
(struct sockaddr*)&addr, sizeof(addr))) < 0) { (struct sockaddr*)&addr, sizeof(addr))) < 0) {
log_warn(LD_APP, "Couldn't get requesting address."); log_warn(LD_APP, "Couldn't get requesting address.");
@ -49,6 +54,11 @@ evdns_server_callback(struct evdns_server_request *req, void *_data)
evdns_server_request_respond(req, DNS_ERR_REFUSED); evdns_server_request_respond(req, DNS_ERR_REFUSED);
return; return;
} }
/* Now, let's find the first actual question of a type we can answer in this
* DNS request. It makes us a little noncompliant to act like this; we
* should fix that eventually if it turns out to make a difference for
* anybody. */
if (req->nquestions == 0) { if (req->nquestions == 0) {
log_info(LD_APP, "No questions in DNS request; sending back nil reply."); log_info(LD_APP, "No questions in DNS request; sending back nil reply.");
evdns_server_request_respond(req, 0); evdns_server_request_respond(req, 0);
@ -76,22 +86,27 @@ evdns_server_callback(struct evdns_server_request *req, void *_data)
return; return;
} }
if (q->type == EVDNS_TYPE_A) { if (q->type == EVDNS_TYPE_A) {
/* Refuse any attempt to resolve a noconnect address, right now. */
if (hostname_is_noconnect_address(q->name)) { if (hostname_is_noconnect_address(q->name)) {
err = DNS_ERR_REFUSED; err = DNS_ERR_REFUSED;
} }
} else { } else {
tor_assert(q->type == EVDNS_TYPE_PTR); tor_assert(q->type == EVDNS_TYPE_PTR);
} }
/* Make sure the name isn't too long: This should be impossible, I think. */
if (err == DNS_ERR_NONE && strlen(q->name) > MAX_SOCKS_ADDR_LEN-1) if (err == DNS_ERR_NONE && strlen(q->name) > MAX_SOCKS_ADDR_LEN-1)
err = DNS_ERR_FORMAT; err = DNS_ERR_FORMAT;
if (err != DNS_ERR_NONE) { if (err != DNS_ERR_NONE) {
/* We got an error? Then send back an answer immediately; we're done. */
evdns_server_request_respond(req, err); evdns_server_request_respond(req, err);
return; return;
} }
/* XXXX020 Send a stream event to the controller. */ /* XXXX020 Send a stream event to the controller. */
/* Make a new dummy AP connection, and attach the request to it. */
conn = TO_EDGE_CONN(connection_new(CONN_TYPE_AP)); conn = TO_EDGE_CONN(connection_new(CONN_TYPE_AP));
conn->_base.state = AP_CONN_STATE_RESOLVE_WAIT; conn->_base.state = AP_CONN_STATE_RESOLVE_WAIT;
if (q->type == EVDNS_TYPE_A) if (q->type == EVDNS_TYPE_A)
@ -104,20 +119,36 @@ evdns_server_callback(struct evdns_server_request *req, void *_data)
conn->dns_server_request = req; conn->dns_server_request = req;
log_info(LD_APP, "Passing request for %s to rewrite_and_attach.", q->name); /* 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(q->name));
q_name = tor_strdup(q->name); /* q could be freed in rewrite_and_attach */
connection_ap_handshake_rewrite_and_attach(conn, NULL, NULL); connection_ap_handshake_rewrite_and_attach(conn, NULL, NULL);
/* Now the connection is marked if it was bad. */ /* Now, the connection is marked if it was bad. */
log_info(LD_APP, "Passed request for %s to rewrite_and_attach.", q->name); 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 void
dnsserv_reject_request(edge_connection_t *conn) dnsserv_reject_request(edge_connection_t *conn)
{ {
evdns_server_request_respond(conn->dns_server_request, DNS_ERR_SERVERFAILED); if (conn->dns_server_request) {
conn->dns_server_request = NULL; evdns_server_request_respond(conn->dns_server_request,
DNS_ERR_SERVERFAILED);
conn->dns_server_request = NULL;
}
} }
/** Tell the dns request waiting for an answer on <b>conn</b> that we have an
* answer of type <b>answer_type</b> (RESOLVE_TYPE_IPV4/IPV6/ERR), of length
* <b>answer_len</b>, in <b>answer</b>, with TTL <b>ttl</b>. Doesn't do
* any caching; that's handled elsewhere. */
void void
dnsserv_resolved(edge_connection_t *conn, dnsserv_resolved(edge_connection_t *conn,
int answer_type, int answer_type,
@ -130,10 +161,13 @@ dnsserv_resolved(edge_connection_t *conn,
if (!req) if (!req)
return; return;
/* XXXX Re-do. */ /* XXXX020 Re-do; this is dumb. */
if (ttl < 60) if (ttl < 60)
ttl = 60; ttl = 60;
/* The evdns interface is: add a bunch of reply items (corresponding to one
* or more of the questions in the request); then, call
* evdns_server_request_respond. */
if (answer_type == RESOLVED_TYPE_IPV6) { if (answer_type == RESOLVED_TYPE_IPV6) {
log_info(LD_APP, "Got an IPv6 answer; that's not implemented."); log_info(LD_APP, "Got an IPv6 answer; that's not implemented.");
err = DNS_ERR_NOTIMPL; err = DNS_ERR_NOTIMPL;
@ -150,26 +184,36 @@ dnsserv_resolved(edge_connection_t *conn,
(char*)answer, ttl); (char*)answer, ttl);
tor_free(ans); tor_free(ans);
} else { } else {
err = DNS_ERR_SERVERFAILED; err = DNS_ERR_SERVERFAILED; /* Really? Not noent? */
} }
evdns_server_request_respond(req, err); evdns_server_request_respond(req, err);
conn->dns_server_request = NULL; conn->dns_server_request = NULL;
} }
/* Set up the evdns server port for the UDP socket on <b>conn</b>, which
* must be an AP_DNS_LISTENER */
void void
dnsserv_configure_listener(connection_t *conn) dnsserv_configure_listener(connection_t *conn)
{ {
tor_assert(conn); tor_assert(conn);
tor_assert(conn->s); tor_assert(conn->s);
tor_assert(conn->type == CONN_TYPE_AP_DNS_LISTENER);
evdns_add_server_port(conn->s, 0, evdns_server_callback, NULL); evdns_add_server_port(conn->s, 0, evdns_server_callback, NULL);
} }
/** Free the evdns server port for <b>conn</b>, which must be an
* AP_DNS_LISTENER. */
void void
dnsserv_close_listener(connection_t *conn) dnsserv_close_listener(connection_t *conn)
{ {
evdns_close_server_port(conn->dns_server_port); tor_assert(conn);
conn->dns_server_port = NULL; tor_assert(conn->type == CONN_TYPE_AP_DNS_LISTENER);
if (conn->dns_server_port) {
evdns_close_server_port(conn->dns_server_port);
conn->dns_server_port = NULL;
}
} }

View File

@ -28,6 +28,7 @@ static void conn_write_callback(int fd, short event, void *_conn);
static void signal_callback(int fd, short events, void *arg); static void signal_callback(int fd, short events, void *arg);
static void second_elapsed_callback(int fd, short event, void *args); static void second_elapsed_callback(int fd, short event, void *args);
static int conn_close_if_marked(int i); static int conn_close_if_marked(int i);
static void connection_start_reading_from_linked_conn(connection_t *conn);
/********* START VARIABLES **********/ /********* START VARIABLES **********/
@ -72,9 +73,12 @@ static smartlist_t *connection_array = NULL;
/** List of connections that have been marked for close and need to be freed /** List of connections that have been marked for close and need to be freed
* and removed from connection_array. */ * and removed from connection_array. */
static smartlist_t *closeable_connection_lst = NULL; static smartlist_t *closeable_connection_lst = NULL;
/** DOCDOC */ /** List of linked connections that are currently reading data into their
* inbuf from their partner's outbuf. */
static smartlist_t *active_linked_connection_lst = NULL; static smartlist_t *active_linked_connection_lst = NULL;
/** DOCDOC */ /** Flag: Set to true iff we entered the current libevent main loop via
* <b>loop_once</b>. If so, there's no need to trigger a loopexit in order
* to handle linked connections. */
static int called_loop_once = 0; static int called_loop_once = 0;
/** We set this to 1 when we've opened a circuit, so we can print a log /** We set this to 1 when we've opened a circuit, so we can print a log
@ -395,8 +399,10 @@ connection_start_writing(connection_t *conn)
} }
} }
/** DOCDOC*/ /** Helper: Tell the main loop to begin reading bytes into <b>conn</b> from
void * its linked connection, if it is not doing so already. Called by
* connection_start_reading and connection_start_writing as appropriate. */
static void
connection_start_reading_from_linked_conn(connection_t *conn) connection_start_reading_from_linked_conn(connection_t *conn)
{ {
tor_assert(conn); tor_assert(conn);
@ -418,7 +424,9 @@ connection_start_reading_from_linked_conn(connection_t *conn)
} }
} }
/** DOCDOC*/ /** Tell the main loop to stop reading bytes into <b>conn</b> from its linked
* connection, if is currently doing so. Called by connection_stop_reading,
* connection_stop_writing, and connection_read. */
void void
connection_stop_reading_from_linked_conn(connection_t *conn) connection_stop_reading_from_linked_conn(connection_t *conn)
{ {
@ -1298,7 +1306,7 @@ do_main_loop(void)
} }
} }
/* DOCDOC */ /* Set up the packed_cell_t memory pool. */
init_cell_pool(); init_cell_pool();
/* Set up our buckets */ /* Set up our buckets */

View File

@ -910,7 +910,8 @@ typedef struct edge_connection_t {
* already retried several times. */ * already retried several times. */
uint8_t num_socks_retries; uint8_t num_socks_retries;
/** DOCDOC */ /** 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; struct evdns_server_request *dns_server_request;
} edge_connection_t; } edge_connection_t;
@ -1057,7 +1058,8 @@ typedef enum {
SAVED_IN_JOURNAL SAVED_IN_JOURNAL
} saved_location_t; } saved_location_t;
/** DOCDOC */ /** Information about our plans for retrying downloads for a downloadable
* object. */
typedef struct download_status_t { typedef struct download_status_t {
time_t next_attempt_at; /**< When should we try downloading this descriptor time_t next_attempt_at; /**< When should we try downloading this descriptor
* again? */ * again? */
@ -1078,18 +1080,19 @@ typedef struct signed_descriptor_t {
char identity_digest[DIGEST_LEN]; char identity_digest[DIGEST_LEN];
/** Declared publication time of the descriptor */ /** Declared publication time of the descriptor */
time_t published_on; time_t published_on;
/** DOCDOC; routerinfo_t only. */ /** For routerdescs only: digest of the corresponding extrainfo. */
char extra_info_digest[DIGEST_LEN]; char extra_info_digest[DIGEST_LEN];
/** DOCDOC; routerinfo_t only: for the corresponding extrainfo. */ /** For routerdescs only: Status of downloading the corresponding
* extrainfo. */
download_status_t ei_dl_status; download_status_t ei_dl_status;
/** Where is the descriptor saved? */ /** Where is the descriptor saved? */
saved_location_t saved_location ; saved_location_t saved_location ;
/** If saved_location is SAVED_IN_CACHE or SAVED_IN_JOURNAL, the offset of /** If saved_location is SAVED_IN_CACHE or SAVED_IN_JOURNAL, the offset of
* this descriptor in the corresponding file. */ * this descriptor in the corresponding file. */
off_t saved_offset; off_t saved_offset;
/* DOCDOC */ /* If true, we do not ever try to save this object in the cache. */
unsigned int do_not_cache : 1; unsigned int do_not_cache : 1;
/* DOCDOC */ /* If true, this item is meant to represent an extrainfo. */
unsigned int is_extrainfo : 1; unsigned int is_extrainfo : 1;
} signed_descriptor_t; } signed_descriptor_t;
@ -1124,7 +1127,8 @@ typedef struct {
* hibernating */ * hibernating */
unsigned int has_old_dnsworkers:1; /**< Whether the router is using unsigned int has_old_dnsworkers:1; /**< Whether the router is using
* dnsworker code. */ * dnsworker code. */
unsigned int caches_extra_info:1; /**< DOCDOC */ unsigned int caches_extra_info:1; /**< Whether the router caches and serves
* extrainfo documents. */
/* local info */ /* local info */
unsigned int is_running:1; /**< As far as we know, is this OR currently unsigned int is_running:1; /**< As far as we know, is this OR currently
@ -1179,7 +1183,7 @@ typedef struct extrainfo_t {
/** If present, we didn't have the right key to verify this extra-info, /** If present, we didn't have the right key to verify this extra-info,
* so this is a copy of the signature in the document. */ * so this is a copy of the signature in the document. */
char *pending_sig; char *pending_sig;
/** DOCDOC */ /** Length of pending_sig. */
size_t pending_sig_len; size_t pending_sig_len;
} extrainfo_t; } extrainfo_t;
@ -1296,10 +1300,12 @@ typedef struct {
/** Map from server descriptor digest to a signed_descriptor_t from /** Map from server descriptor digest to a signed_descriptor_t from
* routers or old_routers. */ * routers or old_routers. */
digestmap_t *desc_digest_map; digestmap_t *desc_digest_map;
/** Map from extra-info digest to a signed_descriptor_t. Only for /** Map from extra-info digest to an extrainfo_t. Only exists for
* routers in routers or old_routers. */ * routers in routers or old_routers. */
digestmap_t *extra_info_map; digestmap_t *extra_info_map;
/** DOCDOC */ /** Map from extra-info digests to a signed_descriptor_t for a router
* descriptor having that extra-info digest. Only exists for
* routers in routers or old_routers. */
digestmap_t *desc_by_eid_map; digestmap_t *desc_by_eid_map;
/** List of routerinfo_t for all currently live routers we know. */ /** List of routerinfo_t for all currently live routers we know. */
smartlist_t *routers; smartlist_t *routers;
@ -1328,7 +1334,8 @@ typedef struct extend_info_t {
crypto_pk_env_t *onion_key; /**< Current onionskin key. */ crypto_pk_env_t *onion_key; /**< Current onionskin key. */
} extend_info_t; } extend_info_t;
/** DOCDOC */ /** Certificate for v3 directory protocol: binds long-term authority identity
* keys to medium-term authority signing keys. */
typedef struct authority_cert_t { typedef struct authority_cert_t {
signed_descriptor_t cache_info; signed_descriptor_t cache_info;
crypto_pk_env_t *identity_key; crypto_pk_env_t *identity_key;
@ -1336,7 +1343,8 @@ typedef struct authority_cert_t {
time_t expires; time_t expires;
} authority_cert_t; } authority_cert_t;
/** DOCDOC */ /** Bitfield enum type listing types of directory authority/directory
* server. */
typedef enum { typedef enum {
NO_AUTHORITY = 0, NO_AUTHORITY = 0,
V1_AUTHORITY = 1 << 0, V1_AUTHORITY = 1 << 0,
@ -1822,8 +1830,12 @@ typedef struct {
int TrackHostExitsExpire; /**< Number of seconds until we expire an int TrackHostExitsExpire; /**< Number of seconds until we expire an
* addressmap */ * addressmap */
config_line_t *AddressMap; /**< List of address map directives. */ config_line_t *AddressMap; /**< List of address map directives. */
int AutomapHostsOnResolve; /**< DOCDOC */ int AutomapHostsOnResolve; /**< If true, when we get a resolve request for a
smartlist_t *AutomapHostsSuffixes; /**< DOCDOC */ * hostname ending with one of the suffixes in
* <b>AutomapHostsSuffixes</b>, map it to a
* virtual address. */
smartlist_t *AutomapHostsSuffixes; /**< List of suffixes for
* <b>AutomapHostsOnResolve</b>. */
int RendPostPeriod; /**< How often do we post each rendezvous service int RendPostPeriod; /**< How often do we post each rendezvous service
* descriptor? Remember to publish them independently. */ * descriptor? Remember to publish them independently. */
int KeepalivePeriod; /**< How often do we send padding cells to keep int KeepalivePeriod; /**< How often do we send padding cells to keep
@ -2029,7 +2041,9 @@ static INLINE void or_state_mark_dirty(or_state_t *state, time_t when)
#define SOCKS_COMMAND_IS_RESOLVE(c) ((c)==SOCKS_COMMAND_RESOLVE || \ #define SOCKS_COMMAND_IS_RESOLVE(c) ((c)==SOCKS_COMMAND_RESOLVE || \
(c)==SOCKS_COMMAND_RESOLVE_PTR) (c)==SOCKS_COMMAND_RESOLVE_PTR)
/** State of a SOCKS request from a user to an OP */ /** State of a SOCKS request from a user to an OP. Also used to encode other
* information for non-socks user request (such as those on TransPort and
* DNSPort) */
struct socks_request_t { struct socks_request_t {
/** Which version of SOCKS did the client use? One of "0, 4, 5" -- where /** Which version of SOCKS did the client use? One of "0, 4, 5" -- where
* 0 means that no socks handshake ever took place, and this is just a * 0 means that no socks handshake ever took place, and this is just a
@ -2043,10 +2057,12 @@ struct socks_request_t {
* socks5 socks reply. We use this for the * socks5 socks reply. We use this for the
* two-stage socks5 handshake. * two-stage socks5 handshake.
*/ */
int has_finished; /**< Has the SOCKS handshake finished? */
char address[MAX_SOCKS_ADDR_LEN]; /**< What address did the client ask to char address[MAX_SOCKS_ADDR_LEN]; /**< What address did the client ask to
connect to? */ connect to/resolve? */
uint16_t port; /**< What port did the client ask to connect to? */ uint16_t port; /**< What port did the client ask to connect to? */
unsigned has_finished : 1; /**< Has the SOCKS handshake finished? Used to
* make sure we send back a socks reply for
* every connection. */
}; };
/* all the function prototypes go here */ /* all the function prototypes go here */
@ -2718,7 +2734,6 @@ void connection_stop_writing(connection_t *conn);
void connection_start_writing(connection_t *conn); void connection_start_writing(connection_t *conn);
void connection_stop_reading_from_linked_conn(connection_t *conn); void connection_stop_reading_from_linked_conn(connection_t *conn);
void connection_start_reading_from_linked_conn(connection_t *conn);
void directory_all_unreachable(time_t now); void directory_all_unreachable(time_t now);
void directory_info_has_arrived(time_t now, int from_cache); void directory_info_has_arrived(time_t now, int from_cache);
@ -3024,7 +3039,8 @@ authority_cert_t *get_my_v3_authority_cert(void);
crypto_pk_env_t *get_my_v3_authority_signing_key(void); crypto_pk_env_t *get_my_v3_authority_signing_key(void);
void dup_onion_keys(crypto_pk_env_t **key, crypto_pk_env_t **last); void dup_onion_keys(crypto_pk_env_t **key, crypto_pk_env_t **last);
void rotate_onion_key(void); void rotate_onion_key(void);
crypto_pk_env_t *init_key_from_file(const char *fname); crypto_pk_env_t *init_key_from_file(const char *fname, int generate,
int severity);
int init_keys(void); int init_keys(void);
int check_whether_orport_reachable(void); int check_whether_orport_reachable(void);
@ -3098,7 +3114,7 @@ typedef struct trusted_dir_server_t {
* we tried to upload to it. */ * we tried to upload to it. */
unsigned int has_accepted_serverdesc:1; unsigned int has_accepted_serverdesc:1;
/** DOCDOC */ /** What kind of authority is this? (Bitfield.) */
authority_type_t type; authority_type_t type;
authority_cert_t *v3_cert; /**< V3 key certificate for this authority */ authority_cert_t *v3_cert; /**< V3 key certificate for this authority */

View File

@ -1480,7 +1480,7 @@ circuit_consider_sending_sendme(circuit_t *circ, crypt_path_t *layer_hint)
#define assert_active_circuits_ok_paranoid(conn) #define assert_active_circuits_ok_paranoid(conn)
#endif #endif
/** DOCDOC */ /** The total number of cells we have allocated from the memory pool. */
static int total_cells_allocated = 0; static int total_cells_allocated = 0;
#ifdef ENABLE_CELL_POOL /* Defined in ./configure. True by default. */ #ifdef ENABLE_CELL_POOL /* Defined in ./configure. True by default. */

View File

@ -350,7 +350,7 @@ rend_service_load_keys(void)
s->directory); s->directory);
return -1; return -1;
} }
s->private_key = init_key_from_file(fname); s->private_key = init_key_from_file(fname, 1, LOG_ERR);
if (!s->private_key) if (!s->private_key)
return -1; return -1;

View File

@ -44,6 +44,11 @@ static crypto_pk_env_t *authority_signing_key = NULL;
* authorities. */ * authorities. */
static authority_cert_t *authority_key_certificate = NULL; static authority_cert_t *authority_key_certificate = NULL;
/* (Note that v3 authorities also have a separate "authority identity key",
* but this key is never actually loaded by the Tor process. Instead, it's
* used by tor-gencert to sign new signing keys and make new key
* certificates. */
/** Replace the current onion key with <b>k</b>. Does not affect lastonionkey; /** Replace the current onion key with <b>k</b>. Does not affect lastonionkey;
* to update onionkey correctly, call rotate_onion_key(). * to update onionkey correctly, call rotate_onion_key().
*/ */
@ -122,14 +127,16 @@ identity_key_is_set(void)
return identitykey != NULL; return identitykey != NULL;
} }
/** DOCDOC */ /** Return the key certificate for this v3 (voting) authority, or NULL
* if we have no such certificate. */
authority_cert_t * authority_cert_t *
get_my_v3_authority_cert(void) get_my_v3_authority_cert(void)
{ {
return authority_key_certificate; return authority_key_certificate;
} }
/** DOCDOC */ /** Return the v3 signing key for this v3 (voting) authority, or NULL
* if we have no such key. */
crypto_pk_env_t * crypto_pk_env_t *
get_my_v3_authority_signing_key(void) get_my_v3_authority_signing_key(void)
{ {
@ -189,9 +196,13 @@ rotate_onion_key(void)
log_warn(LD_GENERAL, "Couldn't rotate onion key."); log_warn(LD_GENERAL, "Couldn't rotate onion key.");
} }
/** DOCDOC */ /** Try to read an RSA key from <b>fname</b>. If <b>fname</b> doesn't exist
static crypto_pk_env_t * * and <b>generate</b> is true, create a new RSA key and save it in
init_key_from_file_impl(const char *fname, int generate, int severity) * <b>fname</b>. Return the read/created key, or NULL on error. Log all
* errors at level <b>severity</b>.
*/
crypto_pk_env_t *
init_key_from_file(const char *fname, int generate, int severity)
{ {
crypto_pk_env_t *prkey = NULL; crypto_pk_env_t *prkey = NULL;
FILE *file = NULL; FILE *file = NULL;
@ -246,17 +257,9 @@ init_key_from_file_impl(const char *fname, int generate, int severity)
return NULL; return NULL;
} }
/** Try to read an RSA key from <b>fname</b>. If <b>fname</b> doesn't exist, /** Load the v3 (voting) authority signing key and certificate from
* create a new RSA key and save it in <b>fname</b>. Return the read/created * <b>keydir</b>, if they are present. */
* key, or NULL on error. /* XXXX020 maybe move to dirserv.c */
*/
crypto_pk_env_t *
init_key_from_file(const char *fname)
{
return init_key_from_file_impl(fname, 1, LOG_ERR);
}
/** DOCDOC; XXXX020 maybe move to dirserv.c */
static void static void
init_v3_authority_keys(const char *keydir) init_v3_authority_keys(const char *keydir)
{ {
@ -269,7 +272,7 @@ init_v3_authority_keys(const char *keydir)
fname = tor_malloc(fname_len); fname = tor_malloc(fname_len);
tor_snprintf(fname, fname_len, "%s"PATH_SEPARATOR"authority_signing_key", tor_snprintf(fname, fname_len, "%s"PATH_SEPARATOR"authority_signing_key",
keydir); keydir);
signing_key = init_key_from_file_impl(fname, 0, LOG_INFO); signing_key = init_key_from_file(fname, 0, LOG_INFO);
if (!signing_key) { if (!signing_key) {
log_warn(LD_DIR, "No version 3 directory key found in %s", fname); log_warn(LD_DIR, "No version 3 directory key found in %s", fname);
goto done; goto done;
@ -364,7 +367,7 @@ init_keys(void)
tor_snprintf(keydir,sizeof(keydir), tor_snprintf(keydir,sizeof(keydir),
"%s"PATH_SEPARATOR"keys"PATH_SEPARATOR"secret_id_key",datadir); "%s"PATH_SEPARATOR"keys"PATH_SEPARATOR"secret_id_key",datadir);
log_info(LD_GENERAL,"Reading/making identity key \"%s\"...",keydir); log_info(LD_GENERAL,"Reading/making identity key \"%s\"...",keydir);
prkey = init_key_from_file(keydir); prkey = init_key_from_file(keydir, 1, LOG_ERR);
if (!prkey) return -1; if (!prkey) return -1;
set_identity_key(prkey); set_identity_key(prkey);
@ -376,7 +379,7 @@ init_keys(void)
tor_snprintf(keydir,sizeof(keydir), tor_snprintf(keydir,sizeof(keydir),
"%s"PATH_SEPARATOR"keys"PATH_SEPARATOR"secret_onion_key",datadir); "%s"PATH_SEPARATOR"keys"PATH_SEPARATOR"secret_onion_key",datadir);
log_info(LD_GENERAL,"Reading/making onion key \"%s\"...",keydir); log_info(LD_GENERAL,"Reading/making onion key \"%s\"...",keydir);
prkey = init_key_from_file(keydir); prkey = init_key_from_file(keydir, 1, LOG_ERR);
if (!prkey) return -1; if (!prkey) return -1;
set_onion_key(prkey); set_onion_key(prkey);
if (state->LastRotatedOnionKey > 100) { /* allow for some parsing slop. */ if (state->LastRotatedOnionKey > 100) { /* allow for some parsing slop. */
@ -393,7 +396,7 @@ init_keys(void)
tor_snprintf(keydir,sizeof(keydir), tor_snprintf(keydir,sizeof(keydir),
"%s"PATH_SEPARATOR"keys"PATH_SEPARATOR"secret_onion_key.old",datadir); "%s"PATH_SEPARATOR"keys"PATH_SEPARATOR"secret_onion_key.old",datadir);
if (file_status(keydir) == FN_FILE) { if (file_status(keydir) == FN_FILE) {
prkey = init_key_from_file(keydir); prkey = init_key_from_file(keydir, 1, LOG_ERR);
if (prkey) if (prkey)
lastonionkey = prkey; lastonionkey = prkey;
} }
@ -844,7 +847,7 @@ router_is_clique_mode(routerinfo_t *router)
/** My routerinfo. */ /** My routerinfo. */
static routerinfo_t *desc_routerinfo = NULL; static routerinfo_t *desc_routerinfo = NULL;
/** DOCDOC */ /** My extrainfo */
static extrainfo_t *desc_extrainfo = NULL; static extrainfo_t *desc_extrainfo = NULL;
/** Since when has our descriptor been "clean"? 0 if we need to regenerate it /** Since when has our descriptor been "clean"? 0 if we need to regenerate it
* now. */ * now. */
@ -966,7 +969,8 @@ router_get_my_descriptor(void)
return body; return body;
} }
/** DOCDOC */ /* Return the extrainfo document for this OR, or NULL if we have none.
* Rebuilt it (and the server descriptor) if necessary. */
extrainfo_t * extrainfo_t *
router_get_my_extrainfo(void) router_get_my_extrainfo(void)
{ {
@ -1001,10 +1005,9 @@ router_pick_published_address(or_options_t *options, uint32_t *addr)
return 0; return 0;
} }
/** If <b>force</b> is true, or our descriptor is out-of-date, rebuild /** If <b>force</b> is true, or our descriptor is out-of-date, rebuild a fresh
* a fresh routerinfo and signed server descriptor for this OR. * routerinfo, signed server descriptor, and extra-info document for this OR.
* Return 0 on success, -1 on temporary error. * Return 0 on success, -1 on temporary error.
* DOCDOC extrainfo.
*/ */
int int
router_rebuild_descriptor(int force) router_rebuild_descriptor(int force)
@ -1541,7 +1544,9 @@ router_dump_router_to_string(char *s, size_t maxlen, routerinfo_t *router,
return written+1; return written+1;
} }
/** DOCDOC */ /** Write the contents of <b>extrainfo</b> to the <b>maxlen</b>-byte string
* <b>s</b>, signing them with <b>ident_key</b>. Return 0 on success,
* negative on failure. */
int int
extrainfo_dump_to_string(char *s, size_t maxlen, extrainfo_t *extrainfo, extrainfo_dump_to_string(char *s, size_t maxlen, extrainfo_t *extrainfo,
crypto_pk_env_t *ident_key) crypto_pk_env_t *ident_key)

View File

@ -49,7 +49,9 @@ static void router_dir_info_changed(void);
/** Global list of a trusted_dir_server_t object for each trusted directory /** Global list of a trusted_dir_server_t object for each trusted directory
* server. */ * server. */
static smartlist_t *trusted_dir_servers = NULL; static smartlist_t *trusted_dir_servers = NULL;
/** DOCDOC */ /** True iff the key certificate in at least one member of
* <b>trusted_dir_server_t</b> has changed since we last flushed the
* certificates to disk. */
static int trusted_dir_servers_certs_changed = 0; static int trusted_dir_servers_certs_changed = 0;
/** Global list of all of the routers that we know about. */ /** Global list of all of the routers that we know about. */
@ -62,7 +64,8 @@ static smartlist_t *networkstatus_list = NULL;
/** Global list of local_routerstatus_t for each router, known or unknown. /** Global list of local_routerstatus_t for each router, known or unknown.
* Kept sorted by digest. */ * Kept sorted by digest. */
static smartlist_t *routerstatus_list = NULL; static smartlist_t *routerstatus_list = NULL;
/** DOCDOC */ /** Map from descriptor digest to a member of routerstatus_list: used to
* update download status when a download fails. */
static digestmap_t *routerstatus_by_desc_digest_map = NULL; static digestmap_t *routerstatus_by_desc_digest_map = NULL;
/** Map from lowercase nickname to digest of named server, if any. */ /** Map from lowercase nickname to digest of named server, if any. */
@ -165,7 +168,8 @@ router_reload_networkstatus(void)
return 0; return 0;
} }
/** DOCDOC */ /** Reload the cached v3 key certificates from the cached-certs file in
* the data directory. Return 0 on success, -1 on failure. */
int int
trusted_dirs_reload_certs(void) trusted_dirs_reload_certs(void)
{ {
@ -183,7 +187,11 @@ trusted_dirs_reload_certs(void)
return r; return r;
} }
/** DOCDOC */ /** Load a bunch of new key certificates from the string <b>contents</b>. If
* <b>from_store</b> is true, the certificates are from the cache, and we
* don't need to flush them to disk. If <b>from_store</b> is false, we need
* to flush any changed certificates to disk. Return 0 on success, -1 on
* failure. */
int int
trusted_dirs_load_certs_from_string(const char *contents, int from_store) trusted_dirs_load_certs_from_string(const char *contents, int from_store)
{ {
@ -206,7 +214,10 @@ trusted_dirs_load_certs_from_string(const char *contents, int from_store)
if (ds->v3_cert) { if (ds->v3_cert) {
if (ds->v3_cert->expires < cert->expires) { if (ds->v3_cert->expires < cert->expires) {
authority_cert_free(ds->v3_cert); authority_cert_free(ds->v3_cert);
ds->v3_cert = NULL; /* redundant, but let's be safe. */
} else { } else {
/* This also covers the case where the certificate is the same
* as the one we have. */
authority_cert_free(cert); authority_cert_free(cert);
continue; continue;
} }
@ -221,7 +232,7 @@ trusted_dirs_load_certs_from_string(const char *contents, int from_store)
return 0; return 0;
} }
/** DOCDOC */ /** Save all v3 key certifiacates to the cached-certs file. */
void void
trusted_dirs_flush_certs_to_disk(void) trusted_dirs_flush_certs_to_disk(void)
{ {
@ -260,19 +271,21 @@ trusted_dirs_flush_certs_to_disk(void)
* On startup, we read both files. * On startup, we read both files.
*/ */
/** DOCDOC */ /** Information about disk space usage in a cached-routers or cached-extrainfo
* file and its associcated journal. */
typedef struct store_stats_t { typedef struct store_stats_t {
/** The size of the router log, in bytes. */ /** The size of the router log, in bytes. */
size_t journal_len; size_t journal_len;
/** The size of the router store, in bytes. */ /** The size of the router store, in bytes. */
size_t store_len; size_t store_len;
/** Total bytes dropped since last rebuild. */ /** Total bytes dropped since last rebuild: this is space currently
* used in the cache and the journal that could be freed by a rebuild. */
size_t bytes_dropped; size_t bytes_dropped;
} store_stats_t; } store_stats_t;
/** DOCDOC */ /** Disk usage for cached-routers and cached-routers.new */
static store_stats_t router_store_stats = { 0, 0, 0 }; static store_stats_t router_store_stats = { 0, 0, 0 };
/** DOCDOC */ /** Disk usage for cached-extrainfo and cached-extrainfo.new */
static store_stats_t extrainfo_store_stats = { 0, 0, 0 }; static store_stats_t extrainfo_store_stats = { 0, 0, 0 };
/** Helper: return 1 iff the router log is so big we want to rebuild the /** Helper: return 1 iff the router log is so big we want to rebuild the
@ -351,7 +364,8 @@ _compare_signed_descriptors_by_age(const void **_a, const void **_b)
* replace the router store with the routers currently in our routerlist, and * replace the router store with the routers currently in our routerlist, and
* clear the journal. Return 0 on success, -1 on failure. * clear the journal. Return 0 on success, -1 on failure.
* *
* DOCDOC extrainfo * If <b>extrainfo</b> is true, rebuild the extrainfo store; else rebuild the
* router descriptor store.
*/ */
static int static int
router_rebuild_store(int force, int extrainfo) router_rebuild_store(int force, int extrainfo)
@ -492,7 +506,9 @@ router_rebuild_store(int force, int extrainfo)
return r; return r;
} }
/** DOCDOC */ /** Helper: Reload a cache file and its associated journal, setting metadata
* appropriately. If <b>extrainfo</b> is true, reload the extrainfo store;
* else reload the router descriptor store. */
static int static int
router_reload_router_list_impl(int extrainfo) router_reload_router_list_impl(int extrainfo)
{ {
@ -1632,8 +1648,9 @@ router_get_by_descriptor_digest(const char *digest)
return digestmap_get(routerlist->desc_digest_map, digest); return digestmap_get(routerlist->desc_digest_map, digest);
} }
/** Return the router in our routerlist whose 20-byte descriptor /** Return the signed descriptor for the router in our routerlist whose
* is <b>digest</b>. Return NULL if no such router is known. */ * 20-byte extra-info digest is <b>digest</b>. Return NULL if no such router
* is known. */
signed_descriptor_t * signed_descriptor_t *
router_get_by_extrainfo_digest(const char *digest) router_get_by_extrainfo_digest(const char *digest)
{ {
@ -1644,7 +1661,9 @@ router_get_by_extrainfo_digest(const char *digest)
return digestmap_get(routerlist->desc_by_eid_map, digest); return digestmap_get(routerlist->desc_by_eid_map, digest);
} }
/** DOCDOC */ /** Return the signed descriptor for the extrainfo_t in our routerlist whose
* extra-info-digest is <b>digest</b>. Return NULL if no such extra-info
* document is known. */
signed_descriptor_t * signed_descriptor_t *
extrainfo_get_by_descriptor_digest(const char *digest) extrainfo_get_by_descriptor_digest(const char *digest)
{ {
@ -1736,7 +1755,7 @@ routerinfo_free(routerinfo_t *router)
tor_free(router); tor_free(router);
} }
/** DOCDOC */ /** Release all storage held by <b>extrainfo</b> */
void void
extrainfo_free(extrainfo_t *extrainfo) extrainfo_free(extrainfo_t *extrainfo)
{ {
@ -1745,8 +1764,8 @@ extrainfo_free(extrainfo_t *extrainfo)
tor_free(extrainfo->cache_info.signed_descriptor_body); tor_free(extrainfo->cache_info.signed_descriptor_body);
tor_free(extrainfo->pending_sig); tor_free(extrainfo->pending_sig);
/* Remove once 414/417 is fixed. But I have a hunch... */ /* XXXX020 remove this once more bugs go away. */
memset(extrainfo, 88, sizeof(extrainfo_t)); memset(extrainfo, 88, sizeof(extrainfo_t)); /* debug bad memory usage */
tor_free(extrainfo); tor_free(extrainfo);
} }
@ -1756,8 +1775,8 @@ signed_descriptor_free(signed_descriptor_t *sd)
{ {
tor_free(sd->signed_descriptor_body); tor_free(sd->signed_descriptor_body);
/* Remove once 414/417 is fixed. But I have a hunch... */ /* XXXX020 remove this once more bugs go away. */
memset(sd, 99, sizeof(signed_descriptor_t)); memset(sd, 99, sizeof(signed_descriptor_t)); /* Debug bad mem usage */
tor_free(sd); tor_free(sd);
} }
@ -1773,7 +1792,7 @@ signed_descriptor_from_routerinfo(routerinfo_t *ri)
return sd; return sd;
} }
/** DOCDOC */ /** Helper: free the storage held by the extrainfo_t in <b>e</b>. */
static void static void
_extrainfo_free(void *e) _extrainfo_free(void *e)
{ {
@ -1891,8 +1910,9 @@ routerlist_insert(routerlist_t *rl, routerinfo_t *ri)
routerlist_check_bug_417(); routerlist_check_bug_417();
} }
/** DOCDOC /** Adds the extrainfo_t <b>ei</b> to the routerlist <b>rl</b>, if there is a
* Returns true if actually inserted. */ * corresponding router in rl-\>routers or rl-\>old_routers. Return true iff
* we actually inserted <b>ei</b>. Free <b>ei</b> if it isn't inserted. */
static int static int
extrainfo_insert(routerlist_t *rl, extrainfo_t *ei) extrainfo_insert(routerlist_t *rl, extrainfo_t *ei)
{ {
@ -2037,7 +2057,9 @@ routerlist_remove(routerlist_t *rl, routerinfo_t *ri, int idx, int make_old)
routerlist_check_bug_417(); routerlist_check_bug_417();
} }
/** DOCDOC */ /** Remove a signed_descriptor_t <b>sd</b> from <b>rl</b>-\>old_routers, and
* adjust <b>rl</b> as appropriate. <b>idx</i> is -1, or the index of
* <b>sd</b>. */
static void static void
routerlist_remove_old(routerlist_t *rl, signed_descriptor_t *sd, int idx) routerlist_remove_old(routerlist_t *rl, signed_descriptor_t *sd, int idx)
{ {
@ -2455,7 +2477,8 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg,
return 0; return 0;
} }
/** DOCDOC */ /** Insert <b>ei</b> into the routerlist, or free it. Other arguments are
* as for router_add_to_routerlist(). */
void void
router_add_extrainfo_to_routerlist(extrainfo_t *ei, const char **msg, router_add_extrainfo_to_routerlist(extrainfo_t *ei, const char **msg,
int from_cache, int from_fetch) int from_cache, int from_fetch)
@ -2809,7 +2832,9 @@ router_load_routers_from_string(const char *s, const char *eos,
smartlist_free(changed); smartlist_free(changed);
} }
/** DOCDOC */ /** Parse one or more extrainfos from <b>s</b> (ending immediately before
* <b>eos</b> if <b>eos</b> is present). Other arguments are as for
* router_load_routers_from_string(). */
void void
router_load_extrainfo_from_string(const char *s, const char *eos, router_load_extrainfo_from_string(const char *s, const char *eos,
saved_location_t saved_location, saved_location_t saved_location,
@ -3142,8 +3167,8 @@ networkstatus_find_entry(networkstatus_t *ns, const char *digest)
_compare_digest_to_routerstatus_entry); _compare_digest_to_routerstatus_entry);
} }
/** Return the consensus view of the status of the router whose digest is /** Return the consensus view of the status of the router whose identity
* <b>digest</b>, or NULL if we don't know about any such router. */ * digest is <b>digest</b>, or NULL if we don't know about any such router. */
local_routerstatus_t * local_routerstatus_t *
router_get_combined_status_by_digest(const char *digest) router_get_combined_status_by_digest(const char *digest)
{ {
@ -3153,7 +3178,9 @@ router_get_combined_status_by_digest(const char *digest)
_compare_digest_to_routerstatus_entry); _compare_digest_to_routerstatus_entry);
} }
/** DOCDOC */ /** Return the consensus view of the status of the router whose current
* <i>descriptor</i> digest is <b>digest</b>, or NULL if no such router is
* known. */
local_routerstatus_t * local_routerstatus_t *
router_get_combined_status_by_descriptor_digest(const char *digest) router_get_combined_status_by_descriptor_digest(const char *digest)
{ {
@ -4258,8 +4285,9 @@ routers_update_status_from_networkstatus(smartlist_t *routers,
router_dir_info_changed(); router_dir_info_changed();
} }
/** For every router descriptor we are currently downloading by descriptor /** For every router descriptor (or extra-info document if <b>extrainfo</b> is
* digest, set result[d] to 1. DOCDOC extrainfo */ * true) we are currently downloading by descriptor digest, set result[d] to
* (void*)1. */
static void static void
list_pending_descriptor_downloads(digestmap_t *result, int extrainfo) list_pending_descriptor_downloads(digestmap_t *result, int extrainfo)
{ {
@ -4681,7 +4709,9 @@ update_router_descriptor_downloads(time_t now)
} }
} }
/** DOCDOC */ /** Return true iff <b>sd</b> is the descriptor for a router descriptor that
* has an extrainfo that we don't currently have, are not currently
* downloading, and have not recently tried to download. */
static INLINE int static INLINE int
should_download_extrainfo(signed_descriptor_t *sd, should_download_extrainfo(signed_descriptor_t *sd,
const routerlist_t *rl, const routerlist_t *rl,
@ -4689,13 +4719,14 @@ should_download_extrainfo(signed_descriptor_t *sd,
time_t now) time_t now)
{ {
const char *d = sd->extra_info_digest; const char *d = sd->extra_info_digest;
return (!tor_digest_is_zero(d) && return (!sd->is_extrainfo &&
!tor_digest_is_zero(d) &&
sd->ei_dl_status.next_attempt_at <= now && sd->ei_dl_status.next_attempt_at <= now &&
!digestmap_get(rl->extra_info_map, d) && !digestmap_get(rl->extra_info_map, d) &&
!digestmap_get(pending, d)); !digestmap_get(pending, d));
} }
/** DOCDOC */ /** Laucnch extrainfo downloads as needed. */
void void
update_extrainfo_downloads(time_t now) update_extrainfo_downloads(time_t now)
{ {
@ -4967,8 +4998,12 @@ router_differences_are_cosmetic(routerinfo_t *r1, routerinfo_t *r2)
return 1; return 1;
} }
/** DOCDOC Returns 1 for "reject with message"; -1 for "reject silently", /** Check whether <b>ri</b> is a router compatible with the extrainfo document
* 0 for "accept". */ * <b>ei</b>. If no router is compatible with <b>ei</b>, <b>ei</b> should be
* dropped. Return 0 for "compatible", return 1 for "reject, and inform
* whoever uploaded <b>ei</b>, and return -1 for "reject silently.". If
* <b>msg</b> is present, set *<b>msg</b> to a description of the
* incompatibility (if any). */
int int
routerinfo_incompatible_with_extrainfo(routerinfo_t *ri, extrainfo_t *ei, routerinfo_incompatible_with_extrainfo(routerinfo_t *ri, extrainfo_t *ei,
const char **msg) const char **msg)