diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/or/hs_client.c | 8 | ||||
-rw-r--r-- | src/or/hs_client.h | 2 | ||||
-rw-r--r-- | src/or/hs_common.c | 6 | ||||
-rw-r--r-- | src/or/hs_service.c | 182 | ||||
-rw-r--r-- | src/or/hs_service.h | 8 | ||||
-rw-r--r-- | src/or/main.c | 2 | ||||
-rw-r--r-- | src/or/networkstatus.c | 2 | ||||
-rw-r--r-- | src/or/nodelist.c | 2 | ||||
-rw-r--r-- | src/or/rendservice.c | 34 |
9 files changed, 100 insertions, 146 deletions
diff --git a/src/or/hs_client.c b/src/or/hs_client.c index 99be058eb7..19e20c0e8d 100644 --- a/src/or/hs_client.c +++ b/src/or/hs_client.c @@ -1251,3 +1251,11 @@ hs_client_reextend_intro_circuit(origin_circuit_t *circ) return ret; } +/* Release all the storage held by the client subsystem. */ +void +hs_client_free_all(void) +{ + /* Purge the hidden service request cache. */ + hs_purge_last_hid_serv_requests(); +} + diff --git a/src/or/hs_client.h b/src/or/hs_client.h index 8ed0501c91..86784f52c3 100644 --- a/src/or/hs_client.h +++ b/src/or/hs_client.h @@ -46,5 +46,7 @@ extend_info_t *hs_client_get_random_intro_from_edge( int hs_client_reextend_intro_circuit(origin_circuit_t *circ); +void hs_client_free_all(void); + #endif /* TOR_HS_CLIENT_H */ diff --git a/src/or/hs_common.c b/src/or/hs_common.c index d866ab6a8f..5ea44b97e7 100644 --- a/src/or/hs_common.c +++ b/src/or/hs_common.c @@ -19,6 +19,7 @@ #include "nodelist.h" #include "hs_cache.h" #include "hs_common.h" +#include "hs_client.h" #include "hs_ident.h" #include "hs_service.h" #include "policies.h" @@ -1206,12 +1207,16 @@ node_has_hsdir_index(const node_t *node, int is_for_next_period) if (BUG(node->hsdir_index == NULL) || BUG(tor_mem_is_zero((const char*)node->hsdir_index->current, DIGEST256_LEN))) { + log_warn(LD_BUG, "Zero current index (ri: %p, rs: %p, md: %p)", + node->ri, node->rs, node->md); return 0; } if (is_for_next_period && BUG(tor_mem_is_zero((const char*)node->hsdir_index->next, DIGEST256_LEN))) { + log_warn(LD_BUG, "Zero next index (ri: %p, rs: %p, md: %p)", + node->ri, node->rs, node->md); return 0; } @@ -1700,6 +1705,7 @@ hs_free_all(void) hs_circuitmap_free_all(); hs_service_free_all(); hs_cache_free_all(); + hs_client_free_all(); } /* For the given origin circuit circ, decrement the number of rendezvous diff --git a/src/or/hs_service.c b/src/or/hs_service.c index 218d49ace3..796efa0c9b 100644 --- a/src/or/hs_service.c +++ b/src/or/hs_service.c @@ -78,6 +78,7 @@ static smartlist_t *hs_service_staging_list; static int consider_republishing_hs_descriptors = 0; static void set_descriptor_revision_counter(hs_descriptor_t *hs_desc); +static void move_descriptors(hs_service_t *src, hs_service_t *dst); /* Helper: Function to compare two objects in the service map. Return 1 if the * two service have the same master public identity key. */ @@ -714,37 +715,6 @@ close_service_circuits(hs_service_t *service) close_service_rp_circuits(service); } -/* Move introduction points from the src descriptor to the dst descriptor. The - * destination service intropoints are wiped out if any before moving. */ -static void -move_descriptor_intro_points(hs_service_descriptor_t *src, - hs_service_descriptor_t *dst) -{ - tor_assert(src); - tor_assert(dst); - - digest256map_free(dst->intro_points.map, service_intro_point_free_); - dst->intro_points.map = src->intro_points.map; - /* Nullify the source. */ - src->intro_points.map = NULL; -} - -/* Move introduction points from the src service to the dst service. The - * destination service intropoints are wiped out if any before moving. */ -static void -move_intro_points(hs_service_t *src, hs_service_t *dst) -{ - tor_assert(src); - tor_assert(dst); - - if (src->desc_current && dst->desc_current) { - move_descriptor_intro_points(src->desc_current, dst->desc_current); - } - if (src->desc_next && dst->desc_next) { - move_descriptor_intro_points(src->desc_next, dst->desc_next); - } -} - /* Move every ephemeral services from the src service map to the dst service * map. It is possible that a service can't be register to the dst map which * won't stop the process of moving them all but will trigger a log warn. */ @@ -785,6 +755,26 @@ service_escaped_dir(const hs_service_t *s) escaped(s->config.directory_path); } +/** Move the hidden service state from <b>src</b> to <b>dst</b>. We do this + * when we receive a SIGHUP: <b>dst</b> is the post-HUP service */ +static void +move_hs_state(hs_service_t *src_service, hs_service_t *dst_service) +{ + tor_assert(src_service); + tor_assert(dst_service); + + hs_service_state_t *src = &src_service->state; + hs_service_state_t *dst = &dst_service->state; + + /* Let's do a shallow copy */ + dst->intro_circ_retry_started_time = src->intro_circ_retry_started_time; + dst->num_intro_circ_launched = src->num_intro_circ_launched; + dst->in_overlap_period = src->in_overlap_period; + dst->replay_cache_rend_cookie = src->replay_cache_rend_cookie; + + src->replay_cache_rend_cookie = NULL; /* steal pointer reference */ +} + /* Register services that are in the staging list. Once this function returns, * the global service map will be set with the right content and all non * surviving services will be cleaned up. */ @@ -817,13 +807,15 @@ register_all_services(void) * transfer the intro points to it. */ s = find_service(hs_service_map, &snew->keys.identity_pk); if (s) { - /* Pass ownership of intro points from s (the current service) to snew - * (the newly configured one). */ - move_intro_points(s, snew); + /* Pass ownership of the descriptors from s (the current service) to + * snew (the newly configured one). */ + move_descriptors(s, snew); + move_hs_state(s, snew); /* Remove the service from the global map because after this, we need to * go over the remaining service in that map that aren't surviving the * reload to close their circuits. */ remove_service(hs_service_map, s); + hs_service_free(s); } /* Great, this service is now ready to be added to our new map. */ if (BUG(register_service(new_service_map, snew) < 0)) { @@ -972,8 +964,6 @@ service_descriptor_free(hs_service_descriptor_t *desc) hs_descriptor_free(desc->desc); memwipe(&desc->signing_kp, 0, sizeof(desc->signing_kp)); memwipe(&desc->blinded_kp, 0, sizeof(desc->blinded_kp)); - SMARTLIST_FOREACH(desc->hsdir_missing_info, char *, id, tor_free(id)); - smartlist_free(desc->hsdir_missing_info); /* Cleanup all intro points. */ digest256map_free(desc->intro_points.map, service_intro_point_free_); digestmap_free(desc->intro_points.failed_id, tor_free_); @@ -993,11 +983,37 @@ service_descriptor_new(void) /* Initialize the intro points map. */ sdesc->intro_points.map = digest256map_new(); sdesc->intro_points.failed_id = digestmap_new(); - sdesc->hsdir_missing_info = smartlist_new(); sdesc->previous_hsdirs = smartlist_new(); return sdesc; } +/* Move descriptor(s) from the src service to the dst service. We do this + * during SIGHUP when we re-create our hidden services. */ +static void +move_descriptors(hs_service_t *src, hs_service_t *dst) +{ + tor_assert(src); + tor_assert(dst); + + if (src->desc_current) { + /* Nothing should be there, but clean it up just in case */ + if (BUG(dst->desc_current)) { + service_descriptor_free(dst->desc_current); + } + dst->desc_current = src->desc_current; + src->desc_current = NULL; + } + + if (src->desc_next) { + /* Nothing should be there, but clean it up just in case */ + if (BUG(dst->desc_next)) { + service_descriptor_free(dst->desc_next); + } + dst->desc_next = src->desc_next; + src->desc_next = NULL; + } +} + /* From the given service, remove all expired failing intro points for each * descriptor. */ static void @@ -2327,18 +2343,6 @@ upload_descriptor_to_all(const hs_service_t *service, /* Getting responsible hsdir implies that the node_t object exists for the * routerstatus_t found in the consensus else we have a problem. */ tor_assert(hsdir_node); - /* Do not upload to an HSDir we don't have a descriptor for. */ - if (!node_has_descriptor(hsdir_node)) { - log_info(LD_REND, "Missing descriptor for HSDir %s. Not uploading " - "descriptor. We'll try later once we have it.", - safe_str_client(node_describe(hsdir_node))); - /* Once we get new directory information, this HSDir will be retried if - * we ever get the descriptor. */ - smartlist_add(desc->hsdir_missing_info, - tor_memdup(hsdir_rs->identity_digest, DIGEST_LEN)); - continue; - } - /* Upload this descriptor to the chosen directory. */ upload_descriptor_to_hsdir(service, desc, hsdir_node); } SMARTLIST_FOREACH_END(hsdir_rs); @@ -2718,58 +2722,6 @@ service_handle_introduce2(origin_circuit_t *circ, const uint8_t *payload, return -1; } -/* For a given service and a descriptor of that service, consider retrying to - * upload the descriptor to any directories from which we had missing - * information when originally tried to be uploaded. This is called when our - * directory information has changed. */ -static void -consider_hsdir_upload_retry(const hs_service_t *service, - hs_service_descriptor_t *desc) -{ - smartlist_t *responsible_dirs = NULL; - smartlist_t *still_missing_dirs = NULL; - - tor_assert(service); - tor_assert(desc); - - responsible_dirs = smartlist_new(); - still_missing_dirs = smartlist_new(); - - /* We first need to get responsible directories from the latest consensus so - * we can then make sure that the node that we were missing information for - * is still responsible for this descriptor. */ - hs_get_responsible_hsdirs(&desc->blinded_kp.pubkey, desc->time_period_num, - service->desc_next == desc, 0, responsible_dirs); - - SMARTLIST_FOREACH_BEGIN(responsible_dirs, const routerstatus_t *, rs) { - const node_t *node; - const char *id = rs->identity_digest; - if (!smartlist_contains_digest(desc->hsdir_missing_info, id)) { - continue; - } - /* We do need a node_t object and descriptor to perform an upload. If - * found, we remove the id from the missing dir list else we add it to the - * still missing dir list to keep track of id that are still missing. */ - node = node_get_by_id(id); - if (node && node_has_descriptor(node)) { - upload_descriptor_to_hsdir(service, desc, node); - smartlist_remove(desc->hsdir_missing_info, id); - } else { - smartlist_add(still_missing_dirs, tor_memdup(id, DIGEST_LEN)); - } - } SMARTLIST_FOREACH_END(rs); - - /* Switch the still missing dir list with the current missing dir list in - * the descriptor. It is possible that the list ends up empty which is what - * we want if we have no more missing dir. */ - SMARTLIST_FOREACH(desc->hsdir_missing_info, char *, id, tor_free(id)); - smartlist_free(desc->hsdir_missing_info); - desc->hsdir_missing_info = still_missing_dirs; - - /* No ownership of the routerstatus_t object in this list. */ - smartlist_free(responsible_dirs); -} - /* Add to list every filename used by service. This is used by the sandbox * subsystem. */ static void @@ -2796,16 +2748,6 @@ service_add_fnames_to_list(const hs_service_t *service, smartlist_t *list) /* Public API */ /* ========== */ -/* We just received a new batch of descriptors which might affect the shape of - * the HSDir hash ring. Signal that we should reexamine the hash ring and - * re-upload our HS descriptors if needed. */ -void -hs_hsdir_set_changed_consider_reupload(void) -{ - log_info(LD_REND, "New dirinfo arrived: consider reuploading descriptor"); - consider_republishing_hs_descriptors = 1; -} - /* Return the number of service we have configured and usable. */ unsigned int hs_service_get_num_services(void) @@ -2975,22 +2917,14 @@ hs_service_lists_fnames_for_sandbox(smartlist_t *file_list, } /* Called when our internal view of the directory has changed. We might have - * new descriptors for hidden service directories that we didn't have before - * so try them if it's the case. */ + * received a new batch of descriptors which might affect the shape of the + * HSDir hash ring. Signal that we should reexamine the hash ring and + * re-upload our HS descriptors if needed. */ void hs_service_dir_info_changed(void) { - /* For each service we have, check every descriptor and consider retrying to - * upload it to directories that we might have had missing information - * previously that is missing a router descriptor. */ - FOR_EACH_SERVICE_BEGIN(service) { - FOR_EACH_DESCRIPTOR_BEGIN(service, desc) { - /* This cleans up the descriptor missing hsdir information list if a - * successful upload is made or if any of the directory aren't - * responsible anymore for the service descriptor. */ - consider_hsdir_upload_retry(service, desc); - } FOR_EACH_DESCRIPTOR_END; - } FOR_EACH_SERVICE_END; + log_info(LD_REND, "New dirinfo arrived: consider reuploading descriptor"); + consider_republishing_hs_descriptors = 1; } /* Called when we get an INTRODUCE2 cell on the circ. Respond to the cell and diff --git a/src/or/hs_service.h b/src/or/hs_service.h index 26f0bc0002..317b9d795d 100644 --- a/src/or/hs_service.h +++ b/src/or/hs_service.h @@ -123,13 +123,6 @@ typedef struct hs_service_descriptor_t { * couldn't pick any nodes. */ unsigned int missing_intro_points : 1; - /* List of identity digests for hidden service directories to which we - * couldn't upload this descriptor because we didn't have its router - * descriptor at the time. If this list is non-empty, only the relays in this - * list are re-tried to upload this descriptor when our directory information - * have been updated. */ - smartlist_t *hsdir_missing_info; - /** List of the responsible HSDirs (their b64ed identity digest) last time we * uploaded this descriptor. If the set of responsible HSDirs is different * from this list, this means we received new dirinfo and we need to @@ -266,7 +259,6 @@ void hs_service_lists_fnames_for_sandbox(smartlist_t *file_list, smartlist_t *dir_list); int hs_service_set_conn_addr_port(const origin_circuit_t *circ, edge_connection_t *conn); -void hs_hsdir_set_changed_consider_reupload(void); void hs_service_dir_info_changed(void); void hs_service_run_scheduled_events(time_t now); diff --git a/src/or/main.c b/src/or/main.c index 5d51d1dead..a29fc315a2 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -1483,7 +1483,7 @@ run_scheduled_events(time_t now) /* 12. launch diff computations. (This is free if there are none to * launch.) */ - if (server_mode(options)) { + if (dir_server_mode(options)) { consdiffmgr_rescan(); } } diff --git a/src/or/networkstatus.c b/src/or/networkstatus.c index 69bff55cff..7136ab2968 100644 --- a/src/or/networkstatus.c +++ b/src/or/networkstatus.c @@ -2021,7 +2021,7 @@ networkstatus_set_current_consensus(const char *consensus, &c->digests, c->digest_sha3_as_signed, c->valid_after); - if (server_mode(get_options())) { + if (dir_server_mode(get_options())) { consdiffmgr_add_consensus(consensus, c); } } diff --git a/src/or/nodelist.c b/src/or/nodelist.c index 6acc87f967..155a511ca1 100644 --- a/src/or/nodelist.c +++ b/src/or/nodelist.c @@ -1810,7 +1810,7 @@ router_dir_info_changed(void) { need_to_update_have_min_dir_info = 1; rend_hsdir_routers_changed(); - hs_hsdir_set_changed_consider_reupload(); + hs_service_dir_info_changed(); } /** Return a string describing what we're missing before we have enough diff --git a/src/or/rendservice.c b/src/or/rendservice.c index 99ba9b3d83..c17d77f970 100644 --- a/src/or/rendservice.c +++ b/src/or/rendservice.c @@ -954,16 +954,23 @@ rend_log_intro_limit(const rend_service_t *service, int min_severity) } time_t intro_period_elapsed = time(NULL) - service->intro_period_started; tor_assert_nonfatal(intro_period_elapsed >= 0); - log_fn(severity, LD_REND, "Hidden service %s %s %d intro points in the last " - "%d seconds. Intro circuit launches are limited to %d per %d " - "seconds.", - service->service_id, - exceeded_limit ? "exceeded launch limit with" : "launched", - service->n_intro_circuits_launched, - (int)intro_period_elapsed, - rend_max_intro_circs_per_period(service->n_intro_points_wanted), - INTRO_CIRC_RETRY_PERIOD); - rend_service_dump_stats(severity); + { + char *msg; + static ratelim_t rlimit = RATELIM_INIT(INTRO_CIRC_RETRY_PERIOD); + if ((msg = rate_limit_log(&rlimit, approx_time()))) { + log_fn(severity, LD_REND, + "Hidden service %s %s %d intro points in the last %d seconds. " + "Intro circuit launches are limited to %d per %d seconds.%s", + service->service_id, + exceeded_limit ? "exceeded launch limit with" : "launched", + service->n_intro_circuits_launched, + (int)intro_period_elapsed, + rend_max_intro_circs_per_period(service->n_intro_points_wanted), + INTRO_CIRC_RETRY_PERIOD, msg); + rend_service_dump_stats(severity); + tor_free(msg); + } + } } /** Replace the old value of <b>service</b>-\>desc with one that reflects @@ -3922,7 +3929,12 @@ rend_max_intro_circs_per_period(unsigned int n_intro_points_wanted) /* Allow all but one of the initial connections to fail and be * retried. (If all fail, we *want* to wait, because something is broken.) */ tor_assert(n_intro_points_wanted <= NUM_INTRO_POINTS_MAX); - return (int)(2*n_intro_points_wanted + NUM_INTRO_POINTS_EXTRA); + + /* For the normal use case, 3 intro points plus 2 extra for performance and + * allow that twice because once every 24h or so, we can do it twice for two + * descriptors that is the current one and the next one. So (3 + 2) * 2 == + * 12 allowed attempts for one period. */ + return ((n_intro_points_wanted + NUM_INTRO_POINTS_EXTRA) * 2); } /** For every service, check how many intro points it currently has, and: |