From 1a75e6da007ddd3207726dc2b1293e22453c81af Mon Sep 17 00:00:00 2001 From: Donncha O'Cearbhaill Date: Wed, 29 Jul 2015 14:40:29 +0200 Subject: Create a service-side descriptor cache Adds a service descriptor cache which is indexed by service ID. This descriptor cache is used to store service descriptors generated by a local rendevous service. The service-side cach can be queried by calling rend_cache_lookup_entry() with the 'service' argument set to 1. --- src/or/rendcache.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src/or/rendcache.h') diff --git a/src/or/rendcache.h b/src/or/rendcache.h index 0512058054..02eab4ba70 100644 --- a/src/or/rendcache.h +++ b/src/or/rendcache.h @@ -55,7 +55,8 @@ void rend_cache_clean_v2_descs_as_dir(time_t now, size_t min_to_remove); void rend_cache_purge(void); void rend_cache_free_all(void); int rend_cache_lookup_entry(const char *query, int version, - rend_cache_entry_t **entry_out); + rend_cache_entry_t **entry_out, + int service); int rend_cache_lookup_v2_desc_as_dir(const char *query, const char **desc); /** Return value from rend_cache_store_v2_desc_as_{dir,client}. */ typedef enum { @@ -65,6 +66,8 @@ typedef enum { } rend_cache_store_status_t; rend_cache_store_status_t rend_cache_store_v2_desc_as_dir(const char *desc); +rend_cache_store_status_t rend_cache_store_v2_desc_as_service( + const char *desc); rend_cache_store_status_t rend_cache_store_v2_desc_as_client(const char *desc, const char *desc_id_base32, const rend_data_t *rend_query, -- cgit v1.2.3-54-g00ecf From 5dc2cbafefa9c15fd5c96707b1e5bde0c59b6132 Mon Sep 17 00:00:00 2001 From: Donncha O'Cearbhaill Date: Mon, 3 Aug 2015 17:33:28 +0200 Subject: Specify descriptor cache type in rend_cache_lookup_entry() Adds an Enum which represents the different types of rendezvous descriptor caches. This argument is passed in each call to rend_cache_lookup_entry() to specify lookup in the client-side or service-side descriptor caches. --- src/or/connection_edge.c | 3 ++- src/or/control.c | 4 ++-- src/or/rendcache.c | 6 +++--- src/or/rendcache.h | 7 ++++++- src/or/rendclient.c | 13 ++++++++----- 5 files changed, 21 insertions(+), 12 deletions(-) (limited to 'src/or/rendcache.h') diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c index defe0ab9e0..5ea82d88b1 100644 --- a/src/or/connection_edge.c +++ b/src/or/connection_edge.c @@ -1527,7 +1527,8 @@ connection_ap_handshake_rewrite_and_attach(entry_connection_t *conn, unsigned int refetch_desc = 0; rend_cache_entry_t *entry = NULL; const int rend_cache_lookup_result = - rend_cache_lookup_entry(rend_data->onion_address, -1, &entry, 0); + rend_cache_lookup_entry(rend_data->onion_address, -1, &entry, + REND_CACHE_TYPE_CLIENT); if (rend_cache_lookup_result < 0) { switch (-rend_cache_lookup_result) { case EINVAL: diff --git a/src/or/control.c b/src/or/control.c index 900162e3e2..c2240bf38c 100644 --- a/src/or/control.c +++ b/src/or/control.c @@ -1920,7 +1920,7 @@ getinfo_helper_dir(control_connection_t *control_conn, return -1; } - if (!rend_cache_lookup_entry(question, -1, &e, 0)) { + if (!rend_cache_lookup_entry(question, -1, &e, REND_CACHE_TYPE_CLIENT)) { /* Descriptor found in cache */ *answer = tor_strdup(e->desc); } else { @@ -1936,7 +1936,7 @@ getinfo_helper_dir(control_connection_t *control_conn, return -1; } - if (!rend_cache_lookup_entry(question, -1, &e, 1)) { + if (!rend_cache_lookup_entry(question, -1, &e, REND_CACHE_TYPE_SERVICE)) { /* Descriptor found in cache */ *answer = tor_strdup(e->desc); } else { diff --git a/src/or/rendcache.c b/src/or/rendcache.c index 1c466414c1..0abfeb50ca 100644 --- a/src/or/rendcache.c +++ b/src/or/rendcache.c @@ -479,7 +479,7 @@ rend_cache_clean_v2_descs_as_dir(time_t now, size_t force_remove) * -ENOENT means that no entry in the cache was found. */ int rend_cache_lookup_entry(const char *query, int version, rend_cache_entry_t **e, - int service) + rend_cache_type_t cache) { int ret = 0; char key[REND_SERVICE_ID_LEN_BASE32 + 2]; /* \0 */ @@ -502,7 +502,7 @@ rend_cache_lookup_entry(const char *query, int version, rend_cache_entry_t **e, case 2: /* Default is version 2. */ default: - if(service){ + if(cache == REND_CACHE_TYPE_SERVICE){ entry = strmap_get_lc(rend_cache_service, query); } else { tor_snprintf(key, sizeof(key), "%d%s", default_version, query); @@ -515,7 +515,7 @@ rend_cache_lookup_entry(const char *query, int version, rend_cache_entry_t **e, goto end; } /* Check descriptor is parsed only if lookup is from client cache */ - if(!service){ + if(cache == REND_CACHE_TYPE_CLIENT){ tor_assert(entry->parsed && entry->parsed->intro_nodes); } diff --git a/src/or/rendcache.h b/src/or/rendcache.h index 02eab4ba70..e13c9b4d1d 100644 --- a/src/or/rendcache.h +++ b/src/or/rendcache.h @@ -48,6 +48,11 @@ typedef struct rend_cache_failure_t { digestmap_t *intro_failures; } rend_cache_failure_t; +typedef enum { + REND_CACHE_TYPE_CLIENT = 1, + REND_CACHE_TYPE_SERVICE = 2, +} rend_cache_type_t; + void rend_cache_init(void); void rend_cache_clean(time_t now); void rend_cache_failure_clean(time_t now); @@ -56,7 +61,7 @@ void rend_cache_purge(void); void rend_cache_free_all(void); int rend_cache_lookup_entry(const char *query, int version, rend_cache_entry_t **entry_out, - int service); + rend_cache_type_t cache); int rend_cache_lookup_v2_desc_as_dir(const char *query, const char **desc); /** Return value from rend_cache_store_v2_desc_as_{dir,client}. */ typedef enum { diff --git a/src/or/rendclient.c b/src/or/rendclient.c index 01ad614352..af1abe59bf 100644 --- a/src/or/rendclient.c +++ b/src/or/rendclient.c @@ -160,7 +160,7 @@ rend_client_send_introduction(origin_circuit_t *introcirc, #endif r = rend_cache_lookup_entry(introcirc->rend_data->onion_address, -1, - &entry, 0); + &entry, REND_CACHE_TYPE_CLIENT); /* An invalid onion address is not possible else we have a big issue. */ tor_assert(r != -EINVAL); if (r < 0 || !rend_client_any_intro_points_usable(entry)) { @@ -906,7 +906,8 @@ rend_client_refetch_v2_renddesc(rend_data_t *rend_query) return; } /* Before fetching, check if we already have a usable descriptor here. */ - if (rend_cache_lookup_entry(rend_query->onion_address, -1, &e, 0) == 0 && + if (rend_cache_lookup_entry(rend_query->onion_address, -1, &e, + REND_CACHE_TYPE_CLIENT) == 0 && rend_client_any_intro_points_usable(e)) { log_info(LD_REND, "We would fetch a v2 rendezvous descriptor, but we " "already have a usable descriptor here. Not fetching."); @@ -987,7 +988,8 @@ rend_client_report_intro_point_failure(extend_info_t *failed_intro, rend_cache_entry_t *ent; connection_t *conn; - r = rend_cache_lookup_entry(rend_query->onion_address, -1, &ent, 0); + r = rend_cache_lookup_entry(rend_query->onion_address, -1, &ent, + REND_CACHE_TYPE_CLIENT); if (r < 0) { /* Either invalid onion address or cache entry not found. */ switch (-r) { @@ -1213,7 +1215,7 @@ rend_client_desc_trynow(const char *query) continue; assert_connection_ok(base_conn, now); if (rend_cache_lookup_entry(rend_data->onion_address, -1, - &entry, 0) == 0 && + &entry, REND_CACHE_TYPE_CLIENT) == 0 && rend_client_any_intro_points_usable(entry)) { /* either this fetch worked, or it failed but there was a * valid entry from before which we should reuse */ @@ -1295,7 +1297,8 @@ rend_client_get_random_intro(const rend_data_t *rend_query) extend_info_t *result; rend_cache_entry_t *entry; - ret = rend_cache_lookup_entry(rend_query->onion_address, -1, &entry, 0); + ret = rend_cache_lookup_entry(rend_query->onion_address, -1, &entry, + REND_CACHE_TYPE_CLIENT); if (ret < 0 || !rend_client_any_intro_points_usable(entry)) { log_warn(LD_REND, "Query '%s' didn't have valid rend desc in cache. Failing.", -- cgit v1.2.3-54-g00ecf From 335d0b95d36bada44e720b365f6482ce8f54c1d7 Mon Sep 17 00:00:00 2001 From: Donncha O'Cearbhaill Date: Tue, 25 Aug 2015 16:35:35 +0200 Subject: Clean old descriptors from the service-side rend cache Parameterize the rend_cache_clean() function to allow it clean old rendezvous descriptors from the service-side cache as well as the client descriptor cache. --- src/or/main.c | 3 ++- src/or/rendcache.c | 19 ++++++++++++++----- src/or/rendcache.h | 2 +- 3 files changed, 17 insertions(+), 7 deletions(-) (limited to 'src/or/rendcache.h') diff --git a/src/or/main.c b/src/or/main.c index 0b0207b975..9e798583f7 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -1518,7 +1518,8 @@ run_scheduled_events(time_t now) /* Remove old information from rephist and the rend cache. */ if (time_to.clean_caches < now) { rep_history_clean(now - options->RephistTrackTime); - rend_cache_clean(now); + rend_cache_clean(now, REND_CACHE_TYPE_CLIENT); + rend_cache_clean(now, REND_CACHE_TYPE_SERVICE); rend_cache_clean_v2_descs_as_dir(now, 0); microdesc_cache_rebuild(NULL, 0); #define CLEAN_CACHES_INTERVAL (30*60) diff --git a/src/or/rendcache.c b/src/or/rendcache.c index aae37ebbf7..09f435ca8e 100644 --- a/src/or/rendcache.c +++ b/src/or/rendcache.c @@ -260,24 +260,33 @@ rend_cache_failure_clean(time_t now) } STRMAP_FOREACH_END; } -/** Removes all old entries from the service descriptor cache. +/** Removes all old entries from the client or service descriptor cache. */ void -rend_cache_clean(time_t now) +rend_cache_clean(time_t now, rend_cache_type_t cache_type) { strmap_iter_t *iter; const char *key; void *val; rend_cache_entry_t *ent; time_t cutoff = now - REND_CACHE_MAX_AGE - REND_CACHE_MAX_SKEW; - for (iter = strmap_iter_init(rend_cache); !strmap_iter_done(iter); ) { + strmap_t *cache = NULL; + + if (cache_type == REND_CACHE_TYPE_CLIENT) { + cache = rend_cache; + } else if (cache_type == REND_CACHE_TYPE_SERVICE) { + cache = rend_cache_service; + } + tor_assert(cache); + + for (iter = strmap_iter_init(cache); !strmap_iter_done(iter); ) { strmap_iter_get(iter, &key, &val); ent = (rend_cache_entry_t*)val; if (ent->parsed->timestamp < cutoff) { - iter = strmap_iter_next_rmv(rend_cache, iter); + iter = strmap_iter_next_rmv(cache, iter); rend_cache_entry_free(ent); } else { - iter = strmap_iter_next(rend_cache, iter); + iter = strmap_iter_next(cache, iter); } } } diff --git a/src/or/rendcache.h b/src/or/rendcache.h index e13c9b4d1d..f04d0871ae 100644 --- a/src/or/rendcache.h +++ b/src/or/rendcache.h @@ -54,7 +54,7 @@ typedef enum { } rend_cache_type_t; void rend_cache_init(void); -void rend_cache_clean(time_t now); +void rend_cache_clean(time_t now, rend_cache_type_t cache_type); void rend_cache_failure_clean(time_t now); void rend_cache_clean_v2_descs_as_dir(time_t now, size_t min_to_remove); void rend_cache_purge(void); -- cgit v1.2.3-54-g00ecf From d47a4aec666396acb10a2bfcd9797a9c6402c1fe Mon Sep 17 00:00:00 2001 From: Donncha O'Cearbhaill Date: Tue, 1 Sep 2015 21:19:01 +0200 Subject: Separate lookup function for service rend cache Performing lookups in both the client and service side descriptor caches from the same rend_cache_lookup_entry() function increases the risk of accidental API misuse. I'm separating the lookup functions to keep the caches distinct. --- src/or/connection_edge.c | 3 +-- src/or/control.c | 4 ++-- src/or/rendcache.c | 57 ++++++++++++++++++++++++++++++++++-------------- src/or/rendcache.h | 5 +++-- src/or/rendclient.c | 15 +++++-------- 5 files changed, 53 insertions(+), 31 deletions(-) (limited to 'src/or/rendcache.h') diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c index 5ea82d88b1..729ef8a4c7 100644 --- a/src/or/connection_edge.c +++ b/src/or/connection_edge.c @@ -1527,8 +1527,7 @@ connection_ap_handshake_rewrite_and_attach(entry_connection_t *conn, unsigned int refetch_desc = 0; rend_cache_entry_t *entry = NULL; const int rend_cache_lookup_result = - rend_cache_lookup_entry(rend_data->onion_address, -1, &entry, - REND_CACHE_TYPE_CLIENT); + rend_cache_lookup_entry(rend_data->onion_address, -1, &entry); if (rend_cache_lookup_result < 0) { switch (-rend_cache_lookup_result) { case EINVAL: diff --git a/src/or/control.c b/src/or/control.c index 2408793bd7..7d72342293 100644 --- a/src/or/control.c +++ b/src/or/control.c @@ -1920,7 +1920,7 @@ getinfo_helper_dir(control_connection_t *control_conn, return -1; } - if (!rend_cache_lookup_entry(question, -1, &e, REND_CACHE_TYPE_CLIENT)) { + if (!rend_cache_lookup_entry(question, -1, &e)) { /* Descriptor found in cache */ *answer = tor_strdup(e->desc); } else { @@ -1936,7 +1936,7 @@ getinfo_helper_dir(control_connection_t *control_conn, return -1; } - if (!rend_cache_lookup_entry(question, -1, &e, REND_CACHE_TYPE_SERVICE)) { + if (!rend_cache_lookup_v2_desc_as_service(question, &e)) { /* Descriptor found in cache */ *answer = tor_strdup(e->desc); } else { diff --git a/src/or/rendcache.c b/src/or/rendcache.c index b8bdf88141..0fe5a47d9c 100644 --- a/src/or/rendcache.c +++ b/src/or/rendcache.c @@ -480,27 +480,23 @@ rend_cache_clean_v2_descs_as_dir(time_t now, size_t force_remove) } while (bytes_removed < force_remove); } -/** Lookup in the client or service cache the given service ID query for - * version. The service argument determines if the lookup should - * be from the client cache or the service cache. +/** Lookup in the client cache the given service ID query for + * version. * * Return 0 if found and if e is non NULL, set it with the entry * found. Else, a negative value is returned and e is untouched. * -EINVAL means that query is not a valid service id. * -ENOENT means that no entry in the cache was found. */ int -rend_cache_lookup_entry(const char *query, int version, rend_cache_entry_t **e, - rend_cache_type_t cache) +rend_cache_lookup_entry(const char *query, int version, rend_cache_entry_t **e) { int ret = 0; char key[REND_SERVICE_ID_LEN_BASE32 + 2]; /* \0 */ rend_cache_entry_t *entry = NULL; static const int default_version = 2; - tor_assert(rend_cache_local_service); tor_assert(rend_cache); tor_assert(query); - tor_assert(cache); if (!rend_valid_service_id(query)) { ret = -EINVAL; @@ -514,21 +510,50 @@ rend_cache_lookup_entry(const char *query, int version, rend_cache_entry_t **e, case 2: /* Default is version 2. */ default: - if(cache == REND_CACHE_TYPE_SERVICE){ - entry = strmap_get_lc(rend_cache_local_service, query); - } else if (cache == REND_CACHE_TYPE_CLIENT) { - tor_snprintf(key, sizeof(key), "%d%s", default_version, query); - entry = strmap_get_lc(rend_cache, key); - } + tor_snprintf(key, sizeof(key), "%d%s", default_version, query); + entry = strmap_get_lc(rend_cache, key); break; } if (!entry) { ret = -ENOENT; goto end; } - /* Check descriptor is parsed only if lookup is from client cache */ - if(cache == REND_CACHE_TYPE_CLIENT){ - tor_assert(entry->parsed && entry->parsed->intro_nodes); + tor_assert(entry->parsed && entry->parsed->intro_nodes); + + if (e) { + *e = entry; + } + + end: + return ret; +} + +/* + * Lookup the v2 service descriptor with the service ID query in the + * local service descriptor cache. Return 0 if found and if e is + * non NULL, set it with the entry found. Else, a negative value is returned + * and e is untouched. + * -EINVAL means that query is not a valid service id. + * -ENOENT means that no entry in the cache was found. */ +int +rend_cache_lookup_v2_desc_as_service(const char *query, rend_cache_entry_t **e) +{ + int ret = 0; + rend_cache_entry_t *entry = NULL; + + tor_assert(rend_cache_local_service); + tor_assert(query); + + if (!rend_valid_service_id(query)) { + ret = -EINVAL; + goto end; + } + + /* Lookup descriptor and return. */ + entry = strmap_get_lc(rend_cache_local_service, query); + if (!entry) { + ret = -ENOENT; + goto end; } if (e) { diff --git a/src/or/rendcache.h b/src/or/rendcache.h index f04d0871ae..a5ad2da3b4 100644 --- a/src/or/rendcache.h +++ b/src/or/rendcache.h @@ -60,8 +60,9 @@ void rend_cache_clean_v2_descs_as_dir(time_t now, size_t min_to_remove); void rend_cache_purge(void); void rend_cache_free_all(void); int rend_cache_lookup_entry(const char *query, int version, - rend_cache_entry_t **entry_out, - rend_cache_type_t cache); + rend_cache_entry_t **entry_out); +int rend_cache_lookup_v2_desc_as_service(const char *query, + rend_cache_entry_t **entry_out); int rend_cache_lookup_v2_desc_as_dir(const char *query, const char **desc); /** Return value from rend_cache_store_v2_desc_as_{dir,client}. */ typedef enum { diff --git a/src/or/rendclient.c b/src/or/rendclient.c index af1abe59bf..a39e518e99 100644 --- a/src/or/rendclient.c +++ b/src/or/rendclient.c @@ -160,7 +160,7 @@ rend_client_send_introduction(origin_circuit_t *introcirc, #endif r = rend_cache_lookup_entry(introcirc->rend_data->onion_address, -1, - &entry, REND_CACHE_TYPE_CLIENT); + &entry); /* An invalid onion address is not possible else we have a big issue. */ tor_assert(r != -EINVAL); if (r < 0 || !rend_client_any_intro_points_usable(entry)) { @@ -906,8 +906,7 @@ rend_client_refetch_v2_renddesc(rend_data_t *rend_query) return; } /* Before fetching, check if we already have a usable descriptor here. */ - if (rend_cache_lookup_entry(rend_query->onion_address, -1, &e, - REND_CACHE_TYPE_CLIENT) == 0 && + if (rend_cache_lookup_entry(rend_query->onion_address, -1, &e) == 0 && rend_client_any_intro_points_usable(e)) { log_info(LD_REND, "We would fetch a v2 rendezvous descriptor, but we " "already have a usable descriptor here. Not fetching."); @@ -988,8 +987,7 @@ rend_client_report_intro_point_failure(extend_info_t *failed_intro, rend_cache_entry_t *ent; connection_t *conn; - r = rend_cache_lookup_entry(rend_query->onion_address, -1, &ent, - REND_CACHE_TYPE_CLIENT); + r = rend_cache_lookup_entry(rend_query->onion_address, -1, &ent); if (r < 0) { /* Either invalid onion address or cache entry not found. */ switch (-r) { @@ -1215,7 +1213,7 @@ rend_client_desc_trynow(const char *query) continue; assert_connection_ok(base_conn, now); if (rend_cache_lookup_entry(rend_data->onion_address, -1, - &entry, REND_CACHE_TYPE_CLIENT) == 0 && + &entry) == 0 && rend_client_any_intro_points_usable(entry)) { /* either this fetch worked, or it failed but there was a * valid entry from before which we should reuse */ @@ -1258,7 +1256,7 @@ rend_client_note_connection_attempt_ended(const rend_data_t *rend_data) if (*rend_data->onion_address != '\0') { /* Ignore return value; we find an entry, or we don't. */ (void) rend_cache_lookup_entry(rend_data->onion_address, -1, - &cache_entry, 0); + &cache_entry); have_onion = 1; } @@ -1297,8 +1295,7 @@ rend_client_get_random_intro(const rend_data_t *rend_query) extend_info_t *result; rend_cache_entry_t *entry; - ret = rend_cache_lookup_entry(rend_query->onion_address, -1, &entry, - REND_CACHE_TYPE_CLIENT); + ret = rend_cache_lookup_entry(rend_query->onion_address, -1, &entry); if (ret < 0 || !rend_client_any_intro_points_usable(entry)) { log_warn(LD_REND, "Query '%s' didn't have valid rend desc in cache. Failing.", -- cgit v1.2.3-54-g00ecf