tor-commits
Threads by month
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
September 2018
- 17 participants
- 3231 discussions
commit 994de7db5345a1c1a2c182000d6e2bd42df5ae57
Merge: dbb0abc9f ab92f9342
Author: Nick Mathewson <nickm(a)torproject.org>
Date: Fri Sep 14 10:16:44 2018 -0400
Merge branch 'ticket27686_034' into x
src/core/or/circuitlist.c | 20 ++++++++++++++++++--
src/core/or/connection_edge.c | 23 ++++++++++++++++++++++-
src/core/or/connection_edge.h | 5 +++++
src/core/or/relay.c | 1 +
4 files changed, 46 insertions(+), 3 deletions(-)
diff --cc src/core/or/circuitlist.c
index 78ecadab7,000000000..25af31328
mode 100644,000000..100644
--- a/src/core/or/circuitlist.c
+++ b/src/core/or/circuitlist.c
@@@ -1,2751 -1,0 +1,2767 @@@
+/* Copyright 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file circuitlist.c
+ *
+ * \brief Manage global structures that list and index circuits, and
+ * look up circuits within them.
+ *
+ * One of the most frequent operations in Tor occurs every time that
+ * a relay cell arrives on a channel. When that happens, we need to
+ * find which circuit it is associated with, based on the channel and the
+ * circuit ID in the relay cell.
+ *
+ * To handle that, we maintain a global list of circuits, and a hashtable
+ * mapping [channel,circID] pairs to circuits. Circuits are added to and
+ * removed from this mapping using circuit_set_p_circid_chan() and
+ * circuit_set_n_circid_chan(). To look up a circuit from this map, most
+ * callers should use circuit_get_by_circid_channel(), though
+ * circuit_get_by_circid_channel_even_if_marked() is appropriate under some
+ * circumstances.
+ *
+ * We also need to allow for the possibility that we have blocked use of a
+ * circuit ID (because we are waiting to send a DESTROY cell), but the
+ * circuit is not there any more. For that case, we allow placeholder
+ * entries in the table, using channel_mark_circid_unusable().
+ *
+ * To efficiently handle a channel that has just opened, we also maintain a
+ * list of the circuits waiting for channels, so we can attach them as
+ * needed without iterating through the whole list of circuits, using
+ * circuit_get_all_pending_on_channel().
+ *
+ * In this module, we also handle the list of circuits that have been
+ * marked for close elsewhere, and close them as needed. (We use this
+ * "mark now, close later" pattern here and elsewhere to avoid
+ * unpredictable recursion if we closed every circuit immediately upon
+ * realizing it needed to close.) See circuit_mark_for_close() for the
+ * mark function, and circuit_close_all_marked() for the close function.
+ *
+ * For hidden services, we need to be able to look up introduction point
+ * circuits and rendezvous circuits by cookie, key, etc. These are
+ * currently handled with linear searches in
+ * circuit_get_ready_rend_circuit_by_rend_data(),
+ * circuit_get_next_by_pk_and_purpose(), and with hash lookups in
+ * circuit_get_rendezvous() and circuit_get_intro_point().
+ *
+ * This module is also the entry point for our out-of-memory handler
+ * logic, which was originally circuit-focused.
+ **/
+#define CIRCUITLIST_PRIVATE
+#include "lib/cc/torint.h" /* TOR_PRIuSZ */
+
+#include "core/or/or.h"
+#include "core/or/channel.h"
+#include "feature/client/circpathbias.h"
+#include "core/or/circuitbuild.h"
+#include "core/or/circuitlist.h"
+#include "core/or/circuituse.h"
+#include "core/or/circuitstats.h"
+#include "core/mainloop/connection.h"
+#include "app/config/config.h"
+#include "core/or/connection_edge.h"
+#include "core/or/connection_or.h"
+#include "feature/control/control.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "lib/crypt_ops/crypto_util.h"
+#include "lib/crypt_ops/crypto_dh.h"
+#include "feature/dircache/directory.h"
+#include "feature/client/entrynodes.h"
+#include "core/mainloop/main.h"
+#include "feature/hs/hs_circuit.h"
+#include "feature/hs/hs_circuitmap.h"
+#include "feature/hs/hs_ident.h"
+#include "feature/nodelist/networkstatus.h"
+#include "feature/nodelist/nodelist.h"
+#include "core/crypto/onion.h"
+#include "core/crypto/onion_fast.h"
+#include "core/or/policies.h"
+#include "core/or/relay.h"
+#include "core/crypto/relay_crypto.h"
+#include "feature/rend/rendclient.h"
+#include "feature/rend/rendcommon.h"
+#include "feature/stats/rephist.h"
+#include "feature/nodelist/routerlist.h"
+#include "feature/nodelist/routerset.h"
+#include "core/or/channelpadding.h"
+#include "lib/compress/compress.h"
+#include "lib/compress/compress_lzma.h"
+#include "lib/compress/compress_zlib.h"
+#include "lib/compress/compress_zstd.h"
+#include "lib/container/buffers.h"
+
+#include "ht.h"
+
+#include "core/or/cpath_build_state_st.h"
+#include "core/or/crypt_path_reference_st.h"
+#include "feature/dircommon/dir_connection_st.h"
+#include "core/or/edge_connection_st.h"
+#include "core/or/half_edge_st.h"
+#include "core/or/extend_info_st.h"
+#include "core/or/or_circuit_st.h"
+#include "core/or/origin_circuit_st.h"
+
+/********* START VARIABLES **********/
+
+/** A global list of all circuits at this hop. */
+static smartlist_t *global_circuitlist = NULL;
+
+/** A global list of all origin circuits. Every element of this is also
+ * an element of global_circuitlist. */
+static smartlist_t *global_origin_circuit_list = NULL;
+
+/** A list of all the circuits in CIRCUIT_STATE_CHAN_WAIT. */
+static smartlist_t *circuits_pending_chans = NULL;
+
+/** List of all the (origin) circuits whose state is
+ * CIRCUIT_STATE_GUARD_WAIT. */
+static smartlist_t *circuits_pending_other_guards = NULL;
+
+/** A list of all the circuits that have been marked with
+ * circuit_mark_for_close and which are waiting for circuit_about_to_free. */
+static smartlist_t *circuits_pending_close = NULL;
+
+static void circuit_free_cpath_node(crypt_path_t *victim);
+static void cpath_ref_decref(crypt_path_reference_t *cpath_ref);
+static void circuit_about_to_free_atexit(circuit_t *circ);
+static void circuit_about_to_free(circuit_t *circ);
+
+/**
+ * A cached value of the current state of the origin circuit list. Has the
+ * value 1 if we saw any opened circuits recently (since the last call to
+ * circuit_any_opened_circuits(), which gets called around once a second by
+ * circuit_expire_building). 0 otherwise.
+ */
+static int any_opened_circs_cached_val = 0;
+
+/********* END VARIABLES ************/
+
+or_circuit_t *
+TO_OR_CIRCUIT(circuit_t *x)
+{
+ tor_assert(x->magic == OR_CIRCUIT_MAGIC);
+ return DOWNCAST(or_circuit_t, x);
+}
+const or_circuit_t *
+CONST_TO_OR_CIRCUIT(const circuit_t *x)
+{
+ tor_assert(x->magic == OR_CIRCUIT_MAGIC);
+ return DOWNCAST(or_circuit_t, x);
+}
+origin_circuit_t *
+TO_ORIGIN_CIRCUIT(circuit_t *x)
+{
+ tor_assert(x->magic == ORIGIN_CIRCUIT_MAGIC);
+ return DOWNCAST(origin_circuit_t, x);
+}
+const origin_circuit_t *
+CONST_TO_ORIGIN_CIRCUIT(const circuit_t *x)
+{
+ tor_assert(x->magic == ORIGIN_CIRCUIT_MAGIC);
+ return DOWNCAST(origin_circuit_t, x);
+}
+
+/** A map from channel and circuit ID to circuit. (Lookup performance is
+ * very important here, since we need to do it every time a cell arrives.) */
+typedef struct chan_circid_circuit_map_t {
+ HT_ENTRY(chan_circid_circuit_map_t) node;
+ channel_t *chan;
+ circid_t circ_id;
+ circuit_t *circuit;
+ /* For debugging 12184: when was this placeholder item added? */
+ time_t made_placeholder_at;
+} chan_circid_circuit_map_t;
+
+/** Helper for hash tables: compare the channel and circuit ID for a and
+ * b, and return less than, equal to, or greater than zero appropriately.
+ */
+static inline int
+chan_circid_entries_eq_(chan_circid_circuit_map_t *a,
+ chan_circid_circuit_map_t *b)
+{
+ return a->chan == b->chan && a->circ_id == b->circ_id;
+}
+
+/** Helper: return a hash based on circuit ID and the pointer value of
+ * chan in <b>a</b>. */
+static inline unsigned int
+chan_circid_entry_hash_(chan_circid_circuit_map_t *a)
+{
+ /* Try to squeze the siphash input into 8 bytes to save any extra siphash
+ * rounds. This hash function is in the critical path. */
+ uintptr_t chan = (uintptr_t) (void*) a->chan;
+ uint32_t array[2];
+ array[0] = a->circ_id;
+ /* The low bits of the channel pointer are uninteresting, since the channel
+ * is a pretty big structure. */
+ array[1] = (uint32_t) (chan >> 6);
+ return (unsigned) siphash24g(array, sizeof(array));
+}
+
+/** Map from [chan,circid] to circuit. */
+static HT_HEAD(chan_circid_map, chan_circid_circuit_map_t)
+ chan_circid_map = HT_INITIALIZER();
+HT_PROTOTYPE(chan_circid_map, chan_circid_circuit_map_t, node,
+ chan_circid_entry_hash_, chan_circid_entries_eq_)
+HT_GENERATE2(chan_circid_map, chan_circid_circuit_map_t, node,
+ chan_circid_entry_hash_, chan_circid_entries_eq_, 0.6,
+ tor_reallocarray_, tor_free_)
+
+/** The most recently returned entry from circuit_get_by_circid_chan;
+ * used to improve performance when many cells arrive in a row from the
+ * same circuit.
+ */
+static chan_circid_circuit_map_t *_last_circid_chan_ent = NULL;
+
+/** Implementation helper for circuit_set_{p,n}_circid_channel: A circuit ID
+ * and/or channel for circ has just changed from <b>old_chan, old_id</b>
+ * to <b>chan, id</b>. Adjust the chan,circid map as appropriate, removing
+ * the old entry (if any) and adding a new one. */
+static void
+circuit_set_circid_chan_helper(circuit_t *circ, int direction,
+ circid_t id,
+ channel_t *chan)
+{
+ chan_circid_circuit_map_t search;
+ chan_circid_circuit_map_t *found;
+ channel_t *old_chan, **chan_ptr;
+ circid_t old_id, *circid_ptr;
+ int make_active, attached = 0;
+
+ if (direction == CELL_DIRECTION_OUT) {
+ chan_ptr = &circ->n_chan;
+ circid_ptr = &circ->n_circ_id;
+ make_active = circ->n_chan_cells.n > 0;
+ } else {
+ or_circuit_t *c = TO_OR_CIRCUIT(circ);
+ chan_ptr = &c->p_chan;
+ circid_ptr = &c->p_circ_id;
+ make_active = c->p_chan_cells.n > 0;
+ }
+ old_chan = *chan_ptr;
+ old_id = *circid_ptr;
+
+ if (id == old_id && chan == old_chan)
+ return;
+
+ if (_last_circid_chan_ent &&
+ ((old_id == _last_circid_chan_ent->circ_id &&
+ old_chan == _last_circid_chan_ent->chan) ||
+ (id == _last_circid_chan_ent->circ_id &&
+ chan == _last_circid_chan_ent->chan))) {
+ _last_circid_chan_ent = NULL;
+ }
+
+ if (old_chan) {
+ /*
+ * If we're changing channels or ID and had an old channel and a non
+ * zero old ID and weren't marked for close (i.e., we should have been
+ * attached), detach the circuit. ID changes require this because
+ * circuitmux hashes on (channel_id, circuit_id).
+ */
+ if (old_id != 0 && (old_chan != chan || old_id != id) &&
+ !(circ->marked_for_close)) {
+ tor_assert(old_chan->cmux);
+ circuitmux_detach_circuit(old_chan->cmux, circ);
+ }
+
+ /* we may need to remove it from the conn-circid map */
+ search.circ_id = old_id;
+ search.chan = old_chan;
+ found = HT_REMOVE(chan_circid_map, &chan_circid_map, &search);
+ if (found) {
+ tor_free(found);
+ if (direction == CELL_DIRECTION_OUT) {
+ /* One fewer circuits use old_chan as n_chan */
+ --(old_chan->num_n_circuits);
+ } else {
+ /* One fewer circuits use old_chan as p_chan */
+ --(old_chan->num_p_circuits);
+ }
+ }
+ }
+
+ /* Change the values only after we have possibly made the circuit inactive
+ * on the previous chan. */
+ *chan_ptr = chan;
+ *circid_ptr = id;
+
+ if (chan == NULL)
+ return;
+
+ /* now add the new one to the conn-circid map */
+ search.circ_id = id;
+ search.chan = chan;
+ found = HT_FIND(chan_circid_map, &chan_circid_map, &search);
+ if (found) {
+ found->circuit = circ;
+ found->made_placeholder_at = 0;
+ } else {
+ found = tor_malloc_zero(sizeof(chan_circid_circuit_map_t));
+ found->circ_id = id;
+ found->chan = chan;
+ found->circuit = circ;
+ HT_INSERT(chan_circid_map, &chan_circid_map, found);
+ }
+
+ /*
+ * Attach to the circuitmux if we're changing channels or IDs and
+ * have a new channel and ID to use and the circuit is not marked for
+ * close.
+ */
+ if (chan && id != 0 && (old_chan != chan || old_id != id) &&
+ !(circ->marked_for_close)) {
+ tor_assert(chan->cmux);
+ circuitmux_attach_circuit(chan->cmux, circ, direction);
+ attached = 1;
+ }
+
+ /*
+ * This is a no-op if we have no cells, but if we do it marks us active to
+ * the circuitmux
+ */
+ if (make_active && attached)
+ update_circuit_on_cmux(circ, direction);
+
+ /* Adjust circuit counts on new channel */
+ if (direction == CELL_DIRECTION_OUT) {
+ ++chan->num_n_circuits;
+ } else {
+ ++chan->num_p_circuits;
+ }
+}
+
+/** Mark that circuit id <b>id</b> shouldn't be used on channel <b>chan</b>,
+ * even if there is no circuit on the channel. We use this to keep the
+ * circuit id from getting re-used while we have queued but not yet sent
+ * a destroy cell. */
+void
+channel_mark_circid_unusable(channel_t *chan, circid_t id)
+{
+ chan_circid_circuit_map_t search;
+ chan_circid_circuit_map_t *ent;
+
+ /* See if there's an entry there. That wouldn't be good. */
+ memset(&search, 0, sizeof(search));
+ search.chan = chan;
+ search.circ_id = id;
+ ent = HT_FIND(chan_circid_map, &chan_circid_map, &search);
+
+ if (ent && ent->circuit) {
+ /* we have a problem. */
+ log_warn(LD_BUG, "Tried to mark %u unusable on %p, but there was already "
+ "a circuit there.", (unsigned)id, chan);
+ } else if (ent) {
+ /* It's already marked. */
+ if (!ent->made_placeholder_at)
+ ent->made_placeholder_at = approx_time();
+ } else {
+ ent = tor_malloc_zero(sizeof(chan_circid_circuit_map_t));
+ ent->chan = chan;
+ ent->circ_id = id;
+ /* leave circuit at NULL. */
+ ent->made_placeholder_at = approx_time();
+ HT_INSERT(chan_circid_map, &chan_circid_map, ent);
+ }
+}
+
+/** Mark that a circuit id <b>id</b> can be used again on <b>chan</b>.
+ * We use this to re-enable the circuit ID after we've sent a destroy cell.
+ */
+void
+channel_mark_circid_usable(channel_t *chan, circid_t id)
+{
+ chan_circid_circuit_map_t search;
+ chan_circid_circuit_map_t *ent;
+
+ /* See if there's an entry there. That wouldn't be good. */
+ memset(&search, 0, sizeof(search));
+ search.chan = chan;
+ search.circ_id = id;
+ ent = HT_REMOVE(chan_circid_map, &chan_circid_map, &search);
+ if (ent && ent->circuit) {
+ log_warn(LD_BUG, "Tried to mark %u usable on %p, but there was already "
+ "a circuit there.", (unsigned)id, chan);
+ return;
+ }
+ if (_last_circid_chan_ent == ent)
+ _last_circid_chan_ent = NULL;
+ tor_free(ent);
+}
+
+/** Called to indicate that a DESTROY is pending on <b>chan</b> with
+ * circuit ID <b>id</b>, but hasn't been sent yet. */
+void
+channel_note_destroy_pending(channel_t *chan, circid_t id)
+{
+ circuit_t *circ = circuit_get_by_circid_channel_even_if_marked(id,chan);
+ if (circ) {
+ if (circ->n_chan == chan && circ->n_circ_id == id) {
+ circ->n_delete_pending = 1;
+ } else {
+ or_circuit_t *orcirc = TO_OR_CIRCUIT(circ);
+ if (orcirc->p_chan == chan && orcirc->p_circ_id == id) {
+ circ->p_delete_pending = 1;
+ }
+ }
+ return;
+ }
+ channel_mark_circid_unusable(chan, id);
+}
+
+/** Called to indicate that a DESTROY is no longer pending on <b>chan</b> with
+ * circuit ID <b>id</b> -- typically, because it has been sent. */
+MOCK_IMPL(void,
+channel_note_destroy_not_pending,(channel_t *chan, circid_t id))
+{
+ circuit_t *circ = circuit_get_by_circid_channel_even_if_marked(id,chan);
+ if (circ) {
+ if (circ->n_chan == chan && circ->n_circ_id == id) {
+ circ->n_delete_pending = 0;
+ } else {
+ or_circuit_t *orcirc = TO_OR_CIRCUIT(circ);
+ if (orcirc->p_chan == chan && orcirc->p_circ_id == id) {
+ circ->p_delete_pending = 0;
+ }
+ }
+ /* XXXX this shouldn't happen; log a bug here. */
+ return;
+ }
+ channel_mark_circid_usable(chan, id);
+}
+
+/** Set the p_conn field of a circuit <b>circ</b>, along
+ * with the corresponding circuit ID, and add the circuit as appropriate
+ * to the (chan,id)-\>circuit map. */
+void
+circuit_set_p_circid_chan(or_circuit_t *or_circ, circid_t id,
+ channel_t *chan)
+{
+ circuit_t *circ = TO_CIRCUIT(or_circ);
+ channel_t *old_chan = or_circ->p_chan;
+ circid_t old_id = or_circ->p_circ_id;
+
+ circuit_set_circid_chan_helper(circ, CELL_DIRECTION_IN, id, chan);
+
+ if (chan) {
+ chan->timestamp_last_had_circuits = approx_time();
+ }
+
+ if (circ->p_delete_pending && old_chan) {
+ channel_mark_circid_unusable(old_chan, old_id);
+ circ->p_delete_pending = 0;
+ }
+}
+
+/** Set the n_conn field of a circuit <b>circ</b>, along
+ * with the corresponding circuit ID, and add the circuit as appropriate
+ * to the (chan,id)-\>circuit map. */
+void
+circuit_set_n_circid_chan(circuit_t *circ, circid_t id,
+ channel_t *chan)
+{
+ channel_t *old_chan = circ->n_chan;
+ circid_t old_id = circ->n_circ_id;
+
+ circuit_set_circid_chan_helper(circ, CELL_DIRECTION_OUT, id, chan);
+
+ if (chan) {
+ chan->timestamp_last_had_circuits = approx_time();
+ }
+
+ if (circ->n_delete_pending && old_chan) {
+ channel_mark_circid_unusable(old_chan, old_id);
+ circ->n_delete_pending = 0;
+ }
+}
+
+/** Change the state of <b>circ</b> to <b>state</b>, adding it to or removing
+ * it from lists as appropriate. */
+void
+circuit_set_state(circuit_t *circ, uint8_t state)
+{
+ tor_assert(circ);
+ if (state == circ->state)
+ return;
+ if (PREDICT_UNLIKELY(!circuits_pending_chans))
+ circuits_pending_chans = smartlist_new();
+ if (PREDICT_UNLIKELY(!circuits_pending_other_guards))
+ circuits_pending_other_guards = smartlist_new();
+ if (circ->state == CIRCUIT_STATE_CHAN_WAIT) {
+ /* remove from waiting-circuit list. */
+ smartlist_remove(circuits_pending_chans, circ);
+ }
+ if (state == CIRCUIT_STATE_CHAN_WAIT) {
+ /* add to waiting-circuit list. */
+ smartlist_add(circuits_pending_chans, circ);
+ }
+ if (circ->state == CIRCUIT_STATE_GUARD_WAIT) {
+ smartlist_remove(circuits_pending_other_guards, circ);
+ }
+ if (state == CIRCUIT_STATE_GUARD_WAIT) {
+ smartlist_add(circuits_pending_other_guards, circ);
+ }
+ if (state == CIRCUIT_STATE_GUARD_WAIT || state == CIRCUIT_STATE_OPEN)
+ tor_assert(!circ->n_chan_create_cell);
+ circ->state = state;
+}
+
+/** Append to <b>out</b> all circuits in state CHAN_WAIT waiting for
+ * the given connection. */
+void
+circuit_get_all_pending_on_channel(smartlist_t *out, channel_t *chan)
+{
+ tor_assert(out);
+ tor_assert(chan);
+
+ if (!circuits_pending_chans)
+ return;
+
+ SMARTLIST_FOREACH_BEGIN(circuits_pending_chans, circuit_t *, circ) {
+ if (circ->marked_for_close)
+ continue;
+ if (!circ->n_hop)
+ continue;
+ tor_assert(circ->state == CIRCUIT_STATE_CHAN_WAIT);
+ if (tor_digest_is_zero(circ->n_hop->identity_digest)) {
+ /* Look at addr/port. This is an unkeyed connection. */
+ if (!channel_matches_extend_info(chan, circ->n_hop))
+ continue;
+ } else {
+ /* We expected a key. See if it's the right one. */
+ if (tor_memneq(chan->identity_digest,
+ circ->n_hop->identity_digest, DIGEST_LEN))
+ continue;
+ }
+ smartlist_add(out, circ);
+ } SMARTLIST_FOREACH_END(circ);
+}
+
+/** Return the number of circuits in state CHAN_WAIT, waiting for the given
+ * channel. */
+int
+circuit_count_pending_on_channel(channel_t *chan)
+{
+ int cnt;
+ smartlist_t *sl = smartlist_new();
+
+ tor_assert(chan);
+
+ circuit_get_all_pending_on_channel(sl, chan);
+ cnt = smartlist_len(sl);
+ smartlist_free(sl);
+ log_debug(LD_CIRC,"or_conn to %s, %d pending circs",
+ channel_get_canonical_remote_descr(chan),
+ cnt);
+ return cnt;
+}
+
+/** Remove <b>origin_circ</b> from the global list of origin circuits.
+ * Called when we are freeing a circuit.
+ */
+static void
+circuit_remove_from_origin_circuit_list(origin_circuit_t *origin_circ)
+{
+ int origin_idx = origin_circ->global_origin_circuit_list_idx;
+ if (origin_idx < 0)
+ return;
+ origin_circuit_t *c2;
+ tor_assert(origin_idx <= smartlist_len(global_origin_circuit_list));
+ c2 = smartlist_get(global_origin_circuit_list, origin_idx);
+ tor_assert(origin_circ == c2);
+ smartlist_del(global_origin_circuit_list, origin_idx);
+ if (origin_idx < smartlist_len(global_origin_circuit_list)) {
+ origin_circuit_t *replacement =
+ smartlist_get(global_origin_circuit_list, origin_idx);
+ replacement->global_origin_circuit_list_idx = origin_idx;
+ }
+ origin_circ->global_origin_circuit_list_idx = -1;
+}
+
+/** Add <b>origin_circ</b> to the global list of origin circuits. Called
+ * when creating the circuit. */
+static void
+circuit_add_to_origin_circuit_list(origin_circuit_t *origin_circ)
+{
+ tor_assert(origin_circ->global_origin_circuit_list_idx == -1);
+ smartlist_t *lst = circuit_get_global_origin_circuit_list();
+ smartlist_add(lst, origin_circ);
+ origin_circ->global_origin_circuit_list_idx = smartlist_len(lst) - 1;
+}
+
+/** Detach from the global circuit list, and deallocate, all
+ * circuits that have been marked for close.
+ */
+void
+circuit_close_all_marked(void)
+{
+ if (circuits_pending_close == NULL)
+ return;
+
+ smartlist_t *lst = circuit_get_global_list();
+ SMARTLIST_FOREACH_BEGIN(circuits_pending_close, circuit_t *, circ) {
+ tor_assert(circ->marked_for_close);
+
+ /* Remove it from the circuit list. */
+ int idx = circ->global_circuitlist_idx;
+ smartlist_del(lst, idx);
+ if (idx < smartlist_len(lst)) {
+ circuit_t *replacement = smartlist_get(lst, idx);
+ replacement->global_circuitlist_idx = idx;
+ }
+ circ->global_circuitlist_idx = -1;
+
+ /* Remove it from the origin circuit list, if appropriate. */
+ if (CIRCUIT_IS_ORIGIN(circ)) {
+ circuit_remove_from_origin_circuit_list(TO_ORIGIN_CIRCUIT(circ));
+ }
+
+ circuit_about_to_free(circ);
+ circuit_free(circ);
+ } SMARTLIST_FOREACH_END(circ);
+
+ smartlist_clear(circuits_pending_close);
+}
+
+/** Return a pointer to the global list of circuits. */
+MOCK_IMPL(smartlist_t *,
+circuit_get_global_list,(void))
+{
+ if (NULL == global_circuitlist)
+ global_circuitlist = smartlist_new();
+ return global_circuitlist;
+}
+
+/** Return a pointer to the global list of origin circuits. */
+smartlist_t *
+circuit_get_global_origin_circuit_list(void)
+{
+ if (NULL == global_origin_circuit_list)
+ global_origin_circuit_list = smartlist_new();
+ return global_origin_circuit_list;
+}
+
+/**
+ * Return true if we have any opened general-purpose 3 hop
+ * origin circuits.
+ *
+ * The result from this function is cached for use by
+ * circuit_any_opened_circuits_cached().
+ */
+int
+circuit_any_opened_circuits(void)
+{
+ SMARTLIST_FOREACH_BEGIN(circuit_get_global_origin_circuit_list(),
+ const origin_circuit_t *, next_circ) {
+ if (!TO_CIRCUIT(next_circ)->marked_for_close &&
+ next_circ->has_opened &&
+ TO_CIRCUIT(next_circ)->state == CIRCUIT_STATE_OPEN &&
+ TO_CIRCUIT(next_circ)->purpose != CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT &&
+ next_circ->build_state &&
+ next_circ->build_state->desired_path_len == DEFAULT_ROUTE_LEN) {
+ circuit_cache_opened_circuit_state(1);
+ return 1;
+ }
+ } SMARTLIST_FOREACH_END(next_circ);
+
+ circuit_cache_opened_circuit_state(0);
+ return 0;
+}
+
+/**
+ * Cache the "any circuits opened" state, as specified in param
+ * circuits_are_opened. This is a helper function to update
+ * the circuit opened status whenever we happen to look at the
+ * circuit list.
+ */
+void
+circuit_cache_opened_circuit_state(int circuits_are_opened)
+{
+ any_opened_circs_cached_val = circuits_are_opened;
+}
+
+/**
+ * Return true if there were any opened circuits since the last call to
+ * circuit_any_opened_circuits(), or since circuit_expire_building() last
+ * ran (it runs roughly once per second).
+ */
+int
+circuit_any_opened_circuits_cached(void)
+{
+ return any_opened_circs_cached_val;
+}
+
+/** Function to make circ-\>state human-readable */
+const char *
+circuit_state_to_string(int state)
+{
+ static char buf[64];
+ switch (state) {
+ case CIRCUIT_STATE_BUILDING: return "doing handshakes";
+ case CIRCUIT_STATE_ONIONSKIN_PENDING: return "processing the onion";
+ case CIRCUIT_STATE_CHAN_WAIT: return "connecting to server";
+ case CIRCUIT_STATE_GUARD_WAIT: return "waiting to see how other "
+ "guards perform";
+ case CIRCUIT_STATE_OPEN: return "open";
+ default:
+ log_warn(LD_BUG, "Unknown circuit state %d", state);
+ tor_snprintf(buf, sizeof(buf), "unknown state [%d]", state);
+ return buf;
+ }
+}
+
+/** Map a circuit purpose to a string suitable to be displayed to a
+ * controller. */
+const char *
+circuit_purpose_to_controller_string(uint8_t purpose)
+{
+ static char buf[32];
+ switch (purpose) {
+ case CIRCUIT_PURPOSE_OR:
+ case CIRCUIT_PURPOSE_INTRO_POINT:
+ case CIRCUIT_PURPOSE_REND_POINT_WAITING:
+ case CIRCUIT_PURPOSE_REND_ESTABLISHED:
+ return "SERVER"; /* A controller should never see these, actually. */
+
+ case CIRCUIT_PURPOSE_C_GENERAL:
+ return "GENERAL";
+
+ case CIRCUIT_PURPOSE_C_HSDIR_GET:
+ return "HS_CLIENT_HSDIR";
+
+ case CIRCUIT_PURPOSE_C_INTRODUCING:
+ case CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT:
+ case CIRCUIT_PURPOSE_C_INTRODUCE_ACKED:
+ return "HS_CLIENT_INTRO";
+
+ case CIRCUIT_PURPOSE_C_ESTABLISH_REND:
+ case CIRCUIT_PURPOSE_C_REND_READY:
+ case CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED:
+ case CIRCUIT_PURPOSE_C_REND_JOINED:
+ return "HS_CLIENT_REND";
+
+ case CIRCUIT_PURPOSE_S_HSDIR_POST:
+ return "HS_SERVICE_HSDIR";
+
+ case CIRCUIT_PURPOSE_S_ESTABLISH_INTRO:
+ case CIRCUIT_PURPOSE_S_INTRO:
+ return "HS_SERVICE_INTRO";
+
+ case CIRCUIT_PURPOSE_S_CONNECT_REND:
+ case CIRCUIT_PURPOSE_S_REND_JOINED:
+ return "HS_SERVICE_REND";
+
+ case CIRCUIT_PURPOSE_TESTING:
+ return "TESTING";
+ case CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT:
+ return "MEASURE_TIMEOUT";
+ case CIRCUIT_PURPOSE_CONTROLLER:
+ return "CONTROLLER";
+ case CIRCUIT_PURPOSE_PATH_BIAS_TESTING:
+ return "PATH_BIAS_TESTING";
+ case CIRCUIT_PURPOSE_HS_VANGUARDS:
+ return "HS_VANGUARDS";
+
+ default:
+ tor_snprintf(buf, sizeof(buf), "UNKNOWN_%d", (int)purpose);
+ return buf;
+ }
+}
+
+/** Return a string specifying the state of the hidden-service circuit
+ * purpose <b>purpose</b>, or NULL if <b>purpose</b> is not a
+ * hidden-service-related circuit purpose. */
+const char *
+circuit_purpose_to_controller_hs_state_string(uint8_t purpose)
+{
+ switch (purpose)
+ {
+ default:
+ log_fn(LOG_WARN, LD_BUG,
+ "Unrecognized circuit purpose: %d",
+ (int)purpose);
+ tor_fragile_assert();
+ /* fall through */
+
+ case CIRCUIT_PURPOSE_OR:
+ case CIRCUIT_PURPOSE_C_GENERAL:
+ case CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT:
+ case CIRCUIT_PURPOSE_TESTING:
+ case CIRCUIT_PURPOSE_CONTROLLER:
+ case CIRCUIT_PURPOSE_PATH_BIAS_TESTING:
+ case CIRCUIT_PURPOSE_HS_VANGUARDS:
+ return NULL;
+
+ case CIRCUIT_PURPOSE_INTRO_POINT:
+ return "OR_HSSI_ESTABLISHED";
+ case CIRCUIT_PURPOSE_REND_POINT_WAITING:
+ return "OR_HSCR_ESTABLISHED";
+ case CIRCUIT_PURPOSE_REND_ESTABLISHED:
+ return "OR_HS_R_JOINED";
+
+ case CIRCUIT_PURPOSE_C_HSDIR_GET:
+ case CIRCUIT_PURPOSE_C_INTRODUCING:
+ return "HSCI_CONNECTING";
+ case CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT:
+ return "HSCI_INTRO_SENT";
+ case CIRCUIT_PURPOSE_C_INTRODUCE_ACKED:
+ return "HSCI_DONE";
+
+ case CIRCUIT_PURPOSE_C_ESTABLISH_REND:
+ return "HSCR_CONNECTING";
+ case CIRCUIT_PURPOSE_C_REND_READY:
+ return "HSCR_ESTABLISHED_IDLE";
+ case CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED:
+ return "HSCR_ESTABLISHED_WAITING";
+ case CIRCUIT_PURPOSE_C_REND_JOINED:
+ return "HSCR_JOINED";
+
+ case CIRCUIT_PURPOSE_S_HSDIR_POST:
+ case CIRCUIT_PURPOSE_S_ESTABLISH_INTRO:
+ return "HSSI_CONNECTING";
+ case CIRCUIT_PURPOSE_S_INTRO:
+ return "HSSI_ESTABLISHED";
+
+ case CIRCUIT_PURPOSE_S_CONNECT_REND:
+ return "HSSR_CONNECTING";
+ case CIRCUIT_PURPOSE_S_REND_JOINED:
+ return "HSSR_JOINED";
+ }
+}
+
+/** Return a human-readable string for the circuit purpose <b>purpose</b>. */
+const char *
+circuit_purpose_to_string(uint8_t purpose)
+{
+ static char buf[32];
+
+ switch (purpose)
+ {
+ case CIRCUIT_PURPOSE_OR:
+ return "Circuit at relay";
+ case CIRCUIT_PURPOSE_INTRO_POINT:
+ return "Acting as intro point";
+ case CIRCUIT_PURPOSE_REND_POINT_WAITING:
+ return "Acting as rendezvous (pending)";
+ case CIRCUIT_PURPOSE_REND_ESTABLISHED:
+ return "Acting as rendezvous (established)";
+ case CIRCUIT_PURPOSE_C_GENERAL:
+ return "General-purpose client";
+ case CIRCUIT_PURPOSE_C_INTRODUCING:
+ return "Hidden service client: Connecting to intro point";
+ case CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT:
+ return "Hidden service client: Waiting for ack from intro point";
+ case CIRCUIT_PURPOSE_C_INTRODUCE_ACKED:
+ return "Hidden service client: Received ack from intro point";
+ case CIRCUIT_PURPOSE_C_ESTABLISH_REND:
+ return "Hidden service client: Establishing rendezvous point";
+ case CIRCUIT_PURPOSE_C_REND_READY:
+ return "Hidden service client: Pending rendezvous point";
+ case CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED:
+ return "Hidden service client: Pending rendezvous point (ack received)";
+ case CIRCUIT_PURPOSE_C_REND_JOINED:
+ return "Hidden service client: Active rendezvous point";
+ case CIRCUIT_PURPOSE_C_HSDIR_GET:
+ return "Hidden service client: Fetching HS descriptor";
+
+ case CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT:
+ return "Measuring circuit timeout";
+
+ case CIRCUIT_PURPOSE_S_ESTABLISH_INTRO:
+ return "Hidden service: Establishing introduction point";
+ case CIRCUIT_PURPOSE_S_INTRO:
+ return "Hidden service: Introduction point";
+ case CIRCUIT_PURPOSE_S_CONNECT_REND:
+ return "Hidden service: Connecting to rendezvous point";
+ case CIRCUIT_PURPOSE_S_REND_JOINED:
+ return "Hidden service: Active rendezvous point";
+ case CIRCUIT_PURPOSE_S_HSDIR_POST:
+ return "Hidden service: Uploading HS descriptor";
+
+ case CIRCUIT_PURPOSE_TESTING:
+ return "Testing circuit";
+
+ case CIRCUIT_PURPOSE_CONTROLLER:
+ return "Circuit made by controller";
+
+ case CIRCUIT_PURPOSE_PATH_BIAS_TESTING:
+ return "Path-bias testing circuit";
+
+ case CIRCUIT_PURPOSE_HS_VANGUARDS:
+ return "Hidden service: Pre-built vanguard circuit";
+
+ default:
+ tor_snprintf(buf, sizeof(buf), "UNKNOWN_%d", (int)purpose);
+ return buf;
+ }
+}
+
+/** Pick a reasonable package_window to start out for our circuits.
+ * Originally this was hard-coded at 1000, but now the consensus votes
+ * on the answer. See proposal 168. */
+int32_t
+circuit_initial_package_window(void)
+{
+ int32_t num = networkstatus_get_param(NULL, "circwindow", CIRCWINDOW_START,
+ CIRCWINDOW_START_MIN,
+ CIRCWINDOW_START_MAX);
+ /* If the consensus tells us a negative number, we'd assert. */
+ if (num < 0)
+ num = CIRCWINDOW_START;
+ return num;
+}
+
+/** Initialize the common elements in a circuit_t, and add it to the global
+ * list. */
+static void
+init_circuit_base(circuit_t *circ)
+{
+ tor_gettimeofday(&circ->timestamp_created);
+
+ // Gets reset when we send CREATE_FAST.
+ // circuit_expire_building() expects these to be equal
+ // until the orconn is built.
+ circ->timestamp_began = circ->timestamp_created;
+
+ circ->package_window = circuit_initial_package_window();
+ circ->deliver_window = CIRCWINDOW_START;
+ cell_queue_init(&circ->n_chan_cells);
+
+ smartlist_add(circuit_get_global_list(), circ);
+ circ->global_circuitlist_idx = smartlist_len(circuit_get_global_list()) - 1;
+}
+
+/** If we haven't yet decided on a good timeout value for circuit
+ * building, we close idle circuits aggressively so we can get more
+ * data points. These are the default, min, and max consensus values */
+#define DFLT_IDLE_TIMEOUT_WHILE_LEARNING (3*60)
+#define MIN_IDLE_TIMEOUT_WHILE_LEARNING (10)
+#define MAX_IDLE_TIMEOUT_WHILE_LEARNING (1000*60)
+
+/** Allocate space for a new circuit, initializing with <b>p_circ_id</b>
+ * and <b>p_conn</b>. Add it to the global circuit list.
+ */
+origin_circuit_t *
+origin_circuit_new(void)
+{
+ origin_circuit_t *circ;
+ /* never zero, since a global ID of 0 is treated specially by the
+ * controller */
+ static uint32_t n_circuits_allocated = 1;
+
+ circ = tor_malloc_zero(sizeof(origin_circuit_t));
+ circ->base_.magic = ORIGIN_CIRCUIT_MAGIC;
+
+ circ->next_stream_id = crypto_rand_int(1<<16);
+ circ->global_identifier = n_circuits_allocated++;
+ circ->remaining_relay_early_cells = MAX_RELAY_EARLY_CELLS_PER_CIRCUIT;
+ circ->remaining_relay_early_cells -= crypto_rand_int(2);
+
+ init_circuit_base(TO_CIRCUIT(circ));
+
+ /* Add to origin-list. */
+ circ->global_origin_circuit_list_idx = -1;
+ circuit_add_to_origin_circuit_list(circ);
+
+ circuit_build_times_update_last_circ(get_circuit_build_times_mutable());
+
+ if (! circuit_build_times_disabled(get_options()) &&
+ circuit_build_times_needs_circuits(get_circuit_build_times())) {
+ /* Circuits should be shorter lived if we need more of them
+ * for learning a good build timeout */
+ circ->circuit_idle_timeout =
+ networkstatus_get_param(NULL, "cbtlearntimeout",
+ DFLT_IDLE_TIMEOUT_WHILE_LEARNING,
+ MIN_IDLE_TIMEOUT_WHILE_LEARNING,
+ MAX_IDLE_TIMEOUT_WHILE_LEARNING);
+ } else {
+ // This should always be larger than the current port prediction time
+ // remaining, or else we'll end up with the case where a circuit times out
+ // and another one is built, effectively doubling the timeout window.
+ //
+ // We also randomize it by up to 5% more (ie 5% of 0 to 3600 seconds,
+ // depending on how much circuit prediction time is remaining) so that
+ // we don't close a bunch of unused circuits all at the same time.
+ int prediction_time_remaining =
+ predicted_ports_prediction_time_remaining(time(NULL));
+ circ->circuit_idle_timeout = prediction_time_remaining+1+
+ crypto_rand_int(1+prediction_time_remaining/20);
+
+ if (circ->circuit_idle_timeout <= 0) {
+ log_warn(LD_BUG,
+ "Circuit chose a negative idle timeout of %d based on "
+ "%d seconds of predictive building remaining.",
+ circ->circuit_idle_timeout,
+ prediction_time_remaining);
+ circ->circuit_idle_timeout =
+ networkstatus_get_param(NULL, "cbtlearntimeout",
+ DFLT_IDLE_TIMEOUT_WHILE_LEARNING,
+ MIN_IDLE_TIMEOUT_WHILE_LEARNING,
+ MAX_IDLE_TIMEOUT_WHILE_LEARNING);
+ }
+
+ log_info(LD_CIRC,
+ "Circuit %"PRIu32" chose an idle timeout of %d based on "
+ "%d seconds of predictive building remaining.",
+ (circ->global_identifier),
+ circ->circuit_idle_timeout,
+ prediction_time_remaining);
+ }
+
+ return circ;
+}
+
+/** Allocate a new or_circuit_t, connected to <b>p_chan</b> as
+ * <b>p_circ_id</b>. If <b>p_chan</b> is NULL, the circuit is unattached. */
+or_circuit_t *
+or_circuit_new(circid_t p_circ_id, channel_t *p_chan)
+{
+ /* CircIDs */
+ or_circuit_t *circ;
+
+ circ = tor_malloc_zero(sizeof(or_circuit_t));
+ circ->base_.magic = OR_CIRCUIT_MAGIC;
+
+ if (p_chan)
+ circuit_set_p_circid_chan(circ, p_circ_id, p_chan);
+
+ circ->remaining_relay_early_cells = MAX_RELAY_EARLY_CELLS_PER_CIRCUIT;
+ cell_queue_init(&circ->p_chan_cells);
+
+ init_circuit_base(TO_CIRCUIT(circ));
+
+ return circ;
+}
+
+/** Free all storage held in circ->testing_cell_stats */
+void
+circuit_clear_testing_cell_stats(circuit_t *circ)
+{
+ if (!circ || !circ->testing_cell_stats)
+ return;
+ SMARTLIST_FOREACH(circ->testing_cell_stats, testing_cell_stats_entry_t *,
+ ent, tor_free(ent));
+ smartlist_free(circ->testing_cell_stats);
+ circ->testing_cell_stats = NULL;
+}
+
+/** Deallocate space associated with circ.
+ */
+STATIC void
+circuit_free_(circuit_t *circ)
+{
+ circid_t n_circ_id = 0;
+ void *mem;
+ size_t memlen;
+ int should_free = 1;
+ if (!circ)
+ return;
+
+ /* We keep a copy of this so we can log its value before it gets unset. */
+ n_circ_id = circ->n_circ_id;
+
+ circuit_clear_testing_cell_stats(circ);
+
+ /* Cleanup circuit from anything HS v3 related. We also do this when the
+ * circuit is closed. This is to avoid any code path that free registered
+ * circuits without closing them before. This needs to be done before the
+ * hs identifier is freed. */
+ hs_circ_cleanup(circ);
+
+ if (CIRCUIT_IS_ORIGIN(circ)) {
+ origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ);
+ mem = ocirc;
+ memlen = sizeof(origin_circuit_t);
+ tor_assert(circ->magic == ORIGIN_CIRCUIT_MAGIC);
+
+ circuit_remove_from_origin_circuit_list(ocirc);
+
+ if (ocirc->half_streams) {
- SMARTLIST_FOREACH_BEGIN(ocirc->half_streams, half_edge_t*,
++ SMARTLIST_FOREACH_BEGIN(ocirc->half_streams, half_edge_t *,
+ half_conn) {
- tor_free(half_conn);
++ half_edge_free(half_conn);
+ } SMARTLIST_FOREACH_END(half_conn);
+ smartlist_free(ocirc->half_streams);
+ }
+
+ if (ocirc->build_state) {
+ extend_info_free(ocirc->build_state->chosen_exit);
+ circuit_free_cpath_node(ocirc->build_state->pending_final_cpath);
+ cpath_ref_decref(ocirc->build_state->service_pending_final_cpath_ref);
+ }
+ tor_free(ocirc->build_state);
+
+ /* Cancel before freeing, if we haven't already succeeded or failed. */
+ if (ocirc->guard_state) {
+ entry_guard_cancel(ô->guard_state);
+ }
+ circuit_guard_state_free(ocirc->guard_state);
+
+ circuit_clear_cpath(ocirc);
+
+ crypto_pk_free(ocirc->intro_key);
+ rend_data_free(ocirc->rend_data);
+
+ /* Finally, free the identifier of the circuit and nullify it so multiple
+ * cleanup will work. */
+ hs_ident_circuit_free(ocirc->hs_ident);
+ ocirc->hs_ident = NULL;
+
+ tor_free(ocirc->dest_address);
+ if (ocirc->socks_username) {
+ memwipe(ocirc->socks_username, 0x12, ocirc->socks_username_len);
+ tor_free(ocirc->socks_username);
+ }
+ if (ocirc->socks_password) {
+ memwipe(ocirc->socks_password, 0x06, ocirc->socks_password_len);
+ tor_free(ocirc->socks_password);
+ }
+ addr_policy_list_free(ocirc->prepend_policy);
+ } else {
+ or_circuit_t *ocirc = TO_OR_CIRCUIT(circ);
+ /* Remember cell statistics for this circuit before deallocating. */
+ if (get_options()->CellStatistics)
+ rep_hist_buffer_stats_add_circ(circ, time(NULL));
+ mem = ocirc;
+ memlen = sizeof(or_circuit_t);
+ tor_assert(circ->magic == OR_CIRCUIT_MAGIC);
+
+ should_free = (ocirc->workqueue_entry == NULL);
+
+ relay_crypto_clear(ô->crypto);
+
+ if (ocirc->rend_splice) {
+ or_circuit_t *other = ocirc->rend_splice;
+ tor_assert(other->base_.magic == OR_CIRCUIT_MAGIC);
+ other->rend_splice = NULL;
+ }
+
+ /* remove from map. */
+ circuit_set_p_circid_chan(ocirc, 0, NULL);
+
+ /* Clear cell queue _after_ removing it from the map. Otherwise our
+ * "active" checks will be violated. */
+ cell_queue_clear(ô->p_chan_cells);
+ }
+
+ extend_info_free(circ->n_hop);
+ tor_free(circ->n_chan_create_cell);
+
+ if (circ->global_circuitlist_idx != -1) {
+ int idx = circ->global_circuitlist_idx;
+ circuit_t *c2 = smartlist_get(global_circuitlist, idx);
+ tor_assert(c2 == circ);
+ smartlist_del(global_circuitlist, idx);
+ if (idx < smartlist_len(global_circuitlist)) {
+ c2 = smartlist_get(global_circuitlist, idx);
+ c2->global_circuitlist_idx = idx;
+ }
+ }
+
+ /* Remove from map. */
+ circuit_set_n_circid_chan(circ, 0, NULL);
+
+ /* Clear cell queue _after_ removing it from the map. Otherwise our
+ * "active" checks will be violated. */
+ cell_queue_clear(&circ->n_chan_cells);
+
+ log_info(LD_CIRC, "Circuit %u (id: %" PRIu32 ") has been freed.",
+ n_circ_id,
+ CIRCUIT_IS_ORIGIN(circ) ?
+ TO_ORIGIN_CIRCUIT(circ)->global_identifier : 0);
+
+ if (should_free) {
+ memwipe(mem, 0xAA, memlen); /* poison memory */
+ tor_free(mem);
+ } else {
+ /* If we made it here, this is an or_circuit_t that still has a pending
+ * cpuworker request which we weren't able to cancel. Instead, set up
+ * the magic value so that when the reply comes back, we'll know to discard
+ * the reply and free this structure.
+ */
+ memwipe(mem, 0xAA, memlen);
+ circ->magic = DEAD_CIRCUIT_MAGIC;
+ }
+}
+
+/** Deallocate the linked list circ-><b>cpath</b>, and remove the cpath from
+ * <b>circ</b>. */
+void
+circuit_clear_cpath(origin_circuit_t *circ)
+{
+ crypt_path_t *victim, *head, *cpath;
+
+ head = cpath = circ->cpath;
+
+ if (!cpath)
+ return;
+
+ /* it's a circular list, so we have to notice when we've
+ * gone through it once. */
+ while (cpath->next && cpath->next != head) {
+ victim = cpath;
+ cpath = victim->next;
+ circuit_free_cpath_node(victim);
+ }
+
+ circuit_free_cpath_node(cpath);
+
+ circ->cpath = NULL;
+}
+
+/** Release all storage held by circuits. */
+void
+circuit_free_all(void)
+{
+ smartlist_t *lst = circuit_get_global_list();
+
+ SMARTLIST_FOREACH_BEGIN(lst, circuit_t *, tmp) {
+ if (! CIRCUIT_IS_ORIGIN(tmp)) {
+ or_circuit_t *or_circ = TO_OR_CIRCUIT(tmp);
+ while (or_circ->resolving_streams) {
+ edge_connection_t *next_conn;
+ next_conn = or_circ->resolving_streams->next_stream;
+ connection_free_(TO_CONN(or_circ->resolving_streams));
+ or_circ->resolving_streams = next_conn;
+ }
+ }
+ tmp->global_circuitlist_idx = -1;
+ circuit_about_to_free_atexit(tmp);
+ circuit_free(tmp);
+ SMARTLIST_DEL_CURRENT(lst, tmp);
+ } SMARTLIST_FOREACH_END(tmp);
+
+ smartlist_free(lst);
+ global_circuitlist = NULL;
+
+ smartlist_free(global_origin_circuit_list);
+ global_origin_circuit_list = NULL;
+
+ smartlist_free(circuits_pending_chans);
+ circuits_pending_chans = NULL;
+
+ smartlist_free(circuits_pending_close);
+ circuits_pending_close = NULL;
+
+ smartlist_free(circuits_pending_other_guards);
+ circuits_pending_other_guards = NULL;
+
+ {
+ chan_circid_circuit_map_t **elt, **next, *c;
+ for (elt = HT_START(chan_circid_map, &chan_circid_map);
+ elt;
+ elt = next) {
+ c = *elt;
+ next = HT_NEXT_RMV(chan_circid_map, &chan_circid_map, elt);
+
+ tor_assert(c->circuit == NULL);
+ tor_free(c);
+ }
+ }
+ HT_CLEAR(chan_circid_map, &chan_circid_map);
+}
+
+/** Deallocate space associated with the cpath node <b>victim</b>. */
+static void
+circuit_free_cpath_node(crypt_path_t *victim)
+{
+ if (!victim)
+ return;
+
+ relay_crypto_clear(&victim->crypto);
+ onion_handshake_state_release(&victim->handshake_state);
+ crypto_dh_free(victim->rend_dh_handshake_state);
+ extend_info_free(victim->extend_info);
+
+ memwipe(victim, 0xBB, sizeof(crypt_path_t)); /* poison memory */
+ tor_free(victim);
+}
+
+/** Release a crypt_path_reference_t*, which may be NULL. */
+static void
+cpath_ref_decref(crypt_path_reference_t *cpath_ref)
+{
+ if (cpath_ref != NULL) {
+ if (--(cpath_ref->refcount) == 0) {
+ circuit_free_cpath_node(cpath_ref->cpath);
+ tor_free(cpath_ref);
+ }
+ }
+}
+
+/** A helper function for circuit_dump_by_conn() below. Log a bunch
+ * of information about circuit <b>circ</b>.
+ */
+static void
+circuit_dump_conn_details(int severity,
+ circuit_t *circ,
+ int conn_array_index,
+ const char *type,
+ circid_t this_circid,
+ circid_t other_circid)
+{
+ tor_log(severity, LD_CIRC, "Conn %d has %s circuit: circID %u "
+ "(other side %u), state %d (%s), born %ld:",
+ conn_array_index, type, (unsigned)this_circid, (unsigned)other_circid,
+ circ->state, circuit_state_to_string(circ->state),
+ (long)circ->timestamp_began.tv_sec);
+ if (CIRCUIT_IS_ORIGIN(circ)) { /* circ starts at this node */
+ circuit_log_path(severity, LD_CIRC, TO_ORIGIN_CIRCUIT(circ));
+ }
+}
+
+/** Log, at severity <b>severity</b>, information about each circuit
+ * that is connected to <b>conn</b>.
+ */
+void
+circuit_dump_by_conn(connection_t *conn, int severity)
+{
+ edge_connection_t *tmpconn;
+
+ SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) {
+ circid_t n_circ_id = circ->n_circ_id, p_circ_id = 0;
+
+ if (circ->marked_for_close) {
+ continue;
+ }
+
+ if (!CIRCUIT_IS_ORIGIN(circ)) {
+ p_circ_id = TO_OR_CIRCUIT(circ)->p_circ_id;
+ }
+
+ if (CIRCUIT_IS_ORIGIN(circ)) {
+ for (tmpconn=TO_ORIGIN_CIRCUIT(circ)->p_streams; tmpconn;
+ tmpconn=tmpconn->next_stream) {
+ if (TO_CONN(tmpconn) == conn) {
+ circuit_dump_conn_details(severity, circ, conn->conn_array_index,
+ "App-ward", p_circ_id, n_circ_id);
+ }
+ }
+ }
+
+ if (! CIRCUIT_IS_ORIGIN(circ)) {
+ for (tmpconn=TO_OR_CIRCUIT(circ)->n_streams; tmpconn;
+ tmpconn=tmpconn->next_stream) {
+ if (TO_CONN(tmpconn) == conn) {
+ circuit_dump_conn_details(severity, circ, conn->conn_array_index,
+ "Exit-ward", n_circ_id, p_circ_id);
+ }
+ }
+ }
+ }
+ SMARTLIST_FOREACH_END(circ);
+}
+
+/** Return the circuit whose global ID is <b>id</b>, or NULL if no
+ * such circuit exists. */
+origin_circuit_t *
+circuit_get_by_global_id(uint32_t id)
+{
+ SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) {
+ if (CIRCUIT_IS_ORIGIN(circ) &&
+ TO_ORIGIN_CIRCUIT(circ)->global_identifier == id) {
+ if (circ->marked_for_close)
+ return NULL;
+ else
+ return TO_ORIGIN_CIRCUIT(circ);
+ }
+ }
+ SMARTLIST_FOREACH_END(circ);
+ return NULL;
+}
+
+/** Return a circ such that:
+ * - circ-\>n_circ_id or circ-\>p_circ_id is equal to <b>circ_id</b>, and
+ * - circ is attached to <b>chan</b>, either as p_chan or n_chan.
+ * Return NULL if no such circuit exists.
+ *
+ * If <b>found_entry_out</b> is provided, set it to true if we have a
+ * placeholder entry for circid/chan, and leave it unset otherwise.
+ */
+static inline circuit_t *
+circuit_get_by_circid_channel_impl(circid_t circ_id, channel_t *chan,
+ int *found_entry_out)
+{
+ chan_circid_circuit_map_t search;
+ chan_circid_circuit_map_t *found;
+
+ if (_last_circid_chan_ent &&
+ circ_id == _last_circid_chan_ent->circ_id &&
+ chan == _last_circid_chan_ent->chan) {
+ found = _last_circid_chan_ent;
+ } else {
+ search.circ_id = circ_id;
+ search.chan = chan;
+ found = HT_FIND(chan_circid_map, &chan_circid_map, &search);
+ _last_circid_chan_ent = found;
+ }
+ if (found && found->circuit) {
+ log_debug(LD_CIRC,
+ "circuit_get_by_circid_channel_impl() returning circuit %p for"
+ " circ_id %u, channel ID %"PRIu64 " (%p)",
+ found->circuit, (unsigned)circ_id,
+ (chan->global_identifier), chan);
+ if (found_entry_out)
+ *found_entry_out = 1;
+ return found->circuit;
+ }
+
+ log_debug(LD_CIRC,
+ "circuit_get_by_circid_channel_impl() found %s for"
+ " circ_id %u, channel ID %"PRIu64 " (%p)",
+ found ? "placeholder" : "nothing",
+ (unsigned)circ_id,
+ (chan->global_identifier), chan);
+
+ if (found_entry_out)
+ *found_entry_out = found ? 1 : 0;
+
+ return NULL;
+ /* The rest of this checks for bugs. Disabled by default. */
+ /* We comment it out because coverity complains otherwise.
+ {
+ circuit_t *circ;
+ TOR_LIST_FOREACH(circ, &global_circuitlist, head) {
+ if (! CIRCUIT_IS_ORIGIN(circ)) {
+ or_circuit_t *or_circ = TO_OR_CIRCUIT(circ);
+ if (or_circ->p_chan == chan && or_circ->p_circ_id == circ_id) {
+ log_warn(LD_BUG,
+ "circuit matches p_chan, but not in hash table (Bug!)");
+ return circ;
+ }
+ }
+ if (circ->n_chan == chan && circ->n_circ_id == circ_id) {
+ log_warn(LD_BUG,
+ "circuit matches n_chan, but not in hash table (Bug!)");
+ return circ;
+ }
+ }
+ return NULL;
+ } */
+}
+
+/** Return a circ such that:
+ * - circ-\>n_circ_id or circ-\>p_circ_id is equal to <b>circ_id</b>, and
+ * - circ is attached to <b>chan</b>, either as p_chan or n_chan.
+ * - circ is not marked for close.
+ * Return NULL if no such circuit exists.
+ */
+circuit_t *
+circuit_get_by_circid_channel(circid_t circ_id, channel_t *chan)
+{
+ circuit_t *circ = circuit_get_by_circid_channel_impl(circ_id, chan, NULL);
+ if (!circ || circ->marked_for_close)
+ return NULL;
+ else
+ return circ;
+}
+
+/** Return a circ such that:
+ * - circ-\>n_circ_id or circ-\>p_circ_id is equal to <b>circ_id</b>, and
+ * - circ is attached to <b>chan</b>, either as p_chan or n_chan.
+ * Return NULL if no such circuit exists.
+ */
+circuit_t *
+circuit_get_by_circid_channel_even_if_marked(circid_t circ_id,
+ channel_t *chan)
+{
+ return circuit_get_by_circid_channel_impl(circ_id, chan, NULL);
+}
+
+/** Return true iff the circuit ID <b>circ_id</b> is currently used by a
+ * circuit, marked or not, on <b>chan</b>, or if the circ ID is reserved until
+ * a queued destroy cell can be sent.
+ *
+ * (Return 1 if the circuit is present, marked or not; Return 2
+ * if the circuit ID is pending a destroy.)
+ **/
+int
+circuit_id_in_use_on_channel(circid_t circ_id, channel_t *chan)
+{
+ int found = 0;
+ if (circuit_get_by_circid_channel_impl(circ_id, chan, &found) != NULL)
+ return 1;
+ if (found)
+ return 2;
+ return 0;
+}
+
+/** Helper for debugging 12184. Returns the time since which 'circ_id' has
+ * been marked unusable on 'chan'. */
+time_t
+circuit_id_when_marked_unusable_on_channel(circid_t circ_id, channel_t *chan)
+{
+ chan_circid_circuit_map_t search;
+ chan_circid_circuit_map_t *found;
+
+ memset(&search, 0, sizeof(search));
+ search.circ_id = circ_id;
+ search.chan = chan;
+
+ found = HT_FIND(chan_circid_map, &chan_circid_map, &search);
+
+ if (! found || found->circuit)
+ return 0;
+
+ return found->made_placeholder_at;
+}
+
+/** Return the circuit that a given edge connection is using. */
+circuit_t *
+circuit_get_by_edge_conn(edge_connection_t *conn)
+{
+ circuit_t *circ;
+
+ circ = conn->on_circuit;
+ tor_assert(!circ ||
+ (CIRCUIT_IS_ORIGIN(circ) ? circ->magic == ORIGIN_CIRCUIT_MAGIC
+ : circ->magic == OR_CIRCUIT_MAGIC));
+
+ return circ;
+}
+
+/** For each circuit that has <b>chan</b> as n_chan or p_chan, unlink the
+ * circuit from the chan,circid map, and mark it for close if it hasn't
+ * been marked already.
+ */
+void
+circuit_unlink_all_from_channel(channel_t *chan, int reason)
+{
+ smartlist_t *detached = smartlist_new();
+
+/* #define DEBUG_CIRCUIT_UNLINK_ALL */
+
+ channel_unlink_all_circuits(chan, detached);
+
+#ifdef DEBUG_CIRCUIT_UNLINK_ALL
+ {
+ smartlist_t *detached_2 = smartlist_new();
+ int mismatch = 0, badlen = 0;
+
+ SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) {
+ if (circ->n_chan == chan ||
+ (!CIRCUIT_IS_ORIGIN(circ) &&
+ TO_OR_CIRCUIT(circ)->p_chan == chan)) {
+ smartlist_add(detached_2, circ);
+ }
+ }
+ SMARTLIST_FOREACH_END(circ);
+
+ if (smartlist_len(detached) != smartlist_len(detached_2)) {
+ log_warn(LD_BUG, "List of detached circuits had the wrong length! "
+ "(got %d, should have gotten %d)",
+ (int)smartlist_len(detached),
+ (int)smartlist_len(detached_2));
+ badlen = 1;
+ }
+ smartlist_sort_pointers(detached);
+ smartlist_sort_pointers(detached_2);
+
+ SMARTLIST_FOREACH(detached, circuit_t *, c,
+ if (c != smartlist_get(detached_2, c_sl_idx))
+ mismatch = 1;
+ );
+
+ if (mismatch)
+ log_warn(LD_BUG, "Mismatch in list of detached circuits.");
+
+ if (badlen || mismatch) {
+ smartlist_free(detached);
+ detached = detached_2;
+ } else {
+ log_notice(LD_CIRC, "List of %d circuits was as expected.",
+ (int)smartlist_len(detached));
+ smartlist_free(detached_2);
+ }
+ }
+#endif /* defined(DEBUG_CIRCUIT_UNLINK_ALL) */
+
+ SMARTLIST_FOREACH_BEGIN(detached, circuit_t *, circ) {
+ int mark = 0;
+ if (circ->n_chan == chan) {
+
+ circuit_set_n_circid_chan(circ, 0, NULL);
+ mark = 1;
+
+ /* If we didn't request this closure, pass the remote
+ * bit to mark_for_close. */
+ if (chan->reason_for_closing != CHANNEL_CLOSE_REQUESTED)
+ reason |= END_CIRC_REASON_FLAG_REMOTE;
+ }
+ if (! CIRCUIT_IS_ORIGIN(circ)) {
+ or_circuit_t *or_circ = TO_OR_CIRCUIT(circ);
+ if (or_circ->p_chan == chan) {
+ circuit_set_p_circid_chan(or_circ, 0, NULL);
+ mark = 1;
+ }
+ }
+ if (!mark) {
+ log_warn(LD_BUG, "Circuit on detached list which I had no reason "
+ "to mark");
+ continue;
+ }
+ if (!circ->marked_for_close)
+ circuit_mark_for_close(circ, reason);
+ } SMARTLIST_FOREACH_END(circ);
+
+ smartlist_free(detached);
+}
+
+/** Return a circ such that
+ * - circ-\>rend_data-\>onion_address is equal to
+ * <b>rend_data</b>-\>onion_address,
+ * - circ-\>rend_data-\>rend_cookie is equal to
+ * <b>rend_data</b>-\>rend_cookie, and
+ * - circ-\>purpose is equal to CIRCUIT_PURPOSE_C_REND_READY.
+ *
+ * Return NULL if no such circuit exists.
+ */
+origin_circuit_t *
+circuit_get_ready_rend_circ_by_rend_data(const rend_data_t *rend_data)
+{
+ SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) {
+ if (!circ->marked_for_close &&
+ circ->purpose == CIRCUIT_PURPOSE_C_REND_READY) {
+ origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ);
+ if (ocirc->rend_data == NULL) {
+ continue;
+ }
+ if (!rend_cmp_service_ids(rend_data_get_address(rend_data),
+ rend_data_get_address(ocirc->rend_data)) &&
+ tor_memeq(ocirc->rend_data->rend_cookie,
+ rend_data->rend_cookie,
+ REND_COOKIE_LEN))
+ return ocirc;
+ }
+ }
+ SMARTLIST_FOREACH_END(circ);
+ return NULL;
+}
+
+/** Return the first service introduction circuit originating from the global
+ * circuit list after <b>start</b> or at the start of the list if <b>start</b>
+ * is NULL. Return NULL if no circuit is found.
+ *
+ * A service introduction point circuit has a purpose of either
+ * CIRCUIT_PURPOSE_S_ESTABLISH_INTRO or CIRCUIT_PURPOSE_S_INTRO. This does not
+ * return a circuit marked for close and its state must be open. */
+origin_circuit_t *
+circuit_get_next_service_intro_circ(origin_circuit_t *start)
+{
+ int idx = 0;
+ smartlist_t *lst = circuit_get_global_list();
+
+ if (start) {
+ idx = TO_CIRCUIT(start)->global_circuitlist_idx + 1;
+ }
+
+ for ( ; idx < smartlist_len(lst); ++idx) {
+ circuit_t *circ = smartlist_get(lst, idx);
+
+ /* Ignore a marked for close circuit or purpose not matching a service
+ * intro point or if the state is not open. */
+ if (circ->marked_for_close || circ->state != CIRCUIT_STATE_OPEN ||
+ (circ->purpose != CIRCUIT_PURPOSE_S_ESTABLISH_INTRO &&
+ circ->purpose != CIRCUIT_PURPOSE_S_INTRO)) {
+ continue;
+ }
+ /* The purposes we are looking for are only for origin circuits so the
+ * following is valid. */
+ return TO_ORIGIN_CIRCUIT(circ);
+ }
+ /* Not found. */
+ return NULL;
+}
+
+/** Return the first service rendezvous circuit originating from the global
+ * circuit list after <b>start</b> or at the start of the list if <b>start</b>
+ * is NULL. Return NULL if no circuit is found.
+ *
+ * A service rendezvous point circuit has a purpose of either
+ * CIRCUIT_PURPOSE_S_CONNECT_REND or CIRCUIT_PURPOSE_S_REND_JOINED. This does
+ * not return a circuit marked for close and its state must be open. */
+origin_circuit_t *
+circuit_get_next_service_rp_circ(origin_circuit_t *start)
+{
+ int idx = 0;
+ smartlist_t *lst = circuit_get_global_list();
+
+ if (start) {
+ idx = TO_CIRCUIT(start)->global_circuitlist_idx + 1;
+ }
+
+ for ( ; idx < smartlist_len(lst); ++idx) {
+ circuit_t *circ = smartlist_get(lst, idx);
+
+ /* Ignore a marked for close circuit or purpose not matching a service
+ * intro point or if the state is not open. */
+ if (circ->marked_for_close || circ->state != CIRCUIT_STATE_OPEN ||
+ (circ->purpose != CIRCUIT_PURPOSE_S_CONNECT_REND &&
+ circ->purpose != CIRCUIT_PURPOSE_S_REND_JOINED)) {
+ continue;
+ }
+ /* The purposes we are looking for are only for origin circuits so the
+ * following is valid. */
+ return TO_ORIGIN_CIRCUIT(circ);
+ }
+ /* Not found. */
+ return NULL;
+}
+
+/** Return the first circuit originating here in global_circuitlist after
+ * <b>start</b> whose purpose is <b>purpose</b>, and where <b>digest</b> (if
+ * set) matches the private key digest of the rend data associated with the
+ * circuit. Return NULL if no circuit is found. If <b>start</b> is NULL,
+ * begin at the start of the list.
+ */
+origin_circuit_t *
+circuit_get_next_by_pk_and_purpose(origin_circuit_t *start,
+ const uint8_t *digest, uint8_t purpose)
+{
+ int idx;
+ smartlist_t *lst = circuit_get_global_list();
+ tor_assert(CIRCUIT_PURPOSE_IS_ORIGIN(purpose));
+ if (start == NULL)
+ idx = 0;
+ else
+ idx = TO_CIRCUIT(start)->global_circuitlist_idx + 1;
+
+ for ( ; idx < smartlist_len(lst); ++idx) {
+ circuit_t *circ = smartlist_get(lst, idx);
+ origin_circuit_t *ocirc;
+
+ if (circ->marked_for_close)
+ continue;
+ if (circ->purpose != purpose)
+ continue;
+ /* At this point we should be able to get a valid origin circuit because
+ * the origin purpose we are looking for matches this circuit. */
+ if (BUG(!CIRCUIT_PURPOSE_IS_ORIGIN(circ->purpose))) {
+ break;
+ }
+ ocirc = TO_ORIGIN_CIRCUIT(circ);
+ if (!digest)
+ return ocirc;
+ if (rend_circuit_pk_digest_eq(ocirc, digest)) {
+ return ocirc;
+ }
+ }
+ return NULL;
+}
+
+/** We might cannibalize this circuit: Return true if its last hop can be used
+ * as a v3 rendezvous point. */
+static int
+circuit_can_be_cannibalized_for_v3_rp(const origin_circuit_t *circ)
+{
+ if (!circ->build_state) {
+ return 0;
+ }
+
+ extend_info_t *chosen_exit = circ->build_state->chosen_exit;
+ if (BUG(!chosen_exit)) {
+ return 0;
+ }
+
+ const node_t *rp_node = node_get_by_id(chosen_exit->identity_digest);
+ if (rp_node) {
+ if (node_supports_v3_rendezvous_point(rp_node)) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+/** We are trying to create a circuit of purpose <b>purpose</b> and we are
+ * looking for cannibalizable circuits. Return the circuit purpose we would be
+ * willing to cannibalize. */
+static uint8_t
+get_circuit_purpose_needed_to_cannibalize(uint8_t purpose)
+{
+ if (circuit_should_use_vanguards(purpose)) {
+ /* If we are using vanguards, then we should only cannibalize vanguard
+ * circuits so that we get the same path construction logic. */
+ return CIRCUIT_PURPOSE_HS_VANGUARDS;
+ } else {
+ /* If no vanguards are used just get a general circuit! */
+ return CIRCUIT_PURPOSE_C_GENERAL;
+ }
+}
+
+/** Return a circuit that is open, is CIRCUIT_PURPOSE_C_GENERAL,
+ * has a timestamp_dirty value of 0, has flags matching the CIRCLAUNCH_*
+ * flags in <b>flags</b>, and if info is defined, does not already use info
+ * as any of its hops; or NULL if no circuit fits this description.
+ *
+ * The <b>purpose</b> argument refers to the purpose of the circuit we want to
+ * create, not the purpose of the circuit we want to cannibalize.
+ *
+ * If !CIRCLAUNCH_NEED_UPTIME, prefer returning non-uptime circuits.
+ *
+ * To "cannibalize" a circuit means to extend it an extra hop, and use it
+ * for some other purpose than we had originally intended. We do this when
+ * we want to perform some low-bandwidth task at a specific relay, and we
+ * would like the circuit to complete as soon as possible. (If we were going
+ * to use a lot of bandwidth, we wouldn't want a circuit with an extra hop.
+ * If we didn't care about circuit completion latency, we would just build
+ * a new circuit.)
+ */
+origin_circuit_t *
+circuit_find_to_cannibalize(uint8_t purpose_to_produce, extend_info_t *info,
+ int flags)
+{
+ origin_circuit_t *best=NULL;
+ int need_uptime = (flags & CIRCLAUNCH_NEED_UPTIME) != 0;
+ int need_capacity = (flags & CIRCLAUNCH_NEED_CAPACITY) != 0;
+ int internal = (flags & CIRCLAUNCH_IS_INTERNAL) != 0;
+ const or_options_t *options = get_options();
+ /* We want the circuit we are trying to cannibalize to have this purpose */
+ int purpose_to_search_for;
+
+ /* Make sure we're not trying to create a onehop circ by
+ * cannibalization. */
+ tor_assert(!(flags & CIRCLAUNCH_ONEHOP_TUNNEL));
+
+ purpose_to_search_for = get_circuit_purpose_needed_to_cannibalize(
+ purpose_to_produce);
+
+ tor_assert_nonfatal(purpose_to_search_for == CIRCUIT_PURPOSE_C_GENERAL ||
+ purpose_to_search_for == CIRCUIT_PURPOSE_HS_VANGUARDS);
+
+ log_debug(LD_CIRC,
+ "Hunting for a circ to cannibalize: purpose %d, uptime %d, "
+ "capacity %d, internal %d",
+ purpose_to_produce, need_uptime, need_capacity, internal);
+
+ SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ_) {
+ if (CIRCUIT_IS_ORIGIN(circ_) &&
+ circ_->state == CIRCUIT_STATE_OPEN &&
+ !circ_->marked_for_close &&
+ circ_->purpose == purpose_to_search_for &&
+ !circ_->timestamp_dirty) {
+ origin_circuit_t *circ = TO_ORIGIN_CIRCUIT(circ_);
+
+ /* Only cannibalize from reasonable length circuits. If we
+ * want C_GENERAL, then only choose 3 hop circs. If we want
+ * HS_VANGUARDS, only choose 4 hop circs.
+ */
+ if (circ->build_state->desired_path_len !=
+ route_len_for_purpose(purpose_to_search_for, NULL)) {
+ goto next;
+ }
+
+ /* Ignore any circuits for which we can't use the Guard. It is possible
+ * that the Guard was removed from the samepled set after the circuit
+ * was created so avoid using it. */
+ if (!entry_guard_could_succeed(circ->guard_state)) {
+ goto next;
+ }
+
+ if ((!need_uptime || circ->build_state->need_uptime) &&
+ (!need_capacity || circ->build_state->need_capacity) &&
+ (internal == circ->build_state->is_internal) &&
+ !circ->unusable_for_new_conns &&
+ circ->remaining_relay_early_cells &&
+ !circ->build_state->onehop_tunnel &&
+ !circ->isolation_values_set) {
+ if (info) {
+ /* need to make sure we don't duplicate hops */
+ crypt_path_t *hop = circ->cpath;
+ const node_t *ri1 = node_get_by_id(info->identity_digest);
+ do {
+ const node_t *ri2;
+ if (tor_memeq(hop->extend_info->identity_digest,
+ info->identity_digest, DIGEST_LEN))
+ goto next;
+ if (ri1 &&
+ (ri2 = node_get_by_id(hop->extend_info->identity_digest))
+ && nodes_in_same_family(ri1, ri2))
+ goto next;
+ hop=hop->next;
+ } while (hop!=circ->cpath);
+ }
+ if (options->ExcludeNodes) {
+ /* Make sure no existing nodes in the circuit are excluded for
+ * general use. (This may be possible if StrictNodes is 0, and we
+ * thought we needed to use an otherwise excluded node for, say, a
+ * directory operation.) */
+ crypt_path_t *hop = circ->cpath;
+ do {
+ if (routerset_contains_extendinfo(options->ExcludeNodes,
+ hop->extend_info))
+ goto next;
+ hop = hop->next;
+ } while (hop != circ->cpath);
+ }
+
+ if ((flags & CIRCLAUNCH_IS_V3_RP) &&
+ !circuit_can_be_cannibalized_for_v3_rp(circ)) {
+ log_debug(LD_GENERAL, "Skipping uncannibalizable circuit for v3 "
+ "rendezvous point.");
+ goto next;
+ }
+
+ if (!best || (best->build_state->need_uptime && !need_uptime))
+ best = circ;
+ next: ;
+ }
+ }
+ }
+ SMARTLIST_FOREACH_END(circ_);
+ return best;
+}
+
+/**
+ * Check whether any of the origin circuits that are waiting to see if
+ * their guard is good enough to use can be upgraded to "ready". If so,
+ * return a new smartlist containing them. Otherwise return NULL.
+ */
+smartlist_t *
+circuit_find_circuits_to_upgrade_from_guard_wait(void)
+{
+ /* Only if some circuit is actually waiting on an upgrade should we
+ * run the algorithm. */
+ if (! circuits_pending_other_guards ||
+ smartlist_len(circuits_pending_other_guards)==0)
+ return NULL;
+ /* Only if we have some origin circuits should we run the algorithm. */
+ if (!global_origin_circuit_list)
+ return NULL;
+
+ /* Okay; we can pass our circuit list to entrynodes.c.*/
+ smartlist_t *result = smartlist_new();
+ int circuits_upgraded = entry_guards_upgrade_waiting_circuits(
+ get_guard_selection_info(),
+ global_origin_circuit_list,
+ result);
+ if (circuits_upgraded && smartlist_len(result)) {
+ return result;
+ } else {
+ smartlist_free(result);
+ return NULL;
+ }
+}
+
+/** Return the number of hops in circuit's path. If circ has no entries,
+ * or is NULL, returns 0. */
+int
+circuit_get_cpath_len(origin_circuit_t *circ)
+{
+ int n = 0;
+ if (circ && circ->cpath) {
+ crypt_path_t *cpath, *cpath_next = NULL;
+ for (cpath = circ->cpath; cpath_next != circ->cpath; cpath = cpath_next) {
+ cpath_next = cpath->next;
+ ++n;
+ }
+ }
+ return n;
+}
+
+/** Return the number of opened hops in circuit's path.
+ * If circ has no entries, or is NULL, returns 0. */
+int
+circuit_get_cpath_opened_len(const origin_circuit_t *circ)
+{
+ int n = 0;
+ if (circ && circ->cpath) {
+ crypt_path_t *cpath, *cpath_next = NULL;
+ for (cpath = circ->cpath;
+ cpath->state == CPATH_STATE_OPEN
+ && cpath_next != circ->cpath;
+ cpath = cpath_next) {
+ cpath_next = cpath->next;
+ ++n;
+ }
+ }
+ return n;
+}
+
+/** Return the <b>hopnum</b>th hop in <b>circ</b>->cpath, or NULL if there
+ * aren't that many hops in the list. <b>hopnum</b> starts at 1.
+ * Returns NULL if <b>hopnum</b> is 0 or negative. */
+crypt_path_t *
+circuit_get_cpath_hop(origin_circuit_t *circ, int hopnum)
+{
+ if (circ && circ->cpath && hopnum > 0) {
+ crypt_path_t *cpath, *cpath_next = NULL;
+ for (cpath = circ->cpath; cpath_next != circ->cpath; cpath = cpath_next) {
+ cpath_next = cpath->next;
+ if (--hopnum <= 0)
+ return cpath;
+ }
+ }
+ return NULL;
+}
+
+/** Go through the circuitlist; mark-for-close each circuit that starts
+ * at us but has not yet been used. */
+void
+circuit_mark_all_unused_circs(void)
+{
+ SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) {
+ if (CIRCUIT_IS_ORIGIN(circ) &&
+ !circ->marked_for_close &&
+ !circ->timestamp_dirty)
+ circuit_mark_for_close(circ, END_CIRC_REASON_FINISHED);
+ }
+ SMARTLIST_FOREACH_END(circ);
+}
+
+/** Go through the circuitlist; for each circuit that starts at us
+ * and is dirty, frob its timestamp_dirty so we won't use it for any
+ * new streams.
+ *
+ * This is useful for letting the user change pseudonyms, so new
+ * streams will not be linkable to old streams.
+ */
+void
+circuit_mark_all_dirty_circs_as_unusable(void)
+{
+ SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) {
+ if (CIRCUIT_IS_ORIGIN(circ) &&
+ !circ->marked_for_close &&
+ circ->timestamp_dirty) {
+ mark_circuit_unusable_for_new_conns(TO_ORIGIN_CIRCUIT(circ));
+ }
+ }
+ SMARTLIST_FOREACH_END(circ);
+}
+
+/** Mark <b>circ</b> to be closed next time we call
+ * circuit_close_all_marked(). Do any cleanup needed:
+ * - If state is onionskin_pending, remove circ from the onion_pending
+ * list.
+ * - If circ isn't open yet: call circuit_build_failed() if we're
+ * the origin.
+ * - If purpose is C_INTRODUCE_ACK_WAIT, report the intro point
+ * failure we just had to the hidden service client module.
+ * - If purpose is C_INTRODUCING and <b>reason</b> isn't TIMEOUT,
+ * report to the hidden service client module that the intro point
+ * we just tried may be unreachable.
+ * - Send appropriate destroys and edge_destroys for conns and
+ * streams attached to circ.
+ * - If circ->rend_splice is set (we are the midpoint of a joined
+ * rendezvous stream), then mark the other circuit to close as well.
+ */
+MOCK_IMPL(void,
+circuit_mark_for_close_, (circuit_t *circ, int reason, int line,
+ const char *file))
+{
+ int orig_reason = reason; /* Passed to the controller */
+ assert_circuit_ok(circ);
+ tor_assert(line);
+ tor_assert(file);
+
+ if (circ->marked_for_close) {
+ log_warn(LD_BUG,
+ "Duplicate call to circuit_mark_for_close at %s:%d"
+ " (first at %s:%d)", file, line,
+ circ->marked_for_close_file, circ->marked_for_close);
+ return;
+ }
+ if (reason == END_CIRC_AT_ORIGIN) {
+ if (!CIRCUIT_IS_ORIGIN(circ)) {
+ log_warn(LD_BUG, "Specified 'at-origin' non-reason for ending circuit, "
+ "but circuit was not at origin. (called %s:%d, purpose=%d)",
+ file, line, circ->purpose);
+ }
+ reason = END_CIRC_REASON_NONE;
+ }
+
+ if (CIRCUIT_IS_ORIGIN(circ)) {
+ if (pathbias_check_close(TO_ORIGIN_CIRCUIT(circ), reason) == -1) {
+ /* Don't close it yet, we need to test it first */
+ return;
+ }
+
+ /* We don't send reasons when closing circuits at the origin. */
+ reason = END_CIRC_REASON_NONE;
+ }
+
+ if (reason & END_CIRC_REASON_FLAG_REMOTE)
+ reason &= ~END_CIRC_REASON_FLAG_REMOTE;
+
+ if (reason < END_CIRC_REASON_MIN_ || reason > END_CIRC_REASON_MAX_) {
+ if (!(orig_reason & END_CIRC_REASON_FLAG_REMOTE))
+ log_warn(LD_BUG, "Reason %d out of range at %s:%d", reason, file, line);
+ reason = END_CIRC_REASON_NONE;
+ }
+
+ circ->marked_for_close = line;
+ circ->marked_for_close_file = file;
+ circ->marked_for_close_reason = reason;
+ circ->marked_for_close_orig_reason = orig_reason;
+
+ if (!CIRCUIT_IS_ORIGIN(circ)) {
+ or_circuit_t *or_circ = TO_OR_CIRCUIT(circ);
+ if (or_circ->rend_splice) {
+ if (!or_circ->rend_splice->base_.marked_for_close) {
+ /* do this after marking this circuit, to avoid infinite recursion. */
+ circuit_mark_for_close(TO_CIRCUIT(or_circ->rend_splice), reason);
+ }
+ or_circ->rend_splice = NULL;
+ }
+ }
+
+ /* Notify the HS subsystem that this circuit is closing. */
+ hs_circ_cleanup(circ);
+
+ if (circuits_pending_close == NULL)
+ circuits_pending_close = smartlist_new();
+
+ smartlist_add(circuits_pending_close, circ);
+ mainloop_schedule_postloop_cleanup();
+
+ log_info(LD_GENERAL, "Circuit %u (id: %" PRIu32 ") marked for close at "
+ "%s:%d (orig reason: %d, new reason: %d)",
+ circ->n_circ_id,
+ CIRCUIT_IS_ORIGIN(circ) ?
+ TO_ORIGIN_CIRCUIT(circ)->global_identifier : 0,
+ file, line, orig_reason, reason);
+}
+
+/** Called immediately before freeing a marked circuit <b>circ</b> from
+ * circuit_free_all() while shutting down Tor; this is a safe-at-shutdown
+ * version of circuit_about_to_free(). It's important that it at least
+ * do circuitmux_detach_circuit() when appropriate.
+ */
+static void
+circuit_about_to_free_atexit(circuit_t *circ)
+{
+
+ if (circ->n_chan) {
+ circuit_clear_cell_queue(circ, circ->n_chan);
+ circuitmux_detach_circuit(circ->n_chan->cmux, circ);
+ circuit_set_n_circid_chan(circ, 0, NULL);
+ }
+
+ if (! CIRCUIT_IS_ORIGIN(circ)) {
+ or_circuit_t *or_circ = TO_OR_CIRCUIT(circ);
+
+ if (or_circ->p_chan) {
+ circuit_clear_cell_queue(circ, or_circ->p_chan);
+ circuitmux_detach_circuit(or_circ->p_chan->cmux, circ);
+ circuit_set_p_circid_chan(or_circ, 0, NULL);
+ }
+ }
+}
+
+/** Called immediately before freeing a marked circuit <b>circ</b>.
+ * Disconnects the circuit from other data structures, launches events
+ * as appropriate, and performs other housekeeping.
+ */
+static void
+circuit_about_to_free(circuit_t *circ)
+{
+
+ int reason = circ->marked_for_close_reason;
+ int orig_reason = circ->marked_for_close_orig_reason;
+
+ if (circ->state == CIRCUIT_STATE_ONIONSKIN_PENDING) {
+ onion_pending_remove(TO_OR_CIRCUIT(circ));
+ }
+ /* If the circuit ever became OPEN, we sent it to the reputation history
+ * module then. If it isn't OPEN, we send it there now to remember which
+ * links worked and which didn't.
+ */
+ if (circ->state != CIRCUIT_STATE_OPEN &&
+ circ->state != CIRCUIT_STATE_GUARD_WAIT) {
+ if (CIRCUIT_IS_ORIGIN(circ)) {
+ origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ);
+ circuit_build_failed(ocirc); /* take actions if necessary */
+ }
+ }
+ if (circ->state == CIRCUIT_STATE_CHAN_WAIT) {
+ if (circuits_pending_chans)
+ smartlist_remove(circuits_pending_chans, circ);
+ }
+ if (circuits_pending_other_guards) {
+ smartlist_remove(circuits_pending_other_guards, circ);
+ }
+ if (CIRCUIT_IS_ORIGIN(circ)) {
+ control_event_circuit_status(TO_ORIGIN_CIRCUIT(circ),
+ (circ->state == CIRCUIT_STATE_OPEN ||
+ circ->state == CIRCUIT_STATE_GUARD_WAIT) ?
+ CIRC_EVENT_CLOSED:CIRC_EVENT_FAILED,
+ orig_reason);
+ }
+
+ if (circ->purpose == CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT) {
+ origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ);
+ int timed_out = (reason == END_CIRC_REASON_TIMEOUT);
+ tor_assert(circ->state == CIRCUIT_STATE_OPEN);
+ tor_assert(ocirc->build_state->chosen_exit);
+ if (orig_reason != END_CIRC_REASON_IP_NOW_REDUNDANT &&
+ ocirc->rend_data) {
+ /* treat this like getting a nack from it */
+ log_info(LD_REND, "Failed intro circ %s to %s (awaiting ack). %s",
+ safe_str_client(rend_data_get_address(ocirc->rend_data)),
+ safe_str_client(build_state_get_exit_nickname(ocirc->build_state)),
+ timed_out ? "Recording timeout." : "Removing from descriptor.");
+ rend_client_report_intro_point_failure(ocirc->build_state->chosen_exit,
+ ocirc->rend_data,
+ timed_out ?
+ INTRO_POINT_FAILURE_TIMEOUT :
+ INTRO_POINT_FAILURE_GENERIC);
+ }
+ } else if (circ->purpose == CIRCUIT_PURPOSE_C_INTRODUCING &&
+ reason != END_CIRC_REASON_TIMEOUT) {
+ origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ);
+ if (ocirc->build_state->chosen_exit && ocirc->rend_data) {
+ if (orig_reason != END_CIRC_REASON_IP_NOW_REDUNDANT &&
+ ocirc->rend_data) {
+ log_info(LD_REND, "Failed intro circ %s to %s "
+ "(building circuit to intro point). "
+ "Marking intro point as possibly unreachable.",
+ safe_str_client(rend_data_get_address(ocirc->rend_data)),
+ safe_str_client(build_state_get_exit_nickname(
+ ocirc->build_state)));
+ rend_client_report_intro_point_failure(ocirc->build_state->chosen_exit,
+ ocirc->rend_data,
+ INTRO_POINT_FAILURE_UNREACHABLE);
+ }
+ }
+ }
+
+ if (circ->n_chan) {
+ circuit_clear_cell_queue(circ, circ->n_chan);
+ /* Only send destroy if the channel isn't closing anyway */
+ if (!CHANNEL_CONDEMNED(circ->n_chan)) {
+ channel_send_destroy(circ->n_circ_id, circ->n_chan, reason);
+ }
+ circuitmux_detach_circuit(circ->n_chan->cmux, circ);
+ circuit_set_n_circid_chan(circ, 0, NULL);
+ }
+
+ if (! CIRCUIT_IS_ORIGIN(circ)) {
+ or_circuit_t *or_circ = TO_OR_CIRCUIT(circ);
+ edge_connection_t *conn;
+ for (conn=or_circ->n_streams; conn; conn=conn->next_stream)
+ connection_edge_destroy(or_circ->p_circ_id, conn);
+ or_circ->n_streams = NULL;
+
+ while (or_circ->resolving_streams) {
+ conn = or_circ->resolving_streams;
+ or_circ->resolving_streams = conn->next_stream;
+ if (!conn->base_.marked_for_close) {
+ /* The client will see a DESTROY, and infer that the connections
+ * are closing because the circuit is getting torn down. No need
+ * to send an end cell. */
+ conn->edge_has_sent_end = 1;
+ conn->end_reason = END_STREAM_REASON_DESTROY;
+ conn->end_reason |= END_STREAM_REASON_FLAG_ALREADY_SENT_CLOSED;
+ connection_mark_for_close(TO_CONN(conn));
+ }
+ conn->on_circuit = NULL;
+ }
+
+ if (or_circ->p_chan) {
+ circuit_clear_cell_queue(circ, or_circ->p_chan);
+ /* Only send destroy if the channel isn't closing anyway */
+ if (!CHANNEL_CONDEMNED(or_circ->p_chan)) {
+ channel_send_destroy(or_circ->p_circ_id, or_circ->p_chan, reason);
+ }
+ circuitmux_detach_circuit(or_circ->p_chan->cmux, circ);
+ circuit_set_p_circid_chan(or_circ, 0, NULL);
+ }
+ } else {
+ origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ);
+ edge_connection_t *conn;
+ for (conn=ocirc->p_streams; conn; conn=conn->next_stream)
+ connection_edge_destroy(circ->n_circ_id, conn);
+ ocirc->p_streams = NULL;
+ }
+}
+
+/** Given a marked circuit <b>circ</b>, aggressively free its cell queues to
+ * recover memory. */
+static void
+marked_circuit_free_cells(circuit_t *circ)
+{
+ if (!circ->marked_for_close) {
+ log_warn(LD_BUG, "Called on non-marked circuit");
+ return;
+ }
+ cell_queue_clear(&circ->n_chan_cells);
+ if (circ->n_mux)
+ circuitmux_clear_num_cells(circ->n_mux, circ);
+ if (! CIRCUIT_IS_ORIGIN(circ)) {
+ or_circuit_t *orcirc = TO_OR_CIRCUIT(circ);
+ cell_queue_clear(&orcirc->p_chan_cells);
+ if (orcirc->p_mux)
+ circuitmux_clear_num_cells(orcirc->p_mux, circ);
+ }
+}
+
+static size_t
+single_conn_free_bytes(connection_t *conn)
+{
+ size_t result = 0;
+ if (conn->inbuf) {
+ result += buf_allocation(conn->inbuf);
+ buf_clear(conn->inbuf);
+ }
+ if (conn->outbuf) {
+ result += buf_allocation(conn->outbuf);
+ buf_clear(conn->outbuf);
+ conn->outbuf_flushlen = 0;
+ }
+ if (conn->type == CONN_TYPE_DIR) {
+ dir_connection_t *dir_conn = TO_DIR_CONN(conn);
+ if (dir_conn->compress_state) {
+ result += tor_compress_state_size(dir_conn->compress_state);
+ tor_compress_free(dir_conn->compress_state);
+ dir_conn->compress_state = NULL;
+ }
+ }
+ return result;
+}
+
+/** Aggressively free buffer contents on all the buffers of all streams in the
+ * list starting at <b>stream</b>. Return the number of bytes recovered. */
+static size_t
+marked_circuit_streams_free_bytes(edge_connection_t *stream)
+{
+ size_t result = 0;
+ for ( ; stream; stream = stream->next_stream) {
+ connection_t *conn = TO_CONN(stream);
+ result += single_conn_free_bytes(conn);
+ if (conn->linked_conn) {
+ result += single_conn_free_bytes(conn->linked_conn);
+ }
+ }
+ return result;
+}
+
+/** Aggressively free buffer contents on all the buffers of all streams on
+ * circuit <b>c</b>. Return the number of bytes recovered. */
+static size_t
+marked_circuit_free_stream_bytes(circuit_t *c)
+{
+ if (CIRCUIT_IS_ORIGIN(c)) {
+ return marked_circuit_streams_free_bytes(TO_ORIGIN_CIRCUIT(c)->p_streams);
+ } else {
+ return marked_circuit_streams_free_bytes(TO_OR_CIRCUIT(c)->n_streams);
+ }
+}
+
+/** Return the number of cells used by the circuit <b>c</b>'s cell queues. */
+STATIC size_t
+n_cells_in_circ_queues(const circuit_t *c)
+{
+ size_t n = c->n_chan_cells.n;
+ if (! CIRCUIT_IS_ORIGIN(c)) {
+ circuit_t *cc = (circuit_t *) c;
+ n += TO_OR_CIRCUIT(cc)->p_chan_cells.n;
+ }
+ return n;
+}
+
++/** Return the number of bytes allocated for <b>c</c>'s half-open streams. */
++static size_t
++circuit_alloc_in_half_streams(const circuit_t *c)
++{
++ if (! CIRCUIT_IS_ORIGIN(c)) {
++ return 0;
++ }
++ const origin_circuit_t *ocirc = CONST_TO_ORIGIN_CIRCUIT(c);
++ if (ocirc->half_streams)
++ return smartlist_len(ocirc->half_streams) * sizeof(half_edge_t);
++ else
++ return 0;
++}
++
+/**
+ * Return the age of the oldest cell queued on <b>c</b>, in timestamp units.
+ * Return 0 if there are no cells queued on c. Requires that <b>now</b> be
+ * the current coarse timestamp.
+ *
+ * This function will return incorrect results if the oldest cell queued on
+ * the circuit is older than about 2**32 msec (about 49 days) old.
+ */
+STATIC uint32_t
+circuit_max_queued_cell_age(const circuit_t *c, uint32_t now)
+{
+ uint32_t age = 0;
+ packed_cell_t *cell;
+
+ if (NULL != (cell = TOR_SIMPLEQ_FIRST(&c->n_chan_cells.head)))
+ age = now - cell->inserted_timestamp;
+
+ if (! CIRCUIT_IS_ORIGIN(c)) {
+ const or_circuit_t *orcirc = CONST_TO_OR_CIRCUIT(c);
+ if (NULL != (cell = TOR_SIMPLEQ_FIRST(&orcirc->p_chan_cells.head))) {
+ uint32_t age2 = now - cell->inserted_timestamp;
+ if (age2 > age)
+ return age2;
+ }
+ }
+ return age;
+}
+
+/** Return the age of the oldest buffer chunk on <b>conn</b>, where age is
+ * taken in timestamp units before the time <b>now</b>. If the connection has
+ * no data, treat it as having age zero.
+ **/
+static uint32_t
+conn_get_buffer_age(const connection_t *conn, uint32_t now_ts)
+{
+ uint32_t age = 0, age2;
+ if (conn->outbuf) {
+ age2 = buf_get_oldest_chunk_timestamp(conn->outbuf, now_ts);
+ if (age2 > age)
+ age = age2;
+ }
+ if (conn->inbuf) {
+ age2 = buf_get_oldest_chunk_timestamp(conn->inbuf, now_ts);
+ if (age2 > age)
+ age = age2;
+ }
+ return age;
+}
+
+/** Return the age in timestamp units of the oldest buffer chunk on any stream
+ * in the linked list <b>stream</b>, where age is taken in timestamp units
+ * before the timestamp <b>now</b>. */
+static uint32_t
+circuit_get_streams_max_data_age(const edge_connection_t *stream, uint32_t now)
+{
+ uint32_t age = 0, age2;
+ for (; stream; stream = stream->next_stream) {
+ const connection_t *conn = TO_CONN(stream);
+ age2 = conn_get_buffer_age(conn, now);
+ if (age2 > age)
+ age = age2;
+ if (conn->linked_conn) {
+ age2 = conn_get_buffer_age(conn->linked_conn, now);
+ if (age2 > age)
+ age = age2;
+ }
+ }
+ return age;
+}
+
+/** Return the age in timestamp units of the oldest buffer chunk on any stream
+ * attached to the circuit <b>c</b>, where age is taken before the timestamp
+ * <b>now</b>. */
+STATIC uint32_t
+circuit_max_queued_data_age(const circuit_t *c, uint32_t now)
+{
+ if (CIRCUIT_IS_ORIGIN(c)) {
+ return circuit_get_streams_max_data_age(
+ CONST_TO_ORIGIN_CIRCUIT(c)->p_streams, now);
+ } else {
+ return circuit_get_streams_max_data_age(
+ CONST_TO_OR_CIRCUIT(c)->n_streams, now);
+ }
+}
+
+/** Return the age of the oldest cell or stream buffer chunk on the circuit
+ * <b>c</b>, where age is taken in timestamp units before the timestamp
+ * <b>now</b> */
+STATIC uint32_t
+circuit_max_queued_item_age(const circuit_t *c, uint32_t now)
+{
+ uint32_t cell_age = circuit_max_queued_cell_age(c, now);
+ uint32_t data_age = circuit_max_queued_data_age(c, now);
+ if (cell_age > data_age)
+ return cell_age;
+ else
+ return data_age;
+}
+
+/** Helper to sort a list of circuit_t by age of oldest item, in descending
+ * order. */
+static int
+circuits_compare_by_oldest_queued_item_(const void **a_, const void **b_)
+{
+ const circuit_t *a = *a_;
+ const circuit_t *b = *b_;
+ uint32_t age_a = a->age_tmp;
+ uint32_t age_b = b->age_tmp;
+
+ if (age_a < age_b)
+ return 1;
+ else if (age_a == age_b)
+ return 0;
+ else
+ return -1;
+}
+
+static uint32_t now_ts_for_buf_cmp;
+
+/** Helper to sort a list of circuit_t by age of oldest item, in descending
+ * order. */
+static int
+conns_compare_by_buffer_age_(const void **a_, const void **b_)
+{
+ const connection_t *a = *a_;
+ const connection_t *b = *b_;
+ time_t age_a = conn_get_buffer_age(a, now_ts_for_buf_cmp);
+ time_t age_b = conn_get_buffer_age(b, now_ts_for_buf_cmp);
+
+ if (age_a < age_b)
+ return 1;
+ else if (age_a == age_b)
+ return 0;
+ else
+ return -1;
+}
+
+#define FRACTION_OF_DATA_TO_RETAIN_ON_OOM 0.90
+
+/** We're out of memory for cells, having allocated <b>current_allocation</b>
+ * bytes' worth. Kill the 'worst' circuits until we're under
+ * FRACTION_OF_DATA_TO_RETAIN_ON_OOM of our maximum usage. */
+void
+circuits_handle_oom(size_t current_allocation)
+{
+ smartlist_t *circlist;
+ smartlist_t *connection_array = get_connection_array();
+ int conn_idx;
+ size_t mem_to_recover;
+ size_t mem_recovered=0;
+ int n_circuits_killed=0;
+ int n_dirconns_killed=0;
+ uint32_t now_ts;
+ log_notice(LD_GENERAL, "We're low on memory (cell queues total alloc:"
+ " %"TOR_PRIuSZ" buffer total alloc: %" TOR_PRIuSZ ","
+ " tor compress total alloc: %" TOR_PRIuSZ
+ " (zlib: %" TOR_PRIuSZ ", zstd: %" TOR_PRIuSZ ","
+ " lzma: %" TOR_PRIuSZ "),"
+ " rendezvous cache total alloc: %" TOR_PRIuSZ "). Killing"
+ " circuits withover-long queues. (This behavior is controlled by"
+ " MaxMemInQueues.)",
+ cell_queues_get_total_allocation(),
+ buf_get_total_allocation(),
+ tor_compress_get_total_allocation(),
+ tor_zlib_get_total_allocation(),
+ tor_zstd_get_total_allocation(),
+ tor_lzma_get_total_allocation(),
+ rend_cache_get_total_allocation());
+
+ {
+ size_t mem_target = (size_t)(get_options()->MaxMemInQueues *
+ FRACTION_OF_DATA_TO_RETAIN_ON_OOM);
+ if (current_allocation <= mem_target)
+ return;
+ mem_to_recover = current_allocation - mem_target;
+ }
+
+ now_ts = monotime_coarse_get_stamp();
+
+ circlist = circuit_get_global_list();
+ SMARTLIST_FOREACH_BEGIN(circlist, circuit_t *, circ) {
+ circ->age_tmp = circuit_max_queued_item_age(circ, now_ts);
+ } SMARTLIST_FOREACH_END(circ);
+
+ /* This is O(n log n); there are faster algorithms we could use instead.
+ * Let's hope this doesn't happen enough to be in the critical path. */
+ smartlist_sort(circlist, circuits_compare_by_oldest_queued_item_);
+
+ /* Fix up the indices before we run into trouble */
+ SMARTLIST_FOREACH_BEGIN(circlist, circuit_t *, circ) {
+ circ->global_circuitlist_idx = circ_sl_idx;
+ } SMARTLIST_FOREACH_END(circ);
+
+ /* Now sort the connection array ... */
+ now_ts_for_buf_cmp = now_ts;
+ smartlist_sort(connection_array, conns_compare_by_buffer_age_);
+ now_ts_for_buf_cmp = 0;
+
+ /* Fix up the connection array to its new order. */
+ SMARTLIST_FOREACH_BEGIN(connection_array, connection_t *, conn) {
+ conn->conn_array_index = conn_sl_idx;
+ } SMARTLIST_FOREACH_END(conn);
+
+ /* Okay, now the worst circuits and connections are at the front of their
+ * respective lists. Let's mark them, and reclaim their storage
+ * aggressively. */
+ conn_idx = 0;
+ SMARTLIST_FOREACH_BEGIN(circlist, circuit_t *, circ) {
+ size_t n;
+ size_t freed;
+
+ /* Free storage in any non-linked directory connections that have buffered
+ * data older than this circuit. */
+ while (conn_idx < smartlist_len(connection_array)) {
+ connection_t *conn = smartlist_get(connection_array, conn_idx);
+ uint32_t conn_age = conn_get_buffer_age(conn, now_ts);
+ if (conn_age < circ->age_tmp) {
+ break;
+ }
+ if (conn->type == CONN_TYPE_DIR && conn->linked_conn == NULL) {
+ if (!conn->marked_for_close)
+ connection_mark_for_close(conn);
+ mem_recovered += single_conn_free_bytes(conn);
+
+ ++n_dirconns_killed;
+
+ if (mem_recovered >= mem_to_recover)
+ goto done_recovering_mem;
+ }
+ ++conn_idx;
+ }
+
+ /* Now, kill the circuit. */
+ n = n_cells_in_circ_queues(circ);
++ const size_t half_stream_alloc = circuit_alloc_in_half_streams(circ);
+ if (! circ->marked_for_close) {
+ circuit_mark_for_close(circ, END_CIRC_REASON_RESOURCELIMIT);
+ }
+ marked_circuit_free_cells(circ);
+ freed = marked_circuit_free_stream_bytes(circ);
+
+ ++n_circuits_killed;
+
+ mem_recovered += n * packed_cell_mem_cost();
++ mem_recovered += half_stream_alloc;
+ mem_recovered += freed;
+
+ if (mem_recovered >= mem_to_recover)
+ goto done_recovering_mem;
+ } SMARTLIST_FOREACH_END(circ);
+
+ done_recovering_mem:
+
+ log_notice(LD_GENERAL, "Removed %"TOR_PRIuSZ" bytes by killing %d circuits; "
+ "%d circuits remain alive. Also killed %d non-linked directory "
+ "connections.",
+ mem_recovered,
+ n_circuits_killed,
+ smartlist_len(circlist) - n_circuits_killed,
+ n_dirconns_killed);
+}
+
+/** Verify that cpath layer <b>cp</b> has all of its invariants
+ * correct. Trigger an assert if anything is invalid.
+ */
+void
+assert_cpath_layer_ok(const crypt_path_t *cp)
+{
+// tor_assert(cp->addr); /* these are zero for rendezvous extra-hops */
+// tor_assert(cp->port);
+ tor_assert(cp);
+ tor_assert(cp->magic == CRYPT_PATH_MAGIC);
+ switch (cp->state)
+ {
+ case CPATH_STATE_OPEN:
+ relay_crypto_assert_ok(&cp->crypto);
+ /* fall through */
+ case CPATH_STATE_CLOSED:
+ /*XXXX Assert that there's no handshake_state either. */
+ tor_assert(!cp->rend_dh_handshake_state);
+ break;
+ case CPATH_STATE_AWAITING_KEYS:
+ /* tor_assert(cp->dh_handshake_state); */
+ break;
+ default:
+ log_fn(LOG_ERR, LD_BUG, "Unexpected state %d", cp->state);
+ tor_assert(0);
+ }
+ tor_assert(cp->package_window >= 0);
+ tor_assert(cp->deliver_window >= 0);
+}
+
+/** Verify that cpath <b>cp</b> has all of its invariants
+ * correct. Trigger an assert if anything is invalid.
+ */
+static void
+assert_cpath_ok(const crypt_path_t *cp)
+{
+ const crypt_path_t *start = cp;
+
+ do {
+ assert_cpath_layer_ok(cp);
+ /* layers must be in sequence of: "open* awaiting? closed*" */
+ if (cp != start) {
+ if (cp->state == CPATH_STATE_AWAITING_KEYS) {
+ tor_assert(cp->prev->state == CPATH_STATE_OPEN);
+ } else if (cp->state == CPATH_STATE_OPEN) {
+ tor_assert(cp->prev->state == CPATH_STATE_OPEN);
+ }
+ }
+ cp = cp->next;
+ tor_assert(cp);
+ } while (cp != start);
+}
+
+/** Verify that circuit <b>c</b> has all of its invariants
+ * correct. Trigger an assert if anything is invalid.
+ */
+MOCK_IMPL(void,
+assert_circuit_ok,(const circuit_t *c))
+{
+ edge_connection_t *conn;
+ const or_circuit_t *or_circ = NULL;
+ const origin_circuit_t *origin_circ = NULL;
+
+ tor_assert(c);
+ tor_assert(c->magic == ORIGIN_CIRCUIT_MAGIC || c->magic == OR_CIRCUIT_MAGIC);
+ tor_assert(c->purpose >= CIRCUIT_PURPOSE_MIN_ &&
+ c->purpose <= CIRCUIT_PURPOSE_MAX_);
+
+ if (CIRCUIT_IS_ORIGIN(c))
+ origin_circ = CONST_TO_ORIGIN_CIRCUIT(c);
+ else
+ or_circ = CONST_TO_OR_CIRCUIT(c);
+
+ if (c->n_chan) {
+ tor_assert(!c->n_hop);
+
+ if (c->n_circ_id) {
+ /* We use the _impl variant here to make sure we don't fail on marked
+ * circuits, which would not be returned by the regular function. */
+ circuit_t *c2 = circuit_get_by_circid_channel_impl(c->n_circ_id,
+ c->n_chan, NULL);
+ tor_assert(c == c2);
+ }
+ }
+ if (or_circ && or_circ->p_chan) {
+ if (or_circ->p_circ_id) {
+ /* ibid */
+ circuit_t *c2 =
+ circuit_get_by_circid_channel_impl(or_circ->p_circ_id,
+ or_circ->p_chan, NULL);
+ tor_assert(c == c2);
+ }
+ }
+ if (or_circ)
+ for (conn = or_circ->n_streams; conn; conn = conn->next_stream)
+ tor_assert(conn->base_.type == CONN_TYPE_EXIT);
+
+ tor_assert(c->deliver_window >= 0);
+ tor_assert(c->package_window >= 0);
+ if (c->state == CIRCUIT_STATE_OPEN ||
+ c->state == CIRCUIT_STATE_GUARD_WAIT) {
+ tor_assert(!c->n_chan_create_cell);
+ if (or_circ) {
+ relay_crypto_assert_ok(&or_circ->crypto);
+ }
+ }
+ if (c->state == CIRCUIT_STATE_CHAN_WAIT && !c->marked_for_close) {
+ tor_assert(circuits_pending_chans &&
+ smartlist_contains(circuits_pending_chans, c));
+ } else {
+ tor_assert(!circuits_pending_chans ||
+ !smartlist_contains(circuits_pending_chans, c));
+ }
+ if (origin_circ && origin_circ->cpath) {
+ assert_cpath_ok(origin_circ->cpath);
+ }
+ if (c->purpose == CIRCUIT_PURPOSE_REND_ESTABLISHED) {
+ tor_assert(or_circ);
+ if (!c->marked_for_close) {
+ tor_assert(or_circ->rend_splice);
+ tor_assert(or_circ->rend_splice->rend_splice == or_circ);
+ }
+ tor_assert(or_circ->rend_splice != or_circ);
+ } else {
+ tor_assert(!or_circ || !or_circ->rend_splice);
+ }
+}
diff --cc src/core/or/connection_edge.c
index 35e68485b,000000000..d49e04021
mode 100644,000000..100644
--- a/src/core/or/connection_edge.c
+++ b/src/core/or/connection_edge.c
@@@ -1,4448 -1,0 +1,4469 @@@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file connection_edge.c
+ * \brief Handle edge streams.
+ *
+ * An edge_connection_t is a subtype of a connection_t, and represents two
+ * critical concepts in Tor: a stream, and an edge connection. From the Tor
+ * protocol's point of view, a stream is a bi-directional channel that is
+ * multiplexed on a single circuit. Each stream on a circuit is identified
+ * with a separate 16-bit stream ID, local to the (circuit,exit) pair.
+ * Streams are created in response to client requests.
+ *
+ * An edge connection is one thing that can implement a stream: it is either a
+ * TCP application socket that has arrived via (e.g.) a SOCKS request, or an
+ * exit connection.
+ *
+ * Not every instance of edge_connection_t truly represents an edge connction,
+ * however. (Sorry!) We also create edge_connection_t objects for streams that
+ * we will not be handling with TCP. The types of these streams are:
+ * <ul>
+ * <li>DNS lookup streams, created on the client side in response to
+ * a UDP DNS request received on a DNSPort, or a RESOLVE command
+ * on a controller.
+ * <li>DNS lookup streams, created on the exit side in response to
+ * a RELAY_RESOLVE cell from a client.
+ * <li>Tunneled directory streams, created on the directory cache side
+ * in response to a RELAY_BEGIN_DIR cell. These streams attach directly
+ * to a dir_connection_t object without ever using TCP.
+ * </ul>
+ *
+ * This module handles general-purpose functionality having to do with
+ * edge_connection_t. On the client side, it accepts various types of
+ * application requests on SocksPorts, TransPorts, and NATDPorts, and
+ * creates streams appropriately.
+ *
+ * This module is also responsible for implementing stream isolation:
+ * ensuring that streams that should not be linkable to one another are
+ * kept to different circuits.
+ *
+ * On the exit side, this module handles the various stream-creating
+ * type of RELAY cells by launching appropriate outgoing connections,
+ * DNS requests, or directory connection objects.
+ *
+ * And for all edge connections, this module is responsible for handling
+ * incoming and outdoing data as it arrives or leaves in the relay.c
+ * module. (Outgoing data will be packaged in
+ * connection_edge_process_inbuf() as it calls
+ * connection_edge_package_raw_inbuf(); incoming data from RELAY_DATA
+ * cells is applied in connection_edge_process_relay_cell().)
+ **/
+#define CONNECTION_EDGE_PRIVATE
+
+#include "core/or/or.h"
+
+#include "lib/err/backtrace.h"
+
+#include "feature/client/addressmap.h"
+#include "lib/container/buffers.h"
+#include "core/or/channel.h"
+#include "feature/client/circpathbias.h"
+#include "core/or/circuitlist.h"
+#include "core/or/circuituse.h"
+#include "app/config/config.h"
+#include "core/mainloop/connection.h"
+#include "core/or/connection_edge.h"
+#include "core/or/connection_or.h"
+#include "feature/control/control.h"
+#include "lib/crypt_ops/crypto_util.h"
+#include "feature/relay/dns.h"
+#include "feature/client/dnsserv.h"
+#include "feature/dircache/directory.h"
+#include "feature/dircache/dirserv.h"
+#include "feature/hibernate/hibernate.h"
+#include "feature/hs/hs_common.h"
+#include "feature/hs/hs_cache.h"
+#include "feature/hs/hs_client.h"
+#include "feature/hs/hs_circuit.h"
+#include "core/mainloop/main.h"
+#include "feature/nodelist/networkstatus.h"
+#include "feature/nodelist/nodelist.h"
+#include "core/or/policies.h"
+#include "core/proto/proto_http.h"
+#include "core/proto/proto_socks.h"
+#include "core/or/reasons.h"
+#include "core/or/relay.h"
+#include "feature/rend/rendclient.h"
+#include "feature/rend/rendcommon.h"
+#include "feature/rend/rendservice.h"
+#include "feature/stats/rephist.h"
+#include "feature/relay/router.h"
+#include "feature/nodelist/routerlist.h"
+#include "feature/nodelist/routerset.h"
+#include "core/or/circuitbuild.h"
+
+#include "core/or/cell_st.h"
+#include "core/or/cpath_build_state_st.h"
+#include "feature/dircommon/dir_connection_st.h"
+#include "core/or/entry_connection_st.h"
+#include "core/or/extend_info_st.h"
+#include "feature/nodelist/node_st.h"
+#include "core/or/or_circuit_st.h"
+#include "core/or/origin_circuit_st.h"
+#include "core/or/half_edge_st.h"
+#include "core/or/socks_request_st.h"
+#include "lib/evloop/compat_libevent.h"
+
+#ifdef HAVE_LINUX_TYPES_H
+#include <linux/types.h>
+#endif
+#ifdef HAVE_LINUX_NETFILTER_IPV4_H
+#include <linux/netfilter_ipv4.h>
+#define TRANS_NETFILTER
+#define TRANS_NETFILTER_IPV4
+#endif
+
+#ifdef HAVE_LINUX_IF_H
+#include <linux/if.h>
+#endif
+
+#ifdef HAVE_LINUX_NETFILTER_IPV6_IP6_TABLES_H
+#include <linux/netfilter_ipv6/ip6_tables.h>
+#if defined(IP6T_SO_ORIGINAL_DST)
+#define TRANS_NETFILTER
+#define TRANS_NETFILTER_IPV6
+#endif
+#endif /* defined(HAVE_LINUX_NETFILTER_IPV6_IP6_TABLES_H) */
+
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+
+#if defined(HAVE_NET_IF_H) && defined(HAVE_NET_PFVAR_H)
+#include <net/if.h>
+#include <net/pfvar.h>
+#define TRANS_PF
+#endif
+
+#ifdef IP_TRANSPARENT
+#define TRANS_TPROXY
+#endif
+
+#define SOCKS4_GRANTED 90
+#define SOCKS4_REJECT 91
+
+static int connection_ap_handshake_process_socks(entry_connection_t *conn);
+static int connection_ap_process_natd(entry_connection_t *conn);
+static int connection_exit_connect_dir(edge_connection_t *exitconn);
+static int consider_plaintext_ports(entry_connection_t *conn, uint16_t port);
+static int connection_ap_supports_optimistic_data(const entry_connection_t *);
+STATIC void connection_half_edge_add(const edge_connection_t *conn,
+ origin_circuit_t *circ);
+STATIC half_edge_t *connection_half_edge_find_stream_id(
+ const smartlist_t *half_conns,
+ streamid_t stream_id);
+
+/** Convert a connection_t* to an edge_connection_t*; assert if the cast is
+ * invalid. */
+edge_connection_t *
+TO_EDGE_CONN(connection_t *c)
+{
+ tor_assert(c->magic == EDGE_CONNECTION_MAGIC ||
+ c->magic == ENTRY_CONNECTION_MAGIC);
+ return DOWNCAST(edge_connection_t, c);
+}
+
+entry_connection_t *
+TO_ENTRY_CONN(connection_t *c)
+{
+ tor_assert(c->magic == ENTRY_CONNECTION_MAGIC);
+ return (entry_connection_t*) SUBTYPE_P(c, entry_connection_t, edge_.base_);
+}
+
+entry_connection_t *
+EDGE_TO_ENTRY_CONN(edge_connection_t *c)
+{
+ tor_assert(c->base_.magic == ENTRY_CONNECTION_MAGIC);
+ return (entry_connection_t*) SUBTYPE_P(c, entry_connection_t, edge_);
+}
+
+/** An AP stream has failed/finished. If it hasn't already sent back
+ * a socks reply, send one now (based on endreason). Also set
+ * has_sent_end to 1, and mark the conn.
+ */
+MOCK_IMPL(void,
+connection_mark_unattached_ap_,(entry_connection_t *conn, int endreason,
+ int line, const char *file))
+{
+ connection_t *base_conn = ENTRY_TO_CONN(conn);
+ edge_connection_t *edge_conn = ENTRY_TO_EDGE_CONN(conn);
+ tor_assert(base_conn->type == CONN_TYPE_AP);
+ ENTRY_TO_EDGE_CONN(conn)->edge_has_sent_end = 1; /* no circ yet */
+
+ /* If this is a rendezvous stream and it is failing without ever
+ * being attached to a circuit, assume that an attempt to connect to
+ * the destination hidden service has just ended.
+ *
+ * XXXX This condition doesn't limit to only streams failing
+ * without ever being attached. That sloppiness should be harmless,
+ * but we should fix it someday anyway. */
+ if ((edge_conn->on_circuit != NULL || edge_conn->edge_has_sent_end) &&
+ connection_edge_is_rendezvous_stream(edge_conn)) {
+ if (edge_conn->rend_data) {
+ rend_client_note_connection_attempt_ended(edge_conn->rend_data);
+ }
+ }
+
+ if (base_conn->marked_for_close) {
+ /* This call will warn as appropriate. */
+ connection_mark_for_close_(base_conn, line, file);
+ return;
+ }
+
+ if (!conn->socks_request->has_finished) {
+ if (endreason & END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED)
+ log_warn(LD_BUG,
+ "stream (marked at %s:%d) sending two socks replies?",
+ file, line);
+
+ if (SOCKS_COMMAND_IS_CONNECT(conn->socks_request->command))
+ connection_ap_handshake_socks_reply(conn, NULL, 0, endreason);
+ else if (SOCKS_COMMAND_IS_RESOLVE(conn->socks_request->command))
+ connection_ap_handshake_socks_resolved(conn,
+ RESOLVED_TYPE_ERROR_TRANSIENT,
+ 0, NULL, -1, -1);
+ else /* unknown or no handshake at all. send no response. */
+ conn->socks_request->has_finished = 1;
+ }
+
+ connection_mark_and_flush_(base_conn, line, file);
+
+ ENTRY_TO_EDGE_CONN(conn)->end_reason = endreason;
+}
+
+/** There was an EOF. Send an end and mark the connection for close.
+ */
+int
+connection_edge_reached_eof(edge_connection_t *conn)
+{
+ if (connection_get_inbuf_len(TO_CONN(conn)) &&
+ connection_state_is_open(TO_CONN(conn))) {
+ /* it still has stuff to process. don't let it die yet. */
+ return 0;
+ }
+ log_info(LD_EDGE,"conn (fd "TOR_SOCKET_T_FORMAT") reached eof. Closing.",
+ conn->base_.s);
+ if (!conn->base_.marked_for_close) {
+ /* only mark it if not already marked. it's possible to
+ * get the 'end' right around when the client hangs up on us. */
+ connection_edge_end(conn, END_STREAM_REASON_DONE);
+ if (conn->base_.type == CONN_TYPE_AP) {
+ /* eof, so don't send a socks reply back */
+ if (EDGE_TO_ENTRY_CONN(conn)->socks_request)
+ EDGE_TO_ENTRY_CONN(conn)->socks_request->has_finished = 1;
+ }
+ connection_mark_for_close(TO_CONN(conn));
+ }
+ return 0;
+}
+
+/** Handle new bytes on conn->inbuf based on state:
+ * - If it's waiting for socks info, try to read another step of the
+ * socks handshake out of conn->inbuf.
+ * - If it's waiting for the original destination, fetch it.
+ * - If it's open, then package more relay cells from the stream.
+ * - Else, leave the bytes on inbuf alone for now.
+ *
+ * Mark and return -1 if there was an unexpected error with the conn,
+ * else return 0.
+ */
+int
+connection_edge_process_inbuf(edge_connection_t *conn, int package_partial)
+{
+ tor_assert(conn);
+
+ switch (conn->base_.state) {
+ case AP_CONN_STATE_SOCKS_WAIT:
+ if (connection_ap_handshake_process_socks(EDGE_TO_ENTRY_CONN(conn)) <0) {
+ /* already marked */
+ return -1;
+ }
+ return 0;
+ case AP_CONN_STATE_NATD_WAIT:
+ if (connection_ap_process_natd(EDGE_TO_ENTRY_CONN(conn)) < 0) {
+ /* already marked */
+ return -1;
+ }
+ return 0;
+ case AP_CONN_STATE_HTTP_CONNECT_WAIT:
+ if (connection_ap_process_http_connect(EDGE_TO_ENTRY_CONN(conn)) < 0) {
+ return -1;
+ }
+ return 0;
+ case AP_CONN_STATE_OPEN:
+ case EXIT_CONN_STATE_OPEN:
+ if (connection_edge_package_raw_inbuf(conn, package_partial, NULL) < 0) {
+ /* (We already sent an end cell if possible) */
+ connection_mark_for_close(TO_CONN(conn));
+ return -1;
+ }
+ return 0;
+ case AP_CONN_STATE_CONNECT_WAIT:
+ if (connection_ap_supports_optimistic_data(EDGE_TO_ENTRY_CONN(conn))) {
+ log_info(LD_EDGE,
+ "data from edge while in '%s' state. Sending it anyway. "
+ "package_partial=%d, buflen=%ld",
+ conn_state_to_string(conn->base_.type, conn->base_.state),
+ package_partial,
+ (long)connection_get_inbuf_len(TO_CONN(conn)));
+ if (connection_edge_package_raw_inbuf(conn, package_partial, NULL)<0) {
+ /* (We already sent an end cell if possible) */
+ connection_mark_for_close(TO_CONN(conn));
+ return -1;
+ }
+ return 0;
+ }
+ /* Fall through if the connection is on a circuit without optimistic
+ * data support. */
+ /* Falls through. */
+ case EXIT_CONN_STATE_CONNECTING:
+ case AP_CONN_STATE_RENDDESC_WAIT:
+ case AP_CONN_STATE_CIRCUIT_WAIT:
+ case AP_CONN_STATE_RESOLVE_WAIT:
+ case AP_CONN_STATE_CONTROLLER_WAIT:
+ log_info(LD_EDGE,
+ "data from edge while in '%s' state. Leaving it on buffer.",
+ conn_state_to_string(conn->base_.type, conn->base_.state));
+ return 0;
+ }
+ log_warn(LD_BUG,"Got unexpected state %d. Closing.",conn->base_.state);
+ tor_fragile_assert();
+ connection_edge_end(conn, END_STREAM_REASON_INTERNAL);
+ connection_mark_for_close(TO_CONN(conn));
+ return -1;
+}
+
+/** This edge needs to be closed, because its circuit has closed.
+ * Mark it for close and return 0.
+ */
+int
+connection_edge_destroy(circid_t circ_id, edge_connection_t *conn)
+{
+ if (!conn->base_.marked_for_close) {
+ log_info(LD_EDGE, "CircID %u: At an edge. Marking connection for close.",
+ (unsigned) circ_id);
+ if (conn->base_.type == CONN_TYPE_AP) {
+ entry_connection_t *entry_conn = EDGE_TO_ENTRY_CONN(conn);
+ connection_mark_unattached_ap(entry_conn, END_STREAM_REASON_DESTROY);
+ control_event_stream_bandwidth(conn);
+ control_event_stream_status(entry_conn, STREAM_EVENT_CLOSED,
+ END_STREAM_REASON_DESTROY);
+ conn->end_reason |= END_STREAM_REASON_FLAG_ALREADY_SENT_CLOSED;
+ } else {
+ /* closing the circuit, nothing to send an END to */
+ conn->edge_has_sent_end = 1;
+ conn->end_reason = END_STREAM_REASON_DESTROY;
+ conn->end_reason |= END_STREAM_REASON_FLAG_ALREADY_SENT_CLOSED;
+ connection_mark_and_flush(TO_CONN(conn));
+ }
+ }
+ conn->cpath_layer = NULL;
+ conn->on_circuit = NULL;
+ return 0;
+}
+
+/** Send a raw end cell to the stream with ID <b>stream_id</b> out over the
+ * <b>circ</b> towards the hop identified with <b>cpath_layer</b>. If this
+ * is not a client connection, set the relay end cell's reason for closing
+ * as <b>reason</b> */
+static int
+relay_send_end_cell_from_edge(streamid_t stream_id, circuit_t *circ,
+ uint8_t reason, crypt_path_t *cpath_layer)
+{
+ char payload[1];
+
+ if (CIRCUIT_PURPOSE_IS_CLIENT(circ->purpose)) {
+ /* Never send the server an informative reason code; it doesn't need to
+ * know why the client stream is failing. */
+ reason = END_STREAM_REASON_MISC;
+ }
+
+ payload[0] = (char) reason;
+
+ /* Note: we have to use relay_send_command_from_edge here, not
+ * connection_edge_end or connection_edge_send_command, since those require
+ * that we have a stream connected to a circuit, and we don't connect to a
+ * circuit until we have a pending/successful resolve. */
+ return relay_send_command_from_edge(stream_id, circ, RELAY_COMMAND_END,
+ payload, 1, cpath_layer);
+}
+
+/* If the connection <b>conn</b> is attempting to connect to an external
+ * destination that is an hidden service and the reason is a connection
+ * refused or timeout, log it so the operator can take appropriate actions.
+ * The log statement is a rate limited warning. */
+static void
+warn_if_hs_unreachable(const edge_connection_t *conn, uint8_t reason)
+{
+ tor_assert(conn);
+
+ if (conn->base_.type == CONN_TYPE_EXIT &&
+ connection_edge_is_rendezvous_stream(conn) &&
+ (reason == END_STREAM_REASON_CONNECTREFUSED ||
+ reason == END_STREAM_REASON_TIMEOUT)) {
+#define WARN_FAILED_HS_CONNECTION 300
+ static ratelim_t warn_limit = RATELIM_INIT(WARN_FAILED_HS_CONNECTION);
+ char *m;
+ if ((m = rate_limit_log(&warn_limit, approx_time()))) {
+ log_warn(LD_EDGE, "Onion service connection to %s failed (%s)",
+ (conn->base_.socket_family == AF_UNIX) ?
+ safe_str(conn->base_.address) :
+ safe_str(fmt_addrport(&conn->base_.addr, conn->base_.port)),
+ stream_end_reason_to_string(reason));
+ tor_free(m);
+ }
+ }
+}
+
+/** Send a relay end cell from stream <b>conn</b> down conn's circuit, and
+ * remember that we've done so. If this is not a client connection, set the
+ * relay end cell's reason for closing as <b>reason</b>.
+ *
+ * Return -1 if this function has already been called on this conn,
+ * else return 0.
+ */
+int
+connection_edge_end(edge_connection_t *conn, uint8_t reason)
+{
+ char payload[RELAY_PAYLOAD_SIZE];
+ size_t payload_len=1;
+ circuit_t *circ;
+ uint8_t control_reason = reason;
+
+ if (conn->edge_has_sent_end) {
+ log_warn(LD_BUG,"(Harmless.) Calling connection_edge_end (reason %d) "
+ "on an already ended stream?", reason);
+ tor_fragile_assert();
+ return -1;
+ }
+
+ if (conn->base_.marked_for_close) {
+ log_warn(LD_BUG,
+ "called on conn that's already marked for close at %s:%d.",
+ conn->base_.marked_for_close_file, conn->base_.marked_for_close);
+ return 0;
+ }
+
+ circ = circuit_get_by_edge_conn(conn);
+ if (circ && CIRCUIT_PURPOSE_IS_CLIENT(circ->purpose)) {
+ /* If this is a client circuit, don't send the server an informative
+ * reason code; it doesn't need to know why the client stream is
+ * failing. */
+ reason = END_STREAM_REASON_MISC;
+ }
+
+ payload[0] = (char)reason;
+ if (reason == END_STREAM_REASON_EXITPOLICY &&
+ !connection_edge_is_rendezvous_stream(conn)) {
+ int addrlen;
+ if (tor_addr_family(&conn->base_.addr) == AF_INET) {
+ set_uint32(payload+1, tor_addr_to_ipv4n(&conn->base_.addr));
+ addrlen = 4;
+ } else {
+ memcpy(payload+1, tor_addr_to_in6_addr8(&conn->base_.addr), 16);
+ addrlen = 16;
+ }
+ set_uint32(payload+1+addrlen, htonl(dns_clip_ttl(conn->address_ttl)));
+ payload_len += 4+addrlen;
+ }
+
+ if (circ && !circ->marked_for_close) {
+ log_debug(LD_EDGE,"Sending end on conn (fd "TOR_SOCKET_T_FORMAT").",
+ conn->base_.s);
+
+ if (CIRCUIT_IS_ORIGIN(circ)) {
+ origin_circuit_t *origin_circ = TO_ORIGIN_CIRCUIT(circ);
+ connection_half_edge_add(conn, origin_circ);
+ }
+
+ connection_edge_send_command(conn, RELAY_COMMAND_END,
+ payload, payload_len);
+ /* We'll log warn if the connection was an hidden service and couldn't be
+ * made because the service wasn't available. */
+ warn_if_hs_unreachable(conn, control_reason);
+ } else {
+ log_debug(LD_EDGE,"No circ to send end on conn "
+ "(fd "TOR_SOCKET_T_FORMAT").",
+ conn->base_.s);
+ }
+
+ conn->edge_has_sent_end = 1;
+ conn->end_reason = control_reason;
+ return 0;
+}
+
+/**
+ * Helper function for bsearch.
+ *
+ * As per smartlist_bsearch, return < 0 if key preceeds member,
+ * > 0 if member preceeds key, and 0 if they are equal.
+ *
+ * This is equivalent to subtraction of the values of key - member
+ * (why does no one ever say that explicitly?).
+ */
+static int
+connection_half_edge_compare_bsearch(const void *key, const void **member)
+{
+ const half_edge_t *e2;
+ tor_assert(key);
+ tor_assert(member && *(half_edge_t**)member);
+ e2 = *(const half_edge_t **)member;
+
+ return *(const streamid_t*)key - e2->stream_id;
+}
+
++/** Total number of half_edge_t objects allocated */
++static size_t n_half_conns_allocated = 0;
++
+/**
+ * Add a half-closed connection to the list, to watch for activity.
+ *
+ * These connections are removed from the list upon receiving an end
+ * cell.
+ */
+STATIC void
+connection_half_edge_add(const edge_connection_t *conn,
+ origin_circuit_t *circ)
+{
+ half_edge_t *half_conn = NULL;
+ int insert_at = 0;
+ int ignored;
+
+ /* Double-check for re-insertion. This should not happen,
+ * but this check is cheap compared to the sort anyway */
+ if (connection_half_edge_find_stream_id(circ->half_streams,
+ conn->stream_id)) {
+ log_warn(LD_BUG, "Duplicate stream close for stream %d on circuit %d",
+ conn->stream_id, circ->global_identifier);
+ return;
+ }
+
+ half_conn = tor_malloc_zero(sizeof(half_edge_t));
++ ++n_half_conns_allocated;
+
+ if (!circ->half_streams) {
+ circ->half_streams = smartlist_new();
+ }
+
+ half_conn->stream_id = conn->stream_id;
+
+ // How many sendme's should I expect?
+ half_conn->sendmes_pending =
+ (STREAMWINDOW_START-conn->package_window)/STREAMWINDOW_INCREMENT;
+
+ // Is there a connected cell pending?
+ half_conn->connected_pending = conn->base_.state ==
+ AP_CONN_STATE_CONNECT_WAIT;
+
+ /* Data should only arrive if we're not waiting on a resolved cell.
+ * It can arrive after waiting on connected, because of optimistic
+ * data. */
+ if (conn->base_.state != AP_CONN_STATE_RESOLVE_WAIT) {
+ // How many more data cells can arrive on this id?
+ half_conn->data_pending = conn->deliver_window;
+ }
+
+ insert_at = smartlist_bsearch_idx(circ->half_streams, &half_conn->stream_id,
+ connection_half_edge_compare_bsearch,
+ &ignored);
+ smartlist_insert(circ->half_streams, insert_at, half_conn);
+}
+
++/** Release space held by <b>he</b> */
++void
++half_edge_free_(half_edge_t *he)
++{
++ if (!he)
++ return;
++ --n_half_conns_allocated;
++ tor_free(he);
++}
++
++/** Return the number of bytes devoted to storing info on half-open streams. */
++size_t
++half_streams_get_total_allocation(void)
++{
++ return n_half_conns_allocated * sizeof(half_edge_t);
++}
++
+/**
+ * Find a stream_id_t in the list in O(lg(n)).
+ *
+ * Returns NULL if the list is empty or element is not found.
+ * Returns a pointer to the element if found.
+ */
+STATIC half_edge_t *
+connection_half_edge_find_stream_id(const smartlist_t *half_conns,
+ streamid_t stream_id)
+{
+ if (!half_conns)
+ return NULL;
+
+ return smartlist_bsearch(half_conns, &stream_id,
+ connection_half_edge_compare_bsearch);
+}
+
+/**
+ * Check if this stream_id is in a half-closed state. If so,
+ * check if it still has data cells pending, and decrement that
+ * window if so.
+ *
+ * Return 1 if the data window was not empty.
+ * Return 0 otherwise.
+ */
+int
+connection_half_edge_is_valid_data(const smartlist_t *half_conns,
+ streamid_t stream_id)
+{
+ half_edge_t *half = connection_half_edge_find_stream_id(half_conns,
+ stream_id);
+
+ if (!half)
+ return 0;
+
+ if (half->data_pending > 0) {
+ half->data_pending--;
+ return 1;
+ }
+
+ return 0;
+}
+
+/**
+ * Check if this stream_id is in a half-closed state. If so,
+ * check if it still has a connected cell pending, and decrement
+ * that window if so.
+ *
+ * Return 1 if the connected window was not empty.
+ * Return 0 otherwise.
+ */
+int
+connection_half_edge_is_valid_connected(const smartlist_t *half_conns,
+ streamid_t stream_id)
+{
+ half_edge_t *half = connection_half_edge_find_stream_id(half_conns,
+ stream_id);
+
+ if (!half)
+ return 0;
+
+ if (half->connected_pending) {
+ half->connected_pending = 0;
+ return 1;
+ }
+
+ return 0;
+}
+
+/**
+ * Check if this stream_id is in a half-closed state. If so,
+ * check if it still has sendme cells pending, and decrement that
+ * window if so.
+ *
+ * Return 1 if the sendme window was not empty.
+ * Return 0 otherwise.
+ */
+int
+connection_half_edge_is_valid_sendme(const smartlist_t *half_conns,
+ streamid_t stream_id)
+{
+ half_edge_t *half = connection_half_edge_find_stream_id(half_conns,
+ stream_id);
+
+ if (!half)
+ return 0;
+
+ if (half->sendmes_pending > 0) {
+ half->sendmes_pending--;
+ return 1;
+ }
+
+ return 0;
+}
+
+/**
+ * Check if this stream_id is in a half-closed state. If so, remove
+ * it from the list. No other data should come after the END cell.
+ *
+ * Return 1 if stream_id was in half-closed state.
+ * Return 0 otherwise.
+ */
+int
+connection_half_edge_is_valid_end(smartlist_t *half_conns,
+ streamid_t stream_id)
+{
+ half_edge_t *half;
+ int found, remove_idx;
+
+ if (!half_conns)
+ return 0;
+
+ remove_idx = smartlist_bsearch_idx(half_conns, &stream_id,
+ connection_half_edge_compare_bsearch,
+ &found);
+ if (!found)
+ return 0;
+
+ half = smartlist_get(half_conns, remove_idx);
+ smartlist_del_keeporder(half_conns, remove_idx);
- tor_free(half);
++ half_edge_free(half);
+ return 1;
+}
+
+/**
+ * Streams that were used to send a RESOLVE cell are closed
+ * when they get the RESOLVED, without an end. So treat
+ * a RESOLVED just like an end, and remove from the list.
+ */
+int
+connection_half_edge_is_valid_resolved(smartlist_t *half_conns,
+ streamid_t stream_id)
+{
+ return connection_half_edge_is_valid_end(half_conns, stream_id);
+}
+
+/** An error has just occurred on an operation on an edge connection
+ * <b>conn</b>. Extract the errno; convert it to an end reason, and send an
+ * appropriate relay end cell to the other end of the connection's circuit.
+ **/
+int
+connection_edge_end_errno(edge_connection_t *conn)
+{
+ uint8_t reason;
+ tor_assert(conn);
+ reason = errno_to_stream_end_reason(tor_socket_errno(conn->base_.s));
+ return connection_edge_end(conn, reason);
+}
+
+/** We just wrote some data to <b>conn</b>; act appropriately.
+ *
+ * (That is, if it's open, consider sending a stream-level sendme cell if we
+ * have just flushed enough.)
+ */
+int
+connection_edge_flushed_some(edge_connection_t *conn)
+{
+ switch (conn->base_.state) {
+ case AP_CONN_STATE_OPEN:
+ case EXIT_CONN_STATE_OPEN:
+ connection_edge_consider_sending_sendme(conn);
+ break;
+ }
+ return 0;
+}
+
+/** Connection <b>conn</b> has finished writing and has no bytes left on
+ * its outbuf.
+ *
+ * If it's in state 'open', stop writing, consider responding with a
+ * sendme, and return.
+ * Otherwise, stop writing and return.
+ *
+ * If <b>conn</b> is broken, mark it for close and return -1, else
+ * return 0.
+ */
+int
+connection_edge_finished_flushing(edge_connection_t *conn)
+{
+ tor_assert(conn);
+
+ switch (conn->base_.state) {
+ case AP_CONN_STATE_OPEN:
+ case EXIT_CONN_STATE_OPEN:
+ connection_edge_consider_sending_sendme(conn);
+ return 0;
+ case AP_CONN_STATE_SOCKS_WAIT:
+ case AP_CONN_STATE_NATD_WAIT:
+ case AP_CONN_STATE_RENDDESC_WAIT:
+ case AP_CONN_STATE_CIRCUIT_WAIT:
+ case AP_CONN_STATE_CONNECT_WAIT:
+ case AP_CONN_STATE_CONTROLLER_WAIT:
+ case AP_CONN_STATE_RESOLVE_WAIT:
+ case AP_CONN_STATE_HTTP_CONNECT_WAIT:
+ return 0;
+ default:
+ log_warn(LD_BUG, "Called in unexpected state %d.",conn->base_.state);
+ tor_fragile_assert();
+ return -1;
+ }
+ return 0;
+}
+
+/** Longest size for the relay payload of a RELAY_CONNECTED cell that we're
+ * able to generate. */
+/* 4 zero bytes; 1 type byte; 16 byte IPv6 address; 4 byte TTL. */
+#define MAX_CONNECTED_CELL_PAYLOAD_LEN 25
+
+/** Set the buffer at <b>payload_out</b> -- which must have at least
+ * MAX_CONNECTED_CELL_PAYLOAD_LEN bytes available -- to the body of a
+ * RELAY_CONNECTED cell indicating that we have connected to <b>addr</b>, and
+ * that the name resolution that led us to <b>addr</b> will be valid for
+ * <b>ttl</b> seconds. Return -1 on error, or the number of bytes used on
+ * success. */
+STATIC int
+connected_cell_format_payload(uint8_t *payload_out,
+ const tor_addr_t *addr,
+ uint32_t ttl)
+{
+ const sa_family_t family = tor_addr_family(addr);
+ int connected_payload_len;
+
+ /* should be needless */
+ memset(payload_out, 0, MAX_CONNECTED_CELL_PAYLOAD_LEN);
+
+ if (family == AF_INET) {
+ set_uint32(payload_out, tor_addr_to_ipv4n(addr));
+ connected_payload_len = 4;
+ } else if (family == AF_INET6) {
+ set_uint32(payload_out, 0);
+ set_uint8(payload_out + 4, 6);
+ memcpy(payload_out + 5, tor_addr_to_in6_addr8(addr), 16);
+ connected_payload_len = 21;
+ } else {
+ return -1;
+ }
+
+ set_uint32(payload_out + connected_payload_len, htonl(dns_clip_ttl(ttl)));
+ connected_payload_len += 4;
+
+ tor_assert(connected_payload_len <= MAX_CONNECTED_CELL_PAYLOAD_LEN);
+
+ return connected_payload_len;
+}
+
+/** Connected handler for exit connections: start writing pending
+ * data, deliver 'CONNECTED' relay cells as appropriate, and check
+ * any pending data that may have been received. */
+int
+connection_edge_finished_connecting(edge_connection_t *edge_conn)
+{
+ connection_t *conn;
+
+ tor_assert(edge_conn);
+ tor_assert(edge_conn->base_.type == CONN_TYPE_EXIT);
+ conn = TO_CONN(edge_conn);
+ tor_assert(conn->state == EXIT_CONN_STATE_CONNECTING);
+
+ log_info(LD_EXIT,"Exit connection to %s:%u (%s) established.",
+ escaped_safe_str(conn->address), conn->port,
+ safe_str(fmt_and_decorate_addr(&conn->addr)));
+
+ rep_hist_note_exit_stream_opened(conn->port);
+
+ conn->state = EXIT_CONN_STATE_OPEN;
+ connection_watch_events(conn, READ_EVENT); /* stop writing, keep reading */
+ if (connection_get_outbuf_len(conn)) /* in case there are any queued relay
+ * cells */
+ connection_start_writing(conn);
+ /* deliver a 'connected' relay cell back through the circuit. */
+ if (connection_edge_is_rendezvous_stream(edge_conn)) {
+ if (connection_edge_send_command(edge_conn,
+ RELAY_COMMAND_CONNECTED, NULL, 0) < 0)
+ return 0; /* circuit is closed, don't continue */
+ } else {
+ uint8_t connected_payload[MAX_CONNECTED_CELL_PAYLOAD_LEN];
+ int connected_payload_len =
+ connected_cell_format_payload(connected_payload, &conn->addr,
+ edge_conn->address_ttl);
+ if (connected_payload_len < 0)
+ return -1;
+
+ if (connection_edge_send_command(edge_conn,
+ RELAY_COMMAND_CONNECTED,
+ (char*)connected_payload, connected_payload_len) < 0)
+ return 0; /* circuit is closed, don't continue */
+ }
+ tor_assert(edge_conn->package_window > 0);
+ /* in case the server has written anything */
+ return connection_edge_process_inbuf(edge_conn, 1);
+}
+
+/** A list of all the entry_connection_t * objects that are not marked
+ * for close, and are in AP_CONN_STATE_CIRCUIT_WAIT.
+ *
+ * (Right now, we check in several places to make sure that this list is
+ * correct. When it's incorrect, we'll fix it, and log a BUG message.)
+ */
+static smartlist_t *pending_entry_connections = NULL;
+
+static int untried_pending_connections = 0;
+
+/**
+ * Mainloop event to tell us to scan for pending connections that can
+ * be attached.
+ */
+static mainloop_event_t *attach_pending_entry_connections_ev = NULL;
+
+/** Common code to connection_(ap|exit)_about_to_close. */
+static void
+connection_edge_about_to_close(edge_connection_t *edge_conn)
+{
+ if (!edge_conn->edge_has_sent_end) {
+ connection_t *conn = TO_CONN(edge_conn);
+ log_warn(LD_BUG, "(Harmless.) Edge connection (marked at %s:%d) "
+ "hasn't sent end yet?",
+ conn->marked_for_close_file, conn->marked_for_close);
+ tor_fragile_assert();
+ }
+}
+
+/** Called when we're about to finally unlink and free an AP (client)
+ * connection: perform necessary accounting and cleanup */
+void
+connection_ap_about_to_close(entry_connection_t *entry_conn)
+{
+ circuit_t *circ;
+ edge_connection_t *edge_conn = ENTRY_TO_EDGE_CONN(entry_conn);
+ connection_t *conn = ENTRY_TO_CONN(entry_conn);
+
+ connection_edge_about_to_close(edge_conn);
+
+ if (entry_conn->socks_request->has_finished == 0) {
+ /* since conn gets removed right after this function finishes,
+ * there's no point trying to send back a reply at this point. */
+ log_warn(LD_BUG,"Closing stream (marked at %s:%d) without sending"
+ " back a socks reply.",
+ conn->marked_for_close_file, conn->marked_for_close);
+ }
+ if (!edge_conn->end_reason) {
+ log_warn(LD_BUG,"Closing stream (marked at %s:%d) without having"
+ " set end_reason.",
+ conn->marked_for_close_file, conn->marked_for_close);
+ }
+ if (entry_conn->dns_server_request) {
+ log_warn(LD_BUG,"Closing stream (marked at %s:%d) without having"
+ " replied to DNS request.",
+ conn->marked_for_close_file, conn->marked_for_close);
+ dnsserv_reject_request(entry_conn);
+ }
+
+ if (TO_CONN(edge_conn)->state == AP_CONN_STATE_CIRCUIT_WAIT) {
+ smartlist_remove(pending_entry_connections, entry_conn);
+ }
+
+#if 1
+ /* Check to make sure that this isn't in pending_entry_connections if it
+ * didn't actually belong there. */
+ if (TO_CONN(edge_conn)->type == CONN_TYPE_AP) {
+ connection_ap_warn_and_unmark_if_pending_circ(entry_conn,
+ "about_to_close");
+ }
+#endif /* 1 */
+
+ control_event_stream_bandwidth(edge_conn);
+ control_event_stream_status(entry_conn, STREAM_EVENT_CLOSED,
+ edge_conn->end_reason);
+ circ = circuit_get_by_edge_conn(edge_conn);
+ if (circ)
+ circuit_detach_stream(circ, edge_conn);
+}
+
+/** Called when we're about to finally unlink and free an exit
+ * connection: perform necessary accounting and cleanup */
+void
+connection_exit_about_to_close(edge_connection_t *edge_conn)
+{
+ circuit_t *circ;
+ connection_t *conn = TO_CONN(edge_conn);
+
+ connection_edge_about_to_close(edge_conn);
+
+ circ = circuit_get_by_edge_conn(edge_conn);
+ if (circ)
+ circuit_detach_stream(circ, edge_conn);
+ if (conn->state == EXIT_CONN_STATE_RESOLVING) {
+ connection_dns_remove(edge_conn);
+ }
+}
+
+/** Define a schedule for how long to wait between retrying
+ * application connections. Rather than waiting a fixed amount of
+ * time between each retry, we wait 10 seconds each for the first
+ * two tries, and 15 seconds for each retry after
+ * that. Hopefully this will improve the expected user experience. */
+static int
+compute_retry_timeout(entry_connection_t *conn)
+{
+ int timeout = get_options()->CircuitStreamTimeout;
+ if (timeout) /* if our config options override the default, use them */
+ return timeout;
+ if (conn->num_socks_retries < 2) /* try 0 and try 1 */
+ return 10;
+ return 15;
+}
+
+/** Find all general-purpose AP streams waiting for a response that sent their
+ * begin/resolve cell too long ago. Detach from their current circuit, and
+ * mark their current circuit as unsuitable for new streams. Then call
+ * connection_ap_handshake_attach_circuit() to attach to a new circuit (if
+ * available) or launch a new one.
+ *
+ * For rendezvous streams, simply give up after SocksTimeout seconds (with no
+ * retry attempt).
+ */
+void
+connection_ap_expire_beginning(void)
+{
+ edge_connection_t *conn;
+ entry_connection_t *entry_conn;
+ circuit_t *circ;
+ time_t now = time(NULL);
+ const or_options_t *options = get_options();
+ int severity;
+ int cutoff;
+ int seconds_idle, seconds_since_born;
+ smartlist_t *conns = get_connection_array();
+
+ SMARTLIST_FOREACH_BEGIN(conns, connection_t *, base_conn) {
+ if (base_conn->type != CONN_TYPE_AP || base_conn->marked_for_close)
+ continue;
+ entry_conn = TO_ENTRY_CONN(base_conn);
+ conn = ENTRY_TO_EDGE_CONN(entry_conn);
+ /* if it's an internal linked connection, don't yell its status. */
+ severity = (tor_addr_is_null(&base_conn->addr) && !base_conn->port)
+ ? LOG_INFO : LOG_NOTICE;
+ seconds_idle = (int)( now - base_conn->timestamp_last_read_allowed );
+ seconds_since_born = (int)( now - base_conn->timestamp_created );
+
+ if (base_conn->state == AP_CONN_STATE_OPEN)
+ continue;
+
+ /* We already consider SocksTimeout in
+ * connection_ap_handshake_attach_circuit(), but we need to consider
+ * it here too because controllers that put streams in controller_wait
+ * state never ask Tor to attach the circuit. */
+ if (AP_CONN_STATE_IS_UNATTACHED(base_conn->state)) {
+ if (seconds_since_born >= options->SocksTimeout) {
+ log_fn(severity, LD_APP,
+ "Tried for %d seconds to get a connection to %s:%d. "
+ "Giving up. (%s)",
+ seconds_since_born,
+ safe_str_client(entry_conn->socks_request->address),
+ entry_conn->socks_request->port,
+ conn_state_to_string(CONN_TYPE_AP, base_conn->state));
+ connection_mark_unattached_ap(entry_conn, END_STREAM_REASON_TIMEOUT);
+ }
+ continue;
+ }
+
+ /* We're in state connect_wait or resolve_wait now -- waiting for a
+ * reply to our relay cell. See if we want to retry/give up. */
+
+ cutoff = compute_retry_timeout(entry_conn);
+ if (seconds_idle < cutoff)
+ continue;
+ circ = circuit_get_by_edge_conn(conn);
+ if (!circ) { /* it's vanished? */
+ log_info(LD_APP,"Conn is waiting (address %s), but lost its circ.",
+ safe_str_client(entry_conn->socks_request->address));
+ connection_mark_unattached_ap(entry_conn, END_STREAM_REASON_TIMEOUT);
+ continue;
+ }
+ if (circ->purpose == CIRCUIT_PURPOSE_C_REND_JOINED) {
+ if (seconds_idle >= options->SocksTimeout) {
+ log_fn(severity, LD_REND,
+ "Rend stream is %d seconds late. Giving up on address"
+ " '%s.onion'.",
+ seconds_idle,
+ safe_str_client(entry_conn->socks_request->address));
+ /* Roll back path bias use state so that we probe the circuit
+ * if nothing else succeeds on it */
+ pathbias_mark_use_rollback(TO_ORIGIN_CIRCUIT(circ));
+
+ connection_edge_end(conn, END_STREAM_REASON_TIMEOUT);
+ connection_mark_unattached_ap(entry_conn, END_STREAM_REASON_TIMEOUT);
+ }
+ continue;
+ }
+
+ if (circ->purpose != CIRCUIT_PURPOSE_C_GENERAL &&
+ circ->purpose != CIRCUIT_PURPOSE_C_HSDIR_GET &&
+ circ->purpose != CIRCUIT_PURPOSE_S_HSDIR_POST &&
+ circ->purpose != CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT &&
+ circ->purpose != CIRCUIT_PURPOSE_PATH_BIAS_TESTING) {
+ log_warn(LD_BUG, "circuit->purpose == CIRCUIT_PURPOSE_C_GENERAL failed. "
+ "The purpose on the circuit was %s; it was in state %s, "
+ "path_state %s.",
+ circuit_purpose_to_string(circ->purpose),
+ circuit_state_to_string(circ->state),
+ CIRCUIT_IS_ORIGIN(circ) ?
+ pathbias_state_to_string(TO_ORIGIN_CIRCUIT(circ)->path_state) :
+ "none");
+ }
+ log_fn(cutoff < 15 ? LOG_INFO : severity, LD_APP,
+ "We tried for %d seconds to connect to '%s' using exit %s."
+ " Retrying on a new circuit.",
+ seconds_idle,
+ safe_str_client(entry_conn->socks_request->address),
+ conn->cpath_layer ?
+ extend_info_describe(conn->cpath_layer->extend_info):
+ "*unnamed*");
+ /* send an end down the circuit */
+ connection_edge_end(conn, END_STREAM_REASON_TIMEOUT);
+ /* un-mark it as ending, since we're going to reuse it */
+ conn->edge_has_sent_end = 0;
+ conn->end_reason = 0;
+ /* make us not try this circuit again, but allow
+ * current streams on it to survive if they can */
+ mark_circuit_unusable_for_new_conns(TO_ORIGIN_CIRCUIT(circ));
+
+ /* give our stream another 'cutoff' seconds to try */
+ conn->base_.timestamp_last_read_allowed += cutoff;
+ if (entry_conn->num_socks_retries < 250) /* avoid overflow */
+ entry_conn->num_socks_retries++;
+ /* move it back into 'pending' state, and try to attach. */
+ if (connection_ap_detach_retriable(entry_conn, TO_ORIGIN_CIRCUIT(circ),
+ END_STREAM_REASON_TIMEOUT)<0) {
+ if (!base_conn->marked_for_close)
+ connection_mark_unattached_ap(entry_conn,
+ END_STREAM_REASON_CANT_ATTACH);
+ }
+ } SMARTLIST_FOREACH_END(base_conn);
+}
+
+/**
+ * As connection_ap_attach_pending, but first scans the entire connection
+ * array to see if any elements are missing.
+ */
+void
+connection_ap_rescan_and_attach_pending(void)
+{
+ entry_connection_t *entry_conn;
+ smartlist_t *conns = get_connection_array();
+
+ if (PREDICT_UNLIKELY(NULL == pending_entry_connections))
+ pending_entry_connections = smartlist_new();
+
+ SMARTLIST_FOREACH_BEGIN(conns, connection_t *, conn) {
+ if (conn->marked_for_close ||
+ conn->type != CONN_TYPE_AP ||
+ conn->state != AP_CONN_STATE_CIRCUIT_WAIT)
+ continue;
+
+ entry_conn = TO_ENTRY_CONN(conn);
+ tor_assert(entry_conn);
+ if (! smartlist_contains(pending_entry_connections, entry_conn)) {
+ log_warn(LD_BUG, "Found a connection %p that was supposed to be "
+ "in pending_entry_connections, but wasn't. No worries; "
+ "adding it.",
+ pending_entry_connections);
+ untried_pending_connections = 1;
+ connection_ap_mark_as_pending_circuit(entry_conn);
+ }
+
+ } SMARTLIST_FOREACH_END(conn);
+
+ connection_ap_attach_pending(1);
+}
+
+#ifdef DEBUGGING_17659
+#define UNMARK() do { \
+ entry_conn->marked_pending_circ_line = 0; \
+ entry_conn->marked_pending_circ_file = 0; \
+ } while (0)
+#else /* !(defined(DEBUGGING_17659)) */
+#define UNMARK() do { } while (0)
+#endif /* defined(DEBUGGING_17659) */
+
+/** Tell any AP streams that are listed as waiting for a new circuit to try
+ * again. If there is an available circuit for a stream, attach it. Otherwise,
+ * launch a new circuit.
+ *
+ * If <b>retry</b> is false, only check the list if it contains at least one
+ * streams that we have not yet tried to attach to a circuit.
+ */
+void
+connection_ap_attach_pending(int retry)
+{
+ if (PREDICT_UNLIKELY(!pending_entry_connections)) {
+ return;
+ }
+
+ if (untried_pending_connections == 0 && !retry)
+ return;
+
+ /* Don't allow any modifications to list while we are iterating over
+ * it. We'll put streams back on this list if we can't attach them
+ * immediately. */
+ smartlist_t *pending = pending_entry_connections;
+ pending_entry_connections = smartlist_new();
+
+ SMARTLIST_FOREACH_BEGIN(pending,
+ entry_connection_t *, entry_conn) {
+ connection_t *conn = ENTRY_TO_CONN(entry_conn);
+ tor_assert(conn && entry_conn);
+ if (conn->marked_for_close) {
+ UNMARK();
+ continue;
+ }
+ if (conn->magic != ENTRY_CONNECTION_MAGIC) {
+ log_warn(LD_BUG, "%p has impossible magic value %u.",
+ entry_conn, (unsigned)conn->magic);
+ UNMARK();
+ continue;
+ }
+ if (conn->state != AP_CONN_STATE_CIRCUIT_WAIT) {
+ log_warn(LD_BUG, "%p is no longer in circuit_wait. Its current state "
+ "is %s. Why is it on pending_entry_connections?",
+ entry_conn,
+ conn_state_to_string(conn->type, conn->state));
+ UNMARK();
+ continue;
+ }
+
+ /* Okay, we're through the sanity checks. Try to handle this stream. */
+ if (connection_ap_handshake_attach_circuit(entry_conn) < 0) {
+ if (!conn->marked_for_close)
+ connection_mark_unattached_ap(entry_conn,
+ END_STREAM_REASON_CANT_ATTACH);
+ }
+
+ if (! conn->marked_for_close &&
+ conn->type == CONN_TYPE_AP &&
+ conn->state == AP_CONN_STATE_CIRCUIT_WAIT) {
+ /* Is it still waiting for a circuit? If so, we didn't attach it,
+ * so it's still pending. Put it back on the list.
+ */
+ if (!smartlist_contains(pending_entry_connections, entry_conn)) {
+ smartlist_add(pending_entry_connections, entry_conn);
+ continue;
+ }
+ }
+
+ /* If we got here, then we either closed the connection, or
+ * we attached it. */
+ UNMARK();
+ } SMARTLIST_FOREACH_END(entry_conn);
+
+ smartlist_free(pending);
+ untried_pending_connections = 0;
+}
+
+static void
+attach_pending_entry_connections_cb(mainloop_event_t *ev, void *arg)
+{
+ (void)ev;
+ (void)arg;
+ connection_ap_attach_pending(0);
+}
+
+/** Mark <b>entry_conn</b> as needing to get attached to a circuit.
+ *
+ * And <b>entry_conn</b> must be in AP_CONN_STATE_CIRCUIT_WAIT,
+ * should not already be pending a circuit. The circuit will get
+ * launched or the connection will get attached the next time we
+ * call connection_ap_attach_pending().
+ */
+void
+connection_ap_mark_as_pending_circuit_(entry_connection_t *entry_conn,
+ const char *fname, int lineno)
+{
+ connection_t *conn = ENTRY_TO_CONN(entry_conn);
+ tor_assert(conn->state == AP_CONN_STATE_CIRCUIT_WAIT);
+ tor_assert(conn->magic == ENTRY_CONNECTION_MAGIC);
+ if (conn->marked_for_close)
+ return;
+
+ if (PREDICT_UNLIKELY(NULL == pending_entry_connections)) {
+ pending_entry_connections = smartlist_new();
+ }
+ if (PREDICT_UNLIKELY(NULL == attach_pending_entry_connections_ev)) {
+ attach_pending_entry_connections_ev = mainloop_event_postloop_new(
+ attach_pending_entry_connections_cb, NULL);
+ }
+ if (PREDICT_UNLIKELY(smartlist_contains(pending_entry_connections,
+ entry_conn))) {
+ log_warn(LD_BUG, "What?? pending_entry_connections already contains %p! "
+ "(Called from %s:%d.)",
+ entry_conn, fname, lineno);
+#ifdef DEBUGGING_17659
+ const char *f2 = entry_conn->marked_pending_circ_file;
+ log_warn(LD_BUG, "(Previously called from %s:%d.)\n",
+ f2 ? f2 : "<NULL>",
+ entry_conn->marked_pending_circ_line);
+#endif /* defined(DEBUGGING_17659) */
+ log_backtrace(LOG_WARN, LD_BUG, "To debug, this may help");
+ return;
+ }
+
+#ifdef DEBUGGING_17659
+ entry_conn->marked_pending_circ_line = (uint16_t) lineno;
+ entry_conn->marked_pending_circ_file = fname;
+#endif
+
+ untried_pending_connections = 1;
+ smartlist_add(pending_entry_connections, entry_conn);
+
+ mainloop_event_activate(attach_pending_entry_connections_ev);
+}
+
+/** Mark <b>entry_conn</b> as no longer waiting for a circuit. */
+void
+connection_ap_mark_as_non_pending_circuit(entry_connection_t *entry_conn)
+{
+ if (PREDICT_UNLIKELY(NULL == pending_entry_connections))
+ return;
+ UNMARK();
+ smartlist_remove(pending_entry_connections, entry_conn);
+}
+
+/* DOCDOC */
+void
+connection_ap_warn_and_unmark_if_pending_circ(entry_connection_t *entry_conn,
+ const char *where)
+{
+ if (pending_entry_connections &&
+ smartlist_contains(pending_entry_connections, entry_conn)) {
+ log_warn(LD_BUG, "What was %p doing in pending_entry_connections in %s?",
+ entry_conn, where);
+ connection_ap_mark_as_non_pending_circuit(entry_conn);
+ }
+}
+
+/** Tell any AP streams that are waiting for a one-hop tunnel to
+ * <b>failed_digest</b> that they are going to fail. */
+/* XXXX We should get rid of this function, and instead attach
+ * one-hop streams to circ->p_streams so they get marked in
+ * circuit_mark_for_close like normal p_streams. */
+void
+connection_ap_fail_onehop(const char *failed_digest,
+ cpath_build_state_t *build_state)
+{
+ entry_connection_t *entry_conn;
+ char digest[DIGEST_LEN];
+ smartlist_t *conns = get_connection_array();
+ SMARTLIST_FOREACH_BEGIN(conns, connection_t *, conn) {
+ if (conn->marked_for_close ||
+ conn->type != CONN_TYPE_AP ||
+ conn->state != AP_CONN_STATE_CIRCUIT_WAIT)
+ continue;
+ entry_conn = TO_ENTRY_CONN(conn);
+ if (!entry_conn->want_onehop)
+ continue;
+ if (hexdigest_to_digest(entry_conn->chosen_exit_name, digest) < 0 ||
+ tor_memneq(digest, failed_digest, DIGEST_LEN))
+ continue;
+ if (tor_digest_is_zero(digest)) {
+ /* we don't know the digest; have to compare addr:port */
+ tor_addr_t addr;
+ if (!build_state || !build_state->chosen_exit ||
+ !entry_conn->socks_request) {
+ continue;
+ }
+ if (tor_addr_parse(&addr, entry_conn->socks_request->address)<0 ||
+ !tor_addr_eq(&build_state->chosen_exit->addr, &addr) ||
+ build_state->chosen_exit->port != entry_conn->socks_request->port)
+ continue;
+ }
+ log_info(LD_APP, "Closing one-hop stream to '%s/%s' because the OR conn "
+ "just failed.", entry_conn->chosen_exit_name,
+ entry_conn->socks_request->address);
+ connection_mark_unattached_ap(entry_conn, END_STREAM_REASON_TIMEOUT);
+ } SMARTLIST_FOREACH_END(conn);
+}
+
+/** A circuit failed to finish on its last hop <b>info</b>. If there
+ * are any streams waiting with this exit node in mind, but they
+ * don't absolutely require it, make them give up on it.
+ */
+void
+circuit_discard_optional_exit_enclaves(extend_info_t *info)
+{
+ entry_connection_t *entry_conn;
+ const node_t *r1, *r2;
+
+ smartlist_t *conns = get_connection_array();
+ SMARTLIST_FOREACH_BEGIN(conns, connection_t *, conn) {
+ if (conn->marked_for_close ||
+ conn->type != CONN_TYPE_AP ||
+ conn->state != AP_CONN_STATE_CIRCUIT_WAIT)
+ continue;
+ entry_conn = TO_ENTRY_CONN(conn);
+ if (!entry_conn->chosen_exit_optional &&
+ !entry_conn->chosen_exit_retries)
+ continue;
+ r1 = node_get_by_nickname(entry_conn->chosen_exit_name,
+ NNF_NO_WARN_UNNAMED);
+ r2 = node_get_by_id(info->identity_digest);
+ if (!r1 || !r2 || r1 != r2)
+ continue;
+ tor_assert(entry_conn->socks_request);
+ if (entry_conn->chosen_exit_optional) {
+ log_info(LD_APP, "Giving up on enclave exit '%s' for destination %s.",
+ safe_str_client(entry_conn->chosen_exit_name),
+ escaped_safe_str_client(entry_conn->socks_request->address));
+ entry_conn->chosen_exit_optional = 0;
+ tor_free(entry_conn->chosen_exit_name); /* clears it */
+ /* if this port is dangerous, warn or reject it now that we don't
+ * think it'll be using an enclave. */
+ consider_plaintext_ports(entry_conn, entry_conn->socks_request->port);
+ }
+ if (entry_conn->chosen_exit_retries) {
+ if (--entry_conn->chosen_exit_retries == 0) { /* give up! */
+ clear_trackexithost_mappings(entry_conn->chosen_exit_name);
+ tor_free(entry_conn->chosen_exit_name); /* clears it */
+ /* if this port is dangerous, warn or reject it now that we don't
+ * think it'll be using an enclave. */
+ consider_plaintext_ports(entry_conn, entry_conn->socks_request->port);
+ }
+ }
+ } SMARTLIST_FOREACH_END(conn);
+}
+
+/** The AP connection <b>conn</b> has just failed while attaching or
+ * sending a BEGIN or resolving on <b>circ</b>, but another circuit
+ * might work. Detach the circuit, and either reattach it, launch a
+ * new circuit, tell the controller, or give up as appropriate.
+ *
+ * Returns -1 on err, 1 on success, 0 on not-yet-sure.
+ */
+int
+connection_ap_detach_retriable(entry_connection_t *conn,
+ origin_circuit_t *circ,
+ int reason)
+{
+ control_event_stream_status(conn, STREAM_EVENT_FAILED_RETRIABLE, reason);
+ ENTRY_TO_CONN(conn)->timestamp_last_read_allowed = time(NULL);
+
+ /* Roll back path bias use state so that we probe the circuit
+ * if nothing else succeeds on it */
+ pathbias_mark_use_rollback(circ);
+
+ if (conn->pending_optimistic_data) {
+ buf_set_to_copy(&conn->sending_optimistic_data,
+ conn->pending_optimistic_data);
+ }
+
+ if (!get_options()->LeaveStreamsUnattached || conn->use_begindir) {
+ /* If we're attaching streams ourself, or if this connection is
+ * a tunneled directory connection, then just attach it. */
+ ENTRY_TO_CONN(conn)->state = AP_CONN_STATE_CIRCUIT_WAIT;
+ circuit_detach_stream(TO_CIRCUIT(circ),ENTRY_TO_EDGE_CONN(conn));
+ connection_ap_mark_as_pending_circuit(conn);
+ } else {
+ CONNECTION_AP_EXPECT_NONPENDING(conn);
+ ENTRY_TO_CONN(conn)->state = AP_CONN_STATE_CONTROLLER_WAIT;
+ circuit_detach_stream(TO_CIRCUIT(circ),ENTRY_TO_EDGE_CONN(conn));
+ }
+ return 0;
+}
+
+/** Check if <b>conn</b> is using a dangerous port. Then warn and/or
+ * reject depending on our config options. */
+static int
+consider_plaintext_ports(entry_connection_t *conn, uint16_t port)
+{
+ const or_options_t *options = get_options();
+ int reject = smartlist_contains_int_as_string(
+ options->RejectPlaintextPorts, port);
+
+ if (smartlist_contains_int_as_string(options->WarnPlaintextPorts, port)) {
+ log_warn(LD_APP, "Application request to port %d: this port is "
+ "commonly used for unencrypted protocols. Please make sure "
+ "you don't send anything you would mind the rest of the "
+ "Internet reading!%s", port, reject ? " Closing." : "");
+ control_event_client_status(LOG_WARN, "DANGEROUS_PORT PORT=%d RESULT=%s",
+ port, reject ? "REJECT" : "WARN");
+ }
+
+ if (reject) {
+ log_info(LD_APP, "Port %d listed in RejectPlaintextPorts. Closing.", port);
+ connection_mark_unattached_ap(conn, END_STREAM_REASON_ENTRYPOLICY);
+ return -1;
+ }
+
+ return 0;
+}
+
+/** How many times do we try connecting with an exit configured via
+ * TrackHostExits before concluding that it won't work any more and trying a
+ * different one? */
+#define TRACKHOSTEXITS_RETRIES 5
+
+/** Call connection_ap_handshake_rewrite_and_attach() unless a controller
+ * asked us to leave streams unattached. Return 0 in that case.
+ *
+ * See connection_ap_handshake_rewrite_and_attach()'s
+ * documentation for arguments and return value.
+ */
+MOCK_IMPL(int,
+connection_ap_rewrite_and_attach_if_allowed,(entry_connection_t *conn,
+ origin_circuit_t *circ,
+ crypt_path_t *cpath))
+{
+ const or_options_t *options = get_options();
+
+ if (options->LeaveStreamsUnattached) {
+ CONNECTION_AP_EXPECT_NONPENDING(conn);
+ ENTRY_TO_CONN(conn)->state = AP_CONN_STATE_CONTROLLER_WAIT;
+ return 0;
+ }
+ return connection_ap_handshake_rewrite_and_attach(conn, circ, cpath);
+}
+
+/* Try to perform any map-based rewriting of the target address in
+ * <b>conn</b>, filling in the fields of <b>out</b> as we go, and modifying
+ * conn->socks_request.address as appropriate.
+ */
+STATIC void
+connection_ap_handshake_rewrite(entry_connection_t *conn,
+ rewrite_result_t *out)
+{
+ socks_request_t *socks = conn->socks_request;
+ const or_options_t *options = get_options();
+ tor_addr_t addr_tmp;
+
+ /* Initialize all the fields of 'out' to reasonable defaults */
+ out->automap = 0;
+ out->exit_source = ADDRMAPSRC_NONE;
+ out->map_expires = TIME_MAX;
+ out->end_reason = 0;
+ out->should_close = 0;
+ out->orig_address[0] = 0;
+
+ /* We convert all incoming addresses to lowercase. */
+ tor_strlower(socks->address);
+ /* Remember the original address. */
+ strlcpy(out->orig_address, socks->address, sizeof(out->orig_address));
+ log_debug(LD_APP,"Client asked for %s:%d",
+ safe_str_client(socks->address),
+ socks->port);
+
+ /* Check for whether this is a .exit address. By default, those are
+ * disallowed when they're coming straight from the client, but you're
+ * allowed to have them in MapAddress commands and so forth. */
+ if (!strcmpend(socks->address, ".exit")) {
+ log_warn(LD_APP, "The \".exit\" notation is disabled in Tor due to "
+ "security risks.");
+ control_event_client_status(LOG_WARN, "SOCKS_BAD_HOSTNAME HOSTNAME=%s",
+ escaped(socks->address));
+ out->end_reason = END_STREAM_REASON_TORPROTOCOL;
+ out->should_close = 1;
+ return;
+ }
+
+ /* Remember the original address so we can tell the user about what
+ * they actually said, not just what it turned into. */
+ /* XXX yes, this is the same as out->orig_address above. One is
+ * in the output, and one is in the connection. */
+ if (! conn->original_dest_address) {
+ /* Is the 'if' necessary here? XXXX */
+ conn->original_dest_address = tor_strdup(conn->socks_request->address);
+ }
+
+ /* First, apply MapAddress and MAPADDRESS mappings. We need to do
+ * these only for non-reverse lookups, since they don't exist for those.
+ * We also need to do this before we consider automapping, since we might
+ * e.g. resolve irc.oftc.net into irconionaddress.onion, at which point
+ * we'd need to automap it. */
+ if (socks->command != SOCKS_COMMAND_RESOLVE_PTR) {
+ const unsigned rewrite_flags = AMR_FLAG_USE_MAPADDRESS;
+ if (addressmap_rewrite(socks->address, sizeof(socks->address),
+ rewrite_flags, &out->map_expires, &out->exit_source)) {
+ control_event_stream_status(conn, STREAM_EVENT_REMAP,
+ REMAP_STREAM_SOURCE_CACHE);
+ }
+ }
+
+ /* Now see if we need to create or return an existing Hostname->IP
+ * automapping. Automapping happens when we're asked to resolve a
+ * hostname, and AutomapHostsOnResolve is set, and the hostname has a
+ * suffix listed in AutomapHostsSuffixes. It's a handy feature
+ * that lets you have Tor assign e.g. IPv6 addresses for .onion
+ * names, and return them safely from DNSPort.
+ */
+ if (socks->command == SOCKS_COMMAND_RESOLVE &&
+ tor_addr_parse(&addr_tmp, socks->address)<0 &&
+ options->AutomapHostsOnResolve) {
+ /* Check the suffix... */
+ out->automap = addressmap_address_should_automap(socks->address, options);
+ if (out->automap) {
+ /* If we get here, then we should apply an automapping for this. */
+ const char *new_addr;
+ /* We return an IPv4 address by default, or an IPv6 address if we
+ * are allowed to do so. */
+ int addr_type = RESOLVED_TYPE_IPV4;
+ if (conn->socks_request->socks_version != 4) {
+ if (!conn->entry_cfg.ipv4_traffic ||
+ (conn->entry_cfg.ipv6_traffic && conn->entry_cfg.prefer_ipv6) ||
+ conn->entry_cfg.prefer_ipv6_virtaddr)
+ addr_type = RESOLVED_TYPE_IPV6;
+ }
+ /* Okay, register the target address as automapped, and find the new
+ * address we're supposed to give as a resolve answer. (Return a cached
+ * value if we've looked up this address before.
+ */
+ new_addr = addressmap_register_virtual_address(
+ addr_type, tor_strdup(socks->address));
+ if (! new_addr) {
+ log_warn(LD_APP, "Unable to automap address %s",
+ escaped_safe_str(socks->address));
+ out->end_reason = END_STREAM_REASON_INTERNAL;
+ out->should_close = 1;
+ return;
+ }
+ log_info(LD_APP, "Automapping %s to %s",
+ escaped_safe_str_client(socks->address),
+ safe_str_client(new_addr));
+ strlcpy(socks->address, new_addr, sizeof(socks->address));
+ }
+ }
+
+ /* Now handle reverse lookups, if they're in the cache. This doesn't
+ * happen too often, since client-side DNS caching is off by default,
+ * and very deprecated. */
+ if (socks->command == SOCKS_COMMAND_RESOLVE_PTR) {
+ unsigned rewrite_flags = 0;
+ if (conn->entry_cfg.use_cached_ipv4_answers)
+ rewrite_flags |= AMR_FLAG_USE_IPV4_DNS;
+ if (conn->entry_cfg.use_cached_ipv6_answers)
+ rewrite_flags |= AMR_FLAG_USE_IPV6_DNS;
+
+ if (addressmap_rewrite_reverse(socks->address, sizeof(socks->address),
+ rewrite_flags, &out->map_expires)) {
+ char *result = tor_strdup(socks->address);
+ /* remember _what_ is supposed to have been resolved. */
+ tor_snprintf(socks->address, sizeof(socks->address), "REVERSE[%s]",
+ out->orig_address);
+ connection_ap_handshake_socks_resolved(conn, RESOLVED_TYPE_HOSTNAME,
+ strlen(result), (uint8_t*)result,
+ -1,
+ out->map_expires);
+ tor_free(result);
+ out->end_reason = END_STREAM_REASON_DONE |
+ END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED;
+ out->should_close = 1;
+ return;
+ }
+
+ /* Hang on, did we find an answer saying that this is a reverse lookup for
+ * an internal address? If so, we should reject it if we're configured to
+ * do so. */
+ if (options->ClientDNSRejectInternalAddresses) {
+ /* Don't let clients try to do a reverse lookup on 10.0.0.1. */
+ tor_addr_t addr;
+ int ok;
+ ok = tor_addr_parse_PTR_name(
+ &addr, socks->address, AF_UNSPEC, 1);
+ if (ok == 1 && tor_addr_is_internal(&addr, 0)) {
+ connection_ap_handshake_socks_resolved(conn, RESOLVED_TYPE_ERROR,
+ 0, NULL, -1, TIME_MAX);
+ out->end_reason = END_STREAM_REASON_SOCKSPROTOCOL |
+ END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED;
+ out->should_close = 1;
+ return;
+ }
+ }
+ }
+
+ /* If we didn't automap it before, then this is still the address that
+ * came straight from the user, mapped according to any
+ * MapAddress/MAPADDRESS commands. Now apply other mappings,
+ * including previously registered Automap entries (IP back to
+ * hostname), TrackHostExits entries, and client-side DNS cache
+ * entries (if they're turned on).
+ */
+ if (socks->command != SOCKS_COMMAND_RESOLVE_PTR &&
+ !out->automap) {
+ unsigned rewrite_flags = AMR_FLAG_USE_AUTOMAP | AMR_FLAG_USE_TRACKEXIT;
+ addressmap_entry_source_t exit_source2;
+ if (conn->entry_cfg.use_cached_ipv4_answers)
+ rewrite_flags |= AMR_FLAG_USE_IPV4_DNS;
+ if (conn->entry_cfg.use_cached_ipv6_answers)
+ rewrite_flags |= AMR_FLAG_USE_IPV6_DNS;
+ if (addressmap_rewrite(socks->address, sizeof(socks->address),
+ rewrite_flags, &out->map_expires, &exit_source2)) {
+ control_event_stream_status(conn, STREAM_EVENT_REMAP,
+ REMAP_STREAM_SOURCE_CACHE);
+ }
+ if (out->exit_source == ADDRMAPSRC_NONE) {
+ /* If it wasn't a .exit before, maybe it turned into a .exit. Remember
+ * the original source of a .exit. */
+ out->exit_source = exit_source2;
+ }
+ }
+
+ /* Check to see whether we're about to use an address in the virtual
+ * range without actually having gotten it from an Automap. */
+ if (!out->automap && address_is_in_virtual_range(socks->address)) {
+ /* This address was probably handed out by
+ * client_dns_get_unmapped_address, but the mapping was discarded for some
+ * reason. Or the user typed in a virtual address range manually. We
+ * *don't* want to send the address through Tor; that's likely to fail,
+ * and may leak information.
+ */
+ log_warn(LD_APP,"Missing mapping for virtual address '%s'. Refusing.",
+ safe_str_client(socks->address));
+ out->end_reason = END_STREAM_REASON_INTERNAL;
+ out->should_close = 1;
+ return;
+ }
+}
+
+/** We just received a SOCKS request in <b>conn</b> to an onion address of type
+ * <b>addresstype</b>. Start connecting to the onion service. */
+static int
+connection_ap_handle_onion(entry_connection_t *conn,
+ socks_request_t *socks,
+ origin_circuit_t *circ,
+ hostname_type_t addresstype)
+{
+ time_t now = approx_time();
+ connection_t *base_conn = ENTRY_TO_CONN(conn);
+
+ /* If .onion address requests are disabled, refuse the request */
+ if (!conn->entry_cfg.onion_traffic) {
+ log_warn(LD_APP, "Onion address %s requested from a port with .onion "
+ "disabled", safe_str_client(socks->address));
+ connection_mark_unattached_ap(conn, END_STREAM_REASON_ENTRYPOLICY);
+ return -1;
+ }
+
+ /* Check whether it's RESOLVE or RESOLVE_PTR. We don't handle those
+ * for hidden service addresses. */
+ if (SOCKS_COMMAND_IS_RESOLVE(socks->command)) {
+ /* if it's a resolve request, fail it right now, rather than
+ * building all the circuits and then realizing it won't work. */
+ log_warn(LD_APP,
+ "Resolve requests to hidden services not allowed. Failing.");
+ connection_ap_handshake_socks_resolved(conn,RESOLVED_TYPE_ERROR,
+ 0,NULL,-1,TIME_MAX);
+ connection_mark_unattached_ap(conn,
+ END_STREAM_REASON_SOCKSPROTOCOL |
+ END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED);
+ return -1;
+ }
+
+ /* If we were passed a circuit, then we need to fail. .onion addresses
+ * only work when we launch our own circuits for now. */
+ if (circ) {
+ log_warn(LD_CONTROL, "Attachstream to a circuit is not "
+ "supported for .onion addresses currently. Failing.");
+ connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL);
+ return -1;
+ }
+
+ /* Interface: Regardless of HS version after the block below we should have
+ set onion_address, rend_cache_lookup_result, and descriptor_is_usable. */
+ const char *onion_address = NULL;
+ int rend_cache_lookup_result = -ENOENT;
+ int descriptor_is_usable = 0;
+
+ if (addresstype == ONION_V2_HOSTNAME) { /* it's a v2 hidden service */
+ rend_cache_entry_t *entry = NULL;
+ /* Look up if we have client authorization configured for this hidden
+ * service. If we do, associate it with the rend_data. */
+ rend_service_authorization_t *client_auth =
+ rend_client_lookup_service_authorization(socks->address);
+
+ const uint8_t *cookie = NULL;
+ rend_auth_type_t auth_type = REND_NO_AUTH;
+ if (client_auth) {
+ log_info(LD_REND, "Using previously configured client authorization "
+ "for hidden service request.");
+ auth_type = client_auth->auth_type;
+ cookie = client_auth->descriptor_cookie;
+ }
+
+ /* Fill in the rend_data field so we can start doing a connection to
+ * a hidden service. */
+ rend_data_t *rend_data = ENTRY_TO_EDGE_CONN(conn)->rend_data =
+ rend_data_client_create(socks->address, NULL, (char *) cookie,
+ auth_type);
+ if (rend_data == NULL) {
+ return -1;
+ }
+ onion_address = rend_data_get_address(rend_data);
+ log_info(LD_REND,"Got a hidden service request for ID '%s'",
+ safe_str_client(onion_address));
+
+ rend_cache_lookup_result = rend_cache_lookup_entry(onion_address,-1,
+ &entry);
+ if (!rend_cache_lookup_result && entry) {
+ descriptor_is_usable = rend_client_any_intro_points_usable(entry);
+ }
+ } else { /* it's a v3 hidden service */
+ tor_assert(addresstype == ONION_V3_HOSTNAME);
+ const hs_descriptor_t *cached_desc = NULL;
+ int retval;
+ /* Create HS conn identifier with HS pubkey */
+ hs_ident_edge_conn_t *hs_conn_ident =
+ tor_malloc_zero(sizeof(hs_ident_edge_conn_t));
+
+ retval = hs_parse_address(socks->address, &hs_conn_ident->identity_pk,
+ NULL, NULL);
+ if (retval < 0) {
+ log_warn(LD_GENERAL, "failed to parse hs address");
+ tor_free(hs_conn_ident);
+ return -1;
+ }
+ ENTRY_TO_EDGE_CONN(conn)->hs_ident = hs_conn_ident;
+
+ onion_address = socks->address;
+
+ /* Check the v3 desc cache */
+ cached_desc = hs_cache_lookup_as_client(&hs_conn_ident->identity_pk);
+ if (cached_desc) {
+ rend_cache_lookup_result = 0;
+ descriptor_is_usable =
+ hs_client_any_intro_points_usable(&hs_conn_ident->identity_pk,
+ cached_desc);
+ log_info(LD_GENERAL, "Found %s descriptor in cache for %s. %s.",
+ (descriptor_is_usable) ? "usable" : "unusable",
+ safe_str_client(onion_address),
+ (descriptor_is_usable) ? "Not fetching." : "Refecting.");
+ } else {
+ rend_cache_lookup_result = -ENOENT;
+ }
+ }
+
+ /* Lookup the given onion address. If invalid, stop right now.
+ * Otherwise, we might have it in the cache or not. */
+ unsigned int refetch_desc = 0;
+ if (rend_cache_lookup_result < 0) {
+ switch (-rend_cache_lookup_result) {
+ case EINVAL:
+ /* We should already have rejected this address! */
+ log_warn(LD_BUG,"Invalid service name '%s'",
+ safe_str_client(onion_address));
+ connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL);
+ return -1;
+ case ENOENT:
+ /* We didn't have this; we should look it up. */
+ log_info(LD_REND, "No descriptor found in our cache for %s. Fetching.",
+ safe_str_client(onion_address));
+ refetch_desc = 1;
+ break;
+ default:
+ log_warn(LD_BUG, "Unknown cache lookup error %d",
+ rend_cache_lookup_result);
+ return -1;
+ }
+ }
+
+ /* Help predict that we'll want to do hidden service circuits in the
+ * future. We're not sure if it will need a stable circuit yet, but
+ * we know we'll need *something*. */
+ rep_hist_note_used_internal(now, 0, 1);
+
+ /* Now we have a descriptor but is it usable or not? If not, refetch.
+ * Also, a fetch could have been requested if the onion address was not
+ * found in the cache previously. */
+ if (refetch_desc || !descriptor_is_usable) {
+ edge_connection_t *edge_conn = ENTRY_TO_EDGE_CONN(conn);
+ connection_ap_mark_as_non_pending_circuit(conn);
+ base_conn->state = AP_CONN_STATE_RENDDESC_WAIT;
+ if (addresstype == ONION_V2_HOSTNAME) {
+ tor_assert(edge_conn->rend_data);
+ rend_client_refetch_v2_renddesc(edge_conn->rend_data);
+ /* Whatever the result of the refetch, we don't go further. */
+ return 0;
+ } else {
+ tor_assert(addresstype == ONION_V3_HOSTNAME);
+ tor_assert(edge_conn->hs_ident);
+ /* Attempt to fetch the hsv3 descriptor. Check the retval to see how it
+ * went and act accordingly. */
+ int ret = hs_client_refetch_hsdesc(&edge_conn->hs_ident->identity_pk);
+ switch (ret) {
+ case HS_CLIENT_FETCH_MISSING_INFO:
+ /* Keeping the connection in descriptor wait state is fine because
+ * once we get enough dirinfo or a new live consensus, the HS client
+ * subsystem is notified and every connection in that state will
+ * trigger a fetch for the service key. */
+ case HS_CLIENT_FETCH_LAUNCHED:
+ case HS_CLIENT_FETCH_PENDING:
+ case HS_CLIENT_FETCH_HAVE_DESC:
+ return 0;
+ case HS_CLIENT_FETCH_ERROR:
+ case HS_CLIENT_FETCH_NO_HSDIRS:
+ case HS_CLIENT_FETCH_NOT_ALLOWED:
+ /* Can't proceed further and better close the SOCKS request. */
+ return -1;
+ }
+ }
+ }
+
+ /* We have the descriptor! So launch a connection to the HS. */
+ log_info(LD_REND, "Descriptor is here. Great.");
+
+ base_conn->state = AP_CONN_STATE_CIRCUIT_WAIT;
+ /* We'll try to attach it at the next event loop, or whenever
+ * we call connection_ap_attach_pending() */
+ connection_ap_mark_as_pending_circuit(conn);
+ return 0;
+}
+
+/** Connection <b>conn</b> just finished its socks handshake, or the
+ * controller asked us to take care of it. If <b>circ</b> is defined,
+ * then that's where we'll want to attach it. Otherwise we have to
+ * figure it out ourselves.
+ *
+ * First, parse whether it's a .exit address, remap it, and so on. Then
+ * if it's for a general circuit, try to attach it to a circuit (or launch
+ * one as needed), else if it's for a rendezvous circuit, fetch a
+ * rendezvous descriptor first (or attach/launch a circuit if the
+ * rendezvous descriptor is already here and fresh enough).
+ *
+ * The stream will exit from the hop
+ * indicated by <b>cpath</b>, or from the last hop in circ's cpath if
+ * <b>cpath</b> is NULL.
+ */
+int
+connection_ap_handshake_rewrite_and_attach(entry_connection_t *conn,
+ origin_circuit_t *circ,
+ crypt_path_t *cpath)
+{
+ socks_request_t *socks = conn->socks_request;
+ const or_options_t *options = get_options();
+ connection_t *base_conn = ENTRY_TO_CONN(conn);
+ time_t now = time(NULL);
+ rewrite_result_t rr;
+
+ /* First we'll do the rewrite part. Let's see if we get a reasonable
+ * answer.
+ */
+ memset(&rr, 0, sizeof(rr));
+ connection_ap_handshake_rewrite(conn,&rr);
+
+ if (rr.should_close) {
+ /* connection_ap_handshake_rewrite told us to close the connection:
+ * either because it sent back an answer, or because it sent back an
+ * error */
+ connection_mark_unattached_ap(conn, rr.end_reason);
+ if (END_STREAM_REASON_DONE == (rr.end_reason & END_STREAM_REASON_MASK))
+ return 0;
+ else
+ return -1;
+ }
+
+ const time_t map_expires = rr.map_expires;
+ const int automap = rr.automap;
+ const addressmap_entry_source_t exit_source = rr.exit_source;
+
+ /* Now, we parse the address to see if it's an .onion or .exit or
+ * other special address.
+ */
+ const hostname_type_t addresstype = parse_extended_hostname(socks->address);
+
+ /* Now see whether the hostname is bogus. This could happen because of an
+ * onion hostname whose format we don't recognize. */
+ if (addresstype == BAD_HOSTNAME) {
+ control_event_client_status(LOG_WARN, "SOCKS_BAD_HOSTNAME HOSTNAME=%s",
+ escaped(socks->address));
+ connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL);
+ return -1;
+ }
+
+ /* If this is a .exit hostname, strip off the .name.exit part, and
+ * see whether we're willing to connect there, and and otherwise handle the
+ * .exit address.
+ *
+ * We'll set chosen_exit_name and/or close the connection as appropriate.
+ */
+ if (addresstype == EXIT_HOSTNAME) {
+ /* If StrictNodes is not set, then .exit overrides ExcludeNodes but
+ * not ExcludeExitNodes. */
+ routerset_t *excludeset = options->StrictNodes ?
+ options->ExcludeExitNodesUnion_ : options->ExcludeExitNodes;
+ const node_t *node = NULL;
+
+ /* If this .exit was added by an AUTOMAP, then it came straight from
+ * a user. That's not safe. */
+ if (exit_source == ADDRMAPSRC_AUTOMAP) {
+ /* Whoops; this one is stale. It must have gotten added earlier?
+ * (Probably this is not possible, since AllowDotExit no longer
+ * exists.) */
+ log_warn(LD_APP,"Stale automapped address for '%s.exit'. Refusing.",
+ safe_str_client(socks->address));
+ control_event_client_status(LOG_WARN, "SOCKS_BAD_HOSTNAME HOSTNAME=%s",
+ escaped(socks->address));
+ connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL);
+ tor_assert_nonfatal_unreached();
+ return -1;
+ }
+
+ /* Double-check to make sure there are no .exits coming from
+ * impossible/weird sources. */
+ if (exit_source == ADDRMAPSRC_DNS || exit_source == ADDRMAPSRC_NONE) {
+ /* It shouldn't be possible to get a .exit address from any of these
+ * sources. */
+ log_warn(LD_BUG,"Address '%s.exit', with impossible source for the "
+ ".exit part. Refusing.",
+ safe_str_client(socks->address));
+ control_event_client_status(LOG_WARN, "SOCKS_BAD_HOSTNAME HOSTNAME=%s",
+ escaped(socks->address));
+ connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL);
+ return -1;
+ }
+
+ tor_assert(!automap);
+
+ /* Now, find the character before the .(name) part.
+ * (The ".exit" part got stripped off by "parse_extended_hostname").
+ *
+ * We're going to put the exit name into conn->chosen_exit_name, and
+ * look up a node correspondingly. */
+ char *s = strrchr(socks->address,'.');
+ if (s) {
+ /* The address was of the form "(stuff).(name).exit */
+ if (s[1] != '\0') {
+ /* Looks like a real .exit one. */
+ conn->chosen_exit_name = tor_strdup(s+1);
+ node = node_get_by_nickname(conn->chosen_exit_name, 0);
+
+ if (exit_source == ADDRMAPSRC_TRACKEXIT) {
+ /* We 5 tries before it expires the addressmap */
+ conn->chosen_exit_retries = TRACKHOSTEXITS_RETRIES;
+ }
+ *s = 0;
+ } else {
+ /* Oops, the address was (stuff)..exit. That's not okay. */
+ log_warn(LD_APP,"Malformed exit address '%s.exit'. Refusing.",
+ safe_str_client(socks->address));
+ control_event_client_status(LOG_WARN, "SOCKS_BAD_HOSTNAME HOSTNAME=%s",
+ escaped(socks->address));
+ connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL);
+ return -1;
+ }
+ } else {
+ /* It looks like they just asked for "foo.exit". That's a special
+ * form that means (foo's address).foo.exit. */
+
+ conn->chosen_exit_name = tor_strdup(socks->address);
+ node = node_get_by_nickname(conn->chosen_exit_name, 0);
+ if (node) {
+ *socks->address = 0;
+ node_get_address_string(node, socks->address, sizeof(socks->address));
+ }
+ }
+
+ /* Now make sure that the chosen exit exists... */
+ if (!node) {
+ log_warn(LD_APP,
+ "Unrecognized relay in exit address '%s.exit'. Refusing.",
+ safe_str_client(socks->address));
+ connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL);
+ return -1;
+ }
+ /* ...and make sure that it isn't excluded. */
+ if (routerset_contains_node(excludeset, node)) {
+ log_warn(LD_APP,
+ "Excluded relay in exit address '%s.exit'. Refusing.",
+ safe_str_client(socks->address));
+ connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL);
+ return -1;
+ }
+ /* XXXX-1090 Should we also allow foo.bar.exit if ExitNodes is set and
+ Bar is not listed in it? I say yes, but our revised manpage branch
+ implies no. */
+ }
+
+ /* Now, we handle everything that isn't a .onion address. */
+ if (addresstype != ONION_V2_HOSTNAME && addresstype != ONION_V3_HOSTNAME) {
+ /* Not a hidden-service request. It's either a hostname or an IP,
+ * possibly with a .exit that we stripped off. We're going to check
+ * if we're allowed to connect/resolve there, and then launch the
+ * appropriate request. */
+
+ /* Check for funny characters in the address. */
+ if (address_is_invalid_destination(socks->address, 1)) {
+ control_event_client_status(LOG_WARN, "SOCKS_BAD_HOSTNAME HOSTNAME=%s",
+ escaped(socks->address));
+ log_warn(LD_APP,
+ "Destination '%s' seems to be an invalid hostname. Failing.",
+ safe_str_client(socks->address));
+ connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL);
+ return -1;
+ }
+
+ /* socks->address is a non-onion hostname or IP address.
+ * If we can't do any non-onion requests, refuse the connection.
+ * If we have a hostname but can't do DNS, refuse the connection.
+ * If we have an IP address, but we can't use that address family,
+ * refuse the connection.
+ *
+ * If we can do DNS requests, and we can use at least one address family,
+ * then we have to resolve the address first. Then we'll know if it
+ * resolves to a usable address family. */
+
+ /* First, check if all non-onion traffic is disabled */
+ if (!conn->entry_cfg.dns_request && !conn->entry_cfg.ipv4_traffic
+ && !conn->entry_cfg.ipv6_traffic) {
+ log_warn(LD_APP, "Refusing to connect to non-hidden-service hostname "
+ "or IP address %s because Port has OnionTrafficOnly set (or "
+ "NoDNSRequest, NoIPv4Traffic, and NoIPv6Traffic).",
+ safe_str_client(socks->address));
+ connection_mark_unattached_ap(conn, END_STREAM_REASON_ENTRYPOLICY);
+ return -1;
+ }
+
+ /* Then check if we have a hostname or IP address, and whether DNS or
+ * the IP address family are permitted. Reject if not. */
+ tor_addr_t dummy_addr;
+ int socks_family = tor_addr_parse(&dummy_addr, socks->address);
+ /* family will be -1 for a non-onion hostname that's not an IP */
+ if (socks_family == -1) {
+ if (!conn->entry_cfg.dns_request) {
+ log_warn(LD_APP, "Refusing to connect to hostname %s "
+ "because Port has NoDNSRequest set.",
+ safe_str_client(socks->address));
+ connection_mark_unattached_ap(conn, END_STREAM_REASON_ENTRYPOLICY);
+ return -1;
+ }
+ } else if (socks_family == AF_INET) {
+ if (!conn->entry_cfg.ipv4_traffic) {
+ log_warn(LD_APP, "Refusing to connect to IPv4 address %s because "
+ "Port has NoIPv4Traffic set.",
+ safe_str_client(socks->address));
+ connection_mark_unattached_ap(conn, END_STREAM_REASON_ENTRYPOLICY);
+ return -1;
+ }
+ } else if (socks_family == AF_INET6) {
+ if (!conn->entry_cfg.ipv6_traffic) {
+ log_warn(LD_APP, "Refusing to connect to IPv6 address %s because "
+ "Port has NoIPv6Traffic set.",
+ safe_str_client(socks->address));
+ connection_mark_unattached_ap(conn, END_STREAM_REASON_ENTRYPOLICY);
+ return -1;
+ }
+ } else {
+ tor_assert_nonfatal_unreached_once();
+ }
+
+ /* See if this is a hostname lookup that we can answer immediately.
+ * (For example, an attempt to look up the IP address for an IP address.)
+ */
+ if (socks->command == SOCKS_COMMAND_RESOLVE) {
+ tor_addr_t answer;
+ /* Reply to resolves immediately if we can. */
+ if (tor_addr_parse(&answer, socks->address) >= 0) {/* is it an IP? */
+ /* remember _what_ is supposed to have been resolved. */
+ strlcpy(socks->address, rr.orig_address, sizeof(socks->address));
+ connection_ap_handshake_socks_resolved_addr(conn, &answer, -1,
+ map_expires);
+ connection_mark_unattached_ap(conn,
+ END_STREAM_REASON_DONE |
+ END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED);
+ return 0;
+ }
+ tor_assert(!automap);
+ rep_hist_note_used_resolve(now); /* help predict this next time */
+ } else if (socks->command == SOCKS_COMMAND_CONNECT) {
+ /* Now see if this is a connect request that we can reject immediately */
+
+ tor_assert(!automap);
+ /* Don't allow connections to port 0. */
+ if (socks->port == 0) {
+ log_notice(LD_APP,"Application asked to connect to port 0. Refusing.");
+ connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL);
+ return -1;
+ }
+ /* You can't make connections to internal addresses, by default.
+ * Exceptions are begindir requests (where the address is meaningless),
+ * or cases where you've hand-configured a particular exit, thereby
+ * making the local address meaningful. */
+ if (options->ClientRejectInternalAddresses &&
+ !conn->use_begindir && !conn->chosen_exit_name && !circ) {
+ /* If we reach this point then we don't want to allow internal
+ * addresses. Check if we got one. */
+ tor_addr_t addr;
+ if (tor_addr_hostname_is_local(socks->address) ||
+ (tor_addr_parse(&addr, socks->address) >= 0 &&
+ tor_addr_is_internal(&addr, 0))) {
+ /* If this is an explicit private address with no chosen exit node,
+ * then we really don't want to try to connect to it. That's
+ * probably an error. */
+ if (conn->is_transparent_ap) {
+#define WARN_INTRVL_LOOP 300
+ static ratelim_t loop_warn_limit = RATELIM_INIT(WARN_INTRVL_LOOP);
+ char *m;
+ if ((m = rate_limit_log(&loop_warn_limit, approx_time()))) {
+ log_warn(LD_NET,
+ "Rejecting request for anonymous connection to private "
+ "address %s on a TransPort or NATDPort. Possible loop "
+ "in your NAT rules?%s", safe_str_client(socks->address),
+ m);
+ tor_free(m);
+ }
+ } else {
+#define WARN_INTRVL_PRIV 300
+ static ratelim_t priv_warn_limit = RATELIM_INIT(WARN_INTRVL_PRIV);
+ char *m;
+ if ((m = rate_limit_log(&priv_warn_limit, approx_time()))) {
+ log_warn(LD_NET,
+ "Rejecting SOCKS request for anonymous connection to "
+ "private address %s.%s",
+ safe_str_client(socks->address),m);
+ tor_free(m);
+ }
+ }
+ connection_mark_unattached_ap(conn, END_STREAM_REASON_PRIVATE_ADDR);
+ return -1;
+ }
+ } /* end "if we should check for internal addresses" */
+
+ /* Okay. We're still doing a CONNECT, and it wasn't a private
+ * address. Here we do special handling for literal IP addresses,
+ * to see if we should reject this preemptively, and to set up
+ * fields in conn->entry_cfg to tell the exit what AF we want. */
+ {
+ tor_addr_t addr;
+ /* XXX Duplicate call to tor_addr_parse. */
+ if (tor_addr_parse(&addr, socks->address) >= 0) {
+ /* If we reach this point, it's an IPv4 or an IPv6 address. */
+ sa_family_t family = tor_addr_family(&addr);
+
+ if ((family == AF_INET && ! conn->entry_cfg.ipv4_traffic) ||
+ (family == AF_INET6 && ! conn->entry_cfg.ipv6_traffic)) {
+ /* You can't do an IPv4 address on a v6-only socks listener,
+ * or vice versa. */
+ log_warn(LD_NET, "Rejecting SOCKS request for an IP address "
+ "family that this listener does not support.");
+ connection_mark_unattached_ap(conn, END_STREAM_REASON_ENTRYPOLICY);
+ return -1;
+ } else if (family == AF_INET6 && socks->socks_version == 4) {
+ /* You can't make a socks4 request to an IPv6 address. Socks4
+ * doesn't support that. */
+ log_warn(LD_NET, "Rejecting SOCKS4 request for an IPv6 address.");
+ connection_mark_unattached_ap(conn, END_STREAM_REASON_ENTRYPOLICY);
+ return -1;
+ } else if (socks->socks_version == 4 &&
+ !conn->entry_cfg.ipv4_traffic) {
+ /* You can't do any kind of Socks4 request when IPv4 is forbidden.
+ *
+ * XXX raise this check outside the enclosing block? */
+ log_warn(LD_NET, "Rejecting SOCKS4 request on a listener with "
+ "no IPv4 traffic supported.");
+ connection_mark_unattached_ap(conn, END_STREAM_REASON_ENTRYPOLICY);
+ return -1;
+ } else if (family == AF_INET6) {
+ /* Tell the exit: we won't accept any ipv4 connection to an IPv6
+ * address. */
+ conn->entry_cfg.ipv4_traffic = 0;
+ } else if (family == AF_INET) {
+ /* Tell the exit: we won't accept any ipv6 connection to an IPv4
+ * address. */
+ conn->entry_cfg.ipv6_traffic = 0;
+ }
+ }
+ }
+
+ /* we never allow IPv6 answers on socks4. (TODO: Is this smart?) */
+ if (socks->socks_version == 4)
+ conn->entry_cfg.ipv6_traffic = 0;
+
+ /* Still handling CONNECT. Now, check for exit enclaves. (Which we
+ * don't do on BEGIN_DIR, or when there is a chosen exit.)
+ *
+ * TODO: Should we remove this? Exit enclaves are nutty and don't
+ * work very well
+ */
+ if (!conn->use_begindir && !conn->chosen_exit_name && !circ) {
+ /* see if we can find a suitable enclave exit */
+ const node_t *r =
+ router_find_exact_exit_enclave(socks->address, socks->port);
+ if (r) {
+ log_info(LD_APP,
+ "Redirecting address %s to exit at enclave router %s",
+ safe_str_client(socks->address), node_describe(r));
+ /* use the hex digest, not nickname, in case there are two
+ routers with this nickname */
+ conn->chosen_exit_name =
+ tor_strdup(hex_str(r->identity, DIGEST_LEN));
+ conn->chosen_exit_optional = 1;
+ }
+ }
+
+ /* Still handling CONNECT: warn or reject if it's using a dangerous
+ * port. */
+ if (!conn->use_begindir && !conn->chosen_exit_name && !circ)
+ if (consider_plaintext_ports(conn, socks->port) < 0)
+ return -1;
+
+ /* Remember the port so that we will predict that more requests
+ there will happen in the future. */
+ if (!conn->use_begindir) {
+ /* help predict this next time */
+ rep_hist_note_used_port(now, socks->port);
+ }
+ } else if (socks->command == SOCKS_COMMAND_RESOLVE_PTR) {
+ rep_hist_note_used_resolve(now); /* help predict this next time */
+ /* no extra processing needed */
+ } else {
+ /* We should only be doing CONNECT, RESOLVE, or RESOLVE_PTR! */
+ tor_fragile_assert();
+ }
+
+ /* Okay. At this point we've set chosen_exit_name if needed, rewritten the
+ * address, and decided not to reject it for any number of reasons. Now
+ * mark the connection as waiting for a circuit, and try to attach it!
+ */
+ base_conn->state = AP_CONN_STATE_CIRCUIT_WAIT;
+
+ /* If we were given a circuit to attach to, try to attach. Otherwise,
+ * try to find a good one and attach to that. */
+ int rv;
+ if (circ) {
+ rv = connection_ap_handshake_attach_chosen_circuit(conn, circ, cpath);
+ } else {
+ /* We'll try to attach it at the next event loop, or whenever
+ * we call connection_ap_attach_pending() */
+ connection_ap_mark_as_pending_circuit(conn);
+ rv = 0;
+ }
+
+ /* If the above function returned 0 then we're waiting for a circuit.
+ * if it returned 1, we're attached. Both are okay. But if it returned
+ * -1, there was an error, so make sure the connection is marked, and
+ * return -1. */
+ if (rv < 0) {
+ if (!base_conn->marked_for_close)
+ connection_mark_unattached_ap(conn, END_STREAM_REASON_CANT_ATTACH);
+ return -1;
+ }
+
+ return 0;
+ } else {
+ /* If we get here, it's a request for a .onion address! */
+ tor_assert(addresstype == ONION_V2_HOSTNAME ||
+ addresstype == ONION_V3_HOSTNAME);
+ tor_assert(!automap);
+ return connection_ap_handle_onion(conn, socks, circ, addresstype);
+ }
+
+ return 0; /* unreached but keeps the compiler happy */
+}
+
+#ifdef TRANS_PF
+static int pf_socket = -1;
+int
+get_pf_socket(void)
+{
+ int pf;
+ /* This should be opened before dropping privileges. */
+ if (pf_socket >= 0)
+ return pf_socket;
+
+#if defined(OpenBSD)
+ /* only works on OpenBSD */
+ pf = tor_open_cloexec("/dev/pf", O_RDONLY, 0);
+#else
+ /* works on NetBSD and FreeBSD */
+ pf = tor_open_cloexec("/dev/pf", O_RDWR, 0);
+#endif /* defined(OpenBSD) */
+
+ if (pf < 0) {
+ log_warn(LD_NET, "open(\"/dev/pf\") failed: %s", strerror(errno));
+ return -1;
+ }
+
+ pf_socket = pf;
+ return pf_socket;
+}
+#endif /* defined(TRANS_PF) */
+
+#if defined(TRANS_NETFILTER) || defined(TRANS_PF) || \
+ defined(TRANS_TPROXY)
+/** Try fill in the address of <b>req</b> from the socket configured
+ * with <b>conn</b>. */
+static int
+destination_from_socket(entry_connection_t *conn, socks_request_t *req)
+{
+ struct sockaddr_storage orig_dst;
+ socklen_t orig_dst_len = sizeof(orig_dst);
+ tor_addr_t addr;
+
+#ifdef TRANS_TPROXY
+ if (get_options()->TransProxyType_parsed == TPT_TPROXY) {
+ if (getsockname(ENTRY_TO_CONN(conn)->s, (struct sockaddr*)&orig_dst,
+ &orig_dst_len) < 0) {
+ int e = tor_socket_errno(ENTRY_TO_CONN(conn)->s);
+ log_warn(LD_NET, "getsockname() failed: %s", tor_socket_strerror(e));
+ return -1;
+ }
+ goto done;
+ }
+#endif /* defined(TRANS_TPROXY) */
+
+#ifdef TRANS_NETFILTER
+ int rv = -1;
+ switch (ENTRY_TO_CONN(conn)->socket_family) {
+#ifdef TRANS_NETFILTER_IPV4
+ case AF_INET:
+ rv = getsockopt(ENTRY_TO_CONN(conn)->s, SOL_IP, SO_ORIGINAL_DST,
+ (struct sockaddr*)&orig_dst, &orig_dst_len);
+ break;
+#endif /* defined(TRANS_NETFILTER_IPV4) */
+#ifdef TRANS_NETFILTER_IPV6
+ case AF_INET6:
+ rv = getsockopt(ENTRY_TO_CONN(conn)->s, SOL_IPV6, IP6T_SO_ORIGINAL_DST,
+ (struct sockaddr*)&orig_dst, &orig_dst_len);
+ break;
+#endif /* defined(TRANS_NETFILTER_IPV6) */
+ default:
+ log_warn(LD_BUG,
+ "Received transparent data from an unsuported socket family %d",
+ ENTRY_TO_CONN(conn)->socket_family);
+ return -1;
+ }
+ if (rv < 0) {
+ int e = tor_socket_errno(ENTRY_TO_CONN(conn)->s);
+ log_warn(LD_NET, "getsockopt() failed: %s", tor_socket_strerror(e));
+ return -1;
+ }
+ goto done;
+#elif defined(TRANS_PF)
+ if (getsockname(ENTRY_TO_CONN(conn)->s, (struct sockaddr*)&orig_dst,
+ &orig_dst_len) < 0) {
+ int e = tor_socket_errno(ENTRY_TO_CONN(conn)->s);
+ log_warn(LD_NET, "getsockname() failed: %s", tor_socket_strerror(e));
+ return -1;
+ }
+ goto done;
+#else
+ (void)conn;
+ (void)req;
+ log_warn(LD_BUG, "Unable to determine destination from socket.");
+ return -1;
+#endif /* defined(TRANS_NETFILTER) || ... */
+
+ done:
+ tor_addr_from_sockaddr(&addr, (struct sockaddr*)&orig_dst, &req->port);
+ tor_addr_to_str(req->address, &addr, sizeof(req->address), 1);
+
+ return 0;
+}
+#endif /* defined(TRANS_NETFILTER) || defined(TRANS_PF) || ... */
+
+#ifdef TRANS_PF
+static int
+destination_from_pf(entry_connection_t *conn, socks_request_t *req)
+{
+ struct sockaddr_storage proxy_addr;
+ socklen_t proxy_addr_len = sizeof(proxy_addr);
+ struct sockaddr *proxy_sa = (struct sockaddr*) &proxy_addr;
+ struct pfioc_natlook pnl;
+ tor_addr_t addr;
+ int pf = -1;
+
+ if (getsockname(ENTRY_TO_CONN(conn)->s, (struct sockaddr*)&proxy_addr,
+ &proxy_addr_len) < 0) {
+ int e = tor_socket_errno(ENTRY_TO_CONN(conn)->s);
+ log_warn(LD_NET, "getsockname() to determine transocks destination "
+ "failed: %s", tor_socket_strerror(e));
+ return -1;
+ }
+
+#ifdef __FreeBSD__
+ if (get_options()->TransProxyType_parsed == TPT_IPFW) {
+ /* ipfw(8) is used and in this case getsockname returned the original
+ destination */
+ if (tor_addr_from_sockaddr(&addr, proxy_sa, &req->port) < 0) {
+ tor_fragile_assert();
+ return -1;
+ }
+
+ tor_addr_to_str(req->address, &addr, sizeof(req->address), 0);
+
+ return 0;
+ }
+#endif /* defined(__FreeBSD__) */
+
+ memset(&pnl, 0, sizeof(pnl));
+ pnl.proto = IPPROTO_TCP;
+ pnl.direction = PF_OUT;
+ if (proxy_sa->sa_family == AF_INET) {
+ struct sockaddr_in *sin = (struct sockaddr_in *)proxy_sa;
+ pnl.af = AF_INET;
+ pnl.saddr.v4.s_addr = tor_addr_to_ipv4n(&ENTRY_TO_CONN(conn)->addr);
+ pnl.sport = htons(ENTRY_TO_CONN(conn)->port);
+ pnl.daddr.v4.s_addr = sin->sin_addr.s_addr;
+ pnl.dport = sin->sin_port;
+ } else if (proxy_sa->sa_family == AF_INET6) {
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)proxy_sa;
+ pnl.af = AF_INET6;
+ memcpy(&pnl.saddr.v6, tor_addr_to_in6(&ENTRY_TO_CONN(conn)->addr),
+ sizeof(struct in6_addr));
+ pnl.sport = htons(ENTRY_TO_CONN(conn)->port);
+ memcpy(&pnl.daddr.v6, &sin6->sin6_addr, sizeof(struct in6_addr));
+ pnl.dport = sin6->sin6_port;
+ } else {
+ log_warn(LD_NET, "getsockname() gave an unexpected address family (%d)",
+ (int)proxy_sa->sa_family);
+ return -1;
+ }
+
+ pf = get_pf_socket();
+ if (pf<0)
+ return -1;
+
+ if (ioctl(pf, DIOCNATLOOK, &pnl) < 0) {
+ log_warn(LD_NET, "ioctl(DIOCNATLOOK) failed: %s", strerror(errno));
+ return -1;
+ }
+
+ if (pnl.af == AF_INET) {
+ tor_addr_from_ipv4n(&addr, pnl.rdaddr.v4.s_addr);
+ } else if (pnl.af == AF_INET6) {
+ tor_addr_from_in6(&addr, &pnl.rdaddr.v6);
+ } else {
+ tor_fragile_assert();
+ return -1;
+ }
+
+ tor_addr_to_str(req->address, &addr, sizeof(req->address), 1);
+ req->port = ntohs(pnl.rdport);
+
+ return 0;
+}
+#endif /* defined(TRANS_PF) */
+
+/** Fetch the original destination address and port from a
+ * system-specific interface and put them into a
+ * socks_request_t as if they came from a socks request.
+ *
+ * Return -1 if an error prevents fetching the destination,
+ * else return 0.
+ */
+static int
+connection_ap_get_original_destination(entry_connection_t *conn,
+ socks_request_t *req)
+{
+#ifdef TRANS_NETFILTER
+ return destination_from_socket(conn, req);
+#elif defined(TRANS_PF)
+ const or_options_t *options = get_options();
+
+ if (options->TransProxyType_parsed == TPT_PF_DIVERT)
+ return destination_from_socket(conn, req);
+
+ if (options->TransProxyType_parsed == TPT_DEFAULT ||
+ options->TransProxyType_parsed == TPT_IPFW)
+ return destination_from_pf(conn, req);
+
+ (void)conn;
+ (void)req;
+ log_warn(LD_BUG, "Proxy destination determination mechanism %s unknown.",
+ options->TransProxyType);
+ return -1;
+#else
+ (void)conn;
+ (void)req;
+ log_warn(LD_BUG, "Called connection_ap_get_original_destination, but no "
+ "transparent proxy method was configured.");
+ return -1;
+#endif /* defined(TRANS_NETFILTER) || ... */
+}
+
+/** connection_edge_process_inbuf() found a conn in state
+ * socks_wait. See if conn->inbuf has the right bytes to proceed with
+ * the socks handshake.
+ *
+ * If the handshake is complete, send it to
+ * connection_ap_handshake_rewrite_and_attach().
+ *
+ * Return -1 if an unexpected error with conn occurs (and mark it for close),
+ * else return 0.
+ */
+static int
+connection_ap_handshake_process_socks(entry_connection_t *conn)
+{
+ socks_request_t *socks;
+ int sockshere;
+ const or_options_t *options = get_options();
+ int had_reply = 0;
+ connection_t *base_conn = ENTRY_TO_CONN(conn);
+
+ tor_assert(conn);
+ tor_assert(base_conn->type == CONN_TYPE_AP);
+ tor_assert(base_conn->state == AP_CONN_STATE_SOCKS_WAIT);
+ tor_assert(conn->socks_request);
+ socks = conn->socks_request;
+
+ log_debug(LD_APP,"entered.");
+
+ sockshere = fetch_from_buf_socks(base_conn->inbuf, socks,
+ options->TestSocks, options->SafeSocks);
+
+ if (socks->replylen) {
+ had_reply = 1;
+ connection_buf_add((const char*)socks->reply, socks->replylen,
+ base_conn);
+ socks->replylen = 0;
+ if (sockshere == -1) {
+ /* An invalid request just got a reply, no additional
+ * one is necessary. */
+ socks->has_finished = 1;
+ }
+ }
+
+ if (sockshere == 0) {
+ log_debug(LD_APP,"socks handshake not all here yet.");
+ return 0;
+ } else if (sockshere == -1) {
+ if (!had_reply) {
+ log_warn(LD_APP,"Fetching socks handshake failed. Closing.");
+ connection_ap_handshake_socks_reply(conn, NULL, 0,
+ END_STREAM_REASON_SOCKSPROTOCOL);
+ }
+ connection_mark_unattached_ap(conn,
+ END_STREAM_REASON_SOCKSPROTOCOL |
+ END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED);
+ return -1;
+ } /* else socks handshake is done, continue processing */
+
+ if (SOCKS_COMMAND_IS_CONNECT(socks->command))
+ control_event_stream_status(conn, STREAM_EVENT_NEW, 0);
+ else
+ control_event_stream_status(conn, STREAM_EVENT_NEW_RESOLVE, 0);
+
+ return connection_ap_rewrite_and_attach_if_allowed(conn, NULL, NULL);
+}
+
+/** connection_init_accepted_conn() found a new trans AP conn.
+ * Get the original destination and send it to
+ * connection_ap_handshake_rewrite_and_attach().
+ *
+ * Return -1 if an unexpected error with conn (and it should be marked
+ * for close), else return 0.
+ */
+int
+connection_ap_process_transparent(entry_connection_t *conn)
+{
+ socks_request_t *socks;
+
+ tor_assert(conn);
+ tor_assert(conn->socks_request);
+ socks = conn->socks_request;
+
+ /* pretend that a socks handshake completed so we don't try to
+ * send a socks reply down a transparent conn */
+ socks->command = SOCKS_COMMAND_CONNECT;
+ socks->has_finished = 1;
+
+ log_debug(LD_APP,"entered.");
+
+ if (connection_ap_get_original_destination(conn, socks) < 0) {
+ log_warn(LD_APP,"Fetching original destination failed. Closing.");
+ connection_mark_unattached_ap(conn,
+ END_STREAM_REASON_CANT_FETCH_ORIG_DEST);
+ return -1;
+ }
+ /* we have the original destination */
+
+ control_event_stream_status(conn, STREAM_EVENT_NEW, 0);
+
+ return connection_ap_rewrite_and_attach_if_allowed(conn, NULL, NULL);
+}
+
+/** connection_edge_process_inbuf() found a conn in state natd_wait. See if
+ * conn-\>inbuf has the right bytes to proceed. See FreeBSD's libalias(3) and
+ * ProxyEncodeTcpStream() in src/lib/libalias/alias_proxy.c for the encoding
+ * form of the original destination.
+ *
+ * If the original destination is complete, send it to
+ * connection_ap_handshake_rewrite_and_attach().
+ *
+ * Return -1 if an unexpected error with conn (and it should be marked
+ * for close), else return 0.
+ */
+static int
+connection_ap_process_natd(entry_connection_t *conn)
+{
+ char tmp_buf[36], *tbuf, *daddr;
+ size_t tlen = 30;
+ int err, port_ok;
+ socks_request_t *socks;
+
+ tor_assert(conn);
+ tor_assert(ENTRY_TO_CONN(conn)->state == AP_CONN_STATE_NATD_WAIT);
+ tor_assert(conn->socks_request);
+ socks = conn->socks_request;
+
+ log_debug(LD_APP,"entered.");
+
+ /* look for LF-terminated "[DEST ip_addr port]"
+ * where ip_addr is a dotted-quad and port is in string form */
+ err = connection_buf_get_line(ENTRY_TO_CONN(conn), tmp_buf, &tlen);
+ if (err == 0)
+ return 0;
+ if (err < 0) {
+ log_warn(LD_APP,"NATD handshake failed (DEST too long). Closing");
+ connection_mark_unattached_ap(conn, END_STREAM_REASON_INVALID_NATD_DEST);
+ return -1;
+ }
+
+ if (strcmpstart(tmp_buf, "[DEST ")) {
+ log_warn(LD_APP,"NATD handshake was ill-formed; closing. The client "
+ "said: %s",
+ escaped(tmp_buf));
+ connection_mark_unattached_ap(conn, END_STREAM_REASON_INVALID_NATD_DEST);
+ return -1;
+ }
+
+ daddr = tbuf = &tmp_buf[0] + 6; /* after end of "[DEST " */
+ if (!(tbuf = strchr(tbuf, ' '))) {
+ log_warn(LD_APP,"NATD handshake was ill-formed; closing. The client "
+ "said: %s",
+ escaped(tmp_buf));
+ connection_mark_unattached_ap(conn, END_STREAM_REASON_INVALID_NATD_DEST);
+ return -1;
+ }
+ *tbuf++ = '\0';
+
+ /* pretend that a socks handshake completed so we don't try to
+ * send a socks reply down a natd conn */
+ strlcpy(socks->address, daddr, sizeof(socks->address));
+ socks->port = (uint16_t)
+ tor_parse_long(tbuf, 10, 1, 65535, &port_ok, &daddr);
+ if (!port_ok) {
+ log_warn(LD_APP,"NATD handshake failed; port %s is ill-formed or out "
+ "of range.", escaped(tbuf));
+ connection_mark_unattached_ap(conn, END_STREAM_REASON_INVALID_NATD_DEST);
+ return -1;
+ }
+
+ socks->command = SOCKS_COMMAND_CONNECT;
+ socks->has_finished = 1;
+
+ control_event_stream_status(conn, STREAM_EVENT_NEW, 0);
+
+ ENTRY_TO_CONN(conn)->state = AP_CONN_STATE_CIRCUIT_WAIT;
+
+ return connection_ap_rewrite_and_attach_if_allowed(conn, NULL, NULL);
+}
+
+/** Called on an HTTP CONNECT entry connection when some bytes have arrived,
+ * but we have not yet received a full HTTP CONNECT request. Try to parse an
+ * HTTP CONNECT request from the connection's inbuf. On success, set up the
+ * connection's socks_request field and try to attach the connection. On
+ * failure, send an HTTP reply, and mark the connection.
+ */
+STATIC int
+connection_ap_process_http_connect(entry_connection_t *conn)
+{
+ if (BUG(ENTRY_TO_CONN(conn)->state != AP_CONN_STATE_HTTP_CONNECT_WAIT))
+ return -1;
+
+ char *headers = NULL, *body = NULL;
+ char *command = NULL, *addrport = NULL;
+ char *addr = NULL;
+ size_t bodylen = 0;
+
+ const char *errmsg = NULL;
+ int rv = 0;
+
+ const int http_status =
+ fetch_from_buf_http(ENTRY_TO_CONN(conn)->inbuf, &headers, 8192,
+ &body, &bodylen, 1024, 0);
+ if (http_status < 0) {
+ /* Bad http status */
+ errmsg = "HTTP/1.0 400 Bad Request\r\n\r\n";
+ goto err;
+ } else if (http_status == 0) {
+ /* no HTTP request yet. */
+ goto done;
+ }
+
+ const int cmd_status = parse_http_command(headers, &command, &addrport);
+ if (cmd_status < 0) {
+ errmsg = "HTTP/1.0 400 Bad Request\r\n\r\n";
+ goto err;
+ }
+ tor_assert(command);
+ tor_assert(addrport);
+ if (strcasecmp(command, "connect")) {
+ errmsg = "HTTP/1.0 405 Method Not Allowed\r\n\r\n";
+ goto err;
+ }
+
+ tor_assert(conn->socks_request);
+ socks_request_t *socks = conn->socks_request;
+ uint16_t port;
+ if (tor_addr_port_split(LOG_WARN, addrport, &addr, &port) < 0) {
+ errmsg = "HTTP/1.0 400 Bad Request\r\n\r\n";
+ goto err;
+ }
+ if (strlen(addr) >= MAX_SOCKS_ADDR_LEN) {
+ errmsg = "HTTP/1.0 414 Request-URI Too Long\r\n\r\n";
+ goto err;
+ }
+
+ /* Abuse the 'username' and 'password' fields here. They are already an
+ * abuse. */
+ {
+ char *authorization = http_get_header(headers, "Proxy-Authorization: ");
+ if (authorization) {
+ socks->username = authorization; // steal reference
+ socks->usernamelen = strlen(authorization);
+ }
+ char *isolation = http_get_header(headers, "X-Tor-Stream-Isolation: ");
+ if (isolation) {
+ socks->password = isolation; // steal reference
+ socks->passwordlen = strlen(isolation);
+ }
+ }
+
+ socks->command = SOCKS_COMMAND_CONNECT;
+ socks->listener_type = CONN_TYPE_AP_HTTP_CONNECT_LISTENER;
+ strlcpy(socks->address, addr, sizeof(socks->address));
+ socks->port = port;
+
+ control_event_stream_status(conn, STREAM_EVENT_NEW, 0);
+
+ rv = connection_ap_rewrite_and_attach_if_allowed(conn, NULL, NULL);
+
+ // XXXX send a "100 Continue" message?
+
+ goto done;
+
+ err:
+ if (BUG(errmsg == NULL))
+ errmsg = "HTTP/1.0 400 Bad Request\r\n\r\n";
+ log_info(LD_EDGE, "HTTP tunnel error: saying %s", escaped(errmsg));
+ connection_buf_add(errmsg, strlen(errmsg), ENTRY_TO_CONN(conn));
+ /* Mark it as "has_finished" so that we don't try to send an extra socks
+ * reply. */
+ conn->socks_request->has_finished = 1;
+ connection_mark_unattached_ap(conn,
+ END_STREAM_REASON_HTTPPROTOCOL|
+ END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED);
+
+ done:
+ tor_free(headers);
+ tor_free(body);
+ tor_free(command);
+ tor_free(addrport);
+ tor_free(addr);
+ return rv;
+}
+
+/** Iterate over the two bytes of stream_id until we get one that is not
+ * already in use; return it. Return 0 if can't get a unique stream_id.
+ */
+streamid_t
+get_unique_stream_id_by_circ(origin_circuit_t *circ)
+{
+ edge_connection_t *tmpconn;
+ streamid_t test_stream_id;
+ uint32_t attempts=0;
+
+ again:
+ test_stream_id = circ->next_stream_id++;
+ if (++attempts > 1<<16) {
+ /* Make sure we don't loop forever if all stream_id's are used. */
+ log_warn(LD_APP,"No unused stream IDs. Failing.");
+ return 0;
+ }
+ if (test_stream_id == 0)
+ goto again;
+ for (tmpconn = circ->p_streams; tmpconn; tmpconn=tmpconn->next_stream)
+ if (tmpconn->stream_id == test_stream_id)
+ goto again;
+
+ if (connection_half_edge_find_stream_id(circ->half_streams,
+ test_stream_id))
+ goto again;
+
+ return test_stream_id;
+}
+
+/** Return true iff <b>conn</b> is linked to a circuit and configured to use
+ * an exit that supports optimistic data. */
+static int
+connection_ap_supports_optimistic_data(const entry_connection_t *conn)
+{
+ const edge_connection_t *edge_conn = ENTRY_TO_EDGE_CONN(conn);
+ /* We can only send optimistic data if we're connected to an open
+ general circuit. */
+ if (edge_conn->on_circuit == NULL ||
+ edge_conn->on_circuit->state != CIRCUIT_STATE_OPEN ||
+ (edge_conn->on_circuit->purpose != CIRCUIT_PURPOSE_C_GENERAL &&
+ edge_conn->on_circuit->purpose != CIRCUIT_PURPOSE_C_HSDIR_GET &&
+ edge_conn->on_circuit->purpose != CIRCUIT_PURPOSE_S_HSDIR_POST &&
+ edge_conn->on_circuit->purpose != CIRCUIT_PURPOSE_C_REND_JOINED))
+ return 0;
+
+ return conn->may_use_optimistic_data;
+}
+
+/** Return a bitmask of BEGIN_FLAG_* flags that we should transmit in the
+ * RELAY_BEGIN cell for <b>ap_conn</b>. */
+static uint32_t
+connection_ap_get_begincell_flags(entry_connection_t *ap_conn)
+{
+ edge_connection_t *edge_conn = ENTRY_TO_EDGE_CONN(ap_conn);
+ const node_t *exitnode = NULL;
+ const crypt_path_t *cpath_layer = edge_conn->cpath_layer;
+ uint32_t flags = 0;
+
+ /* No flags for begindir */
+ if (ap_conn->use_begindir)
+ return 0;
+
+ /* No flags for hidden services. */
+ if (edge_conn->on_circuit->purpose != CIRCUIT_PURPOSE_C_GENERAL)
+ return 0;
+
+ /* If only IPv4 is supported, no flags */
+ if (ap_conn->entry_cfg.ipv4_traffic && !ap_conn->entry_cfg.ipv6_traffic)
+ return 0;
+
+ if (! cpath_layer ||
+ ! cpath_layer->extend_info)
+ return 0;
+
+ if (!ap_conn->entry_cfg.ipv4_traffic)
+ flags |= BEGIN_FLAG_IPV4_NOT_OK;
+
+ exitnode = node_get_by_id(cpath_layer->extend_info->identity_digest);
+
+ if (ap_conn->entry_cfg.ipv6_traffic && exitnode) {
+ tor_addr_t a;
+ tor_addr_make_null(&a, AF_INET6);
+ if (compare_tor_addr_to_node_policy(&a, ap_conn->socks_request->port,
+ exitnode)
+ != ADDR_POLICY_REJECTED) {
+ /* Only say "IPv6 OK" if the exit node supports IPv6. Otherwise there's
+ * no point. */
+ flags |= BEGIN_FLAG_IPV6_OK;
+ }
+ }
+
+ if (flags == BEGIN_FLAG_IPV6_OK) {
+ /* When IPv4 and IPv6 are both allowed, consider whether to say we
+ * prefer IPv6. Otherwise there's no point in declaring a preference */
+ if (ap_conn->entry_cfg.prefer_ipv6)
+ flags |= BEGIN_FLAG_IPV6_PREFERRED;
+ }
+
+ if (flags == BEGIN_FLAG_IPV4_NOT_OK) {
+ log_warn(LD_EDGE, "I'm about to ask a node for a connection that I "
+ "am telling it to fulfil with neither IPv4 nor IPv6. That's "
+ "not going to work. Did you perhaps ask for an IPv6 address "
+ "on an IPv4Only port, or vice versa?");
+ }
+
+ return flags;
+}
+
+/** Write a relay begin cell, using destaddr and destport from ap_conn's
+ * socks_request field, and send it down circ.
+ *
+ * If ap_conn is broken, mark it for close and return -1. Else return 0.
+ */
+MOCK_IMPL(int,
+connection_ap_handshake_send_begin,(entry_connection_t *ap_conn))
+{
+ char payload[CELL_PAYLOAD_SIZE];
+ int payload_len;
+ int begin_type;
+ const or_options_t *options = get_options();
+ origin_circuit_t *circ;
+ edge_connection_t *edge_conn = ENTRY_TO_EDGE_CONN(ap_conn);
+ connection_t *base_conn = TO_CONN(edge_conn);
+ tor_assert(edge_conn->on_circuit);
+ circ = TO_ORIGIN_CIRCUIT(edge_conn->on_circuit);
+
+ tor_assert(base_conn->type == CONN_TYPE_AP);
+ tor_assert(base_conn->state == AP_CONN_STATE_CIRCUIT_WAIT);
+ tor_assert(ap_conn->socks_request);
+ tor_assert(SOCKS_COMMAND_IS_CONNECT(ap_conn->socks_request->command));
+
+ edge_conn->stream_id = get_unique_stream_id_by_circ(circ);
+ if (edge_conn->stream_id==0) {
+ /* XXXX+ Instead of closing this stream, we should make it get
+ * retried on another circuit. */
+ connection_mark_unattached_ap(ap_conn, END_STREAM_REASON_INTERNAL);
+
+ /* Mark this circuit "unusable for new streams". */
+ mark_circuit_unusable_for_new_conns(circ);
+ return -1;
+ }
+
+ /* Set up begin cell flags. */
+ edge_conn->begincell_flags = connection_ap_get_begincell_flags(ap_conn);
+
+ tor_snprintf(payload,RELAY_PAYLOAD_SIZE, "%s:%d",
+ (circ->base_.purpose == CIRCUIT_PURPOSE_C_GENERAL) ?
+ ap_conn->socks_request->address : "",
+ ap_conn->socks_request->port);
+ payload_len = (int)strlen(payload)+1;
+ if (payload_len <= RELAY_PAYLOAD_SIZE - 4 && edge_conn->begincell_flags) {
+ set_uint32(payload + payload_len, htonl(edge_conn->begincell_flags));
+ payload_len += 4;
+ }
+
+ log_info(LD_APP,
+ "Sending relay cell %d on circ %u to begin stream %d.",
+ (int)ap_conn->use_begindir,
+ (unsigned)circ->base_.n_circ_id,
+ edge_conn->stream_id);
+
+ begin_type = ap_conn->use_begindir ?
+ RELAY_COMMAND_BEGIN_DIR : RELAY_COMMAND_BEGIN;
+
+ /* Check that circuits are anonymised, based on their type. */
+ if (begin_type == RELAY_COMMAND_BEGIN) {
+ /* This connection is a standard OR connection.
+ * Make sure its path length is anonymous, or that we're in a
+ * non-anonymous mode. */
+ assert_circ_anonymity_ok(circ, options);
+ } else if (begin_type == RELAY_COMMAND_BEGIN_DIR) {
+ /* This connection is a begindir directory connection.
+ * Look at the linked directory connection to access the directory purpose.
+ * If a BEGINDIR connection is ever not linked, that's a bug. */
+ if (BUG(!base_conn->linked)) {
+ return -1;
+ }
+ connection_t *linked_dir_conn_base = base_conn->linked_conn;
+ /* If the linked connection has been unlinked by other code, we can't send
+ * a begin cell on it. */
+ if (!linked_dir_conn_base) {
+ return -1;
+ }
+ /* Sensitive directory connections must have an anonymous path length.
+ * Otherwise, directory connections are typically one-hop.
+ * This matches the earlier check for directory connection path anonymity
+ * in directory_initiate_request(). */
+ if (purpose_needs_anonymity(linked_dir_conn_base->purpose,
+ TO_DIR_CONN(linked_dir_conn_base)->router_purpose,
+ TO_DIR_CONN(linked_dir_conn_base)->requested_resource)) {
+ assert_circ_anonymity_ok(circ, options);
+ }
+ } else {
+ /* This code was written for the two connection types BEGIN and BEGIN_DIR
+ */
+ tor_assert_unreached();
+ }
+
+ if (connection_edge_send_command(edge_conn, begin_type,
+ begin_type == RELAY_COMMAND_BEGIN ? payload : NULL,
+ begin_type == RELAY_COMMAND_BEGIN ? payload_len : 0) < 0)
+ return -1; /* circuit is closed, don't continue */
+
+ edge_conn->package_window = STREAMWINDOW_START;
+ edge_conn->deliver_window = STREAMWINDOW_START;
+ base_conn->state = AP_CONN_STATE_CONNECT_WAIT;
+ log_info(LD_APP,"Address/port sent, ap socket "TOR_SOCKET_T_FORMAT
+ ", n_circ_id %u",
+ base_conn->s, (unsigned)circ->base_.n_circ_id);
+ control_event_stream_status(ap_conn, STREAM_EVENT_SENT_CONNECT, 0);
+
+ /* If there's queued-up data, send it now */
+ if ((connection_get_inbuf_len(base_conn) ||
+ ap_conn->sending_optimistic_data) &&
+ connection_ap_supports_optimistic_data(ap_conn)) {
+ log_info(LD_APP, "Sending up to %ld + %ld bytes of queued-up data",
+ (long)connection_get_inbuf_len(base_conn),
+ ap_conn->sending_optimistic_data ?
+ (long)buf_datalen(ap_conn->sending_optimistic_data) : 0);
+ if (connection_edge_package_raw_inbuf(edge_conn, 1, NULL) < 0) {
+ connection_mark_for_close(base_conn);
+ }
+ }
+
+ return 0;
+}
+
+/** Write a relay resolve cell, using destaddr and destport from ap_conn's
+ * socks_request field, and send it down circ.
+ *
+ * If ap_conn is broken, mark it for close and return -1. Else return 0.
+ */
+int
+connection_ap_handshake_send_resolve(entry_connection_t *ap_conn)
+{
+ int payload_len, command;
+ const char *string_addr;
+ char inaddr_buf[REVERSE_LOOKUP_NAME_BUF_LEN];
+ origin_circuit_t *circ;
+ edge_connection_t *edge_conn = ENTRY_TO_EDGE_CONN(ap_conn);
+ connection_t *base_conn = TO_CONN(edge_conn);
+ tor_assert(edge_conn->on_circuit);
+ circ = TO_ORIGIN_CIRCUIT(edge_conn->on_circuit);
+
+ tor_assert(base_conn->type == CONN_TYPE_AP);
+ tor_assert(base_conn->state == AP_CONN_STATE_CIRCUIT_WAIT);
+ tor_assert(ap_conn->socks_request);
+ tor_assert(circ->base_.purpose == CIRCUIT_PURPOSE_C_GENERAL);
+
+ command = ap_conn->socks_request->command;
+ tor_assert(SOCKS_COMMAND_IS_RESOLVE(command));
+
+ edge_conn->stream_id = get_unique_stream_id_by_circ(circ);
+ if (edge_conn->stream_id==0) {
+ /* XXXX+ Instead of closing this stream, we should make it get
+ * retried on another circuit. */
+ connection_mark_unattached_ap(ap_conn, END_STREAM_REASON_INTERNAL);
+
+ /* Mark this circuit "unusable for new streams". */
+ mark_circuit_unusable_for_new_conns(circ);
+ return -1;
+ }
+
+ if (command == SOCKS_COMMAND_RESOLVE) {
+ string_addr = ap_conn->socks_request->address;
+ payload_len = (int)strlen(string_addr)+1;
+ } else {
+ /* command == SOCKS_COMMAND_RESOLVE_PTR */
+ const char *a = ap_conn->socks_request->address;
+ tor_addr_t addr;
+ int r;
+
+ /* We're doing a reverse lookup. The input could be an IP address, or
+ * could be an .in-addr.arpa or .ip6.arpa address */
+ r = tor_addr_parse_PTR_name(&addr, a, AF_UNSPEC, 1);
+ if (r <= 0) {
+ log_warn(LD_APP, "Rejecting ill-formed reverse lookup of %s",
+ safe_str_client(a));
+ connection_mark_unattached_ap(ap_conn, END_STREAM_REASON_INTERNAL);
+ return -1;
+ }
+
+ r = tor_addr_to_PTR_name(inaddr_buf, sizeof(inaddr_buf), &addr);
+ if (r < 0) {
+ log_warn(LD_BUG, "Couldn't generate reverse lookup hostname of %s",
+ safe_str_client(a));
+ connection_mark_unattached_ap(ap_conn, END_STREAM_REASON_INTERNAL);
+ return -1;
+ }
+
+ string_addr = inaddr_buf;
+ payload_len = (int)strlen(inaddr_buf)+1;
+ tor_assert(payload_len <= (int)sizeof(inaddr_buf));
+ }
+
+ log_debug(LD_APP,
+ "Sending relay cell to begin stream %d.", edge_conn->stream_id);
+
+ if (connection_edge_send_command(edge_conn,
+ RELAY_COMMAND_RESOLVE,
+ string_addr, payload_len) < 0)
+ return -1; /* circuit is closed, don't continue */
+
+ if (!base_conn->address) {
+ /* This might be unnecessary. XXXX */
+ base_conn->address = tor_addr_to_str_dup(&base_conn->addr);
+ }
+ base_conn->state = AP_CONN_STATE_RESOLVE_WAIT;
+ log_info(LD_APP,"Address sent for resolve, ap socket "TOR_SOCKET_T_FORMAT
+ ", n_circ_id %u",
+ base_conn->s, (unsigned)circ->base_.n_circ_id);
+ control_event_stream_status(ap_conn, STREAM_EVENT_SENT_RESOLVE, 0);
+ return 0;
+}
+
+/** Make an AP connection_t linked to the connection_t <b>partner</b>. make a
+ * new linked connection pair, and attach one side to the conn, connection_add
+ * it, initialize it to circuit_wait, and call
+ * connection_ap_handshake_attach_circuit(conn) on it.
+ *
+ * Return the newly created end of the linked connection pair, or -1 if error.
+ */
+entry_connection_t *
+connection_ap_make_link(connection_t *partner,
+ char *address, uint16_t port,
+ const char *digest,
+ int session_group, int isolation_flags,
+ int use_begindir, int want_onehop)
+{
+ entry_connection_t *conn;
+ connection_t *base_conn;
+
+ log_info(LD_APP,"Making internal %s tunnel to %s:%d ...",
+ want_onehop ? "direct" : "anonymized",
+ safe_str_client(address), port);
+
+ conn = entry_connection_new(CONN_TYPE_AP, tor_addr_family(&partner->addr));
+ base_conn = ENTRY_TO_CONN(conn);
+ base_conn->linked = 1; /* so that we can add it safely below. */
+
+ /* populate conn->socks_request */
+
+ /* leave version at zero, so the socks_reply is empty */
+ conn->socks_request->socks_version = 0;
+ conn->socks_request->has_finished = 0; /* waiting for 'connected' */
+ strlcpy(conn->socks_request->address, address,
+ sizeof(conn->socks_request->address));
+ conn->socks_request->port = port;
+ conn->socks_request->command = SOCKS_COMMAND_CONNECT;
+ conn->want_onehop = want_onehop;
+ conn->use_begindir = use_begindir;
+ if (use_begindir) {
+ conn->chosen_exit_name = tor_malloc(HEX_DIGEST_LEN+2);
+ conn->chosen_exit_name[0] = '$';
+ tor_assert(digest);
+ base16_encode(conn->chosen_exit_name+1,HEX_DIGEST_LEN+1,
+ digest, DIGEST_LEN);
+ }
+
+ /* Populate isolation fields. */
+ conn->socks_request->listener_type = CONN_TYPE_DIR_LISTENER;
+ conn->original_dest_address = tor_strdup(address);
+ conn->entry_cfg.session_group = session_group;
+ conn->entry_cfg.isolation_flags = isolation_flags;
+
+ base_conn->address = tor_strdup("(Tor_internal)");
+ tor_addr_make_unspec(&base_conn->addr);
+ base_conn->port = 0;
+
+ connection_link_connections(partner, base_conn);
+
+ if (connection_add(base_conn) < 0) { /* no space, forget it */
+ connection_free(base_conn);
+ return NULL;
+ }
+
+ base_conn->state = AP_CONN_STATE_CIRCUIT_WAIT;
+
+ control_event_stream_status(conn, STREAM_EVENT_NEW, 0);
+
+ /* attaching to a dirty circuit is fine */
+ connection_ap_mark_as_pending_circuit(conn);
+ log_info(LD_APP,"... application connection created and linked.");
+ return conn;
+}
+
+/** Notify any interested controller connections about a new hostname resolve
+ * or resolve error. Takes the same arguments as does
+ * connection_ap_handshake_socks_resolved(). */
+static void
+tell_controller_about_resolved_result(entry_connection_t *conn,
+ int answer_type,
+ size_t answer_len,
+ const char *answer,
+ int ttl,
+ time_t expires)
+{
+ expires = time(NULL) + ttl;
+ if (answer_type == RESOLVED_TYPE_IPV4 && answer_len >= 4) {
+ char *cp = tor_dup_ip(ntohl(get_uint32(answer)));
+ control_event_address_mapped(conn->socks_request->address,
+ cp, expires, NULL, 0);
+ tor_free(cp);
+ } else if (answer_type == RESOLVED_TYPE_HOSTNAME && answer_len < 256) {
+ char *cp = tor_strndup(answer, answer_len);
+ control_event_address_mapped(conn->socks_request->address,
+ cp, expires, NULL, 0);
+ tor_free(cp);
+ } else {
+ control_event_address_mapped(conn->socks_request->address,
+ "<error>", time(NULL)+ttl,
+ "error=yes", 0);
+ }
+}
+
+/**
+ * As connection_ap_handshake_socks_resolved, but take a tor_addr_t to send
+ * as the answer.
+ */
+void
+connection_ap_handshake_socks_resolved_addr(entry_connection_t *conn,
+ const tor_addr_t *answer,
+ int ttl,
+ time_t expires)
+{
+ if (tor_addr_family(answer) == AF_INET) {
+ uint32_t a = tor_addr_to_ipv4n(answer); /* network order */
+ connection_ap_handshake_socks_resolved(conn,RESOLVED_TYPE_IPV4,4,
+ (uint8_t*)&a,
+ ttl, expires);
+ } else if (tor_addr_family(answer) == AF_INET6) {
+ const uint8_t *a = tor_addr_to_in6_addr8(answer);
+ connection_ap_handshake_socks_resolved(conn,RESOLVED_TYPE_IPV6,16,
+ a,
+ ttl, expires);
+ } else {
+ log_warn(LD_BUG, "Got called with address of unexpected family %d",
+ tor_addr_family(answer));
+ connection_ap_handshake_socks_resolved(conn,
+ RESOLVED_TYPE_ERROR,0,NULL,-1,-1);
+ }
+}
+
+/** Send an answer to an AP connection that has requested a DNS lookup via
+ * SOCKS. The type should be one of RESOLVED_TYPE_(IPV4|IPV6|HOSTNAME) or -1
+ * for unreachable; the answer should be in the format specified in the socks
+ * extensions document. <b>ttl</b> is the ttl for the answer, or -1 on
+ * certain errors or for values that didn't come via DNS. <b>expires</b> is
+ * a time when the answer expires, or -1 or TIME_MAX if there's a good TTL.
+ **/
+/* XXXX the use of the ttl and expires fields is nutty. Let's make this
+ * interface and those that use it less ugly. */
+MOCK_IMPL(void,
+connection_ap_handshake_socks_resolved,(entry_connection_t *conn,
+ int answer_type,
+ size_t answer_len,
+ const uint8_t *answer,
+ int ttl,
+ time_t expires))
+{
+ char buf[384];
+ size_t replylen;
+
+ if (ttl >= 0) {
+ if (answer_type == RESOLVED_TYPE_IPV4 && answer_len == 4) {
+ tor_addr_t a;
+ tor_addr_from_ipv4n(&a, get_uint32(answer));
+ if (! tor_addr_is_null(&a)) {
+ client_dns_set_addressmap(conn,
+ conn->socks_request->address, &a,
+ conn->chosen_exit_name, ttl);
+ }
+ } else if (answer_type == RESOLVED_TYPE_IPV6 && answer_len == 16) {
+ tor_addr_t a;
+ tor_addr_from_ipv6_bytes(&a, (char*)answer);
+ if (! tor_addr_is_null(&a)) {
+ client_dns_set_addressmap(conn,
+ conn->socks_request->address, &a,
+ conn->chosen_exit_name, ttl);
+ }
+ } else if (answer_type == RESOLVED_TYPE_HOSTNAME && answer_len < 256) {
+ char *cp = tor_strndup((char*)answer, answer_len);
+ client_dns_set_reverse_addressmap(conn,
+ conn->socks_request->address,
+ cp,
+ conn->chosen_exit_name, ttl);
+ tor_free(cp);
+ }
+ }
+
+ if (ENTRY_TO_EDGE_CONN(conn)->is_dns_request) {
+ if (conn->dns_server_request) {
+ /* We had a request on our DNS port: answer it. */
+ dnsserv_resolved(conn, answer_type, answer_len, (char*)answer, ttl);
+ conn->socks_request->has_finished = 1;
+ return;
+ } else {
+ /* This must be a request from the controller. Since answers to those
+ * requests are not cached, they do not generate an ADDRMAP event on
+ * their own. */
+ tell_controller_about_resolved_result(conn, answer_type, answer_len,
+ (char*)answer, ttl, expires);
+ conn->socks_request->has_finished = 1;
+ return;
+ }
+ /* We shouldn't need to free conn here; it gets marked by the caller. */
+ }
+
+ if (conn->socks_request->socks_version == 4) {
+ buf[0] = 0x00; /* version */
+ if (answer_type == RESOLVED_TYPE_IPV4 && answer_len == 4) {
+ buf[1] = SOCKS4_GRANTED;
+ set_uint16(buf+2, 0);
+ memcpy(buf+4, answer, 4); /* address */
+ replylen = SOCKS4_NETWORK_LEN;
+ } else { /* "error" */
+ buf[1] = SOCKS4_REJECT;
+ memset(buf+2, 0, 6);
+ replylen = SOCKS4_NETWORK_LEN;
+ }
+ } else if (conn->socks_request->socks_version == 5) {
+ /* SOCKS5 */
+ buf[0] = 0x05; /* version */
+ if (answer_type == RESOLVED_TYPE_IPV4 && answer_len == 4) {
+ buf[1] = SOCKS5_SUCCEEDED;
+ buf[2] = 0; /* reserved */
+ buf[3] = 0x01; /* IPv4 address type */
+ memcpy(buf+4, answer, 4); /* address */
+ set_uint16(buf+8, 0); /* port == 0. */
+ replylen = 10;
+ } else if (answer_type == RESOLVED_TYPE_IPV6 && answer_len == 16) {
+ buf[1] = SOCKS5_SUCCEEDED;
+ buf[2] = 0; /* reserved */
+ buf[3] = 0x04; /* IPv6 address type */
+ memcpy(buf+4, answer, 16); /* address */
+ set_uint16(buf+20, 0); /* port == 0. */
+ replylen = 22;
+ } else if (answer_type == RESOLVED_TYPE_HOSTNAME && answer_len < 256) {
+ buf[1] = SOCKS5_SUCCEEDED;
+ buf[2] = 0; /* reserved */
+ buf[3] = 0x03; /* Domainname address type */
+ buf[4] = (char)answer_len;
+ memcpy(buf+5, answer, answer_len); /* address */
+ set_uint16(buf+5+answer_len, 0); /* port == 0. */
+ replylen = 5+answer_len+2;
+ } else {
+ buf[1] = SOCKS5_HOST_UNREACHABLE;
+ memset(buf+2, 0, 8);
+ replylen = 10;
+ }
+ } else {
+ /* no socks version info; don't send anything back */
+ return;
+ }
+ connection_ap_handshake_socks_reply(conn, buf, replylen,
+ (answer_type == RESOLVED_TYPE_IPV4 ||
+ answer_type == RESOLVED_TYPE_IPV6 ||
+ answer_type == RESOLVED_TYPE_HOSTNAME) ?
+ 0 : END_STREAM_REASON_RESOLVEFAILED);
+}
+
+/** Send a socks reply to stream <b>conn</b>, using the appropriate
+ * socks version, etc, and mark <b>conn</b> as completed with SOCKS
+ * handshaking.
+ *
+ * If <b>reply</b> is defined, then write <b>replylen</b> bytes of it to conn
+ * and return, else reply based on <b>endreason</b> (one of
+ * END_STREAM_REASON_*). If <b>reply</b> is undefined, <b>endreason</b> can't
+ * be 0 or REASON_DONE. Send endreason to the controller, if appropriate.
+ */
+void
+connection_ap_handshake_socks_reply(entry_connection_t *conn, char *reply,
+ size_t replylen, int endreason)
+{
+ char buf[256];
+ socks5_reply_status_t status =
+ stream_end_reason_to_socks5_response(endreason);
+
+ tor_assert(conn->socks_request); /* make sure it's an AP stream */
+
+ if (!SOCKS_COMMAND_IS_RESOLVE(conn->socks_request->command)) {
+ control_event_stream_status(conn, status==SOCKS5_SUCCEEDED ?
+ STREAM_EVENT_SUCCEEDED : STREAM_EVENT_FAILED,
+ endreason);
+ }
+
+ /* Flag this stream's circuit as having completed a stream successfully
+ * (for path bias) */
+ if (status == SOCKS5_SUCCEEDED ||
+ endreason == END_STREAM_REASON_RESOLVEFAILED ||
+ endreason == END_STREAM_REASON_CONNECTREFUSED ||
+ endreason == END_STREAM_REASON_CONNRESET ||
+ endreason == END_STREAM_REASON_NOROUTE ||
+ endreason == END_STREAM_REASON_RESOURCELIMIT) {
+ if (!conn->edge_.on_circuit ||
+ !CIRCUIT_IS_ORIGIN(conn->edge_.on_circuit)) {
+ if (endreason != END_STREAM_REASON_RESOLVEFAILED) {
+ log_info(LD_BUG,
+ "No origin circuit for successful SOCKS stream %"PRIu64
+ ". Reason: %d",
+ (ENTRY_TO_CONN(conn)->global_identifier),
+ endreason);
+ }
+ /*
+ * Else DNS remaps and failed hidden service lookups can send us
+ * here with END_STREAM_REASON_RESOLVEFAILED; ignore it
+ *
+ * Perhaps we could make the test more precise; we can tell hidden
+ * services by conn->edge_.renddata != NULL; anything analogous for
+ * the DNS remap case?
+ */
+ } else {
+ // XXX: Hrmm. It looks like optimistic data can't go through this
+ // codepath, but someone should probably test it and make sure.
+ // We don't want to mark optimistically opened streams as successful.
+ pathbias_mark_use_success(TO_ORIGIN_CIRCUIT(conn->edge_.on_circuit));
+ }
+ }
+
+ if (conn->socks_request->has_finished) {
+ log_warn(LD_BUG, "(Harmless.) duplicate calls to "
+ "connection_ap_handshake_socks_reply.");
+ return;
+ }
+ if (replylen) { /* we already have a reply in mind */
+ connection_buf_add(reply, replylen, ENTRY_TO_CONN(conn));
+ conn->socks_request->has_finished = 1;
+ return;
+ }
+ if (conn->socks_request->listener_type ==
+ CONN_TYPE_AP_HTTP_CONNECT_LISTENER) {
+ const char *response = end_reason_to_http_connect_response_line(endreason);
+ if (!response) {
+ response = "HTTP/1.0 400 Bad Request\r\n\r\n";
+ }
+ connection_buf_add(response, strlen(response), ENTRY_TO_CONN(conn));
+ } else if (conn->socks_request->socks_version == 4) {
+ memset(buf,0,SOCKS4_NETWORK_LEN);
+ buf[1] = (status==SOCKS5_SUCCEEDED ? SOCKS4_GRANTED : SOCKS4_REJECT);
+ /* leave version, destport, destip zero */
+ connection_buf_add(buf, SOCKS4_NETWORK_LEN, ENTRY_TO_CONN(conn));
+ } else if (conn->socks_request->socks_version == 5) {
+ size_t buf_len;
+ memset(buf,0,sizeof(buf));
+ if (tor_addr_family(&conn->edge_.base_.addr) == AF_INET) {
+ buf[0] = 5; /* version 5 */
+ buf[1] = (char)status;
+ buf[2] = 0;
+ buf[3] = 1; /* ipv4 addr */
+ /* 4 bytes for the header, 2 bytes for the port, 4 for the address. */
+ buf_len = 10;
+ } else { /* AF_INET6. */
+ buf[0] = 5; /* version 5 */
+ buf[1] = (char)status;
+ buf[2] = 0;
+ buf[3] = 4; /* ipv6 addr */
+ /* 4 bytes for the header, 2 bytes for the port, 16 for the address. */
+ buf_len = 22;
+ }
+ connection_buf_add(buf,buf_len,ENTRY_TO_CONN(conn));
+ }
+ /* If socks_version isn't 4 or 5, don't send anything.
+ * This can happen in the case of AP bridges. */
+ conn->socks_request->has_finished = 1;
+ return;
+}
+
+/** Read a RELAY_BEGIN or RELAY_BEGIN_DIR cell from <b>cell</b>, decode it, and
+ * place the result in <b>bcell</b>. On success return 0; on failure return
+ * <0 and set *<b>end_reason_out</b> to the end reason we should send back to
+ * the client.
+ *
+ * Return -1 in the case where we want to send a RELAY_END cell, and < -1 when
+ * we don't.
+ **/
+STATIC int
+begin_cell_parse(const cell_t *cell, begin_cell_t *bcell,
+ uint8_t *end_reason_out)
+{
+ relay_header_t rh;
+ const uint8_t *body, *nul;
+
+ memset(bcell, 0, sizeof(*bcell));
+ *end_reason_out = END_STREAM_REASON_MISC;
+
+ relay_header_unpack(&rh, cell->payload);
+ if (rh.length > RELAY_PAYLOAD_SIZE) {
+ return -2; /*XXXX why not TORPROTOCOL? */
+ }
+
+ bcell->stream_id = rh.stream_id;
+
+ if (rh.command == RELAY_COMMAND_BEGIN_DIR) {
+ bcell->is_begindir = 1;
+ return 0;
+ } else if (rh.command != RELAY_COMMAND_BEGIN) {
+ log_warn(LD_BUG, "Got an unexpected command %d", (int)rh.command);
+ *end_reason_out = END_STREAM_REASON_INTERNAL;
+ return -1;
+ }
+
+ body = cell->payload + RELAY_HEADER_SIZE;
+ nul = memchr(body, 0, rh.length);
+ if (! nul) {
+ log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
+ "Relay begin cell has no \\0. Closing.");
+ *end_reason_out = END_STREAM_REASON_TORPROTOCOL;
+ return -1;
+ }
+
+ if (tor_addr_port_split(LOG_PROTOCOL_WARN,
+ (char*)(body),
+ &bcell->address,&bcell->port)<0) {
+ log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
+ "Unable to parse addr:port in relay begin cell. Closing.");
+ *end_reason_out = END_STREAM_REASON_TORPROTOCOL;
+ return -1;
+ }
+ if (bcell->port == 0) {
+ log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
+ "Missing port in relay begin cell. Closing.");
+ tor_free(bcell->address);
+ *end_reason_out = END_STREAM_REASON_TORPROTOCOL;
+ return -1;
+ }
+ if (body + rh.length >= nul + 4)
+ bcell->flags = ntohl(get_uint32(nul+1));
+
+ return 0;
+}
+
+/** For the given <b>circ</b> and the edge connection <b>conn</b>, setup the
+ * connection, attach it to the circ and connect it. Return 0 on success
+ * or END_CIRC_AT_ORIGIN if we can't find the requested hidden service port
+ * where the caller should close the circuit. */
+static int
+handle_hs_exit_conn(circuit_t *circ, edge_connection_t *conn)
+{
+ int ret;
+ origin_circuit_t *origin_circ;
+
+ assert_circuit_ok(circ);
+ tor_assert(circ->purpose == CIRCUIT_PURPOSE_S_REND_JOINED);
+ tor_assert(conn);
+
+ log_debug(LD_REND, "Connecting the hidden service rendezvous circuit "
+ "to the service destination.");
+
+ origin_circ = TO_ORIGIN_CIRCUIT(circ);
+ conn->base_.address = tor_strdup("(rendezvous)");
+ conn->base_.state = EXIT_CONN_STATE_CONNECTING;
+
+ /* The circuit either has an hs identifier for v3+ or a rend_data for legacy
+ * service. */
+ if (origin_circ->rend_data) {
+ conn->rend_data = rend_data_dup(origin_circ->rend_data);
+ tor_assert(connection_edge_is_rendezvous_stream(conn));
+ ret = rend_service_set_connection_addr_port(conn, origin_circ);
+ } else if (origin_circ->hs_ident) {
+ /* Setup the identifier to be the one for the circuit service. */
+ conn->hs_ident =
+ hs_ident_edge_conn_new(&origin_circ->hs_ident->identity_pk);
+ tor_assert(connection_edge_is_rendezvous_stream(conn));
+ ret = hs_service_set_conn_addr_port(origin_circ, conn);
+ } else {
+ /* We should never get here if the circuit's purpose is rendezvous. */
+ tor_assert_nonfatal_unreached();
+ return -1;
+ }
+ if (ret < 0) {
+ log_info(LD_REND, "Didn't find rendezvous service (addr%s, port %d)",
+ fmt_addr(&TO_CONN(conn)->addr), TO_CONN(conn)->port);
+ /* Send back reason DONE because we want to make hidden service port
+ * scanning harder thus instead of returning that the exit policy
+ * didn't match, which makes it obvious that the port is closed,
+ * return DONE and kill the circuit. That way, a user (malicious or
+ * not) needs one circuit per bad port unless it matches the policy of
+ * the hidden service. */
+ relay_send_end_cell_from_edge(conn->stream_id, circ,
+ END_STREAM_REASON_DONE,
+ origin_circ->cpath->prev);
+ connection_free_(TO_CONN(conn));
+
+ /* Drop the circuit here since it might be someone deliberately
+ * scanning the hidden service ports. Note that this mitigates port
+ * scanning by adding more work on the attacker side to successfully
+ * scan but does not fully solve it. */
+ if (ret < -1) {
+ return END_CIRC_AT_ORIGIN;
+ } else {
+ return 0;
+ }
+ }
+
+ /* Link the circuit and the connection crypt path. */
+ conn->cpath_layer = origin_circ->cpath->prev;
+
+ /* Add it into the linked list of p_streams on this circuit */
+ conn->next_stream = origin_circ->p_streams;
+ origin_circ->p_streams = conn;
+ conn->on_circuit = circ;
+ assert_circuit_ok(circ);
+
+ hs_inc_rdv_stream_counter(origin_circ);
+
+ /* Connect tor to the hidden service destination. */
+ connection_exit_connect(conn);
+
+ /* For path bias: This circuit was used successfully */
+ pathbias_mark_use_success(origin_circ);
+ return 0;
+}
+
+/** A relay 'begin' or 'begin_dir' cell has arrived, and either we are
+ * an exit hop for the circuit, or we are the origin and it is a
+ * rendezvous begin.
+ *
+ * Launch a new exit connection and initialize things appropriately.
+ *
+ * If it's a rendezvous stream, call connection_exit_connect() on
+ * it.
+ *
+ * For general streams, call dns_resolve() on it first, and only call
+ * connection_exit_connect() if the dns answer is already known.
+ *
+ * Note that we don't call connection_add() on the new stream! We wait
+ * for connection_exit_connect() to do that.
+ *
+ * Return -(some circuit end reason) if we want to tear down <b>circ</b>.
+ * Else return 0.
+ */
+int
+connection_exit_begin_conn(cell_t *cell, circuit_t *circ)
+{
+ edge_connection_t *n_stream;
+ relay_header_t rh;
+ char *address = NULL;
+ uint16_t port = 0;
+ or_circuit_t *or_circ = NULL;
+ origin_circuit_t *origin_circ = NULL;
+ crypt_path_t *layer_hint = NULL;
+ const or_options_t *options = get_options();
+ begin_cell_t bcell;
+ int rv;
+ uint8_t end_reason=0;
+
+ assert_circuit_ok(circ);
+ if (!CIRCUIT_IS_ORIGIN(circ)) {
+ or_circ = TO_OR_CIRCUIT(circ);
+ } else {
+ tor_assert(circ->purpose == CIRCUIT_PURPOSE_S_REND_JOINED);
+ origin_circ = TO_ORIGIN_CIRCUIT(circ);
+ layer_hint = origin_circ->cpath->prev;
+ }
+
+ relay_header_unpack(&rh, cell->payload);
+ if (rh.length > RELAY_PAYLOAD_SIZE)
+ return -END_CIRC_REASON_TORPROTOCOL;
+
+ if (!server_mode(options) &&
+ circ->purpose != CIRCUIT_PURPOSE_S_REND_JOINED) {
+ log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
+ "Relay begin cell at non-server. Closing.");
+ relay_send_end_cell_from_edge(rh.stream_id, circ,
+ END_STREAM_REASON_EXITPOLICY, NULL);
+ return 0;
+ }
+
+ rv = begin_cell_parse(cell, &bcell, &end_reason);
+ if (rv < -1) {
+ return -END_CIRC_REASON_TORPROTOCOL;
+ } else if (rv == -1) {
+ tor_free(bcell.address);
+ relay_send_end_cell_from_edge(rh.stream_id, circ, end_reason, layer_hint);
+ return 0;
+ }
+
+ if (! bcell.is_begindir) {
+ /* Steal reference */
+ address = bcell.address;
+ port = bcell.port;
+
+ if (or_circ && or_circ->p_chan) {
+ const int client_chan = channel_is_client(or_circ->p_chan);
+ if ((client_chan ||
+ (!connection_or_digest_is_known_relay(
+ or_circ->p_chan->identity_digest) &&
+ should_refuse_unknown_exits(options)))) {
+ /* Don't let clients use us as a single-hop proxy. It attracts
+ * attackers and users who'd be better off with, well, single-hop
+ * proxies. */
+ log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
+ "Attempt by %s to open a stream %s. Closing.",
+ safe_str(channel_get_canonical_remote_descr(or_circ->p_chan)),
+ client_chan ? "on first hop of circuit" :
+ "from unknown relay");
+ relay_send_end_cell_from_edge(rh.stream_id, circ,
+ client_chan ?
+ END_STREAM_REASON_TORPROTOCOL :
+ END_STREAM_REASON_MISC,
+ NULL);
+ tor_free(address);
+ return 0;
+ }
+ }
+ } else if (rh.command == RELAY_COMMAND_BEGIN_DIR) {
+ if (!directory_permits_begindir_requests(options) ||
+ circ->purpose != CIRCUIT_PURPOSE_OR) {
+ relay_send_end_cell_from_edge(rh.stream_id, circ,
+ END_STREAM_REASON_NOTDIRECTORY, layer_hint);
+ return 0;
+ }
+ /* Make sure to get the 'real' address of the previous hop: the
+ * caller might want to know whether the remote IP address has changed,
+ * and we might already have corrected base_.addr[ess] for the relay's
+ * canonical IP address. */
+ if (or_circ && or_circ->p_chan)
+ address = tor_strdup(channel_get_actual_remote_address(or_circ->p_chan));
+ else
+ address = tor_strdup("127.0.0.1");
+ port = 1; /* XXXX This value is never actually used anywhere, and there
+ * isn't "really" a connection here. But we
+ * need to set it to something nonzero. */
+ } else {
+ log_warn(LD_BUG, "Got an unexpected command %d", (int)rh.command);
+ relay_send_end_cell_from_edge(rh.stream_id, circ,
+ END_STREAM_REASON_INTERNAL, layer_hint);
+ return 0;
+ }
+
+ if (! options->IPv6Exit) {
+ /* I don't care if you prefer IPv6; I can't give you any. */
+ bcell.flags &= ~BEGIN_FLAG_IPV6_PREFERRED;
+ /* If you don't want IPv4, I can't help. */
+ if (bcell.flags & BEGIN_FLAG_IPV4_NOT_OK) {
+ tor_free(address);
+ relay_send_end_cell_from_edge(rh.stream_id, circ,
+ END_STREAM_REASON_EXITPOLICY, layer_hint);
+ return 0;
+ }
+ }
+
+ log_debug(LD_EXIT,"Creating new exit connection.");
+ /* The 'AF_INET' here is temporary; we might need to change it later in
+ * connection_exit_connect(). */
+ n_stream = edge_connection_new(CONN_TYPE_EXIT, AF_INET);
+
+ /* Remember the tunneled request ID in the new edge connection, so that
+ * we can measure download times. */
+ n_stream->dirreq_id = circ->dirreq_id;
+
+ n_stream->base_.purpose = EXIT_PURPOSE_CONNECT;
+ n_stream->begincell_flags = bcell.flags;
+ n_stream->stream_id = rh.stream_id;
+ n_stream->base_.port = port;
+ /* leave n_stream->s at -1, because it's not yet valid */
+ n_stream->package_window = STREAMWINDOW_START;
+ n_stream->deliver_window = STREAMWINDOW_START;
+
+ if (circ->purpose == CIRCUIT_PURPOSE_S_REND_JOINED) {
+ int ret;
+ tor_free(address);
+ /* We handle this circuit and stream in this function for all supported
+ * hidden service version. */
+ ret = handle_hs_exit_conn(circ, n_stream);
+
+ if (ret == 0) {
+ /* This was a valid cell. Count it as delivered + overhead. */
+ circuit_read_valid_data(origin_circ, rh.length);
+ }
+ return ret;
+ }
+ tor_strlower(address);
+ n_stream->base_.address = address;
+ n_stream->base_.state = EXIT_CONN_STATE_RESOLVEFAILED;
+ /* default to failed, change in dns_resolve if it turns out not to fail */
+
+ /* If we're hibernating or shutting down, we refuse to open new streams. */
+ if (we_are_hibernating()) {
+ relay_send_end_cell_from_edge(rh.stream_id, circ,
+ END_STREAM_REASON_HIBERNATING, NULL);
+ connection_free_(TO_CONN(n_stream));
+ return 0;
+ }
+
+ n_stream->on_circuit = circ;
+
+ if (rh.command == RELAY_COMMAND_BEGIN_DIR) {
+ tor_addr_t tmp_addr;
+ tor_assert(or_circ);
+ if (or_circ->p_chan &&
+ channel_get_addr_if_possible(or_circ->p_chan, &tmp_addr)) {
+ tor_addr_copy(&n_stream->base_.addr, &tmp_addr);
+ }
+ return connection_exit_connect_dir(n_stream);
+ }
+
+ log_debug(LD_EXIT,"about to start the dns_resolve().");
+
+ /* send it off to the gethostbyname farm */
+ switch (dns_resolve(n_stream)) {
+ case 1: /* resolve worked; now n_stream is attached to circ. */
+ assert_circuit_ok(circ);
+ log_debug(LD_EXIT,"about to call connection_exit_connect().");
+ connection_exit_connect(n_stream);
+ return 0;
+ case -1: /* resolve failed */
+ relay_send_end_cell_from_edge(rh.stream_id, circ,
+ END_STREAM_REASON_RESOLVEFAILED, NULL);
+ /* n_stream got freed. don't touch it. */
+ break;
+ case 0: /* resolve added to pending list */
+ assert_circuit_ok(circ);
+ break;
+ }
+ return 0;
+}
+
+/**
+ * Called when we receive a RELAY_COMMAND_RESOLVE cell 'cell' along the
+ * circuit <b>circ</b>;
+ * begin resolving the hostname, and (eventually) reply with a RESOLVED cell.
+ */
+int
+connection_exit_begin_resolve(cell_t *cell, or_circuit_t *circ)
+{
+ edge_connection_t *dummy_conn;
+ relay_header_t rh;
+
+ assert_circuit_ok(TO_CIRCUIT(circ));
+ relay_header_unpack(&rh, cell->payload);
+ if (rh.length > RELAY_PAYLOAD_SIZE)
+ return -1;
+
+ /* This 'dummy_conn' only exists to remember the stream ID
+ * associated with the resolve request; and to make the
+ * implementation of dns.c more uniform. (We really only need to
+ * remember the circuit, the stream ID, and the hostname to be
+ * resolved; but if we didn't store them in a connection like this,
+ * the housekeeping in dns.c would get way more complicated.)
+ */
+ dummy_conn = edge_connection_new(CONN_TYPE_EXIT, AF_INET);
+ dummy_conn->stream_id = rh.stream_id;
+ dummy_conn->base_.address = tor_strndup(
+ (char*)cell->payload+RELAY_HEADER_SIZE,
+ rh.length);
+ dummy_conn->base_.port = 0;
+ dummy_conn->base_.state = EXIT_CONN_STATE_RESOLVEFAILED;
+ dummy_conn->base_.purpose = EXIT_PURPOSE_RESOLVE;
+
+ dummy_conn->on_circuit = TO_CIRCUIT(circ);
+
+ /* send it off to the gethostbyname farm */
+ switch (dns_resolve(dummy_conn)) {
+ case -1: /* Impossible to resolve; a resolved cell was sent. */
+ /* Connection freed; don't touch it. */
+ return 0;
+ case 1: /* The result was cached; a resolved cell was sent. */
+ if (!dummy_conn->base_.marked_for_close)
+ connection_free_(TO_CONN(dummy_conn));
+ return 0;
+ case 0: /* resolve added to pending list */
+ assert_circuit_ok(TO_CIRCUIT(circ));
+ break;
+ }
+ return 0;
+}
+
+/** Helper: Return true and set *<b>why_rejected</b> to an optional clarifying
+ * message message iff we do not allow connections to <b>addr</b>:<b>port</b>.
+ */
+static int
+my_exit_policy_rejects(const tor_addr_t *addr,
+ uint16_t port,
+ const char **why_rejected)
+{
+ if (router_compare_to_my_exit_policy(addr, port)) {
+ *why_rejected = "";
+ return 1;
+ } else if (tor_addr_family(addr) == AF_INET6 && !get_options()->IPv6Exit) {
+ *why_rejected = " (IPv6 address without IPv6Exit configured)";
+ return 1;
+ }
+ return 0;
+}
+
+/** Connect to conn's specified addr and port. If it worked, conn
+ * has now been added to the connection_array.
+ *
+ * Send back a connected cell. Include the resolved IP of the destination
+ * address, but <em>only</em> if it's a general exit stream. (Rendezvous
+ * streams must not reveal what IP they connected to.)
+ */
+void
+connection_exit_connect(edge_connection_t *edge_conn)
+{
+ const tor_addr_t *addr;
+ uint16_t port;
+ connection_t *conn = TO_CONN(edge_conn);
+ int socket_error = 0, result;
+ const char *why_failed_exit_policy = NULL;
+
+ /* Apply exit policy to non-rendezvous connections. */
+ if (! connection_edge_is_rendezvous_stream(edge_conn) &&
+ my_exit_policy_rejects(&edge_conn->base_.addr,
+ edge_conn->base_.port,
+ &why_failed_exit_policy)) {
+ if (BUG(!why_failed_exit_policy))
+ why_failed_exit_policy = "";
+ log_info(LD_EXIT,"%s:%d failed exit policy%s. Closing.",
+ escaped_safe_str_client(conn->address), conn->port,
+ why_failed_exit_policy);
+ connection_edge_end(edge_conn, END_STREAM_REASON_EXITPOLICY);
+ circuit_detach_stream(circuit_get_by_edge_conn(edge_conn), edge_conn);
+ connection_free(conn);
+ return;
+ }
+
+#ifdef HAVE_SYS_UN_H
+ if (conn->socket_family != AF_UNIX) {
+#else
+ {
+#endif /* defined(HAVE_SYS_UN_H) */
+ addr = &conn->addr;
+ port = conn->port;
+
+ if (tor_addr_family(addr) == AF_INET6)
+ conn->socket_family = AF_INET6;
+
+ log_debug(LD_EXIT, "about to try connecting");
+ result = connection_connect(conn, conn->address,
+ addr, port, &socket_error);
+#ifdef HAVE_SYS_UN_H
+ } else {
+ /*
+ * In the AF_UNIX case, we expect to have already had conn->port = 1,
+ * tor_addr_make_unspec(conn->addr) (cf. the way we mark in the incoming
+ * case in connection_handle_listener_read()), and conn->address should
+ * have the socket path to connect to.
+ */
+ tor_assert(conn->address && strlen(conn->address) > 0);
+
+ log_debug(LD_EXIT, "about to try connecting");
+ result = connection_connect_unix(conn, conn->address, &socket_error);
+#endif /* defined(HAVE_SYS_UN_H) */
+ }
+
+ switch (result) {
+ case -1: {
+ int reason = errno_to_stream_end_reason(socket_error);
+ connection_edge_end(edge_conn, reason);
+ circuit_detach_stream(circuit_get_by_edge_conn(edge_conn), edge_conn);
+ connection_free(conn);
+ return;
+ }
+ case 0:
+ conn->state = EXIT_CONN_STATE_CONNECTING;
+
+ connection_watch_events(conn, READ_EVENT | WRITE_EVENT);
+ /* writable indicates finish;
+ * readable/error indicates broken link in windows-land. */
+ return;
+ /* case 1: fall through */
+ }
+
+ conn->state = EXIT_CONN_STATE_OPEN;
+ if (connection_get_outbuf_len(conn)) {
+ /* in case there are any queued data cells, from e.g. optimistic data */
+ connection_watch_events(conn, READ_EVENT|WRITE_EVENT);
+ } else {
+ connection_watch_events(conn, READ_EVENT);
+ }
+
+ /* also, deliver a 'connected' cell back through the circuit. */
+ if (connection_edge_is_rendezvous_stream(edge_conn)) {
+ /* don't send an address back! */
+ connection_edge_send_command(edge_conn,
+ RELAY_COMMAND_CONNECTED,
+ NULL, 0);
+ } else { /* normal stream */
+ uint8_t connected_payload[MAX_CONNECTED_CELL_PAYLOAD_LEN];
+ int connected_payload_len =
+ connected_cell_format_payload(connected_payload, &conn->addr,
+ edge_conn->address_ttl);
+ if (connected_payload_len < 0) {
+ connection_edge_end(edge_conn, END_STREAM_REASON_INTERNAL);
+ circuit_detach_stream(circuit_get_by_edge_conn(edge_conn), edge_conn);
+ connection_free(conn);
+ return;
+ }
+
+ connection_edge_send_command(edge_conn,
+ RELAY_COMMAND_CONNECTED,
+ (char*)connected_payload,
+ connected_payload_len);
+ }
+}
+
+/** Given an exit conn that should attach to us as a directory server, open a
+ * bridge connection with a linked connection pair, create a new directory
+ * conn, and join them together. Return 0 on success (or if there was an
+ * error we could send back an end cell for). Return -(some circuit end
+ * reason) if the circuit needs to be torn down. Either connects
+ * <b>exitconn</b>, frees it, or marks it, as appropriate.
+ */
+static int
+connection_exit_connect_dir(edge_connection_t *exitconn)
+{
+ dir_connection_t *dirconn = NULL;
+ or_circuit_t *circ = TO_OR_CIRCUIT(exitconn->on_circuit);
+
+ log_info(LD_EXIT, "Opening local connection for anonymized directory exit");
+
+ exitconn->base_.state = EXIT_CONN_STATE_OPEN;
+
+ dirconn = dir_connection_new(tor_addr_family(&exitconn->base_.addr));
+
+ tor_addr_copy(&dirconn->base_.addr, &exitconn->base_.addr);
+ dirconn->base_.port = 0;
+ dirconn->base_.address = tor_strdup(exitconn->base_.address);
+ dirconn->base_.type = CONN_TYPE_DIR;
+ dirconn->base_.purpose = DIR_PURPOSE_SERVER;
+ dirconn->base_.state = DIR_CONN_STATE_SERVER_COMMAND_WAIT;
+
+ /* Note that the new dir conn belongs to the same tunneled request as
+ * the edge conn, so that we can measure download times. */
+ dirconn->dirreq_id = exitconn->dirreq_id;
+
+ connection_link_connections(TO_CONN(dirconn), TO_CONN(exitconn));
+
+ if (connection_add(TO_CONN(exitconn))<0) {
+ connection_edge_end(exitconn, END_STREAM_REASON_RESOURCELIMIT);
+ connection_free_(TO_CONN(exitconn));
+ connection_free_(TO_CONN(dirconn));
+ return 0;
+ }
+
+ /* link exitconn to circ, now that we know we can use it. */
+ exitconn->next_stream = circ->n_streams;
+ circ->n_streams = exitconn;
+
+ if (connection_add(TO_CONN(dirconn))<0) {
+ connection_edge_end(exitconn, END_STREAM_REASON_RESOURCELIMIT);
+ connection_close_immediate(TO_CONN(exitconn));
+ connection_mark_for_close(TO_CONN(exitconn));
+ connection_free_(TO_CONN(dirconn));
+ return 0;
+ }
+
+ connection_start_reading(TO_CONN(dirconn));
+ connection_start_reading(TO_CONN(exitconn));
+
+ if (connection_edge_send_command(exitconn,
+ RELAY_COMMAND_CONNECTED, NULL, 0) < 0) {
+ connection_mark_for_close(TO_CONN(exitconn));
+ connection_mark_for_close(TO_CONN(dirconn));
+ return 0;
+ }
+
+ return 0;
+}
+
+/** Return 1 if <b>conn</b> is a rendezvous stream, or 0 if
+ * it is a general stream.
+ */
+int
+connection_edge_is_rendezvous_stream(const edge_connection_t *conn)
+{
+ tor_assert(conn);
+ /* It should not be possible to set both of these structs */
+ tor_assert_nonfatal(!(conn->rend_data && conn->hs_ident));
+
+ if (conn->rend_data || conn->hs_ident) {
+ return 1;
+ }
+ return 0;
+}
+
+/** Return 1 if router <b>exit_node</b> is likely to allow stream <b>conn</b>
+ * to exit from it, or 0 if it probably will not allow it.
+ * (We might be uncertain if conn's destination address has not yet been
+ * resolved.)
+ */
+int
+connection_ap_can_use_exit(const entry_connection_t *conn,
+ const node_t *exit_node)
+{
+ const or_options_t *options = get_options();
+
+ tor_assert(conn);
+ tor_assert(conn->socks_request);
+ tor_assert(exit_node);
+
+ /* If a particular exit node has been requested for the new connection,
+ * make sure the exit node of the existing circuit matches exactly.
+ */
+ if (conn->chosen_exit_name) {
+ const node_t *chosen_exit =
+ node_get_by_nickname(conn->chosen_exit_name, 0);
+ if (!chosen_exit || tor_memneq(chosen_exit->identity,
+ exit_node->identity, DIGEST_LEN)) {
+ /* doesn't match */
+// log_debug(LD_APP,"Requested node '%s', considering node '%s'. No.",
+// conn->chosen_exit_name, exit->nickname);
+ return 0;
+ }
+ }
+
+ if (conn->use_begindir) {
+ /* Internal directory fetches do not count as exiting. */
+ return 1;
+ }
+
+ if (conn->socks_request->command == SOCKS_COMMAND_CONNECT) {
+ tor_addr_t addr, *addrp = NULL;
+ addr_policy_result_t r;
+ if (0 == tor_addr_parse(&addr, conn->socks_request->address)) {
+ addrp = &addr;
+ } else if (!conn->entry_cfg.ipv4_traffic && conn->entry_cfg.ipv6_traffic) {
+ tor_addr_make_null(&addr, AF_INET6);
+ addrp = &addr;
+ } else if (conn->entry_cfg.ipv4_traffic && !conn->entry_cfg.ipv6_traffic) {
+ tor_addr_make_null(&addr, AF_INET);
+ addrp = &addr;
+ }
+ r = compare_tor_addr_to_node_policy(addrp, conn->socks_request->port,
+ exit_node);
+ if (r == ADDR_POLICY_REJECTED)
+ return 0; /* We know the address, and the exit policy rejects it. */
+ if (r == ADDR_POLICY_PROBABLY_REJECTED && !conn->chosen_exit_name)
+ return 0; /* We don't know the addr, but the exit policy rejects most
+ * addresses with this port. Since the user didn't ask for
+ * this node, err on the side of caution. */
+ } else if (SOCKS_COMMAND_IS_RESOLVE(conn->socks_request->command)) {
+ /* Don't send DNS requests to non-exit servers by default. */
+ if (!conn->chosen_exit_name && node_exit_policy_rejects_all(exit_node))
+ return 0;
+ }
+ if (routerset_contains_node(options->ExcludeExitNodesUnion_, exit_node)) {
+ /* Not a suitable exit. Refuse it. */
+ return 0;
+ }
+
+ return 1;
+}
+
+/** If address is of the form "y.onion" with a well-formed handle y:
+ * Put a NUL after y, lower-case it, and return ONION_V2_HOSTNAME or
+ * ONION_V3_HOSTNAME depending on the HS version.
+ *
+ * If address is of the form "x.y.onion" with a well-formed handle x:
+ * Drop "x.", put a NUL after y, lower-case it, and return
+ * ONION_V2_HOSTNAME or ONION_V3_HOSTNAME depending on the HS version.
+ *
+ * If address is of the form "y.onion" with a badly-formed handle y:
+ * Return BAD_HOSTNAME and log a message.
+ *
+ * If address is of the form "y.exit":
+ * Put a NUL after y and return EXIT_HOSTNAME.
+ *
+ * Otherwise:
+ * Return NORMAL_HOSTNAME and change nothing.
+ */
+hostname_type_t
+parse_extended_hostname(char *address)
+{
+ char *s;
+ char *q;
+ char query[HS_SERVICE_ADDR_LEN_BASE32+1];
+
+ s = strrchr(address,'.');
+ if (!s)
+ return NORMAL_HOSTNAME; /* no dot, thus normal */
+ if (!strcmp(s+1,"exit")) {
+ *s = 0; /* NUL-terminate it */
+ return EXIT_HOSTNAME; /* .exit */
+ }
+ if (strcmp(s+1,"onion"))
+ return NORMAL_HOSTNAME; /* neither .exit nor .onion, thus normal */
+
+ /* so it is .onion */
+ *s = 0; /* NUL-terminate it */
+ /* locate a 'sub-domain' component, in order to remove it */
+ q = strrchr(address, '.');
+ if (q == address) {
+ goto failed; /* reject sub-domain, as DNS does */
+ }
+ q = (NULL == q) ? address : q + 1;
+ if (strlcpy(query, q, HS_SERVICE_ADDR_LEN_BASE32+1) >=
+ HS_SERVICE_ADDR_LEN_BASE32+1)
+ goto failed;
+ if (q != address) {
+ memmove(address, q, strlen(q) + 1 /* also get \0 */);
+ }
+ if (rend_valid_v2_service_id(query)) {
+ return ONION_V2_HOSTNAME; /* success */
+ }
+ if (hs_address_is_valid(query)) {
+ return ONION_V3_HOSTNAME;
+ }
+ failed:
+ /* otherwise, return to previous state and return 0 */
+ *s = '.';
+ log_warn(LD_APP, "Invalid onion hostname %s; rejecting",
+ safe_str_client(address));
+ return BAD_HOSTNAME;
+}
+
+/** Return true iff the (possibly NULL) <b>alen</b>-byte chunk of memory at
+ * <b>a</b> is equal to the (possibly NULL) <b>blen</b>-byte chunk of memory
+ * at <b>b</b>. */
+static int
+memeq_opt(const char *a, size_t alen, const char *b, size_t blen)
+{
+ if (a == NULL) {
+ return (b == NULL);
+ } else if (b == NULL) {
+ return 0;
+ } else if (alen != blen) {
+ return 0;
+ } else {
+ return tor_memeq(a, b, alen);
+ }
+}
+
+/**
+ * Return true iff none of the isolation flags and fields in <b>conn</b>
+ * should prevent it from being attached to <b>circ</b>.
+ */
+int
+connection_edge_compatible_with_circuit(const entry_connection_t *conn,
+ const origin_circuit_t *circ)
+{
+ const uint8_t iso = conn->entry_cfg.isolation_flags;
+ const socks_request_t *sr = conn->socks_request;
+
+ /* If circ has never been used for an isolated connection, we can
+ * totally use it for this one. */
+ if (!circ->isolation_values_set)
+ return 1;
+
+ /* If circ has been used for connections having more than one value
+ * for some field f, it will have the corresponding bit set in
+ * isolation_flags_mixed. If isolation_flags_mixed has any bits
+ * in common with iso, then conn must be isolated from at least
+ * one stream that has been attached to circ. */
+ if ((iso & circ->isolation_flags_mixed) != 0) {
+ /* For at least one field where conn is isolated, the circuit
+ * already has mixed streams. */
+ return 0;
+ }
+
+ if (! conn->original_dest_address) {
+ log_warn(LD_BUG, "Reached connection_edge_compatible_with_circuit without "
+ "having set conn->original_dest_address");
+ ((entry_connection_t*)conn)->original_dest_address =
+ tor_strdup(conn->socks_request->address);
+ }
+
+ if ((iso & ISO_STREAM) &&
+ (circ->associated_isolated_stream_global_id !=
+ ENTRY_TO_CONN(conn)->global_identifier))
+ return 0;
+
+ if ((iso & ISO_DESTPORT) && conn->socks_request->port != circ->dest_port)
+ return 0;
+ if ((iso & ISO_DESTADDR) &&
+ strcasecmp(conn->original_dest_address, circ->dest_address))
+ return 0;
+ if ((iso & ISO_SOCKSAUTH) &&
+ (! memeq_opt(sr->username, sr->usernamelen,
+ circ->socks_username, circ->socks_username_len) ||
+ ! memeq_opt(sr->password, sr->passwordlen,
+ circ->socks_password, circ->socks_password_len)))
+ return 0;
+ if ((iso & ISO_CLIENTPROTO) &&
+ (conn->socks_request->listener_type != circ->client_proto_type ||
+ conn->socks_request->socks_version != circ->client_proto_socksver))
+ return 0;
+ if ((iso & ISO_CLIENTADDR) &&
+ !tor_addr_eq(&ENTRY_TO_CONN(conn)->addr, &circ->client_addr))
+ return 0;
+ if ((iso & ISO_SESSIONGRP) &&
+ conn->entry_cfg.session_group != circ->session_group)
+ return 0;
+ if ((iso & ISO_NYM_EPOCH) && conn->nym_epoch != circ->nym_epoch)
+ return 0;
+
+ return 1;
+}
+
+/**
+ * If <b>dry_run</b> is false, update <b>circ</b>'s isolation flags and fields
+ * to reflect having had <b>conn</b> attached to it, and return 0. Otherwise,
+ * if <b>dry_run</b> is true, then make no changes to <b>circ</b>, and return
+ * a bitfield of isolation flags that we would have to set in
+ * isolation_flags_mixed to add <b>conn</b> to <b>circ</b>, or -1 if
+ * <b>circ</b> has had no streams attached to it.
+ */
+int
+connection_edge_update_circuit_isolation(const entry_connection_t *conn,
+ origin_circuit_t *circ,
+ int dry_run)
+{
+ const socks_request_t *sr = conn->socks_request;
+ if (! conn->original_dest_address) {
+ log_warn(LD_BUG, "Reached connection_update_circuit_isolation without "
+ "having set conn->original_dest_address");
+ ((entry_connection_t*)conn)->original_dest_address =
+ tor_strdup(conn->socks_request->address);
+ }
+
+ if (!circ->isolation_values_set) {
+ if (dry_run)
+ return -1;
+ circ->associated_isolated_stream_global_id =
+ ENTRY_TO_CONN(conn)->global_identifier;
+ circ->dest_port = conn->socks_request->port;
+ circ->dest_address = tor_strdup(conn->original_dest_address);
+ circ->client_proto_type = conn->socks_request->listener_type;
+ circ->client_proto_socksver = conn->socks_request->socks_version;
+ tor_addr_copy(&circ->client_addr, &ENTRY_TO_CONN(conn)->addr);
+ circ->session_group = conn->entry_cfg.session_group;
+ circ->nym_epoch = conn->nym_epoch;
+ circ->socks_username = sr->username ?
+ tor_memdup(sr->username, sr->usernamelen) : NULL;
+ circ->socks_password = sr->password ?
+ tor_memdup(sr->password, sr->passwordlen) : NULL;
+ circ->socks_username_len = sr->usernamelen;
+ circ->socks_password_len = sr->passwordlen;
+
+ circ->isolation_values_set = 1;
+ return 0;
+ } else {
+ uint8_t mixed = 0;
+ if (conn->socks_request->port != circ->dest_port)
+ mixed |= ISO_DESTPORT;
+ if (strcasecmp(conn->original_dest_address, circ->dest_address))
+ mixed |= ISO_DESTADDR;
+ if (!memeq_opt(sr->username, sr->usernamelen,
+ circ->socks_username, circ->socks_username_len) ||
+ !memeq_opt(sr->password, sr->passwordlen,
+ circ->socks_password, circ->socks_password_len))
+ mixed |= ISO_SOCKSAUTH;
+ if ((conn->socks_request->listener_type != circ->client_proto_type ||
+ conn->socks_request->socks_version != circ->client_proto_socksver))
+ mixed |= ISO_CLIENTPROTO;
+ if (!tor_addr_eq(&ENTRY_TO_CONN(conn)->addr, &circ->client_addr))
+ mixed |= ISO_CLIENTADDR;
+ if (conn->entry_cfg.session_group != circ->session_group)
+ mixed |= ISO_SESSIONGRP;
+ if (conn->nym_epoch != circ->nym_epoch)
+ mixed |= ISO_NYM_EPOCH;
+
+ if (dry_run)
+ return mixed;
+
+ if ((mixed & conn->entry_cfg.isolation_flags) != 0) {
+ log_warn(LD_BUG, "Updating a circuit with seemingly incompatible "
+ "isolation flags.");
+ }
+ circ->isolation_flags_mixed |= mixed;
+ return 0;
+ }
+}
+
+/**
+ * Clear the isolation settings on <b>circ</b>.
+ *
+ * This only works on an open circuit that has never had a stream attached to
+ * it, and whose isolation settings are hypothetical. (We set hypothetical
+ * isolation settings on circuits as we're launching them, so that we
+ * know whether they can handle more streams or whether we need to launch
+ * even more circuits. Once the circuit is open, if it turns out that
+ * we no longer have any streams to attach to it, we clear the isolation flags
+ * and data so that other streams can have a chance.)
+ */
+void
+circuit_clear_isolation(origin_circuit_t *circ)
+{
+ if (circ->isolation_any_streams_attached) {
+ log_warn(LD_BUG, "Tried to clear the isolation status of a dirty circuit");
+ return;
+ }
+ if (TO_CIRCUIT(circ)->state != CIRCUIT_STATE_OPEN) {
+ log_warn(LD_BUG, "Tried to clear the isolation status of a non-open "
+ "circuit");
+ return;
+ }
+
+ circ->isolation_values_set = 0;
+ circ->isolation_flags_mixed = 0;
+ circ->associated_isolated_stream_global_id = 0;
+ circ->client_proto_type = 0;
+ circ->client_proto_socksver = 0;
+ circ->dest_port = 0;
+ tor_addr_make_unspec(&circ->client_addr);
+ tor_free(circ->dest_address);
+ circ->session_group = -1;
+ circ->nym_epoch = 0;
+ if (circ->socks_username) {
+ memwipe(circ->socks_username, 0x11, circ->socks_username_len);
+ tor_free(circ->socks_username);
+ }
+ if (circ->socks_password) {
+ memwipe(circ->socks_password, 0x05, circ->socks_password_len);
+ tor_free(circ->socks_password);
+ }
+ circ->socks_username_len = circ->socks_password_len = 0;
+}
+
+/** Free all storage held in module-scoped variables for connection_edge.c */
+void
+connection_edge_free_all(void)
+{
+ untried_pending_connections = 0;
+ smartlist_free(pending_entry_connections);
+ pending_entry_connections = NULL;
+ mainloop_event_free(attach_pending_entry_connections_ev);
+}
diff --cc src/core/or/connection_edge.h
index 1348dd49f,000000000..a1da8a34c
mode 100644,000000..100644
--- a/src/core/or/connection_edge.h
+++ b/src/core/or/connection_edge.h
@@@ -1,259 -1,0 +1,264 @@@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file connection_edge.h
+ * \brief Header file for connection_edge.c.
+ **/
+
+#ifndef TOR_CONNECTION_EDGE_H
+#define TOR_CONNECTION_EDGE_H
+
+#include "lib/testsupport/testsupport.h"
+
+edge_connection_t *TO_EDGE_CONN(connection_t *);
+entry_connection_t *TO_ENTRY_CONN(connection_t *);
+entry_connection_t *EDGE_TO_ENTRY_CONN(edge_connection_t *);
+
+#define EXIT_CONN_STATE_MIN_ 1
+/** State for an exit connection: waiting for response from DNS farm. */
+#define EXIT_CONN_STATE_RESOLVING 1
+/** State for an exit connection: waiting for connect() to finish. */
+#define EXIT_CONN_STATE_CONNECTING 2
+/** State for an exit connection: open and ready to transmit data. */
+#define EXIT_CONN_STATE_OPEN 3
+/** State for an exit connection: waiting to be removed. */
+#define EXIT_CONN_STATE_RESOLVEFAILED 4
+#define EXIT_CONN_STATE_MAX_ 4
+
+/* The AP state values must be disjoint from the EXIT state values. */
+#define AP_CONN_STATE_MIN_ 5
+/** State for a SOCKS connection: waiting for SOCKS request. */
+#define AP_CONN_STATE_SOCKS_WAIT 5
+/** State for a SOCKS connection: got a y.onion URL; waiting to receive
+ * rendezvous descriptor. */
+#define AP_CONN_STATE_RENDDESC_WAIT 6
+/** The controller will attach this connection to a circuit; it isn't our
+ * job to do so. */
+#define AP_CONN_STATE_CONTROLLER_WAIT 7
+/** State for a SOCKS connection: waiting for a completed circuit. */
+#define AP_CONN_STATE_CIRCUIT_WAIT 8
+/** State for a SOCKS connection: sent BEGIN, waiting for CONNECTED. */
+#define AP_CONN_STATE_CONNECT_WAIT 9
+/** State for a SOCKS connection: sent RESOLVE, waiting for RESOLVED. */
+#define AP_CONN_STATE_RESOLVE_WAIT 10
+/** State for a SOCKS connection: ready to send and receive. */
+#define AP_CONN_STATE_OPEN 11
+/** State for a transparent natd connection: waiting for original
+ * destination. */
+#define AP_CONN_STATE_NATD_WAIT 12
+/** State for an HTTP tunnel: waiting for an HTTP CONNECT command. */
+#define AP_CONN_STATE_HTTP_CONNECT_WAIT 13
+#define AP_CONN_STATE_MAX_ 13
+
+#define EXIT_PURPOSE_MIN_ 1
+/** This exit stream wants to do an ordinary connect. */
+#define EXIT_PURPOSE_CONNECT 1
+/** This exit stream wants to do a resolve (either normal or reverse). */
+#define EXIT_PURPOSE_RESOLVE 2
+#define EXIT_PURPOSE_MAX_ 2
+
+/** True iff the AP_CONN_STATE_* value <b>s</b> means that the corresponding
+ * edge connection is not attached to any circuit. */
+#define AP_CONN_STATE_IS_UNATTACHED(s) \
+ ((s) <= AP_CONN_STATE_CIRCUIT_WAIT || (s) == AP_CONN_STATE_NATD_WAIT)
+
+#define connection_mark_unattached_ap(conn, endreason) \
+ connection_mark_unattached_ap_((conn), (endreason), __LINE__, SHORT_FILE__)
+
+MOCK_DECL(void,connection_mark_unattached_ap_,
+ (entry_connection_t *conn, int endreason,
+ int line, const char *file));
+int connection_edge_reached_eof(edge_connection_t *conn);
+int connection_edge_process_inbuf(edge_connection_t *conn,
+ int package_partial);
+int connection_edge_destroy(circid_t circ_id, edge_connection_t *conn);
+int connection_edge_end(edge_connection_t *conn, uint8_t reason);
+int connection_edge_end_errno(edge_connection_t *conn);
+int connection_edge_flushed_some(edge_connection_t *conn);
+int connection_edge_finished_flushing(edge_connection_t *conn);
+int connection_edge_finished_connecting(edge_connection_t *conn);
+
+void connection_ap_about_to_close(entry_connection_t *edge_conn);
+void connection_exit_about_to_close(edge_connection_t *edge_conn);
+
+MOCK_DECL(int,
+ connection_ap_handshake_send_begin,(entry_connection_t *ap_conn));
+int connection_ap_handshake_send_resolve(entry_connection_t *ap_conn);
+
+entry_connection_t *connection_ap_make_link(connection_t *partner,
+ char *address, uint16_t port,
+ const char *digest,
+ int session_group,
+ int isolation_flags,
+ int use_begindir, int want_onehop);
+void connection_ap_handshake_socks_reply(entry_connection_t *conn, char *reply,
+ size_t replylen,
+ int endreason);
+MOCK_DECL(void,connection_ap_handshake_socks_resolved,
+ (entry_connection_t *conn,
+ int answer_type,
+ size_t answer_len,
+ const uint8_t *answer,
+ int ttl,
+ time_t expires));
+void connection_ap_handshake_socks_resolved_addr(entry_connection_t *conn,
+ const tor_addr_t *answer,
+ int ttl,
+ time_t expires);
+
+int connection_exit_begin_conn(cell_t *cell, circuit_t *circ);
+int connection_exit_begin_resolve(cell_t *cell, or_circuit_t *circ);
+void connection_exit_connect(edge_connection_t *conn);
+int connection_edge_is_rendezvous_stream(const edge_connection_t *conn);
+int connection_ap_can_use_exit(const entry_connection_t *conn,
+ const node_t *exit);
+void connection_ap_expire_beginning(void);
+void connection_ap_rescan_and_attach_pending(void);
+void connection_ap_attach_pending(int retry);
+void connection_ap_mark_as_pending_circuit_(entry_connection_t *entry_conn,
+ const char *file, int line);
+#define connection_ap_mark_as_pending_circuit(c) \
+ connection_ap_mark_as_pending_circuit_((c), __FILE__, __LINE__)
+void connection_ap_mark_as_non_pending_circuit(entry_connection_t *entry_conn);
+#define CONNECTION_AP_EXPECT_NONPENDING(c) do { \
+ if (ENTRY_TO_CONN(c)->state == AP_CONN_STATE_CIRCUIT_WAIT) { \
+ log_warn(LD_BUG, "At %s:%d: %p was unexpectedly in circuit_wait.", \
+ __FILE__, __LINE__, (c)); \
+ connection_ap_mark_as_non_pending_circuit(c); \
+ } \
+ } while (0)
+void connection_ap_fail_onehop(const char *failed_digest,
+ cpath_build_state_t *build_state);
+void circuit_discard_optional_exit_enclaves(extend_info_t *info);
+int connection_ap_detach_retriable(entry_connection_t *conn,
+ origin_circuit_t *circ,
+ int reason);
+int connection_ap_process_transparent(entry_connection_t *conn);
+
+int address_is_invalid_destination(const char *address, int client);
+
+MOCK_DECL(int, connection_ap_rewrite_and_attach_if_allowed,
+ (entry_connection_t *conn,
+ origin_circuit_t *circ,
+ crypt_path_t *cpath));
+int connection_ap_handshake_rewrite_and_attach(entry_connection_t *conn,
+ origin_circuit_t *circ,
+ crypt_path_t *cpath);
+
+/** Possible return values for parse_extended_hostname. */
+typedef enum hostname_type_t {
+ NORMAL_HOSTNAME, ONION_V2_HOSTNAME, ONION_V3_HOSTNAME,
+ EXIT_HOSTNAME, BAD_HOSTNAME
+} hostname_type_t;
+hostname_type_t parse_extended_hostname(char *address);
+
+#if defined(HAVE_NET_IF_H) && defined(HAVE_NET_PFVAR_H)
+int get_pf_socket(void);
+#endif
+
+int connection_edge_compatible_with_circuit(const entry_connection_t *conn,
+ const origin_circuit_t *circ);
+int connection_edge_update_circuit_isolation(const entry_connection_t *conn,
+ origin_circuit_t *circ,
+ int dry_run);
+void circuit_clear_isolation(origin_circuit_t *circ);
+streamid_t get_unique_stream_id_by_circ(origin_circuit_t *circ);
+
+void connection_edge_free_all(void);
+
+void connection_ap_warn_and_unmark_if_pending_circ(
+ entry_connection_t *entry_conn,
+ const char *where);
+
+int connection_half_edge_is_valid_data(const smartlist_t *half_conns,
+ streamid_t stream_id);
+int connection_half_edge_is_valid_sendme(const smartlist_t *half_conns,
+ streamid_t stream_id);
+int connection_half_edge_is_valid_connected(const smartlist_t *half_conns,
+ streamid_t stream_id);
+int connection_half_edge_is_valid_end(smartlist_t *half_conns,
+ streamid_t stream_id);
+int connection_half_edge_is_valid_resolved(smartlist_t *half_conns,
+ streamid_t stream_id);
+
++size_t half_streams_get_total_allocation(void);
++void half_edge_free_(half_edge_t *he);
++#define half_edge_free(he) \
++ FREE_AND_NULL(half_edge_t, half_edge_free_, (he))
++
+/** @name Begin-cell flags
+ *
+ * These flags are used in RELAY_BEGIN cells to change the default behavior
+ * of the cell.
+ *
+ * @{
+ **/
+/** When this flag is set, the client is willing to get connected to IPv6
+ * addresses */
+#define BEGIN_FLAG_IPV6_OK (1u<<0)
+/** When this flag is set, the client DOES NOT support connecting to IPv4
+ * addresses. (The sense of this flag is inverted from IPV6_OK, so that the
+ * old default behavior of Tor is equivalent to having all flags set to 0.)
+ **/
+#define BEGIN_FLAG_IPV4_NOT_OK (1u<<1)
+/** When this flag is set, if we find both an IPv4 and an IPv6 address,
+ * we use the IPv6 address. Otherwise we use the IPv4 address. */
+#define BEGIN_FLAG_IPV6_PREFERRED (1u<<2)
+/**@}*/
+
+#ifdef CONNECTION_EDGE_PRIVATE
+
+/** A parsed BEGIN or BEGIN_DIR cell */
+typedef struct begin_cell_t {
+ /** The address the client has asked us to connect to, or NULL if this is
+ * a BEGIN_DIR cell*/
+ char *address;
+ /** The flags specified in the BEGIN cell's body. One or more of
+ * BEGIN_FLAG_*. */
+ uint32_t flags;
+ /** The client's requested port. */
+ uint16_t port;
+ /** The client's requested Stream ID */
+ uint16_t stream_id;
+ /** True iff this is a BEGIN_DIR cell. */
+ unsigned is_begindir : 1;
+} begin_cell_t;
+
+STATIC int begin_cell_parse(const cell_t *cell, begin_cell_t *bcell,
+ uint8_t *end_reason_out);
+STATIC int connected_cell_format_payload(uint8_t *payload_out,
+ const tor_addr_t *addr,
+ uint32_t ttl);
+
+typedef struct {
+ /** Original address, after we lowercased it but before we started
+ * mapping it.
+ */
+ char orig_address[MAX_SOCKS_ADDR_LEN];
+ /** True iff the address has been automatically remapped to a local
+ * address in VirtualAddrNetwork. (Only set true when we do a resolve
+ * and get a virtual address; not when we connect to the address.) */
+ int automap;
+ /** If this connection has a .exit address, who put it there? */
+ addressmap_entry_source_t exit_source;
+ /** If we've rewritten the address, when does this map expire? */
+ time_t map_expires;
+ /** If we should close the connection, this is the end_reason to pass
+ * to connection_mark_unattached_ap */
+ int end_reason;
+ /** True iff we should close the connection, either because of error or
+ * because of successful early RESOLVED reply. */
+ int should_close;
+} rewrite_result_t;
+
+STATIC void connection_ap_handshake_rewrite(entry_connection_t *conn,
+ rewrite_result_t *out);
+
+STATIC int connection_ap_process_http_connect(entry_connection_t *conn);
+#endif /* defined(CONNECTION_EDGE_PRIVATE) */
+
+#endif /* !defined(TOR_CONNECTION_EDGE_H) */
diff --cc src/core/or/relay.c
index 407873e2a,000000000..fe6062a6c
mode 100644,000000..100644
--- a/src/core/or/relay.c
+++ b/src/core/or/relay.c
@@@ -1,3168 -1,0 +1,3169 @@@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file relay.c
+ * \brief Handle relay cell encryption/decryption, plus packaging and
+ * receiving from circuits, plus queuing on circuits.
+ *
+ * This is a core modules that makes Tor work. It's responsible for
+ * dealing with RELAY cells (the ones that travel more than one hop along a
+ * circuit), by:
+ * <ul>
+ * <li>constructing relays cells,
+ * <li>encrypting relay cells,
+ * <li>decrypting relay cells,
+ * <li>demultiplexing relay cells as they arrive on a connection,
+ * <li>queueing relay cells for retransmission,
+ * <li>or handling relay cells that are for us to receive (as an exit or a
+ * client).
+ * </ul>
+ *
+ * RELAY cells are generated throughout the code at the client or relay side,
+ * using relay_send_command_from_edge() or one of the functions like
+ * connection_edge_send_command() that calls it. Of particular interest is
+ * connection_edge_package_raw_inbuf(), which takes information that has
+ * arrived on an edge connection socket, and packages it as a RELAY_DATA cell
+ * -- this is how information is actually sent across the Tor network. The
+ * cryptography for these functions is handled deep in
+ * circuit_package_relay_cell(), which either adds a single layer of
+ * encryption (if we're an exit), or multiple layers (if we're the origin of
+ * the circuit). After construction and encryption, the RELAY cells are
+ * passed to append_cell_to_circuit_queue(), which queues them for
+ * transmission and tells the circuitmux (see circuitmux.c) that the circuit
+ * is waiting to send something.
+ *
+ * Incoming RELAY cells arrive at circuit_receive_relay_cell(), called from
+ * command.c. There they are decrypted and, if they are for us, are passed to
+ * connection_edge_process_relay_cell(). If they're not for us, they're
+ * re-queued for retransmission again with append_cell_to_circuit_queue().
+ *
+ * The connection_edge_process_relay_cell() function handles all the different
+ * types of relay cells, launching requests or transmitting data as needed.
+ **/
+
+#define RELAY_PRIVATE
+#include "core/or/or.h"
+#include "feature/client/addressmap.h"
+#include "lib/err/backtrace.h"
+#include "lib/container/buffers.h"
+#include "core/or/channel.h"
+#include "feature/client/circpathbias.h"
+#include "core/or/circuitbuild.h"
+#include "core/or/circuitlist.h"
+#include "core/or/circuituse.h"
+#include "lib/compress/compress.h"
+#include "app/config/config.h"
+#include "core/mainloop/connection.h"
+#include "core/or/connection_edge.h"
+#include "core/or/connection_or.h"
+#include "feature/control/control.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "lib/crypt_ops/crypto_util.h"
+#include "feature/dircache/directory.h"
+#include "feature/relay/dns.h"
+#include "feature/stats/geoip.h"
+#include "feature/hs/hs_cache.h"
+#include "core/mainloop/main.h"
+#include "feature/nodelist/networkstatus.h"
+#include "feature/nodelist/nodelist.h"
+#include "core/crypto/onion.h"
+#include "core/or/policies.h"
+#include "core/or/reasons.h"
+#include "core/or/relay.h"
+#include "core/crypto/relay_crypto.h"
+#include "feature/rend/rendcache.h"
+#include "feature/rend/rendcommon.h"
+#include "feature/relay/router.h"
+#include "feature/nodelist/routerlist.h"
+#include "feature/nodelist/routerparse.h"
+#include "core/or/scheduler.h"
+#include "feature/stats/rephist.h"
+
+#include "core/or/cell_st.h"
+#include "core/or/cell_queue_st.h"
+#include "core/or/cpath_build_state_st.h"
+#include "feature/dircommon/dir_connection_st.h"
+#include "core/or/destroy_cell_queue_st.h"
+#include "core/or/entry_connection_st.h"
+#include "core/or/extend_info_st.h"
+#include "core/or/or_circuit_st.h"
+#include "core/or/origin_circuit_st.h"
+#include "feature/nodelist/routerinfo_st.h"
+#include "core/or/socks_request_st.h"
+
+#include "lib/intmath/weakrng.h"
+
+static edge_connection_t *relay_lookup_conn(circuit_t *circ, cell_t *cell,
+ cell_direction_t cell_direction,
+ crypt_path_t *layer_hint);
+
+static void circuit_consider_sending_sendme(circuit_t *circ,
+ crypt_path_t *layer_hint);
+static void circuit_resume_edge_reading(circuit_t *circ,
+ crypt_path_t *layer_hint);
+static int circuit_resume_edge_reading_helper(edge_connection_t *conn,
+ circuit_t *circ,
+ crypt_path_t *layer_hint);
+static int circuit_consider_stop_edge_reading(circuit_t *circ,
+ crypt_path_t *layer_hint);
+static int circuit_queue_streams_are_blocked(circuit_t *circ);
+static void adjust_exit_policy_from_exitpolicy_failure(origin_circuit_t *circ,
+ entry_connection_t *conn,
+ node_t *node,
+ const tor_addr_t *addr);
+
+/** Stop reading on edge connections when we have this many cells
+ * waiting on the appropriate queue. */
+#define CELL_QUEUE_HIGHWATER_SIZE 256
+/** Start reading from edge connections again when we get down to this many
+ * cells. */
+#define CELL_QUEUE_LOWWATER_SIZE 64
+
+/** Stats: how many relay cells have originated at this hop, or have
+ * been relayed onward (not recognized at this hop)?
+ */
+uint64_t stats_n_relay_cells_relayed = 0;
+/** Stats: how many relay cells have been delivered to streams at this
+ * hop?
+ */
+uint64_t stats_n_relay_cells_delivered = 0;
+/** Stats: how many circuits have we closed due to the cell queue limit being
+ * reached (see append_cell_to_circuit_queue()) */
+uint64_t stats_n_circ_max_cell_reached = 0;
+
+/** Used to tell which stream to read from first on a circuit. */
+static tor_weak_rng_t stream_choice_rng = TOR_WEAK_RNG_INIT;
+
+/**
+ * Update channel usage state based on the type of relay cell and
+ * circuit properties.
+ *
+ * This is needed to determine if a client channel is being
+ * used for application traffic, and if a relay channel is being
+ * used for multihop circuits and application traffic. The decision
+ * to pad in channelpadding.c depends upon this info (as well as
+ * consensus parameters) to decide what channels to pad.
+ */
+static void
+circuit_update_channel_usage(circuit_t *circ, cell_t *cell)
+{
+ if (CIRCUIT_IS_ORIGIN(circ)) {
+ /*
+ * The client state was first set much earlier in
+ * circuit_send_next_onion_skin(), so we can start padding as early as
+ * possible.
+ *
+ * However, if padding turns out to be expensive, we may want to not do
+ * it until actual application traffic starts flowing (which is controlled
+ * via consensus param nf_pad_before_usage).
+ *
+ * So: If we're an origin circuit and we've created a full length circuit,
+ * then any CELL_RELAY cell means application data. Increase the usage
+ * state of the channel to indicate this.
+ *
+ * We want to wait for CELL_RELAY specifically here, so we know that
+ * the channel was definitely being used for data and not for extends.
+ * By default, we pad as soon as a channel has been used for *any*
+ * circuits, so this state is irrelevant to the padding decision in
+ * the default case. However, if padding turns out to be expensive,
+ * we would like the ability to avoid padding until we're absolutely
+ * sure that a channel is used for enough application data to be worth
+ * padding.
+ *
+ * (So it does not matter that CELL_RELAY_EARLY can actually contain
+ * application data. This is only a load reducing option and that edge
+ * case does not matter if we're desperately trying to reduce overhead
+ * anyway. See also consensus parameter nf_pad_before_usage).
+ */
+ if (BUG(!circ->n_chan))
+ return;
+
+ if (circ->n_chan->channel_usage == CHANNEL_USED_FOR_FULL_CIRCS &&
+ cell->command == CELL_RELAY) {
+ circ->n_chan->channel_usage = CHANNEL_USED_FOR_USER_TRAFFIC;
+ }
+ } else {
+ /* If we're a relay circuit, the question is more complicated. Basically:
+ * we only want to pad connections that carry multihop (anonymous)
+ * circuits.
+ *
+ * We assume we're more than one hop if either the previous hop
+ * is not a client, or if the previous hop is a client and there's
+ * a next hop. Then, circuit traffic starts at RELAY_EARLY, and
+ * user application traffic starts when we see RELAY cells.
+ */
+ or_circuit_t *or_circ = TO_OR_CIRCUIT(circ);
+
+ if (BUG(!or_circ->p_chan))
+ return;
+
+ if (!channel_is_client(or_circ->p_chan) ||
+ (channel_is_client(or_circ->p_chan) && circ->n_chan)) {
+ if (cell->command == CELL_RELAY_EARLY) {
+ if (or_circ->p_chan->channel_usage < CHANNEL_USED_FOR_FULL_CIRCS) {
+ or_circ->p_chan->channel_usage = CHANNEL_USED_FOR_FULL_CIRCS;
+ }
+ } else if (cell->command == CELL_RELAY) {
+ or_circ->p_chan->channel_usage = CHANNEL_USED_FOR_USER_TRAFFIC;
+ }
+ }
+ }
+}
+
+/** Receive a relay cell:
+ * - Crypt it (encrypt if headed toward the origin or if we <b>are</b> the
+ * origin; decrypt if we're headed toward the exit).
+ * - Check if recognized (if exitward).
+ * - If recognized and the digest checks out, then find if there's a stream
+ * that the cell is intended for, and deliver it to the right
+ * connection_edge.
+ * - If not recognized, then we need to relay it: append it to the appropriate
+ * cell_queue on <b>circ</b>.
+ *
+ * Return -<b>reason</b> on failure.
+ */
+int
+circuit_receive_relay_cell(cell_t *cell, circuit_t *circ,
+ cell_direction_t cell_direction)
+{
+ channel_t *chan = NULL;
+ crypt_path_t *layer_hint=NULL;
+ char recognized=0;
+ int reason;
+
+ tor_assert(cell);
+ tor_assert(circ);
+ tor_assert(cell_direction == CELL_DIRECTION_OUT ||
+ cell_direction == CELL_DIRECTION_IN);
+ if (circ->marked_for_close)
+ return 0;
+
+ if (relay_decrypt_cell(circ, cell, cell_direction, &layer_hint, &recognized)
+ < 0) {
+ log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
+ "relay crypt failed. Dropping connection.");
+ return -END_CIRC_REASON_INTERNAL;
+ }
+
+ circuit_update_channel_usage(circ, cell);
+
+ if (recognized) {
+ edge_connection_t *conn = NULL;
+
+ if (circ->purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) {
+ if (pathbias_check_probe_response(circ, cell) == -1) {
+ pathbias_count_valid_cells(circ, cell);
+ }
+
+ /* We need to drop this cell no matter what to avoid code that expects
+ * a certain purpose (such as the hidserv code). */
+ return 0;
+ }
+
+ conn = relay_lookup_conn(circ, cell, cell_direction, layer_hint);
+ if (cell_direction == CELL_DIRECTION_OUT) {
+ ++stats_n_relay_cells_delivered;
+ log_debug(LD_OR,"Sending away from origin.");
+ if ((reason=connection_edge_process_relay_cell(cell, circ, conn, NULL))
+ < 0) {
+ log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
+ "connection_edge_process_relay_cell (away from origin) "
+ "failed.");
+ return reason;
+ }
+ }
+ if (cell_direction == CELL_DIRECTION_IN) {
+ ++stats_n_relay_cells_delivered;
+ log_debug(LD_OR,"Sending to origin.");
+ if ((reason = connection_edge_process_relay_cell(cell, circ, conn,
+ layer_hint)) < 0) {
+ /* If a client is trying to connect to unknown hidden service port,
+ * END_CIRC_AT_ORIGIN is sent back so we can then close the circuit.
+ * Do not log warn as this is an expected behavior for a service. */
+ if (reason != END_CIRC_AT_ORIGIN) {
+ log_warn(LD_OR,
+ "connection_edge_process_relay_cell (at origin) failed.");
+ }
+ return reason;
+ }
+ }
+ return 0;
+ }
+
+ /* not recognized. pass it on. */
+ if (cell_direction == CELL_DIRECTION_OUT) {
+ cell->circ_id = circ->n_circ_id; /* switch it */
+ chan = circ->n_chan;
+ } else if (! CIRCUIT_IS_ORIGIN(circ)) {
+ cell->circ_id = TO_OR_CIRCUIT(circ)->p_circ_id; /* switch it */
+ chan = TO_OR_CIRCUIT(circ)->p_chan;
+ } else {
+ log_fn(LOG_PROTOCOL_WARN, LD_OR,
+ "Dropping unrecognized inbound cell on origin circuit.");
+ /* If we see unrecognized cells on path bias testing circs,
+ * it's bad mojo. Those circuits need to die.
+ * XXX: Shouldn't they always die? */
+ if (circ->purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) {
+ TO_ORIGIN_CIRCUIT(circ)->path_state = PATH_STATE_USE_FAILED;
+ return -END_CIRC_REASON_TORPROTOCOL;
+ } else {
+ return 0;
+ }
+ }
+
+ if (!chan) {
+ // XXXX Can this splice stuff be done more cleanly?
+ if (! CIRCUIT_IS_ORIGIN(circ) &&
+ TO_OR_CIRCUIT(circ)->rend_splice &&
+ cell_direction == CELL_DIRECTION_OUT) {
+ or_circuit_t *splice_ = TO_OR_CIRCUIT(circ)->rend_splice;
+ tor_assert(circ->purpose == CIRCUIT_PURPOSE_REND_ESTABLISHED);
+ tor_assert(splice_->base_.purpose == CIRCUIT_PURPOSE_REND_ESTABLISHED);
+ cell->circ_id = splice_->p_circ_id;
+ cell->command = CELL_RELAY; /* can't be relay_early anyway */
+ if ((reason = circuit_receive_relay_cell(cell, TO_CIRCUIT(splice_),
+ CELL_DIRECTION_IN)) < 0) {
+ log_warn(LD_REND, "Error relaying cell across rendezvous; closing "
+ "circuits");
+ /* XXXX Do this here, or just return -1? */
+ circuit_mark_for_close(circ, -reason);
+ return reason;
+ }
+ return 0;
+ }
+ log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
+ "Didn't recognize cell, but circ stops here! Closing circ.");
+ return -END_CIRC_REASON_TORPROTOCOL;
+ }
+
+ log_debug(LD_OR,"Passing on unrecognized cell.");
+
+ ++stats_n_relay_cells_relayed; /* XXXX no longer quite accurate {cells}
+ * we might kill the circ before we relay
+ * the cells. */
+
+ append_cell_to_circuit_queue(circ, chan, cell, cell_direction, 0);
+ return 0;
+}
+
+/** Package a relay cell from an edge:
+ * - Encrypt it to the right layer
+ * - Append it to the appropriate cell_queue on <b>circ</b>.
+ */
+static int
+circuit_package_relay_cell(cell_t *cell, circuit_t *circ,
+ cell_direction_t cell_direction,
+ crypt_path_t *layer_hint, streamid_t on_stream,
+ const char *filename, int lineno)
+{
+ channel_t *chan; /* where to send the cell */
+
+ if (circ->marked_for_close) {
+ /* Circuit is marked; send nothing. */
+ return 0;
+ }
+
+ if (cell_direction == CELL_DIRECTION_OUT) {
+ chan = circ->n_chan;
+ if (!chan) {
+ log_warn(LD_BUG,"outgoing relay cell sent from %s:%d has n_chan==NULL."
+ " Dropping. Circuit is in state %s (%d), and is "
+ "%smarked for close. (%s:%d, %d)", filename, lineno,
+ circuit_state_to_string(circ->state), circ->state,
+ circ->marked_for_close ? "" : "not ",
+ circ->marked_for_close_file?circ->marked_for_close_file:"",
+ circ->marked_for_close, circ->marked_for_close_reason);
+ if (CIRCUIT_IS_ORIGIN(circ)) {
+ circuit_log_path(LOG_WARN, LD_BUG, TO_ORIGIN_CIRCUIT(circ));
+ }
+ log_backtrace(LOG_WARN,LD_BUG,"");
+ return 0; /* just drop it */
+ }
+ if (!CIRCUIT_IS_ORIGIN(circ)) {
+ log_warn(LD_BUG,"outgoing relay cell sent from %s:%d on non-origin "
+ "circ. Dropping.", filename, lineno);
+ log_backtrace(LOG_WARN,LD_BUG,"");
+ return 0; /* just drop it */
+ }
+
+ relay_encrypt_cell_outbound(cell, TO_ORIGIN_CIRCUIT(circ), layer_hint);
+
+ /* Update circ written totals for control port */
+ origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ);
+ ocirc->n_written_circ_bw = tor_add_u32_nowrap(ocirc->n_written_circ_bw,
+ CELL_PAYLOAD_SIZE);
+
+ } else { /* incoming cell */
+ if (CIRCUIT_IS_ORIGIN(circ)) {
+ /* We should never package an _incoming_ cell from the circuit
+ * origin; that means we messed up somewhere. */
+ log_warn(LD_BUG,"incoming relay cell at origin circuit. Dropping.");
+ assert_circuit_ok(circ);
+ return 0; /* just drop it */
+ }
+ or_circuit_t *or_circ = TO_OR_CIRCUIT(circ);
+ relay_encrypt_cell_inbound(cell, or_circ);
+ chan = or_circ->p_chan;
+ }
+ ++stats_n_relay_cells_relayed;
+
+ append_cell_to_circuit_queue(circ, chan, cell, cell_direction, on_stream);
+ return 0;
+}
+
+/** If cell's stream_id matches the stream_id of any conn that's
+ * attached to circ, return that conn, else return NULL.
+ */
+static edge_connection_t *
+relay_lookup_conn(circuit_t *circ, cell_t *cell,
+ cell_direction_t cell_direction, crypt_path_t *layer_hint)
+{
+ edge_connection_t *tmpconn;
+ relay_header_t rh;
+
+ relay_header_unpack(&rh, cell->payload);
+
+ if (!rh.stream_id)
+ return NULL;
+
+ /* IN or OUT cells could have come from either direction, now
+ * that we allow rendezvous *to* an OP.
+ */
+
+ if (CIRCUIT_IS_ORIGIN(circ)) {
+ for (tmpconn = TO_ORIGIN_CIRCUIT(circ)->p_streams; tmpconn;
+ tmpconn=tmpconn->next_stream) {
+ if (rh.stream_id == tmpconn->stream_id &&
+ !tmpconn->base_.marked_for_close &&
+ tmpconn->cpath_layer == layer_hint) {
+ log_debug(LD_APP,"found conn for stream %d.", rh.stream_id);
+ return tmpconn;
+ }
+ }
+ } else {
+ for (tmpconn = TO_OR_CIRCUIT(circ)->n_streams; tmpconn;
+ tmpconn=tmpconn->next_stream) {
+ if (rh.stream_id == tmpconn->stream_id &&
+ !tmpconn->base_.marked_for_close) {
+ log_debug(LD_EXIT,"found conn for stream %d.", rh.stream_id);
+ if (cell_direction == CELL_DIRECTION_OUT ||
+ connection_edge_is_rendezvous_stream(tmpconn))
+ return tmpconn;
+ }
+ }
+ for (tmpconn = TO_OR_CIRCUIT(circ)->resolving_streams; tmpconn;
+ tmpconn=tmpconn->next_stream) {
+ if (rh.stream_id == tmpconn->stream_id &&
+ !tmpconn->base_.marked_for_close) {
+ log_debug(LD_EXIT,"found conn for stream %d.", rh.stream_id);
+ return tmpconn;
+ }
+ }
+ }
+ return NULL; /* probably a begin relay cell */
+}
+
+/** Pack the relay_header_t host-order structure <b>src</b> into
+ * network-order in the buffer <b>dest</b>. See tor-spec.txt for details
+ * about the wire format.
+ */
+void
+relay_header_pack(uint8_t *dest, const relay_header_t *src)
+{
+ set_uint8(dest, src->command);
+ set_uint16(dest+1, htons(src->recognized));
+ set_uint16(dest+3, htons(src->stream_id));
+ memcpy(dest+5, src->integrity, 4);
+ set_uint16(dest+9, htons(src->length));
+}
+
+/** Unpack the network-order buffer <b>src</b> into a host-order
+ * relay_header_t structure <b>dest</b>.
+ */
+void
+relay_header_unpack(relay_header_t *dest, const uint8_t *src)
+{
+ dest->command = get_uint8(src);
+ dest->recognized = ntohs(get_uint16(src+1));
+ dest->stream_id = ntohs(get_uint16(src+3));
+ memcpy(dest->integrity, src+5, 4);
+ dest->length = ntohs(get_uint16(src+9));
+}
+
+/** Convert the relay <b>command</b> into a human-readable string. */
+static const char *
+relay_command_to_string(uint8_t command)
+{
+ static char buf[64];
+ switch (command) {
+ case RELAY_COMMAND_BEGIN: return "BEGIN";
+ case RELAY_COMMAND_DATA: return "DATA";
+ case RELAY_COMMAND_END: return "END";
+ case RELAY_COMMAND_CONNECTED: return "CONNECTED";
+ case RELAY_COMMAND_SENDME: return "SENDME";
+ case RELAY_COMMAND_EXTEND: return "EXTEND";
+ case RELAY_COMMAND_EXTENDED: return "EXTENDED";
+ case RELAY_COMMAND_TRUNCATE: return "TRUNCATE";
+ case RELAY_COMMAND_TRUNCATED: return "TRUNCATED";
+ case RELAY_COMMAND_DROP: return "DROP";
+ case RELAY_COMMAND_RESOLVE: return "RESOLVE";
+ case RELAY_COMMAND_RESOLVED: return "RESOLVED";
+ case RELAY_COMMAND_BEGIN_DIR: return "BEGIN_DIR";
+ case RELAY_COMMAND_ESTABLISH_INTRO: return "ESTABLISH_INTRO";
+ case RELAY_COMMAND_ESTABLISH_RENDEZVOUS: return "ESTABLISH_RENDEZVOUS";
+ case RELAY_COMMAND_INTRODUCE1: return "INTRODUCE1";
+ case RELAY_COMMAND_INTRODUCE2: return "INTRODUCE2";
+ case RELAY_COMMAND_RENDEZVOUS1: return "RENDEZVOUS1";
+ case RELAY_COMMAND_RENDEZVOUS2: return "RENDEZVOUS2";
+ case RELAY_COMMAND_INTRO_ESTABLISHED: return "INTRO_ESTABLISHED";
+ case RELAY_COMMAND_RENDEZVOUS_ESTABLISHED:
+ return "RENDEZVOUS_ESTABLISHED";
+ case RELAY_COMMAND_INTRODUCE_ACK: return "INTRODUCE_ACK";
+ case RELAY_COMMAND_EXTEND2: return "EXTEND2";
+ case RELAY_COMMAND_EXTENDED2: return "EXTENDED2";
+ default:
+ tor_snprintf(buf, sizeof(buf), "Unrecognized relay command %u",
+ (unsigned)command);
+ return buf;
+ }
+}
+
+/** Make a relay cell out of <b>relay_command</b> and <b>payload</b>, and send
+ * it onto the open circuit <b>circ</b>. <b>stream_id</b> is the ID on
+ * <b>circ</b> for the stream that's sending the relay cell, or 0 if it's a
+ * control cell. <b>cpath_layer</b> is NULL for OR->OP cells, or the
+ * destination hop for OP->OR cells.
+ *
+ * If you can't send the cell, mark the circuit for close and return -1. Else
+ * return 0.
+ */
+MOCK_IMPL(int,
+relay_send_command_from_edge_,(streamid_t stream_id, circuit_t *circ,
+ uint8_t relay_command, const char *payload,
+ size_t payload_len, crypt_path_t *cpath_layer,
+ const char *filename, int lineno))
+{
+ cell_t cell;
+ relay_header_t rh;
+ cell_direction_t cell_direction;
+ /* XXXX NM Split this function into a separate versions per circuit type? */
+
+ tor_assert(circ);
+ tor_assert(payload_len <= RELAY_PAYLOAD_SIZE);
+
+ memset(&cell, 0, sizeof(cell_t));
+ cell.command = CELL_RELAY;
+ if (CIRCUIT_IS_ORIGIN(circ)) {
+ tor_assert(cpath_layer);
+ cell.circ_id = circ->n_circ_id;
+ cell_direction = CELL_DIRECTION_OUT;
+ } else {
+ tor_assert(! cpath_layer);
+ cell.circ_id = TO_OR_CIRCUIT(circ)->p_circ_id;
+ cell_direction = CELL_DIRECTION_IN;
+ }
+
+ memset(&rh, 0, sizeof(rh));
+ rh.command = relay_command;
+ rh.stream_id = stream_id;
+ rh.length = payload_len;
+ relay_header_pack(cell.payload, &rh);
+ if (payload_len)
+ memcpy(cell.payload+RELAY_HEADER_SIZE, payload, payload_len);
+
+ log_debug(LD_OR,"delivering %d cell %s.", relay_command,
+ cell_direction == CELL_DIRECTION_OUT ? "forward" : "backward");
+
+ if (relay_command == RELAY_COMMAND_DROP)
+ rep_hist_padding_count_write(PADDING_TYPE_DROP);
+
+ /* If we are sending an END cell and this circuit is used for a tunneled
+ * directory request, advance its state. */
+ if (relay_command == RELAY_COMMAND_END && circ->dirreq_id)
+ geoip_change_dirreq_state(circ->dirreq_id, DIRREQ_TUNNELED,
+ DIRREQ_END_CELL_SENT);
+
+ if (cell_direction == CELL_DIRECTION_OUT && circ->n_chan) {
+ /* if we're using relaybandwidthrate, this conn wants priority */
+ channel_timestamp_client(circ->n_chan);
+ }
+
+ if (cell_direction == CELL_DIRECTION_OUT) {
+ origin_circuit_t *origin_circ = TO_ORIGIN_CIRCUIT(circ);
+ if (origin_circ->remaining_relay_early_cells > 0 &&
+ (relay_command == RELAY_COMMAND_EXTEND ||
+ relay_command == RELAY_COMMAND_EXTEND2 ||
+ cpath_layer != origin_circ->cpath)) {
+ /* If we've got any relay_early cells left and (we're sending
+ * an extend cell or we're not talking to the first hop), use
+ * one of them. Don't worry about the conn protocol version:
+ * append_cell_to_circuit_queue will fix it up. */
+ cell.command = CELL_RELAY_EARLY;
+ --origin_circ->remaining_relay_early_cells;
+ log_debug(LD_OR, "Sending a RELAY_EARLY cell; %d remaining.",
+ (int)origin_circ->remaining_relay_early_cells);
+ /* Memorize the command that is sent as RELAY_EARLY cell; helps debug
+ * task 878. */
+ origin_circ->relay_early_commands[
+ origin_circ->relay_early_cells_sent++] = relay_command;
+ } else if (relay_command == RELAY_COMMAND_EXTEND ||
+ relay_command == RELAY_COMMAND_EXTEND2) {
+ /* If no RELAY_EARLY cells can be sent over this circuit, log which
+ * commands have been sent as RELAY_EARLY cells before; helps debug
+ * task 878. */
+ smartlist_t *commands_list = smartlist_new();
+ int i = 0;
+ char *commands = NULL;
+ for (; i < origin_circ->relay_early_cells_sent; i++)
+ smartlist_add(commands_list, (char *)
+ relay_command_to_string(origin_circ->relay_early_commands[i]));
+ commands = smartlist_join_strings(commands_list, ",", 0, NULL);
+ log_warn(LD_BUG, "Uh-oh. We're sending a RELAY_COMMAND_EXTEND cell, "
+ "but we have run out of RELAY_EARLY cells on that circuit. "
+ "Commands sent before: %s", commands);
+ tor_free(commands);
+ smartlist_free(commands_list);
+ }
+
+ /* Let's assume we're well-behaved: Anything that we decide to send is
+ * valid, delivered data. */
+ circuit_sent_valid_data(origin_circ, rh.length);
+ }
+
+ if (circuit_package_relay_cell(&cell, circ, cell_direction, cpath_layer,
+ stream_id, filename, lineno) < 0) {
+ log_warn(LD_BUG,"circuit_package_relay_cell failed. Closing.");
+ circuit_mark_for_close(circ, END_CIRC_REASON_INTERNAL);
+ return -1;
+ }
+ return 0;
+}
+
+/** Make a relay cell out of <b>relay_command</b> and <b>payload</b>, and
+ * send it onto the open circuit <b>circ</b>. <b>fromconn</b> is the stream
+ * that's sending the relay cell, or NULL if it's a control cell.
+ * <b>cpath_layer</b> is NULL for OR->OP cells, or the destination hop
+ * for OP->OR cells.
+ *
+ * If you can't send the cell, mark the circuit for close and
+ * return -1. Else return 0.
+ */
+int
+connection_edge_send_command(edge_connection_t *fromconn,
+ uint8_t relay_command, const char *payload,
+ size_t payload_len)
+{
+ /* XXXX NM Split this function into a separate versions per circuit type? */
+ circuit_t *circ;
+ crypt_path_t *cpath_layer = fromconn->cpath_layer;
+ tor_assert(fromconn);
+ circ = fromconn->on_circuit;
+
+ if (fromconn->base_.marked_for_close) {
+ log_warn(LD_BUG,
+ "called on conn that's already marked for close at %s:%d.",
+ fromconn->base_.marked_for_close_file,
+ fromconn->base_.marked_for_close);
+ return 0;
+ }
+
+ if (!circ) {
+ if (fromconn->base_.type == CONN_TYPE_AP) {
+ log_info(LD_APP,"no circ. Closing conn.");
+ connection_mark_unattached_ap(EDGE_TO_ENTRY_CONN(fromconn),
+ END_STREAM_REASON_INTERNAL);
+ } else {
+ log_info(LD_EXIT,"no circ. Closing conn.");
+ fromconn->edge_has_sent_end = 1; /* no circ to send to */
+ fromconn->end_reason = END_STREAM_REASON_INTERNAL;
+ connection_mark_for_close(TO_CONN(fromconn));
+ }
+ return -1;
+ }
+
+ if (circ->marked_for_close) {
+ /* The circuit has been marked, but not freed yet. When it's freed, it
+ * will mark this connection for close. */
+ return -1;
+ }
+
+#ifdef MEASUREMENTS_21206
+ /* Keep track of the number of RELAY_DATA cells sent for directory
+ * connections. */
+ connection_t *linked_conn = TO_CONN(fromconn)->linked_conn;
+
+ if (linked_conn && linked_conn->type == CONN_TYPE_DIR) {
+ ++(TO_DIR_CONN(linked_conn)->data_cells_sent);
+ }
+#endif /* defined(MEASUREMENTS_21206) */
+
+ return relay_send_command_from_edge(fromconn->stream_id, circ,
+ relay_command, payload,
+ payload_len, cpath_layer);
+}
+
+/** How many times will I retry a stream that fails due to DNS
+ * resolve failure or misc error?
+ */
+#define MAX_RESOLVE_FAILURES 3
+
+/** Return 1 if reason is something that you should retry if you
+ * get the end cell before you've connected; else return 0. */
+static int
+edge_reason_is_retriable(int reason)
+{
+ return reason == END_STREAM_REASON_HIBERNATING ||
+ reason == END_STREAM_REASON_RESOURCELIMIT ||
+ reason == END_STREAM_REASON_EXITPOLICY ||
+ reason == END_STREAM_REASON_RESOLVEFAILED ||
+ reason == END_STREAM_REASON_MISC ||
+ reason == END_STREAM_REASON_NOROUTE;
+}
+
+/** Called when we receive an END cell on a stream that isn't open yet,
+ * from the client side.
+ * Arguments are as for connection_edge_process_relay_cell().
+ */
+static int
+connection_ap_process_end_not_open(
+ relay_header_t *rh, cell_t *cell, origin_circuit_t *circ,
+ entry_connection_t *conn, crypt_path_t *layer_hint)
+{
+ node_t *exitrouter;
+ int reason = *(cell->payload+RELAY_HEADER_SIZE);
+ int control_reason;
+ edge_connection_t *edge_conn = ENTRY_TO_EDGE_CONN(conn);
+ (void) layer_hint; /* unused */
+
+ if (rh->length > 0) {
+ if (reason == END_STREAM_REASON_TORPROTOCOL ||
+ reason == END_STREAM_REASON_DESTROY) {
+ /* Both of these reasons could mean a failed tag
+ * hit the exit and it complained. Do not probe.
+ * Fail the circuit. */
+ circ->path_state = PATH_STATE_USE_FAILED;
+ return -END_CIRC_REASON_TORPROTOCOL;
+ } else if (reason == END_STREAM_REASON_INTERNAL) {
+ /* We can't infer success or failure, since older Tors report
+ * ENETUNREACH as END_STREAM_REASON_INTERNAL. */
+ } else {
+ /* Path bias: If we get a valid reason code from the exit,
+ * it wasn't due to tagging.
+ *
+ * We rely on recognized+digest being strong enough to make
+ * tags unlikely to allow us to get tagged, yet 'recognized'
+ * reason codes here. */
+ pathbias_mark_use_success(circ);
+ }
+ }
+
+ /* This end cell is now valid. */
+ circuit_read_valid_data(circ, rh->length);
+
+ if (rh->length == 0) {
+ reason = END_STREAM_REASON_MISC;
+ }
+
+ control_reason = reason | END_STREAM_REASON_FLAG_REMOTE;
+
+ if (edge_reason_is_retriable(reason) &&
+ /* avoid retry if rend */
+ !connection_edge_is_rendezvous_stream(edge_conn)) {
+ const char *chosen_exit_digest =
+ circ->build_state->chosen_exit->identity_digest;
+ log_info(LD_APP,"Address '%s' refused due to '%s'. Considering retrying.",
+ safe_str(conn->socks_request->address),
+ stream_end_reason_to_string(reason));
+ exitrouter = node_get_mutable_by_id(chosen_exit_digest);
+ switch (reason) {
+ case END_STREAM_REASON_EXITPOLICY: {
+ tor_addr_t addr;
+ tor_addr_make_unspec(&addr);
+ if (rh->length >= 5) {
+ int ttl = -1;
+ tor_addr_make_unspec(&addr);
+ if (rh->length == 5 || rh->length == 9) {
+ tor_addr_from_ipv4n(&addr,
+ get_uint32(cell->payload+RELAY_HEADER_SIZE+1));
+ if (rh->length == 9)
+ ttl = (int)ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE+5));
+ } else if (rh->length == 17 || rh->length == 21) {
+ tor_addr_from_ipv6_bytes(&addr,
+ (char*)(cell->payload+RELAY_HEADER_SIZE+1));
+ if (rh->length == 21)
+ ttl = (int)ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE+17));
+ }
+ if (tor_addr_is_null(&addr)) {
+ log_info(LD_APP,"Address '%s' resolved to 0.0.0.0. Closing,",
+ safe_str(conn->socks_request->address));
+ connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL);
+ return 0;
+ }
+
+ if ((tor_addr_family(&addr) == AF_INET &&
+ !conn->entry_cfg.ipv4_traffic) ||
+ (tor_addr_family(&addr) == AF_INET6 &&
+ !conn->entry_cfg.ipv6_traffic)) {
+ log_fn(LOG_PROTOCOL_WARN, LD_APP,
+ "Got an EXITPOLICY failure on a connection with a "
+ "mismatched family. Closing.");
+ connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL);
+ return 0;
+ }
+ if (get_options()->ClientDNSRejectInternalAddresses &&
+ tor_addr_is_internal(&addr, 0)) {
+ log_info(LD_APP,"Address '%s' resolved to internal. Closing,",
+ safe_str(conn->socks_request->address));
+ connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL);
+ return 0;
+ }
+
+ client_dns_set_addressmap(conn,
+ conn->socks_request->address, &addr,
+ conn->chosen_exit_name, ttl);
+
+ {
+ char new_addr[TOR_ADDR_BUF_LEN];
+ tor_addr_to_str(new_addr, &addr, sizeof(new_addr), 1);
+ if (strcmp(conn->socks_request->address, new_addr)) {
+ strlcpy(conn->socks_request->address, new_addr,
+ sizeof(conn->socks_request->address));
+ control_event_stream_status(conn, STREAM_EVENT_REMAP, 0);
+ }
+ }
+ }
+ /* check if the exit *ought* to have allowed it */
+
+ adjust_exit_policy_from_exitpolicy_failure(circ,
+ conn,
+ exitrouter,
+ &addr);
+
+ if (conn->chosen_exit_optional ||
+ conn->chosen_exit_retries) {
+ /* stop wanting a specific exit */
+ conn->chosen_exit_optional = 0;
+ /* A non-zero chosen_exit_retries can happen if we set a
+ * TrackHostExits for this address under a port that the exit
+ * relay allows, but then try the same address with a different
+ * port that it doesn't allow to exit. We shouldn't unregister
+ * the mapping, since it is probably still wanted on the
+ * original port. But now we give away to the exit relay that
+ * we probably have a TrackHostExits on it. So be it. */
+ conn->chosen_exit_retries = 0;
+ tor_free(conn->chosen_exit_name); /* clears it */
+ }
+ if (connection_ap_detach_retriable(conn, circ, control_reason) >= 0)
+ return 0;
+ /* else, conn will get closed below */
+ break;
+ }
+ case END_STREAM_REASON_CONNECTREFUSED:
+ if (!conn->chosen_exit_optional)
+ break; /* break means it'll close, below */
+ /* Else fall through: expire this circuit, clear the
+ * chosen_exit_name field, and try again. */
+ /* Falls through. */
+ case END_STREAM_REASON_RESOLVEFAILED:
+ case END_STREAM_REASON_TIMEOUT:
+ case END_STREAM_REASON_MISC:
+ case END_STREAM_REASON_NOROUTE:
+ if (client_dns_incr_failures(conn->socks_request->address)
+ < MAX_RESOLVE_FAILURES) {
+ /* We haven't retried too many times; reattach the connection. */
+ circuit_log_path(LOG_INFO,LD_APP,circ);
+ /* Mark this circuit "unusable for new streams". */
+ mark_circuit_unusable_for_new_conns(circ);
+
+ if (conn->chosen_exit_optional) {
+ /* stop wanting a specific exit */
+ conn->chosen_exit_optional = 0;
+ tor_free(conn->chosen_exit_name); /* clears it */
+ }
+ if (connection_ap_detach_retriable(conn, circ, control_reason) >= 0)
+ return 0;
+ /* else, conn will get closed below */
+ } else {
+ log_notice(LD_APP,
+ "Have tried resolving or connecting to address '%s' "
+ "at %d different places. Giving up.",
+ safe_str(conn->socks_request->address),
+ MAX_RESOLVE_FAILURES);
+ /* clear the failures, so it will have a full try next time */
+ client_dns_clear_failures(conn->socks_request->address);
+ }
+ break;
+ case END_STREAM_REASON_HIBERNATING:
+ case END_STREAM_REASON_RESOURCELIMIT:
+ if (exitrouter) {
+ policies_set_node_exitpolicy_to_reject_all(exitrouter);
+ }
+ if (conn->chosen_exit_optional) {
+ /* stop wanting a specific exit */
+ conn->chosen_exit_optional = 0;
+ tor_free(conn->chosen_exit_name); /* clears it */
+ }
+ if (connection_ap_detach_retriable(conn, circ, control_reason) >= 0)
+ return 0;
+ /* else, will close below */
+ break;
+ } /* end switch */
+ log_info(LD_APP,"Giving up on retrying; conn can't be handled.");
+ }
+
+ log_info(LD_APP,
+ "Edge got end (%s) before we're connected. Marking for close.",
+ stream_end_reason_to_string(rh->length > 0 ? reason : -1));
+ circuit_log_path(LOG_INFO,LD_APP,circ);
+ /* need to test because of detach_retriable */
+ if (!ENTRY_TO_CONN(conn)->marked_for_close)
+ connection_mark_unattached_ap(conn, control_reason);
+ return 0;
+}
+
+/** Called when we have gotten an END_REASON_EXITPOLICY failure on <b>circ</b>
+ * for <b>conn</b>, while attempting to connect via <b>node</b>. If the node
+ * told us which address it rejected, then <b>addr</b> is that address;
+ * otherwise it is AF_UNSPEC.
+ *
+ * If we are sure the node should have allowed this address, mark the node as
+ * having a reject *:* exit policy. Otherwise, mark the circuit as unusable
+ * for this particular address.
+ **/
+static void
+adjust_exit_policy_from_exitpolicy_failure(origin_circuit_t *circ,
+ entry_connection_t *conn,
+ node_t *node,
+ const tor_addr_t *addr)
+{
+ int make_reject_all = 0;
+ const sa_family_t family = tor_addr_family(addr);
+
+ if (node) {
+ tor_addr_t tmp;
+ int asked_for_family = tor_addr_parse(&tmp, conn->socks_request->address);
+ if (family == AF_UNSPEC) {
+ make_reject_all = 1;
+ } else if (node_exit_policy_is_exact(node, family) &&
+ asked_for_family != -1 && !conn->chosen_exit_name) {
+ make_reject_all = 1;
+ }
+
+ if (make_reject_all) {
+ log_info(LD_APP,
+ "Exitrouter %s seems to be more restrictive than its exit "
+ "policy. Not using this router as exit for now.",
+ node_describe(node));
+ policies_set_node_exitpolicy_to_reject_all(node);
+ }
+ }
+
+ if (family != AF_UNSPEC)
+ addr_policy_append_reject_addr(&circ->prepend_policy, addr);
+}
+
+/** Helper: change the socks_request->address field on conn to the
+ * dotted-quad representation of <b>new_addr</b>,
+ * and send an appropriate REMAP event. */
+static void
+remap_event_helper(entry_connection_t *conn, const tor_addr_t *new_addr)
+{
+ tor_addr_to_str(conn->socks_request->address, new_addr,
+ sizeof(conn->socks_request->address),
+ 1);
+ control_event_stream_status(conn, STREAM_EVENT_REMAP,
+ REMAP_STREAM_SOURCE_EXIT);
+}
+
+/** Extract the contents of a connected cell in <b>cell</b>, whose relay
+ * header has already been parsed into <b>rh</b>. On success, set
+ * <b>addr_out</b> to the address we're connected to, and <b>ttl_out</b> to
+ * the ttl of that address, in seconds, and return 0. On failure, return
+ * -1.
+ *
+ * Note that the resulting address can be UNSPEC if the connected cell had no
+ * address (as for a stream to an union service or a tunneled directory
+ * connection), and that the ttl can be absent (in which case <b>ttl_out</b>
+ * is set to -1). */
+STATIC int
+connected_cell_parse(const relay_header_t *rh, const cell_t *cell,
+ tor_addr_t *addr_out, int *ttl_out)
+{
+ uint32_t bytes;
+ const uint8_t *payload = cell->payload + RELAY_HEADER_SIZE;
+
+ tor_addr_make_unspec(addr_out);
+ *ttl_out = -1;
+ if (rh->length == 0)
+ return 0;
+ if (rh->length < 4)
+ return -1;
+ bytes = ntohl(get_uint32(payload));
+
+ /* If bytes is 0, this is maybe a v6 address. Otherwise it's a v4 address */
+ if (bytes != 0) {
+ /* v4 address */
+ tor_addr_from_ipv4h(addr_out, bytes);
+ if (rh->length >= 8) {
+ bytes = ntohl(get_uint32(payload + 4));
+ if (bytes <= INT32_MAX)
+ *ttl_out = bytes;
+ }
+ } else {
+ if (rh->length < 25) /* 4 bytes of 0s, 1 addr, 16 ipv4, 4 ttl. */
+ return -1;
+ if (get_uint8(payload + 4) != 6)
+ return -1;
+ tor_addr_from_ipv6_bytes(addr_out, (char*)(payload + 5));
+ bytes = ntohl(get_uint32(payload + 21));
+ if (bytes <= INT32_MAX)
+ *ttl_out = (int) bytes;
+ }
+ return 0;
+}
+
+/** Drop all storage held by <b>addr</b>. */
+STATIC void
+address_ttl_free_(address_ttl_t *addr)
+{
+ if (!addr)
+ return;
+ tor_free(addr->hostname);
+ tor_free(addr);
+}
+
+/** Parse a resolved cell in <b>cell</b>, with parsed header in <b>rh</b>.
+ * Return -1 on parse error. On success, add one or more newly allocated
+ * address_ttl_t to <b>addresses_out</b>; set *<b>errcode_out</b> to
+ * one of 0, RESOLVED_TYPE_ERROR, or RESOLVED_TYPE_ERROR_TRANSIENT, and
+ * return 0. */
+STATIC int
+resolved_cell_parse(const cell_t *cell, const relay_header_t *rh,
+ smartlist_t *addresses_out, int *errcode_out)
+{
+ const uint8_t *cp;
+ uint8_t answer_type;
+ size_t answer_len;
+ address_ttl_t *addr;
+ size_t remaining;
+ int errcode = 0;
+ smartlist_t *addrs;
+
+ tor_assert(cell);
+ tor_assert(rh);
+ tor_assert(addresses_out);
+ tor_assert(errcode_out);
+
+ *errcode_out = 0;
+
+ if (rh->length > RELAY_PAYLOAD_SIZE)
+ return -1;
+
+ addrs = smartlist_new();
+
+ cp = cell->payload + RELAY_HEADER_SIZE;
+
+ remaining = rh->length;
+ while (remaining) {
+ const uint8_t *cp_orig = cp;
+ if (remaining < 2)
+ goto err;
+ answer_type = *cp++;
+ answer_len = *cp++;
+ if (remaining < 2 + answer_len + 4) {
+ goto err;
+ }
+ if (answer_type == RESOLVED_TYPE_IPV4) {
+ if (answer_len != 4) {
+ goto err;
+ }
+ addr = tor_malloc_zero(sizeof(*addr));
+ tor_addr_from_ipv4n(&addr->addr, get_uint32(cp));
+ cp += 4;
+ addr->ttl = ntohl(get_uint32(cp));
+ cp += 4;
+ smartlist_add(addrs, addr);
+ } else if (answer_type == RESOLVED_TYPE_IPV6) {
+ if (answer_len != 16)
+ goto err;
+ addr = tor_malloc_zero(sizeof(*addr));
+ tor_addr_from_ipv6_bytes(&addr->addr, (const char*) cp);
+ cp += 16;
+ addr->ttl = ntohl(get_uint32(cp));
+ cp += 4;
+ smartlist_add(addrs, addr);
+ } else if (answer_type == RESOLVED_TYPE_HOSTNAME) {
+ if (answer_len == 0) {
+ goto err;
+ }
+ addr = tor_malloc_zero(sizeof(*addr));
+ addr->hostname = tor_memdup_nulterm(cp, answer_len);
+ cp += answer_len;
+ addr->ttl = ntohl(get_uint32(cp));
+ cp += 4;
+ smartlist_add(addrs, addr);
+ } else if (answer_type == RESOLVED_TYPE_ERROR_TRANSIENT ||
+ answer_type == RESOLVED_TYPE_ERROR) {
+ errcode = answer_type;
+ /* Ignore the error contents */
+ cp += answer_len + 4;
+ } else {
+ cp += answer_len + 4;
+ }
+ tor_assert(((ssize_t)remaining) >= (cp - cp_orig));
+ remaining -= (cp - cp_orig);
+ }
+
+ if (errcode && smartlist_len(addrs) == 0) {
+ /* Report an error only if there were no results. */
+ *errcode_out = errcode;
+ }
+
+ smartlist_add_all(addresses_out, addrs);
+ smartlist_free(addrs);
+
+ return 0;
+
+ err:
+ /* On parse error, don't report any results */
+ SMARTLIST_FOREACH(addrs, address_ttl_t *, a, address_ttl_free(a));
+ smartlist_free(addrs);
+ return -1;
+}
+
+/** Helper for connection_edge_process_resolved_cell: given an error code,
+ * an entry_connection, and a list of address_ttl_t *, report the best answer
+ * to the entry_connection. */
+static void
+connection_ap_handshake_socks_got_resolved_cell(entry_connection_t *conn,
+ int error_code,
+ smartlist_t *results)
+{
+ address_ttl_t *addr_ipv4 = NULL;
+ address_ttl_t *addr_ipv6 = NULL;
+ address_ttl_t *addr_hostname = NULL;
+ address_ttl_t *addr_best = NULL;
+
+ /* If it's an error code, that's easy. */
+ if (error_code) {
+ tor_assert(error_code == RESOLVED_TYPE_ERROR ||
+ error_code == RESOLVED_TYPE_ERROR_TRANSIENT);
+ connection_ap_handshake_socks_resolved(conn,
+ error_code,0,NULL,-1,-1);
+ return;
+ }
+
+ /* Get the first answer of each type. */
+ SMARTLIST_FOREACH_BEGIN(results, address_ttl_t *, addr) {
+ if (addr->hostname) {
+ if (!addr_hostname) {
+ addr_hostname = addr;
+ }
+ } else if (tor_addr_family(&addr->addr) == AF_INET) {
+ if (!addr_ipv4 && conn->entry_cfg.ipv4_traffic) {
+ addr_ipv4 = addr;
+ }
+ } else if (tor_addr_family(&addr->addr) == AF_INET6) {
+ if (!addr_ipv6 && conn->entry_cfg.ipv6_traffic) {
+ addr_ipv6 = addr;
+ }
+ }
+ } SMARTLIST_FOREACH_END(addr);
+
+ /* Now figure out which type we wanted to deliver. */
+ if (conn->socks_request->command == SOCKS_COMMAND_RESOLVE_PTR) {
+ if (addr_hostname) {
+ connection_ap_handshake_socks_resolved(conn,
+ RESOLVED_TYPE_HOSTNAME,
+ strlen(addr_hostname->hostname),
+ (uint8_t*)addr_hostname->hostname,
+ addr_hostname->ttl,-1);
+ } else {
+ connection_ap_handshake_socks_resolved(conn,
+ RESOLVED_TYPE_ERROR,0,NULL,-1,-1);
+ }
+ return;
+ }
+
+ if (conn->entry_cfg.prefer_ipv6) {
+ addr_best = addr_ipv6 ? addr_ipv6 : addr_ipv4;
+ } else {
+ addr_best = addr_ipv4 ? addr_ipv4 : addr_ipv6;
+ }
+
+ /* Now convert it to the ugly old interface */
+ if (! addr_best) {
+ connection_ap_handshake_socks_resolved(conn,
+ RESOLVED_TYPE_ERROR,0,NULL,-1,-1);
+ return;
+ }
+
+ connection_ap_handshake_socks_resolved_addr(conn,
+ &addr_best->addr,
+ addr_best->ttl,
+ -1);
+
+ remap_event_helper(conn, &addr_best->addr);
+}
+
+/** Handle a RELAY_COMMAND_RESOLVED cell that we received on a non-open AP
+ * stream. */
+STATIC int
+connection_edge_process_resolved_cell(edge_connection_t *conn,
+ const cell_t *cell,
+ const relay_header_t *rh)
+{
+ entry_connection_t *entry_conn = EDGE_TO_ENTRY_CONN(conn);
+ smartlist_t *resolved_addresses = NULL;
+ int errcode = 0;
+
+ if (conn->base_.state != AP_CONN_STATE_RESOLVE_WAIT) {
+ log_fn(LOG_PROTOCOL_WARN, LD_APP, "Got a 'resolved' cell while "
+ "not in state resolve_wait. Dropping.");
+ return 0;
+ }
+ tor_assert(SOCKS_COMMAND_IS_RESOLVE(entry_conn->socks_request->command));
+
+ resolved_addresses = smartlist_new();
+ if (resolved_cell_parse(cell, rh, resolved_addresses, &errcode)) {
+ log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
+ "Dropping malformed 'resolved' cell");
+ connection_mark_unattached_ap(entry_conn, END_STREAM_REASON_TORPROTOCOL);
+ goto done;
+ }
+
+ if (get_options()->ClientDNSRejectInternalAddresses) {
+ int orig_len = smartlist_len(resolved_addresses);
+ SMARTLIST_FOREACH_BEGIN(resolved_addresses, address_ttl_t *, addr) {
+ if (addr->hostname == NULL && tor_addr_is_internal(&addr->addr, 0)) {
+ log_info(LD_APP, "Got a resolved cell with answer %s; dropping that "
+ "answer.",
+ safe_str_client(fmt_addr(&addr->addr)));
+ address_ttl_free(addr);
+ SMARTLIST_DEL_CURRENT(resolved_addresses, addr);
+ }
+ } SMARTLIST_FOREACH_END(addr);
+ if (orig_len && smartlist_len(resolved_addresses) == 0) {
+ log_info(LD_APP, "Got a resolved cell with only private addresses; "
+ "dropping it.");
+ connection_ap_handshake_socks_resolved(entry_conn,
+ RESOLVED_TYPE_ERROR_TRANSIENT,
+ 0, NULL, 0, TIME_MAX);
+ connection_mark_unattached_ap(entry_conn,
+ END_STREAM_REASON_TORPROTOCOL);
+ goto done;
+ }
+ }
+
+ /* This is valid data at this point. Count it */
+ if (conn->on_circuit && CIRCUIT_IS_ORIGIN(conn->on_circuit)) {
+ circuit_read_valid_data(TO_ORIGIN_CIRCUIT(conn->on_circuit),
+ rh->length);
+ }
+
+ connection_ap_handshake_socks_got_resolved_cell(entry_conn,
+ errcode,
+ resolved_addresses);
+
+ connection_mark_unattached_ap(entry_conn,
+ END_STREAM_REASON_DONE |
+ END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED);
+
+ done:
+ SMARTLIST_FOREACH(resolved_addresses, address_ttl_t *, addr,
+ address_ttl_free(addr));
+ smartlist_free(resolved_addresses);
+ return 0;
+}
+
+/** An incoming relay cell has arrived from circuit <b>circ</b> to
+ * stream <b>conn</b>.
+ *
+ * The arguments here are the same as in
+ * connection_edge_process_relay_cell() below; this function is called
+ * from there when <b>conn</b> is defined and not in an open state.
+ */
+static int
+connection_edge_process_relay_cell_not_open(
+ relay_header_t *rh, cell_t *cell, circuit_t *circ,
+ edge_connection_t *conn, crypt_path_t *layer_hint)
+{
+ if (rh->command == RELAY_COMMAND_END) {
+ if (CIRCUIT_IS_ORIGIN(circ) && conn->base_.type == CONN_TYPE_AP) {
+ return connection_ap_process_end_not_open(rh, cell,
+ TO_ORIGIN_CIRCUIT(circ),
+ EDGE_TO_ENTRY_CONN(conn),
+ layer_hint);
+ } else {
+ /* we just got an 'end', don't need to send one */
+ conn->edge_has_sent_end = 1;
+ conn->end_reason = *(cell->payload+RELAY_HEADER_SIZE) |
+ END_STREAM_REASON_FLAG_REMOTE;
+ connection_mark_for_close(TO_CONN(conn));
+ return 0;
+ }
+ }
+
+ if (conn->base_.type == CONN_TYPE_AP &&
+ rh->command == RELAY_COMMAND_CONNECTED) {
+ tor_addr_t addr;
+ int ttl;
+ entry_connection_t *entry_conn = EDGE_TO_ENTRY_CONN(conn);
+ tor_assert(CIRCUIT_IS_ORIGIN(circ));
+ if (conn->base_.state != AP_CONN_STATE_CONNECT_WAIT) {
+ log_fn(LOG_PROTOCOL_WARN, LD_APP,
+ "Got 'connected' while not in state connect_wait. Dropping.");
+ return 0;
+ }
+ CONNECTION_AP_EXPECT_NONPENDING(entry_conn);
+ conn->base_.state = AP_CONN_STATE_OPEN;
+ log_info(LD_APP,"'connected' received for circid %u streamid %d "
+ "after %d seconds.",
+ (unsigned)circ->n_circ_id,
+ rh->stream_id,
+ (int)(time(NULL) - conn->base_.timestamp_last_read_allowed));
+ if (connected_cell_parse(rh, cell, &addr, &ttl) < 0) {
+ log_fn(LOG_PROTOCOL_WARN, LD_APP,
+ "Got a badly formatted connected cell. Closing.");
+ connection_edge_end(conn, END_STREAM_REASON_TORPROTOCOL);
+ connection_mark_unattached_ap(entry_conn, END_STREAM_REASON_TORPROTOCOL);
+ return 0;
+ }
+ if (tor_addr_family(&addr) != AF_UNSPEC) {
+ /* The family is not UNSPEC: so we were given an address in the
+ * connected cell. (This is normal, except for BEGINDIR and onion
+ * service streams.) */
+ const sa_family_t family = tor_addr_family(&addr);
+ if (tor_addr_is_null(&addr) ||
+ (get_options()->ClientDNSRejectInternalAddresses &&
+ tor_addr_is_internal(&addr, 0))) {
+ log_info(LD_APP, "...but it claims the IP address was %s. Closing.",
+ fmt_addr(&addr));
+ connection_edge_end(conn, END_STREAM_REASON_TORPROTOCOL);
+ connection_mark_unattached_ap(entry_conn,
+ END_STREAM_REASON_TORPROTOCOL);
+ return 0;
+ }
+
+ if ((family == AF_INET && ! entry_conn->entry_cfg.ipv4_traffic) ||
+ (family == AF_INET6 && ! entry_conn->entry_cfg.ipv6_traffic)) {
+ log_fn(LOG_PROTOCOL_WARN, LD_APP,
+ "Got a connected cell to %s with unsupported address family."
+ " Closing.", fmt_addr(&addr));
+ connection_edge_end(conn, END_STREAM_REASON_TORPROTOCOL);
+ connection_mark_unattached_ap(entry_conn,
+ END_STREAM_REASON_TORPROTOCOL);
+ return 0;
+ }
+
+ client_dns_set_addressmap(entry_conn,
+ entry_conn->socks_request->address, &addr,
+ entry_conn->chosen_exit_name, ttl);
+
+ remap_event_helper(entry_conn, &addr);
+ }
+ circuit_log_path(LOG_INFO,LD_APP,TO_ORIGIN_CIRCUIT(circ));
+ /* don't send a socks reply to transparent conns */
+ tor_assert(entry_conn->socks_request != NULL);
+ if (!entry_conn->socks_request->has_finished) {
+ connection_ap_handshake_socks_reply(entry_conn, NULL, 0, 0);
+ }
+
+ /* Was it a linked dir conn? If so, a dir request just started to
+ * fetch something; this could be a bootstrap status milestone. */
+ log_debug(LD_APP, "considering");
+ if (TO_CONN(conn)->linked_conn &&
+ TO_CONN(conn)->linked_conn->type == CONN_TYPE_DIR) {
+ connection_t *dirconn = TO_CONN(conn)->linked_conn;
+ log_debug(LD_APP, "it is! %d", dirconn->purpose);
+ switch (dirconn->purpose) {
+ case DIR_PURPOSE_FETCH_CERTIFICATE:
+ if (consensus_is_waiting_for_certs())
+ control_event_bootstrap(BOOTSTRAP_STATUS_LOADING_KEYS, 0);
+ break;
+ case DIR_PURPOSE_FETCH_CONSENSUS:
+ control_event_bootstrap(BOOTSTRAP_STATUS_LOADING_STATUS, 0);
+ break;
+ case DIR_PURPOSE_FETCH_SERVERDESC:
+ case DIR_PURPOSE_FETCH_MICRODESC:
+ if (TO_DIR_CONN(dirconn)->router_purpose == ROUTER_PURPOSE_GENERAL)
+ control_event_boot_dir(BOOTSTRAP_STATUS_LOADING_DESCRIPTORS,
+ count_loading_descriptors_progress());
+ break;
+ }
+ }
+ /* This is definitely a success, so forget about any pending data we
+ * had sent. */
+ if (entry_conn->pending_optimistic_data) {
+ buf_free(entry_conn->pending_optimistic_data);
+ entry_conn->pending_optimistic_data = NULL;
+ }
+
+ /* This is valid data at this point. Count it */
+ circuit_read_valid_data(TO_ORIGIN_CIRCUIT(circ), rh->length);
+
+ /* handle anything that might have queued */
+ if (connection_edge_package_raw_inbuf(conn, 1, NULL) < 0) {
+ /* (We already sent an end cell if possible) */
+ connection_mark_for_close(TO_CONN(conn));
+ return 0;
+ }
+ return 0;
+ }
+ if (conn->base_.type == CONN_TYPE_AP &&
+ rh->command == RELAY_COMMAND_RESOLVED) {
+ return connection_edge_process_resolved_cell(conn, cell, rh);
+ }
+
+ log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
+ "Got an unexpected relay command %d, in state %d (%s). Dropping.",
+ rh->command, conn->base_.state,
+ conn_state_to_string(conn->base_.type, conn->base_.state));
+ return 0; /* for forward compatibility, don't kill the circuit */
+// connection_edge_end(conn, END_STREAM_REASON_TORPROTOCOL);
+// connection_mark_for_close(conn);
+// return -1;
+}
+
+/** An incoming relay cell has arrived on circuit <b>circ</b>. If
+ * <b>conn</b> is NULL this is a control cell, else <b>cell</b> is
+ * destined for <b>conn</b>.
+ *
+ * If <b>layer_hint</b> is defined, then we're the origin of the
+ * circuit, and it specifies the hop that packaged <b>cell</b>.
+ *
+ * Return -reason if you want to warn and tear down the circuit, else 0.
+ */
+STATIC int
+connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
+ edge_connection_t *conn,
+ crypt_path_t *layer_hint)
+{
+ static int num_seen=0;
+ relay_header_t rh;
+ unsigned domain = layer_hint?LD_APP:LD_EXIT;
+ int reason;
+ int optimistic_data = 0; /* Set to 1 if we receive data on a stream
+ * that's in the EXIT_CONN_STATE_RESOLVING
+ * or EXIT_CONN_STATE_CONNECTING states. */
+
+ tor_assert(cell);
+ tor_assert(circ);
+
+ relay_header_unpack(&rh, cell->payload);
+// log_fn(LOG_DEBUG,"command %d stream %d", rh.command, rh.stream_id);
+ num_seen++;
+ log_debug(domain, "Now seen %d relay cells here (command %d, stream %d).",
+ num_seen, rh.command, rh.stream_id);
+
+ if (rh.length > RELAY_PAYLOAD_SIZE) {
+ log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
+ "Relay cell length field too long. Closing circuit.");
+ return - END_CIRC_REASON_TORPROTOCOL;
+ }
+
+ if (rh.stream_id == 0) {
+ switch (rh.command) {
+ case RELAY_COMMAND_BEGIN:
+ case RELAY_COMMAND_CONNECTED:
+ case RELAY_COMMAND_END:
+ case RELAY_COMMAND_RESOLVE:
+ case RELAY_COMMAND_RESOLVED:
+ case RELAY_COMMAND_BEGIN_DIR:
+ log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, "Relay command %d with zero "
+ "stream_id. Dropping.", (int)rh.command);
+ return 0;
+ default:
+ ;
+ }
+ }
+
+ /* either conn is NULL, in which case we've got a control cell, or else
+ * conn points to the recognized stream. */
+
+ if (conn && !connection_state_is_open(TO_CONN(conn))) {
+ if (conn->base_.type == CONN_TYPE_EXIT &&
+ (conn->base_.state == EXIT_CONN_STATE_CONNECTING ||
+ conn->base_.state == EXIT_CONN_STATE_RESOLVING) &&
+ rh.command == RELAY_COMMAND_DATA) {
+ /* Allow DATA cells to be delivered to an exit node in state
+ * EXIT_CONN_STATE_CONNECTING or EXIT_CONN_STATE_RESOLVING.
+ * This speeds up HTTP, for example. */
+ optimistic_data = 1;
+ } else if (rh.stream_id == 0 && rh.command == RELAY_COMMAND_DATA) {
+ log_warn(LD_BUG, "Somehow I had a connection that matched a "
+ "data cell with stream ID 0.");
+ } else {
+ return connection_edge_process_relay_cell_not_open(
+ &rh, cell, circ, conn, layer_hint);
+ }
+ }
+
+ switch (rh.command) {
+ case RELAY_COMMAND_DROP:
+ rep_hist_padding_count_read(PADDING_TYPE_DROP);
+// log_info(domain,"Got a relay-level padding cell. Dropping.");
+ return 0;
+ case RELAY_COMMAND_BEGIN:
+ case RELAY_COMMAND_BEGIN_DIR:
+ if (layer_hint &&
+ circ->purpose != CIRCUIT_PURPOSE_S_REND_JOINED) {
+ log_fn(LOG_PROTOCOL_WARN, LD_APP,
+ "Relay begin request unsupported at AP. Dropping.");
+ return 0;
+ }
+ if (circ->purpose == CIRCUIT_PURPOSE_S_REND_JOINED &&
+ layer_hint != TO_ORIGIN_CIRCUIT(circ)->cpath->prev) {
+ log_fn(LOG_PROTOCOL_WARN, LD_APP,
+ "Relay begin request to Hidden Service "
+ "from intermediary node. Dropping.");
+ return 0;
+ }
+ if (conn) {
+ log_fn(LOG_PROTOCOL_WARN, domain,
+ "Begin cell for known stream. Dropping.");
+ return 0;
+ }
+ if (rh.command == RELAY_COMMAND_BEGIN_DIR &&
+ circ->purpose != CIRCUIT_PURPOSE_S_REND_JOINED) {
+ /* Assign this circuit and its app-ward OR connection a unique ID,
+ * so that we can measure download times. The local edge and dir
+ * connection will be assigned the same ID when they are created
+ * and linked. */
+ static uint64_t next_id = 0;
+ circ->dirreq_id = ++next_id;
+ TO_OR_CIRCUIT(circ)->p_chan->dirreq_id = circ->dirreq_id;
+ }
+ return connection_exit_begin_conn(cell, circ);
+ case RELAY_COMMAND_DATA:
+ ++stats_n_data_cells_received;
+ if (( layer_hint && --layer_hint->deliver_window < 0) ||
+ (!layer_hint && --circ->deliver_window < 0)) {
+ log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
+ "(relay data) circ deliver_window below 0. Killing.");
+ if (conn) {
+ /* XXXX Do we actually need to do this? Will killing the circuit
+ * not send an END and mark the stream for close as appropriate? */
+ connection_edge_end(conn, END_STREAM_REASON_TORPROTOCOL);
+ connection_mark_for_close(TO_CONN(conn));
+ }
+ return -END_CIRC_REASON_TORPROTOCOL;
+ }
+ log_debug(domain,"circ deliver_window now %d.", layer_hint ?
+ layer_hint->deliver_window : circ->deliver_window);
+
+ circuit_consider_sending_sendme(circ, layer_hint);
+
+ if (rh.stream_id == 0) {
+ log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, "Relay data cell with zero "
+ "stream_id. Dropping.");
+ return 0;
+ } else if (!conn) {
+ if (CIRCUIT_IS_ORIGIN(circ)) {
+ origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ);
+ if (connection_half_edge_is_valid_data(ocirc->half_streams,
+ rh.stream_id)) {
+ circuit_read_valid_data(ocirc, rh.length);
+ log_info(domain,
+ "data cell on circ %u valid on half-closed "
+ "stream id %d", ocirc->global_identifier, rh.stream_id);
+ }
+ }
+
+ log_info(domain,"data cell dropped, unknown stream (streamid %d).",
+ rh.stream_id);
+ return 0;
+ }
+
+ if (--conn->deliver_window < 0) { /* is it below 0 after decrement? */
+ log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
+ "(relay data) conn deliver_window below 0. Killing.");
+ return -END_CIRC_REASON_TORPROTOCOL;
+ }
+ /* Total all valid application bytes delivered */
+ if (CIRCUIT_IS_ORIGIN(circ) && rh.length > 0) {
+ circuit_read_valid_data(TO_ORIGIN_CIRCUIT(circ), rh.length);
+ }
+
+ stats_n_data_bytes_received += rh.length;
+ connection_buf_add((char*)(cell->payload + RELAY_HEADER_SIZE),
+ rh.length, TO_CONN(conn));
+
+#ifdef MEASUREMENTS_21206
+ /* Count number of RELAY_DATA cells received on a linked directory
+ * connection. */
+ connection_t *linked_conn = TO_CONN(conn)->linked_conn;
+
+ if (linked_conn && linked_conn->type == CONN_TYPE_DIR) {
+ ++(TO_DIR_CONN(linked_conn)->data_cells_received);
+ }
+#endif /* defined(MEASUREMENTS_21206) */
+
+ if (!optimistic_data) {
+ /* Only send a SENDME if we're not getting optimistic data; otherwise
+ * a SENDME could arrive before the CONNECTED.
+ */
+ connection_edge_consider_sending_sendme(conn);
+ }
+
+ return 0;
+ case RELAY_COMMAND_END:
+ reason = rh.length > 0 ?
+ get_uint8(cell->payload+RELAY_HEADER_SIZE) : END_STREAM_REASON_MISC;
+ if (!conn) {
+ if (CIRCUIT_IS_ORIGIN(circ)) {
+ origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ);
+ if (connection_half_edge_is_valid_end(ocirc->half_streams,
+ rh.stream_id)) {
+
+ circuit_read_valid_data(ocirc, rh.length);
+ log_info(domain,
+ "end cell (%s) on circ %u valid on half-closed "
+ "stream id %d",
+ stream_end_reason_to_string(reason),
+ ocirc->global_identifier, rh.stream_id);
+ return 0;
+ }
+ }
+ log_info(domain,"end cell (%s) dropped, unknown stream.",
+ stream_end_reason_to_string(reason));
+ return 0;
+ }
+/* XXX add to this log_fn the exit node's nickname? */
+ log_info(domain,TOR_SOCKET_T_FORMAT": end cell (%s) for stream %d. "
+ "Removing stream.",
+ conn->base_.s,
+ stream_end_reason_to_string(reason),
+ conn->stream_id);
+ if (conn->base_.type == CONN_TYPE_AP) {
+ entry_connection_t *entry_conn = EDGE_TO_ENTRY_CONN(conn);
+ if (entry_conn->socks_request &&
+ !entry_conn->socks_request->has_finished)
+ log_warn(LD_BUG,
+ "open stream hasn't sent socks answer yet? Closing.");
+ }
+ /* We just *got* an end; no reason to send one. */
+ conn->edge_has_sent_end = 1;
+ if (!conn->end_reason)
+ conn->end_reason = reason | END_STREAM_REASON_FLAG_REMOTE;
+ if (!conn->base_.marked_for_close) {
+ /* only mark it if not already marked. it's possible to
+ * get the 'end' right around when the client hangs up on us. */
+ connection_mark_and_flush(TO_CONN(conn));
+
+ /* Total all valid application bytes delivered */
+ if (CIRCUIT_IS_ORIGIN(circ)) {
+ circuit_read_valid_data(TO_ORIGIN_CIRCUIT(circ), rh.length);
+ }
+ }
+ return 0;
+ case RELAY_COMMAND_EXTEND:
+ case RELAY_COMMAND_EXTEND2: {
+ static uint64_t total_n_extend=0, total_nonearly=0;
+ total_n_extend++;
+ if (rh.stream_id) {
+ log_fn(LOG_PROTOCOL_WARN, domain,
+ "'extend' cell received for non-zero stream. Dropping.");
+ return 0;
+ }
+ if (cell->command != CELL_RELAY_EARLY &&
+ !networkstatus_get_param(NULL,"AllowNonearlyExtend",0,0,1)) {
+#define EARLY_WARNING_INTERVAL 3600
+ static ratelim_t early_warning_limit =
+ RATELIM_INIT(EARLY_WARNING_INTERVAL);
+ char *m;
+ if (cell->command == CELL_RELAY) {
+ ++total_nonearly;
+ if ((m = rate_limit_log(&early_warning_limit, approx_time()))) {
+ double percentage = ((double)total_nonearly)/total_n_extend;
+ percentage *= 100;
+ log_fn(LOG_PROTOCOL_WARN, domain, "EXTEND cell received, "
+ "but not via RELAY_EARLY. Dropping.%s", m);
+ log_fn(LOG_PROTOCOL_WARN, domain, " (We have dropped %.02f%% of "
+ "all EXTEND cells for this reason)", percentage);
+ tor_free(m);
+ }
+ } else {
+ log_fn(LOG_WARN, domain,
+ "EXTEND cell received, in a cell with type %d! Dropping.",
+ cell->command);
+ }
+ return 0;
+ }
+ return circuit_extend(cell, circ);
+ }
+ case RELAY_COMMAND_EXTENDED:
+ case RELAY_COMMAND_EXTENDED2:
+ if (!layer_hint) {
+ log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
+ "'extended' unsupported at non-origin. Dropping.");
+ return 0;
+ }
+ log_debug(domain,"Got an extended cell! Yay.");
+ {
+ extended_cell_t extended_cell;
+ if (extended_cell_parse(&extended_cell, rh.command,
+ (const uint8_t*)cell->payload+RELAY_HEADER_SIZE,
+ rh.length)<0) {
+ log_warn(LD_PROTOCOL,
+ "Can't parse EXTENDED cell; killing circuit.");
+ return -END_CIRC_REASON_TORPROTOCOL;
+ }
+ if ((reason = circuit_finish_handshake(TO_ORIGIN_CIRCUIT(circ),
+ &extended_cell.created_cell)) < 0) {
+ circuit_mark_for_close(circ, -reason);
+ return 0; /* We don't want to cause a warning, so we mark the circuit
+ * here. */
+ }
+ }
+ if ((reason=circuit_send_next_onion_skin(TO_ORIGIN_CIRCUIT(circ)))<0) {
+ log_info(domain,"circuit_send_next_onion_skin() failed.");
+ return reason;
+ }
+ /* Total all valid bytes delivered. */
+ if (CIRCUIT_IS_ORIGIN(circ)) {
+ circuit_read_valid_data(TO_ORIGIN_CIRCUIT(circ), rh.length);
+ }
+ return 0;
+ case RELAY_COMMAND_TRUNCATE:
+ if (layer_hint) {
+ log_fn(LOG_PROTOCOL_WARN, LD_APP,
+ "'truncate' unsupported at origin. Dropping.");
+ return 0;
+ }
+ if (circ->n_hop) {
+ if (circ->n_chan)
+ log_warn(LD_BUG, "n_chan and n_hop set on the same circuit!");
+ extend_info_free(circ->n_hop);
+ circ->n_hop = NULL;
+ tor_free(circ->n_chan_create_cell);
+ circuit_set_state(circ, CIRCUIT_STATE_OPEN);
+ }
+ if (circ->n_chan) {
+ uint8_t trunc_reason = get_uint8(cell->payload + RELAY_HEADER_SIZE);
+ circuit_clear_cell_queue(circ, circ->n_chan);
+ channel_send_destroy(circ->n_circ_id, circ->n_chan,
+ trunc_reason);
+ circuit_set_n_circid_chan(circ, 0, NULL);
+ }
+ log_debug(LD_EXIT, "Processed 'truncate', replying.");
+ {
+ char payload[1];
+ payload[0] = (char)END_CIRC_REASON_REQUESTED;
+ relay_send_command_from_edge(0, circ, RELAY_COMMAND_TRUNCATED,
+ payload, sizeof(payload), NULL);
+ }
+ return 0;
+ case RELAY_COMMAND_TRUNCATED:
+ if (!layer_hint) {
+ log_fn(LOG_PROTOCOL_WARN, LD_EXIT,
+ "'truncated' unsupported at non-origin. Dropping.");
+ return 0;
+ }
+
+ /* Count the truncated as valid, for completeness. The
+ * circuit is being torn down anyway, though. */
+ if (CIRCUIT_IS_ORIGIN(circ)) {
+ circuit_read_valid_data(TO_ORIGIN_CIRCUIT(circ),
+ rh.length);
+ }
+ circuit_truncated(TO_ORIGIN_CIRCUIT(circ),
+ get_uint8(cell->payload + RELAY_HEADER_SIZE));
+ return 0;
+ case RELAY_COMMAND_CONNECTED:
+ if (conn) {
+ log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
+ "'connected' unsupported while open. Closing circ.");
+ return -END_CIRC_REASON_TORPROTOCOL;
+ }
+
+ if (CIRCUIT_IS_ORIGIN(circ)) {
+ origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ);
+ if (connection_half_edge_is_valid_connected(ocirc->half_streams,
+ rh.stream_id)) {
+ circuit_read_valid_data(ocirc, rh.length);
+ log_info(domain,
+ "connected cell on circ %u valid on half-closed "
+ "stream id %d", ocirc->global_identifier, rh.stream_id);
+ return 0;
+ }
+ }
+
+ log_info(domain,
+ "'connected' received on circid %u for streamid %d, "
+ "no conn attached anymore. Ignoring.",
+ (unsigned)circ->n_circ_id, rh.stream_id);
+ return 0;
+ case RELAY_COMMAND_SENDME:
+ if (!rh.stream_id) {
+ if (layer_hint) {
+ if (layer_hint->package_window + CIRCWINDOW_INCREMENT >
+ CIRCWINDOW_START_MAX) {
+ static struct ratelim_t exit_warn_ratelim = RATELIM_INIT(600);
+ log_fn_ratelim(&exit_warn_ratelim, LOG_WARN, LD_PROTOCOL,
+ "Unexpected sendme cell from exit relay. "
+ "Closing circ.");
+ return -END_CIRC_REASON_TORPROTOCOL;
+ }
+ layer_hint->package_window += CIRCWINDOW_INCREMENT;
+ log_debug(LD_APP,"circ-level sendme at origin, packagewindow %d.",
+ layer_hint->package_window);
+ circuit_resume_edge_reading(circ, layer_hint);
+
+ /* We count circuit-level sendme's as valid delivered data because
+ * they are rate limited.
+ */
+ if (CIRCUIT_IS_ORIGIN(circ)) {
+ circuit_read_valid_data(TO_ORIGIN_CIRCUIT(circ),
+ rh.length);
+ }
+
+ } else {
+ if (circ->package_window + CIRCWINDOW_INCREMENT >
+ CIRCWINDOW_START_MAX) {
+ static struct ratelim_t client_warn_ratelim = RATELIM_INIT(600);
+ log_fn_ratelim(&client_warn_ratelim,LOG_PROTOCOL_WARN, LD_PROTOCOL,
+ "Unexpected sendme cell from client. "
+ "Closing circ (window %d).",
+ circ->package_window);
+ return -END_CIRC_REASON_TORPROTOCOL;
+ }
+ circ->package_window += CIRCWINDOW_INCREMENT;
+ log_debug(LD_APP,
+ "circ-level sendme at non-origin, packagewindow %d.",
+ circ->package_window);
+ circuit_resume_edge_reading(circ, layer_hint);
+ }
+ return 0;
+ }
+ if (!conn) {
+ if (CIRCUIT_IS_ORIGIN(circ)) {
+ origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ);
+ if (connection_half_edge_is_valid_sendme(ocirc->half_streams,
+ rh.stream_id)) {
+ circuit_read_valid_data(ocirc, rh.length);
+ log_info(domain,
+ "sendme cell on circ %u valid on half-closed "
+ "stream id %d", ocirc->global_identifier, rh.stream_id);
+ }
+ }
+
+ log_info(domain,"sendme cell dropped, unknown stream (streamid %d).",
+ rh.stream_id);
+ return 0;
+ }
+
+ /* Don't allow the other endpoint to request more than our maximum
+ * (i.e. initial) stream SENDME window worth of data. Well-behaved
+ * stock clients will not request more than this max (as per the check
+ * in the while loop of connection_edge_consider_sending_sendme()).
+ */
+ if (conn->package_window + STREAMWINDOW_INCREMENT >
+ STREAMWINDOW_START_MAX) {
+ static struct ratelim_t stream_warn_ratelim = RATELIM_INIT(600);
+ log_fn_ratelim(&stream_warn_ratelim, LOG_PROTOCOL_WARN, LD_PROTOCOL,
+ "Unexpected stream sendme cell. Closing circ (window %d).",
+ conn->package_window);
+ return -END_CIRC_REASON_TORPROTOCOL;
+ }
+
+ /* At this point, the stream sendme is valid */
+ if (CIRCUIT_IS_ORIGIN(circ)) {
+ circuit_read_valid_data(TO_ORIGIN_CIRCUIT(circ),
+ rh.length);
+ }
+
+ conn->package_window += STREAMWINDOW_INCREMENT;
+ log_debug(domain,"stream-level sendme, packagewindow now %d.",
+ conn->package_window);
+ if (circuit_queue_streams_are_blocked(circ)) {
+ /* Still waiting for queue to flush; don't touch conn */
+ return 0;
+ }
+ connection_start_reading(TO_CONN(conn));
+ /* handle whatever might still be on the inbuf */
+ if (connection_edge_package_raw_inbuf(conn, 1, NULL) < 0) {
+ /* (We already sent an end cell if possible) */
+ connection_mark_for_close(TO_CONN(conn));
+ return 0;
+ }
+ return 0;
+ case RELAY_COMMAND_RESOLVE:
+ if (layer_hint) {
+ log_fn(LOG_PROTOCOL_WARN, LD_APP,
+ "resolve request unsupported at AP; dropping.");
+ return 0;
+ } else if (conn) {
+ log_fn(LOG_PROTOCOL_WARN, domain,
+ "resolve request for known stream; dropping.");
+ return 0;
+ } else if (circ->purpose != CIRCUIT_PURPOSE_OR) {
+ log_fn(LOG_PROTOCOL_WARN, domain,
+ "resolve request on circ with purpose %d; dropping",
+ circ->purpose);
+ return 0;
+ }
+ connection_exit_begin_resolve(cell, TO_OR_CIRCUIT(circ));
+ return 0;
+ case RELAY_COMMAND_RESOLVED:
+ if (conn) {
+ log_fn(LOG_PROTOCOL_WARN, domain,
+ "'resolved' unsupported while open. Closing circ.");
+ return -END_CIRC_REASON_TORPROTOCOL;
+ }
+
+ if (CIRCUIT_IS_ORIGIN(circ)) {
+ origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ);
+ if (connection_half_edge_is_valid_resolved(ocirc->half_streams,
+ rh.stream_id)) {
+ circuit_read_valid_data(ocirc, rh.length);
+ log_info(domain,
+ "resolved cell on circ %u valid on half-closed "
+ "stream id %d", ocirc->global_identifier, rh.stream_id);
+ return 0;
+ }
+ }
+
+ log_info(domain,
+ "'resolved' received, no conn attached anymore. Ignoring.");
+ return 0;
+ case RELAY_COMMAND_ESTABLISH_INTRO:
+ case RELAY_COMMAND_ESTABLISH_RENDEZVOUS:
+ case RELAY_COMMAND_INTRODUCE1:
+ case RELAY_COMMAND_INTRODUCE2:
+ case RELAY_COMMAND_INTRODUCE_ACK:
+ case RELAY_COMMAND_RENDEZVOUS1:
+ case RELAY_COMMAND_RENDEZVOUS2:
+ case RELAY_COMMAND_INTRO_ESTABLISHED:
+ case RELAY_COMMAND_RENDEZVOUS_ESTABLISHED:
+ rend_process_relay_cell(circ, layer_hint,
+ rh.command, rh.length,
+ cell->payload+RELAY_HEADER_SIZE);
+ return 0;
+ }
+ log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
+ "Received unknown relay command %d. Perhaps the other side is using "
+ "a newer version of Tor? Dropping.",
+ rh.command);
+ return 0; /* for forward compatibility, don't kill the circuit */
+}
+
+/** How many relay_data cells have we built, ever? */
+uint64_t stats_n_data_cells_packaged = 0;
+/** How many bytes of data have we put in relay_data cells have we built,
+ * ever? This would be RELAY_PAYLOAD_SIZE*stats_n_data_cells_packaged if
+ * every relay cell we ever sent were completely full of data. */
+uint64_t stats_n_data_bytes_packaged = 0;
+/** How many relay_data cells have we received, ever? */
+uint64_t stats_n_data_cells_received = 0;
+/** How many bytes of data have we received relay_data cells, ever? This would
+ * be RELAY_PAYLOAD_SIZE*stats_n_data_cells_packaged if every relay cell we
+ * ever received were completely full of data. */
+uint64_t stats_n_data_bytes_received = 0;
+
+/** If <b>conn</b> has an entire relay payload of bytes on its inbuf (or
+ * <b>package_partial</b> is true), and the appropriate package windows aren't
+ * empty, grab a cell and send it down the circuit.
+ *
+ * If *<b>max_cells</b> is given, package no more than max_cells. Decrement
+ * *<b>max_cells</b> by the number of cells packaged.
+ *
+ * Return -1 (and send a RELAY_COMMAND_END cell if necessary) if conn should
+ * be marked for close, else return 0.
+ */
+int
+connection_edge_package_raw_inbuf(edge_connection_t *conn, int package_partial,
+ int *max_cells)
+{
+ size_t bytes_to_process, length;
+ char payload[CELL_PAYLOAD_SIZE];
+ circuit_t *circ;
+ const unsigned domain = conn->base_.type == CONN_TYPE_AP ? LD_APP : LD_EXIT;
+ int sending_from_optimistic = 0;
+ entry_connection_t *entry_conn =
+ conn->base_.type == CONN_TYPE_AP ? EDGE_TO_ENTRY_CONN(conn) : NULL;
+ const int sending_optimistically =
+ entry_conn &&
+ conn->base_.type == CONN_TYPE_AP &&
+ conn->base_.state != AP_CONN_STATE_OPEN;
+ crypt_path_t *cpath_layer = conn->cpath_layer;
+
+ tor_assert(conn);
+
+ if (conn->base_.marked_for_close) {
+ log_warn(LD_BUG,
+ "called on conn that's already marked for close at %s:%d.",
+ conn->base_.marked_for_close_file, conn->base_.marked_for_close);
+ return 0;
+ }
+
+ if (max_cells && *max_cells <= 0)
+ return 0;
+
+ repeat_connection_edge_package_raw_inbuf:
+
+ circ = circuit_get_by_edge_conn(conn);
+ if (!circ) {
+ log_info(domain,"conn has no circuit! Closing.");
+ conn->end_reason = END_STREAM_REASON_CANT_ATTACH;
+ return -1;
+ }
+
+ if (circuit_consider_stop_edge_reading(circ, cpath_layer))
+ return 0;
+
+ if (conn->package_window <= 0) {
+ log_info(domain,"called with package_window %d. Skipping.",
+ conn->package_window);
+ connection_stop_reading(TO_CONN(conn));
+ return 0;
+ }
+
+ sending_from_optimistic = entry_conn &&
+ entry_conn->sending_optimistic_data != NULL;
+
+ if (PREDICT_UNLIKELY(sending_from_optimistic)) {
+ bytes_to_process = buf_datalen(entry_conn->sending_optimistic_data);
+ if (PREDICT_UNLIKELY(!bytes_to_process)) {
+ log_warn(LD_BUG, "sending_optimistic_data was non-NULL but empty");
+ bytes_to_process = connection_get_inbuf_len(TO_CONN(conn));
+ sending_from_optimistic = 0;
+ }
+ } else {
+ bytes_to_process = connection_get_inbuf_len(TO_CONN(conn));
+ }
+
+ if (!bytes_to_process)
+ return 0;
+
+ if (!package_partial && bytes_to_process < RELAY_PAYLOAD_SIZE)
+ return 0;
+
+ if (bytes_to_process > RELAY_PAYLOAD_SIZE) {
+ length = RELAY_PAYLOAD_SIZE;
+ } else {
+ length = bytes_to_process;
+ }
+ stats_n_data_bytes_packaged += length;
+ stats_n_data_cells_packaged += 1;
+
+ if (PREDICT_UNLIKELY(sending_from_optimistic)) {
+ /* XXXX We could be more efficient here by sometimes packing
+ * previously-sent optimistic data in the same cell with data
+ * from the inbuf. */
+ buf_get_bytes(entry_conn->sending_optimistic_data, payload, length);
+ if (!buf_datalen(entry_conn->sending_optimistic_data)) {
+ buf_free(entry_conn->sending_optimistic_data);
+ entry_conn->sending_optimistic_data = NULL;
+ }
+ } else {
+ connection_buf_get_bytes(payload, length, TO_CONN(conn));
+ }
+
+ log_debug(domain,TOR_SOCKET_T_FORMAT": Packaging %d bytes (%d waiting).",
+ conn->base_.s,
+ (int)length, (int)connection_get_inbuf_len(TO_CONN(conn)));
+
+ if (sending_optimistically && !sending_from_optimistic) {
+ /* This is new optimistic data; remember it in case we need to detach and
+ retry */
+ if (!entry_conn->pending_optimistic_data)
+ entry_conn->pending_optimistic_data = buf_new();
+ buf_add(entry_conn->pending_optimistic_data, payload, length);
+ }
+
+ if (connection_edge_send_command(conn, RELAY_COMMAND_DATA,
+ payload, length) < 0 ) {
+ /* circuit got marked for close, don't continue, don't need to mark conn */
+ return 0;
+ }
+
+ if (!cpath_layer) { /* non-rendezvous exit */
+ tor_assert(circ->package_window > 0);
+ circ->package_window--;
+ } else { /* we're an AP, or an exit on a rendezvous circ */
+ tor_assert(cpath_layer->package_window > 0);
+ cpath_layer->package_window--;
+ }
+
+ if (--conn->package_window <= 0) { /* is it 0 after decrement? */
+ connection_stop_reading(TO_CONN(conn));
+ log_debug(domain,"conn->package_window reached 0.");
+ circuit_consider_stop_edge_reading(circ, cpath_layer);
+ return 0; /* don't process the inbuf any more */
+ }
+ log_debug(domain,"conn->package_window is now %d",conn->package_window);
+
+ if (max_cells) {
+ *max_cells -= 1;
+ if (*max_cells <= 0)
+ return 0;
+ }
+
+ /* handle more if there's more, or return 0 if there isn't */
+ goto repeat_connection_edge_package_raw_inbuf;
+}
+
+/** Called when we've just received a relay data cell, when
+ * we've just finished flushing all bytes to stream <b>conn</b>,
+ * or when we've flushed *some* bytes to the stream <b>conn</b>.
+ *
+ * If conn->outbuf is not too full, and our deliver window is
+ * low, send back a suitable number of stream-level sendme cells.
+ */
+void
+connection_edge_consider_sending_sendme(edge_connection_t *conn)
+{
+ circuit_t *circ;
+
+ if (connection_outbuf_too_full(TO_CONN(conn)))
+ return;
+
+ circ = circuit_get_by_edge_conn(conn);
+ if (!circ) {
+ /* this can legitimately happen if the destroy has already
+ * arrived and torn down the circuit */
+ log_info(LD_APP,"No circuit associated with conn. Skipping.");
+ return;
+ }
+
+ while (conn->deliver_window <= STREAMWINDOW_START - STREAMWINDOW_INCREMENT) {
+ log_debug(conn->base_.type == CONN_TYPE_AP ?LD_APP:LD_EXIT,
+ "Outbuf %d, Queuing stream sendme.",
+ (int)conn->base_.outbuf_flushlen);
+ conn->deliver_window += STREAMWINDOW_INCREMENT;
+ if (connection_edge_send_command(conn, RELAY_COMMAND_SENDME,
+ NULL, 0) < 0) {
+ log_warn(LD_APP,"connection_edge_send_command failed. Skipping.");
+ return; /* the circuit's closed, don't continue */
+ }
+ }
+}
+
+/** The circuit <b>circ</b> has received a circuit-level sendme
+ * (on hop <b>layer_hint</b>, if we're the OP). Go through all the
+ * attached streams and let them resume reading and packaging, if
+ * their stream windows allow it.
+ */
+static void
+circuit_resume_edge_reading(circuit_t *circ, crypt_path_t *layer_hint)
+{
+ if (circuit_queue_streams_are_blocked(circ)) {
+ log_debug(layer_hint?LD_APP:LD_EXIT,"Too big queue, no resuming");
+ return;
+ }
+ log_debug(layer_hint?LD_APP:LD_EXIT,"resuming");
+
+ if (CIRCUIT_IS_ORIGIN(circ))
+ circuit_resume_edge_reading_helper(TO_ORIGIN_CIRCUIT(circ)->p_streams,
+ circ, layer_hint);
+ else
+ circuit_resume_edge_reading_helper(TO_OR_CIRCUIT(circ)->n_streams,
+ circ, layer_hint);
+}
+
+void
+stream_choice_seed_weak_rng(void)
+{
+ crypto_seed_weak_rng(&stream_choice_rng);
+}
+
+/** A helper function for circuit_resume_edge_reading() above.
+ * The arguments are the same, except that <b>conn</b> is the head
+ * of a linked list of edge streams that should each be considered.
+ */
+static int
+circuit_resume_edge_reading_helper(edge_connection_t *first_conn,
+ circuit_t *circ,
+ crypt_path_t *layer_hint)
+{
+ edge_connection_t *conn;
+ int n_packaging_streams, n_streams_left;
+ int packaged_this_round;
+ int cells_on_queue;
+ int cells_per_conn;
+ edge_connection_t *chosen_stream = NULL;
+ int max_to_package;
+
+ if (first_conn == NULL) {
+ /* Don't bother to try to do the rest of this if there are no connections
+ * to resume. */
+ return 0;
+ }
+
+ /* How many cells do we have space for? It will be the minimum of
+ * the number needed to exhaust the package window, and the minimum
+ * needed to fill the cell queue. */
+ max_to_package = circ->package_window;
+ if (CIRCUIT_IS_ORIGIN(circ)) {
+ cells_on_queue = circ->n_chan_cells.n;
+ } else {
+ or_circuit_t *or_circ = TO_OR_CIRCUIT(circ);
+ cells_on_queue = or_circ->p_chan_cells.n;
+ }
+ if (CELL_QUEUE_HIGHWATER_SIZE - cells_on_queue < max_to_package)
+ max_to_package = CELL_QUEUE_HIGHWATER_SIZE - cells_on_queue;
+
+ /* Once we used to start listening on the streams in the order they
+ * appeared in the linked list. That leads to starvation on the
+ * streams that appeared later on the list, since the first streams
+ * would always get to read first. Instead, we just pick a random
+ * stream on the list, and enable reading for streams starting at that
+ * point (and wrapping around as if the list were circular). It would
+ * probably be better to actually remember which streams we've
+ * serviced in the past, but this is simple and effective. */
+
+ /* Select a stream uniformly at random from the linked list. We
+ * don't need cryptographic randomness here. */
+ {
+ int num_streams = 0;
+ for (conn = first_conn; conn; conn = conn->next_stream) {
+ num_streams++;
+ if (tor_weak_random_one_in_n(&stream_choice_rng, num_streams)) {
+ chosen_stream = conn;
+ }
+ /* Invariant: chosen_stream has been chosen uniformly at random from
+ * among the first num_streams streams on first_conn.
+ *
+ * (Note that we iterate over every stream on the circuit, so that after
+ * we've considered the first stream, we've chosen it with P=1; and
+ * after we consider the second stream, we've switched to it with P=1/2
+ * and stayed with the first stream with P=1/2; and after we've
+ * considered the third stream, we've switched to it with P=1/3 and
+ * remained with one of the first two streams with P=(2/3), giving each
+ * one P=(1/2)(2/3) )=(1/3).) */
+ }
+ }
+
+ /* Count how many non-marked streams there are that have anything on
+ * their inbuf, and enable reading on all of the connections. */
+ n_packaging_streams = 0;
+ /* Activate reading starting from the chosen stream */
+ for (conn=chosen_stream; conn; conn = conn->next_stream) {
+ /* Start reading for the streams starting from here */
+ if (conn->base_.marked_for_close || conn->package_window <= 0)
+ continue;
+ if (!layer_hint || conn->cpath_layer == layer_hint) {
+ connection_start_reading(TO_CONN(conn));
+
+ if (connection_get_inbuf_len(TO_CONN(conn)) > 0)
+ ++n_packaging_streams;
+ }
+ }
+ /* Go back and do the ones we skipped, circular-style */
+ for (conn = first_conn; conn != chosen_stream; conn = conn->next_stream) {
+ if (conn->base_.marked_for_close || conn->package_window <= 0)
+ continue;
+ if (!layer_hint || conn->cpath_layer == layer_hint) {
+ connection_start_reading(TO_CONN(conn));
+
+ if (connection_get_inbuf_len(TO_CONN(conn)) > 0)
+ ++n_packaging_streams;
+ }
+ }
+
+ if (n_packaging_streams == 0) /* avoid divide-by-zero */
+ return 0;
+
+ again:
+
+ cells_per_conn = CEIL_DIV(max_to_package, n_packaging_streams);
+
+ packaged_this_round = 0;
+ n_streams_left = 0;
+
+ /* Iterate over all connections. Package up to cells_per_conn cells on
+ * each. Update packaged_this_round with the total number of cells
+ * packaged, and n_streams_left with the number that still have data to
+ * package.
+ */
+ for (conn=first_conn; conn; conn=conn->next_stream) {
+ if (conn->base_.marked_for_close || conn->package_window <= 0)
+ continue;
+ if (!layer_hint || conn->cpath_layer == layer_hint) {
+ int n = cells_per_conn, r;
+ /* handle whatever might still be on the inbuf */
+ r = connection_edge_package_raw_inbuf(conn, 1, &n);
+
+ /* Note how many we packaged */
+ packaged_this_round += (cells_per_conn-n);
+
+ if (r<0) {
+ /* Problem while packaging. (We already sent an end cell if
+ * possible) */
+ connection_mark_for_close(TO_CONN(conn));
+ continue;
+ }
+
+ /* If there's still data to read, we'll be coming back to this stream. */
+ if (connection_get_inbuf_len(TO_CONN(conn)))
+ ++n_streams_left;
+
+ /* If the circuit won't accept any more data, return without looking
+ * at any more of the streams. Any connections that should be stopped
+ * have already been stopped by connection_edge_package_raw_inbuf. */
+ if (circuit_consider_stop_edge_reading(circ, layer_hint))
+ return -1;
+ /* XXXX should we also stop immediately if we fill up the cell queue?
+ * Probably. */
+ }
+ }
+
+ /* If we made progress, and we are willing to package more, and there are
+ * any streams left that want to package stuff... try again!
+ */
+ if (packaged_this_round && packaged_this_round < max_to_package &&
+ n_streams_left) {
+ max_to_package -= packaged_this_round;
+ n_packaging_streams = n_streams_left;
+ goto again;
+ }
+
+ return 0;
+}
+
+/** Check if the package window for <b>circ</b> is empty (at
+ * hop <b>layer_hint</b> if it's defined).
+ *
+ * If yes, tell edge streams to stop reading and return 1.
+ * Else return 0.
+ */
+static int
+circuit_consider_stop_edge_reading(circuit_t *circ, crypt_path_t *layer_hint)
+{
+ edge_connection_t *conn = NULL;
+ unsigned domain = layer_hint ? LD_APP : LD_EXIT;
+
+ if (!layer_hint) {
+ or_circuit_t *or_circ = TO_OR_CIRCUIT(circ);
+ log_debug(domain,"considering circ->package_window %d",
+ circ->package_window);
+ if (circ->package_window <= 0) {
+ log_debug(domain,"yes, not-at-origin. stopped.");
+ for (conn = or_circ->n_streams; conn; conn=conn->next_stream)
+ connection_stop_reading(TO_CONN(conn));
+ return 1;
+ }
+ return 0;
+ }
+ /* else, layer hint is defined, use it */
+ log_debug(domain,"considering layer_hint->package_window %d",
+ layer_hint->package_window);
+ if (layer_hint->package_window <= 0) {
+ log_debug(domain,"yes, at-origin. stopped.");
+ for (conn = TO_ORIGIN_CIRCUIT(circ)->p_streams; conn;
+ conn=conn->next_stream) {
+ if (conn->cpath_layer == layer_hint)
+ connection_stop_reading(TO_CONN(conn));
+ }
+ return 1;
+ }
+ return 0;
+}
+
+/** Check if the deliver_window for circuit <b>circ</b> (at hop
+ * <b>layer_hint</b> if it's defined) is low enough that we should
+ * send a circuit-level sendme back down the circuit. If so, send
+ * enough sendmes that the window would be overfull if we sent any
+ * more.
+ */
+static void
+circuit_consider_sending_sendme(circuit_t *circ, crypt_path_t *layer_hint)
+{
+// log_fn(LOG_INFO,"Considering: layer_hint is %s",
+// layer_hint ? "defined" : "null");
+ while ((layer_hint ? layer_hint->deliver_window : circ->deliver_window) <=
+ CIRCWINDOW_START - CIRCWINDOW_INCREMENT) {
+ log_debug(LD_CIRC,"Queuing circuit sendme.");
+ if (layer_hint)
+ layer_hint->deliver_window += CIRCWINDOW_INCREMENT;
+ else
+ circ->deliver_window += CIRCWINDOW_INCREMENT;
+ if (relay_send_command_from_edge(0, circ, RELAY_COMMAND_SENDME,
+ NULL, 0, layer_hint) < 0) {
+ log_warn(LD_CIRC,
+ "relay_send_command_from_edge failed. Circuit's closed.");
+ return; /* the circuit's closed, don't continue */
+ }
+ }
+}
+
+/** The total number of cells we have allocated. */
+static size_t total_cells_allocated = 0;
+
+/** Release storage held by <b>cell</b>. */
+static inline void
+packed_cell_free_unchecked(packed_cell_t *cell)
+{
+ --total_cells_allocated;
+ tor_free(cell);
+}
+
+/** Allocate and return a new packed_cell_t. */
+STATIC packed_cell_t *
+packed_cell_new(void)
+{
+ ++total_cells_allocated;
+ return tor_malloc_zero(sizeof(packed_cell_t));
+}
+
+/** Return a packed cell used outside by channel_t lower layer */
+void
+packed_cell_free_(packed_cell_t *cell)
+{
+ if (!cell)
+ return;
+ packed_cell_free_unchecked(cell);
+}
+
+/** Log current statistics for cell pool allocation at log level
+ * <b>severity</b>. */
+void
+dump_cell_pool_usage(int severity)
+{
+ int n_circs = 0;
+ int n_cells = 0;
+ SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, c) {
+ n_cells += c->n_chan_cells.n;
+ if (!CIRCUIT_IS_ORIGIN(c))
+ n_cells += TO_OR_CIRCUIT(c)->p_chan_cells.n;
+ ++n_circs;
+ }
+ SMARTLIST_FOREACH_END(c);
+ tor_log(severity, LD_MM,
+ "%d cells allocated on %d circuits. %d cells leaked.",
+ n_cells, n_circs, (int)total_cells_allocated - n_cells);
+}
+
+/** Allocate a new copy of packed <b>cell</b>. */
+static inline packed_cell_t *
+packed_cell_copy(const cell_t *cell, int wide_circ_ids)
+{
+ packed_cell_t *c = packed_cell_new();
+ cell_pack(c, cell, wide_circ_ids);
+ return c;
+}
+
+/** Append <b>cell</b> to the end of <b>queue</b>. */
+void
+cell_queue_append(cell_queue_t *queue, packed_cell_t *cell)
+{
+ TOR_SIMPLEQ_INSERT_TAIL(&queue->head, cell, next);
+ ++queue->n;
+}
+
+/** Append a newly allocated copy of <b>cell</b> to the end of the
+ * <b>exitward</b> (or app-ward) <b>queue</b> of <b>circ</b>. If
+ * <b>use_stats</b> is true, record statistics about the cell.
+ */
+void
+cell_queue_append_packed_copy(circuit_t *circ, cell_queue_t *queue,
+ int exitward, const cell_t *cell,
+ int wide_circ_ids, int use_stats)
+{
+ packed_cell_t *copy = packed_cell_copy(cell, wide_circ_ids);
+ (void)circ;
+ (void)exitward;
+ (void)use_stats;
+
+ copy->inserted_timestamp = monotime_coarse_get_stamp();
+
+ cell_queue_append(queue, copy);
+}
+
+/** Initialize <b>queue</b> as an empty cell queue. */
+void
+cell_queue_init(cell_queue_t *queue)
+{
+ memset(queue, 0, sizeof(cell_queue_t));
+ TOR_SIMPLEQ_INIT(&queue->head);
+}
+
+/** Remove and free every cell in <b>queue</b>. */
+void
+cell_queue_clear(cell_queue_t *queue)
+{
+ packed_cell_t *cell;
+ while ((cell = TOR_SIMPLEQ_FIRST(&queue->head))) {
+ TOR_SIMPLEQ_REMOVE_HEAD(&queue->head, next);
+ packed_cell_free_unchecked(cell);
+ }
+ TOR_SIMPLEQ_INIT(&queue->head);
+ queue->n = 0;
+}
+
+/** Extract and return the cell at the head of <b>queue</b>; return NULL if
+ * <b>queue</b> is empty. */
+STATIC packed_cell_t *
+cell_queue_pop(cell_queue_t *queue)
+{
+ packed_cell_t *cell = TOR_SIMPLEQ_FIRST(&queue->head);
+ if (!cell)
+ return NULL;
+ TOR_SIMPLEQ_REMOVE_HEAD(&queue->head, next);
+ --queue->n;
+ return cell;
+}
+
+/** Initialize <b>queue</b> as an empty cell queue. */
+void
+destroy_cell_queue_init(destroy_cell_queue_t *queue)
+{
+ memset(queue, 0, sizeof(destroy_cell_queue_t));
+ TOR_SIMPLEQ_INIT(&queue->head);
+}
+
+/** Remove and free every cell in <b>queue</b>. */
+void
+destroy_cell_queue_clear(destroy_cell_queue_t *queue)
+{
+ destroy_cell_t *cell;
+ while ((cell = TOR_SIMPLEQ_FIRST(&queue->head))) {
+ TOR_SIMPLEQ_REMOVE_HEAD(&queue->head, next);
+ tor_free(cell);
+ }
+ TOR_SIMPLEQ_INIT(&queue->head);
+ queue->n = 0;
+}
+
+/** Extract and return the cell at the head of <b>queue</b>; return NULL if
+ * <b>queue</b> is empty. */
+STATIC destroy_cell_t *
+destroy_cell_queue_pop(destroy_cell_queue_t *queue)
+{
+ destroy_cell_t *cell = TOR_SIMPLEQ_FIRST(&queue->head);
+ if (!cell)
+ return NULL;
+ TOR_SIMPLEQ_REMOVE_HEAD(&queue->head, next);
+ --queue->n;
+ return cell;
+}
+
+/** Append a destroy cell for <b>circid</b> to <b>queue</b>. */
+void
+destroy_cell_queue_append(destroy_cell_queue_t *queue,
+ circid_t circid,
+ uint8_t reason)
+{
+ destroy_cell_t *cell = tor_malloc_zero(sizeof(destroy_cell_t));
+ cell->circid = circid;
+ cell->reason = reason;
+ /* Not yet used, but will be required for OOM handling. */
+ cell->inserted_timestamp = monotime_coarse_get_stamp();
+
+ TOR_SIMPLEQ_INSERT_TAIL(&queue->head, cell, next);
+ ++queue->n;
+}
+
+/** Convert a destroy_cell_t to a newly allocated cell_t. Frees its input. */
+static packed_cell_t *
+destroy_cell_to_packed_cell(destroy_cell_t *inp, int wide_circ_ids)
+{
+ packed_cell_t *packed = packed_cell_new();
+ cell_t cell;
+ memset(&cell, 0, sizeof(cell));
+ cell.circ_id = inp->circid;
+ cell.command = CELL_DESTROY;
+ cell.payload[0] = inp->reason;
+ cell_pack(packed, &cell, wide_circ_ids);
+
+ tor_free(inp);
+ return packed;
+}
+
+/** Return the total number of bytes used for each packed_cell in a queue.
+ * Approximate. */
+size_t
+packed_cell_mem_cost(void)
+{
+ return sizeof(packed_cell_t);
+}
+
+/* DOCDOC */
+size_t
+cell_queues_get_total_allocation(void)
+{
+ return total_cells_allocated * packed_cell_mem_cost();
+}
+
+/** How long after we've been low on memory should we try to conserve it? */
+#define MEMORY_PRESSURE_INTERVAL (30*60)
+
+/** The time at which we were last low on memory. */
+static time_t last_time_under_memory_pressure = 0;
+
+/** Check whether we've got too much space used for cells. If so,
+ * call the OOM handler and return 1. Otherwise, return 0. */
+STATIC int
+cell_queues_check_size(void)
+{
+ time_t now = time(NULL);
+ size_t alloc = cell_queues_get_total_allocation();
++ alloc += half_streams_get_total_allocation();
+ alloc += buf_get_total_allocation();
+ alloc += tor_compress_get_total_allocation();
+ const size_t rend_cache_total = rend_cache_get_total_allocation();
+ alloc += rend_cache_total;
+ const size_t geoip_client_cache_total =
+ geoip_client_cache_total_allocation();
+ alloc += geoip_client_cache_total;
+ const size_t dns_cache_total = dns_cache_total_allocation();
+ alloc += dns_cache_total;
+ if (alloc >= get_options()->MaxMemInQueues_low_threshold) {
+ last_time_under_memory_pressure = approx_time();
+ if (alloc >= get_options()->MaxMemInQueues) {
+ /* If we're spending over 20% of the memory limit on hidden service
+ * descriptors, free them until we're down to 10%. Do the same for geoip
+ * client cache. */
+ if (rend_cache_total > get_options()->MaxMemInQueues / 5) {
+ const size_t bytes_to_remove =
+ rend_cache_total - (size_t)(get_options()->MaxMemInQueues / 10);
+ alloc -= hs_cache_handle_oom(now, bytes_to_remove);
+ }
+ if (geoip_client_cache_total > get_options()->MaxMemInQueues / 5) {
+ const size_t bytes_to_remove =
+ geoip_client_cache_total -
+ (size_t)(get_options()->MaxMemInQueues / 10);
+ alloc -= geoip_client_cache_handle_oom(now, bytes_to_remove);
+ }
+ if (dns_cache_total > get_options()->MaxMemInQueues / 5) {
+ const size_t bytes_to_remove =
+ dns_cache_total - (size_t)(get_options()->MaxMemInQueues / 10);
+ alloc -= dns_cache_handle_oom(now, bytes_to_remove);
+ }
+ circuits_handle_oom(alloc);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/** Return true if we've been under memory pressure in the last
+ * MEMORY_PRESSURE_INTERVAL seconds. */
+int
+have_been_under_memory_pressure(void)
+{
+ return last_time_under_memory_pressure + MEMORY_PRESSURE_INTERVAL
+ < approx_time();
+}
+
+/**
+ * Update the number of cells available on the circuit's n_chan or p_chan's
+ * circuit mux.
+ */
+void
+update_circuit_on_cmux_(circuit_t *circ, cell_direction_t direction,
+ const char *file, int lineno)
+{
+ channel_t *chan = NULL;
+ or_circuit_t *or_circ = NULL;
+ circuitmux_t *cmux = NULL;
+
+ tor_assert(circ);
+
+ /* Okay, get the channel */
+ if (direction == CELL_DIRECTION_OUT) {
+ chan = circ->n_chan;
+ } else {
+ or_circ = TO_OR_CIRCUIT(circ);
+ chan = or_circ->p_chan;
+ }
+
+ tor_assert(chan);
+ tor_assert(chan->cmux);
+
+ /* Now get the cmux */
+ cmux = chan->cmux;
+
+ /* Cmux sanity check */
+ if (! circuitmux_is_circuit_attached(cmux, circ)) {
+ log_warn(LD_BUG, "called on non-attached circuit from %s:%d",
+ file, lineno);
+ return;
+ }
+ tor_assert(circuitmux_attached_circuit_direction(cmux, circ) == direction);
+
+ /* Update the number of cells we have for the circuit mux */
+ if (direction == CELL_DIRECTION_OUT) {
+ circuitmux_set_num_cells(cmux, circ, circ->n_chan_cells.n);
+ } else {
+ circuitmux_set_num_cells(cmux, circ, or_circ->p_chan_cells.n);
+ }
+}
+
+/** Remove all circuits from the cmux on <b>chan</b>.
+ *
+ * If <b>circuits_out</b> is non-NULL, add all detached circuits to
+ * <b>circuits_out</b>.
+ **/
+void
+channel_unlink_all_circuits(channel_t *chan, smartlist_t *circuits_out)
+{
+ tor_assert(chan);
+ tor_assert(chan->cmux);
+
+ circuitmux_detach_all_circuits(chan->cmux, circuits_out);
+ chan->num_n_circuits = 0;
+ chan->num_p_circuits = 0;
+}
+
+/** Block (if <b>block</b> is true) or unblock (if <b>block</b> is false)
+ * every edge connection that is using <b>circ</b> to write to <b>chan</b>,
+ * and start or stop reading as appropriate.
+ *
+ * If <b>stream_id</b> is nonzero, block only the edge connection whose
+ * stream_id matches it.
+ *
+ * Returns the number of streams whose status we changed.
+ */
+static int
+set_streams_blocked_on_circ(circuit_t *circ, channel_t *chan,
+ int block, streamid_t stream_id)
+{
+ edge_connection_t *edge = NULL;
+ int n = 0;
+ if (circ->n_chan == chan) {
+ circ->streams_blocked_on_n_chan = block;
+ if (CIRCUIT_IS_ORIGIN(circ))
+ edge = TO_ORIGIN_CIRCUIT(circ)->p_streams;
+ } else {
+ circ->streams_blocked_on_p_chan = block;
+ tor_assert(!CIRCUIT_IS_ORIGIN(circ));
+ edge = TO_OR_CIRCUIT(circ)->n_streams;
+ }
+
+ for (; edge; edge = edge->next_stream) {
+ connection_t *conn = TO_CONN(edge);
+ if (stream_id && edge->stream_id != stream_id)
+ continue;
+
+ if (edge->edge_blocked_on_circ != block) {
+ ++n;
+ edge->edge_blocked_on_circ = block;
+ }
+
+ if (!conn->read_event) {
+ /* This connection is a placeholder for something; probably a DNS
+ * request. It can't actually stop or start reading.*/
+ continue;
+ }
+
+ if (block) {
+ if (connection_is_reading(conn))
+ connection_stop_reading(conn);
+ } else {
+ /* Is this right? */
+ if (!connection_is_reading(conn))
+ connection_start_reading(conn);
+ }
+ }
+
+ return n;
+}
+
+/** Extract the command from a packed cell. */
+static uint8_t
+packed_cell_get_command(const packed_cell_t *cell, int wide_circ_ids)
+{
+ if (wide_circ_ids) {
+ return get_uint8(cell->body+4);
+ } else {
+ return get_uint8(cell->body+2);
+ }
+}
+
+/** Extract the circuit ID from a packed cell. */
+circid_t
+packed_cell_get_circid(const packed_cell_t *cell, int wide_circ_ids)
+{
+ if (wide_circ_ids) {
+ return ntohl(get_uint32(cell->body));
+ } else {
+ return ntohs(get_uint16(cell->body));
+ }
+}
+
+/** Pull as many cells as possible (but no more than <b>max</b>) from the
+ * queue of the first active circuit on <b>chan</b>, and write them to
+ * <b>chan</b>->outbuf. Return the number of cells written. Advance
+ * the active circuit pointer to the next active circuit in the ring. */
+MOCK_IMPL(int,
+channel_flush_from_first_active_circuit, (channel_t *chan, int max))
+{
+ circuitmux_t *cmux = NULL;
+ int n_flushed = 0;
+ cell_queue_t *queue;
+ destroy_cell_queue_t *destroy_queue=NULL;
+ circuit_t *circ;
+ or_circuit_t *or_circ;
+ int streams_blocked;
+ packed_cell_t *cell;
+
+ /* Get the cmux */
+ tor_assert(chan);
+ tor_assert(chan->cmux);
+ cmux = chan->cmux;
+
+ /* Main loop: pick a circuit, send a cell, update the cmux */
+ while (n_flushed < max) {
+ circ = circuitmux_get_first_active_circuit(cmux, &destroy_queue);
+ if (destroy_queue) {
+ destroy_cell_t *dcell;
+ /* this code is duplicated from some of the logic below. Ugly! XXXX */
+ /* If we are given a destroy_queue here, then it is required to be
+ * nonempty... */
+ tor_assert(destroy_queue->n > 0);
+ dcell = destroy_cell_queue_pop(destroy_queue);
+ /* ...and pop() will always yield a cell from a nonempty queue. */
+ tor_assert(dcell);
+ /* frees dcell */
+ cell = destroy_cell_to_packed_cell(dcell, chan->wide_circ_ids);
+ /* Send the DESTROY cell. It is very unlikely that this fails but just
+ * in case, get rid of the channel. */
+ if (channel_write_packed_cell(chan, cell) < 0) {
+ /* The cell has been freed. */
+ channel_mark_for_close(chan);
+ continue;
+ }
+ /* Update the cmux destroy counter */
+ circuitmux_notify_xmit_destroy(cmux);
+ cell = NULL;
+ ++n_flushed;
+ continue;
+ }
+ /* If it returns NULL, no cells left to send */
+ if (!circ) break;
+
+ if (circ->n_chan == chan) {
+ queue = &circ->n_chan_cells;
+ streams_blocked = circ->streams_blocked_on_n_chan;
+ } else {
+ or_circ = TO_OR_CIRCUIT(circ);
+ tor_assert(or_circ->p_chan == chan);
+ queue = &TO_OR_CIRCUIT(circ)->p_chan_cells;
+ streams_blocked = circ->streams_blocked_on_p_chan;
+ }
+
+ /* Circuitmux told us this was active, so it should have cells */
+ if (/*BUG(*/ queue->n == 0 /*)*/) {
+ log_warn(LD_BUG, "Found a supposedly active circuit with no cells "
+ "to send. Trying to recover.");
+ circuitmux_set_num_cells(cmux, circ, 0);
+ if (! circ->marked_for_close)
+ circuit_mark_for_close(circ, END_CIRC_REASON_INTERNAL);
+ continue;
+ }
+
+ tor_assert(queue->n > 0);
+
+ /*
+ * Get just one cell here; once we've sent it, that can change the circuit
+ * selection, so we have to loop around for another even if this circuit
+ * has more than one.
+ */
+ cell = cell_queue_pop(queue);
+
+ /* Calculate the exact time that this cell has spent in the queue. */
+ if (get_options()->CellStatistics ||
+ get_options()->TestingEnableCellStatsEvent) {
+ uint32_t timestamp_now = monotime_coarse_get_stamp();
+ uint32_t msec_waiting =
+ (uint32_t) monotime_coarse_stamp_units_to_approx_msec(
+ timestamp_now - cell->inserted_timestamp);
+
+ if (get_options()->CellStatistics && !CIRCUIT_IS_ORIGIN(circ)) {
+ or_circ = TO_OR_CIRCUIT(circ);
+ or_circ->total_cell_waiting_time += msec_waiting;
+ or_circ->processed_cells++;
+ }
+
+ if (get_options()->TestingEnableCellStatsEvent) {
+ uint8_t command = packed_cell_get_command(cell, chan->wide_circ_ids);
+
+ testing_cell_stats_entry_t *ent =
+ tor_malloc_zero(sizeof(testing_cell_stats_entry_t));
+ ent->command = command;
+ ent->waiting_time = msec_waiting / 10;
+ ent->removed = 1;
+ if (circ->n_chan == chan)
+ ent->exitward = 1;
+ if (!circ->testing_cell_stats)
+ circ->testing_cell_stats = smartlist_new();
+ smartlist_add(circ->testing_cell_stats, ent);
+ }
+ }
+
+ /* If we just flushed our queue and this circuit is used for a
+ * tunneled directory request, possibly advance its state. */
+ if (queue->n == 0 && chan->dirreq_id)
+ geoip_change_dirreq_state(chan->dirreq_id,
+ DIRREQ_TUNNELED,
+ DIRREQ_CIRC_QUEUE_FLUSHED);
+
+ /* Now send the cell. It is very unlikely that this fails but just in
+ * case, get rid of the channel. */
+ if (channel_write_packed_cell(chan, cell) < 0) {
+ /* The cell has been freed at this point. */
+ channel_mark_for_close(chan);
+ continue;
+ }
+ cell = NULL;
+
+ /*
+ * Don't packed_cell_free_unchecked(cell) here because the channel will
+ * do so when it gets out of the channel queue (probably already did, in
+ * which case that was an immediate double-free bug).
+ */
+
+ /* Update the counter */
+ ++n_flushed;
+
+ /*
+ * Now update the cmux; tell it we've just sent a cell, and how many
+ * we have left.
+ */
+ circuitmux_notify_xmit_cells(cmux, circ, 1);
+ circuitmux_set_num_cells(cmux, circ, queue->n);
+ if (queue->n == 0)
+ log_debug(LD_GENERAL, "Made a circuit inactive.");
+
+ /* Is the cell queue low enough to unblock all the streams that are waiting
+ * to write to this circuit? */
+ if (streams_blocked && queue->n <= CELL_QUEUE_LOWWATER_SIZE)
+ set_streams_blocked_on_circ(circ, chan, 0, 0); /* unblock streams */
+
+ /* If n_flushed < max still, loop around and pick another circuit */
+ }
+
+ /* Okay, we're done sending now */
+ return n_flushed;
+}
+
+/* Minimum value is the maximum circuit window size.
+ *
+ * SENDME cells makes it that we can control how many cells can be inflight on
+ * a circuit from end to end. This logic makes it that on any circuit cell
+ * queue, we have a maximum of cells possible.
+ *
+ * Because the Tor protocol allows for a client to exit at any hop in a
+ * circuit and a circuit can be of a maximum of 8 hops, so in theory the
+ * normal worst case will be the circuit window start value times the maximum
+ * number of hops (8). Having more cells then that means something is wrong.
+ *
+ * However, because padding cells aren't counted in the package window, we set
+ * the maximum size to a reasonably large size for which we expect that we'll
+ * never reach in theory. And if we ever do because of future changes, we'll
+ * be able to control it with a consensus parameter.
+ *
+ * XXX: Unfortunately, END cells aren't accounted for in the circuit window
+ * which means that for instance if a client opens 8001 streams, the 8001
+ * following END cells will queue up in the circuit which will get closed if
+ * the max limit is 8000. Which is sad because it is allowed by the Tor
+ * protocol. But, we need an upper bound on circuit queue in order to avoid
+ * DoS memory pressure so the default size is a middle ground between not
+ * having any limit and having a very restricted one. This is why we can also
+ * control it through a consensus parameter. */
+#define RELAY_CIRC_CELL_QUEUE_SIZE_MIN CIRCWINDOW_START_MAX
+/* We can't have a consensus parameter above this value. */
+#define RELAY_CIRC_CELL_QUEUE_SIZE_MAX INT32_MAX
+/* Default value is set to a large value so we can handle padding cells
+ * properly which aren't accounted for in the SENDME window. Default is 50000
+ * allowed cells in the queue resulting in ~25MB. */
+#define RELAY_CIRC_CELL_QUEUE_SIZE_DEFAULT \
+ (50 * RELAY_CIRC_CELL_QUEUE_SIZE_MIN)
+
+/* The maximum number of cell a circuit queue can contain. This is updated at
+ * every new consensus and controlled by a parameter. */
+static int32_t max_circuit_cell_queue_size =
+ RELAY_CIRC_CELL_QUEUE_SIZE_DEFAULT;
+
+/* Called when the consensus has changed. At this stage, the global consensus
+ * object has NOT been updated. It is called from
+ * notify_before_networkstatus_changes(). */
+void
+relay_consensus_has_changed(const networkstatus_t *ns)
+{
+ tor_assert(ns);
+
+ /* Update the circuit max cell queue size from the consensus. */
+ max_circuit_cell_queue_size =
+ networkstatus_get_param(ns, "circ_max_cell_queue_size",
+ RELAY_CIRC_CELL_QUEUE_SIZE_DEFAULT,
+ RELAY_CIRC_CELL_QUEUE_SIZE_MIN,
+ RELAY_CIRC_CELL_QUEUE_SIZE_MAX);
+}
+
+/** Add <b>cell</b> to the queue of <b>circ</b> writing to <b>chan</b>
+ * transmitting in <b>direction</b>.
+ *
+ * The given <b>cell</b> is copied onto the circuit queue so the caller must
+ * cleanup the memory.
+ *
+ * This function is part of the fast path. */
+void
+append_cell_to_circuit_queue(circuit_t *circ, channel_t *chan,
+ cell_t *cell, cell_direction_t direction,
+ streamid_t fromstream)
+{
+ or_circuit_t *orcirc = NULL;
+ cell_queue_t *queue;
+ int streams_blocked;
+ int exitward;
+ if (circ->marked_for_close)
+ return;
+
+ exitward = (direction == CELL_DIRECTION_OUT);
+ if (exitward) {
+ queue = &circ->n_chan_cells;
+ streams_blocked = circ->streams_blocked_on_n_chan;
+ } else {
+ orcirc = TO_OR_CIRCUIT(circ);
+ queue = &orcirc->p_chan_cells;
+ streams_blocked = circ->streams_blocked_on_p_chan;
+ }
+
+ if (PREDICT_UNLIKELY(queue->n >= max_circuit_cell_queue_size)) {
+ log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
+ "%s circuit has %d cells in its queue, maximum allowed is %d. "
+ "Closing circuit for safety reasons.",
+ (exitward) ? "Outbound" : "Inbound", queue->n,
+ max_circuit_cell_queue_size);
+ circuit_mark_for_close(circ, END_CIRC_REASON_RESOURCELIMIT);
+ stats_n_circ_max_cell_reached++;
+ return;
+ }
+
+ /* Very important that we copy to the circuit queue because all calls to
+ * this function use the stack for the cell memory. */
+ cell_queue_append_packed_copy(circ, queue, exitward, cell,
+ chan->wide_circ_ids, 1);
+
+ /* Check and run the OOM if needed. */
+ if (PREDICT_UNLIKELY(cell_queues_check_size())) {
+ /* We ran the OOM handler which might have closed this circuit. */
+ if (circ->marked_for_close)
+ return;
+ }
+
+ /* If we have too many cells on the circuit, we should stop reading from
+ * the edge streams for a while. */
+ if (!streams_blocked && queue->n >= CELL_QUEUE_HIGHWATER_SIZE)
+ set_streams_blocked_on_circ(circ, chan, 1, 0); /* block streams */
+
+ if (streams_blocked && fromstream) {
+ /* This edge connection is apparently not blocked; block it. */
+ set_streams_blocked_on_circ(circ, chan, 1, fromstream);
+ }
+
+ update_circuit_on_cmux(circ, direction);
+ if (queue->n == 1) {
+ /* This was the first cell added to the queue. We just made this
+ * circuit active. */
+ log_debug(LD_GENERAL, "Made a circuit active.");
+ }
+
+ /* New way: mark this as having waiting cells for the scheduler */
+ scheduler_channel_has_waiting_cells(chan);
+}
+
+/** Append an encoded value of <b>addr</b> to <b>payload_out</b>, which must
+ * have at least 18 bytes of free space. The encoding is, as specified in
+ * tor-spec.txt:
+ * RESOLVED_TYPE_IPV4 or RESOLVED_TYPE_IPV6 [1 byte]
+ * LENGTH [1 byte]
+ * ADDRESS [length bytes]
+ * Return the number of bytes added, or -1 on error */
+int
+append_address_to_payload(uint8_t *payload_out, const tor_addr_t *addr)
+{
+ uint32_t a;
+ switch (tor_addr_family(addr)) {
+ case AF_INET:
+ payload_out[0] = RESOLVED_TYPE_IPV4;
+ payload_out[1] = 4;
+ a = tor_addr_to_ipv4n(addr);
+ memcpy(payload_out+2, &a, 4);
+ return 6;
+ case AF_INET6:
+ payload_out[0] = RESOLVED_TYPE_IPV6;
+ payload_out[1] = 16;
+ memcpy(payload_out+2, tor_addr_to_in6_addr8(addr), 16);
+ return 18;
+ case AF_UNSPEC:
+ default:
+ return -1;
+ }
+}
+
+/** Given <b>payload_len</b> bytes at <b>payload</b>, starting with an address
+ * encoded as by append_address_to_payload(), try to decode the address into
+ * *<b>addr_out</b>. Return the next byte in the payload after the address on
+ * success, or NULL on failure. */
+const uint8_t *
+decode_address_from_payload(tor_addr_t *addr_out, const uint8_t *payload,
+ int payload_len)
+{
+ if (payload_len < 2)
+ return NULL;
+ if (payload_len < 2+payload[1])
+ return NULL;
+
+ switch (payload[0]) {
+ case RESOLVED_TYPE_IPV4:
+ if (payload[1] != 4)
+ return NULL;
+ tor_addr_from_ipv4n(addr_out, get_uint32(payload+2));
+ break;
+ case RESOLVED_TYPE_IPV6:
+ if (payload[1] != 16)
+ return NULL;
+ tor_addr_from_ipv6_bytes(addr_out, (char*)(payload+2));
+ break;
+ default:
+ tor_addr_make_unspec(addr_out);
+ break;
+ }
+ return payload + 2 + payload[1];
+}
+
+/** Remove all the cells queued on <b>circ</b> for <b>chan</b>. */
+void
+circuit_clear_cell_queue(circuit_t *circ, channel_t *chan)
+{
+ cell_queue_t *queue;
+ cell_direction_t direction;
+
+ if (circ->n_chan == chan) {
+ queue = &circ->n_chan_cells;
+ direction = CELL_DIRECTION_OUT;
+ } else {
+ or_circuit_t *orcirc = TO_OR_CIRCUIT(circ);
+ tor_assert(orcirc->p_chan == chan);
+ queue = &orcirc->p_chan_cells;
+ direction = CELL_DIRECTION_IN;
+ }
+
+ /* Clear the queue */
+ cell_queue_clear(queue);
+
+ /* Update the cell counter in the cmux */
+ if (chan->cmux && circuitmux_is_circuit_attached(chan->cmux, circ))
+ update_circuit_on_cmux(circ, direction);
+}
+
+/** Return 1 if we shouldn't restart reading on this circuit, even if
+ * we get a SENDME. Else return 0.
+*/
+static int
+circuit_queue_streams_are_blocked(circuit_t *circ)
+{
+ if (CIRCUIT_IS_ORIGIN(circ)) {
+ return circ->streams_blocked_on_n_chan;
+ } else {
+ return circ->streams_blocked_on_p_chan;
+ }
+}
1
0
18 Sep '18
commit 221a3499c76b71a38d0f79f9f64cabebd66e4992
Author: Damian Johnson <atagar(a)torproject.org>
Date: Fri Sep 7 04:03:25 2018 -0700
Missing ORPort descriptor download example
Oops, forgot to add the new example when expanding our tutorial in the last
commit.
---
docs/_static/example/descriptor_from_orport.py | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/docs/_static/example/descriptor_from_orport.py b/docs/_static/example/descriptor_from_orport.py
new file mode 100644
index 00000000..48b0673b
--- /dev/null
+++ b/docs/_static/example/descriptor_from_orport.py
@@ -0,0 +1,14 @@
+import stem.descriptor.remote
+
+# Unlike the above example, this one downloads specifically through the
+# ORPort of moria1 (long time tor directory authority).
+
+try:
+ consensus = stem.descriptor.remote.get_consensus(
+ endpoints = (stem.ORPort('128.31.0.34', 9101),)
+ )
+
+ for desc in consensus:
+ print("found relay %s (%s)" % (desc.nickname, desc.fingerprint))
+except Exception as exc:
+ print("Unable to retrieve the consensus: %s" % exc)
1
0
commit 29e70dfe8af598aa7f54518c92490d32a8a0dd76
Author: Damian Johnson <atagar(a)torproject.org>
Date: Fri Sep 7 03:43:27 2018 -0700
Deprecate stem.descriptor.export
This module was provided by a contributor in stem's early days to export
descriptors as csvs. I've never used it, and aside from that contributor
years ago never heard of anyone else using it either.
Lets propose dropping it and see if anyone would mind. Happy to keep it
if it's useful, but if it isn't seems the very definition of bloat. ;)
---
docs/change_log.rst | 1 +
stem/descriptor/export.py | 5 +++++
2 files changed, 6 insertions(+)
diff --git a/docs/change_log.rst b/docs/change_log.rst
index 9331890c..b91f69b3 100644
--- a/docs/change_log.rst
+++ b/docs/change_log.rst
@@ -79,6 +79,7 @@ The following are only available within Stem's `git repository
* Don't retry downloading descriptors when we've timed out
* Don't download from tor26 and Bifroest, which are authorities that frequently timeout
* `stem.descriptor.remote <api/descriptor/remote.html>`_ now consistently defaults **fall_back_to_authority** to false
+ * Deprecated `stem.descriptor.export <api/descriptor/export.html>`_. If you use it please `let us know <https://www.atagar.com/contact/>`_.
* Added :func:`~stem.descriptor.remote.their_server_descriptor`
* Added the reply_headers attribute to :class:`~stem.descriptor.remote.Query`
* Supplying a User-Agent when downloading descriptors
diff --git a/stem/descriptor/export.py b/stem/descriptor/export.py
index f6d73ebb..c565bfac 100644
--- a/stem/descriptor/export.py
+++ b/stem/descriptor/export.py
@@ -10,6 +10,11 @@ Toolkit for exporting descriptors to other formats.
export_csv - Exports descriptors to a CSV
export_csv_file - Writes exported CSV output to a file
+
+.. deprecated:: 1.7.0
+
+ This module will likely be removed in Stem 2.0 due to lack of usage. If you
+ use this modle please `let me know <https://www.atagar.com/contact/>`_.
"""
import csv
1
0
commit 545abe82f682f4260e1347b7d4a797e223b89ff0
Author: Colin Childs <colin(a)torproject.org>
Date: Tue Sep 18 14:23:13 2018 -0500
Fixing id translation push
---
id/id.po | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/id/id.po b/id/id.po
index 39e0d05..cd90a85 100644
--- a/id/id.po
+++ b/id/id.po
@@ -91,7 +91,7 @@ msgstr ""
#: about-tor-browser.page:50
msgid "How Tor works"
-msgstr "Bagaimana Tor bekerja\n"
+msgstr "Bagaimana Tor bekerja"
#: about-tor-browser.page:52
msgid ""
1
0
commit 8dd53acf68fff044d19b6ec16567592e31774eb0
Author: Colin Childs <colin(a)torproject.org>
Date: Tue Sep 18 14:23:53 2018 -0500
Adding zh-TW translations
---
Makefile.am | 2 +-
zh-TW/zh-TW.po | 1557 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 1558 insertions(+), 1 deletion(-)
diff --git a/Makefile.am b/Makefile.am
index 03d31aa..d08ec37 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -8,7 +8,7 @@ TOR_AND_HTTPS = ../tor-and-https
HELP_ID = tor-browser-user-manual
HELP_FILES = $(shell cd $(srcdir)/C && git ls-files '*.page')
HELP_MEDIA = $(shell cd $(srcdir)/C && git ls-files 'media')
-HELP_LINGUAS = en-US ja sv ga bn_BD id ca @TOR_BROWSER_BUNDLE_LOCALES@
+HELP_LINGUAS = en-US ja sv ga bn_BD id ca zh-TW @TOR_BROWSER_BUNDLE_LOCALES@
.PHONY: html
html: all media-symlinks.stamp
diff --git a/zh-TW/zh-TW.po b/zh-TW/zh-TW.po
new file mode 100644
index 0000000..e9612ed
--- /dev/null
+++ b/zh-TW/zh-TW.po
@@ -0,0 +1,1557 @@
+# Translators:
+# Mingye Wang <arthur200126(a)gmail.com>, 2016
+# guihu, 2016
+# Vel <veloci85(a)gmail.com>, 2016
+# Agustín Wu <losangwuyts(a)gmail.com>, 2016
+# Chinrur Yang <chinrur(a)gmail.com>, 2016
+# LNDDYL, 2016
+# Quence Lin <qqq89513(a)yahoo.com.tw>, 2016
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"POT-Creation-Date: 2016-12-06 16:36-0600\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Quence Lin <qqq89513(a)yahoo.com.tw>, 2016\n"
+"Language-Team: Chinese (Taiwan) (https://www.transifex.com/otf/teams/1519/zh_TW/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: zh_TW\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#. Put one translator per line, in the form NAME <EMAIL>, YEAR1, YEAR2
+msgctxt "_"
+msgid "translator-credits"
+msgstr "OTF 譯者 <https://www.transifex.com/otf/public>"
+
+#: about-tor-browser.page:7
+msgid "Learn what Tor Browser can do to protect your privacy and anonymity"
+msgstr "了解洋蔥路由瀏覽器如何保護您的的隱私和匿名性"
+
+#: about-tor-browser.page:10
+msgid "About Tor Browser"
+msgstr "關於洋蔥路由瀏覽器"
+
+#: about-tor-browser.page:12
+msgid ""
+"Tor Browser uses the Tor network to protect your privacy and anonymity. "
+"Using the Tor network has two main properties:"
+msgstr "洋蔥路由瀏覽器使用洋蔥路由網路來保護您的隱私和匿名性。使用洋蔥路由網路有兩個主要的功能:"
+
+#: about-tor-browser.page:18
+msgid ""
+"Your internet service provider, and anyone watching your connection locally,"
+" will not be able to track your internet activity, including the names and "
+"addresses of the websites you visit."
+msgstr "無論是您的網路服務提供者或在您本地網路上監看網路流量的任何人,都無法追蹤您的網路活動,包括您所拜訪的網站名稱和位址。"
+
+#: about-tor-browser.page:25
+msgid ""
+"The operators of the websites and services that you use, and anyone watching"
+" them, will see a connection coming from the Tor network instead of your "
+"real Internet (IP) address, and will not know who you are unless you "
+"explicitly identify yourself."
+msgstr ""
+"不論是網站管理員或網路服務提供者,只能看見某個來自洋蔥路由網路的連線,完全看不到您的真實網路位址(IP "
+"位址),除非您主動表明身份,否則他們絕對無法得知您的真實身份。"
+
+#: about-tor-browser.page:34
+msgid ""
+"In addition, Tor Browser is designed to prevent websites from "
+"“fingerprinting” or identifying you based on your browser configuration."
+msgstr "並且,洋蔥路由瀏覽器有經過特殊設計,可以防止網站利用各種瀏覽器的個人設定值作為「特徵指紋」來追蹤辨識您的網路活動。"
+
+#: about-tor-browser.page:39
+msgid ""
+"By default, Tor Browser does not keep any browsing history. Cookies are only"
+" valid for a single session (until Tor Browser is exited or a <link xref"
+"=\"managing-identities#new-identity\">New Identity</link> is requested)."
+msgstr ""
+"在預設狀態下,洋蔥路由瀏覽器不會在硬碟中儲存任何網路瀏覽紀錄,網站使用的 Cookie 紀錄也會在洋蔥路由瀏覽器關閉後或者是<link xref"
+"=\"managing-identities#new-identity\">新的身份</link>功能被執行後全部消失。"
+
+#: about-tor-browser.page:50
+msgid "How Tor works"
+msgstr "洋蔥路由如何運作"
+
+#: about-tor-browser.page:52
+msgid ""
+"Tor is a network of virtual tunnels that allows you to improve your privacy "
+"and security on the Internet. Tor works by sending your traffic through "
+"three random servers (also known as <em>relays</em>) in the Tor network. The"
+" last relay in the circuit (the “exit relay”) then sends the traffic out "
+"onto the public Internet."
+msgstr ""
+"洋蔥路由是一種由虛擬通道所建構成的網路,它可以強化您在網路上活動時的安全性與隱私性。它運作的原理是把您上網時的網路訊號導引轉跳過洋蔥路由網路上的三個隨機伺服器(又稱為<em>中繼節點</em>),這條迴路上的第三個也是最後一個中繼節點(又稱為出口節點)會將您的網路訊號送上公開的網際網路。"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: about-tor-browser.page:59
+msgctxt "_"
+msgid ""
+"external ref='media/how-tor-works.png' "
+"md5='6fe4151a88b7a518466f0582e40ccc8c'"
+msgstr ""
+"external ref='media/how-tor-works.png' "
+"md5='6fe4151a88b7a518466f0582e40ccc8c'"
+
+#: about-tor-browser.page:60
+msgid ""
+"The image above illustrates a user browsing to different websites over Tor. "
+"The green middle computers represent relays in the Tor network, while the "
+"three keys represent the layers of encryption between the user and each "
+"relay."
+msgstr ""
+"上圖說明了當使用者透過洋蔥路由來造訪不同網站時的情況,綠色的中繼電腦代表洋蔥路由網路上的中繼節點,而圖中的三把鑰匙意指在使用者與各個中繼節點間的多層加密結構。"
+
+#: bridges.page:6
+msgid "Learn what bridges are and how to get them"
+msgstr "認識橋接器及其使用方式"
+
+#: bridges.page:10
+msgid "Bridges"
+msgstr "橋接器"
+
+#: bridges.page:12
+msgid ""
+"Most <link xref=\"transports\">Pluggable Transports</link>, such as obfs3 "
+"and obfs4, rely on the use of “bridge” relays. Like ordinary Tor relays, "
+"bridges are run by volunteers; unlike ordinary relays, however, they are not"
+" listed publicly, so an adversary cannot identify them easily. Using bridges"
+" in combination with pluggable transports helps to disguise the fact that "
+"you are using Tor."
+msgstr ""
+"大部分像是 obfs3 或 obfs4 之類的的<link xref=\"transports\">Pluggable "
+"Transports</link>都仰賴橋接器來運作,基本上它們和普通的洋蔥路由中繼節點一樣,都是由志願者自行架設營運的伺服器,只不過這些中繼節點的相關資訊是不公開的,因此一般人很難分辨出它們是一般的電腦主機或是洋蔥路由網路的中繼節點,當橋接器同時與"
+" Pluggable Transports 啟用時,可以讓其他人非常難以看出您是否正透過洋蔥路由來上網。"
+
+#: bridges.page:21
+msgid ""
+"Other pluggable transports, like meek, use different anti-censorship "
+"techniques that do not rely on bridges. You do not need to obtain bridge "
+"addresses in order to use these transports."
+msgstr ""
+"其他像是 meek 之類的 Pluggable Transport "
+"使用不同的反監控過濾技術,它們並不需依賴橋接器來運作,因此您使用時也不需要事先去取得橋接器的位址。"
+
+#: bridges.page:28
+msgid "Getting bridge addresses"
+msgstr "取得橋接器位址"
+
+#: bridges.page:29
+msgid ""
+"Because bridge addresses are not public, you will need to request them "
+"yourself. You have two options:"
+msgstr "因為橋接器的位址是不公開的,您要先設法取得位址。有兩個方法:"
+
+#: bridges.page:36
+msgid ""
+"Visit <link "
+"href=\"https://bridges.torproject.org/\">https://bridges.torproject.org/</link>"
+" and follow the instructions, or"
+msgstr ""
+"前往 <link "
+"href=\"https://bridges.torproject.org/\">https://bridges.torproject.org/</link>"
+" 並按照上面的指示操作,或者"
+
+#: bridges.page:42
+msgid ""
+"Email bridges(a)torproject.org from a Gmail, Yahoo, or Riseup email address, "
+"or"
+msgstr "使用 Gmail、Yahoo 或 Riseup 的電子郵件帳號發送電子郵件到 bridges(a)torproject.xn--org,-875hs64m"
+
+#: bridges.page:51
+msgid "Entering bridge addresses"
+msgstr "輸入橋接器位址"
+
+#: bridges.page:52
+msgid ""
+"Once you have obtained some bridge addresses, you will need to enter them "
+"into Tor Launcher."
+msgstr "在您取得橋接器位址後,還需要將它輸入洋蔥路由啟動器裡面。"
+
+#: bridges.page:57
+msgid ""
+"Choose “yes” when asked if your Internet Service Provider blocks connections"
+" to the Tor network. Select “Use custom bridges” and enter each bridge "
+"address on a separate line."
+msgstr ""
+"如果您的網路服務供應商(ISP)會阻擋洋蔥路由網路連線的話,請點選「是」,並選擇「使用自行設定之橋接器」再將橋接器的位址輸入,每個位址皆應置於單獨的一行中。"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: bridges.page:63
+msgctxt "_"
+msgid ""
+"external ref='media/tor-launcher-custom-bridges_en-US.png' "
+"md5='93365c2aa3fb4d627497e83f28a39b7e'"
+msgstr ""
+"external ref='media/tor-launcher-custom-bridges_en-US.png' "
+"md5='93365c2aa3fb4d627497e83f28a39b7e'"
+
+#: bridges.page:65
+msgid ""
+"Click “Connect”. Using bridges may slow down the connection compared to "
+"using ordinary Tor relays. If the connection fails, the bridges you received"
+" may be down. Please use one of the above methods to obtain more bridge "
+"addresses, and try again."
+msgstr ""
+"點選「連線」以便建立洋蔥路由迴路,使用橋接器會讓網路連線速度比使用一般的洋蔥路由中繼節點還要慢。如果連線失敗的話,可能是因為您所指定的橋接器目前並非正常運作中,請使用上面所提的方法取得更多的橋接器位址後,再行嘗試。"
+
+#: circumvention.page:6
+msgid "What to do if the Tor network is blocked"
+msgstr "當洋蔥路由網路被過濾阻擋時該怎麼辦"
+
+#: circumvention.page:10
+msgid "Circumvention"
+msgstr "規避"
+
+#: circumvention.page:12
+msgid ""
+"Direct access to the Tor network may sometimes be blocked by your Internet "
+"Service Provider or by a government. Tor Browser includes some circumvention"
+" tools for getting around these blocks. These tools are called “pluggable "
+"transports”. See the <link xref=\"transports\">Pluggable Transports</link> "
+"page for more information on the types of transport that are currently "
+"available."
+msgstr ""
+"有時候您的網路服務供應商(ISP)或政府單位會過濾阻擋通往洋蔥路由網路的連線,因此洋蔥路由瀏覽器有內建一些能夠繞過這類過濾機制的規避工具,它們通常叫作「Pluggable"
+" Transports」,您可以參考此網頁<link xref=\"transports\">Pluggable "
+"Transports</link>以取得更多關於各種目前可以使用的規避工具。"
+
+#: circumvention.page:22
+msgid "Using pluggable transports"
+msgstr "使用 Pluggable Transports"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: circumvention.page:26 first-time.page:35
+msgctxt "_"
+msgid ""
+"external ref='media/circumvention/configure.png' "
+"md5='519d888303eadfe4cb03f178aedd90f5'"
+msgstr ""
+"external ref='media/circumvention/configure.png' "
+"md5='519d888303eadfe4cb03f178aedd90f5'"
+
+#: circumvention.page:28
+msgid ""
+"To use pluggable transports, click \"Configure\" in the Tor Launcher window "
+"that appears when you first run Tor Browser."
+msgstr "若要使用 Pluggable Transport,請在開啟洋蔥路由瀏覽器時的啟動器中,點選「設定」按鈕。"
+
+#: circumvention.page:33
+msgid ""
+"You can also configure pluggable transports while Tor Browser is running, by"
+" clicking on the green onion near your address bar and selecting “Tor "
+"Network Settings”."
+msgstr ""
+"您也可以在此用洋蔥路由瀏覽器的時候,點擊位在網址列旁邊的綠色洋蔥圖示並選擇「洋蔥路由網路設定」功能,來調整有關 Pluggable Transport "
+"之設定。"
+
+#: circumvention.page:41
+msgid ""
+"Select “yes” when asked if your Internet Service Provider blocks connections"
+" to the Tor network."
+msgstr "如果您的網路服務供應商(ISP)會過濾阻擋通往洋蔥路由網路的連線,請點選「是」。"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: circumvention.page:49
+msgctxt "_"
+msgid ""
+"external ref='media/circumvention/bridges.png' "
+"md5='910cdd5e45860b81a1ad4739c589a195'"
+msgstr ""
+"external ref='media/circumvention/bridges.png' "
+"md5='910cdd5e45860b81a1ad4739c589a195'"
+
+#: circumvention.page:51
+msgid ""
+"Select “Connect with provided bridges”. Tor Browser currently has six "
+"pluggable transport options to choose from."
+msgstr "選擇「以所提供的橋接器連線」,目前洋蔥路由瀏覽器有提供六個 Pluggable Transport 供您選擇。"
+
+#: circumvention.page:60
+msgid "Which transport should I use?"
+msgstr "我應該要使用哪個 Pluggable Transport?"
+
+#: circumvention.page:61
+msgid ""
+"Each of the transports listed in Tor Launcher’s menu works in a different "
+"way (for more details, see the <link xref=\"transports\">Pluggable "
+"Transports</link> page), and their effectiveness depends on your individual "
+"circumstances."
+msgstr ""
+"在洋蔥錄由啟動器之清單中所羅列的 Pluggable Transport,其運作原理皆不相同(請參考 <link "
+"xref=\"transports\">Pluggable "
+"Transports</link>以了解更多相關資訊),且其產生的效果也會因您的實際情況而有所差異。"
+
+#: circumvention.page:67
+msgid ""
+"If you are trying to circumvent a blocked connection for the first time, you"
+" should try the different transports: obfs3, obfs4, ScrambleSuit, fte, meek-"
+"azure, meek-amazon."
+msgstr ""
+"如果這是您首次嘗試規避網路連線之過濾阻擋機制,您應該要試著使用不同的 Pluggable "
+"Transport:obfs3、obfs4、ScrambleSuit、FTE、meek-azure、meek-amazon。"
+
+#: circumvention.page:72
+msgid ""
+"If you try all of these options, and none of them gets you online, you will "
+"need to enter bridge addresses manually. Read the <link "
+"xref=\"bridges\">Bridges</link> section to learn what bridges are and how to"
+" obtain them."
+msgstr ""
+"如果您試過了上述的全部選項後,仍然無法連上線的話,您將必須要手動輸入橋接器位址,請參考<link "
+"xref=\"bridges\">橋接器</link>部分以進一步了解橋接器之運作原理與取得方式。"
+
+#: downloading.page:7
+msgid "How to download Tor Browser"
+msgstr "如何下載洋蔥路由瀏覽器"
+
+#: downloading.page:10
+msgid "Downloading"
+msgstr "下載中"
+
+#: downloading.page:12
+msgid ""
+"The safest and simplest way to download Tor Browser is from the official Tor"
+" Project website at https://www.torproject.org. Your connection to the site "
+"will be secured using <link xref=\"secure-connections\">HTTPS</link>, which "
+"makes it much harder for somebody to tamper with."
+msgstr ""
+"要取得洋蔥路由瀏覽器,最安全且簡便的方式就是從洋蔥路由專案計畫之官方網站 https://www.torproject.org "
+"下載。造訪該網站之網路連線都將會受到<link xref=\"secure-"
+"connections\">HTTPS</link>機制保護,以便讓連線之資料傳輸更難以被竄改。"
+
+#: downloading.page:19
+msgid ""
+"However, there may be times when you cannot access the Tor Project website: "
+"for example, it could be blocked on your network. If this happens, you can "
+"use one of the alternative download methods listed below."
+msgstr ""
+"然而,某些情況下您可能無法成功造訪洋蔥路由專案計畫之官方網站,例如您所在的網路會阻檔通往該網站之連線,如果您遭遇到類似情況的話,可以利用下列幾種不同的方式取得洋蔥路由瀏覽器。"
+
+#: downloading.page:27
+msgid "GetTor"
+msgstr "GetTor"
+
+#: downloading.page:28
+msgid ""
+"GetTor is a service that automatically responds to messages with links to "
+"the latest version of Tor Browser, hosted at a variety of locations, such as"
+" Dropbox, Google Drive and Github.."
+msgstr ""
+"GetTor 是一個特殊的服務,它會自動回覆一個訊息,內含有最新版洋蔥路由瀏覽器下載連結,通常是位於 Dropbox、Google Drive 或 "
+"Github 上的檔案下載連結。"
+
+#: downloading.page:34
+msgid "To use GetTor via email:"
+msgstr "利用電子郵件信箱來使用 GetTor 服務:"
+
+#: downloading.page:39
+msgid ""
+"Send an email to gettor(a)torproject.org, and in the body of the message "
+"simply write “windows”, “osx”, or “linux”, (without quotation marks) "
+"depending on your operating system."
+msgstr ""
+"發送一封電子郵件至 gettor(a)torproject.org "
+",並且依照您欲使用洋蔥路由瀏覽器的電腦系統,在郵件內容填寫「windows」、「osx」或「linux」來指定平台版本(不含括號)"
+
+#: downloading.page:46
+msgid ""
+"GetTor will respond with an email containing links from which you can "
+"download the Tor Browser package, the cryptographic signature (needed for "
+"verifying the download), the fingerprint of the key used to make the "
+"signature, and the package’s checksum. You may be offered a choice of "
+"“32-bit” or “64-bit” software: this depends on the model of the computer you"
+" are using."
+msgstr ""
+"GetTor "
+"將會自動回覆一封電子郵件給您,信中會帶有洋蔥路由瀏覽器的下載連結、數位簽章(用於確認所下載之檔案其來源可信)、數位簽章所用之金鑰特徵指紋碼、所下載檔案之總和檢查碼。另外,您亦可以依照您所使用的電腦系統架構,選擇要下載"
+" 32 位元或是 64 位元的版本。"
+
+#: downloading.page:57
+msgid "To use GetTor via Twitter:"
+msgstr "利用推特來使用 GetTor 服務:"
+
+#: downloading.page:62
+msgid ""
+"To get links for downloading Tor Browser in English for OS X, send a Direct "
+"Message to @get_tor with the words \"osx en\" in it (you don't need to "
+"follow the account)."
+msgstr ""
+"若要取得 OS X 平台之英文版洋蔥路由瀏覽器的下載超連結,只要將「osx en」這幾個字寫成訊息並直接傳訊發送給 @get_tor "
+"帳號即可。(您不需要去跟隨該帳號)"
+
+#: downloading.page:70
+msgid "To use GetTor via Jabber/XMPP (Tor Messenger, Jitsi, CoyIM):"
+msgstr "利用 Jabber/XMPP (Tor Messenger, Jitsi, CoyIM) 來使用 GetTor 服務的方式:"
+
+#: downloading.page:75
+msgid ""
+"To get links for downloading Tor Browser in Chinese for Linux, send a "
+"message to gettor(a)torproject.org with the words \"linux zh\" in it."
+msgstr ""
+"若要取得可於 Linux 平台上使用的中文版洋蔥路由瀏覽器下載連結,可以將「linux zh」字串寫在電子郵件裡並發送到 "
+"gettor(a)torproject.org."
+
+#: downloading.page:84
+msgid "Satori"
+msgstr "Satori"
+
+#: downloading.page:85
+msgid ""
+"Satori is an add-on for the Chrome or Chromium browsers that allows you to "
+"download several security and privacy programs from different sources."
+msgstr ""
+"Satori 是一個設計給 Chrome 及 Chromium "
+"瀏覽器使用的擴充元件,它可以讓使用者從不同的來源下載許多有關強化資訊安全與確保個人隱私的相關軟體。"
+
+#: downloading.page:90
+msgid "To download Tor Browser using Satori:"
+msgstr "利用 Satori 來下載洋蔥路由瀏覽器:"
+
+#: downloading.page:95
+msgid "Install Satori from the Chrome App Store."
+msgstr "從 Chrome 的 App Store 中安裝 Satori:"
+
+#: downloading.page:100
+msgid "Select Satori from your browser’s Apps menu."
+msgstr "從您的 APP 清單中點選 Satori。"
+
+#: downloading.page:105
+msgid ""
+"When Satori opens, click on your preferred language. A menu will open "
+"listing the available downloads for that language. Find the entry for Tor "
+"Browser under the name of your operating system. Select either “A” or “B” "
+"after the name of the program — each one represents a different source from "
+"which to get the software. Your download will then begin."
+msgstr ""
+"當 Satori "
+"開啟後,您可以選擇您所想要使用的語言介面,下載清單將會自動羅列出對應該語言的可用下載連結,此時您只需要找到符合您電腦系統版本的洋蔥路由瀏覽器,並在「A」或「B」兩個不同的下載來源中,任選一個以開始下載程序。"
+
+#: downloading.page:115
+msgid ""
+"Wait for your download to finish, then find the “Generate Hash” section in "
+"Satori’s menu and click “Select Files”."
+msgstr "等下載完成以後,在 Satori 的功能清單中找到「Generate Hash」功能,並選擇「Select Files」。"
+
+#: downloading.page:121
+msgid ""
+"Select the downloaded Tor Browser file. Satori will display the checksum of "
+"the file, which you should compare with the software’s original checksum: "
+"you can find this by clicking the word “checksum” after the link you clicked"
+" on to start the download. If the checksums match, your download was "
+"successful, and you can <link xref=\"first-time\">begin using Tor "
+"Browser</link>. If they do not match, you may need to try downloading again,"
+" or from a different source."
+msgstr ""
+"選擇下載下來的洋蔥路由瀏覽器檔案,此時 Satori "
+"將會自動為該檔案計算出其總和檢查碼,您需要親自核對此檢查碼與軟體原本的檢查碼是否完全符合:您可以在您下載該檔案的超連結旁邊找到「checksum」字樣,點擊後就可以看到軟體原本的檢查碼,若兩組檢查碼完全一致的話,表示您的下載已經成功,此時您可以直接<link"
+" xref=\"first-"
+"time\">開始使用洋蔥路由瀏覽器</link>,若兩組檢查碼不相符的話,您可能需要再重新下載,或者選擇不同的下載來源重新嘗試。"
+
+#: first-time.page:7
+msgid "Learn how to use Tor Browser for the first time"
+msgstr "學習如何開始使用洋蔥路由瀏覽器"
+
+#: first-time.page:10
+msgid "Running Tor Browser for the first time"
+msgstr "首次執行洋蔥路由瀏覽器"
+
+#: first-time.page:12
+msgid ""
+"When you run Tor Browser for the first time, you will see the Tor Network "
+"Settings window. This offers you the option to connect directly to the Tor "
+"network, or to configure Tor Browser for your connection."
+msgstr "當您首次啟動洋蔥路由瀏覽器時,您會看到洋蔥路由網路的設定視窗,此處您可以選擇要瀏覽器直接連上洋蔥路由網路,或者是要設定不同的連線方式。"
+
+#: first-time.page:19
+msgid "Connect"
+msgstr "連線"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: first-time.page:21 troubleshooting.page:18
+msgctxt "_"
+msgid ""
+"external ref='media/first-time/connect.png' "
+"md5='9d07068f751a3bfd274365a4ba8d90ca'"
+msgstr ""
+"external ref='media/first-time/connect.png' "
+"md5='9d07068f751a3bfd274365a4ba8d90ca'"
+
+#: first-time.page:23
+msgid ""
+"In most cases, choosing \"Connect\" will allow you to connect to the Tor "
+"network without any further configuration. Once clicked, a status bar will "
+"appear, showing Tor’s connection progress. If you are on a relatively fast "
+"connection, but this bar seems to get stuck at a certain point, see the "
+"<link xref=\"troubleshooting\">Troubleshooting</link> page for help solving "
+"the problem."
+msgstr ""
+"在大多數情況下,點選「連線」可以讓您不作任何進一步的設定就直接連上洋蔥路由網路,點擊後將會出現一條狀態列顯示目前洋蔥路由的連線建立過程,如果您的網路頻寬充足但是此狀態列卻長時間停滯在某個點上無法完成連線建立,請參考"
+" <link xref=\"troubleshooting\">錯誤處理</link>頁面以尋求解決問題的協助。"
+
+#: first-time.page:33
+msgid "Configure"
+msgstr "設定"
+
+#: first-time.page:37
+msgid ""
+"If you know that your connection is censored, or uses a proxy, you should "
+"select this option. Tor Browser will take you through a series of "
+"configuration options."
+msgstr "如果您使用的網路有被過濾阻擋,或是您有使用代理伺服器,那您就必須要選擇此項目,洋蔥路由瀏覽器將會引導您進行一連串的相關設定程序。"
+
+#: first-time.page:44
+msgid ""
+"The first screen asks if access to the Tor network is blocked or censored on"
+" your connection. If you do not believe this is the case, select “No”. If "
+"you know your connection is censored, or you have tried and failed to "
+"connect to the Tor network and no other solutions have worked, select “Yes”."
+" You will then be taken to the <link "
+"xref=\"circumvention\">Circumvention</link> screen to configure a pluggable "
+"transport."
+msgstr ""
+"在第一個畫面中您必須回答您所處的網路環境是否會過濾阻擋通往洋蔥路由網路的連線,若您認為不會的話,請選擇「否」。否則若您的網路有被過濾阻擋,或您已經嘗試過各種連上洋蔥路由網路的方法但都失敗的話,請選擇「是」,本程式將會帶領您前往"
+" <link xref=\"circumvention\">審查規避</link>畫面進行 Pluggable Transport 的相關設定。"
+
+#: first-time.page:55
+msgid ""
+"The next screen asks if your connection uses a proxy. In most cases, this is"
+" not necessary. You will usually know if you need to answer “Yes”, as the "
+"same settings will be used for other browsers on your system. If possible, "
+"ask your network administrator for guidance. If your connection does not use"
+" a proxy, click “Continue”."
+msgstr ""
+"在下一個畫面中,您必須要回答您的網路連線是否有透過代理伺服器來連上網路,通常您應該很清楚自己是否有使用代理伺服器,因為這部分的設定在您電腦中的每個網路瀏覽器裡都會一樣。若您不確定的話,可以詢問您的網路管理員,若您確定無使用代理伺服器的話,請點選「繼續」。"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: first-time.page:63
+msgctxt "_"
+msgid ""
+"external ref='media/first-time/proxy_question.png' "
+"md5='30853b3e86cfd386bbc32e5b8b45a378'"
+msgstr ""
+"external ref='media/first-time/proxy_question.png' "
+"md5='30853b3e86cfd386bbc32e5b8b45a378'"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: first-time.page:66
+msgctxt "_"
+msgid ""
+"external ref='media/first-time/proxy.png' "
+"md5='13f21a351cd0aa1cf11aada690f3dc90'"
+msgstr ""
+"external ref='media/first-time/proxy.png' "
+"md5='13f21a351cd0aa1cf11aada690f3dc90'"
+
+#: index.page:6
+msgid "Tor Browser User Manual"
+msgstr "洋蔥路由瀏覽器之使用者手冊"
+
+#: known-issues.page:6
+msgid "A list of known issues."
+msgstr "目前已知的問題。"
+
+#: known-issues.page:10
+msgid "Known Issues"
+msgstr "已知的問題"
+
+#: known-issues.page:14
+msgid ""
+"Tor needs your system clock (and your time zone) set to the correct time."
+msgstr "您必須要將系統的時間(以及您的所在時區)正確設定,方能夠使用洋蔥路由網路。"
+
+#: known-issues.page:19
+msgid ""
+"The following firewall software have been known to interfere with Tor and "
+"may need to be temporarily disabled:"
+msgstr "下列的防火牆軟體會干擾洋蔥路由的運作,您或許需要先暫時將它們關閉:"
+
+#: known-issues.page:23
+msgid "Webroot SecureAnywhere"
+msgstr "Webroot SecureAnywhere"
+
+#: known-issues.page:26
+msgid "Kaspersky Internet Security 2012"
+msgstr "Kaspersky Internet Security 2012"
+
+#: known-issues.page:29
+msgid "Sophos Antivirus for Mac"
+msgstr "Sophos Antivirus for Mac"
+
+#: known-issues.page:32
+msgid "Microsoft Security Essentials"
+msgstr "Microsoft Security Essentials"
+
+#: known-issues.page:37
+msgid ""
+"Videos that require Adobe Flash are unavailable. Flash is disabled for "
+"security reasons."
+msgstr "由於 Adobe Flash 會造成安全性疑慮,需要 Adobe Flash 外掛程式的影片皆無法使用。"
+
+#: known-issues.page:43
+msgid "Tor can not use a bridge if a proxy is set."
+msgstr "洋蔥路由的橋接器無法與代理伺服器一起運行。"
+
+#: known-issues.page:48
+msgid ""
+"The Tor Browser package is dated January 1, 2000 00:00:00 UTC. This is to "
+"ensure that each software build is exactly reproducible."
+msgstr ""
+"洋蔥路由瀏覽器套件的日期時間押在UTC時間西元 2000 年一月 1 日零時零分零秒,其目的是在確保每個軟體的編譯建構都能夠完整無誤差地重現。"
+
+#: known-issues.page:54
+msgid ""
+"To run Tor Browser on Ubuntu, users need to execute a shell script. Open "
+"\"Files\" (Unity's explorer), open Preferences → Behavior Tab → Set \"Run "
+"executable text files when they are opened\" to \"Ask every time\", then "
+"click OK."
+msgstr ""
+"若要在 Ubuntu 系統中執行洋蔥路由瀏覽器的話,必須要執行一個命令稿程式(Shell Script),請使用 Unity "
+"的瀏覽功能開啟「檔案」,再開啟「個人設定」,點選行為頁籤,將「每當開起可執行文字文件時直接執行」的設定更改為「每次都詢問」,然後點擊「OK」。"
+
+#: known-issues.page:62
+msgid ""
+"Tor Browser can also be started from the command line by running the "
+"following command from inside the Tor Browser directory:"
+msgstr "也可以用命令列模式在洋蔥路由瀏覽器的目錄中,執行下面這個指令來啟動它:"
+
+#: known-issues.page:66
+#, no-wrap
+msgid ""
+"\n"
+" ./start-tor-browser.desktop\n"
+" "
+msgstr ""
+"\n"
+" ./start-tor-browser.desktop\n"
+" "
+
+#: managing-identities.page:6
+msgid "Learn how to control personally-identifying information in Tor Browser"
+msgstr "學習如何在洋蔥路由瀏覽器中,管控可識別個人身分的資訊"
+
+#: managing-identities.page:10
+msgid "Managing identities"
+msgstr "身分管理"
+
+#: managing-identities.page:12
+msgid ""
+"When you connect to a website, it is not only the operators of that website "
+"who can record information about your visit. Most websites now use numerous "
+"third-party services, including social networking “Like” buttons, analytics "
+"trackers, and advertising beacons, all of which can link your activity "
+"across different sites."
+msgstr ""
+"當您連上某個網站時,不只是該網站的管理員可取得有關於您的相關資訊,現今許多網站都會使用像是臉書的「讚」功能按鈕、訪客追蹤分析、廣告推播服務等各種第三方網路服務,此類的功能可以將您在不同網站上的活動紀錄串連組合起來。"
+
+#: managing-identities.page:20
+msgid ""
+"Using the Tor network stops observers from being able to discover your exact"
+" location and IP address, but even without this information they might be "
+"able to link different areas of your activity together. For this reason, Tor"
+" Browser includes some additional features that help you control what "
+"information can be tied to your identity."
+msgstr ""
+"使用洋蔥路由網路可以防止網路監聽者找出您的真實網路位址以及實際地理位置,但是他們仍然能夠將您在網路上活動的各種紀錄連接組合在一起,並還原出您的網路活動全貌。有鑑於此,洋蔥路由瀏覽器有加入一些特殊設計,可以幫助您管控可能被用於身分識別的相關資訊。"
+
+#: managing-identities.page:29
+msgid "The URL bar"
+msgstr "網址列"
+
+#: managing-identities.page:30
+msgid ""
+"Tor Browser centers your web experience around your relationship with the "
+"website in the URL bar. Even if you connect to two different sites that use "
+"the same third-party tracking service, Tor Browser will force the content to"
+" be served over two different Tor circuits, so the tracker will not know "
+"that both connections originate from your browser."
+msgstr ""
+"洋蔥路由瀏覽器會以您在網址列中的網站名稱為中心,來維護您與網站間的互動關係,因此,即使您連上了兩個不同的網站,但兩個站台上都有使用相同的第三方網路追蹤服務,洋蔥路由瀏覽器仍會強制讓您與這兩個網站間的連線,透過兩條不同的洋蔥路由迴路來交換資料,如此可以讓第三方網路追蹤服務非常難以察覺這兩條通往不同網站的連線,其實都是源自於您的瀏覽器。"
+
+#: managing-identities.page:38
+msgid ""
+"On the other hand, all connections to a single website address will be made "
+"over the same Tor circuit, meaning you can browse different pages of a "
+"single website in separate tabs or windows, without any loss of "
+"functionality."
+msgstr ""
+"從另一方面而言,所有通往同一網站的連線都將會透過同一條洋蔥路由迴路來達成,因此即使您在瀏覽器中開啟多個不同的頁籤來閱覽同一網站中的不同網頁,其網站的功能也不會受到影響。"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: managing-identities.page:46
+msgctxt "_"
+msgid ""
+"external ref='media/managing-identities/circuit_full.png' "
+"md5='bd46d22de952fee42643be46d3f95928'"
+msgstr ""
+"external ref='media/managing-identities/circuit_full.png' "
+"md5='bd46d22de952fee42643be46d3f95928'"
+
+#: managing-identities.page:48
+msgid ""
+"You can see a diagram of the circuit that Tor Browser is using for the "
+"current tab in the onion menu."
+msgstr "在洋蔥路由瀏覽器的各個頁籤中,皆有個洋蔥清單功能按鈕,該功能裡會以簡易圖表來顯示目前該頁籤與所造訪網站間之洋蔥路由迴路。"
+
+#: managing-identities.page:55
+msgid "Logging in over Tor"
+msgstr "正透過洋蔥路由登入中"
+
+#: managing-identities.page:56
+msgid ""
+"Although Tor Browser is designed to enable total user anonymity on the web, "
+"there may be situations in which it makes sense to use Tor with websites "
+"that require usernames, passwords, or other identifying information."
+msgstr ""
+"雖然說洋蔥路由瀏覽器的設計,是要提供使用者以完全匿名的方式來上網,但是在某些情況中,用它來登入需要帳號密碼或可識別個人身分的網站,仍有其實用的價值。"
+
+#: managing-identities.page:62
+msgid ""
+"If you log into a website using a regular browser, you also reveal your IP "
+"address and geographical location in the process. The same is often true "
+"when you send an email. Logging into your social networking or email "
+"accounts using Tor Browser allows you to choose exactly which information "
+"you reveal to the websites you browse. Logging in using Tor Browser is also "
+"useful if the website you are trying to reach is censored on your network."
+msgstr ""
+"當您使用普通的網路瀏覽器來登入某個網站時,您的真實網路位址與實際地理位置都將被公開得知,或者當您發送電子郵件時也是一樣的。然而,使用洋蔥路由瀏覽器來登入社群網站或電子郵件服務時,您則可以選擇哪些個人資訊要公開給網站取得哪些不要。而且,洋蔥路由瀏覽器也可以用來繞過某些有審查過濾機制的網路。"
+
+#: managing-identities.page:72
+msgid ""
+"When you log in to a website over Tor, there are several points you should "
+"bear in mind:"
+msgstr "當您透過洋蔥路由來登入某個網站時,以下幾個重點您必須要牢記在心:"
+
+#: managing-identities.page:79
+msgid ""
+"See the <link xref=\"secure-connections\">Secure Connections</link> page for"
+" important information on how to secure your connection when logging in."
+msgstr ""
+"請參考<link xref=\"secure-connections\">安全的連線</link>頁面以瞭解關於登入網站時,要確保連線安全的重要資訊。"
+
+#: managing-identities.page:87
+msgid ""
+"Tor Browser often makes your connection appear as though it is coming from "
+"an entirely different part of the world. Some websites, such as banks or "
+"email providers, might interpret this as a sign that your account has been "
+"hacked or compromised, and lock you out. The only way to resolve this is by "
+"following the site’s recommended procedure for account recovery, or "
+"contacting the operators and explaining the situation."
+msgstr ""
+"洋蔥路由瀏覽器會讓您的網路活動看起來像是來自於世界各個不同地區的網路連線,有時候某些像是銀行或電子郵件服務的網站會認為您的帳號被他人盜用了,因此自動將您的帳號鎖定,要解決此情況的唯一方式是利用網站服務提供的帳號恢復功能,或直接向該網站服務的提供業者說明您的情況。"
+
+#: managing-identities.page:101
+msgid "Changing identities and circuits"
+msgstr "改變識別身分與洋蔥路由迴路"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: managing-identities.page:103
+msgctxt "_"
+msgid ""
+"external ref='media/managing-identities/new_identity.png' "
+"md5='15b01e35fa83185d94b57bf0ccf09d76'"
+msgstr ""
+"external ref='media/managing-identities/new_identity.png' "
+"md5='15b01e35fa83185d94b57bf0ccf09d76'"
+
+#: managing-identities.page:105
+msgid ""
+"Tor Browser features “New Identity” and “New Tor Circuit for this Site” "
+"options, located in the Torbutton menu."
+msgstr "在 Torbutton 功能清單中,有「新的識別身分」以及「新的洋蔥路由迴路」兩個洋蔥路由瀏覽器所提供的功能。"
+
+#: managing-identities.page:111
+msgid "New Identity"
+msgstr "新的識別身分"
+
+#: managing-identities.page:112
+msgid ""
+"This option is useful if you want to prevent your subsequent browser "
+"activity from being linkable to what you were doing before. Selecting it "
+"will close all your open tabs and windows, clear all private information "
+"such as cookies and browsing history, and use new Tor circuits for all "
+"connections. Tor Browser will warn you that all activity and downloads will "
+"be stopped, so take this into account before clicking “New Identity”."
+msgstr ""
+"若您想要避免後續在網路上活動的相關記錄,與您之前網路活動之記錄被連結組合在一起,此選項即可幫助您達成此目的。執行此功能將會關閉所有已經開啟的瀏覽器視窗及分頁、清除所有的瀏覽器"
+" cookie "
+"與歷史記錄等個人資訊,並且為後續所有的網路連線建立新的洋蔥路由迴路。洋蔥路由瀏覽器將會警告您說所有正在進行中的活動與下載將會被終止,因此當要執行「新的識別身分」功能前,請先做好相關的準備。"
+
+#: managing-identities.page:123
+msgid "New Tor Circuit for this Site"
+msgstr "建立新的洋蔥路由迴路來連接上此網站"
+
+#: managing-identities.page:124
+msgid ""
+"This option is useful if the <link xref=\"about-tor-browser#how-tor-"
+"works\">exit relay</link> you are using is unable to connect to the website "
+"you require, or is not loading it properly. Selecting it will cause the "
+"currently-active tab or window to be reloaded over a new Tor circuit. Other "
+"open tabs and windows from the same website will use the new circuit as well"
+" once they are reloaded. This option does not clear any private information "
+"or unlink your activity, nor does it affect your current connections to "
+"other websites."
+msgstr ""
+"當您目前的洋蔥路由迴路中所使用的<link xref=\"about-tor-browser#how-tor-"
+"works\">出口節點</link>無法正常連上您所欲造訪的網站或載入其網頁時,可以試著執行此功能,它會讓當前視窗或頁籤建立另一條新的洋蔥路由迴路並重新連上該址定網站,若有其他視窗或頁籤也是連上該網站的話,在重新整理時也會改用新的洋蔥路由迴路來連線,此功能不會清除任何個人相關資訊或中斷連上其他網站的活動。"
+
+#: onionsites.page:6
+msgid "Services that are only accessible using Tor"
+msgstr "只有透過洋蔥路由才能存取的服務"
+
+#: onionsites.page:10
+msgid "Onion Services"
+msgstr "洋蔥服務"
+
+#: onionsites.page:11
+msgid ""
+"Onion services (formerly known as “hidden services”) are services (like "
+"websites) that are only accessible through the Tor network."
+msgstr "洋蔥服務(舊名為「隱藏式服務」)是一種只能透過洋蔥路由網路來存取的網路服務(網站)。"
+
+#: onionsites.page:16
+msgid ""
+"Onion services offer several advantages over ordinary services on the non-"
+"private web:"
+msgstr "洋蔥服務提供了許多架設在公開網路空間之普通網站所沒有的優勢:"
+
+#: onionsites.page:23
+msgid ""
+"An onion services’s location and IP address are hidden, making it difficult "
+"for adversaries to censor it or identify its operators."
+msgstr "洋蔥服務的真實網路位址與地理位置資訊是被隱藏的,因此讓人很難過濾審查通往該站台之網路連線,也很難找出該網站管理員的真實身分。"
+
+#: onionsites.page:29
+msgid ""
+"All traffic between Tor users and onion services is end-to-end encrypted, so"
+" you do not need to worry about <link xref=\"secure-connections\">connecting"
+" over HTTPS</link>."
+msgstr ""
+"所有洋蔥路由瀏覽器使用者與洋蔥服務站台之間的網路連線,都是端對端加密的,因此您無需擔心連線是否是<link xref=\"secure-"
+"connections\">透過HTTPS</link>來進行的。"
+
+#: onionsites.page:36
+msgid ""
+"The address of an onion service is automatically generated, so the operators"
+" do not need to purchase a domain name; the .onion URL also helps Tor ensure"
+" that it is connecting to the right location and that the connection is not "
+"being tampered with."
+msgstr ""
+"洋蔥服務的網址是自動產生的,因此網站的架設者或管理員無需另行購買網域名稱,其網址皆是以 .onion "
+"結尾的,此等設計可以讓洋蔥路由系統確保所有網路連線都是通往正確的站台,並且其連線資料未被竄改。"
+
+#: onionsites.page:46
+msgid "How to access an onion service"
+msgstr "如何存取洋蔥服務"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: onionsites.page:48
+msgctxt "_"
+msgid ""
+"external ref='media/onionsites/onion_url.png' "
+"md5='f97f7fe10f07c3959c4430934974bbaa'"
+msgstr ""
+"external ref='media/onionsites/onion_url.png' "
+"md5='f97f7fe10f07c3959c4430934974bbaa'"
+
+#: onionsites.page:50
+msgid ""
+"Just like any other website, you will need to know the address of an onion "
+"service in order to connect to it. An onion address is a string of sixteen "
+"mostly random letters and numbers, followed by “.onion”."
+msgstr ""
+"就像是普通的網站一般,您必須要知道洋蔥服務的位址才能夠連上該網站,洋蔥服務的位址是由十六個看似為亂碼的英文字母與數字和一個「.onion」的結尾所組成。"
+
+#: onionsites.page:58 troubleshooting.page:10
+msgid "Troubleshooting"
+msgstr "錯誤處理"
+
+#: onionsites.page:59
+msgid ""
+"If you cannot reach the onion service you require, make sure that you have "
+"entered the 16-character onion address correctly: even a small mistake will "
+"stop Tor Browser from being able to reach the site."
+msgstr ""
+"如果您無法連上某個洋蔥服務,請確認是否有把洋蔥位址中的 16 "
+"個英文字母與數字正確鍵入,即使是一個字母或數字的輸入錯誤,都會導致洋蔥路由瀏覽器無法連上該網站。"
+
+#: onionsites.page:64
+msgid ""
+"If you are still unable to connect to the onion service, please try again "
+"later. There may be a temporary connection issue, or the site operators may "
+"have allowed it to go offline without warning."
+msgstr "如果您仍然無法連上該洋蔥服務的話,請稍候再試,有可能是網路連線有出現暫時性阻礙,或者是該網站的管理員暫時將站台關閉了。"
+
+#: onionsites.page:69
+msgid ""
+"You can also ensure that you're able to access other onion services by "
+"connecting to <link href=\"http://3g2upl4pq6kufc4m.onion/\">DuckDuckGo's "
+"Onion Service</link>"
+msgstr ""
+"您也可以藉由連上 <link href=\"http://3g2upl4pq6kufc4m.onion/\">DuckDuckGo "
+"的洋蔥服務</link>來確認您是可以正常造訪洋蔥服務的"
+
+#: plugins.page:6
+msgid "How Tor Browser handles add-ons, plugins and JavaScript"
+msgstr "洋蔥路由瀏覽器如何處理擴充元件、外掛程式以及 JavaScript"
+
+#: plugins.page:10
+msgid "Plugins, add-ons and JavaScript"
+msgstr "擴充元件、外掛程式以及 JavaScript"
+
+#: plugins.page:13
+msgid "Flash Player"
+msgstr "Flash Player"
+
+#: plugins.page:14
+msgid ""
+"Video websites, such as Vimeo make use of the Flash Player plugin to display"
+" video content. Unfortunately, this software operates independently of Tor "
+"Browser and cannot easily be made to obey Tor Browser’s proxy settings. It "
+"can therefore reveal your real location and IP address to the website "
+"operators, or to an outside observer. For this reason, Flash is disabled by "
+"default in Tor Browser, and enabling it is not recommended."
+msgstr ""
+"某些像是 Vimeo 之類的影音平台會使用 Flash Player "
+"外掛程式來播放影片,而非常遺憾地,此外掛程式是獨立運行的軟體且完全不遵循洋蔥路由瀏覽器之代理伺服器設定,因此若啟用此外掛程式的話,將會直接把您的真實網路位址公開給網站的管理員以及任何正在網路上監聽的惡意人士得知,故在洋蔥路由瀏覽器中預設是將"
+" Flash Player 關閉的,在此也不建議您去啟用它。"
+
+#: plugins.page:23
+msgid ""
+"Some video websites (such as YouTube) offer alternative video delivery "
+"methods that do not use Flash. These methods may be compatible with Tor "
+"Browser."
+msgstr ""
+"某些影音平台網站(像是 YouTube)有提供不需使用 Flash Player "
+"外掛程式的影片播放器,此類型的線上影片播放方式即可與洋蔥路由瀏覽器相容。"
+
+#: plugins.page:31
+msgid "JavaScript"
+msgstr "JavaScript"
+
+#: plugins.page:32
+msgid ""
+"JavaScript is a programming language that websites use to offer interactive "
+"elements such as video, animation, audio, and status timelines. "
+"Unfortunately, JavaScript can also enable attacks on the security of the "
+"browser, which might lead to deanonymization."
+msgstr ""
+"JavaScript 是一種內嵌於網頁中的程式語言,它可以提供網站的各種互動式元件,像是影片、音樂、動畫、時間狀態列等,而遺憾的是,JavaScript"
+" 也可能被利用來發動破解瀏覽器安全防護機制的攻擊,其結果有可能會讓使用者的真實身分曝光。"
+
+#: plugins.page:39
+msgid ""
+"Tor Browser includes an add-on called NoScript, accessed through the “S” "
+"icon at the top-left of the window, which allows you to control the "
+"JavaScript that runs on individual web pages, or to block it entirely."
+msgstr ""
+"洋蔥路由瀏覽器有提供一個名為「NoScript」的擴充元件,其功能按鈕是一個位於視窗左上方帶有「S」字樣的圖示,它可以讓您針對個別網頁中所含的 "
+"JavaScript 程式之執行與否,進行控制。"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: plugins.page:45
+msgctxt "_"
+msgid ""
+"external ref='media/plugins/noscript_menu.png' "
+"md5='df9e684b76a3c2e2bdcb879a19c20471'"
+msgstr ""
+"external ref='media/plugins/noscript_menu.png' "
+"md5='df9e684b76a3c2e2bdcb879a19c20471'"
+
+#: plugins.page:47
+msgid ""
+"Users who require a high degree of security in their web browsing should set"
+" Tor Browser’s <link xref=\"security-slider\">Security Slider</link> to "
+"“Medium-High” (which disables JavaScript for non-HTTPS websites) or “High” "
+"(which does so for all websites). However, disabling JavaScript will prevent"
+" many websites from displaying correctly, so Tor Browser’s default setting "
+"is to allow all websites to run scripts."
+msgstr ""
+"對於網路瀏覽器之安全性有較高需求的使用者,可以將洋蔥路由瀏覽器中的<link xref=\"security-"
+"slider\">安全性等級調整棒</link> 調整至「中高」(在造訪未使用 HTTPS 連線的網站時,將 JavaScript "
+"之功能關閉)或者是「高」(將 JavaScript 功能全部關閉)。然而,關閉 JavaScript "
+"功能可能會導致部分網頁之顯示發生異常,因此洋蔥路由瀏覽器在預設狀態下,對所有網站都會啟用 JavaScript 功能。"
+
+#: plugins.page:58
+msgid "Browser Add-ons"
+msgstr "瀏覽器擴充元件"
+
+#: plugins.page:59
+msgid ""
+"Tor Browser is based on Firefox, and any browser add-ons or themes that are "
+"compatible with Firefox can also be installed in Tor Browser."
+msgstr "洋蔥路由瀏覽器是以火狐狸瀏覽器為基礎改良成的,因此所有與火狐狸瀏覽器相容的擴充元件或佈景主題,都可以安裝在洋蔥路由瀏覽器中。"
+
+#: plugins.page:64
+msgid ""
+"However, the only add-ons that have been tested for use with Tor Browser are"
+" those included by default. Installing any other browser add-ons may break "
+"functionality in Tor Browser or cause more serious problems that affect your"
+" privacy and security. It is strongly discouraged to install additional add-"
+"ons, and the Tor Project will not offer support for these configurations."
+msgstr ""
+"然而,有經過測試的擴充元件只有那些洋蔥路由瀏覽器中已經預設啟用的擴充元件,若自行安裝其他的瀏覽器擴充元件有可能造成洋蔥路由瀏覽器運行發生異常,也可能對您的個人隱私與資訊安全造成負面影響。因此,洋蔥路由專案計畫團隊完全不建議您安裝任何額外的擴充元件,也不對其它擴充元件之設定或使用提供任何支援。"
+
+#: secure-connections.page:8
+msgid "Learn how to protect your data using Tor Browser and HTTPS"
+msgstr "瞭解要如何利用洋蔥路由瀏覽器以及 HTTPS 來保護個人的資料"
+
+#: secure-connections.page:12
+msgid "Secure Connections"
+msgstr "安全的連線"
+
+#: secure-connections.page:14
+msgid ""
+"If personal information such as a login password travels unencrypted over "
+"the Internet, it can very easily be intercepted by an eavesdropper. If you "
+"are logging into any website, you should make sure that the site offers "
+"HTTPS encryption, which protects against this kind of eavesdropping. You can"
+" verify this in the URL bar: if your connection is encrypted, the address "
+"will begin with “https://”, rather than “http://”."
+msgstr ""
+"如果像是登入帳號用的密碼等個人資料,是以未經加密的形態在網路上傳送的話,那任何的網路監聽者都可以輕易地攔截竊取到此資訊,因此,每當您試圖登入某網站時,應該要先確認該站台有提供"
+" HTTPS "
+"加密連線,以確保您個人資料的安全。確認的方式很簡單,只要注意看其網址的部分,若是以「https://」開頭的話,表示連線是處於加密狀態,但若開頭是「http://」的話則表示該連線上所傳輸的資料都沒有加密。"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: secure-connections.page:24
+msgctxt "_"
+msgid ""
+"external ref='media/secure-connections/https.png' "
+"md5='364bcbde7a649b0cea9ae178007c1a50'"
+msgstr ""
+"external ref='media/secure-connections/https.png' "
+"md5='364bcbde7a649b0cea9ae178007c1a50'"
+
+#: secure-connections.page:26
+msgid ""
+"The following visualization shows what information is visible to "
+"eavesdroppers with and without Tor Browser and HTTPS encryption:"
+msgstr "底下的視覺化呈現圖表,展示了在有使用以及沒有使用洋蔥路由瀏覽器與 HTTPS 加密連線時,網路監聽者可以攔截竊取到的資料種類分別有:"
+
+#: secure-connections.page:35
+msgid ""
+"Click the “Tor” button to see what data is visible to observers when you're "
+"using Tor. The button will turn green to indicate that Tor is on."
+msgstr "點擊「Tor」按鈕可以查看當您未使用洋蔥路由時,有哪些資料可以讓網路監聽者直接攔截取得,當此按鈕呈現綠色狀態時,表示洋蔥路由功能已經啟動。"
+
+#: secure-connections.page:42
+msgid ""
+"Click the “HTTPS” button to see what data is visible to observers when "
+"you're using HTTPS. The button will turn green to indicate that HTTPS is on."
+msgstr ""
+"您可以點擊「HTTPS」功能按鈕來查看當 HTTPS 啟用時,有哪些資料仍然可能被網路監聽者攔截竊取,而當此按鈕呈現綠色狀態時,表示 HTTPS "
+"功能已經啟動。"
+
+#: secure-connections.page:49
+msgid ""
+"When both buttons are green, you see the data that is visible to observers "
+"when you are using both tools."
+msgstr "當兩個按鈕都是綠色狀態時,您則可以看見在這兩個功能都同時啟動的狀態下,網路監聽者依然能夠竊取到的資料有哪些。"
+
+#: secure-connections.page:55
+msgid ""
+"When both buttons are grey, you see the data that is visible to observers "
+"when you don't use either tool."
+msgstr "而當這兩個按鈕都呈現灰色時,您則可以查看當這兩個功能都在關閉的狀態下時,網路監聽者能夠攔截竊取到的資料有哪些。"
+
+#: secure-connections.page:62
+msgid "Potentially visible data"
+msgstr "可能被攔截竊取的資料"
+
+#: secure-connections.page:70
+msgid "The site being visited."
+msgstr "被造訪的網站。"
+
+#: secure-connections.page:81
+msgid "Username and password used for authentication."
+msgstr "用來認證的使用者名稱與密碼。"
+
+#: secure-connections.page:92
+msgid "Data being transmitted."
+msgstr "被傳送的資料"
+
+#: secure-connections.page:103
+msgid ""
+"Network location of the computer used to visit the website (the public IP "
+"address)."
+msgstr "當此電腦造訪該網站時的網路位置(公眾網路上的IP位址)"
+
+#: secure-connections.page:115
+msgid "Whether or not Tor is being used."
+msgstr "不論是否有使用洋蔥路由"
+
+#: security-slider.page:6
+msgid "Configuring Tor Browser for security and usability"
+msgstr "正在為洋蔥路由瀏覽器進行安全性與可用性設定"
+
+#: security-slider.page:10
+msgid "Security Slider"
+msgstr "安全等級調整棒"
+
+#: security-slider.page:11
+msgid ""
+"Tor Browser includes a “Security Slider” that lets you increase your "
+"security by disabling certain web features that can be used to attack your "
+"security and anonymity. Increasing Tor Browser’s security level will stop "
+"some web pages from functioning properly, so you should weigh your security "
+"needs against the degree of usability you require."
+msgstr ""
+"洋蔥路由瀏覽器有內建一個「安全性等級調整棒」,可以讓您藉由關閉某些可能被利用來破壞安全性或匿名性的網頁功能,來提高自身的資訊安全。然而,提高洋蔥路由瀏覽器的安全等級可能會造成某些網頁的功能無法正常使用,因此您必須要在安全性與可用性兩者之間自行衡量取捨。"
+
+#: security-slider.page:21
+msgid "Accessing the Security Slider"
+msgstr "存取安全性等級調整棒"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: security-slider.page:23
+msgctxt "_"
+msgid ""
+"external ref='media/security-slider/slider.png' "
+"md5='3c469cd3ed9f60ebb6bbbc63daa90082'"
+msgstr ""
+"external ref='media/security-slider/slider.png' "
+"md5='3c469cd3ed9f60ebb6bbbc63daa90082'"
+
+#: security-slider.page:25
+msgid ""
+"The Security Slider is located in Torbutton’s “Privacy and Security "
+"Settings” menu."
+msgstr "安全性等級調整棒位於 Torbutton 裡的「隱私與安全性設定」清單中。"
+
+#: security-slider.page:32
+msgid "Security Levels"
+msgstr "安全性等級"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: security-slider.page:34
+msgctxt "_"
+msgid ""
+"external ref='media/security-slider/slider_window.png' "
+"md5='c733bdccd1731ed1a772777b25bae7a1'"
+msgstr ""
+"external ref='media/security-slider/slider_window.png' "
+"md5='c733bdccd1731ed1a772777b25bae7a1'"
+
+#: security-slider.page:36
+msgid ""
+"Increasing the level of the Security Slider will disable or partially "
+"disable certain browser features to protect against possible attacks."
+msgstr "藉由安全性等級調整棒來提高安全性等級,會讓部分瀏覽器的功能被關閉,以減少遭受到惡意攻擊的可能性。"
+
+#: security-slider.page:42
+msgid "High"
+msgstr "高"
+
+#: security-slider.page:43
+msgid ""
+"At this level, HTML5 video and audio media become click-to-play via "
+"NoScript; all JavaScript performance optimizations are disabled; some "
+"mathematical equations may not display properly; some font rendering "
+"features are disabled; some types of image are disabled; Javascript is "
+"disabled by default on all sites; most video and audio formats are disabled;"
+" and some fonts and icons may not display correctly."
+msgstr ""
+"在此安全性等級下,以 HTML 5 所建構的影音多媒體可透過 NoScript 擴充元件來隨點即播;所有的 JavaScript "
+"效能最佳化功能皆會被關閉;某些數學函式可能無法正常顯示;某些字型渲染功能會被關閉;部分格式的圖形顯示功能會被關閉;所有網站上的 JavaScript "
+"功能都會被關閉;大部分的影片與音效格式的支援都會被關閉;並且某些字型以及圖示可能無法正常顯示。"
+
+#: security-slider.page:53
+msgid "Medium-High"
+msgstr "中-高"
+
+#: security-slider.page:54
+msgid ""
+"At this level, HTML5 video and audio media become click-to-play via "
+"NoScript; all JavaScript performance optimizations are disabled; some "
+"mathematical equations may not display properly; some font rendering "
+"features are disabled; some types of image are disabled; and JavaScript is "
+"disabled by default on all non-<link xref=\"secure-"
+"connections\">HTTPS</link> sites."
+msgstr ""
+"在此安全性等級下,以 HTML5 所建構的影音多媒體可透過 NoScript 擴充元件來隨點即播;所有的 JavaScript "
+"效能最佳化功能皆會被關閉;某些數學函式可能無法正常顯示;某些字型渲染功能會被關閉;部分格式的圖形顯示功能會被關閉;針對不支援<link xref"
+"=\"secure-connections\">HTTPS</link>加密連線的網站關閉 JavaScript 功能。"
+
+#: security-slider.page:64
+msgid "Medium-Low"
+msgstr "中-低"
+
+#: security-slider.page:65
+msgid ""
+"At this level, HTML5 video and audio media become click-to-play via "
+"NoScript; some <link xref=\"plugins\">JavaScript</link> performance "
+"optimizations are disabled, causing some websites to run more slowly; and "
+"some mathematical equations may not display properly."
+msgstr ""
+"在此安全性等級下,以 HTML 5 所建構的影音多媒體可透過 NoScript 擴充元件來隨點即播;部分的 <link "
+"xref=\"plugins\">JavaScript</link> "
+"效能最佳化功能會被關閉,導致某些網站的載入執行速度會變慢;且某些數學函式將無法正常顯示。"
+
+#: security-slider.page:73
+msgid "Low"
+msgstr "低"
+
+#: security-slider.page:74
+msgid ""
+"At this level, all browser features are enabled. This is the most usable "
+"option."
+msgstr "在此安全性等級下,所有瀏覽器的功能都將被啟用,這是可用性最高的安全性模式。"
+
+#: transports.page:6 transports.page:20
+msgid "Types of pluggable transport"
+msgstr "Pluggable Transport 的種類"
+
+#: transports.page:10
+msgid "Pluggable Transports"
+msgstr "可插式傳輸"
+
+#: transports.page:12
+msgid ""
+"Pluggable transports are tools that Tor can use to disguise the traffic it "
+"sends out. This can be useful in situations where an Internet Service "
+"Provider or other authority is actively blocking connections to the Tor "
+"network."
+msgstr ""
+"Pluggable Transport "
+"是一種洋蔥路由用來偽裝其傳輸的資料訊號之特殊工具,當您的網路服務供應商或所處的網路環境會過濾阻擋通往洋蔥路由網路的連線時,此工具即可發揮其功用。"
+
+#: transports.page:21
+msgid ""
+"Currently there are six pluggable transports available, but more are being "
+"developed."
+msgstr "目前已支援的 Pluggable Transport 有六種,此數量正隨著開發進度陸續增加中。"
+
+#: transports.page:28
+msgid "obfs3"
+msgstr "obfs3"
+
+#: transports.page:33
+msgid ""
+"obfs3 makes Tor traffic look random, so that it does not look like Tor or "
+"any other protocol. obfs3 bridges will work in most places."
+msgstr ""
+"obfs3 可以讓洋蔥路由傳送的網路訊號看起來像是隨機亂數,因此讓網路的過濾阻檔機制難以判定此網路連線是否為洋蔥路由網路之連線。在大多數的情況下 "
+"obfs3 橋接器皆可以正常運行。"
+
+#: transports.page:42
+msgid "obfs4"
+msgstr "obfs4"
+
+#: transports.page:47
+msgid ""
+"obfs4 makes Tor traffic look random like obfs3, and also prevents censors "
+"from finding bridges by Internet scanning. obfs4 bridges are less likely to "
+"be blocked than obfs3 bridges."
+msgstr ""
+"obfs4 可以像 obfs3 "
+"一樣讓洋蔥路由所傳送的網路訊號看起來像是隨機亂數一般,並且還可以避免網路過濾監控機制利用網段掃描法找出橋接器的位址,因此相較之下 obfs4 "
+"橋接器更難以被網路監控過濾機制阻擋。"
+
+#: transports.page:56
+msgid "Scramblesuit"
+msgstr "Scramblesuit"
+
+#: transports.page:61
+msgid "ScrambleSuit is similar to obfs4 but has a different set of bridges."
+msgstr "ScrambleSuit 的運作機制和 obfs4 很類似,只不過它使用了不同的橋接器。"
+
+#: transports.page:69
+msgid "FTE"
+msgstr "FTE"
+
+#: transports.page:74
+msgid ""
+"FTE (format-transforming encryption) disguises Tor traffic as ordinary web "
+"(HTTP) traffic."
+msgstr "FTE (format-transforming encryption) 可將洋蔥路由網路連線的訊號偽裝成普通的網路資料封包(HTTP)。"
+
+#: transports.page:82
+msgid "meek"
+msgstr "meek"
+
+#: transports.page:87
+msgid ""
+"These transports all make it look like you are browsing a major web site "
+"instead of using Tor. meek-amazon makes it look like you are using Amazon "
+"Web Services; meek-azure makes it look like you are using a Microsoft web "
+"site; and meek-google makes it look like you are using Google search."
+msgstr ""
+"這些 Pluggable Transport 都可以讓您在使用洋蔥路由來上網時,在網路上傳輸的資料訊號看起來就像是在瀏覽普通網站一樣,meek-"
+"amazon 可以讓您的網路訊號看起來像是在造訪亞馬遜網路服務一樣;meek-azure "
+"則可以讓您的網路訊號看起來像是正在使用微軟的網路雲端服務一般;而 meek-google 會讓您的網路訊號看起來像是在使用谷歌搜尋引擎一樣。"
+
+#: troubleshooting.page:6
+msgid "What to do if Tor Browser doesn’t work"
+msgstr "當洋蔥路由瀏覽器無法正常運形時該怎麼辦"
+
+#: troubleshooting.page:12
+msgid ""
+"You should be able to start browsing the web using Tor Browser shortly after"
+" running the program, and clicking the “Connect” button if you are using it "
+"for the first time."
+msgstr "理論上來說,當洋蔥路由瀏覽器啟動後您應該可以直接開始瀏覽網頁,若是首次啟動的話,頂多只需要再點擊「連線」按鈕即可開始上網。"
+
+#: troubleshooting.page:21
+msgid "Quick fixes"
+msgstr "快速修復"
+
+#: troubleshooting.page:22
+msgid ""
+"If Tor Browser doesn’t connect, there may be a simple solution. Try each of "
+"the following:"
+msgstr "如果洋蔥路由瀏覽器無法連線,可以嘗試底下幾個簡單的解決方式:"
+
+#: troubleshooting.page:29
+msgid ""
+"Your computer’s system clock must be set correctly, or Tor will not be able "
+"to connect."
+msgstr "您電腦系統中的日期與時間必須要正確設定,否則無法建立洋蔥路由的連線。"
+
+#: troubleshooting.page:35
+msgid ""
+"Make sure another Tor Browser is not already running. If you’re not sure if "
+"Tor Browser is running, restart your computer."
+msgstr "請確認系統中沒有開啟另外一個洋蔥路由瀏覽器,若您無法確定洋蔥路由瀏覽器是否有被啟動的話,請將電腦重新開機。"
+
+#: troubleshooting.page:41
+msgid ""
+"Make sure that any antivirus program you have installed is not preventing "
+"Tor from running. You may need to consult the documentation for your "
+"antivirus software if you do not know how to do this."
+msgstr "請確認您電腦中所安裝的防毒軟體不會干擾或阻擋洋蔥路由的運行,若您不確定的話可能需要查閱防毒軟體的相關手冊或說明文件。"
+
+#: troubleshooting.page:49
+msgid "Temporarily disable your firewall."
+msgstr "暫時關閉您的防火牆。"
+
+#: troubleshooting.page:54
+msgid ""
+"Delete Tor Browser and install it again. If updating, do not just overwrite "
+"your previous Tor Browser files; ensure they are fully deleted beforehand."
+msgstr "移除掉洋蔥路由瀏覽器後再重新安裝,若是要更新版本的話,請不要用新版軟體去覆蓋已安裝的舊版本,安裝前先確認舊版本是否已經完全移除。"
+
+#: troubleshooting.page:64
+msgid "Is your connection censored?"
+msgstr "您的網路連線是否有被過濾審查?"
+
+#: troubleshooting.page:65
+msgid ""
+"If you still can’t connect, your Internet Service Provider might be "
+"censoring connections to the Tor network. Read the <link "
+"xref=\"circumvention\">Circumvention</link> section for possible solutions."
+msgstr ""
+"如果您仍然無法連線上網,很有可能是因為您的網路服務供應商有使用會阻擋洋蔥路由網路連線的網路過濾監控系統,請參考<link "
+"xref=\"circumvention\">迴避</link>網頁以瞭解可行的解決方式。"
+
+#: troubleshooting.page:74
+msgid "Known issues"
+msgstr "已知的問題"
+
+#: troubleshooting.page:75
+msgid ""
+"Tor Browser is under constant development, and some issues are known about "
+"but not yet fixed. Please check the <link xref=\"known-issues\">Known "
+"Issues</link> page to see if the problem you are experiencing is already "
+"listed there."
+msgstr ""
+"洋蔥路由瀏覽器的開發仍然不斷地在進行中,有些已知的軟體錯誤但是仍未被修復,您可以查閱<link xref=\"known-"
+"issues\">已知的問題</link>網頁來確認您所遭遇到的問題,是否已經被收錄在其中。"
+
+#: uninstalling.page:6
+msgid "How to remove Tor Browser from your system"
+msgstr "如何從您的系統中移除洋蔥路由瀏覽器"
+
+#: uninstalling.page:10
+msgid "Uninstalling"
+msgstr "反安裝中"
+
+#: uninstalling.page:12
+msgid ""
+"Tor Browser does not affect any of the existing software or settings on your"
+" computer. Uninstalling Tor Browser will not affect your system’s software "
+"or settings."
+msgstr "洋蔥路由瀏覽器不會更動或影響您電腦系統中的設定或其他軟體的運作,移除洋蔥路由瀏覽器亦同。"
+
+#: uninstalling.page:18
+msgid "Removing Tor Browser from your system is simple:"
+msgstr "要從您的系統中將洋蔥路由瀏覽器移除是很簡單的:"
+
+#: uninstalling.page:24
+msgid ""
+"Locate your Tor Browser folder. The default location on Windows is the "
+"Desktop; on Mac OS X it is the Applications folder. On Linux, there is no "
+"default location, however the folder will be named \"tor-browser_en-US\" if "
+"you are running the English Tor Browser."
+msgstr ""
+"先找到您的洋蔥路由瀏覽器目錄,在 Windows 系統中預設是在桌面;在 Mac OS X 中則是應用程式資料夾;而在 Linux "
+"系統中則沒有預設路徑,但是若您的洋蔥路由瀏覽器是英文版的話,那目錄的名稱會是「tor-browser_en-US」。"
+
+#: uninstalling.page:32
+msgid "Delete the Tor Browser folder."
+msgstr "刪除洋蔥路由瀏覽器的目錄。"
+
+#: uninstalling.page:35
+msgid "Empty your Trash"
+msgstr "清空垃圾桶"
+
+#: uninstalling.page:39
+msgid ""
+"Note that your operating system’s standard “Uninstall” utility is not used."
+msgstr "請注意,您作業系統中的標準「反安裝」工具並未被使用。"
+
+#: updating.page:6
+msgid "How to update Tor Browser"
+msgstr "如何更新洋蔥路由瀏覽器"
+
+#: updating.page:10
+msgid "Updating"
+msgstr "更新中"
+
+#: updating.page:12
+msgid ""
+"Tor Browser must be kept updated at all times. If you continue to use an "
+"outdated version of the software, you may be vulnerable to serious security "
+"flaws that compromise your privacy and anonymity."
+msgstr "洋蔥路由瀏覽器必須要隨時保持在最新版本狀態,若您使用較舊版本的話,可能存在某些能夠用來破壞您的隱私性或匿名性的安全性漏洞。"
+
+#: updating.page:18
+msgid ""
+"Tor Browser will prompt you to update the software once a new version has "
+"been released: the Torbutton icon will display a yellow triangle, and you "
+"may see a written update indicator when Tor Browser opens. You can update "
+"either automatically or manually."
+msgstr ""
+"每當洋蔥路由瀏覽器有更新版被釋出時,都會有通報訊息自動出現:Torbutton "
+"功能按鈕會出現黃色三角形圖示,且當您開啟洋蔥路由瀏覽器時,也會以文字說明通知您,此時您可以手動或自動的方式來更新。"
+
+#: updating.page:26
+msgid "Updating Tor Browser automatically"
+msgstr "自動更新洋蔥路由瀏覽器中"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: updating.page:30
+msgctxt "_"
+msgid ""
+"external ref='media/updating/update1.png' "
+"md5='9ff01eb653d92124746fc31efde2bf07'"
+msgstr ""
+"external ref='media/updating/update1.png' "
+"md5='9ff01eb653d92124746fc31efde2bf07'"
+
+#: updating.page:32
+msgid ""
+"When you are prompted to update Tor Browser, click on the Torbutton icon, "
+"then select “Check for Tor Browser Update”."
+msgstr "當您看見洋蔥路由瀏覽器有出現更新版本的通知時,請點擊 Torbutton 按鈕圖示,並點選「確認洋蔥路由瀏覽器的更新」。"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: updating.page:39
+msgctxt "_"
+msgid ""
+"external ref='media/updating/update3.png' "
+"md5='4bd08622b0cacf20b13f75c432176ed3'"
+msgstr ""
+"external ref='media/updating/update3.png' "
+"md5='4bd08622b0cacf20b13f75c432176ed3'"
+
+#: updating.page:41
+msgid ""
+"When Tor Browser has finished checking for updates, click on the “Update” "
+"button."
+msgstr "當洋蔥路由瀏覽器完成更新確認後,請點擊「更新」按鈕。"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: updating.page:48
+msgctxt "_"
+msgid ""
+"external ref='media/updating/update4.png' "
+"md5='1d795e7b695738531db9d4b2b0fb5313'"
+msgstr ""
+"external ref='media/updating/update4.png' "
+"md5='1d795e7b695738531db9d4b2b0fb5313'"
+
+#: updating.page:50
+msgid ""
+"Wait for the update to download and install, then restart Tor Browser. You "
+"will now be running the latest version."
+msgstr "請稍候等軟體更新下載並安裝完成後再重新啟動洋蔥路由瀏覽器,此時您的瀏覽器就將會是最新版本了。"
+
+#: updating.page:58
+msgid "Updating Tor Browser manually"
+msgstr "手動更新洋蔥路由瀏覽器中"
+
+#: updating.page:61
+msgid ""
+"When you are prompted to update Tor Browser, finish the browsing session and"
+" close the program."
+msgstr "當洋蔥路由瀏覽器通知您必須要更新時,請結束網頁瀏覽並關閉瀏覽器。"
+
+#: updating.page:67
+msgid ""
+"Remove Tor Browser from your system by deleting the folder that contains it "
+"(see the <link xref=\"uninstalling\">Uninstalling</link> section for more "
+"information)."
+msgstr "刪除洋蔥路由瀏覽器目錄以將軟體移除(請參考<link xref=\"uninstalling\">反安裝</link>以取得更多相關資訊)。"
+
+#: updating.page:74
+msgid ""
+"Visit <link href=\"https://www.torproject.org/projects/torbrowser.html.en\">"
+" https://www.torproject.org/projects/torbrowser.html.en</link> and download "
+"a copy of the latest Tor Browser release, then install it as before."
+msgstr ""
+"請到 <link href=\"https://www.torproject.org/projects/torbrowser.html.en\"> "
+"https://www.torproject.org/projects/torbrowser.html.en</link> "
+"下載最新版的洋蔥路由瀏覽器,並用和之前一樣的方式將它安裝進系統中。"
1
0
commit 638cadb079a490084b704bcd36356ec0f23e20e0
Author: Colin Childs <colin(a)torproject.org>
Date: Tue Sep 18 14:19:05 2018 -0500
Adding ca translations
---
Makefile.am | 2 +-
ca/ca.po | 1975 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 1976 insertions(+), 1 deletion(-)
diff --git a/Makefile.am b/Makefile.am
index 062f4dd..03d31aa 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -8,7 +8,7 @@ TOR_AND_HTTPS = ../tor-and-https
HELP_ID = tor-browser-user-manual
HELP_FILES = $(shell cd $(srcdir)/C && git ls-files '*.page')
HELP_MEDIA = $(shell cd $(srcdir)/C && git ls-files 'media')
-HELP_LINGUAS = en-US ja sv ga bn_BD id @TOR_BROWSER_BUNDLE_LOCALES@
+HELP_LINGUAS = en-US ja sv ga bn_BD id ca @TOR_BROWSER_BUNDLE_LOCALES@
.PHONY: html
html: all media-symlinks.stamp
diff --git a/ca/ca.po b/ca/ca.po
new file mode 100644
index 0000000..f3357f5
--- /dev/null
+++ b/ca/ca.po
@@ -0,0 +1,1975 @@
+# Translators:
+# laia_, 2016
+# Albert <provisionalib(a)hotmail.com>, 2016
+# F Xavier Castane <electromigracion(a)gmail.com>, 2016
+# Gerard Farràs Ballabriga <>, 2016
+# joanj94 <joanj_94(a)hotmail.com>, 2016
+# icc <mail(a)koopic.net>, 2016
+# escufi <escufi(a)gmail.com>, 2018
+# Vte A.F <viarfer3(a)inf.upv.es>, 2018
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"POT-Creation-Date: 2018-09-07 16:48-0500\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Vte A.F <viarfer3(a)inf.upv.es>, 2018\n"
+"Language-Team: Catalan (https://www.transifex.com/otf/teams/1519/ca/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: ca\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#. Put one translator per line, in the form NAME <EMAIL>, YEAR1, YEAR2
+msgctxt "_"
+msgid "translator-credits"
+msgstr "Informació del traductor"
+
+#: about-tor-browser.page:7
+msgid "Learn what Tor Browser can do to protect your privacy and anonymity"
+msgstr ""
+"Aprengui com pot el navegador Tor protegir-lo amb anonimat i privacitat"
+
+#: about-tor-browser.page:10
+msgid "About Tor Browser"
+msgstr "Sobre el navegador Tor"
+
+#: about-tor-browser.page:12
+msgid ""
+"Tor Browser uses the Tor network to protect your privacy and anonymity. "
+"Using the Tor network has two main properties:"
+msgstr ""
+"El navegador Tor utilitza la xarxa Tor per protegir l'anonimat i la "
+"privacitat. Utilitzant la xarxa Tor existeixen 2 propietats:"
+
+#: about-tor-browser.page:18
+msgid ""
+"Your internet service provider, and anyone watching your connection locally,"
+" will not be able to track your internet activity, including the names and "
+"addresses of the websites you visit."
+msgstr ""
+"El proveïdor d'Internet i qualsevulla persona que observi la connexió local,"
+" no podran fer seguiment de la activitat d'Internet, incloent el nom i "
+"direcció dels webs que visiti."
+
+#: about-tor-browser.page:25
+msgid ""
+"The operators of the websites and services that you use, and anyone watching"
+" them, will see a connection coming from the Tor network instead of your "
+"real Internet (IP) address, and will not know who you are unless you "
+"explicitly identify yourself."
+msgstr ""
+" Els administradors de webs i serveis que s'utilitzin, o qualsevol que sigui"
+" observant de la connexió, veurà una connexió que prové de la xarxa Tor en "
+"lloc de l'adreça (IP) real, i no podrà saber la seva identitat a menys que "
+"ho expliciti."
+
+#: about-tor-browser.page:34
+msgid ""
+"In addition, Tor Browser is designed to prevent websites from "
+"“fingerprinting” or identifying you based on your browser configuration."
+msgstr ""
+"A més, el navegador Tor està dissenyat per prevenir pàgines web amb "
+"identificació per empremta digital o identificació mitjançant els paràmetres"
+" del navegador."
+
+#: about-tor-browser.page:39
+msgid ""
+"By default, Tor Browser does not keep any browsing history. Cookies are only"
+" valid for a single session (until Tor Browser is exited or a <link xref"
+"=\"managing-identities#new-identity\">New Identity</link> is requested)."
+msgstr ""
+"Per defecte, el navegador Tor no desa l'historial de navegació. Les galetes "
+"només són vàlides per la sessió en marxa (fins que el navegador Tor es "
+"tanqui o <link xref=\"managing-identities#new-identity\"Nova "
+"identitat</link> es sol·licitada)."
+
+#: about-tor-browser.page:50
+msgid "How Tor works"
+msgstr "Com funciona Tor"
+
+#: about-tor-browser.page:52
+msgid ""
+"Tor is a network of virtual tunnels that allows you to improve your privacy "
+"and security on the Internet. Tor works by sending your traffic through "
+"three random servers (also known as <em>relays</em>) in the Tor network. The"
+" last relay in the circuit (the “exit relay”) then sends the traffic out "
+"onto the public Internet."
+msgstr ""
+"Tor és una xarxa de túnels virtuals que permeten incrementar la privacitat i"
+" la seguretat a Internet. Tor funciona enviant el tràfic de dades a 3 "
+"servidors aleatòris (també anomenats com <em>relés</em>) a la xarxa Tor. "
+"L'últim relé del circuit (el relé de sortida) envia la informació al "
+"Internet públic."
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: about-tor-browser.page:59
+msgctxt "_"
+msgid ""
+"external ref='media/how-tor-works.png' "
+"md5='6fe4151a88b7a518466f0582e40ccc8c'"
+msgstr ""
+"external ref='media/how-tor-works.png' "
+"md5='6fe4151a88b7a518466f0582e40ccc8c'"
+
+#: about-tor-browser.page:60
+msgid ""
+"The image above illustrates a user browsing to different websites over Tor. "
+"The green middle computers represent relays in the Tor network, while the "
+"three keys represent the layers of encryption between the user and each "
+"relay."
+msgstr ""
+"La imatge superior mostra un navegador d'usuari amb diferents webs "
+"mitjançant Tor. L'ordinador verd del centre representa el relé en la xarxa "
+"Tor, mentre que les 3 claus representen les capes d'encriptació entre "
+"l'usuari i el relé."
+
+#: bridges.page:6
+msgid "Learn what bridges are and how to get them"
+msgstr "Aprengui sobre que són els ponts i com aconseguir-los."
+
+#: bridges.page:10
+msgid "Bridges"
+msgstr "Ponts"
+
+#: bridges.page:12
+msgid ""
+"Most <link xref=\"transports\">Pluggable Transports</link>, such as obfs3 "
+"and obfs4, rely on the use of “bridge” relays. Like ordinary Tor relays, "
+"bridges are run by volunteers; unlike ordinary relays, however, they are not"
+" listed publicly, so an adversary cannot identify them easily. Using bridges"
+" in combination with pluggable transports helps to disguise the fact that "
+"you are using Tor."
+msgstr ""
+"La majoria <link xref=\"transports\">Transports connectors</link>, com obfs3"
+" i obfs4, utilitzen els relés de \"pont\". Com el relés estàndard de Tor, "
+"els ponts són usuaris voluntaris; a diferència els relés tradicionals, "
+"independentment, no estan llistat, d'aquesta manera no poden ser fàcilment "
+"identificats. La utilització de ponts en combinació amb els transports "
+"connectors ajuden a disfressar la utilització de Tor."
+
+#: bridges.page:21
+msgid ""
+"Other pluggable transports, like meek, use different anti-censorship "
+"techniques that do not rely on bridges. You do not need to obtain bridge "
+"addresses in order to use these transports."
+msgstr ""
+"Altres transports connectors, com Meek, utilitzant altres tècniques anit-"
+"censura sense ponts. No es precisen l'obtenció de direccions ponts."
+
+#: bridges.page:28
+msgid "Getting bridge addresses"
+msgstr "Obtenció de direcció pont"
+
+#: bridges.page:29
+msgid ""
+"Because bridge addresses are not public, you will need to request them "
+"yourself. You have two options:"
+msgstr ""
+"Com que les direccions ponts no són públiques, s'hauran de demanar en "
+"l'instant. Existeixen dos opcions:"
+
+#: bridges.page:36
+msgid ""
+"Visit <link "
+"href=\"https://bridges.torproject.org/\">https://bridges.torproject.org/</link>"
+" and follow the instructions, or"
+msgstr ""
+"Visita <link "
+"href=\"https://bridges.torproject.org/\">https://bridges.torproject.org/</link>"
+" i segueixi les instruccions, o"
+
+#: bridges.page:42
+msgid ""
+"Email bridges(a)torproject.org from a Gmail, Yahoo, or Riseup email address, "
+"or"
+msgstr ""
+"Correu electrònic bridges(a)torproject.org des de Gmail, Yahoo, o Riseup o"
+
+#: bridges.page:51
+msgid "Entering bridge addresses"
+msgstr "Entri la direcció pont"
+
+#: bridges.page:52
+msgid ""
+"Once you have obtained some bridge addresses, you will need to enter them "
+"into Tor Launcher."
+msgstr ""
+"Un cop s'hagi obtingut alguna direcció pont, l'haurà d'introduir en el Tor "
+"Launcher."
+
+#: bridges.page:57
+msgid ""
+"Choose “yes” when asked if your Internet Service Provider blocks connections"
+" to the Tor network. Select “Use custom bridges” and enter each bridge "
+"address on a separate line."
+msgstr ""
+"Esculli \"si\" quan sigui preguntat si el seu proveïdor d'Internet bloqueja "
+"les connexions a la xarxa Tor. Seleccioni \"Utilització de ponts "
+"personalitzat\" i introdueixi en linines separades les direccions pont."
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: bridges.page:63
+msgctxt "_"
+msgid ""
+"external ref='media/tor-launcher-custom-bridges.png' "
+"md5='34b5e99516d297fcbb467209d8479f40'"
+msgstr ""
+"external ref='media/tor-launcher-custom-bridges.png' "
+"md5='34b5e99516d297fcbb467209d8479f40'"
+
+#: bridges.page:65
+msgid ""
+"Click “Connect”. Using bridges may slow down the connection compared to "
+"using ordinary Tor relays. If the connection fails, the bridges you received"
+" may be down. Please use one of the above methods to obtain more bridge "
+"addresses, and try again."
+msgstr ""
+"Faci clic en \"Connectar\". La utilització de ponts pot alentir la connexió "
+"comparat amb l'ús de relés estàndard Tor. Si la connexió falla, el ponts "
+"obtingut haurà caigut. Si us plau, utilitzi un del mencionats a sobre per "
+"obtindre més direccions ponts, i provi-ho posteriorment."
+
+#: circumvention.page:6
+msgid "What to do if the Tor network is blocked"
+msgstr "Que fer si la xarxa Tor està bloquejada"
+
+#: circumvention.page:10
+msgid "Circumvention"
+msgstr "Elusió"
+
+#: circumvention.page:12
+msgid ""
+"Direct access to the Tor network may sometimes be blocked by your Internet "
+"Service Provider or by a government. Tor Browser includes some circumvention"
+" tools for getting around these blocks. These tools are called “pluggable "
+"transports”. See the <link xref=\"transports\">Pluggable Transports</link> "
+"page for more information on the types of transport that are currently "
+"available."
+msgstr ""
+"L'accés a la xarxa Tor pot tot sovint ser bloquejat pel seu proveïdor "
+"d'Internet o pel govern. El navegador Tor incorpora una serie de programari "
+"per evitar-ho. Aquestes eines s'anomenen \"connectors de transport\". "
+"Consulti <link xref=\"transports\">connectors de transport</link> per a més "
+"informació del tipus de transport disponible."
+
+#: circumvention.page:22
+msgid "Using pluggable transports"
+msgstr "Utilització de connectors de transport"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: circumvention.page:26 first-time.page:35
+msgctxt "_"
+msgid ""
+"external ref='media/circumvention/configure.png' "
+"md5='1107595d21fe90f2aab1263d7fb0abd3'"
+msgstr ""
+"external ref='media/circumvention/configure.png' "
+"md5='1107595d21fe90f2aab1263d7fb0abd3'"
+
+#: circumvention.page:28
+msgid ""
+"To use pluggable transports, click \"Configure\" in the Tor Launcher window "
+"that appears when you first run Tor Browser."
+msgstr ""
+"Per l'utilització de connectors de transport, faci clic a \"Paràmetres\" en "
+"el iniciador de Tor que apareix qua s'utilitza per primer cop."
+
+#: circumvention.page:33
+msgid ""
+"You can also configure pluggable transports while Tor Browser is running, by"
+" clicking on the green onion near your address bar and selecting “Tor "
+"Network Settings”."
+msgstr ""
+"També pot configurar els connectors de transport mentre el navegador Tor "
+"està executant-se, amb el clic en la ceba verda aprop de la barra d'adreces "
+"i seleccionar \"Paràmetres de xarxa Tor\"."
+
+#: circumvention.page:41
+msgid ""
+"Select “yes” when asked if your Internet Service Provider blocks connections"
+" to the Tor network."
+msgstr ""
+"Seleccioni \"Si\" quan sigui preguntat si el seu proveïdor d'Internet "
+"bloqueja les connexions de la xarxa Tor."
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: circumvention.page:49
+msgctxt "_"
+msgid ""
+"external ref='media/circumvention/bridges.png' "
+"md5='f5acc05bd9bacf6c69a31163d25a8778'"
+msgstr ""
+"external ref='media/circumvention/bridges.png' "
+"md5='f5acc05bd9bacf6c69a31163d25a8778'"
+
+#: circumvention.page:51
+msgid ""
+"Select “Connect with provided bridges”. Tor Browser currently has six "
+"pluggable transport options to choose from."
+msgstr ""
+"Seleccioni \"Connectar amb ponts\". El navegador Tor actualment té sis "
+"connectors de transport disponibles."
+
+#: circumvention.page:60
+msgid "Which transport should I use?"
+msgstr "Quin tipus de transport vol utilitzar?"
+
+#: circumvention.page:61
+msgid ""
+"Each of the transports listed in Tor Launcher’s menu works in a different "
+"way (for more details, see the <link xref=\"transports\">Pluggable "
+"Transports</link> page), and their effectiveness depends on your individual "
+"circumstances."
+msgstr ""
+"Cadascun dels transports llistat en el menú d'iniciador Tor treballa de "
+"manera diferent (per més informació, consultar <link "
+"xref=\"transports\">connectors de transport</link> pàgina) per saber la seva"
+" efectivitat depenen de les circumstàncies individuals. "
+
+#: circumvention.page:67
+msgid ""
+"If you are trying to circumvent a blocked connection for the first time, you"
+" should try the different transports: obfs3, obfs4, ScrambleSuit, fte, meek-"
+"azure and Snowflake."
+msgstr ""
+"Si esteu intentant evitar una connexió bloquejada per primera vegada, heu de"
+" provar els diferents transports: obfs3, obfs4, ScrambleSuit, fte, meek-"
+"azure i Snowflake."
+
+#: circumvention.page:72
+msgid ""
+"If you try all of these options, and none of them gets you online, you will "
+"need to enter bridge addresses manually. Read the <link "
+"xref=\"bridges\">Bridges</link> section to learn what bridges are and how to"
+" obtain them."
+msgstr ""
+"Si priva totes aquestes opcions, i cap resulta amb una connexió vàlida, "
+"haurà d'introduir una adreça de pont de forma manual. Llegeixi <link "
+"xref=\"bridges\">Ponts</link> la secció d'aprenentatge sobre ponts per saber"
+" com fer-ho."
+
+#: downloading.page:7
+msgid "How to download Tor Browser"
+msgstr "Com descarregar el navegador Tor."
+
+#: downloading.page:10
+msgid "Downloading"
+msgstr "Descarregant"
+
+#: downloading.page:12
+msgid ""
+"The safest and simplest way to download Tor Browser is from the official Tor"
+" Project website at https://www.torproject.org. Your connection to the site "
+"will be secured using <link xref=\"secure-connections\">HTTPS</link>, which "
+"makes it much harder for somebody to tamper with."
+msgstr ""
+"La manera segura i simple de descarregar el navegador Tor és mitjançant la "
+"pàgina oficial del projecte Tor en el web https://www.torproject.org. La "
+"connexió s'estableix de forma segura mitjançat <link xref=\"secure-"
+"connections\">HTTPS</link>, que permet evitar les falsificacions."
+
+#: downloading.page:19
+msgid ""
+"However, there may be times when you cannot access the Tor Project website: "
+"for example, it could be blocked on your network. If this happens, you can "
+"use one of the alternative download methods listed below."
+msgstr ""
+"Com sigui, hi han diverses maneres d'evitar l'accés al web del Projecte Tor:"
+" per exemple, el bloqueig en la xarxa d'accés. Si això succeïx, pot "
+"utilitzar un dels llocs de descàrrega que es citen a continuació."
+
+#: downloading.page:27
+msgid "GetTor"
+msgstr "Obtenir Tor"
+
+#: downloading.page:28
+msgid ""
+"GetTor is a service that automatically responds to messages with links to "
+"the latest version of Tor Browser, hosted at a variety of locations, such as"
+" Dropbox, Google Drive and GitHub."
+msgstr ""
+"GetTor és un servei que respon automàticament a missatges amb enllaços a la "
+"versió més recent del navegador de Tor, allotjada en diverses ubicacions, "
+"com ara Dropbox, Google Drive i GitHub."
+
+#: downloading.page:33
+msgid "To use GetTor via email:"
+msgstr "Per utilitzar Obtenir Tor per correu electrònic:"
+
+#: downloading.page:38
+msgid ""
+"Send an email to gettor(a)torproject.org, and in the body of the message "
+"simply write “windows”, “osx”, or “linux”, (without quotation marks) "
+"depending on your operating system."
+msgstr ""
+"Enviï un correu electrònic a gettor(a)torproject.org, i en el cos del missatge"
+" escrigui les paraules \"windows\", \"osx\" o \"linux\", (sense cometes) "
+"depenen del tipus de sistema operatiu que tingui."
+
+#: downloading.page:45
+msgid ""
+"GetTor will respond with an email containing links from which you can "
+"download the Tor Browser package, the cryptographic signature (needed for "
+"verifying the download), the fingerprint of the key used to make the "
+"signature, and the package’s checksum. You may be offered a choice of "
+"“32-bit” or “64-bit” software: this depends on the model of the computer you"
+" are using."
+msgstr ""
+"Obtenir Tor contestarà amb un correu electrònic amb enllaços per a la "
+"descàrrega dle paquet de dades del navegador Tor, la signatura criptogràfica"
+" (que es precisa per verificar al descàrrega), la empremta digital "
+"utilitzada com a signatura, i la suma de verificació. Haurà d'escollir entre"
+" la opció de \"32-bit\" o \"64-bit\" depenen del processador de càlcul del "
+"ordinador."
+
+#: downloading.page:56
+msgid "To use GetTor via Twitter:"
+msgstr "Per utilitzar Obtenir Tor mitjançant Twitter: "
+
+#: downloading.page:61
+msgid ""
+"To get links for downloading Tor Browser in English for OS X, send a Direct "
+"Message to @get_tor with the words \"osx en\" in it (you don't need to "
+"follow the account)."
+msgstr ""
+"Per obtenir els enllaços per la descàrrega del navegador Tor en anglès per "
+"OS X, enviï una piulada a @get_tor amb el següent text: \"osx en\" (no "
+"precisa se seguidor del compte)."
+
+#: downloading.page:69
+msgid "To use GetTor via Jabber/XMPP (Jitsi, CoyIM, etc.):"
+msgstr "Per utilitzar GetTor a través de Jabber/XMPP (Jitsi, CoyIM, etc.):"
+
+#: downloading.page:74
+msgid ""
+"To get links for downloading Tor Browser in Chinese for Linux, send a "
+"message to gettor(a)torproject.org with the words \"linux zh\" in it."
+msgstr ""
+"Per obtenir enllaços per la descàrrega del navegado Tor en Xinès per Linux, "
+"enviï un correu electrònic gettor(a)torproject.org amb les següents paraules "
+"en el cos del missatge: linux zh\"."
+
+#: downloading.page:83
+msgid "Satori"
+msgstr "Satori"
+
+#: downloading.page:84
+msgid ""
+"Satori is an add-on for the Chrome or Chromium browsers that allows you to "
+"download several security and privacy programs from different sources."
+msgstr ""
+"Satori és un complement pels navegadors Chrome o Chromium que permet la "
+"descàrrega de diversos programes de seguretat i privacitat mitjançant "
+"diferents fonts."
+
+#: downloading.page:89
+msgid "To download Tor Browser using Satori:"
+msgstr "Per la descàrrega del navegador Tor mitjançant Satori:"
+
+#: downloading.page:94
+msgid "Install Satori from the Chrome App Store."
+msgstr "Instal·lar Satori des de Chrome App Store."
+
+#: downloading.page:99
+msgid "Select Satori from your browser’s Apps menu."
+msgstr "Seleccioni Satori del menú d'aplicacions del navegador."
+
+#: downloading.page:104
+msgid ""
+"When Satori opens, click on your preferred language. A menu will open "
+"listing the available downloads for that language. Find the entry for Tor "
+"Browser under the name of your operating system. Select either “A” or “B” "
+"after the name of the program — each one represents a different source from "
+"which to get the software. Your download will then begin."
+msgstr ""
+"Quan Satori s'executi, seleccioni la llengua. Un menú de selecció dels "
+"llenguatges descarregats s'obrirà. Cerqui la entrada pel navegador Tor sota "
+"el nom del sistema operatiu. Seleccioni \"A\" o \"B\" després del nom o del "
+"programa - cadascun representa diferents fonts d'on obtindre el programari, "
+"posteriorment la descàrrega començarà. "
+
+#: downloading.page:114
+msgid ""
+"Wait for your download to finish, then find the “Generate Hash” section in "
+"Satori’s menu and click “Select Files”."
+msgstr ""
+"Esperi per la descàrrega completa, posteriorment cerqui \"Generar resum\" "
+"del menú Satori i fer clic en \"Selecció d'arxiu\"."
+
+#: downloading.page:120
+msgid ""
+"Select the downloaded Tor Browser file. Satori will display the checksum of "
+"the file, which you should compare with the software’s original checksum: "
+"you can find this by clicking the word “checksum” after the link you clicked"
+" on to start the download. If the checksums match, your download was "
+"successful, and you can <link xref=\"first-time\">begin using Tor "
+"Browser</link>. If they do not match, you may need to try downloading again,"
+" or from a different source."
+msgstr ""
+"Seleccioni l'arxiu del navegador Tor. Satori mostrarà la suma de verificació"
+" de l'arxiu, que haurà de comprar amb la suma que mostra el programari: "
+"accedint fent clic en la paraula \"suma de verificació\" després de començar"
+" al descàrrega. Si la suma coincideix, la descàrrega ha estat satisfactòria,"
+" i es podrà <link xref=\"first-time\">començar a utilitzar el navegador "
+"Tor</link>. Si no coincideixen, haurà de fer la descàrrega de nou, o potser "
+"des de una font diferent."
+
+#: first-time.page:7
+msgid "Learn how to use Tor Browser for the first time"
+msgstr "Aprengui com utilitzar per primer cop el navegador Tor."
+
+#: first-time.page:10
+msgid "Running Tor Browser for the first time"
+msgstr "Executant per primer cop el navegador Tor."
+
+#: first-time.page:12
+msgid ""
+"When you run Tor Browser for the first time, you will see the Tor Network "
+"Settings window. This offers you the option to connect directly to the Tor "
+"network, or to configure Tor Browser for your connection."
+msgstr ""
+"Quan s'executi per primer cop el navegador Tor, s'obriran els paràmetres de "
+"xarxa Tor. Permetent la opció de connexió directa a la xarxa Tor, o "
+"configurar el navegador Tor per les connexions."
+
+#: first-time.page:19
+msgid "Connect"
+msgstr "Conecta't"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: first-time.page:21 troubleshooting.page:18
+msgctxt "_"
+msgid ""
+"external ref='media/first-time/connect.png' "
+"md5='f6de80de01c8fa2a8f80857eb8213768'"
+msgstr ""
+"external ref='media/first-time/connect.png' "
+"md5='f6de80de01c8fa2a8f80857eb8213768'"
+
+#: first-time.page:23
+msgid ""
+"In most cases, choosing \"Connect\" will allow you to connect to the Tor "
+"network without any further configuration. Once clicked, a status bar will "
+"appear, showing Tor’s connection progress. If you are on a relatively fast "
+"connection, but this bar seems to get stuck at a certain point, see the "
+"<link xref=\"troubleshooting\">Troubleshooting</link> page for help solving "
+"the problem."
+msgstr ""
+"En molts casos, escollint \"Connectat\" permetrà la connexió a la xarxa Tor "
+"sense més configuració. Un cop fet clic, la barra d'estat apareixerà, "
+"mostrat la progressió de la connexió Tor. La progressió dependrà de la "
+"velocitat de connexió, si experimentà algun problema, consulti <link "
+"xref=\"troubleshooting\">Resolució de problemes</link> la pàgina per tronar "
+"una solució."
+
+#: first-time.page:33
+msgid "Configure"
+msgstr "Configura"
+
+#: first-time.page:37
+msgid ""
+"If you know that your connection is censored, or uses a proxy, you should "
+"select this option. Tor Browser will take you through a series of "
+"configuration options."
+msgstr ""
+"Si coneix que les seves connexions pateixen censura, o utilitza un servidor "
+"intermedi, seleccioni aquesta opció. El navegador Tor permetrà fer les "
+"configuracions pertinents."
+
+#: first-time.page:44
+msgid ""
+"The first screen asks if access to the Tor network is blocked or censored on"
+" your connection. If you do not believe this is the case, select “No”. If "
+"you know your connection is censored, or you have tried and failed to "
+"connect to the Tor network and no other solutions have worked, select “Yes”."
+" You will then be taken to the <link "
+"xref=\"circumvention\">Circumvention</link> screen to configure a pluggable "
+"transport."
+msgstr ""
+"La primera pantalla pregunta si l'accés a la xarxa Tor està bloquejada o "
+"censurada. Si creu que no és el cas, seleccioni \"No\". Si creu que la seva "
+"connexió està censurada, o ha fet un intent fallit de connexió a la xarxa "
+"Tor i cap solució ha funcionat, seleccioni \"Si\". Posteriorment serà "
+"derivat a <link xref=\"elusió\">Circumvention</link> a la pantalla de "
+"paràmetres dels connectors de transport."
+
+#: first-time.page:55
+msgid ""
+"The next screen asks if your connection uses a proxy. In most cases, this is"
+" not necessary. You will usually know if you need to answer “Yes”, as the "
+"same settings will be used for other browsers on your system. If possible, "
+"ask your network administrator for guidance. If your connection does not use"
+" a proxy, click “Continue”."
+msgstr ""
+"La pròxima pantalla pregunta si la seva connexió utilitza un servidor "
+"intermedi. En molts casos, no és necessari. En cas afirmatiu cliqui \"Si\", "
+"els mateixos paràmetres seran aplicats a tots els navegadors del sistema. Si"
+" és possible, pregunti al seu administrador de xarxa. Si la connexió no "
+"utilitza un servidor intermedi, cliqui \"Continuar\"."
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: first-time.page:63
+msgctxt "_"
+msgid ""
+"external ref='media/first-time/proxy_question.png' "
+"md5='f72753a963e3449129718e3d824a8ac8'"
+msgstr ""
+"external ref='media/first-time/proxy_question.png' "
+"md5='f72753a963e3449129718e3d824a8ac8'"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: first-time.page:66
+msgctxt "_"
+msgid ""
+"external ref='media/first-time/proxy.png' "
+"md5='9a5cf5c044b1dfc5f006a9d1ff77507b'"
+msgstr ""
+"external ref='media/first-time/proxy.png' "
+"md5='9a5cf5c044b1dfc5f006a9d1ff77507b'"
+
+#: index.page:8
+msgid "Tor Browser User Manual"
+msgstr "Manual d'usuari del navegador Tor"
+
+#: known-issues.page:6
+msgid "A list of known issues."
+msgstr "Un llistat d'assumptes coneguts"
+
+#: known-issues.page:10
+msgid "Known Issues"
+msgstr "Assumptes coneguts"
+
+#: known-issues.page:14
+msgid ""
+"Tor needs your system clock (and your time zone) set to the correct time."
+msgstr ""
+"Tor necessita el rellotge de sistema (i el fus horari) per configurar el "
+"temps correctament."
+
+#: known-issues.page:19
+msgid ""
+"The following firewall software have been known to interfere with Tor and "
+"may need to be temporarily disabled:"
+msgstr ""
+"El següent programari tallafoc ha interferit amb Tor i s'hauria de "
+"deshabilitar de forma temporal."
+
+#: known-issues.page:23
+msgid "Webroot SecureAnywhere"
+msgstr "Webroot SecureAnywhere"
+
+#: known-issues.page:26
+msgid "Kaspersky Internet Security 2012"
+msgstr "Kaspersky Internet Security 2012"
+
+#: known-issues.page:29
+msgid "Sophos Antivirus for Mac"
+msgstr "Sophos Antivirus per Mac"
+
+#: known-issues.page:32
+msgid "Microsoft Security Essentials"
+msgstr "Microsoft Security Essentials"
+
+#: known-issues.page:37
+msgid ""
+"Videos that require Adobe Flash are unavailable. Flash is disabled for "
+"security reasons."
+msgstr ""
+"Els vídeos que precisen d'Adobe Flash són inaccessibles per motius de "
+"seguretat."
+
+#: known-issues.page:43
+msgid "Tor can not use a bridge if a proxy is set."
+msgstr ""
+"Tor no pot utilitzar un pont si el servidor intermedi està configurat."
+
+#: known-issues.page:48
+msgid ""
+"The Tor Browser package is dated January 1, 2000 00:00:00 UTC. This is to "
+"ensure that each software build is exactly reproducible."
+msgstr ""
+"El paquet d'aplicació del navegador Tor està datat a 1 de gener, 2000 "
+"00:00:00 UTC. Això permet assegurar que la versió és reproduïble. "
+
+#: known-issues.page:54
+msgid ""
+"To run Tor Browser on Ubuntu, users need to execute a shell script. Open "
+"\"Files\" (Unity's explorer), open Preferences → Behavior Tab → Set \"Run "
+"executable text files when they are opened\" to \"Ask every time\", then "
+"click OK."
+msgstr ""
+"Per executar el navegador Tor sobre Ubuntu, s'haurà d'executar mitjançant "
+"shell script. Per això accedir a \"Arxius\" (navegador unificat), "
+"Paràmetres → Comportament pestanyes → Configurar, executar l'arxiu de text "
+"quan s'obri la pantalla emergent a \"Preguntar cada cop\" i fer clic a "
+"\"Acceptar\"."
+
+#: known-issues.page:62
+msgid ""
+"Tor Browser can also be started from the command line by running the "
+"following command from inside the Tor Browser directory:"
+msgstr ""
+"El navegador Tor pot ser inicialitzat per línia de comanda mitjançant la "
+"següent instrucció en el director del navegador Tor:"
+
+#: known-issues.page:66
+#, no-wrap
+msgid ""
+"\n"
+" ./start-tor-browser.desktop\n"
+" "
+msgstr ""
+"\n"
+"./start-tor-browser.desktop"
+
+#: managing-identities.page:6
+msgid "Learn how to control personally-identifying information in Tor Browser"
+msgstr ""
+"Aprengui com controlar la informació d'identificació personal al navegador "
+"Tor."
+
+#: managing-identities.page:10
+msgid "Managing identities"
+msgstr "Administrador d'identitats"
+
+#: managing-identities.page:12
+msgid ""
+"When you connect to a website, it is not only the operators of that website "
+"who can record information about your visit. Most websites now use numerous "
+"third-party services, including social networking “Like” buttons, analytics "
+"trackers, and advertising beacons, all of which can link your activity "
+"across different sites."
+msgstr ""
+"Quan es connecta a un lloc web, no tan sols els administradors del web poden"
+" tenir informació sobre la visita. Molts webs utilitzant programari de "
+"tercers, incloent els botons d'agradar de xarxes socials, rastrejadors i "
+"publicitat, tots ells poden enllaçar la seva activitat de navegació en "
+"diferents webs."
+
+#: managing-identities.page:20
+msgid ""
+"Using the Tor network stops observers from being able to discover your exact"
+" location and IP address, but even without this information they might be "
+"able to link different areas of your activity together. For this reason, Tor"
+" Browser includes some additional features that help you control what "
+"information can be tied to your identity."
+msgstr ""
+"Utilitzant la xarxa Tor es pot aturar l'observació de la localització "
+"mitjançant la seva direcció IP, però fins i tot sense aquesta informació "
+"poden arribar a enllaçar diferents àrees de la seva activitat. Per aquesta "
+"raó, el navegador Tor inclou característiques addicionals que permeten "
+"ajudar al control de quina informació pot enllaçar-se a la seva identitat."
+
+#: managing-identities.page:29
+msgid "The URL bar"
+msgstr "Barra de URL"
+
+#: managing-identities.page:30
+msgid ""
+"Tor Browser centers your web experience around your relationship with the "
+"website in the URL bar. Even if you connect to two different sites that use "
+"the same third-party tracking service, Tor Browser will force the content to"
+" be served over two different Tor circuits, so the tracker will not know "
+"that both connections originate from your browser."
+msgstr ""
+"El navegador Tor centra la experiència web amb la barra d'URL. Fins i tot si"
+" es connecta a dos llocs web diferents que utilitzen el mateix sistema de "
+"rastrejament de terceres parts, el navegador Tor forçarà que el contingut "
+"viatgi per dos circuits independents, per tant el rastrejador no podrà "
+"conèixer la relació entre les dues peticions."
+
+#: managing-identities.page:38
+msgid ""
+"On the other hand, all connections to a single website address will be made "
+"over the same Tor circuit, meaning you can browse different pages of a "
+"single website in separate tabs or windows, without any loss of "
+"functionality."
+msgstr ""
+"Per altra banda, totes les connexions a un lloc web es realitzaran pel "
+"mateix circuit virtual, permeten navegar per diferents pàgines web en "
+"diferents pestanyes o finestres, sense perdre cap funcionalitat."
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: managing-identities.page:46
+msgctxt "_"
+msgid ""
+"external ref='media/managing-identities/circuit_full.png' "
+"md5='bd46d22de952fee42643be46d3f95928'"
+msgstr ""
+"extern ref='media/managing-identities/circuit_full.png' "
+"md5='bd46d22de952fee42643be46d3f95928'"
+
+#: managing-identities.page:48
+msgid ""
+"You can see a diagram of the circuit that Tor Browser is using for the "
+"current tab in the onion menu."
+msgstr ""
+"Pot observar el diagrama del circuit que el navegador Tor està utilitzant en"
+" la pestanya del menú de la ceba."
+
+#: managing-identities.page:55
+msgid "Logging in over Tor"
+msgstr "Registre de Tor"
+
+#: managing-identities.page:56
+msgid ""
+"Although Tor Browser is designed to enable total user anonymity on the web, "
+"there may be situations in which it makes sense to use Tor with websites "
+"that require usernames, passwords, or other identifying information."
+msgstr ""
+"Tot i que el navegador Tor està dissenyat per una navegació totalment "
+"anònima, poden existir situacions que no faci falta la utilització de Tor, "
+"com per exemple pàgines web amb inici de sessió, contrasenyes o necessitat "
+"d'autenticació."
+
+#: managing-identities.page:62
+msgid ""
+"If you log into a website using a regular browser, you also reveal your IP "
+"address and geographical location in the process. The same is often true "
+"when you send an email. Logging into your social networking or email "
+"accounts using Tor Browser allows you to choose exactly which information "
+"you reveal to the websites you browse. Logging in using Tor Browser is also "
+"useful if the website you are trying to reach is censored on your network."
+msgstr ""
+"Si inicia sessió amb un navegador convencional, està mostrant la seva "
+"direcció IP i localització, i amb una alta probabilitat quan estigui enviant"
+" un correu electrònic. Iniciar sessió en una xarxa social o entrar en un "
+"gestor de correu electrònic web mitjançant Tor permet enviar la informació "
+"de forma selectiva. Altrament pot ser útil si s'intenta accedir a una pàgina"
+" web censurada."
+
+#: managing-identities.page:72
+msgid ""
+"When you log in to a website over Tor, there are several points you should "
+"bear in mind:"
+msgstr ""
+"Quan iniciï sessió mitjançant el navegador Tor, hi han diverses "
+"consideracions a tenir en ment:"
+
+#: managing-identities.page:79
+msgid ""
+"See the <link xref=\"secure-connections\">Secure Connections</link> page for"
+" important information on how to secure your connection when logging in."
+msgstr ""
+"Consulti <link xref=\"secure-connections\">Connexions segures</link> la "
+"pàgina on mostra com augmentar la seguretat en les connexions d'inici de "
+"sessió."
+
+#: managing-identities.page:87
+msgid ""
+"Tor Browser often makes your connection appear as though it is coming from "
+"an entirely different part of the world. Some websites, such as banks or "
+"email providers, might interpret this as a sign that your account has been "
+"hacked or compromised, and lock you out. The only way to resolve this is by "
+"following the site’s recommended procedure for account recovery, or "
+"contacting the operators and explaining the situation."
+msgstr ""
+"El navegador Tor tot sovint fa aparèixer la connexió des de una localització"
+" diferent. Alguns webs, com els bancs o proveïdors de correu electrònic, "
+"poden interpretar com si la connexió fos furonada i per tant fer fora del "
+"web. La única manera de resoldre-ho és seguir les recomanacions de la "
+"recuperació del compte o contactar al operador i explicar la situació. "
+
+#: managing-identities.page:101
+msgid "Changing identities and circuits"
+msgstr "Canviant identitats i circuits"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: managing-identities.page:103
+msgctxt "_"
+msgid ""
+"external ref='media/managing-identities/new_identity.png' "
+"md5='15b01e35fa83185d94b57bf0ccf09d76'"
+msgstr ""
+"extern ref='media/managing-identities/new_identity.png' "
+"md5='15b01e35fa83185d94b57bf0ccf09d76'"
+
+#: managing-identities.page:105
+msgid ""
+"Tor Browser features “New Identity” and “New Tor Circuit for this Site” "
+"options, located in the Torbutton menu."
+msgstr ""
+"Les característiques del navegador Tor \"Nova identitat\" i \"Nou circuit "
+"Tor per aquest lloc\" localitzades en el botó Tor del menú."
+
+#: managing-identities.page:111
+msgid "New Identity"
+msgstr "Nova identitat"
+
+#: managing-identities.page:112
+msgid ""
+"This option is useful if you want to prevent your subsequent browser "
+"activity from being linkable to what you were doing before. Selecting it "
+"will close all your open tabs and windows, clear all private information "
+"such as cookies and browsing history, and use new Tor circuits for all "
+"connections. Tor Browser will warn you that all activity and downloads will "
+"be stopped, so take this into account before clicking “New Identity”."
+msgstr ""
+"Aquesta opció pot ser d'ajuda si vol prevenir l'enllaç de l'activitat del "
+"navegador amb activitats anteriors. Si es selecciona es tancaran totes les "
+"pestanyes i finestres, i es suprimiran totes les galetes i historial de "
+"navegació, a més de la utilització de nous circuits Tor per totes les "
+"connexions. El navegador Tor advertirà que totes les activitats i "
+"descàrregues seran aturades, prengui-ho en consideració abans de fer clic a "
+"\"Nova identitat\"."
+
+#: managing-identities.page:123
+msgid "New Tor Circuit for this Site"
+msgstr "Nou circuit Tor per a aquest lloc"
+
+#: managing-identities.page:124
+msgid ""
+"This option is useful if the <link xref=\"about-tor-browser#how-tor-"
+"works\">exit relay</link> you are using is unable to connect to the website "
+"you require, or is not loading it properly. Selecting it will cause the "
+"currently-active tab or window to be reloaded over a new Tor circuit. Other "
+"open tabs and windows from the same website will use the new circuit as well"
+" once they are reloaded. This option does not clear any private information "
+"or unlink your activity, nor does it affect your current connections to "
+"other websites."
+msgstr ""
+"Aquesta opció pot ser d'ajuda si <link xref=\"about-tor-browser#how-tor-"
+"works\">surt del relé</link> que està utilitzant per la connexió al lloc web"
+" que està intentant connectar. Si se selecciona farà que la pestanya o "
+"finestra activa s'actualitzi mitjançant un nou circuit Tor. Altres pestanyes"
+" i finestres obertes del mateix lloc web utilitzaran un nou circuit Tor al "
+"ser actualitzades. Aquesta opció no permet la neteja d'informació privada o "
+"desenllaçar la activitat, a més de no afectar connexions a altres lloc web."
+
+#: onionsites.page:6
+msgid "Services that are only accessible using Tor"
+msgstr "Serveis que només són accessibles utilitzant Tor."
+
+#: onionsites.page:10
+msgid "Onion Services"
+msgstr "Serveis Ceba"
+
+#: onionsites.page:11
+msgid ""
+"Onion services (formerly known as “hidden services”) are services (like "
+"websites) that are only accessible through the Tor network."
+msgstr ""
+"Els serveis ceba (també anomenats \"serveis amagats\") són serveis (com els "
+"webs) que només són accessibles mitjançant la xarxa Tor."
+
+#: onionsites.page:16
+msgid ""
+"Onion services offer several advantages over ordinary services on the non-"
+"private web:"
+msgstr ""
+"Els serveis ceba permeten tenir diferents avantatges a diferència dels "
+"serveis ordinaris sense privacitat:"
+
+#: onionsites.page:23
+msgid ""
+"An onion services’s location and IP address are hidden, making it difficult "
+"for adversaries to censor it or identify its operators."
+msgstr ""
+"Un servei ceba oculta la direcció IP i realitza una dificultat afegida pels "
+"censors o operador que pretenen identificar."
+
+#: onionsites.page:29
+msgid ""
+"All traffic between Tor users and onion services is end-to-end encrypted, so"
+" you do not need to worry about <link xref=\"secure-connections\">connecting"
+" over HTTPS</link>."
+msgstr ""
+"Tot el tràfic entre els usuaris Tor i els serveis ceba és amb encriptació "
+"punt-a-punt, per tant no cal patir <link xref=\"secure-connections\">de la "
+"connexió mitjançant HTTPS</link>."
+
+#: onionsites.page:36
+msgid ""
+"The address of an onion service is automatically generated, so the operators"
+" do not need to purchase a domain name; the .onion URL also helps Tor ensure"
+" that it is connecting to the right location and that the connection is not "
+"being tampered with."
+msgstr ""
+"Les adreces del servei ceba són generades de forma automàtica, per tant els "
+"operador no cal que comprin cap domini; la URL de ceba també permet "
+"assegurar que la connexió a i la localització no és interceptada."
+
+#: onionsites.page:46
+msgid "How to access an onion service"
+msgstr "Com accedir a un servei ceba"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: onionsites.page:48
+msgctxt "_"
+msgid ""
+"external ref='media/onionsites/onion_url.png' "
+"md5='f97f7fe10f07c3959c4430934974bbaa'"
+msgstr ""
+"extern ref='media/onionsites/onion_url.png' "
+"md5='f97f7fe10f07c3959c4430934974bbaa'"
+
+#: onionsites.page:50
+msgid ""
+"Just like any other website, you will need to know the address of an onion "
+"service in order to connect to it. An onion address is a string of 16 (and "
+"in V3 format, 56) mostly random letters and numbers, followed by “.onion”."
+msgstr ""
+"Igual que qualsevol altre lloc web, haurà de conèixer l'adreça d'un servei "
+"de onion per connectar-s'hi. Una adreça de onion és una cadena de 16 "
+"caràcters (i en format V3, 56), principalment lletres i números aleatoris, "
+"seguit de \".onion\"."
+
+#: onionsites.page:58 troubleshooting.page:10
+msgid "Troubleshooting"
+msgstr "Detecció d'errors"
+
+#: onionsites.page:59
+msgid ""
+"If you cannot reach the onion service you require, make sure that you have "
+"entered the onion address correctly: even a small mistake will stop Tor "
+"Browser from being able to reach the site."
+msgstr ""
+"Si no podeu arribar al servei de onion que necessiteu, assegureu-vos que heu"
+" introduït correctament l'adreça de onion: fins i tot un petit error deixarà"
+" que el navegador Tor no pugui accedir al lloc."
+
+#: onionsites.page:64
+msgid ""
+"If you are still unable to connect to the onion service, please try again "
+"later. There may be a temporary connection issue, or the site operators may "
+"have allowed it to go offline without warning."
+msgstr ""
+"Si encara no pot establir connexió amb un servei ceba, si us plau provi-ho "
+"posteriorment. Pot estar esdeveniment una connexió errònia de forma temporal"
+" o els operadors de xarxa han permès estar fóra de línia sense un "
+"advertència."
+
+#: onionsites.page:69
+msgid ""
+"You can also ensure that you're able to access other onion services by "
+"connecting to <link href=\"http://3g2upl4pq6kufc4m.onion/\">DuckDuckGo's "
+"Onion Service</link>"
+msgstr ""
+"Pot assegurar que pot tenir accés als servis ceba mitjançat la connexió "
+"<link href=\"http://3g2upl4pq6kufc4m.onion/\">al servei ceba de "
+"DuckDuckGo's</link>"
+
+#: plugins.page:6
+msgid "How Tor Browser handles add-ons, plugins and JavaScript"
+msgstr ""
+"Com el navegador Tor gestiona els connectors, complements i JavaScript"
+
+#: plugins.page:10
+msgid "Plugins, add-ons and JavaScript"
+msgstr "Connectors, complements i JavaScript"
+
+#: plugins.page:13
+msgid "Flash Player"
+msgstr "Reproductor Flash"
+
+#: plugins.page:14
+msgid ""
+"Video websites, such as Vimeo make use of the Flash Player plugin to display"
+" video content. Unfortunately, this software operates independently of Tor "
+"Browser and cannot easily be made to obey Tor Browser’s proxy settings. It "
+"can therefore reveal your real location and IP address to the website "
+"operators, or to an outside observer. For this reason, Flash is disabled by "
+"default in Tor Browser, and enabling it is not recommended."
+msgstr ""
+"Llocs web com Vimeo utilitzen el reproductor Flash per mostrar els "
+"continguts de video. Desafortunadament, aquest programari s'executa de forma"
+" independent del navegador Tor i en pocs casos permet la utilització de "
+"paràmetres del servidor intermedi. Conseqüentment pot mostrar la "
+"localització IP o per ser un visitant anònim. Per aquesta raó, Flash està "
+"deshabilitada per defecte i no es recomana executar-lo."
+
+#: plugins.page:23
+msgid ""
+"Some video websites (such as YouTube) offer alternative video delivery "
+"methods that do not use Flash. These methods may be compatible with Tor "
+"Browser."
+msgstr ""
+"Algunes pàgines web de vídeos (com per exemple Youtube) permeten la "
+"visualització dels seus vídeos amb altres mètodes diferents a Flash. Aquests"
+" mètodes poden ser comptables amb el navegador Tor."
+
+#: plugins.page:31
+msgid "JavaScript"
+msgstr "JavaScript"
+
+#: plugins.page:32
+msgid ""
+"JavaScript is a programming language that websites use to offer interactive "
+"elements such as video, animation, audio, and status timelines. "
+"Unfortunately, JavaScript can also enable attacks on the security of the "
+"browser, which might lead to deanonymization."
+msgstr ""
+"JavaScript és un llenguatge de programació que els webs utilitzen per "
+"augmentar els ginys interactius, com els vídeos, animacions, àudio i estats "
+"de cronologies. Malauradament, JavaScript és vulnerables a atacs de "
+"seguretats, que poden causar la descoberta de l'anonimat. "
+
+#: plugins.page:39
+msgid ""
+"Tor Browser includes an add-on called NoScript, accessed through the “S” "
+"icon at the top-left of the window. NoScript allows you to control the "
+"JavaScript (and other scripts) that runs on individual web pages, or block "
+"it entirely."
+msgstr ""
+"El navegador Tor inclou un complement anomenat NoScript, que es pot accedir "
+"a través de la icona \"S\" a la part superior esquerra de la finestra. "
+"NoScript us permet controlar el codi JavaScript (i altres scripts) que "
+"s'executa en pàgines web individuals o bé bloquejar-les completament."
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: plugins.page:46
+msgctxt "_"
+msgid ""
+"external ref='media/plugins/noscript_menu.png' "
+"md5='df9e684b76a3c2e2bdcb879a19c20471'"
+msgstr ""
+"extern ref='media/plugins/noscript_menu.png' "
+"md5='df9e684b76a3c2e2bdcb879a19c20471'"
+
+#: plugins.page:48
+msgid ""
+"Users who require a high degree of security in their web browsing should set"
+" Tor Browser’s <link xref=\"security-slider\">Security Slider</link> to "
+"“Safer” (which disables JavaScript for non-HTTPS websites) or “Safest” "
+"(which does so for all websites). However, disabling JavaScript will prevent"
+" many websites from displaying correctly, so Tor Browser’s default setting "
+"is to allow all websites to run scripts in \"Standard\" mode."
+msgstr ""
+"Els usuaris que requereixin un alt grau de seguretat en la seva navegació "
+"web haurien de configurar el <link xref=\"security-slider\">control "
+"deslizador</link>de seguretat del navegador Tor a \"Més segur\" (que "
+"desabilita JavaScript per a llocs web que no siguin d'HTTPS) o \"Seguretat\""
+" (que ho fa per a tots els llocs web). Tanmateix, la desactivació de "
+"JavaScript evitarà que molts llocs web es mostrin correctament, de manera "
+"que la configuració predeterminada del navegador Tor és permetre que tots "
+"els llocs web executin scripts en el mode \"Estàndard\"."
+
+#: plugins.page:59
+msgid "Browser Add-ons"
+msgstr "Complements"
+
+#: plugins.page:60
+msgid ""
+"Tor Browser is based on Firefox, and any browser add-ons or themes that are "
+"compatible with Firefox can also be installed in Tor Browser."
+msgstr ""
+"El navegador Tor està basat amb Firefox, i tots els complements i temes "
+"compatibles amb Firefox poden ser instal·lats al navegador Tor."
+
+#: plugins.page:65
+msgid ""
+"However, the only add-ons that have been tested for use with Tor Browser are"
+" those included by default. Installing any other browser add-ons may break "
+"functionality in Tor Browser or cause more serious problems that affect your"
+" privacy and security. It is strongly discouraged to install additional add-"
+"ons, and the Tor Project will not offer support for these configurations."
+msgstr ""
+"Tanmateix, els únics complements que s'han testejat pel navegador Tor són "
+"els inclosos per defecte. La instal·lació d'altres complements pot causar "
+"greus problemes que afectin la seguretat i la privacitat. És altament "
+"recomanat no instal·lar complements, ja que tampoc gaudeixen de suport per "
+"part del projecte Tor."
+
+#: secure-connections.page:8
+msgid "Learn how to protect your data using Tor Browser and HTTPS"
+msgstr ""
+"Aprengui com protegir les seves dades amb la utilització del navegador Tor i"
+" HTTPS"
+
+#: secure-connections.page:12
+msgid "Secure Connections"
+msgstr "Connexions segures"
+
+#: secure-connections.page:14
+msgid ""
+"If personal information such as a login password travels unencrypted over "
+"the Internet, it can very easily be intercepted by an eavesdropper. If you "
+"are logging into any website, you should make sure that the site offers "
+"HTTPS encryption, which protects against this kind of eavesdropping. You can"
+" verify this in the URL bar: if your connection is encrypted, the address "
+"will begin with “https://”, rather than “http://”."
+msgstr ""
+"Si informació personal d'inici de sessió viatge desencriptada per Internet, "
+"pot ser fàcilment interceptada per escoltes clandestines. Si inicia sessió "
+"cal assegurar-se que s'estableix una connexió HTTPS encriptada, que el "
+"protegeix. Ho pot comprovar en al barra URL quan les primeres lletres siguin"
+" \"https://\", en contra de \"http://\"."
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: secure-connections.page:24
+msgctxt "_"
+msgid ""
+"external ref='media/secure-connections/https.png' "
+"md5='364bcbde7a649b0cea9ae178007c1a50'"
+msgstr ""
+"extern ref='media/secure-connections/https.png' "
+"md5='364bcbde7a649b0cea9ae178007c1a50'"
+
+#: secure-connections.page:26
+msgid ""
+"The following visualization shows what information is visible to "
+"eavesdroppers with and without Tor Browser and HTTPS encryption:"
+msgstr ""
+"La següent imatge mostra quina informació és visible a ulls del interceptors"
+" de dades sense el navegador Tor i una encriptació sota HTTPS:"
+
+#: secure-connections.page:35
+msgid ""
+"Click the “Tor” button to see what data is visible to observers when you're "
+"using Tor. The button will turn green to indicate that Tor is on."
+msgstr ""
+"Faci clic en el icona \"Tor\" per saber quines dades són visibles als "
+"observadors quan s'utilitzi Tor. El icona es tornarà de color verd per "
+"indicar que Tor està en marxa."
+
+#: secure-connections.page:42
+msgid ""
+"Click the “HTTPS” button to see what data is visible to observers when "
+"you're using HTTPS. The button will turn green to indicate that HTTPS is on."
+msgstr ""
+"Faci clic al botó \"HTTPS\" per saber quines dades són visibles als "
+"observador quan s'utilitzi HTTPS. El botó es tornarà verd per indicar que "
+"HTTPS està en marxa."
+
+#: secure-connections.page:49
+msgid ""
+"When both buttons are green, you see the data that is visible to observers "
+"when you are using both tools."
+msgstr ""
+"Quan ambdós botons estan en verd, es pot veure quines dades són visibles als"
+" observadors amb les dos eines."
+
+#: secure-connections.page:55
+msgid ""
+"When both buttons are grey, you see the data that is visible to observers "
+"when you don't use either tool."
+msgstr ""
+"Quan ambdós botons estan en gris, es pot veure quines dades són visibles als"
+" observadors sense la utilització de les dos eines."
+
+#: secure-connections.page:62
+msgid "Potentially visible data"
+msgstr "Dades potencialment visibles"
+
+#: secure-connections.page:70
+msgid "The site being visited."
+msgstr "El web visitat."
+
+#: secure-connections.page:81
+msgid "Username and password used for authentication."
+msgstr "Nom d'usuari i contrasenya usats per la autenticació."
+
+#: secure-connections.page:92
+msgid "Data being transmitted."
+msgstr "Dades trameses."
+
+#: secure-connections.page:103
+msgid ""
+"Network location of the computer used to visit the website (the public IP "
+"address)."
+msgstr ""
+"Localització del ordinador usat per la consulta del web (l'adreça pública "
+"IP)."
+
+#: secure-connections.page:115
+msgid "Whether or not Tor is being used."
+msgstr "Si o no, Tor s'està utilitzant."
+
+#: security-slider.page:6
+msgid "Configuring Tor Browser for security and usability"
+msgstr "Configurant el navegador Tor per seguretat i usabilitat."
+
+#: security-slider.page:10
+msgid "Security Slider"
+msgstr "Control lliscant de seguretat"
+
+#: security-slider.page:11
+msgid ""
+"Tor Browser includes a “Security Slider” that lets you increase your "
+"security by disabling certain web features that can be used to attack your "
+"security and anonymity. Increasing Tor Browser’s security level will stop "
+"some web pages from functioning properly, so you should weigh your security "
+"needs against the degree of usability you require."
+msgstr ""
+"El navegador Tor inclou un \"control lliscant de seguretat\" que permet "
+"incrementar la seguretat deshabilitant característiques dels webs que poden "
+"ser blanc d'atacs de seguretat i d'anonimat. Incrementant el nivell de "
+"seguretat del navegador no es podrà visualitzar parts dels webs, per tant "
+"cal pensar quin grau de seguretat es vol tenir ponderat amb la usabilitat "
+"que s'aconseguirà."
+
+#: security-slider.page:21
+msgid "Accessing the Security Slider"
+msgstr "Accedint al control lliscant de seguretat"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: security-slider.page:23
+msgctxt "_"
+msgid ""
+"external ref='media/security-slider/slider.png' "
+"md5='026da7c021ba5b85caf04bbf45530667'"
+msgstr ""
+"external ref='media/security-slider/slider.png' "
+"md5='026da7c021ba5b85caf04bbf45530667'"
+
+#: security-slider.page:25
+msgid ""
+"The Security Slider is located in Torbutton’s “Security Settings” menu."
+msgstr ""
+"El Control deslizador de seguretat es troba al menú \"Paràmetres de "
+"seguretat\" del botó Tor."
+
+#: security-slider.page:32
+msgid "Security Levels"
+msgstr "Nivells de seguretat"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: security-slider.page:34
+msgctxt "_"
+msgid ""
+"external ref='media/security-slider/slider_window.png' "
+"md5='d5faf391c99f88aff8541a68bdc6a776'"
+msgstr ""
+"external ref='media/security-slider/slider_window.png' "
+"md5='d5faf391c99f88aff8541a68bdc6a776'"
+
+#: security-slider.page:36
+msgid ""
+"Increasing the level of the Security Slider will disable or partially "
+"disable certain browser features to protect against possible attacks."
+msgstr ""
+"Augmentant el nivell de seguretat mitjançant el control lliscant es pot "
+"deshabilitar parcialment característiques de protecció davant d'atacs."
+
+#: security-slider.page:42
+msgid "Safest"
+msgstr "més segur"
+
+#: security-slider.page:43
+msgid ""
+"At this level, HTML5 video and audio media become click-to-play via "
+"NoScript; all JavaScript performance optimizations are disabled; some "
+"mathematical equations may not display properly; some font rendering "
+"features are disabled; some types of image are disabled; Javascript is "
+"disabled by default on all sites; most video and audio formats are disabled;"
+" and some fonts and icons may not display correctly."
+msgstr ""
+"A aquest nivell, el vídeo de HTML5 i l'àudio esdevindrà reproduïble "
+"mitjançant un clic via NoScript; els augmentadors de rendiments seran "
+"abolits; algunes equacions matemàtiques no es mostraran correctament; alguns"
+" renderitzats de tipus de lletra seran deshabilitats; alguns tipus "
+"d'imatges; javaScript es mantindrà per defecte sense utilització; la majoria"
+" de vídeos i àudios no es reproduiran; algunes lletres i imatges no es "
+"podran visualitzar correctament."
+
+#: security-slider.page:53
+msgid "Safer"
+msgstr "Més segur."
+
+#: security-slider.page:54
+msgid ""
+"At this level, HTML5 video and audio media become click-to-play via "
+"NoScript; all JavaScript performance optimizations are disabled; some "
+"mathematical equations may not display properly; some font rendering "
+"features are disabled; some types of image are disabled; and JavaScript is "
+"disabled by default on all non-<link xref=\"secure-"
+"connections\">HTTPS</link> sites."
+msgstr ""
+"A aquest nivell, el vídeo de HTML5 i l'àudio esdevindrà reproduïble "
+"mitjançant un clic via NoScript; els augmentadors de rendiments seran "
+"abolits; algunes equacions matemàtiques no es mostraran correctament; alguns"
+" renderitzats de tipus de lletra seran deshabilitats; alguns tipus "
+"d'imatges; javaScript es mantindrà per defecte sense utilització i en-<link "
+"xref=\"secure-connections\">HTTPS</link> tots els llocs."
+
+#: security-slider.page:64
+msgid "Standard"
+msgstr "Estàndard"
+
+#: security-slider.page:65
+msgid ""
+"At this level, all browser features are enabled. This is the most usable "
+"option."
+msgstr ""
+"En aquest nivell, tots els navegadors i les seves característiques són "
+"activades. Aquesta és la opció més utilitzada."
+
+#: translate.page:6
+msgid "Becoming a translator for the Tor Project"
+msgstr "Convertir-se en un traductor del projecte Tor"
+
+#: translate.page:10
+msgid "Becoming a Tor Translator"
+msgstr "Converteix-te en un traductor de Tor"
+
+#: translate.page:12
+msgid ""
+"If you are interested in helping out the project by translating the manual "
+"or the Tor Browser to your language, your help would be greatly appreciated!"
+" In order to begin contributing you will have to sign up with Transifex, the"
+" third-party that faciliates our translations. Below is an outline of how to"
+" sign up and begin."
+msgstr ""
+"Si esteu interessat a ajudar el projecte traduint el manual o el navegador "
+"Tor al vostre idioma, la vostra ajuda seria molt apreciada. Per començar a "
+"contribuir, hauràs d'inscriure't amb Transifex, un tercer que facilita les "
+"nostres traduccions. A continuació es mostra un resum de com inscriure's i "
+"començar."
+
+#: translate.page:21
+msgid "Signing up on Transifex"
+msgstr "Registra't a Transifex"
+
+#: translate.page:24
+msgid ""
+"Head over to the <link href=\"https://transifex.com/signup/\">Transifex "
+"signup page</link>."
+msgstr ""
+"Passeu a la <link href=\"https://transifex.com/signup/\">pàgina d'inscripció"
+" de Transifex</link>."
+
+#: translate.page:30
+msgid "Enter your information into the fields and click the 'Sign Up' button:"
+msgstr ""
+"Introduïu la vostra informació als camps i feu clic al botó \"Registra't\":"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: translate.page:34
+msgctxt "_"
+msgid ""
+"external ref='media/translate/tr1.png' "
+"md5='a94cfd90c9982916a987e2807ae5e4f6'"
+msgstr ""
+"external ref='media/translate/tr1.png' "
+"md5='a94cfd90c9982916a987e2807ae5e4f6'"
+
+#: translate.page:38
+msgid ""
+"Fill out the next page with your name and select \"Localization\" and "
+"\"Translator\" from the drop-down menus:"
+msgstr ""
+"Ompliu la pàgina següent amb el vostre nom i seleccioneu \"Localització\" i "
+"\"Traductor\" al menú desplegable:"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: translate.page:43
+msgctxt "_"
+msgid ""
+"external ref='media/translate/tr2.png' "
+"md5='06debc9e9dbc7ac198103a89a6961774'"
+msgstr ""
+"external ref='media/translate/tr2.png' "
+"md5='06debc9e9dbc7ac198103a89a6961774'"
+
+#: translate.page:47
+msgid "On the next page, select 'Join an existing project' and continue."
+msgstr ""
+"A la pàgina següent, seleccioneu \"Uniu-vos a un projecte existent\" i "
+"continueu."
+
+#: translate.page:52
+msgid ""
+"On the next page, select the languages you speak from the drop-down menu and"
+" continue."
+msgstr ""
+"A la pàgina següent, seleccioneu els idiomes que parleu al menú desplegable "
+"i continueu."
+
+#: translate.page:58
+msgid ""
+"You are now signed up! Go to the <link "
+"href=\"https://www.transifex.com/otf/torproject/\">Tor Transifex "
+"page</link>."
+msgstr ""
+"Ja t'has inscrit! Aneu a la pàgina de <link "
+"href=\"https://www.transifex.com/otf/torproject/\">Tor Transifex</link>."
+
+#: translate.page:64
+msgid "Click the blue 'Join Team' button on the far right:"
+msgstr "Feu clic al botó blau \"Uneix-te a l'equip\" a l'extrem dret:"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: translate.page:68
+msgctxt "_"
+msgid ""
+"external ref='media/translate/tr3.png' "
+"md5='7da6c9968cabbe9c1ecc7cdf645407e8'"
+msgstr ""
+"external ref='media/translate/tr3.png' "
+"md5='7da6c9968cabbe9c1ecc7cdf645407e8'"
+
+#: translate.page:72
+msgid ""
+"Select the language you would like to translate from the dropdown menu:"
+msgstr "Seleccioneu l'idioma que voleu traduir al menú desplegable:"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: translate.page:76
+msgctxt "_"
+msgid ""
+"external ref='media/translate/tr4.png' "
+"md5='835a266a5d4c368a2777cf171980f0b4'"
+msgstr ""
+"external ref='media/translate/tr4.png' "
+"md5='835a266a5d4c368a2777cf171980f0b4'"
+
+#: translate.page:80
+msgid "A notification will now show up on the top of the page like so:"
+msgstr "Ara, una notificació apareixerà a la part superior de la pàgina:"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: translate.page:84
+msgctxt "_"
+msgid ""
+"external ref='media/translate/tr5.png' "
+"md5='935417a5d3b4a89e5d00508ea671a1fc'"
+msgstr ""
+"external ref='media/translate/tr5.png' "
+"md5='935417a5d3b4a89e5d00508ea671a1fc'"
+
+#: translate.page:88
+msgid ""
+"After your membership is approved you can begin translating; simply navigate"
+" back to the <link href=\"https://www.transifex.com/otf/torproject/\">Tor "
+"Transifex page</link> when you are ready to begin. Thanks for your interest "
+"in helping the project!"
+msgstr ""
+"Un cop aprovada la vostra membresia, podeu començar a traduir; simplement, "
+"torneu a la <link href=\"https://www.transifex.com/otf/torproject/\">pàgina "
+"Tor Transifex</link> quan estigueu a punt per començar. Gràcies pel vostre "
+"interès per ajudar el projecte!"
+
+#: transports.page:6 transports.page:20
+msgid "Types of pluggable transport"
+msgstr "Tipus de connectors de transport"
+
+#: transports.page:10
+msgid "Pluggable Transports"
+msgstr "Transports integrables"
+
+#: transports.page:12
+msgid ""
+"Pluggable transports are tools that Tor can use to disguise the traffic it "
+"sends out. This can be useful in situations where an Internet Service "
+"Provider or other authority is actively blocking connections to the Tor "
+"network."
+msgstr ""
+"Els connectors de transport són eines que Tor utilitza per disfressar el "
+"tràfic que envia al exterior. Això pot ser d'utilitat en situacions com quan"
+" els proveïdors d'Internet o altres autoritat bloquegen les connexions a la "
+"xarxa Tor. "
+
+#: transports.page:21
+msgid ""
+"Currently there are six pluggable transports available, but more are being "
+"developed."
+msgstr ""
+"Actualment hi han sis connectors de transports per utilitzar, però n'hi ha "
+"més en desenvolupament."
+
+#: transports.page:28
+msgid "obfs3"
+msgstr "obfs3"
+
+#: transports.page:33
+msgid ""
+"obfs3 makes Tor traffic look random, so that it does not look like Tor or "
+"any other protocol. While still included by default, it is reccomended to "
+"use obfs4 instead, as it has several security improvements over obfs3."
+msgstr ""
+"obfs3 fa que el trànsit de Tor sigui aleatori, de manera que no s'assembla a"
+" Tor o cap altre protocol. Encara que s'inclou per defecte, es recomana "
+"utilitzar obfs4, ja que té diverses millores de seguretat sobre obfs3."
+
+#: transports.page:43
+msgid "obfs4"
+msgstr "obfs4"
+
+#: transports.page:48
+msgid ""
+"obfs4 makes Tor traffic look random like obfs3, and also prevents censors "
+"from finding bridges by Internet scanning. obfs4 bridges are less likely to "
+"be blocked than obfs3 bridges."
+msgstr ""
+"obfs4 fa que el tràfic Tor sigui aleatori com obfs3, però també pot prevenir"
+" la censura del escaneig de Internet. El pont obfs4 permet menys bloquejos "
+"que el obfs3."
+
+#: transports.page:57
+msgid "Scramblesuit"
+msgstr "Scramblesuit"
+
+#: transports.page:62
+msgid "ScrambleSuit is similar to obfs4 but has a different set of bridges."
+msgstr "ScrambleSuit és similar a obfs4 però amb ponts diferents."
+
+#: transports.page:70
+msgid "FTE"
+msgstr "FTE"
+
+#: transports.page:75
+msgid ""
+"FTE (format-transforming encryption) disguises Tor traffic as ordinary web "
+"(HTTP) traffic."
+msgstr ""
+"FTE (format-transforming encryption) emmascara el tràfic Tor com una "
+"connexió (HTTP) web."
+
+#: transports.page:83
+msgid "meek"
+msgstr "meek"
+
+#: transports.page:88
+msgid ""
+"These transports all make it look like you are browsing a major web site "
+"instead of using Tor. meek-amazon makes it look like you are using Amazon "
+"Web Services; meek-azure makes it look like you are using a Microsoft web "
+"site; and meek-google makes it look like you are using Google search."
+msgstr ""
+"Aquests transports es visualitzen com un web en lloc de la utilització de "
+"Tor. meek-amazon fa semblar que s'està utilitzant amazon Web Services; meek-"
+"azure makes simula que s'està usant Microsoft web site; i meek-google simula"
+" l'utilització de Google search."
+
+#: transports.page:100
+msgid "Snowflake"
+msgstr "Snowflake"
+
+#: transports.page:105
+msgid ""
+"Snowflake is an improvement upon Flashproxy. It sends your traffic through "
+"WebRTC, a peer-to-peer protocol with built-in NAT punching."
+msgstr ""
+"Snowflake és una millora en Flashproxy. Envia el teu trànsit a través de "
+"WebRTC, un protocol punt a punt amb NAT incorporat."
+
+#: troubleshooting.page:6
+msgid "What to do if Tor Browser doesn’t work"
+msgstr "Què fer si el navegador Tor no funciona"
+
+#: troubleshooting.page:12
+msgid ""
+"You should be able to start browsing the web using Tor Browser shortly after"
+" running the program, and clicking the “Connect” button if you are using it "
+"for the first time."
+msgstr ""
+"Hauria de poder navegar pels webs mitjançant el navegador Tor executant el "
+"programa i fent clic a \"Connectar\" si l'està utilitzant per primer cop."
+
+#: troubleshooting.page:21
+msgid "Quick fixes"
+msgstr "Correccions ràpides"
+
+#: troubleshooting.page:22
+msgid ""
+"If Tor Browser doesn’t connect, there may be a simple solution. Try each of "
+"the following:"
+msgstr ""
+"Si el navegador Tor no es connecta, pot haver una solució fàcil. Provi "
+"alguna de les següents opcions:"
+
+#: troubleshooting.page:29
+msgid ""
+"Your computer’s system clock must be set correctly, or Tor will not be able "
+"to connect."
+msgstr ""
+"El rellotge de sistema s'hauria de configurar correctament o Tor no podrà "
+"connectar-se."
+
+#: troubleshooting.page:35
+msgid ""
+"Make sure another Tor Browser is not already running. If you’re not sure if "
+"Tor Browser is running, restart your computer."
+msgstr ""
+"Comprovi que el navegador Tor no s'està executant en aquest moment. Si no "
+"està segur, reinicii el ordinador."
+
+#: troubleshooting.page:41
+msgid ""
+"Make sure that any antivirus program you have installed is not preventing "
+"Tor from running. You may need to consult the documentation for your "
+"antivirus software if you do not know how to do this."
+msgstr ""
+"Comprovi que cap programa d'antivirus instal·lat està intentant evitar que "
+"Tor s'executi. Haurà de consultar la documentació del antivirus si no sap "
+"com realitzar-ho."
+
+#: troubleshooting.page:49
+msgid "Temporarily disable your firewall."
+msgstr "Deshabiliti de forma temporal el tallafoc."
+
+#: troubleshooting.page:54
+msgid ""
+"Delete Tor Browser and install it again. If updating, do not just overwrite "
+"your previous Tor Browser files; ensure they are fully deleted beforehand."
+msgstr ""
+"Suprimir el navegador Tor i tornar a instal·lar. Si l'actualització no ha "
+"reescrit la versió anterior del navegador Tor, comprovi que s'han eliminat "
+"tots els arxius."
+
+#: troubleshooting.page:64
+msgid "Is your connection censored?"
+msgstr "Està la seva connexió en censura?"
+
+#: troubleshooting.page:65
+msgid ""
+"If you still can’t connect, your Internet Service Provider might be "
+"censoring connections to the Tor network. Read the <link "
+"xref=\"circumvention\">Circumvention</link> section for possible solutions."
+msgstr ""
+"Si continua sense poder connectar-se, el seu proveïdor d'Internet "
+"probablement està censurant les connexions a la xarxa Tor. Per a més "
+"informació <link xref=\"eludir\">Circumvention</link> per trobar possibles "
+"solucions."
+
+#: troubleshooting.page:74
+msgid "Known issues"
+msgstr "Assumptes coneguts"
+
+#: troubleshooting.page:75
+msgid ""
+"Tor Browser is under constant development, and some issues are known about "
+"but not yet fixed. Please check the <link xref=\"known-issues\">Known "
+"Issues</link> page to see if the problem you are experiencing is already "
+"listed there."
+msgstr ""
+"El navegador Tor està en constant desenvolupament, i alguns aspectes s'han "
+"d'arranjar en el futur. Si us plau comprovi a <link xref=\"més "
+"informació\">Known Issues</link> si el problema que experimenta ha estat "
+"llistat. "
+
+#: uninstalling.page:6
+msgid "How to remove Tor Browser from your system"
+msgstr "Com eliminar el navegador Tor del seu sistema"
+
+#: uninstalling.page:10
+msgid "Uninstalling"
+msgstr "Desinstal·lant"
+
+#: uninstalling.page:12
+msgid ""
+"Tor Browser does not affect any of the existing software or settings on your"
+" computer. Uninstalling Tor Browser will not affect your system’s software "
+"or settings."
+msgstr ""
+"El navegador no interacciona amb cap altra programari ni configuració del "
+"seu ordinador. Desinstal·lar el navegador Tor, tampoc afectarà cap paràmetre"
+" del ordinador."
+
+#: uninstalling.page:18
+msgid "Removing Tor Browser from your system is simple:"
+msgstr "Desinstal·lar el navegador Tor del sistema operatiu és simple:"
+
+#: uninstalling.page:24
+msgid ""
+"Locate your Tor Browser folder. The default location on Windows is the "
+"Desktop; on Mac OS X it is the Applications folder. On Linux, there is no "
+"default location, however the folder will be named \"tor-browser_en-US\" if "
+"you are running the English Tor Browser."
+msgstr ""
+"Ubica la carpeta del navegador Tor. La localització per defecte a Windows és"
+" en el escriptori; en OSX és en la carpeta d'aplicacions. A Linux, no hi ha "
+"una localització prefixada, de manera que la carpeta serà anomenada \"tor-"
+"browser_en-US\" si s'utilitza la versió anglesa."
+
+#: uninstalling.page:32
+msgid "Delete the Tor Browser folder."
+msgstr "Suprimir la carpeta del navegador Tor."
+
+#: uninstalling.page:35
+msgid "Empty your Trash"
+msgstr "Buidar la paperera"
+
+#: uninstalling.page:39
+msgid ""
+"Note that your operating system’s standard “Uninstall” utility is not used."
+msgstr ""
+"El sistema operatiu de forma estandarditzada la funció de \"Desinstal·lar\" "
+"no està usada."
+
+#: updating.page:6
+msgid "How to update Tor Browser"
+msgstr "Com actualitzar el navegador Tor."
+
+#: updating.page:10
+msgid "Updating"
+msgstr "Actualitzant"
+
+#: updating.page:12
+msgid ""
+"Tor Browser must be kept updated at all times. If you continue to use an "
+"outdated version of the software, you may be vulnerable to serious security "
+"flaws that compromise your privacy and anonymity."
+msgstr ""
+"El navegador Tor ha d'estar actualitzat. Si continua amb l'ús de versions "
+"obsoletes, pot ser vulnerable a seriosos problemes de seguretat, "
+"comprometent la seva seguretat i anonimat."
+
+#: updating.page:18
+msgid ""
+"Tor Browser will prompt you to update the software once a new version has "
+"been released: the Torbutton icon will display a yellow triangle, and you "
+"may see a written update indicator when Tor Browser opens. You can update "
+"either automatically or manually."
+msgstr ""
+"El navegador Tor mostrarà quan es pot actualitzar un cop la última versió "
+"sigui alliberada: La icona Tor mostrarà un triangle groc amb un indicador "
+"d'actualització. Es pot realitzar de forma manual o automàtica."
+
+#: updating.page:26
+msgid "Updating Tor Browser automatically"
+msgstr "Actualitzacions automàtiques del navegador Tor"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: updating.page:30
+msgctxt "_"
+msgid ""
+"external ref='media/updating/update1.png' "
+"md5='9ff01eb653d92124746fc31efde2bf07'"
+msgstr ""
+"extern ref='media/updating/update1.png' "
+"md5='9ff01eb653d92124746fc31efde2bf07'"
+
+#: updating.page:32
+msgid ""
+"When you are prompted to update Tor Browser, click on the Torbutton icon, "
+"then select “Check for Tor Browser Update”."
+msgstr ""
+"Quan sigui requerit a actualitzar el navegador Tor, faci clic en la icona "
+"Tor i seleccioni \"comprovar actualitzacions\"."
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: updating.page:39
+msgctxt "_"
+msgid ""
+"external ref='media/updating/update3.png' "
+"md5='19b1f46d748dbcd9250883044165d218'"
+msgstr ""
+"external ref='media/updating/update3.png' "
+"md5='19b1f46d748dbcd9250883044165d218'"
+
+#: updating.page:41
+msgid ""
+"When Tor Browser has finished checking for updates, click on the “Update” "
+"button."
+msgstr ""
+"Quan el navegador Tor hagi finalitzat la comprovació d'actualitzacions, faci"
+" clic en el botó \"Actualitzar\"."
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: updating.page:48
+msgctxt "_"
+msgid ""
+"external ref='media/updating/update4.png' "
+"md5='7e8ead67c03597f00c580c77c3103fbb'"
+msgstr ""
+"external ref='media/updating/update4.png' "
+"md5='7e8ead67c03597f00c580c77c3103fbb'"
+
+#: updating.page:50
+msgid ""
+"Wait for the update to download and install, then restart Tor Browser. You "
+"will now be running the latest version."
+msgstr ""
+"Esperi a la descarrega de l'actualització i posterior instal·lació, "
+"reiniciar el programa. Finalment s'executarà la última versió."
+
+#: updating.page:58
+msgid "Updating Tor Browser manually"
+msgstr "Actualització manual del navegador Tor"
+
+#: updating.page:61
+msgid ""
+"When you are prompted to update Tor Browser, finish the browsing session and"
+" close the program."
+msgstr ""
+"Quan se li requereixi l'actualització del navegador Tor, acabi la seva "
+"navegació i tanqui el programa."
+
+#: updating.page:67
+msgid ""
+"Remove Tor Browser from your system by deleting the folder that contains it "
+"(see the <link xref=\"uninstalling\">Uninstalling</link> section for more "
+"information)."
+msgstr ""
+"Suprimir el navegador Tor del sistema amb la supressió de la carpeta que "
+"conté (consultar l'enllaç <link xref=\"Desinstal·lar>Uninstalling</link> "
+"d'un sistema operatiu)."
+
+#: updating.page:74
+msgid ""
+"Visit <link href=\"https://www.torproject.org/projects/torbrowser.html.en\">"
+" https://www.torproject.org/projects/torbrowser.html.en</link> and download "
+"a copy of the latest Tor Browser release, then install it as before."
+msgstr ""
+"Visitar <link "
+"href=\"https://www.torproject.org/projects/torbrowser.html.en\"> "
+"https://www.torproject.org/projects/torbrowser.html.en</link> i descarregar "
+"una còpia de l'última versió del navegador Tor, posteriorment instal·lar."
1
0
commit e610eeda23990bafe6acce389aac5559f10e9697
Author: Colin Childs <colin(a)torproject.org>
Date: Tue Sep 18 14:18:10 2018 -0500
Adding id translations
---
Makefile.am | 2 +-
id/id.po | 1838 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 1839 insertions(+), 1 deletion(-)
diff --git a/Makefile.am b/Makefile.am
index 3fd3409..062f4dd 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -8,7 +8,7 @@ TOR_AND_HTTPS = ../tor-and-https
HELP_ID = tor-browser-user-manual
HELP_FILES = $(shell cd $(srcdir)/C && git ls-files '*.page')
HELP_MEDIA = $(shell cd $(srcdir)/C && git ls-files 'media')
-HELP_LINGUAS = en-US ja sv ga bn_BD @TOR_BROWSER_BUNDLE_LOCALES@
+HELP_LINGUAS = en-US ja sv ga bn_BD id @TOR_BROWSER_BUNDLE_LOCALES@
.PHONY: html
html: all media-symlinks.stamp
diff --git a/id/id.po b/id/id.po
new file mode 100644
index 0000000..39e0d05
--- /dev/null
+++ b/id/id.po
@@ -0,0 +1,1838 @@
+# Translators:
+# zk, 2016
+# Yerry Borang <yerry.borang(a)gmail.com>, 2016
+# Irham Duilah <irhamduilah03(a)gmail.com>, 2016
+# Jaya Wijaya <SecretCommission(a)tormail.org>, 2016
+# runasand <inactive+runasand(a)transifex.com>, 2016
+# Rendiyono Wahyu Saputro <rendi.7936(a)gmail.com>, 2016
+# Lucas Susanto <susantolucas(a)yahoo.com>, 2016
+# hpiece 8 <hpiece8(a)gmail.com>, 2017
+# Christian "crse" Elbrianno, 2017
+# adhisuryo i <adhisuryo(a)gmail.com>, 2017
+# ical, 2017
+# Benyamin Adrianus Dos Santos <bendroxnahak(a)gmail.com>, 2017
+# Dinar Lubis <goarhudinar(a)yahoo.com>, 2017
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"POT-Creation-Date: 2016-12-06 16:36-0600\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Dinar Lubis <goarhudinar(a)yahoo.com>, 2017\n"
+"Language-Team: Indonesian (https://www.transifex.com/otf/teams/1519/id/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: id\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#. Put one translator per line, in the form NAME <EMAIL>, YEAR1, YEAR2
+msgctxt "_"
+msgid "translator-credits"
+msgstr "Penghargaan untuk Penerjemah"
+
+#: about-tor-browser.page:7
+msgid "Learn what Tor Browser can do to protect your privacy and anonymity"
+msgstr ""
+"Pelajari apa yang Tor Browser dapat lakukan untuk melindungi privasi dan "
+"kerahasiaan anda"
+
+#: about-tor-browser.page:10
+msgid "About Tor Browser"
+msgstr "Tentang Tor Browser"
+
+#: about-tor-browser.page:12
+msgid ""
+"Tor Browser uses the Tor network to protect your privacy and anonymity. "
+"Using the Tor network has two main properties:"
+msgstr ""
+"Tor Browser menggunakan jaringan Tor untuk melindungi privasi dan "
+"kerahasiaan anda. Jaringan Tor memiliki dua pengaturan utama:"
+
+#: about-tor-browser.page:18
+msgid ""
+"Your internet service provider, and anyone watching your connection locally,"
+" will not be able to track your internet activity, including the names and "
+"addresses of the websites you visit."
+msgstr ""
+"Penyedia layanan internet dan siapapun yang memantau koneksi anda tidak bisa"
+" melacak aktivitas internet anda termasuk nama dan alamat situs yang anda "
+"kunjungi."
+
+#: about-tor-browser.page:25
+msgid ""
+"The operators of the websites and services that you use, and anyone watching"
+" them, will see a connection coming from the Tor network instead of your "
+"real Internet (IP) address, and will not know who you are unless you "
+"explicitly identify yourself."
+msgstr ""
+"Operator website dan layanan yang anda gunakan, dan setiap orang yang "
+"menyaksikannya, akan melihat koneksi berasal dari jaringan Tor ketimbang "
+"alamat asli internet (IP) anda, dan tidak akan mengetahui identitas anda "
+"kecuali anda memberitahu identitas anda."
+
+#: about-tor-browser.page:34
+msgid ""
+"In addition, Tor Browser is designed to prevent websites from "
+"“fingerprinting” or identifying you based on your browser configuration."
+msgstr ""
+"Tambahan, Tor Browser telah di desain untuk mencegah situs melakukan "
+"\"fingerprinting\" atau mengidentifikasi anda berdasarkan pengaturan "
+"browser."
+
+#: about-tor-browser.page:39
+msgid ""
+"By default, Tor Browser does not keep any browsing history. Cookies are only"
+" valid for a single session (until Tor Browser is exited or a <link xref"
+"=\"managing-identities#new-identity\">New Identity</link> is requested)."
+msgstr ""
+"Secara bawaan, Tor Browser tidak menyimpan sejarah perambahan. Cookies hanya"
+" valid untuk sesi tunggal (hingga keluar dari Tor Browser atau sebuah<link "
+"xref=\"managing-identities#new-identity\">Identitas Baru</link>diminta)."
+
+#: about-tor-browser.page:50
+msgid "How Tor works"
+msgstr "Bagaimana Tor bekerja\n"
+
+#: about-tor-browser.page:52
+msgid ""
+"Tor is a network of virtual tunnels that allows you to improve your privacy "
+"and security on the Internet. Tor works by sending your traffic through "
+"three random servers (also known as <em>relays</em>) in the Tor network. The"
+" last relay in the circuit (the “exit relay”) then sends the traffic out "
+"onto the public Internet."
+msgstr ""
+"Tor adalah sebuah jaringan dari terowongan-terowongan virtual yang "
+"memungkinkan anda untuk meningkatkan privasi anda dan keamanan dalam "
+"Internet. Tor bekerja dengan mengirim lalu lintas anda melalui tiga server "
+"acak (juga dikenal sebagai <em>relay</em>) dalam jaringan Tor. Relay yang "
+"terakhir dalam sirkuit (\"relay keluar\") lalu mengirim lalu lintas keluar "
+"menuju Internet publik."
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: about-tor-browser.page:59
+msgctxt "_"
+msgid ""
+"external ref='media/how-tor-works.png' "
+"md5='6fe4151a88b7a518466f0582e40ccc8c'"
+msgstr ""
+"external ref='media/how-tor-works.png' "
+"md5='6fe4151a88b7a518466f0582e40ccc8c'"
+
+#: about-tor-browser.page:60
+msgid ""
+"The image above illustrates a user browsing to different websites over Tor. "
+"The green middle computers represent relays in the Tor network, while the "
+"three keys represent the layers of encryption between the user and each "
+"relay."
+msgstr ""
+"Gambar di atas menggambarkan seorang pengguna meramban beberapa website "
+"melalui Tor. Komputer-komputer hijau di tengah merepresentasikan relay-relay"
+" dalam jaringan Tor, sementara tiga kunci merepresentasikan lapisan-lapisan "
+"enkripsi antara pengguna dan setiap relay."
+
+#: bridges.page:6
+msgid "Learn what bridges are and how to get them"
+msgstr "Pelajari apa itu jembatan-jembatan dan bagaimana mendapatkannya"
+
+#: bridges.page:10
+msgid "Bridges"
+msgstr "Jembatan-jembatan"
+
+#: bridges.page:12
+msgid ""
+"Most <link xref=\"transports\">Pluggable Transports</link>, such as obfs3 "
+"and obfs4, rely on the use of “bridge” relays. Like ordinary Tor relays, "
+"bridges are run by volunteers; unlike ordinary relays, however, they are not"
+" listed publicly, so an adversary cannot identify them easily. Using bridges"
+" in combination with pluggable transports helps to disguise the fact that "
+"you are using Tor."
+msgstr ""
+"Kebanyakan <link xref=\"transports\">Angkutan Colok</link>, seperti obfs3 "
+"dan obfs4, bergantung pada penggunaan \"jembatan\" relay. Seperti relay-"
+"relay Tor biasa, jembatan-jembatan ini dijalankan oleh para relawan; namun "
+"tidak seperti relay pada umumnya, mereka tidak terdaftar secara publik, "
+"sehingga seorang lawan tidak dapat mengidentifikasi pengguna dengan mudah. "
+"Menggunakan jembatan-jembatan dikombinasikan dengan angkutan colok membantu "
+"menyamarkan fakta bahwa anda sedang menggunakan Tor."
+
+#: bridges.page:21
+msgid ""
+"Other pluggable transports, like meek, use different anti-censorship "
+"techniques that do not rely on bridges. You do not need to obtain bridge "
+"addresses in order to use these transports."
+msgstr ""
+"Diska lepas yang lain, seperti meek, menggunakan teknik anti-sensor berbeda "
+"yang tidak mengandalkan jembatan-jembatan. Anda tidak perlu mencari alamat-"
+"alamat jembatan untuk menggunakannya."
+
+#: bridges.page:28
+msgid "Getting bridge addresses"
+msgstr "Mendapatkan alamat-alamat jembatan"
+
+#: bridges.page:29
+msgid ""
+"Because bridge addresses are not public, you will need to request them "
+"yourself. You have two options:"
+msgstr ""
+"Karena alamat-alamat jembatan tidak terbuka untuk umum, anda perlu membuat "
+"permintaan sendiri. Anda punya dua pilihan:"
+
+#: bridges.page:36
+msgid ""
+"Visit <link "
+"href=\"https://bridges.torproject.org/\">https://bridges.torproject.org/</link>"
+" and follow the instructions, or"
+msgstr ""
+"Kunjungi <link "
+"href=\"https://bridges.torproject.org/\">https://bridges.torproject.org/</link>"
+" dan ikuti petunjuk, atau"
+
+#: bridges.page:42
+msgid ""
+"Email bridges(a)torproject.org from a Gmail, Yahoo, or Riseup email address, "
+"or"
+msgstr ""
+"Email bridges(a)torproject.org melalui alamat email Gmail, Yahoo, atau Riseup,"
+" atau"
+
+#: bridges.page:51
+msgid "Entering bridge addresses"
+msgstr "Memasukkan alamat-alamat jembatan"
+
+#: bridges.page:52
+msgid ""
+"Once you have obtained some bridge addresses, you will need to enter them "
+"into Tor Launcher."
+msgstr ""
+"Begitu anda mendapatkan beberapa alamat jembatan, anda perlu untuk "
+"memasukkannya ke dalam Peluncur Tor."
+
+#: bridges.page:57
+msgid ""
+"Choose “yes” when asked if your Internet Service Provider blocks connections"
+" to the Tor network. Select “Use custom bridges” and enter each bridge "
+"address on a separate line."
+msgstr ""
+"Pilih \"yes\" ketika ditanya apakah ISP atau penyedia layanan internet anda "
+"memblokir hubungan ke jaringan Tor. Pilih \"Use custom bridges\" dan "
+"masukkan setiap alamat jembatan dalam baris yang berbeda."
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: bridges.page:63
+msgctxt "_"
+msgid ""
+"external ref='media/tor-launcher-custom-bridges_en-US.png' "
+"md5='93365c2aa3fb4d627497e83f28a39b7e'"
+msgstr ""
+"external ref='media/tor-launcher-custom-bridges_en-US.png' "
+"md5='93365c2aa3fb4d627497e83f28a39b7e'"
+
+#: bridges.page:65
+msgid ""
+"Click “Connect”. Using bridges may slow down the connection compared to "
+"using ordinary Tor relays. If the connection fails, the bridges you received"
+" may be down. Please use one of the above methods to obtain more bridge "
+"addresses, and try again."
+msgstr ""
+"Klik \"Connect\". Menggunakan jembatan-jembatan bisa memperlambat koneksi "
+"dibandingkan menggunakan relay-relay Tor biasa. Jika koneksi gagal, "
+"jembatan-jembatan yang anda terima mungkin sedang mati. Gunakan salah satu "
+"metode di atas untuk mendapatkan alamat-alamat jembatan, dan coba lagi."
+
+#: circumvention.page:6
+msgid "What to do if the Tor network is blocked"
+msgstr "Apa yang perlu dilakukan jika jaringan Tor diblok"
+
+#: circumvention.page:10
+msgid "Circumvention"
+msgstr "Pengelakan"
+
+#: circumvention.page:12
+msgid ""
+"Direct access to the Tor network may sometimes be blocked by your Internet "
+"Service Provider or by a government. Tor Browser includes some circumvention"
+" tools for getting around these blocks. These tools are called “pluggable "
+"transports”. See the <link xref=\"transports\">Pluggable Transports</link> "
+"page for more information on the types of transport that are currently "
+"available."
+msgstr ""
+"Akses langsung pada jaringan Tor terkadang bisa diblokir oleh penyedia "
+"layanan internet atau oleh pemerintah. Peramban Tor termasuk beberapa "
+"perangkat mengelak untuk mengatasi pemblokiran ini. Perangkat-perangkat ini "
+"disebut \"Angkutan Colok\". Lihat halaman <link xref=\"transports\">Angkutan"
+" Colok</link>untuk informasi lebih tentang jenis angkutan yang tersedia."
+
+#: circumvention.page:22
+msgid "Using pluggable transports"
+msgstr "Menggunakan pluggable transports"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: circumvention.page:26 first-time.page:35
+msgctxt "_"
+msgid ""
+"external ref='media/circumvention/configure.png' "
+"md5='519d888303eadfe4cb03f178aedd90f5'"
+msgstr ""
+"external ref='media/circumvention/configure.png' "
+"md5='519d888303eadfe4cb03f178aedd90f5'"
+
+#: circumvention.page:28
+msgid ""
+"To use pluggable transports, click \"Configure\" in the Tor Launcher window "
+"that appears when you first run Tor Browser."
+msgstr ""
+"Untuk menggunakan angkutan colok, klik \"Configure\" dalam jendela Peluncur "
+"Tor yang muncul ketika anda menjalankan Peramban Tor pertama kali."
+
+#: circumvention.page:33
+msgid ""
+"You can also configure pluggable transports while Tor Browser is running, by"
+" clicking on the green onion near your address bar and selecting “Tor "
+"Network Settings”."
+msgstr ""
+"Anda juga bisa mengatur pluggable transports sembari Tor Browser sedang "
+"berjalan, dengan menekan pada bawang berwarna hijau di dekat kolom alamat "
+"dan memilih \"Tor Network Settings\""
+
+#: circumvention.page:41
+msgid ""
+"Select “yes” when asked if your Internet Service Provider blocks connections"
+" to the Tor network."
+msgstr ""
+"Pilih \"yes\" ketika ditanya jika penyedia layanan internet anda memblokir "
+"koneksi ke jaringan Tor."
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: circumvention.page:49
+msgctxt "_"
+msgid ""
+"external ref='media/circumvention/bridges.png' "
+"md5='910cdd5e45860b81a1ad4739c589a195'"
+msgstr ""
+"external ref='media/circumvention/bridges.png' "
+"md5='910cdd5e45860b81a1ad4739c589a195'"
+
+#: circumvention.page:51
+msgid ""
+"Select “Connect with provided bridges”. Tor Browser currently has six "
+"pluggable transport options to choose from."
+msgstr ""
+"PIlih \"Connect with provided bridges\". Peramban Tor saat ini memiliki enam"
+" opsi angkutan colok untuk dipilih."
+
+#: circumvention.page:60
+msgid "Which transport should I use?"
+msgstr "Transport manakah yang sebaiknya saya gunakan?"
+
+#: circumvention.page:61
+msgid ""
+"Each of the transports listed in Tor Launcher’s menu works in a different "
+"way (for more details, see the <link xref=\"transports\">Pluggable "
+"Transports</link> page), and their effectiveness depends on your individual "
+"circumstances."
+msgstr ""
+"Setiap transports yang terdaftar dalam menu Peluncur Tor bekerja dengan cara"
+" berbeda (untuk detil, lihat laman<link xref=\"transports\">Angkutan "
+"Colok</link>), dan efektivitasnya bergantung pada keadaan anda."
+
+#: circumvention.page:67
+msgid ""
+"If you are trying to circumvent a blocked connection for the first time, you"
+" should try the different transports: obfs3, obfs4, ScrambleSuit, fte, meek-"
+"azure, meek-amazon."
+msgstr ""
+"Jika anda mencoba mengelak dari koneksi yang diblokir untuk pertama kali, "
+"anda perlu mencoba angkutan yang berbeda: obfs3, obfs4, ScrambeSuit, fte, "
+"meek-azure, meek-amazon."
+
+#: circumvention.page:72
+msgid ""
+"If you try all of these options, and none of them gets you online, you will "
+"need to enter bridge addresses manually. Read the <link "
+"xref=\"bridges\">Bridges</link> section to learn what bridges are and how to"
+" obtain them."
+msgstr ""
+"Jika anda mencoba semua opsi yang tersedia, dan tidak ada yang membuat anda "
+"daring, anda oerlu untuk memasukkan alamat jembatan secara manual. Baca "
+"bagian<link xref=\"bridges\">Jembatan-jembatan</link> untuk mempelajari apa "
+"itu jembatan dan bagaimana mendapatkannya."
+
+#: downloading.page:7
+msgid "How to download Tor Browser"
+msgstr "Bagaimana mengunduh Tor Browser"
+
+#: downloading.page:10
+msgid "Downloading"
+msgstr "Mengunduh"
+
+#: downloading.page:12
+msgid ""
+"The safest and simplest way to download Tor Browser is from the official Tor"
+" Project website at https://www.torproject.org. Your connection to the site "
+"will be secured using <link xref=\"secure-connections\">HTTPS</link>, which "
+"makes it much harder for somebody to tamper with."
+msgstr ""
+"Cara aman dan mudah untuk mengunduh TOR Browser yaitu berasal dari situs "
+"resmi TOR Project https:/www.torproject.org. Koneksi ke situs akan "
+"terlindungi dengan menggunakan <link xref=\"secure-"
+"connections\">HTTPS</link>, sehingga ini akan membuat seseorang sulit "
+"melakukan gangguan."
+
+#: downloading.page:19
+msgid ""
+"However, there may be times when you cannot access the Tor Project website: "
+"for example, it could be blocked on your network. If this happens, you can "
+"use one of the alternative download methods listed below."
+msgstr ""
+"Namun, dalam sejumlah kasus anda tak bisa mengakses situs TOR Project: "
+"misalnya, situs ini diblokir oleh jaringan Anda. Jika ini terjadi, Anda bisa"
+" menggunakan sejumlah jalur alternatif unduhan seperti daftar di bawah ini."
+
+#: downloading.page:27
+msgid "GetTor"
+msgstr "GetTor"
+
+#: downloading.page:28
+msgid ""
+"GetTor is a service that automatically responds to messages with links to "
+"the latest version of Tor Browser, hosted at a variety of locations, such as"
+" Dropbox, Google Drive and Github.."
+msgstr ""
+"GetTor adalah sebuah servise yang secara otomatis menjawab pesan dengan "
+"tautan pada versi terakhir dari TorBrowser, penerima diberbagai lokasi, "
+"seperti Dropbox, Google Drive dan Github.."
+
+#: downloading.page:34
+msgid "To use GetTor via email:"
+msgstr "Menggunakan GetTor lewat email:"
+
+#: downloading.page:39
+msgid ""
+"Send an email to gettor(a)torproject.org, and in the body of the message "
+"simply write “windows”, “osx”, or “linux”, (without quotation marks) "
+"depending on your operating system."
+msgstr ""
+"Kirim email ke gettor(a)torproject.org, dan di dalam pesan tulislah "
+"\"windows\", \"osx\", atau \"linux\", (tanpa tanda kutip) tergantung sistem "
+"operasi ada."
+
+#: downloading.page:46
+msgid ""
+"GetTor will respond with an email containing links from which you can "
+"download the Tor Browser package, the cryptographic signature (needed for "
+"verifying the download), the fingerprint of the key used to make the "
+"signature, and the package’s checksum. You may be offered a choice of "
+"“32-bit” or “64-bit” software: this depends on the model of the computer you"
+" are using."
+msgstr ""
+"GetTor akan merespon dengan email yang memuat tautan dari sumber pengunduh "
+"paket Tor Browser, tanda tangan kriptografi (diperlukan untuk memverikasi "
+"unduhan), sidik jari pengguna utama yang akan digunakan untuk membuat tanda "
+"tangan, dan paket checksum. Anda akan di tawarkan dengan dua pilihan "
+"perangkat lunak: '32 bit\" atau 64 bit. Pilihan ini tergantung dengan model "
+"komputer yang anda gunakan"
+
+#: downloading.page:57
+msgid "To use GetTor via Twitter:"
+msgstr "Mengunakan GetTor melalui Twitter"
+
+#: downloading.page:62
+msgid ""
+"To get links for downloading Tor Browser in English for OS X, send a Direct "
+"Message to @get_tor with the words \"osx en\" in it (you don't need to "
+"follow the account)."
+msgstr ""
+"Untuk mendapatkan tautan guna mengunduh Tor browser dalam bahasa Inggris "
+"pada OS X, kirimlah email langsung ke @get_tor dengan subjek \"osx en\" "
+"(anda tidak perlu mengikuti akun tersebut)"
+
+#: downloading.page:70
+msgid "To use GetTor via Jabber/XMPP (Tor Messenger, Jitsi, CoyIM):"
+msgstr ""
+"Untuk menggunakan GetTor melalui Jabber/XMPP (Tor Messenger, Jitsi, CoyIM)"
+
+#: downloading.page:75
+msgid ""
+"To get links for downloading Tor Browser in Chinese for Linux, send a "
+"message to gettor(a)torproject.org with the words \"linux zh\" in it."
+msgstr ""
+"Untuk mendapatkan tautan guna mengunduh Tor Browser dalam bahasa China untu"
+" Linux, kirimkan sebuah email ke gettor(a)torproject.org dengan subjek \"linux"
+" zh\""
+
+#: downloading.page:84
+msgid "Satori"
+msgstr "Satori"
+
+#: downloading.page:85
+msgid ""
+"Satori is an add-on for the Chrome or Chromium browsers that allows you to "
+"download several security and privacy programs from different sources."
+msgstr ""
+"Satori adalah sebuah tambahan untuk peramban chrome atau chromium yang "
+"mengijinkan anda mengunduh beberapa program keamanan dan privasi dari "
+"sumber yang berbeda"
+
+#: downloading.page:90
+msgid "To download Tor Browser using Satori:"
+msgstr "Gunakan Satori untuk menguduh Tor Browser"
+
+#: downloading.page:95
+msgid "Install Satori from the Chrome App Store."
+msgstr "Pasang Satori pada Chrome apps store"
+
+#: downloading.page:100
+msgid "Select Satori from your browser’s Apps menu."
+msgstr "Seleksi Satori dari browser apps menu anda"
+
+#: downloading.page:105
+msgid ""
+"When Satori opens, click on your preferred language. A menu will open "
+"listing the available downloads for that language. Find the entry for Tor "
+"Browser under the name of your operating system. Select either “A” or “B” "
+"after the name of the program — each one represents a different source from "
+"which to get the software. Your download will then begin."
+msgstr ""
+"Ketika Satori dibuka, Klik pada bahasa yang anda inginkan. Menu A akan "
+"membuka daftar mengunduh yang tersedia untuk bahasa tersebut. Temukan akses "
+"untuk TorBrowser dengan nama sistem operasi Anda. Pilih \"A\" atau \"B\" "
+"setelah nama program - masing-masing mewakili sumber yang berbeda untuk "
+"mendapatkan perangkat lunak. Unduhan anda akan di mulai."
+
+#: downloading.page:115
+msgid ""
+"Wait for your download to finish, then find the “Generate Hash” section in "
+"Satori’s menu and click “Select Files”."
+msgstr ""
+"Tunggu hingga unduhan anda selesai, kemudian temukan \"Generate Hash\" pada"
+" menu Satori, lalu klik \"Select Files\". "
+
+#: downloading.page:121
+msgid ""
+"Select the downloaded Tor Browser file. Satori will display the checksum of "
+"the file, which you should compare with the software’s original checksum: "
+"you can find this by clicking the word “checksum” after the link you clicked"
+" on to start the download. If the checksums match, your download was "
+"successful, and you can <link xref=\"first-time\">begin using Tor "
+"Browser</link>. If they do not match, you may need to try downloading again,"
+" or from a different source."
+msgstr ""
+"Pilih pengunduh file Tor Browser . Satori akan memunculkan checksum dari "
+"seuah fil, yang mana anda harus membandingkan dengan perangkat lunak "
+"checksum yang asli: anda dapat menemukannya dengan mengklik kata "
+"\"checksum\" setelah tautan yang ada klik mulai mengunduh. Jika the checksum"
+" cocok, anda telah berhasil mengunduh, sehingga anda dapat :1) memulai Tor "
+"Browser, 2) jika tidak cocok, maka anda perlu mencoba mengunduh kembali, "
+"atau mencoba dari sumber yang berbeda. "
+
+#: first-time.page:7
+msgid "Learn how to use Tor Browser for the first time"
+msgstr "Pelajari cara menggunakan Tor Browser untuk pertama kali"
+
+#: first-time.page:10
+msgid "Running Tor Browser for the first time"
+msgstr "Menjalankan Tor Browser untuk pertama kali"
+
+#: first-time.page:12
+msgid ""
+"When you run Tor Browser for the first time, you will see the Tor Network "
+"Settings window. This offers you the option to connect directly to the Tor "
+"network, or to configure Tor Browser for your connection."
+msgstr ""
+"Saat kamu menjalankan Tor Browser untuk pertama kali, kamu akan melihat "
+"laman Pengaturan Jaringan Tor. Ini memberikan pilihan untuk langsung "
+"terhubung ke jaringan Tor, atau melakukan konfigurasi Tor Browser untuk "
+"koneksi anda."
+
+#: first-time.page:19
+msgid "Connect"
+msgstr "Sambung"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: first-time.page:21 troubleshooting.page:18
+msgctxt "_"
+msgid ""
+"external ref='media/first-time/connect.png' "
+"md5='9d07068f751a3bfd274365a4ba8d90ca'"
+msgstr ""
+"external ref='media/first-time/connect.png' "
+"md5='9d07068f751a3bfd274365a4ba8d90ca'"
+
+#: first-time.page:23
+msgid ""
+"In most cases, choosing \"Connect\" will allow you to connect to the Tor "
+"network without any further configuration. Once clicked, a status bar will "
+"appear, showing Tor’s connection progress. If you are on a relatively fast "
+"connection, but this bar seems to get stuck at a certain point, see the "
+"<link xref=\"troubleshooting\">Troubleshooting</link> page for help solving "
+"the problem."
+msgstr ""
+"Dalam kebanyakan kasus, memilih \"Connect\" akan memungkinkan Anda terhubung"
+" ke jaringan Tor tanpa konfigurasi lebih lanjut. Setelah diklik, bar status "
+"akan muncul, menunjukkan kemajuan koneksi Tor. Jika Anda berada pada koneksi"
+" yang relatif cepat, namun bar ini tampaknya terjebak pada titik tertentu, "
+"lihat halaman 1 PPemecahan Masalah 2 untuk mendapatkan bantuan dalam "
+"menyelesaikan masalah."
+
+#: first-time.page:33
+msgid "Configure"
+msgstr "Konfigurasikan"
+
+#: first-time.page:37
+msgid ""
+"If you know that your connection is censored, or uses a proxy, you should "
+"select this option. Tor Browser will take you through a series of "
+"configuration options."
+msgstr ""
+"Jika Anda tahu bahwa koneksi Anda disensor, atau menggunakan proxy, Anda "
+"harus memilih opsi ini. Tor Browser akan membawa Anda melalui serangkaian "
+"pilihan konfigurasi."
+
+#: first-time.page:44
+msgid ""
+"The first screen asks if access to the Tor network is blocked or censored on"
+" your connection. If you do not believe this is the case, select “No”. If "
+"you know your connection is censored, or you have tried and failed to "
+"connect to the Tor network and no other solutions have worked, select “Yes”."
+" You will then be taken to the <link "
+"xref=\"circumvention\">Circumvention</link> screen to configure a pluggable "
+"transport."
+msgstr ""
+"Layar pertama menanyakan jika akses ke jaringan Tor di blokir atau di sensor"
+" pada koneksi anda. Jika anda tidak yakin hal ini menjadi kasus, pilih "
+"\"No\". Jika anda mengetahui bahwa jaringan di sensor, atau anda mencoba dan"
+" gagal terhubung dengan jaringan Tor dan tidak ada yang lain yang berhasil, "
+"pilih \"yes\". Anda akan dibawa pada 1) circumvention 2) layar untuk "
+"mengkonfigurasi pluggable transport"
+
+#: first-time.page:55
+msgid ""
+"The next screen asks if your connection uses a proxy. In most cases, this is"
+" not necessary. You will usually know if you need to answer “Yes”, as the "
+"same settings will be used for other browsers on your system. If possible, "
+"ask your network administrator for guidance. If your connection does not use"
+" a proxy, click “Continue”."
+msgstr ""
+"Layar selanjutnya menanyakan jika koneksi anda menggunakan sebuah proxy. "
+"Pada banyak kasus, hal ini tidak diperlukan. Biasanya anda akan mengetahui "
+"jika anda perlu menjawab \"yes\", sebagaimana pada pengaturan yang "
+"digunakan oleh browser yang lain pada sistem anda. Jika memungkinkan, "
+"tanyakan pengelola jaringan untuk panduan. Jika koneksi tidak menggunakan "
+"sebuah proksi, klik \"continue\". "
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: first-time.page:63
+msgctxt "_"
+msgid ""
+"external ref='media/first-time/proxy_question.png' "
+"md5='30853b3e86cfd386bbc32e5b8b45a378'"
+msgstr ""
+"external ref='media/first-time/proxy_question.png' "
+"md5='30853b3e86cfd386bbc32e5b8b45a378'"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: first-time.page:66
+msgctxt "_"
+msgid ""
+"external ref='media/first-time/proxy.png' "
+"md5='13f21a351cd0aa1cf11aada690f3dc90'"
+msgstr ""
+"external ref='media/first-time/proxy.png' "
+"md5='13f21a351cd0aa1cf11aada690f3dc90'"
+
+#: index.page:6
+msgid "Tor Browser User Manual"
+msgstr "Panduan Pengguna Tor Browser"
+
+#: known-issues.page:6
+msgid "A list of known issues."
+msgstr "Daftar masalah yang diketahui."
+
+#: known-issues.page:10
+msgid "Known Issues"
+msgstr "Masalah yang telah diketahui"
+
+#: known-issues.page:14
+msgid ""
+"Tor needs your system clock (and your time zone) set to the correct time."
+msgstr ""
+"Tor membutuhkan sistem waktu (dan zona waktu anda) diatur pada waktu yang "
+"tepat."
+
+#: known-issues.page:19
+msgid ""
+"The following firewall software have been known to interfere with Tor and "
+"may need to be temporarily disabled:"
+msgstr ""
+"Perangkat lunak firewall berikut telah diketahui mengganggu Tor dan mungkin "
+"perlu dinonaktifkan sementara:"
+
+#: known-issues.page:23
+msgid "Webroot SecureAnywhere"
+msgstr "Webroot aman dimana saja"
+
+#: known-issues.page:26
+msgid "Kaspersky Internet Security 2012"
+msgstr "Kaspersky Internet Security 2012"
+
+#: known-issues.page:29
+msgid "Sophos Antivirus for Mac"
+msgstr "Sophos Antivirus untuk Mac"
+
+#: known-issues.page:32
+msgid "Microsoft Security Essentials"
+msgstr "Microsoft Security yang penting"
+
+#: known-issues.page:37
+msgid ""
+"Videos that require Adobe Flash are unavailable. Flash is disabled for "
+"security reasons."
+msgstr ""
+"Video yang membutuhkan Adobe Flash tidak tersedia. Flash dinon-aktifkan "
+"untuk alasan keamanan."
+
+#: known-issues.page:43
+msgid "Tor can not use a bridge if a proxy is set."
+msgstr "Tor tidak dapat menggunakan bridge apabila proxy sudah diatur."
+
+#: known-issues.page:48
+msgid ""
+"The Tor Browser package is dated January 1, 2000 00:00:00 UTC. This is to "
+"ensure that each software build is exactly reproducible."
+msgstr ""
+"Paket Tor Browser bertanggal 1 Januari 2000 00:00:00 UTC. Hal ini untuk "
+"menjamin bahwa setiap perangkat lunak secara tepat dapat digandakan."
+
+#: known-issues.page:54
+msgid ""
+"To run Tor Browser on Ubuntu, users need to execute a shell script. Open "
+"\"Files\" (Unity's explorer), open Preferences → Behavior Tab → Set \"Run "
+"executable text files when they are opened\" to \"Ask every time\", then "
+"click OK."
+msgstr ""
+"Untuk menjalankan Tor Browser pada Ubuntu, pengguna perlu menjalankan shell "
+"script. Buka \"Files\" (Unity Explorer), buka Preference → Behavior Tab → "
+"Set \"Run executable text files when they are opened\" menjadi \"Ask every "
+"time\", lalu klik OK."
+
+#: known-issues.page:62
+msgid ""
+"Tor Browser can also be started from the command line by running the "
+"following command from inside the Tor Browser directory:"
+msgstr ""
+"Tor Browser bisa juga di mulai dari garis command dengan menjalankan "
+"perintah dari dalam direktori Tor Browser"
+
+#: known-issues.page:66
+#, no-wrap
+msgid ""
+"\n"
+" ./start-tor-browser.desktop\n"
+" "
+msgstr ""
+"\n"
+" ./start-tor-browser.desktop\n"
+" "
+
+#: managing-identities.page:6
+msgid "Learn how to control personally-identifying information in Tor Browser"
+msgstr ""
+"Pelajari bagaimana mengontrol informasi identifikasi pribadi di Tor Browser"
+
+#: managing-identities.page:10
+msgid "Managing identities"
+msgstr "Mengelola identitas"
+
+#: managing-identities.page:12
+msgid ""
+"When you connect to a website, it is not only the operators of that website "
+"who can record information about your visit. Most websites now use numerous "
+"third-party services, including social networking “Like” buttons, analytics "
+"trackers, and advertising beacons, all of which can link your activity "
+"across different sites."
+msgstr ""
+"Saat kamu terkoneksi ke sebuah situs, bukan hanya operator situs tersebut "
+"yang bisa merekam informasi mengenai kunjungan anda. Kebanyakan situs saat "
+"ini menggunakan banyak sekali layanan pihak ketiga, termasuk tombol \"Like\""
+" pada sosial media, analisis pelacak, dan suar iklan, yang semuanya bisa "
+"mengkaitkan aktivitasmu di situs yang berbeda."
+
+#: managing-identities.page:20
+msgid ""
+"Using the Tor network stops observers from being able to discover your exact"
+" location and IP address, but even without this information they might be "
+"able to link different areas of your activity together. For this reason, Tor"
+" Browser includes some additional features that help you control what "
+"information can be tied to your identity."
+msgstr ""
+"Menggunakan jaringan Tor, dapat menghentikan pengamat menemukan lokasi dan "
+"alamat IP anda yang sebenarnya, namun jika walaupun tanpa informasi tersebut"
+" pengamat masih mungkin dapat menghubungkan lokasi aktifitas anda yang "
+"berbeda beda secara keseluruhan. Untuk tujuan ini, Tor Browser menyertakan "
+"beberapa fitur tambahan yang akan membantu anda mengkontrol informasi apa "
+"yang akan disertakan pada identitas anda. "
+
+#: managing-identities.page:29
+msgid "The URL bar"
+msgstr "Bar URL"
+
+#: managing-identities.page:30
+msgid ""
+"Tor Browser centers your web experience around your relationship with the "
+"website in the URL bar. Even if you connect to two different sites that use "
+"the same third-party tracking service, Tor Browser will force the content to"
+" be served over two different Tor circuits, so the tracker will not know "
+"that both connections originate from your browser."
+msgstr ""
+"Tor Browser memusatkan aktifitas berinternet seputar hubungan anda dengan "
+"situs pada kolom URL. Bahkan jika anda terhubung dengan dua situs berbeda "
+"yang menggunakan layanan pelacak pihak ke tiga, Tor Browser akan memaksa "
+"konten untuk dilewati dua sirkuit Tor yang berbeda, jadi orang yang melacak "
+"tidak mengetahui bahwa kedua koneksi tersebut berasal dari browser anda. "
+
+#: managing-identities.page:38
+msgid ""
+"On the other hand, all connections to a single website address will be made "
+"over the same Tor circuit, meaning you can browse different pages of a "
+"single website in separate tabs or windows, without any loss of "
+"functionality."
+msgstr ""
+"Disamping itu, setiap koneksi untuk alamat situs tunggal akan dibuat dengan "
+"sirkuit Tor yang sama, artinya anda dapat menjelajahi halaman yang berbeda "
+"pada sebuat situs tunggal pada tabs atau jendela yang berbeda, tanpa "
+"kehilangan satupun funsionalitas. "
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: managing-identities.page:46
+msgctxt "_"
+msgid ""
+"external ref='media/managing-identities/circuit_full.png' "
+"md5='bd46d22de952fee42643be46d3f95928'"
+msgstr ""
+"external ref='media/managing-identities/circuit_full.png' "
+"md5='bd46d22de952fee42643be46d3f95928'"
+
+#: managing-identities.page:48
+msgid ""
+"You can see a diagram of the circuit that Tor Browser is using for the "
+"current tab in the onion menu."
+msgstr ""
+"Kamu dapat melihat diagram dari sirkuit yang digunakan Tor Browser pada tab "
+"saat ini di menu onion."
+
+#: managing-identities.page:55
+msgid "Logging in over Tor"
+msgstr "Masuk lebih dari Tor"
+
+#: managing-identities.page:56
+msgid ""
+"Although Tor Browser is designed to enable total user anonymity on the web, "
+"there may be situations in which it makes sense to use Tor with websites "
+"that require usernames, passwords, or other identifying information."
+msgstr ""
+"Meskipun Tor Browser dirancang untuk memungkinkan anonimitas total pengguna "
+"di web, mungkin ada situasi di mana masuk akal untuk menggunakan Tor dengan "
+"situs web yang memerlukan nama pengguna, kata sandi, atau informasi "
+"identitas lainnya."
+
+#: managing-identities.page:62
+msgid ""
+"If you log into a website using a regular browser, you also reveal your IP "
+"address and geographical location in the process. The same is often true "
+"when you send an email. Logging into your social networking or email "
+"accounts using Tor Browser allows you to choose exactly which information "
+"you reveal to the websites you browse. Logging in using Tor Browser is also "
+"useful if the website you are trying to reach is censored on your network."
+msgstr ""
+"Bila kamu masuk ke sebuah situs menggunakan peramban reguler, kamu juga "
+"menunjukkan alamat IP dan lokasi geografis anda dalam prosesnya. Hal yang "
+"sama seringkali juga terjadi saat kamu mengirim surel. Masuk ke dalam media "
+"sosial atau akun surel anda menggunakan Tor Browser memungkinkan anda untuk "
+"memilih informasi mana yang ingin anda ungkap ke situs yang anda kunjungi. "
+"Masuk menggunakan Tor Browser juga berguna bila situs yang kamu coba untuk "
+"akses disensor pada jaringan anda."
+
+#: managing-identities.page:72
+msgid ""
+"When you log in to a website over Tor, there are several points you should "
+"bear in mind:"
+msgstr ""
+"Ketika anda masuk ke sebuah website memakai TOR, ada sejumlah hal yang mesti"
+" anda ingat:"
+
+#: managing-identities.page:79
+msgid ""
+"See the <link xref=\"secure-connections\">Secure Connections</link> page for"
+" important information on how to secure your connection when logging in."
+msgstr ""
+"Lihat halaman<link xref=\"secure-connections\">Secure "
+"Connections</link>untuk informasi penting tentang cara mengamankan koneksi "
+"Anda saat login."
+
+#: managing-identities.page:87
+msgid ""
+"Tor Browser often makes your connection appear as though it is coming from "
+"an entirely different part of the world. Some websites, such as banks or "
+"email providers, might interpret this as a sign that your account has been "
+"hacked or compromised, and lock you out. The only way to resolve this is by "
+"following the site’s recommended procedure for account recovery, or "
+"contacting the operators and explaining the situation."
+msgstr ""
+"Tor Browser seringkali membuat koneksi anda seakan-akan datang dari bagian "
+"dunia yang sama sekali berbeda. Sejumlah situs, seperti bank atau penyedia "
+"email mungkin saja mengartikan ini sebagai tanda bahwa akun anda telah "
+"diretas atau terkompromikan dan mengkunci anda dari layanan. Satu-satunya "
+"cara untuk memecahkan masalah ini adalah dengan mematuhi prosedur yang "
+"direkomendasikan oleh situs yang dimaksud untuk menjalankan pemulihan akun "
+"atau menghubungi operator manusia dan menjelaskan situasi anda."
+
+#: managing-identities.page:101
+msgid "Changing identities and circuits"
+msgstr "Mengubah identitas dan sirkuit"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: managing-identities.page:103
+msgctxt "_"
+msgid ""
+"external ref='media/managing-identities/new_identity.png' "
+"md5='15b01e35fa83185d94b57bf0ccf09d76'"
+msgstr ""
+"external ref='media/managing-identities/new_identity.png' "
+"md5='15b01e35fa83185d94b57bf0ccf09d76'"
+
+#: managing-identities.page:105
+msgid ""
+"Tor Browser features “New Identity” and “New Tor Circuit for this Site” "
+"options, located in the Torbutton menu."
+msgstr ""
+"Pilihan fitur Tor Browser \"New Identity (Identitas Baru)\" dan \"New Tor "
+"Circuit for this Site (Sirkuit Tor Baru untuk situs ini)\" berada di menu "
+"Torbutton."
+
+#: managing-identities.page:111
+msgid "New Identity"
+msgstr "Identitas Baru"
+
+#: managing-identities.page:112
+msgid ""
+"This option is useful if you want to prevent your subsequent browser "
+"activity from being linkable to what you were doing before. Selecting it "
+"will close all your open tabs and windows, clear all private information "
+"such as cookies and browsing history, and use new Tor circuits for all "
+"connections. Tor Browser will warn you that all activity and downloads will "
+"be stopped, so take this into account before clicking “New Identity”."
+msgstr ""
+"Pilihan ini berguna jika Anda ingin mencegah aktivitas browser Anda agar "
+"tidak terhubung dengan apa yang Anda lakukan sebelumnya. Memilihnya akan "
+"menutup semua tab dan jendela yang terbuka, menghapus semua informasi "
+"pribadi seperti cookies dan riwayat penjelajahan, dan menggunakan sirkuit "
+"Tor baru untuk semua koneksi. Browser Tor akan memperingatkan Anda bahwa "
+"semua aktivitas dan unduhan akan dihentikan, jadi pertimbangkanlah ini "
+"sebelum mengklik \"New Identity\"."
+
+#: managing-identities.page:123
+msgid "New Tor Circuit for this Site"
+msgstr "Sirkuit Tor Baru untuk Situs ini"
+
+#: managing-identities.page:124
+msgid ""
+"This option is useful if the <link xref=\"about-tor-browser#how-tor-"
+"works\">exit relay</link> you are using is unable to connect to the website "
+"you require, or is not loading it properly. Selecting it will cause the "
+"currently-active tab or window to be reloaded over a new Tor circuit. Other "
+"open tabs and windows from the same website will use the new circuit as well"
+" once they are reloaded. This option does not clear any private information "
+"or unlink your activity, nor does it affect your current connections to "
+"other websites."
+msgstr ""
+"Pilihan ini berguna jika 1) exit relay 2) anda menggunakan saat tidak dapat"
+" terhubung dengan situs yang ada inginkan, atau tidak berjalan dengan baik. "
+"Memilih itu akan menyebabkan tab yang aktif saat ini atau jendela yang "
+"sedang berjalan melalui sebuah sirkuit Tor yang baru. Tabs lain yang sedang "
+"terbuka dan jendela dari website yang sama akan menggunakan sirkuit yang "
+"baru demikian juga dengan yang sedang dijalankan. Opsi ini tidak akan "
+"menghilangkan setiap infomasi pribadi atau tidak menghubungkan aktivitas "
+"anda, tidak juga berdampak pada koneksi anda saat ini pada website yang "
+"lain. "
+
+#: onionsites.page:6
+msgid "Services that are only accessible using Tor"
+msgstr "Layanan hanya bisa diakses menggunakan Tor"
+
+#: onionsites.page:10
+msgid "Onion Services"
+msgstr "Layanan Onion"
+
+#: onionsites.page:11
+msgid ""
+"Onion services (formerly known as “hidden services”) are services (like "
+"websites) that are only accessible through the Tor network."
+msgstr ""
+"Layanan Onion (sebelumnya diketahui sebagai \"hidden services (layanan "
+"tersembunyi)\" adalah layanan (seperti sebuah situs web) yang hanya bisa "
+"diakses melalui jaringan Tor"
+
+#: onionsites.page:16
+msgid ""
+"Onion services offer several advantages over ordinary services on the non-"
+"private web:"
+msgstr ""
+"Layanan Onion menawarkan beberapa keuntungan daripada layanan biasa pada "
+"situs web yang tidak privat."
+
+#: onionsites.page:23
+msgid ""
+"An onion services’s location and IP address are hidden, making it difficult "
+"for adversaries to censor it or identify its operators."
+msgstr ""
+"Lokasi dan alamat IP pada layanan onion tersembunyi, membuat penentang sulit"
+" untuk menyensor atau mengidentifikasi operator yang menjalankannya."
+
+#: onionsites.page:29
+msgid ""
+"All traffic between Tor users and onion services is end-to-end encrypted, so"
+" you do not need to worry about <link xref=\"secure-connections\">connecting"
+" over HTTPS</link>."
+msgstr ""
+"Semua lalu lintas antara pengguna Tor dan layanan onion terenkripsi dari "
+"ujung ke ujung, jadi anda tidak perlu khawatir untuk<link xref=\"secure-"
+"connections\">menghubungkan melalui HTTPS</link>"
+
+#: onionsites.page:36
+msgid ""
+"The address of an onion service is automatically generated, so the operators"
+" do not need to purchase a domain name; the .onion URL also helps Tor ensure"
+" that it is connecting to the right location and that the connection is not "
+"being tampered with."
+msgstr ""
+"Alamat dari layanan onion dihasilkan secara otomatis, oleh sebab itu "
+"operator tidak perlu membeli sebuah nama domain; URL .onion juga menjamin "
+"bahwa Tor terhubung ke lokasi yang tepat dan koneksinya tidak digelapkan."
+
+#: onionsites.page:46
+msgid "How to access an onion service"
+msgstr "Cara mengakses sebuah layanan onion"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: onionsites.page:48
+msgctxt "_"
+msgid ""
+"external ref='media/onionsites/onion_url.png' "
+"md5='f97f7fe10f07c3959c4430934974bbaa'"
+msgstr ""
+"external ref='media/onionsites/onion_url.png' "
+"md5='f97f7fe10f07c3959c4430934974bbaa'"
+
+#: onionsites.page:50
+msgid ""
+"Just like any other website, you will need to know the address of an onion "
+"service in order to connect to it. An onion address is a string of sixteen "
+"mostly random letters and numbers, followed by “.onion”."
+msgstr ""
+"Seperti situs web yang lain, anda perlu tahu alamat dari sebuah layanan "
+"onion untuk dapat terhubung. Sebuah alamat layanan onion berupa deretan enam"
+" belas huruf dan nomor acak, diakhiri dengan \".onion\"."
+
+#: onionsites.page:58 troubleshooting.page:10
+msgid "Troubleshooting"
+msgstr "Tawaran solusi"
+
+#: onionsites.page:59
+msgid ""
+"If you cannot reach the onion service you require, make sure that you have "
+"entered the 16-character onion address correctly: even a small mistake will "
+"stop Tor Browser from being able to reach the site."
+msgstr ""
+"Bila anda tidak dapat menjangkau layanan onion yang anda inginkan, pastikan "
+"anda sudah memasukkan 16 karakter alamat onion secara tepat: sebuah "
+"kesalahan kecil akan menghentikan Tor Browser menjangkau situs tersebut."
+
+#: onionsites.page:64
+msgid ""
+"If you are still unable to connect to the onion service, please try again "
+"later. There may be a temporary connection issue, or the site operators may "
+"have allowed it to go offline without warning."
+msgstr ""
+"Bila anda tetap tidak dapat terhubung ke layanan onion, mohon coba kembali. "
+"Mungkin ada persoalan koneksi, atau operator situs membuatnya \"offline\" "
+"tanpa peringatan."
+
+#: onionsites.page:69
+msgid ""
+"You can also ensure that you're able to access other onion services by "
+"connecting to <link href=\"http://3g2upl4pq6kufc4m.onion/\">DuckDuckGo's "
+"Onion Service</link>"
+msgstr ""
+"Anda juga bisa memastikan bahwa anda dapat mengakes layanan onion lain "
+"dengan tersambung ke <link "
+"href=\"http://3g2upl4pq6kufc4m.onion/\">DuckDuckGo's Onion Service</link>"
+
+#: plugins.page:6
+msgid "How Tor Browser handles add-ons, plugins and JavaScript"
+msgstr "Bagaimana Tor Browser memperlakukan add-ons, plugins dan JavaScript"
+
+#: plugins.page:10
+msgid "Plugins, add-ons and JavaScript"
+msgstr "Plugins, add-ons dan JavaScript"
+
+#: plugins.page:13
+msgid "Flash Player"
+msgstr "Flash Player"
+
+#: plugins.page:14
+msgid ""
+"Video websites, such as Vimeo make use of the Flash Player plugin to display"
+" video content. Unfortunately, this software operates independently of Tor "
+"Browser and cannot easily be made to obey Tor Browser’s proxy settings. It "
+"can therefore reveal your real location and IP address to the website "
+"operators, or to an outside observer. For this reason, Flash is disabled by "
+"default in Tor Browser, and enabling it is not recommended."
+msgstr ""
+"Situs web video, seperti Vimeo menggunakan plugin Flash Player untuk "
+"menampilkan konten video. Sayangnya, perangkat lunak ini beroperasi secara "
+"independen dari Tor Browser dan tidak dapat secara mudah untuk dibuat "
+"mentaati pengaturan proxy Tor Browser. Itu dapat menyingkap lokasi "
+"sebenarnya dan alamat IP anda kepada operator situs web, atau kepada "
+"pengamat dari luar. Untuk alasan ini, Flash dinonaktifkan secara bawaan di "
+"Tor Browser, dan tidak direkomendasikan untuk mengaktifkannya."
+
+#: plugins.page:23
+msgid ""
+"Some video websites (such as YouTube) offer alternative video delivery "
+"methods that do not use Flash. These methods may be compatible with Tor "
+"Browser."
+msgstr ""
+"Sejumlah situs video (misalnya Youtube) menawarkan metode pengiriman "
+"alternatif yang tidak menggunakan Flash. Metode ini mungkin cocok dengan Tor"
+" Browser."
+
+#: plugins.page:31
+msgid "JavaScript"
+msgstr "JavaScript"
+
+#: plugins.page:32
+msgid ""
+"JavaScript is a programming language that websites use to offer interactive "
+"elements such as video, animation, audio, and status timelines. "
+"Unfortunately, JavaScript can also enable attacks on the security of the "
+"browser, which might lead to deanonymization."
+msgstr ""
+"JavaScript merupakan bahasa pemograman yang digunakan peramban yang "
+"menawarkan elemen interaktif semisal video, animasi, audio, dan linemasa. "
+"Sayangnya, JavaScript juga memudahkan serangan keamanan terhadap peramban "
+"yang bisa mengarah pada hilangnya anonimitas."
+
+#: plugins.page:39
+msgid ""
+"Tor Browser includes an add-on called NoScript, accessed through the “S” "
+"icon at the top-left of the window, which allows you to control the "
+"JavaScript that runs on individual web pages, or to block it entirely."
+msgstr ""
+"Tor Browser memuat perangkat tambahan bernama NoScript, yang dapat diakses "
+"melalui ikon 'S' pada bagian kanan-atas jendela. Ini memperbolehkan anda "
+"untuk mengkontrol JavaScript pada satu halaman situs atau memblokir secara "
+"keseluruhan"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: plugins.page:45
+msgctxt "_"
+msgid ""
+"external ref='media/plugins/noscript_menu.png' "
+"md5='df9e684b76a3c2e2bdcb879a19c20471'"
+msgstr ""
+"external ref='media/plugins/noscript_menu.png' "
+"md5='df9e684b76a3c2e2bdcb879a19c20471'"
+
+#: plugins.page:47
+msgid ""
+"Users who require a high degree of security in their web browsing should set"
+" Tor Browser’s <link xref=\"security-slider\">Security Slider</link> to "
+"“Medium-High” (which disables JavaScript for non-HTTPS websites) or “High” "
+"(which does so for all websites). However, disabling JavaScript will prevent"
+" many websites from displaying correctly, so Tor Browser’s default setting "
+"is to allow all websites to run scripts."
+msgstr ""
+"Pengguna yang menginginkan tingkat keamanan yang tinggi pada situs "
+"jelajahnya sebaiknya mengatur Tor Browser: 1) slider pengamanan, 2) pada "
+"'Medium-High\" (yang menon-aktifkan JavaScript untuk situs non-HTTPS) atau "
+"\"High\" (yang melakukan hal seperti itu pada semua situs) Namun, "
+"menonaktifkan JavaScript akan menyebabkan banyak situs tidak muncul dengan "
+"betul, jadi pengaturan Tor Browser pada default adalah untuk memperbolehkan "
+"setiap situs untuk menjalankan skrip. "
+
+#: plugins.page:58
+msgid "Browser Add-ons"
+msgstr "Peraban Add-ons"
+
+#: plugins.page:59
+msgid ""
+"Tor Browser is based on Firefox, and any browser add-ons or themes that are "
+"compatible with Firefox can also be installed in Tor Browser."
+msgstr ""
+"Tor Browser berbasiskan pada Firefox, dan setiap add-ons atau tema peramban "
+"yang cocok dengan Firefox dapat dipasang pada Tor Browser."
+
+#: plugins.page:64
+msgid ""
+"However, the only add-ons that have been tested for use with Tor Browser are"
+" those included by default. Installing any other browser add-ons may break "
+"functionality in Tor Browser or cause more serious problems that affect your"
+" privacy and security. It is strongly discouraged to install additional add-"
+"ons, and the Tor Project will not offer support for these configurations."
+msgstr ""
+"Namun, hanya add-ons yang sudah diuji untuk digunakan dengan Tor Browser "
+"yang termasuk dalam bawaan. Memasang add-ons pada peramban lain bisa merusak"
+" fungsi dalam Tor Browser atau menyebabkan masalah lebih serius terhadap "
+"privasi dan keamanan anda. Sangat tidak dianjurkan untuk memasang add-ons "
+"tambahan, dan Tor Project tidak akan menawarkan bantuan untuk konfigurasi "
+"seperti ini."
+
+#: secure-connections.page:8
+msgid "Learn how to protect your data using Tor Browser and HTTPS"
+msgstr ""
+"Pelajari bagaimana mengamankan data anda memakai Tor Browser dan HTTPS"
+
+#: secure-connections.page:12
+msgid "Secure Connections"
+msgstr "Koneksi Aman"
+
+#: secure-connections.page:14
+msgid ""
+"If personal information such as a login password travels unencrypted over "
+"the Internet, it can very easily be intercepted by an eavesdropper. If you "
+"are logging into any website, you should make sure that the site offers "
+"HTTPS encryption, which protects against this kind of eavesdropping. You can"
+" verify this in the URL bar: if your connection is encrypted, the address "
+"will begin with “https://”, rather than “http://”."
+msgstr ""
+"Bila informasi personal seperti kata sandi dikirimkan ke internet tanpa "
+"enkripsi bisa dengan mudah disadap. Bila anda masuk ke sebuah situs web, "
+"anda harus memastikan apakah situs tersebut menawarkan enkripsi HTTPS, yang "
+"melindungi anda dari penyadapan seperti ini. Anda bisa memverifikasi ini di "
+"kolom URL: Bila koneksi anda terenkripsi, alamat situs tersebut diawali "
+"dengan \"https://, bukan \"http://\""
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: secure-connections.page:24
+msgctxt "_"
+msgid ""
+"external ref='media/secure-connections/https.png' "
+"md5='364bcbde7a649b0cea9ae178007c1a50'"
+msgstr ""
+"eksternal ref='media/secure-connections/https.png' "
+"md5='364bcbde7a649b0cea9ae178007c1a50'"
+
+#: secure-connections.page:26
+msgid ""
+"The following visualization shows what information is visible to "
+"eavesdroppers with and without Tor Browser and HTTPS encryption:"
+msgstr ""
+"Visualisasi berikut ini menunjukkan informasi apa yang bisa dilihat oleh "
+"penyusup dengan atau tanpa Tor Browser dan enskripsi HTTPS:"
+
+#: secure-connections.page:35
+msgid ""
+"Click the “Tor” button to see what data is visible to observers when you're "
+"using Tor. The button will turn green to indicate that Tor is on."
+msgstr ""
+"Click tombol \"Tor\" untuk melihat apakah data ditampilkan kepada pengamat "
+"ketika Anda menggunakan Tor. Tombol akan berubah menjadi hijau untuk "
+"menandakan Tor sedang aktif."
+
+#: secure-connections.page:42
+msgid ""
+"Click the “HTTPS” button to see what data is visible to observers when "
+"you're using HTTPS. The button will turn green to indicate that HTTPS is on."
+msgstr ""
+"Click tombol \"HTTPS\" untuk melihat apakah data ditampilkan kepada pengamat"
+" saat Anda menggunakan HTTPS, tombol akan berubah menjadi hijau untuk "
+"menandakan HTTPS sedang aktif."
+
+#: secure-connections.page:49
+msgid ""
+"When both buttons are green, you see the data that is visible to observers "
+"when you are using both tools."
+msgstr ""
+"Saat masing-masing tombol berwarna hijau, Anda dapat melihat data "
+"ditampilkan kepada orang yang mengamati ketika Anda tidak menggunakan salah "
+"satu perkakas."
+
+#: secure-connections.page:55
+msgid ""
+"When both buttons are grey, you see the data that is visible to observers "
+"when you don't use either tool."
+msgstr ""
+"Saat masing-masing tombol berwarna abu-abu, Anda dapat melihat data "
+"ditampilkan kepada orang yang mengamati ketika Anda tidak menggunakan salah "
+"satu perkakas."
+
+#: secure-connections.page:62
+msgid "Potentially visible data"
+msgstr "Data berpotensi ditampilkan."
+
+#: secure-connections.page:70
+msgid "The site being visited."
+msgstr "Situs telah dikunjungi."
+
+#: secure-connections.page:81
+msgid "Username and password used for authentication."
+msgstr "Nama pengguna dan kata sandi digunakan untuk autentifikasi."
+
+#: secure-connections.page:92
+msgid "Data being transmitted."
+msgstr "Data sudah dikirim."
+
+#: secure-connections.page:103
+msgid ""
+"Network location of the computer used to visit the website (the public IP "
+"address)."
+msgstr ""
+"Lokasi jaringan komputer yang digunakan untuk mengunjungi situs (IP alamat "
+"publik)."
+
+#: secure-connections.page:115
+msgid "Whether or not Tor is being used."
+msgstr "Apakah Tor sedang dipakai atau tidak."
+
+#: security-slider.page:6
+msgid "Configuring Tor Browser for security and usability"
+msgstr "Mengkonfigurasi Tor Browser untuk keamanan dan kegunaan."
+
+#: security-slider.page:10
+msgid "Security Slider"
+msgstr "Security Slider"
+
+#: security-slider.page:11
+msgid ""
+"Tor Browser includes a “Security Slider” that lets you increase your "
+"security by disabling certain web features that can be used to attack your "
+"security and anonymity. Increasing Tor Browser’s security level will stop "
+"some web pages from functioning properly, so you should weigh your security "
+"needs against the degree of usability you require."
+msgstr ""
+"Tor Browser termasuk \"Security Slider\" akan mengajak Anda untuk "
+"meningkatkan keamanan dengan me-nonaktif-kan fitur situs tertentu yang bisa "
+"digunakan untuk menyerang kemanan dan identitas Anda. Peningkatan keamanan "
+"Tor Browser akan menghentikan sejumlah fungsi dari halaman situs, jadi Anda "
+"harus menyesuaikan kebutuhan tingkat keamanan Anda."
+
+#: security-slider.page:21
+msgid "Accessing the Security Slider"
+msgstr "Mengakses Security Slider"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: security-slider.page:23
+msgctxt "_"
+msgid ""
+"external ref='media/security-slider/slider.png' "
+"md5='3c469cd3ed9f60ebb6bbbc63daa90082'"
+msgstr ""
+"eksternal ref='media/security-slider/slider.png' "
+"md5='3c469cd3ed9f60ebb6bbbc63daa90082'"
+
+#: security-slider.page:25
+msgid ""
+"The Security Slider is located in Torbutton’s “Privacy and Security "
+"Settings” menu."
+msgstr ""
+"Security Slider berada di menu Torbutton's \"Privacy and Security "
+"Settings\"."
+
+#: security-slider.page:32
+msgid "Security Levels"
+msgstr "Tingkat Keamanan"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: security-slider.page:34
+msgctxt "_"
+msgid ""
+"external ref='media/security-slider/slider_window.png' "
+"md5='c733bdccd1731ed1a772777b25bae7a1'"
+msgstr ""
+"eksternal ref='media/security-slider/slider_window.png' "
+"md5='c733bdccd1731ed1a772777b25bae7a1'"
+
+#: security-slider.page:36
+msgid ""
+"Increasing the level of the Security Slider will disable or partially "
+"disable certain browser features to protect against possible attacks."
+msgstr ""
+"Peningkatan level Security Slider akan di-nonaktif-kan atau sebagian di-"
+"nonaktif-kan khususnya fitur peramban untuk melindungi pelbagai kemungkinan "
+"serangan."
+
+#: security-slider.page:42
+msgid "High"
+msgstr "Tinggi"
+
+#: security-slider.page:43
+msgid ""
+"At this level, HTML5 video and audio media become click-to-play via "
+"NoScript; all JavaScript performance optimizations are disabled; some "
+"mathematical equations may not display properly; some font rendering "
+"features are disabled; some types of image are disabled; Javascript is "
+"disabled by default on all sites; most video and audio formats are disabled;"
+" and some fonts and icons may not display correctly."
+msgstr ""
+"Pada tingkat ini, media video dan audio HTML 5 menjadi klik-untuk- memainkan"
+" melalui NoScript; setiap optimalisasi tampilan JavaScript menjadi non-"
+"aktif; beberapa persamaan matematika kemungkinan tidak ditampilkan secara "
+"benar; beberapa fitur terjemahan huruf menjadi non-aktif; beberapa tipe "
+"dari gambar menjadi non-aktif; Javascript menjadi non-aktif secara otomatis"
+" pada seluruh situs; hampir semua video dan audio format menjadi non-aktif; "
+"dan beberapa huruf dan ikon kemungkinan tidak dapat ditampilkan secara tepat"
+" "
+
+#: security-slider.page:53
+msgid "Medium-High"
+msgstr "Menengah-Tinggi"
+
+#: security-slider.page:54
+msgid ""
+"At this level, HTML5 video and audio media become click-to-play via "
+"NoScript; all JavaScript performance optimizations are disabled; some "
+"mathematical equations may not display properly; some font rendering "
+"features are disabled; some types of image are disabled; and JavaScript is "
+"disabled by default on all non-<link xref=\"secure-"
+"connections\">HTTPS</link> sites."
+msgstr ""
+"Pada level ini, HTML5 media audio dan visual menjadi click-to-play lewat "
+"NoScript; semua optimalisasi kinerja JavaScript akan di-nonaktif-kan; "
+"beberapa formula matematika kemngkinan tidak ditampilkan secara baik; "
+"sejumlah perubahan fitur huruf di-nonaktif-kan; sejumlah jenis gambar di-"
+"nonaktif-kan; dan JavaScript di-nonaktif-kan secara otomatif pada semua "
+"non-<link xref=\"secure-connections\">HTTPS</link>sites"
+
+#: security-slider.page:64
+msgid "Medium-Low"
+msgstr "Menengah-Bawah"
+
+#: security-slider.page:65
+msgid ""
+"At this level, HTML5 video and audio media become click-to-play via "
+"NoScript; some <link xref=\"plugins\">JavaScript</link> performance "
+"optimizations are disabled, causing some websites to run more slowly; and "
+"some mathematical equations may not display properly."
+msgstr ""
+"Pada level ini, HTML5 media audio dan visual menjadi click-to-play lewat "
+"NoScript, beberapa <link xref=\"plugins\">JavaScript</link>Optimalisasi "
+"kinerja nonaktif, membuat sejumllah websites berjalan lambat; dan sejumlah "
+"formula matematika tidak akan ditampilkan dengan baik."
+
+#: security-slider.page:73
+msgid "Low"
+msgstr "Bawah"
+
+#: security-slider.page:74
+msgid ""
+"At this level, all browser features are enabled. This is the most usable "
+"option."
+msgstr ""
+"Pada level ini, semua fitur peramban dapat digunakan. Ini adalah pilihan "
+"yang paling berguna."
+
+#: transports.page:6 transports.page:20
+msgid "Types of pluggable transport"
+msgstr "Jenis-jenis pluggable transport"
+
+#: transports.page:10
+msgid "Pluggable Transports"
+msgstr "Pluggable Transports"
+
+#: transports.page:12
+msgid ""
+"Pluggable transports are tools that Tor can use to disguise the traffic it "
+"sends out. This can be useful in situations where an Internet Service "
+"Provider or other authority is actively blocking connections to the Tor "
+"network."
+msgstr ""
+"Pluggable transports adalah perkakas yang Tor bisa gunakan untuk menyamarkan"
+" lalu lintas ini untuk pengiriman keluar. Ini bisa berguna dalam situasi-"
+"situasi di mana penyedia layanan internet atau otoritas lain aktif memblokir"
+" koneksi ke jaringan Tor."
+
+#: transports.page:21
+msgid ""
+"Currently there are six pluggable transports available, but more are being "
+"developed."
+msgstr ""
+"Sekarang terdapat tiga pluggable transports dapat diakses, tapi lebih untuk "
+"pengembangan."
+
+#: transports.page:28
+msgid "obfs3"
+msgstr "obfs3"
+
+#: transports.page:33
+msgid ""
+"obfs3 makes Tor traffic look random, so that it does not look like Tor or "
+"any other protocol. obfs3 bridges will work in most places."
+msgstr ""
+"obfs3 membuat lalu lintas Tor tampak acak, jadi nantinya tidak akan tampak "
+"seperti Tor atau protokol lainnya. obfs3 bridges akan bekerja di banyak "
+"tempat."
+
+#: transports.page:42
+msgid "obfs4"
+msgstr "obfs4"
+
+#: transports.page:47
+msgid ""
+"obfs4 makes Tor traffic look random like obfs3, and also prevents censors "
+"from finding bridges by Internet scanning. obfs4 bridges are less likely to "
+"be blocked than obfs3 bridges."
+msgstr ""
+"obfs4 membuat lalu lintas Tor tampak acak seperti obfs3, dan juga mencegah "
+"sensor dari menemukan bridges oleh pemindaian internet. obfs4 bridges "
+"sedikit mirip dalam blokir dibandingkan obfs3 bridges."
+
+#: transports.page:56
+msgid "Scramblesuit"
+msgstr "Scramblesuit"
+
+#: transports.page:61
+msgid "ScrambleSuit is similar to obfs4 but has a different set of bridges."
+msgstr "ScrambleSuit mirip dengan obfs4 namun memiliki jembatan berbeda."
+
+#: transports.page:69
+msgid "FTE"
+msgstr "FTE"
+
+#: transports.page:74
+msgid ""
+"FTE (format-transforming encryption) disguises Tor traffic as ordinary web "
+"(HTTP) traffic."
+msgstr ""
+"FTE (format-transforming encryption) penyamaran lalu lintas Tor sebagai "
+"situs biasa (HTTP) lalu lintas."
+
+#: transports.page:82
+msgid "meek"
+msgstr "lunak"
+
+#: transports.page:87
+msgid ""
+"These transports all make it look like you are browsing a major web site "
+"instead of using Tor. meek-amazon makes it look like you are using Amazon "
+"Web Services; meek-azure makes it look like you are using a Microsoft web "
+"site; and meek-google makes it look like you are using Google search."
+msgstr ""
+"Mengangkut semua ini membuatnya terlihat seperti Anda menjelajah situs web "
+"utama daripada menggunakan Tor. Meek-amazon membuatnya terlihat seperti Anda"
+" menggunakan Amazon Web Services; Meek-azure membuatnya terlihat seperti "
+"Anda menggunakan situs web Microsoft; dan meek-google membuatnya terlihat "
+"seperti Anda menggunakan Google search. "
+
+#: troubleshooting.page:6
+msgid "What to do if Tor Browser doesn’t work"
+msgstr "Apa yang harus dilakukan ketika Tor Browser tidak bekerja"
+
+#: troubleshooting.page:12
+msgid ""
+"You should be able to start browsing the web using Tor Browser shortly after"
+" running the program, and clicking the “Connect” button if you are using it "
+"for the first time."
+msgstr ""
+"Anda sudah bisa mulai berselancar di internet menggunakan Tor Browser segera"
+" setelah menjalankan program dan menekan tombol \"Connect\" jika anda "
+"menggunakannya pertama kali."
+
+#: troubleshooting.page:21
+msgid "Quick fixes"
+msgstr "Perbaikan cepat"
+
+#: troubleshooting.page:22
+msgid ""
+"If Tor Browser doesn’t connect, there may be a simple solution. Try each of "
+"the following:"
+msgstr ""
+"Jika Tor Browser tidak terkoneksi, ada sejumlah solusi sederhana. Coba "
+"masing-masing di bawah ini:"
+
+#: troubleshooting.page:29
+msgid ""
+"Your computer’s system clock must be set correctly, or Tor will not be able "
+"to connect."
+msgstr ""
+"Sistem jam komputer Anda mesti diatur secara tepat, atau Tor tidak bisa "
+"terkoneksi."
+
+#: troubleshooting.page:35
+msgid ""
+"Make sure another Tor Browser is not already running. If you’re not sure if "
+"Tor Browser is running, restart your computer."
+msgstr ""
+"Pastikan Tor Browser lainnya tidak sedang berjalan. Jika tak yakin jika Tor "
+"Browser sedang berjalan, nyalakan ulang komputer Anda."
+
+#: troubleshooting.page:41
+msgid ""
+"Make sure that any antivirus program you have installed is not preventing "
+"Tor from running. You may need to consult the documentation for your "
+"antivirus software if you do not know how to do this."
+msgstr ""
+"Pastikan program antivirus yang telah terpasang tidak menghalangi jalannya "
+"Tor. Anda kemungkinan perlu memeriksa dokumentasi pada perangkat antivirus "
+"Anda jika tidak tahu mengenai hal ini."
+
+#: troubleshooting.page:49
+msgid "Temporarily disable your firewall."
+msgstr "Sementara men-nonaktif-kan firewall Anda."
+
+#: troubleshooting.page:54
+msgid ""
+"Delete Tor Browser and install it again. If updating, do not just overwrite "
+"your previous Tor Browser files; ensure they are fully deleted beforehand."
+msgstr ""
+"Hapus Tor Browser dan pasang lagi. Jika pembaruan berjalan, jangan hanya "
+"minmpa file Tor Browser anda sebelumnya; sebelumnya pastikan seluruhnya "
+"sudah dihapus."
+
+#: troubleshooting.page:64
+msgid "Is your connection censored?"
+msgstr "Apakah koneksi Anda disensor?"
+
+#: troubleshooting.page:65
+msgid ""
+"If you still can’t connect, your Internet Service Provider might be "
+"censoring connections to the Tor network. Read the <link "
+"xref=\"circumvention\">Circumvention</link> section for possible solutions."
+msgstr ""
+"Jika Anda masih tak bisa terkoneksi, ISP Anda kemungkinan menghalangi "
+"koneksi ke jaringan Tor, baca <link xref=\"circumvention\">Perdaya</link> "
+"bagian untuk peluang solusi."
+
+#: troubleshooting.page:74
+msgid "Known issues"
+msgstr "Persoalan yang telah diketahui"
+
+#: troubleshooting.page:75
+msgid ""
+"Tor Browser is under constant development, and some issues are known about "
+"but not yet fixed. Please check the <link xref=\"known-issues\">Known "
+"Issues</link> page to see if the problem you are experiencing is already "
+"listed there."
+msgstr ""
+"Tor Browser selalu berada di bawah pengembangan, dan sejumlah persoalan "
+"telah diketahui tapi tidak bisa diperbaiki. Harap periksa <link xref"
+"=\"known-issues\">persoalan yang sudah diketahui </link>halaman untuk "
+"melihat persoalanmu sudah masuk ke dalam daftar ini."
+
+#: uninstalling.page:6
+msgid "How to remove Tor Browser from your system"
+msgstr "Cara mencopot Tor Browser dari sistem Anda."
+
+#: uninstalling.page:10
+msgid "Uninstalling"
+msgstr "Pencopotan"
+
+#: uninstalling.page:12
+msgid ""
+"Tor Browser does not affect any of the existing software or settings on your"
+" computer. Uninstalling Tor Browser will not affect your system’s software "
+"or settings."
+msgstr ""
+"Tor Browser tidak mempengaruhi perangkat dan pengaturan di dalam komputer "
+"Anda. Pencopotan Tor Browser tidak akan berpengaruh terhadap sistem "
+"perangkat dan pengaturan."
+
+#: uninstalling.page:18
+msgid "Removing Tor Browser from your system is simple:"
+msgstr "Mencopot Tor Browser pada sistem Anda sangat mudah:"
+
+#: uninstalling.page:24
+msgid ""
+"Locate your Tor Browser folder. The default location on Windows is the "
+"Desktop; on Mac OS X it is the Applications folder. On Linux, there is no "
+"default location, however the folder will be named \"tor-browser_en-US\" if "
+"you are running the English Tor Browser."
+msgstr ""
+"Tempatkan Tor Browser folder. Lokasi foldernya biasanya untuk Windows berada"
+" di Desktop; sementara pada Mac OS X berada di Applications. Di Linux, tidak"
+" ada lokasi tertentu, tapi folder akan dinamakan \"tor-browser_en-US\" jika "
+"Anda menjalankan versi Inggris Tor Browser."
+
+#: uninstalling.page:32
+msgid "Delete the Tor Browser folder."
+msgstr "Hapus folder Tor Browser"
+
+#: uninstalling.page:35
+msgid "Empty your Trash"
+msgstr "Kosongkan tempat sampah"
+
+#: uninstalling.page:39
+msgid ""
+"Note that your operating system’s standard “Uninstall” utility is not used."
+msgstr ""
+"Perhatikan operating sistem anda standard \"Uninstall\" utilitas tidak "
+"digunakan"
+
+#: updating.page:6
+msgid "How to update Tor Browser"
+msgstr "Cara untuk memperbarui Tor Browser"
+
+#: updating.page:10
+msgid "Updating"
+msgstr "Pembaruan"
+
+#: updating.page:12
+msgid ""
+"Tor Browser must be kept updated at all times. If you continue to use an "
+"outdated version of the software, you may be vulnerable to serious security "
+"flaws that compromise your privacy and anonymity."
+msgstr ""
+"Tor Browser akan tetap menyimpan pembaruan selama mungkin. Jika Anda tetap "
+"melanjutkan menggunakan versi lama, maka kemanan privasi dan anonimitas Anda"
+" akan mudah diserang."
+
+#: updating.page:18
+msgid ""
+"Tor Browser will prompt you to update the software once a new version has "
+"been released: the Torbutton icon will display a yellow triangle, and you "
+"may see a written update indicator when Tor Browser opens. You can update "
+"either automatically or manually."
+msgstr ""
+"Tor Browser akan meminta Anda untuk memperbarui perangkat lunak untuk versi "
+"terakhir yang baru dikeluarkan: ikon Torbutton akan menampilkan segitiga "
+"kuning, dan anda akan melihat tulisan indikator pembaruan ketika Tor Browser"
+" terbuka. Anda dapat memperbaruinya secara otomatis atau manual."
+
+#: updating.page:26
+msgid "Updating Tor Browser automatically"
+msgstr "Pembaruan Tor Browser secara otomatis"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: updating.page:30
+msgctxt "_"
+msgid ""
+"external ref='media/updating/update1.png' "
+"md5='9ff01eb653d92124746fc31efde2bf07'"
+msgstr ""
+"eksternal ref='media/updating/update1.png' "
+"md5='9ff01eb653d92124746fc31efde2bf07'"
+
+#: updating.page:32
+msgid ""
+"When you are prompted to update Tor Browser, click on the Torbutton icon, "
+"then select “Check for Tor Browser Update”."
+msgstr ""
+"Ketika Anda diminta untuk memperbarui Tor Browser, click ikon Torbutton, "
+"kemudian pilih \"Check for Tor Browser Update\""
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: updating.page:39
+msgctxt "_"
+msgid ""
+"external ref='media/updating/update3.png' "
+"md5='4bd08622b0cacf20b13f75c432176ed3'"
+msgstr ""
+"eksternal ref='media/updating/update3.png' "
+"md5='4bd08622b0cacf20b13f75c432176ed3'"
+
+#: updating.page:41
+msgid ""
+"When Tor Browser has finished checking for updates, click on the “Update” "
+"button."
+msgstr "Saat Tor Browser telah selesai untuk pembaruan, click tombol \"Update\"."
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: updating.page:48
+msgctxt "_"
+msgid ""
+"external ref='media/updating/update4.png' "
+"md5='1d795e7b695738531db9d4b2b0fb5313'"
+msgstr ""
+"eksternal ref='media/updating/update4.png' "
+"md5='1d795e7b695738531db9d4b2b0fb5313'"
+
+#: updating.page:50
+msgid ""
+"Wait for the update to download and install, then restart Tor Browser. You "
+"will now be running the latest version."
+msgstr ""
+"Tunggu pembaruan untuk mengunduh dan pemasangan, lalu hidupkan kembali Tor "
+"Browser. Setelah itu, Anda akan menjalankan versi terbaru."
+
+#: updating.page:58
+msgid "Updating Tor Browser manually"
+msgstr "Perbarui Tor Browser secara manual"
+
+#: updating.page:61
+msgid ""
+"When you are prompted to update Tor Browser, finish the browsing session and"
+" close the program."
+msgstr ""
+"Ketika Anda diminta untuk memperbarui Tor Brower, selesaikan dulu aktivitas "
+"berselancar dan tutup program ini"
+
+#: updating.page:67
+msgid ""
+"Remove Tor Browser from your system by deleting the folder that contains it "
+"(see the <link xref=\"uninstalling\">Uninstalling</link> section for more "
+"information)."
+msgstr ""
+"Copot Tor Browser dari sistem Anda dengan cara menghapus folder yang berisi "
+"file terkait (lihat <link xref=\"uninstalling\">copot perangkat</link>bagian"
+" untuk informasi lanjut)."
+
+#: updating.page:74
+msgid ""
+"Visit <link href=\"https://www.torproject.org/projects/torbrowser.html.en\">"
+" https://www.torproject.org/projects/torbrowser.html.en</link> and download "
+"a copy of the latest Tor Browser release, then install it as before."
+msgstr ""
+"Kunjungi <link "
+"href=\"https://www.torproject.org/projects/torbrowser.html.en\">https://www.torproject.org/projects/torbrowser.html.en</link>dan"
+" unduh sebuah salinan dari versi terakhir Tor Browser, lalu pasang "
+"sebelumnya."
1
0
commit 3bb8030aff964840645c4729373b6f745a530307
Author: Colin Childs <colin(a)torproject.org>
Date: Tue Sep 18 14:16:47 2018 -0500
Adding bn_BD translations
---
Makefile.am | 2 +-
bn_BD/bn_BD.po | 1790 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 1791 insertions(+), 1 deletion(-)
diff --git a/Makefile.am b/Makefile.am
index eb78a9d..3fd3409 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -8,7 +8,7 @@ TOR_AND_HTTPS = ../tor-and-https
HELP_ID = tor-browser-user-manual
HELP_FILES = $(shell cd $(srcdir)/C && git ls-files '*.page')
HELP_MEDIA = $(shell cd $(srcdir)/C && git ls-files 'media')
-HELP_LINGUAS = en-US ja sv ga @TOR_BROWSER_BUNDLE_LOCALES@
+HELP_LINGUAS = en-US ja sv ga bn_BD @TOR_BROWSER_BUNDLE_LOCALES@
.PHONY: html
html: all media-symlinks.stamp
diff --git a/bn_BD/bn_BD.po b/bn_BD/bn_BD.po
new file mode 100644
index 0000000..90df5c4
--- /dev/null
+++ b/bn_BD/bn_BD.po
@@ -0,0 +1,1790 @@
+# Translators:
+# Al Shahrior Hasan Sagor <shahrior3814(a)gmail.com>, 2017
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"POT-Creation-Date: 2016-12-06 16:36-0600\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Al Shahrior Hasan Sagor <shahrior3814(a)gmail.com>, 2017\n"
+"Language-Team: Bengali (Bangladesh) (https://www.transifex.com/otf/teams/1519/bn_BD/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: bn_BD\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#. Put one translator per line, in the form NAME <EMAIL>, YEAR1, YEAR2
+msgctxt "_"
+msgid "translator-credits"
+msgstr "àŠ
àŠšà§àŠ¬àŠŸàŠŠàŠ-àŠà§àаà§àŠ¡àŠ¿àŠ"
+
+#: about-tor-browser.page:7
+msgid "Learn what Tor Browser can do to protect your privacy and anonymity"
+msgstr ""
+"àŠàŠªàŠšàŠŸàŠ° àŠà§àŠªàŠšà§àŠ¯àŠŒàŠ€àŠŸ àŠàŠ¬àŠ àŠà§àŠªàŠšà§àŠ¯àŠŒàŠ€àŠŸàŠ° àŠžà§àаàŠà§àŠ·àŠŸàŠ° àŠàŠšà§àН àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ° àŠàŠ¿ àŠàŠ°àŠ€à§ àŠªàŠŸàŠ°à§ àŠ€àŠŸ "
+"àŠàŠŸàŠšà§àŠš"
+
+#: about-tor-browser.page:10
+msgid "About Tor Browser"
+msgstr "àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ° àŠžàŠ®à§àŠªàŠ°à§àŠà§"
+
+#: about-tor-browser.page:12
+msgid ""
+"Tor Browser uses the Tor network to protect your privacy and anonymity. "
+"Using the Tor network has two main properties:"
+msgstr ""
+"àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ° àŠàŠªàŠšàŠŸàŠ° àŠà§àŠªàŠšà§àŠ¯àŠŒàŠ€àŠŸ àŠàŠ¬àŠ àŠà§àŠªàŠšà§àŠ¯àŠŒàŠ€àŠŸ àŠ°àŠà§àŠ·àŠŸ àŠàŠ°àŠŸàŠ° àŠàŠšà§àН àŠàа àŠšà§àŠàŠàŠ¯àŠŒàŠŸàŠ°à§àŠ "
+"àŠ¬à§àŠ¯àŠ¬àŠ¹àŠŸàŠ° àŠàаà§à¥€ àŠàа àŠšà§àŠàŠàŠ¯àŠŒàŠŸàŠ°à§àŠ àŠ¬à§àŠ¯àŠ¬àŠ¹àŠŸàŠ° àŠàŠ°à§ àŠŠà§àŠàŠ¿ àŠªà§àŠ°àŠ§àŠŸàŠš àŠ¬à§àŠ¶àŠ¿àŠ·à§àŠà§àН àŠ°àŠ¯àŠŒà§àŠà§:"
+
+#: about-tor-browser.page:18
+msgid ""
+"Your internet service provider, and anyone watching your connection locally,"
+" will not be able to track your internet activity, including the names and "
+"addresses of the websites you visit."
+msgstr ""
+"àŠàŠªàŠšàŠŸàŠ° àŠàŠšà§àŠàŠŸàŠ°àŠšà§àŠ àŠªàŠ°àŠ¿àŠ·à§àŠ¬àŠŸ àŠªà§àŠ°àŠŠàŠŸàŠšàŠàŠŸàŠ°à§, àŠàŠ¬àŠ àŠžà§àŠ¥àŠŸàŠšà§àŠ¯àŠŒàŠàŠŸàŠ¬à§ àŠàŠªàŠšàŠŸàŠ° àŠžàŠàНà§àŠ àŠŠà§àŠà§ àŠà§àŠ, "
+"àŠàŠªàŠšàŠŸàŠ° àŠàŠ¯àŠŒà§àЬ àŠžàŠŸàŠàŠà§àа àŠšàŠŸàŠ® àŠàŠ¬àŠ àŠ àŠ¿àŠàŠŸàŠšàŠŸ àŠžàŠ¹ àŠàŠªàŠšàŠŸàŠ° àŠàŠšà§àŠàŠŸàŠ°àŠšà§àŠ àŠàŠŸàŠ°à§àНàŠàŠ²àŠŸàŠª àŠà§àаà§àŠ¯àŠŸàŠ àŠàŠ°àŠ€à§ "
+"àŠžàŠà§àŠ·àŠ® àŠ¹àŠ¬à§ àŠšàŠŸà¥€"
+
+#: about-tor-browser.page:25
+msgid ""
+"The operators of the websites and services that you use, and anyone watching"
+" them, will see a connection coming from the Tor network instead of your "
+"real Internet (IP) address, and will not know who you are unless you "
+"explicitly identify yourself."
+msgstr ""
+"àŠàŠªàŠšàŠ¿ àŠ¬à§àŠ¯àŠ¬àŠ¹àŠŸàŠ° àŠàаà§àŠš àŠàŠ®àŠš àŠàŠ¯àŠŒà§àŠ¬àŠžàŠŸàŠàŠ àŠàŠ¬àŠ àŠªàŠ°àŠ¿àŠ·à§àŠ¬àŠŸàŠà§àŠ²àŠ¿àŠ° àŠ
àŠªàŠŸàŠ°à§àŠàа àŠàŠ¬àŠ àŠ¯à§ àŠà§àŠ àŠ€àŠŸàŠŠà§àаàŠà§ "
+"àŠŠà§àŠàŠà§àŠš, àŠàŠªàŠšàŠŸàŠ° àŠàŠžàŠ² àŠàŠšà§àŠàŠŸàŠ°àŠšà§àŠ (àŠàŠàŠªàŠ¿) àŠ àŠ¿àŠàŠŸàŠšàŠŸàŠ° àŠªàŠ°àŠ¿àŠ¬àŠ°à§àŠ€à§ àŠàа àŠšà§àŠàŠàŠ¯àŠŒàŠŸàŠ°à§àŠà§ àŠàŠžàŠà§ àŠàŠàŠàŠ¿"
+" àŠžàŠàНà§àŠ àŠŠà§àŠàŠ€à§ àŠªàŠŸàŠ¬à§àŠš àŠàŠ¬àŠ àŠ¯àŠŠàŠ¿ àŠàŠªàŠšàŠ¿ àŠžà§àŠªàŠ·à§àŠàŠàŠŸàŠ¬à§ àŠšàŠ¿àŠà§àŠà§ àŠàŠ¿àŠ¹à§àŠšàŠ¿àŠ€ àŠšàŠŸ àŠàаà§àŠš àŠ€àŠ¬à§ àŠàŠªàŠšàŠ¿ "
+"àŠà§ àŠàŠŸàŠšà§àŠš àŠšàŠŸà¥€"
+
+#: about-tor-browser.page:34
+msgid ""
+"In addition, Tor Browser is designed to prevent websites from "
+"âfingerprintingâ or identifying you based on your browser configuration."
+msgstr ""
+"àŠàŠªàŠ°àŠšà§àŠ€à§, àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ° \"àŠ«àŠ¿àŠà§àŠàŠŸàŠ°àŠªà§àŠ°àŠ¿àŠšà§àŠàŠ¿àŠ\" àŠ¥à§àŠà§ àŠàŠ¯àŠŒà§àŠ¬àŠžàŠŸàŠàŠàŠà§àŠ²àŠ¿àŠà§ àŠªà§àŠ°àŠ€àŠ¿àŠ°à§àЧ àŠàŠ°àŠ€à§"
+" àŠ¬àŠŸ àŠàŠªàŠšàŠŸàŠ° àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ° àŠàŠšàŠ«àŠ¿àŠàŠŸàŠ°à§àŠ¶àŠšà§àа àŠàŠªàŠ° àŠàŠ¿àŠ€à§àŠ€àŠ¿ àŠàŠ°à§ àŠàŠªàŠšàŠŸàŠà§ àŠžàŠšàŠŸàŠà§àŠ€ àŠàŠ°àŠŸàŠ° àŠàŠšà§àН "
+"àŠ¡àŠ¿àŠàŠŸàŠàŠš àŠàŠ°àŠŸ àŠ¹àŠ¯àŠŒà§àŠà§à¥€"
+
+#: about-tor-browser.page:39
+msgid ""
+"By default, Tor Browser does not keep any browsing history. Cookies are only"
+" valid for a single session (until Tor Browser is exited or a <link xref"
+"=\"managing-identities#new-identity\">New Identity</link> is requested)."
+msgstr ""
+"àŠ¡àŠ¿àŠ«àŠ²à§àŠàаà§àŠªà§, àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ° àŠà§àŠšàŠ àŠ¬à§àŠ°àŠŸàŠàŠàŠ¿àŠ àŠàŠ€àŠ¿àŠ¹àŠŸàŠž àŠ°àŠŸàŠà§ àŠšàŠŸ àŠà§àŠàŠ¿àŠ àŠàŠàŠ àŠžà§àŠ¶àŠšà§àа àŠàŠšà§àН "
+"àŠ¶à§àЧà§àŠ®àŠŸàŠ€à§àа àŠ¬à§àЧ (àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ° àŠ¥à§àŠà§ àŠªà§àŠ°àŠžà§àŠ¥àŠŸàŠš àŠàŠ°àŠŸ àŠ¹àŠ¯àŠŒ àŠ¬àŠŸ àŠàŠàŠàŠ¿ <link xref"
+"=\"managing-identities#new-identity\">àŠšàŠ€à§àŠš àŠªàŠ°àŠ¿àŠàŠ¯àŠŒ</link> àŠ
àŠšà§àаà§àЧ àŠàŠ°àŠŸ àŠ¹àŠ¯àŠŒ) "
+"àŠªàŠ°à§àŠ¯àŠšà§àŠ€ àŠ¬à§àŠ§à¥€"
+
+#: about-tor-browser.page:50
+msgid "How Tor works"
+msgstr "àŠàŠ¿àŠàŠŸàŠ¬à§ àŠàа àŠàŠŸàŠ àŠàаà§"
+
+#: about-tor-browser.page:52
+msgid ""
+"Tor is a network of virtual tunnels that allows you to improve your privacy "
+"and security on the Internet. Tor works by sending your traffic through "
+"three random servers (also known as <em>relays</em>) in the Tor network. The"
+" last relay in the circuit (the âexit relayâ) then sends the traffic out "
+"onto the public Internet."
+msgstr ""
+"àŠàа àŠàŠŸàŠ°à§àŠà§àŠ¯àŠŒàŠŸàŠ² àŠàŠŸàŠšà§àвàŠà§àŠ²àŠ¿àŠ° àŠàŠàŠàŠ¿ àŠšà§àŠàŠàŠ¯àŠŒàŠŸàŠ°à§àŠ àŠ¯àŠŸ àŠàŠªàŠšàŠŸàŠà§ àŠàŠšà§àŠàŠŸàŠ°àŠšà§àŠà§ àŠàŠªàŠšàŠŸàŠ° "
+"àŠà§àŠªàŠšà§àŠ¯àŠŒàŠ€àŠŸ àŠ àŠšàŠ¿àŠ°àŠŸàŠªàŠ€à§àŠ€àŠŸ àŠàŠšà§àŠšàŠ€ àŠàŠ°àŠ€à§ àŠžàŠ¹àŠŸàŠ¯àŠŒàŠ€àŠŸ àŠàаà§à¥€ àŠàа àŠàа àŠšà§àŠàŠàŠ¯àŠŒàŠŸàŠ°à§àŠà§ àŠ€àŠ¿àŠšàŠàŠ¿ "
+"àŠ°à§àŠ¯àŠŸàŠšà§àŠ¡àŠ® àŠžàŠŸàŠ°à§àŠàŠŸàŠ° (àŠ°àŠ¿àŠ²à§ àŠšàŠŸàŠ®à§àŠ àŠªàŠ°àŠ¿àŠàŠ¿àŠ€) àŠàа àŠ®àŠŸàŠ§à§àŠ¯àŠ®à§ àŠàŠªàŠšàŠŸàŠ° àŠà§àаà§àŠ¯àŠŸàŠ«àŠ¿àŠ àŠªàŠŸàŠ àŠ¿àŠ¯àŠŒà§ àŠàŠŸàŠ "
+"àŠàаà§à¥€ àŠžàŠŸàŠ°à§àŠàŠ¿àŠà§àа àŠžàŠ°à§àŠ¬àŠ¶à§àŠ· <em>àŠ°àŠ¿àŠ²à§</em> (\"àŠªà§àŠ°àŠžà§àŠ¥àŠŸàŠš àŠ°àŠ¿àŠ²à§\") àŠ€àŠŸàŠ°àŠªàŠ° àŠªàŠŸàŠ¬àŠ²àŠ¿àŠ "
+"àŠàŠšà§àŠàŠŸàŠ°àŠšà§àŠà§ àŠà§àаà§àŠ¯àŠŸàŠ«àŠ¿àŠ àŠªàŠŸàŠ àŠŸàŠ¯àŠŒà¥€"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: about-tor-browser.page:59
+msgctxt "_"
+msgid ""
+"external ref='media/how-tor-works.png' "
+"md5='6fe4151a88b7a518466f0582e40ccc8c'"
+msgstr ""
+"àŠ¬àŠŸàŠ¹à§àŠ¯àŠ¿àŠ àŠ°à§àŠ«='media/how-tor-works.png' md5='6fe4151a88b7a518466f0582e40ccc8c'"
+
+#: about-tor-browser.page:60
+msgid ""
+"The image above illustrates a user browsing to different websites over Tor. "
+"The green middle computers represent relays in the Tor network, while the "
+"three keys represent the layers of encryption between the user and each "
+"relay."
+msgstr ""
+"àŠàŠªàŠ°à§àŠà§àŠ€ àŠàŠ¿àŠ€à§àаàŠàŠ¿ àŠàаàŠà§ àŠ¬àŠ¿àŠàŠ¿àŠšà§àŠš àŠàŠ¯àŠŒà§àŠ¬àŠžàŠŸàŠàŠàŠà§àŠ²àŠ¿àŠ€à§ àŠ¬à§àŠ¯àŠ¬àŠ¹àŠŸàŠ°àŠàŠŸàŠ°à§ àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ°àŠà§ àŠàŠ¿àŠ€à§àŠ°àŠ¿àŠ€ "
+"àŠàаà§à¥€ àŠžàŠ¬à§àŠ àŠ®àŠŸàŠàŠŸàŠ°àŠ¿ àŠàŠ®à§àŠªàŠ¿àŠàŠàŠŸàŠ° àŠàа àŠšà§àŠàŠàŠ¯àŠŒàŠŸàŠ°à§àŠàŠà§àŠ²àŠ¿àŠ€à§ àŠ°àŠ¿àŠ²à§àŠž àŠàŠªàŠžà§àŠ¥àŠŸàŠªàŠš àŠàаà§, àŠ¯àŠàŠš àŠ€àŠ¿àŠšàŠàŠ¿"
+" àŠà§ àŠ¬à§àŠ¯àŠ¬àŠ¹àŠŸàŠ°àŠàŠŸàŠ°à§àа àŠ®àŠ§à§àŠ¯à§ àŠàŠšàŠà§àŠ°àŠ¿àŠªàŠ¶àŠš àŠžà§àŠ€àŠ° àŠàŠ¬àŠ àŠªà§àŠ°àŠ€àŠ¿àŠàŠ¿ àŠ°àŠ¿àŠ²à§ àŠªà§àŠ°àŠ€àŠ¿àŠšàŠ¿àŠ§àŠ¿àŠ€à§àЬ àŠàаà§à¥€"
+
+#: bridges.page:6
+msgid "Learn what bridges are and how to get them"
+msgstr "àŠàŠ¿ àŠ¬à§àŠ°àŠ¿àŠ àŠàŠà§ àŠàŠ¬àŠ àŠàŠ¿àŠàŠŸàŠ¬à§ àŠ€àŠŸàŠŠà§àа àŠªà§àŠ€à§ àŠ¶àŠ¿àŠàŠ€à§"
+
+#: bridges.page:10
+msgid "Bridges"
+msgstr "àŠ¬à§àŠ°àŠ¿àŠ"
+
+#: bridges.page:12
+msgid ""
+"Most <link xref=\"transports\">Pluggable Transports</link>, such as obfs3 "
+"and obfs4, rely on the use of âbridgeâ relays. Like ordinary Tor relays, "
+"bridges are run by volunteers; unlike ordinary relays, however, they are not"
+" listed publicly, so an adversary cannot identify them easily. Using bridges"
+" in combination with pluggable transports helps to disguise the fact that "
+"you are using Tor."
+msgstr ""
+"àŠžàŠ°à§àŠ¬àŠŸàŠ§àŠ¿àŠ <link xref=\"transports\">àŠªà§àвà§àŠ¯àŠŸàŠà§àŠ¬àŠ² àŠà§àŠ°àŠŸàŠšà§àŠžàŠªà§àаà§àŠ</link>\n"
+", àŠ¯à§àŠ®àŠš obfs3 àŠàŠ¬àŠ obfs4 àŠ¹àŠ¿àŠžàŠŸàŠ¬à§, \"àŠ¬à§àŠ°àŠ¿àŠ\" relays àŠ¬à§àŠ¯àŠ¬àŠ¹àŠŸàŠ°à§àа àŠàŠªàŠ° àŠšàŠ¿àŠ°à§àŠàа àŠàаà§à¥€ àŠžàŠŸàŠ§àŠŸàŠ°àŠ£ àŠàа àŠ°àŠ¿àŠ²à§àŠž àŠ®àŠ€, àŠžà§àŠ€à§ àŠžà§àЬà§àŠà§àŠàŠŸàŠžà§àЬàŠàŠŠà§àа àŠŠà§àŠ¬àŠŸàŠ°àŠŸ àŠàŠŸàŠ²àŠŸàŠšà§ àŠ¹àŠ¯àŠŒ; àŠžàŠŸàŠ§àŠŸàŠ°àŠ£ àŠ°àŠ¿àŠ²à§àŠž àŠ¬à§àŠ¯àŠ€à§àŠ€, àŠ€àŠ¬à§, àŠ€àŠŸàŠ°àŠŸ àŠžàŠ°à§àЬàŠàŠšà§àŠš àŠ€àŠŸàŠ²àŠ¿àŠàŠŸàŠà§àŠà§àŠ€ àŠšàŠŸ àŠ¹àŠ¯àŠŒ, àŠ€àŠŸàŠ àŠàŠàŠàŠ¿ àŠªà§àŠ°àŠ€àŠ¿àŠªàŠà§àŠ· àŠ€àŠŸàŠŠà§àа àŠžàŠ¹àŠà§àŠ àŠžàŠšàŠŸàŠà§àŠ€ àŠàŠ°àŠ€à§ àŠªàŠŸàŠ°à§ àŠšàŠŸà¥€ àŠªà§àвà§àŠ¯àŠŸàŠà§àŠ¬àŠ² àŠà§àŠ°àŠŸàŠšà§àŠžàŠ«àŠ°à§àŠ®à§àа àŠžàŠŸàŠ¥à§ àŠ®àŠ¿àŠ²àŠ¿àŠ€ àŠ¬à§àŠ°àŠ¿àŠ àŠ¬à§àŠ¯àŠ¬àŠ¹àŠŸàŠ° àŠàŠ°à§ àŠàŠªàŠšàŠ¿ àŠàа àŠ¬à§àŠ¯àŠ¬àŠ¹àŠŸàŠ° àŠàаàŠà§àŠš àŠ€àŠŸ àŠàŠŠà§àŠ®àŠ¬à§àŠ¶à§ àŠžàŠŸàŠ¹àŠŸàŠ¯à§àН àŠàаà§à¥€"
+
+#: bridges.page:21
+msgid ""
+"Other pluggable transports, like meek, use different anti-censorship "
+"techniques that do not rely on bridges. You do not need to obtain bridge "
+"addresses in order to use these transports."
+msgstr ""
+"àŠ
àŠšà§àŠ¯àŠŸàŠšà§àН àŠªà§àвà§àŠ¯àŠŸàŠà§àŠ¬àŠ² àŠà§àŠ°àŠŸàŠšà§àŠžàŠ«àŠ°à§àŠ®àŠà§àŠ²àŠ¿, àŠ¯à§àŠ®àŠš àŠ¬àŠ¿àŠšàŠ¯àŠŒà§, àŠ¬àŠ¿àŠàŠ¿àŠšà§àŠš àŠ¬àŠ¿àŠ°à§àŠ§à§ àŠžà§àŠšà§àŠžàŠ°àŠ¶àŠ¿àŠª "
+"àŠà§àŠ¶àŠ²àŠà§àŠ²àŠ¿ àŠ¬à§àŠ¯àŠ¬àŠ¹àŠŸàŠ° àŠàŠ°à§ àŠ¯àŠŸ àŠžà§àŠ€à§àŠà§àŠ²àŠ¿àŠ€à§ àŠšàŠ¿àŠ°à§àŠàа àŠàŠ°à§ àŠšàŠŸà¥€ àŠàŠ àŠà§àŠ°àŠŸàŠšà§àŠžàŠªà§àаà§àŠàŠà§àŠ²àŠ¿ "
+"àŠ¬à§àŠ¯àŠ¬àŠ¹àŠŸàŠ° àŠàŠ°àŠŸàŠ° àŠàŠšà§àН àŠàŠªàŠšàŠŸàŠà§ àŠ¬à§àŠ°àŠ¿àŠà§àа àŠ àŠ¿àŠàŠŸàŠšàŠŸàŠà§àŠ²àŠ¿ àŠªà§àŠ€à§ àŠ¹àŠ¬à§ àŠšàŠŸà¥€"
+
+#: bridges.page:28
+msgid "Getting bridge addresses"
+msgstr "àŠ¬à§àŠ°àŠ¿àŠà§àа àŠ àŠ¿àŠàŠŸàŠšàŠŸàŠà§àŠ²àŠ¿ àŠªàŠŸàŠàŠ¯àŠŒàŠŸ"
+
+#: bridges.page:29
+msgid ""
+"Because bridge addresses are not public, you will need to request them "
+"yourself. You have two options:"
+msgstr ""
+"àŠ¯à§àйà§àŠ€à§ àŠ¬à§àŠ°àŠ¿àŠàŠà§àŠ²àŠ¿ àŠ àŠ¿àŠàŠŸàŠšàŠŸàŠà§àŠ²àŠ¿ àŠžàŠ°à§àЬàŠàŠšà§àŠš àŠšàŠ¯àŠŒ àŠ€àŠŸàŠ àŠàŠªàŠšàŠŸàŠà§ àŠ€àŠŸàŠŠà§àа àŠšàŠ¿àŠà§àа àŠàŠŸàŠà§ àŠ
àŠšà§àаà§àЧ "
+"àŠàŠ°àŠ€à§ àŠ¹àŠ¬à§à¥€ àŠàŠªàŠšàŠŸàŠ° àŠŠà§àŠàŠ¿ àŠ¬àŠ¿àŠàвà§àŠª àŠàŠà§:"
+
+#: bridges.page:36
+msgid ""
+"Visit <link "
+"href=\"https://bridges.torproject.org/\">https://bridges.torproject.org/</link>"
+" and follow the instructions, or"
+msgstr ""
+"<link "
+"href=\"https://bridges.torproject.org/\">Https://bridges.torproject.org/</link>"
+" àŠŠà§àŠà§àŠš àŠàŠ¬àŠ àŠšàŠ¿àŠ°à§àŠŠà§àŠ¶àŠŸàŠ¬àŠ²à§ àŠ
àŠšà§àŠžàŠ°àŠ£ àŠàаà§àŠš, àŠ
àŠ¥àŠ¬àŠŸ"
+
+#: bridges.page:42
+msgid ""
+"Email bridges(a)torproject.org from a Gmail, Yahoo, or Riseup email address, "
+"or"
+msgstr ""
+"àŠàŠ®à§àŠàв, bridges(a)torproject.org àŠàŠàŠàŠ¿ àŠàŠ¿àŠ®à§àŠàв, àŠàŠ¯àŠŒàŠŸàŠ¹à§, àŠ¬àŠŸ àŠ°àŠ¿àŠ¯àŠŒà§àŠª àŠàŠ®à§àв àŠ àŠ¿àŠàŠŸàŠšàŠŸ, àŠ¬àŠŸ"
+
+#: bridges.page:51
+msgid "Entering bridge addresses"
+msgstr "àŠ¬à§àŠ°àŠ¿àŠ àŠ àŠ¿àŠàŠŸàŠšàŠŸàŠà§àŠ²àŠ¿ àŠªà§àŠ°àŠ¬à§àж àŠàŠ°àŠŸàŠšà§"
+
+#: bridges.page:52
+msgid ""
+"Once you have obtained some bridge addresses, you will need to enter them "
+"into Tor Launcher."
+msgstr ""
+"àŠàŠàŠ¬àŠŸàŠ° àŠàŠªàŠšàŠ¿ àŠàŠ¿àŠà§ àŠ¬à§àŠ°àŠ¿àŠ àŠ àŠ¿àŠàŠŸàŠšàŠŸ àŠªà§àŠ°àŠŸàŠªà§àŠ€ àŠàŠ°àŠŸ àŠ¹àŠ¯àŠŒà§àŠà§, àŠàŠªàŠšàŠ¿ àŠàа àŠ²àŠà§àŠàŠŸàŠ° àŠ®àŠ§à§àŠ¯à§ àŠ€àŠŸàŠŠà§àа "
+"àŠªà§àŠ°àŠ¬à§àж àŠàŠ°àŠ€à§ àŠ¹àŠ¬à§à¥€"
+
+#: bridges.page:57
+msgid ""
+"Choose âyesâ when asked if your Internet Service Provider blocks connections"
+" to the Tor network. Select âUse custom bridgesâ and enter each bridge "
+"address on a separate line."
+msgstr ""
+"àŠàŠªàŠšàŠŸàŠ° àŠàŠšà§àŠàŠŸàŠ°àŠšà§àŠ àŠªàŠ°àŠ¿àŠ·à§àŠ¬àŠŸ àŠžàŠ°àŠ¬àŠ°àŠŸàŠ¹àŠàŠŸàŠ°à§ àŠàа àŠšà§àŠàŠàŠ¯àŠŒàŠŸàŠ°à§àŠ àŠžàŠàНà§àŠ àŠ¬àŠšà§àЧ àŠàŠ°à§ àŠàŠ¿àŠà§àŠàŠŸàŠžàŠŸ àŠàŠ°àŠŸ"
+" àŠ¹àŠ²à§ \"àŠ¹à§àŠ¯àŠŸàŠ\" àŠàŠ¯àŠŒàŠš àŠàаà§àŠšà¥€ \"àŠàŠŸàŠžà§àŠàŠ® àŠ¬à§àŠ°àŠ¿àŠàŠà§àŠ²àŠ¿ àŠ¬à§àŠ¯àŠ¬àŠ¹àŠŸàŠ° àŠàаà§àŠš\" àŠšàŠ¿àŠ°à§àŠ¬àŠŸàŠàŠš àŠàаà§àŠš "
+"àŠàŠ¬àŠ àŠàŠàŠàŠ¿ àŠªà§àŠ¥àŠ àŠ²àŠŸàŠàŠšà§àа àŠªà§àŠ°àŠ€àŠ¿àŠàŠ¿ àŠžà§àŠ€à§ àŠ àŠ¿àŠàŠŸàŠšàŠŸàŠàŠ¿ àŠ²àŠ¿àŠà§àŠšà¥€"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: bridges.page:63
+msgctxt "_"
+msgid ""
+"external ref='media/tor-launcher-custom-bridges_en-US.png' "
+"md5='93365c2aa3fb4d627497e83f28a39b7e'"
+msgstr ""
+"àŠ¬àŠŸàŠ¹à§àŠ¯àŠ¿àŠ àŠ°à§àŠ«='media/tor-launcher-custom-bridges_en-US.png' "
+"md5='93365c2aa3fb4d627497e83f28a39b7e'"
+
+#: bridges.page:65
+msgid ""
+"Click âConnectâ. Using bridges may slow down the connection compared to "
+"using ordinary Tor relays. If the connection fails, the bridges you received"
+" may be down. Please use one of the above methods to obtain more bridge "
+"addresses, and try again."
+msgstr ""
+"\"àŠžàŠàНà§àŠ\" àŠà§àŠ²àŠ¿àŠ àŠàаà§àŠš àŠžàŠŸàŠ§àŠŸàŠ°àŠ£ àŠàа àŠ°àŠ¿àŠ²à§ àŠ¬à§àŠ¯àŠ¬àŠ¹àŠŸàŠ° àŠàŠ°àŠŸàŠ° àŠžàŠŸàŠ¥à§ àŠ€à§àŠ²àŠšàŠŸàŠ¯àŠŒ àŠ¬à§àŠ°àŠ¿àŠàŠà§àŠ²àŠ¿ "
+"àŠžàŠàНà§àŠ àŠ¬àŠšà§àЧ àŠàŠ°à§ àŠŠàŠ¿àŠ€à§ àŠªàŠŸàŠ°à§à¥€ àŠžàŠàНà§àŠ àŠ¬à§àŠ¯àŠ°à§àŠ¥ àŠ¹àŠ²à§, àŠàŠªàŠšàŠ¿ àŠ¯à§ àŠ¬à§àŠ°àŠ¿àŠàŠà§àŠ²àŠ¿ àŠªà§àŠ¯àŠŒà§àŠà§àŠš àŠ€àŠŸ "
+"àŠšàŠ¿àŠà§ àŠ¹àŠ€à§ àŠªàŠŸàŠ°à§à¥€ àŠàŠ°àŠ àŠžà§àŠ€à§ àŠ àŠ¿àŠàŠŸàŠšàŠŸ àŠªà§àŠ°àŠŸàŠªà§àŠ€ àŠàŠ°àŠŸàŠ° àŠàŠšà§àН àŠàŠªàŠ°à§àа àŠªàŠŠà§àŠ§àŠ€àŠ¿àŠà§àŠ²àŠ¿àŠ° àŠàŠàŠàŠ¿ "
+"àŠ¬à§àŠ¯àŠ¬àŠ¹àŠŸàŠ° àŠàаà§àŠš, àŠàŠ¬àŠ àŠàŠ¬àŠŸàŠ° àŠà§àŠ·à§àŠàŠŸ àŠàаà§àŠšà¥€"
+
+#: circumvention.page:6
+msgid "What to do if the Tor network is blocked"
+msgstr "àŠàŠ°à§ àŠšà§àŠàŠàŠ¯àŠŒàŠŸàŠ°à§àŠ àŠ
àŠ¬àŠ°à§àЧ àŠàŠ°àŠ²à§ àŠàŠ¿ àŠàŠ°àŠ¬à§àŠš?"
+
+#: circumvention.page:10
+msgid "Circumvention"
+msgstr "àŠªà§àŠ°àŠ€àŠŸàŠ°àŠ£àŠŸ"
+
+#: circumvention.page:12
+msgid ""
+"Direct access to the Tor network may sometimes be blocked by your Internet "
+"Service Provider or by a government. Tor Browser includes some circumvention"
+" tools for getting around these blocks. These tools are called âpluggable "
+"transportsâ. See the <link xref=\"transports\">Pluggable Transports</link> "
+"page for more information on the types of transport that are currently "
+"available."
+msgstr ""
+"àŠàа àŠšà§àŠàŠàŠ¯àŠŒàŠŸàŠ°à§àŠà§ àŠžàŠ°àŠŸàŠžàŠ°àŠ¿ àŠ
à§àŠ¯àŠŸàŠà§àŠžà§àŠžàŠàŠ¿ àŠàŠàŠšàŠ àŠàŠàŠšàŠ àŠàŠªàŠšàŠŸàŠ° àŠàŠšà§àŠàŠŸàŠ°àŠšà§àŠ àŠžàŠŸàŠ°à§àŠàŠ¿àŠž "
+"àŠªà§àаà§àŠàŠŸàŠàŠ¡àŠŸàŠ° àŠ¬àŠŸ àŠžàŠ°àŠàŠŸàŠ° àŠàаà§àŠ€à§àŠ àŠ
àŠ¬àŠ°à§àŠŠà§àЧ àŠ¥àŠŸàŠà§à¥€ àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ° àŠàŠ àŠ¬à§àŠ²àŠ àŠàŠŸàŠàŠŸàŠàŠŸàŠàŠ¿ àŠªà§àŠ€à§ "
+"àŠàŠšà§àН àŠàŠ¿àŠà§ circumvention àŠžàŠ°àŠà§àŠàŠŸàŠ® àŠ
àŠšà§àŠ€àŠ°à§àŠà§àŠà§àŠ€à¥€ àŠàŠ àŠžàŠ°àŠà§àŠàŠŸàŠ®àŠà§àŠ²àŠ¿ <link "
+"xref=\"transports\">\"àŠªà§àŠ²àŠŸàŠàНà§àŠà§àН àŠà§àŠ°àŠŸàŠšà§àŠžàŠªà§àаà§àŠàŠà§àŠ²àŠ¿\"</link> àŠ¬àŠ²àŠŸ àŠ¹àŠ¯àŠŒà¥€ àŠ¬àŠ°à§àŠ€àŠ®àŠŸàŠšà§"
+" àŠàŠªàŠ²àŠ¬à§àЧ àŠ¯à§ àŠ§àŠ°àŠšà§àа àŠ§àŠ°àŠšà§àа àŠàŠªàŠ° àŠàŠ°à§ àŠ€àŠ¥à§àНà§àа àŠàŠšà§àН àŠªà§àвà§àŠ¯àŠŸàŠà§àŠ¬àŠ² àŠà§àŠ°àŠŸàŠšà§àŠžàŠ«àŠ°à§àŠ® àŠªà§àŠ·à§àŠ àŠŸ "
+"àŠŠà§àŠà§àŠš"
+
+#: circumvention.page:22
+msgid "Using pluggable transports"
+msgstr "àŠªà§àвà§àŠ¯àŠŸàŠà§àŠ¬àŠ² àŠà§àŠ°àŠŸàŠšà§àŠžàŠªà§àаà§àŠàŠà§àŠ²àŠ¿ àŠ¬à§àŠ¯àŠ¬àŠ¹àŠŸàŠ° àŠàаà§àŠš"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: circumvention.page:26 first-time.page:35
+msgctxt "_"
+msgid ""
+"external ref='media/circumvention/configure.png' "
+"md5='519d888303eadfe4cb03f178aedd90f5'"
+msgstr ""
+"àŠ¬àŠŸàŠ¹à§àŠ¯àŠ¿àŠ àŠ°à§àŠ«='media/circumvention/configure.png' "
+"md5='519d888303eadfe4cb03f178aedd90f5'"
+
+#: circumvention.page:28
+msgid ""
+"To use pluggable transports, click \"Configure\" in the Tor Launcher window "
+"that appears when you first run Tor Browser."
+msgstr ""
+"àŠªà§àвà§àŠ¯àŠŸàŠà§àŠ¬àŠ² àŠà§àŠ°àŠŸàŠšà§àŠžàŠ«àŠ°à§àŠ® àŠ¬à§àŠ¯àŠ¬àŠ¹àŠŸàŠ° àŠàŠ°àŠŸàŠ° àŠàŠšà§àН, àŠàа àŠ²àŠà§àŠàŠŸàŠ° àŠàŠàŠšà§àŠ¡à§àŠ€à§ \"àŠàŠšàŠ«àŠ¿àŠàŠŸàŠ° "
+"àŠàаà§àŠš\" àŠà§àŠ²àŠ¿àŠ àŠàаà§àŠš àŠ¯àŠŸ àŠàŠªàŠšàŠ¿ àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ°àŠàŠ¿ àŠªà§àŠ°àŠ¥àŠ® àŠàŠŸàŠ²àŠŸàŠšà§àа àŠªàŠ°à§ àŠŠà§àŠà§àŠšà¥€"
+
+#: circumvention.page:33
+msgid ""
+"You can also configure pluggable transports while Tor Browser is running, by"
+" clicking on the green onion near your address bar and selecting âTor "
+"Network Settingsâ."
+msgstr ""
+"àŠàŠªàŠšàŠŸàŠ° àŠ
à§àŠ¯àŠŸàŠ¡à§àаà§àŠž àŠ¬àŠŸàŠ°à§àа àŠªàŠŸàŠ¶à§ àŠžàŠ¬à§àŠ onion àŠ àŠà§àŠ²àŠ¿àŠ àŠàŠ°à§ àŠàŠ¬àŠ \"àŠàа àŠšà§àŠàŠàŠ¯àŠŒàŠŸàŠ°à§àŠ "
+"àŠžà§àŠàŠ¿àŠàŠž\" àŠšàŠ¿àŠ°à§àŠ¬àŠŸàŠàŠš àŠàŠ°à§ àŠàŠªàŠšàŠ¿ àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ° àŠàŠŸàŠ²àŠšàŠŸ àŠàŠ°àŠ²à§ àŠªà§àвà§àŠ¯àŠŸàŠà§àŠ¬àŠ² àŠà§àŠ°àŠŸàŠšà§àŠžàŠ«àŠ°à§àŠ®àŠà§àŠ²àŠ¿"
+" àŠàŠšàŠ«àŠ¿àŠàŠŸàŠ° àŠàŠ°àŠ€à§ àŠªàŠŸàŠ°àŠ¬à§àŠšà¥€"
+
+#: circumvention.page:41
+msgid ""
+"Select âyesâ when asked if your Internet Service Provider blocks connections"
+" to the Tor network."
+msgstr ""
+"àŠàŠªàŠšàŠŸàŠ° àŠàŠšà§àŠàŠŸàŠ°àŠšà§àŠ àŠªàŠ°àŠ¿àŠ·à§àŠ¬àŠŸ àŠžàŠ°àŠ¬àŠ°àŠŸàŠ¹àŠàŠŸàŠ°à§ àŠàа àŠšà§àŠàŠàŠ¯àŠŒàŠŸàŠ°à§àŠ àŠžàŠàНà§àŠ àŠ¬àŠšà§àЧ àŠàŠ°à§ àŠàŠ¿àŠà§àŠàŠŸàŠžàŠŸ àŠàŠ°àŠŸ"
+" àŠ¹àŠ²à§ \"àŠ¹à§àŠ¯àŠŸàŠ\" àŠšàŠ¿àŠ°à§àŠ¬àŠŸàŠàŠš àŠàаà§àŠšà¥€"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: circumvention.page:49
+msgctxt "_"
+msgid ""
+"external ref='media/circumvention/bridges.png' "
+"md5='910cdd5e45860b81a1ad4739c589a195'"
+msgstr ""
+"àŠ¬àŠŸàŠ¹à§àŠ¯àŠ¿àŠ àŠ°à§àŠ«='media/circumvention/bridges.png' "
+"md5='910cdd5e45860b81a1ad4739c589a195'"
+
+#: circumvention.page:51
+msgid ""
+"Select âConnect with provided bridgesâ. Tor Browser currently has six "
+"pluggable transport options to choose from."
+msgstr ""
+"\"àŠžàŠ°àŠ¬àŠ°àŠŸàŠ¹àŠà§àŠ€ àŠ¬à§àŠ°àŠ¿àŠàŠà§àŠ²àŠ¿àŠ° àŠžàŠŸàŠ¥à§ àŠžàŠàНà§àŠ àŠàаà§àŠš\" àŠšàŠ¿àŠ°à§àŠ¬àŠŸàŠàŠš àŠàаà§àŠš àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ° àŠ¬àŠ°à§àŠ€àŠ®àŠŸàŠšà§ "
+"àŠ¥à§àŠà§ àŠšàŠ¿àŠ°à§àŠ¬àŠŸàŠàŠš àŠàŠ°àŠ€à§ àŠàŠ¯àŠŒ àŠªà§àвà§àŠ¯àŠŸàŠà§àŠ¬àŠ² àŠªàŠ°àŠ¿àŠ¬àŠ¹àŠš àŠ¬àŠ¿àŠàвà§àŠª àŠàŠà§"
+
+#: circumvention.page:60
+msgid "Which transport should I use?"
+msgstr "àŠà§àŠš àŠªàŠ°àŠ¿àŠ¬àŠ¹àŠš àŠàŠ®àŠ¿ àŠ¬à§àŠ¯àŠ¬àŠ¹àŠŸàŠ° àŠàŠ°àŠŸ àŠàŠàŠ¿àŠ€?"
+
+#: circumvention.page:61
+msgid ""
+"Each of the transports listed in Tor Launcherâs menu works in a different "
+"way (for more details, see the <link xref=\"transports\">Pluggable "
+"Transports</link> page), and their effectiveness depends on your individual "
+"circumstances."
+msgstr ""
+"àŠàа àŠ²àŠà§àŠàŠŸàŠ°à§àа àŠ®à§àŠšà§àŠ€à§ àŠ€àŠŸàŠ²àŠ¿àŠàŠŸàŠà§àŠà§àŠ€ àŠªà§àŠ°àŠ€àŠ¿àŠàŠ¿ àŠà§àŠ°àŠŸàŠšà§àŠžàŠ²à§ àŠàŠàŠàŠ¿ àŠàŠ¿àŠšà§àŠš àŠàŠªàŠŸàŠ¯àŠŒà§ àŠàŠŸàŠ àŠàŠ°à§ "
+"(àŠàŠ°à§ àŠ¬àŠ¿àŠ¶àŠŠ àŠ¬àŠ¿àŠ¬àŠ°àŠ£à§àа àŠàŠšà§àН, <link xref=\"transports\">àŠªà§àвà§àŠ¯àŠŸàŠà§àŠ¬àŠ² "
+"àŠà§àŠ°àŠŸàŠšà§àŠžàŠ«àŠ°à§àŠ®</link> àŠªà§àŠ·à§àŠ àŠŸàŠàŠ¿ àŠŠà§àŠà§àŠš), àŠàŠ¬àŠ àŠ€àŠŸàŠŠà§àа àŠàŠŸàŠ°à§àНàŠàŠŸàŠ°àŠ¿àŠ€àŠŸ àŠàŠªàŠšàŠŸàŠ° àŠ¬à§àНàŠà§àŠ€àŠ¿àŠàŠ€ "
+"àŠªàŠ°àŠ¿àŠžà§àŠ¥àŠ¿àŠ€àŠ¿àŠ° àŠàŠªàŠ° àŠšàŠ¿àŠ°à§àŠàа àŠàаà§à¥€"
+
+#: circumvention.page:67
+msgid ""
+"If you are trying to circumvent a blocked connection for the first time, you"
+" should try the different transports: obfs3, obfs4, ScrambleSuit, fte, meek-"
+"azure, meek-amazon."
+msgstr ""
+"àŠ¯àŠŠàŠ¿ àŠàŠªàŠšàŠ¿ àŠªà§àŠ°àŠ¥àŠ®àŠ¬àŠŸàŠ°à§àа àŠàŠšà§àН àŠàŠàŠàŠ¿ àŠ¬à§àŠ²àŠ àŠàŠ°àŠŸ àŠžàŠàНà§àŠàŠà§ àŠà§àŠ£àŠŸ àŠàŠ°àŠŸàŠ° àŠà§àŠ·à§àŠàŠŸ àŠàаàŠà§àŠš, àŠ€àŠŸàŠ¹àŠ²à§"
+" àŠàŠªàŠšàŠŸàŠà§ àŠ¬àŠ¿àŠàŠ¿àŠšà§àŠš àŠà§àŠ°àŠŸàŠšà§àŠžàŠªà§àаà§àŠà§àа àŠà§àŠ·à§àŠàŠŸ àŠàŠ°àŠ€à§ àŠ¹àŠ¬à§: obfs3, obfs4, ScrambleSuit, "
+"fte, meek-azure, meek-amazonी"
+
+#: circumvention.page:72
+msgid ""
+"If you try all of these options, and none of them gets you online, you will "
+"need to enter bridge addresses manually. Read the <link "
+"xref=\"bridges\">Bridges</link> section to learn what bridges are and how to"
+" obtain them."
+msgstr ""
+"àŠàŠªàŠšàŠ¿ àŠ¯àŠŠàŠ¿ àŠàŠ àŠžàŠ®àŠžà§àŠ€ àŠ¬àŠ¿àŠàвà§àŠªàŠà§àŠ²àŠ¿ àŠ¬à§àŠ¯àŠ¬àŠ¹àŠŸàŠ° àŠàаà§àŠš, àŠàŠ¬àŠ àŠ€àŠŸàŠŠà§àа àŠà§àŠàŠ àŠàŠªàŠšàŠŸàŠà§ àŠ
àŠšàŠ²àŠŸàŠàŠšà§ àŠšàŠŸ "
+"àŠªàŠŸàŠš, àŠ€àŠ¬à§ àŠàŠªàŠšàŠŸàŠà§ àŠ®à§àŠ¯àŠŸàŠšà§àŠ¯àŠŒàŠŸàŠ²àŠ¿ àŠ¬à§àŠ°àŠ¿àŠà§àа àŠ àŠ¿àŠàŠŸàŠšàŠŸàŠà§àŠ²àŠ¿ àŠªà§àŠ°àŠ¬à§àж àŠàŠ°àŠ€à§ àŠ¹àŠ¬à§à¥€ àŠ¬à§àŠ°àŠ¿àŠàŠà§àŠ²àŠ¿ "
+"àŠà§àŠàŠŸàŠ¬à§ àŠ¶àŠ¿àŠàŠà§ àŠàŠ¬àŠ àŠàŠ¿àŠàŠŸàŠ¬à§ àŠžà§àŠà§àŠ²àŠ¿ àŠªà§àŠ€à§ àŠ¹àŠ¯àŠŒ àŠ€àŠŸ àŠ¶àŠ¿àŠàŠ€à§ <link "
+"xref=\"bridges\">àŠ¬à§àŠ°àŠ¿àŠà§àŠž</link> àŠ¬àŠ¿àŠàŠŸàŠàŠàŠ¿ àŠªàŠ¡àŠŒà§àŠšà¥€"
+
+#: downloading.page:7
+msgid "How to download Tor Browser"
+msgstr "àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ° àŠ¡àŠŸàŠàŠšàŠ²à§àŠ¡ àŠàŠ¿àŠàŠŸàŠ¬à§?"
+
+#: downloading.page:10
+msgid "Downloading"
+msgstr "àŠ¡àŠŸàŠàŠšàŠ²à§àŠ¡ àŠ¹àŠà§àŠà§"
+
+#: downloading.page:12
+msgid ""
+"The safest and simplest way to download Tor Browser is from the official Tor"
+" Project website at https://www.torproject.org. Your connection to the site "
+"will be secured using <link xref=\"secure-connections\">HTTPS</link>, which "
+"makes it much harder for somebody to tamper with."
+msgstr ""
+"àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ° àŠ¡àŠŸàŠàŠšàŠ²à§àŠ¡ àŠàŠ°àŠŸàŠ° àŠžàŠ¬àŠà§àŠ¯àŠŒà§ àŠšàŠ¿àŠ°àŠŸàŠªàŠŠ àŠàŠ¬àŠ àŠžàŠ¹àŠ àŠàŠªàŠŸàŠ¯àŠŒàŠàŠ¿ àŠ¹àŠ² "
+"https://www.torproject.org àŠ àŠ
àŠ«àŠ¿àŠžàŠ¿àŠ¯àŠŒàŠŸàŠ² àŠàа àŠªà§àаàŠàвà§àŠª àŠàŠ¯àŠŒà§àŠ¬àŠžàŠŸàŠàŠ àŠ¥à§àŠà§à¥€ àŠžàŠŸàŠàŠàŠàŠ¿àŠ€à§ "
+"àŠàŠªàŠšàŠŸàŠ° àŠžàŠàНà§àŠàŠàŠ¿ HTTPS àŠ¬à§àŠ¯àŠ¬àŠ¹àŠŸàŠ° àŠàŠ°à§ àŠžà§àаàŠà§àŠ·àŠ¿àŠ€ àŠ¥àŠŸàŠàЬà§, àŠ¯àŠŸàŠ° àŠžàŠŸàŠ¹àŠŸàŠ¯à§àŠ¯à§ àŠàŠŸàŠàŠà§ àŠàŠŸàŠàŠà§ "
+"àŠàŠ¿àŠàŠ¡àŠŒà§ àŠ«à§àŠ²àŠŸ àŠ¹àŠ¬à§à¥€"
+
+#: downloading.page:19
+msgid ""
+"However, there may be times when you cannot access the Tor Project website: "
+"for example, it could be blocked on your network. If this happens, you can "
+"use one of the alternative download methods listed below."
+msgstr ""
+"àŠ¯àŠŸàŠàйà§àŠ, àŠàŠ®àŠš àŠžàŠ®àŠ¯àŠŒ àŠ¹àŠ€à§ àŠªàŠŸàŠ°à§ àŠ¯àŠàŠš àŠàŠªàŠšàŠ¿ àŠàа àŠªà§àаàŠàвà§àŠª àŠàŠ¯àŠŒà§àŠ¬àŠžàŠŸàŠàŠ àŠ
à§àŠ¯àŠŸàŠà§àŠžà§àŠž àŠàŠ°àŠ€à§ "
+"àŠªàŠŸàŠ°àŠ¬à§àŠš àŠšàŠŸ: àŠàŠŠàŠŸàŠ¹àŠ°àŠ£àŠžà§àŠ¬àŠ°à§àŠª, àŠàŠàŠ¿ àŠàŠªàŠšàŠŸàŠ° àŠšà§àŠàŠàŠ¯àŠŒàŠŸàŠ°à§àŠà§ àŠ¬à§àŠ²àŠ àŠàŠ°àŠŸ àŠ¯à§àŠ€à§ àŠªàŠŸàŠ°à§à¥€ àŠ¯àŠŠàŠ¿ àŠàŠàŠ¿ "
+"àŠàŠà§, àŠàŠªàŠšàŠ¿ àŠšà§àŠà§ àŠ€àŠŸàŠ²àŠ¿àŠàŠŸàŠà§àŠà§àŠ€ àŠ¬àŠ¿àŠàвà§àŠª àŠ¡àŠŸàŠàŠšàŠ²à§àŠ¡ àŠªàŠŠà§àŠ§àŠ€àŠ¿àŠà§àŠ²àŠ¿àŠ° àŠ®àŠ§à§àŠ¯à§ àŠàŠàŠàŠ¿ àŠ¬à§àŠ¯àŠ¬àŠ¹àŠŸàŠ° "
+"àŠàŠ°àŠ€à§ àŠªàŠŸàŠ°à§àŠšà¥€"
+
+#: downloading.page:27
+msgid "GetTor"
+msgstr "GetTor"
+
+#: downloading.page:28
+msgid ""
+"GetTor is a service that automatically responds to messages with links to "
+"the latest version of Tor Browser, hosted at a variety of locations, such as"
+" Dropbox, Google Drive and Github.."
+msgstr ""
+"GetTor àŠ¹àŠ² àŠàŠàŠàŠ¿ àŠªàŠ°àŠ¿àŠ·à§àŠ¬àŠŸ àŠ¯àŠŸ àŠžà§àŠ¬àŠ¯àŠŒàŠàŠà§àŠ°àŠ¿àŠ¯àŠŒàŠàŠŸàŠ¬à§ àŠ¬àŠ¿àŠàŠ¿àŠšà§àŠš àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ°à§àа àŠ¡à§àŠ°àŠªàŠ¬àŠà§àŠž, "
+"Google àŠ¡à§àŠ°àŠŸàŠàŠ àŠàŠ¬àŠ Github àŠ¹àŠ¿àŠžàŠŸàŠ¬à§ àŠ¹à§àŠžà§àŠà§àа àŠžàŠ°à§àŠ¬àŠ¶à§àŠ· àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ°à§àа àŠàŠ°à§ àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ°à§àа "
+"àŠ²àŠ¿àŠà§àŠàŠà§àŠ²àŠ¿àŠ° àŠžàŠŸàŠ¥à§ àŠ¬àŠŸàŠ°à§àŠ€àŠŸàŠà§àŠ²àŠ¿àŠ€à§ àŠªà§àŠ°àŠ€àŠ¿àŠà§àŠ°àŠ¿àŠ¯àŠŒàŠŸ àŠŠà§àŠ¯àŠŒà¥€"
+
+#: downloading.page:34
+msgid "To use GetTor via email:"
+msgstr "àŠàŠ®à§àвà§àа àŠ®àŠŸàŠ§à§àŠ¯àŠ®à§ GetTor àŠ¬à§àŠ¯àŠ¬àŠ¹àŠŸàŠ° àŠàŠ°àŠ€à§:"
+
+#: downloading.page:39
+msgid ""
+"Send an email to gettor(a)torproject.org, and in the body of the message "
+"simply write âwindowsâ, âosxâ, or âlinuxâ, (without quotation marks) "
+"depending on your operating system."
+msgstr ""
+"Gettor(a)torproject.org- àŠ àŠàŠàŠàŠ¿ àŠàŠ®à§àв àŠªàŠŸàŠ àŠŸàŠš, àŠàŠ¬àŠ àŠ¬àŠŸàŠ°à§àŠ€àŠŸàŠàŠ¿ àŠàŠªàŠšàŠŸàŠ° àŠ
àŠªàŠŸàŠ°à§àŠàŠ¿àŠ "
+"àŠžàŠ¿àŠžà§àŠà§àŠ®à§àа àŠàŠªàŠ° àŠšàŠ¿àŠ°à§àŠàа àŠàŠ°à§ àŠ¶à§àŠ§à§ \"àŠàŠàŠšà§àŠ¡à§àŠ\", \"àŠàŠàŠžàŠàŠà§àŠž\", àŠ¬àŠŸ \"àŠ²àŠ¿àŠšàŠŸàŠà§àŠž\" "
+"(àŠàŠŠà§àЧà§àŠ€àŠ¿ àŠàŠ¿àŠ¹à§àŠš àŠàŠŸàŠ¡àŠŒàŠŸàŠ) àŠ²àŠ¿àŠà§àŠšà¥€"
+
+#: downloading.page:46
+msgid ""
+"GetTor will respond with an email containing links from which you can "
+"download the Tor Browser package, the cryptographic signature (needed for "
+"verifying the download), the fingerprint of the key used to make the "
+"signature, and the packageâs checksum. You may be offered a choice of "
+"â32-bitâ or â64-bitâ software: this depends on the model of the computer you"
+" are using."
+msgstr ""
+"GetTor àŠàŠàŠàŠ¿ àŠàŠ®à§àв àŠ§àŠŸàŠ°àŠ£àŠàŠŸàŠ°à§ àŠ²àŠ¿àŠà§àŠà§ àŠžàŠŸàŠ¡àŠŒàŠŸ àŠŠà§àŠ¬à§ àŠ¯àŠŸàŠ° àŠ¥à§àŠà§ àŠàŠªàŠšàŠ¿ àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ° "
+"àŠªà§àŠ¯àŠŸàŠà§àŠ àŠ¡àŠŸàŠàŠšàŠ²à§àŠ¡ àŠàŠ°àŠ€à§ àŠªàŠŸàŠ°à§àŠš, àŠà§àŠ°àŠ¿àŠªà§àŠà§àŠà§àŠ°àŠŸàŠ«àŠ¿àŠ àŠžà§àŠ¬àŠŸàŠà§àŠ·àŠ° (àŠ¡àŠŸàŠàŠšàŠ²à§àŠ¡ àŠ¯àŠŸàŠàŠŸàŠ àŠàŠ°àŠŸàŠ° "
+"àŠàŠšà§àН àŠªà§àŠ°àŠ¯àŠŒà§àŠàŠšà§àŠ¯àŠŒ), àŠžà§àŠ¬àŠŸàŠà§àŠ·àŠ° àŠàŠ°àŠŸàŠ° àŠàŠšà§àН àŠ¬à§àŠ¯àŠ¬àŠ¹à§àŠ€ àŠà§àŠàŠ¿àŠ° àŠàŠà§àŠà§àвà§àа àŠàŠŸàŠª àŠàŠ¬àŠ "
+"àŠªà§àŠ¯àŠŸàŠà§àŠà§àа àŠà§àŠàŠžàŠŸàŠ®à¥€ àŠàŠªàŠšàŠ¿ \"32-àŠ¬àŠ¿àŠ\" àŠ¬àŠŸ \"64-àŠ¬àŠ¿àŠ\" àŠžàŠ«à§àŠàŠàŠ¯àŠŒà§àŠ¯àŠŸàŠ° àŠàŠ¯àŠŒàŠš àŠàŠ°àŠ€à§ àŠªàŠŸàŠ°à§àŠš:"
+" àŠàŠàŠ¿ àŠàŠªàŠšàŠŸàŠ° àŠ¬à§àŠ¯àŠ¬àŠ¹àŠŸàŠ° àŠàŠ°àŠŸ àŠàŠ®à§àŠªàŠ¿àŠàŠàŠŸàŠ°à§àа àŠ®àŠ¡à§àвà§àа àŠàŠªàŠ° àŠšàŠ¿àŠ°à§àŠàа àŠàаà§à¥€"
+
+#: downloading.page:57
+msgid "To use GetTor via Twitter:"
+msgstr "àŠà§àŠàŠàŠŸàŠ°à§àа àŠ®àŠŸàŠ§à§àŠ¯àŠ®à§ GetTor àŠ¬à§àŠ¯àŠ¬àŠ¹àŠŸàŠ° àŠàŠ°àŠ€à§:"
+
+#: downloading.page:62
+msgid ""
+"To get links for downloading Tor Browser in English for OS X, send a Direct "
+"Message to @get_tor with the words \"osx en\" in it (you don't need to "
+"follow the account)."
+msgstr ""
+"àŠàŠàŠž àŠàŠà§àŠžà§àа àŠàŠšà§àН àŠàŠàаà§àŠàŠ¿àŠ€à§ àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ° àŠ¡àŠŸàŠàŠšàŠ²à§àŠ¡ àŠàŠ°àŠŸàŠ° àŠàŠšà§àН àŠ²àŠ¿àŠà§àŠ àŠªà§àŠ€à§, àŠàŠàŠ¿àŠ€à§ "
+"\"àŠàŠàŠžàŠàŠà§àŠž àŠàŠš\" àŠ¶àŠ¬à§àŠŠàŠàŠ¿ àŠŠàŠ¿àŠ¯àŠŒà§ (àŠàŠàŠ¿ àŠàŠªàŠšàŠŸàŠà§ àŠ
à§àŠ¯àŠŸàŠàŠŸàŠàŠšà§àŠàŠàŠ¿ àŠ
àŠšà§àŠžàŠ°àŠ£ àŠàŠ°àŠ€à§ àŠ¹àŠ¬à§ àŠšàŠŸ) "
+"àŠŠàŠ¿àŠ¯àŠŒà§ @get_tor- àŠ àŠàŠàŠàŠ¿ àŠžàŠ°àŠŸàŠžàŠ°àŠ¿ àŠ¬àŠŸàŠ°à§àŠ€àŠŸ àŠªàŠŸàŠ àŠŸàŠšà¥€"
+
+#: downloading.page:70
+msgid "To use GetTor via Jabber/XMPP (Tor Messenger, Jitsi, CoyIM):"
+msgstr ""
+"àŠàŠ¬àŠ¬àŠŸàŠ° / àŠàŠà§àŠžàŠàŠ®àŠªàŠ¿àŠªàŠ¿ (àŠàа àŠ®à§àŠžà§àŠà§àŠàŠŸàŠ°, àŠàŠ¿àŠà§, àŠàŠàŠàŠ®) àŠàа àŠ®àŠŸàŠ§à§àŠ¯àŠ®à§ GetTor àŠ¬à§àŠ¯àŠ¬àŠ¹àŠŸàŠ° "
+"àŠàŠ°àŠ€à§:"
+
+#: downloading.page:75
+msgid ""
+"To get links for downloading Tor Browser in Chinese for Linux, send a "
+"message to gettor(a)torproject.org with the words \"linux zh\" in it."
+msgstr ""
+"àŠ²àŠ¿àŠšàŠŸàŠà§àŠžà§àа àŠàŠšà§àН àŠà§àŠšà§ àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ° àŠ¡àŠŸàŠàŠšàŠ²à§àŠ¡ àŠàŠ°àŠŸàŠ° àŠàŠšà§àН àŠ²àŠ¿àŠà§àŠ àŠªà§àŠ€à§ "
+"<a>Gettor(a)torproject.org</a>- àŠ àŠàŠàŠàŠ¿ àŠ¬àŠŸàŠ°à§àŠ€àŠŸ àŠªàŠŸàŠ àŠŸàŠš àŠ¯àŠŸàŠ€à§ \"linux zh\" àŠ¶àŠ¬à§àŠŠàŠàŠ¿ "
+"àŠ¬à§àŠ¯àŠ¬àŠ¹àŠŸàŠ° àŠàаà§àŠšà¥€"
+
+#: downloading.page:84
+msgid "Satori"
+msgstr "Satori"
+
+#: downloading.page:85
+msgid ""
+"Satori is an add-on for the Chrome or Chromium browsers that allows you to "
+"download several security and privacy programs from different sources."
+msgstr ""
+"àŠžàŠà§àŠ°àŠ¿ àŠà§àаà§àŠ® àŠ¬àŠŸ àŠà§àаà§àŠ® àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ°àŠà§àŠ²àŠ¿àŠ° àŠàŠšà§àН àŠàŠàŠàŠ¿ àŠ
à§àŠ¯àŠŸàŠ¡-àŠ
àŠš àŠ¯àŠŸ àŠàŠªàŠšàŠŸàŠà§ àŠ¬àŠ¿àŠàŠ¿àŠšà§àŠš àŠàŠ€à§àŠž"
+" àŠ¥à§àŠà§ àŠ¬àŠ¿àŠàŠ¿àŠšà§àŠš àŠšàŠ¿àŠ°àŠŸàŠªàŠ€à§àŠ€àŠŸ àŠàŠ¬àŠ àŠà§àŠªàŠšà§àŠ¯àŠŒàŠ€àŠŸ àŠªà§àаà§àŠà§àŠ°àŠŸàŠ®àŠà§àŠ²àŠ¿ àŠ¡àŠŸàŠàŠšàŠ²à§àŠ¡ àŠàŠ°àŠ€à§ àŠŠà§àŠ¯àŠŒà¥€"
+
+#: downloading.page:90
+msgid "To download Tor Browser using Satori:"
+msgstr "Satori àŠ¬à§àŠ¯àŠ¬àŠ¹àŠŸàŠ° àŠàŠ°à§ àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ° àŠ¡àŠŸàŠàŠšàŠ²à§àŠ¡ àŠàŠ°àŠ€à§:"
+
+#: downloading.page:95
+msgid "Install Satori from the Chrome App Store."
+msgstr "Chrome àŠ
à§àŠ¯àŠŸàŠª àŠžà§àŠà§àа àŠ¥à§àŠà§ Satori àŠàŠšàŠžà§àŠàв àŠàаà§àŠšà¥€"
+
+#: downloading.page:100
+msgid "Select Satori from your browserâs Apps menu."
+msgstr "àŠàŠªàŠšàŠŸàŠ° àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ°à§àа àŠ
à§àŠ¯àŠŸàŠªàŠž àŠ®à§àŠšà§ àŠ¥à§àŠà§ Satori àŠšàŠ¿àŠ°à§àŠ¬àŠŸàŠàŠš àŠàаà§àŠšà¥€"
+
+#: downloading.page:105
+msgid ""
+"When Satori opens, click on your preferred language. A menu will open "
+"listing the available downloads for that language. Find the entry for Tor "
+"Browser under the name of your operating system. Select either âAâ or âBâ "
+"after the name of the program â each one represents a different source from "
+"which to get the software. Your download will then begin."
+msgstr ""
+"Satori àŠ¯àŠàŠš àŠà§àвà§, àŠàŠªàŠšàŠŸàŠ° àŠªàŠàŠšà§àŠŠà§àа àŠàŠŸàŠ·àŠŸàŠ€à§ àŠà§àŠ²àŠ¿àŠ àŠàаà§àŠšà¥€ àŠàŠàŠàŠ¿ àŠ®à§àŠšà§ àŠà§àŠ²àŠŸ àŠ¹àŠ¬à§ àŠ¯à§ àŠàŠŸàŠ·àŠŸ"
+" àŠàŠšà§àН àŠàŠªàŠ²àŠ¬à§àЧ àŠ¡àŠŸàŠàŠšàŠ²à§àŠ¡ àŠ€àŠŸàŠ²àŠ¿àŠàŠŸà¥€ àŠàŠªàŠšàŠŸàŠ° àŠ
àŠªàŠŸàŠ°à§àŠàŠ¿àŠ àŠžàŠ¿àŠžà§àŠà§àŠ®à§àа àŠšàŠŸàŠ®à§àа àŠ
àŠ§à§àŠšà§ àŠàа "
+"àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ°à§àа àŠàŠšà§àН àŠàŠšà§àŠà§àŠ°àŠ¿ àŠà§àŠàŠà§àŠšà¥€ àŠªà§àаà§àŠà§àŠ°àŠŸàŠ®à§àа àŠšàŠŸàŠ® àŠ
àŠšà§àŠžàŠŸàŠ°à§ \"A\" àŠ¬àŠŸ \"B\" "
+"àŠšàŠ¿àŠ°à§àŠ¬àŠŸàŠàŠš àŠàаà§àŠš - àŠªà§àŠ°àŠ€àŠ¿àŠàŠ¿ àŠžàŠ«à§àŠàŠàŠ¯àŠŒà§àŠ¯àŠŸàŠ° àŠªàŠŸàŠàŠ¯àŠŒàŠŸàŠ° àŠàŠšà§àН àŠàŠàŠàŠ¿ àŠàŠ¿àŠšà§àŠš àŠà§àŠž àŠªà§àŠ°àŠ€àŠ¿àŠšàŠ¿àŠ§àŠ¿àŠ€à§àЬ"
+" àŠàаà§à¥€ àŠàŠªàŠšàŠŸàŠ° àŠ¡àŠŸàŠàŠšàŠ²à§àŠ¡ àŠ€àŠŸàŠ°àŠªàŠ° àŠ¶à§àŠ°à§ àŠ¹àŠ¬à§à¥€"
+
+#: downloading.page:115
+msgid ""
+"Wait for your download to finish, then find the âGenerate Hashâ section in "
+"Satoriâs menu and click âSelect Filesâ."
+msgstr ""
+"àŠàŠªàŠšàŠŸàŠ° àŠ¡àŠŸàŠàŠšàŠ²à§àŠ¡ àŠ¶à§àŠ· àŠ¹àŠàŠ¯àŠŒàŠŸàŠ° àŠàŠšà§àН àŠ
àŠªà§àŠà§àŠ·àŠŸ àŠàаà§àŠš, àŠ€àŠŸàŠ°àŠªàŠ° Satori àŠàа àŠ®à§àŠšà§àŠ€à§ \"àŠ¹à§àŠ¯àŠŸàŠ¶ "
+"àŠ€à§àŠ°àŠ¿ àŠàаà§àŠš\" àŠ¬àŠ¿àŠàŠŸàŠàŠàŠ¿ àŠà§àŠàŠà§àŠš àŠàŠ¬àŠ \"àŠ«àŠŸàŠàв àŠšàŠ¿àŠ°à§àŠ¬àŠŸàŠàŠš àŠàаà§àŠš\" àŠ àŠà§àŠ²àŠ¿àŠ àŠàаà§àŠšà¥€"
+
+#: downloading.page:121
+msgid ""
+"Select the downloaded Tor Browser file. Satori will display the checksum of "
+"the file, which you should compare with the softwareâs original checksum: "
+"you can find this by clicking the word âchecksumâ after the link you clicked"
+" on to start the download. If the checksums match, your download was "
+"successful, and you can <link xref=\"first-time\">begin using Tor "
+"Browser</link>. If they do not match, you may need to try downloading again,"
+" or from a different source."
+msgstr ""
+"àŠ¡àŠŸàŠàŠšàŠ²à§àŠ¡ àŠàŠ°àŠŸ àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ° àŠ«àŠŸàŠàвàŠàŠ¿ àŠšàŠ¿àŠ°à§àŠ¬àŠŸàŠàŠš àŠàаà§àŠšà¥€ Satori àŠ«àŠŸàŠàвà§àа àŠà§àŠàŠžàŠŸàŠ® àŠªà§àŠ°àŠŠàŠ°à§àŠ¶àŠš "
+"àŠàŠ°àŠ¬à§, àŠ¯àŠŸ àŠàŠªàŠšàŠŸàŠà§ àŠžàŠ«àŠàŠàŠ¯àŠŒà§àŠ¯àŠŸàŠ°à§àа àŠ®à§àв àŠà§àŠàŠžàŠŸàŠ®à§àа àŠžàŠŸàŠ¥à§ àŠ€à§àŠ²àŠšàŠŸ àŠàŠ°àŠŸ àŠàŠàŠ¿àŠ€: àŠ¡àŠŸàŠàŠšàŠ²à§àŠ¡àŠàŠ¿ "
+"àŠ¡àŠŸàŠàŠšàŠ²à§àŠ¡ àŠàŠ°àŠŸàŠ° àŠàŠšà§àН àŠàŠªàŠšàŠ¿ àŠ¯à§ àŠ²àŠ¿àŠà§àŠàŠàŠ¿ àŠà§àŠ²àŠ¿àŠ àŠàаà§àŠà§àŠš àŠ€àŠŸàŠ° àŠªàŠ°à§ àŠàŠªàŠšàŠ¿ \"àŠà§àŠàŠžàŠŸàŠ®\" "
+"àŠ¶àŠ¬à§àŠŠàŠàŠ¿ àŠà§àŠ²àŠ¿àŠ àŠàŠ°à§ àŠàŠàŠ¿ àŠà§àŠàŠà§ àŠªà§àŠ€à§ àŠªàŠŸàŠ°à§àŠšà¥€ àŠ¯àŠŠàŠ¿ checksums àŠ®àŠ¿àŠ²àŠ¿àŠ€ àŠ¹àŠ¯àŠŒ, àŠàŠªàŠšàŠŸàŠ° "
+"àŠ¡àŠŸàŠàŠšàŠ²à§àŠ¡ àŠžàŠ«àŠ² àŠ¹àŠ¯àŠŒà§àŠà§, àŠàŠ¬àŠ àŠàŠªàŠšàŠ¿ <link xref=\"first-time\">àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ°</link> "
+"àŠ¬à§àŠ¯àŠ¬àŠ¹àŠŸàŠ° àŠàŠ°à§ àŠ¶à§àŠ°à§ àŠàŠ°àŠ€à§ àŠªàŠŸàŠ°à§àŠšà¥€ àŠ¯àŠŠàŠ¿ àŠ€àŠŸàŠ°àŠŸ àŠ®àŠ¿àŠ²àŠ¿àŠ€ àŠšàŠŸ àŠ¹àŠ¯àŠŒ, àŠ€àŠ¬à§ àŠàŠªàŠšàŠŸàŠà§ àŠàŠ¬àŠŸàŠ° àŠ¡àŠŸàŠàŠšàŠ²à§àŠ¡ "
+"àŠàŠ°àŠŸàŠ° àŠà§àŠ·à§àŠàŠŸ àŠàŠ°àŠ€à§ àŠ¹àŠ€à§ àŠªàŠŸàŠ°à§, àŠ
àŠ¥àŠ¬àŠŸ àŠàŠàŠàŠ¿ àŠàŠ¿àŠšà§àŠš àŠà§àŠž àŠ¥à§àŠà§à¥€"
+
+#: first-time.page:7
+msgid "Learn how to use Tor Browser for the first time"
+msgstr "àŠªà§àŠ°àŠ¥àŠ®àŠ¬àŠŸàŠ° àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ° àŠàŠ¿àŠàŠŸàŠ¬à§ àŠ¬à§àŠ¯àŠ¬àŠ¹àŠŸàŠ° àŠàŠ°àŠ¬à§àŠš àŠàŠŸàŠšà§àŠš"
+
+#: first-time.page:10
+msgid "Running Tor Browser for the first time"
+msgstr "àŠªà§àŠ°àŠ¥àŠ®àŠ¬àŠŸàŠ° àŠ°àŠŸàŠš àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ°"
+
+#: first-time.page:12
+msgid ""
+"When you run Tor Browser for the first time, you will see the Tor Network "
+"Settings window. This offers you the option to connect directly to the Tor "
+"network, or to configure Tor Browser for your connection."
+msgstr ""
+"àŠàŠªàŠšàŠ¿ àŠªà§àŠ°àŠ¥àŠ®àŠ¬àŠŸàŠ° àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ° àŠàŠŸàŠ²àŠŸàŠšà§àа àŠžàŠ®àŠ¯àŠŒ, àŠàŠªàŠšàŠ¿ àŠàа àŠšà§àŠàŠàŠ¯àŠŒàŠŸàŠ°à§àŠ àŠžà§àŠàŠ¿àŠàŠž àŠàŠàŠšà§àŠ¡à§ "
+"àŠŠà§àŠàŠ€à§ àŠªàŠŸàŠ¬à§àŠšà¥€ àŠàŠàŠ¿ àŠàŠªàŠšàŠŸàŠà§ àŠàа àŠšà§àŠàŠàŠ¯àŠŒàŠŸàŠ°à§àŠà§ àŠžàŠ°àŠŸàŠžàŠ°àŠ¿ àŠžàŠàНà§àŠà§àа àŠ¬àŠ¿àŠàвà§àŠª àŠªà§àŠ°àŠŠàŠŸàŠš àŠàаà§, "
+"àŠ
àŠ¥àŠ¬àŠŸ àŠàŠªàŠšàŠŸàŠ° àŠžàŠàНà§àŠà§àа àŠàŠšà§àН àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ° àŠàŠšàŠ«àŠ¿àŠàŠŸàŠ° àŠàŠ°àŠ€à§ àŠŠà§àŠ¯àŠŒà¥€"
+
+#: first-time.page:19
+msgid "Connect"
+msgstr "àŠžàŠàНà§àŠ àŠàŠ°àŠŸ"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: first-time.page:21 troubleshooting.page:18
+msgctxt "_"
+msgid ""
+"external ref='media/first-time/connect.png' "
+"md5='9d07068f751a3bfd274365a4ba8d90ca'"
+msgstr ""
+"àŠ¬àŠŸàŠ¹à§àŠ¯àŠ¿àŠ àŠ°à§àŠ«='media/first-time/connect.png' "
+"md5='9d07068f751a3bfd274365a4ba8d90ca'"
+
+#: first-time.page:23
+msgid ""
+"In most cases, choosing \"Connect\" will allow you to connect to the Tor "
+"network without any further configuration. Once clicked, a status bar will "
+"appear, showing Torâs connection progress. If you are on a relatively fast "
+"connection, but this bar seems to get stuck at a certain point, see the "
+"<link xref=\"troubleshooting\">Troubleshooting</link> page for help solving "
+"the problem."
+msgstr ""
+"àŠ¬à§àŠ¶àŠ¿àŠ°àŠàŠŸàŠ àŠà§àŠ·à§àŠ€à§àаà§, \"àŠžàŠàНà§àŠ\" àŠšàŠ¿àŠ°à§àŠ¬àŠŸàŠàŠš àŠàŠ°àŠŸ àŠ¹àŠ²à§ àŠàŠªàŠšàŠ¿ àŠàа àŠàŠŸ àŠšà§àŠàŠàŠ¯àŠŒàŠŸàŠ°à§àŠ àŠ¥à§àŠà§ "
+"àŠžàŠàНà§àŠ àŠžà§àŠ¥àŠŸàŠªàŠšà§àа àŠ
àŠšà§àŠ®àŠ€àŠ¿ àŠŠà§àŠ¬à§ àŠšàŠŸà¥€ àŠàŠàŠ¬àŠŸàŠ° àŠà§àŠ²àŠ¿àŠ àŠàŠ°àŠ²à§, àŠàа àŠàа àŠžàŠàНà§àŠ àŠ
àŠà§àаàŠàŠ€àŠ¿ àŠŠà§àŠàŠŸàŠšà§ "
+"àŠ¹àŠ¬à§, àŠàŠàŠàŠ¿ àŠžà§àŠà§àŠ¯àŠŸàŠàŠŸàŠž àŠ¬àŠŸàŠ° àŠªà§àŠ°àŠŠàŠ°à§àŠ¶àŠ¿àŠ€ àŠ¹àŠ¬à§à¥€ àŠ¯àŠŠàŠ¿ àŠàŠªàŠšàŠ¿ àŠàŠàŠàŠ¿ àŠ
àŠªà§àŠà§àŠ·àŠŸàŠà§àŠ€ àŠŠà§àаà§àŠ€ àŠžàŠàНà§àŠ "
+"àŠàŠà§, àŠàŠ¿àŠšà§àŠ€à§ àŠàŠ àŠ¬àŠŸàŠ° àŠàŠàŠàŠ¿ àŠšàŠ¿àŠ°à§àŠŠàŠ¿àŠ·à§àŠ àŠžàŠ®àŠ¯àŠŒà§ àŠàŠàŠà§ àŠ®àŠšà§ àŠ¹àŠ¯àŠŒ, <link "
+"xref=\"troubleshooting\">àŠžàŠ®àŠžà§àŠ¯àŠŸàŠ° àŠžàŠ®àŠŸàŠ§àŠŸàŠš</link> àŠžàŠŸàŠ¹àŠŸàŠ¯à§àНà§àа àŠàŠšà§àН àŠžàŠ®àŠžà§àŠ¯àŠŸ àŠžàŠ®àŠŸàŠ§àŠŸàŠš "
+"àŠªà§àŠ·à§àŠ àŠŸ àŠŠà§àŠà§àŠšà¥€"
+
+#: first-time.page:33
+msgid "Configure"
+msgstr "àŠàŠšàŠ«àŠ¿àŠàŠŸàŠ° àŠàаà§àŠš"
+
+#: first-time.page:37
+msgid ""
+"If you know that your connection is censored, or uses a proxy, you should "
+"select this option. Tor Browser will take you through a series of "
+"configuration options."
+msgstr ""
+"àŠ¯àŠŠàŠ¿ àŠàŠªàŠšàŠ¿ àŠàŠŸàŠšà§àŠš àŠ¯à§ àŠàŠªàŠšàŠŸàŠ° àŠžàŠàНà§àŠ àŠžà§àŠšà§àŠžàŠ° àŠàŠ°àŠŸ àŠ¹àŠ¯àŠŒ, àŠ¬àŠŸ àŠªà§àаàŠà§àŠžàŠ¿ àŠ¬à§àŠ¯àŠ¬àŠ¹àŠŸàŠ° àŠàаà§, àŠàŠªàŠšàŠ¿ "
+"àŠàŠ àŠ¬àŠ¿àŠàвà§àŠªàŠàŠ¿ àŠšàŠ¿àŠ°à§àŠ¬àŠŸàŠàŠš àŠàŠ°àŠŸ àŠàŠàŠ¿àŠ€à¥€ àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ° àŠàŠšàŠ«àŠ¿àŠàŠŸàŠ°à§àŠ¶àŠš àŠ¬àŠ¿àŠàвà§àŠªàŠà§àŠ²àŠ¿àŠ° àŠàŠàŠàŠ¿ àŠžàŠ¿àŠ°àŠ¿àŠ"
+" àŠ®àŠŸàŠ§à§àŠ¯àŠ®à§ àŠàŠªàŠšàŠŸàŠà§ àŠšàŠ¿àŠ¯àŠŒà§ àŠ¯àŠŸàŠ¬à§à¥€"
+
+#: first-time.page:44
+msgid ""
+"The first screen asks if access to the Tor network is blocked or censored on"
+" your connection. If you do not believe this is the case, select âNoâ. If "
+"you know your connection is censored, or you have tried and failed to "
+"connect to the Tor network and no other solutions have worked, select âYesâ."
+" You will then be taken to the <link "
+"xref=\"circumvention\">Circumvention</link> screen to configure a pluggable "
+"transport."
+msgstr ""
+"àŠàа àŠšà§àŠàŠàŠ¯àŠŒàŠŸàŠ°à§àŠ àŠ
à§àŠ¯àŠŸàŠà§àŠžà§àŠž àŠàŠªàŠšàŠŸàŠ° àŠžàŠàНà§àŠ àŠ¬à§àŠ²àŠ àŠ¬àŠŸ àŠžà§àŠšà§àŠžàŠ° àŠàŠ°àŠŸ àŠ¹àŠ¯àŠŒ àŠàŠ¿àŠšàŠŸ àŠªà§àŠ°àŠ¥àŠ® àŠªàŠ°à§àŠŠàŠŸ "
+"àŠàŠ¿àŠà§àŠàŠŸàŠžàŠŸà¥€ àŠ¯àŠŠàŠ¿ àŠàŠªàŠšàŠ¿ àŠ¬àŠ¿àŠ¶à§àŠ¬àŠŸàŠž àŠàаà§àŠš àŠšàŠŸ àŠàŠàŠ¿ àŠàŠ àŠà§àŠ·à§àŠ€à§àаà§, \"àŠšàŠŸ\" àŠšàŠ¿àŠ°à§àŠ¬àŠŸàŠàŠš àŠàаà§àŠš àŠ¯àŠŠàŠ¿"
+" àŠàŠªàŠšàŠ¿ àŠàŠŸàŠšà§àŠš àŠ¯à§ àŠàŠªàŠšàŠŸàŠ° àŠžàŠàНà§àŠ àŠžà§àŠšà§àŠžàŠ° àŠàŠ°àŠŸ àŠ¹àŠ¯àŠŒà§àŠà§, àŠ¬àŠŸ àŠàŠªàŠšàŠ¿ àŠà§àŠ·à§àŠàŠŸ àŠàаà§àŠà§àŠš àŠàŠ¬àŠ àŠàа "
+"àŠšà§àŠàŠàŠ¯àŠŒàŠŸàŠ°à§àŠà§ àŠžàŠàНà§àŠ àŠàŠ°àŠ€à§ àŠ¬à§àŠ¯àŠ°à§àŠ¥ àŠ¹àŠ¯àŠŒà§àŠà§àŠš àŠàŠ¬àŠ àŠ
àŠšà§àН àŠà§àŠšà§ àŠžàŠ®àŠŸàŠ§àŠŸàŠš àŠàŠŸàŠ àŠàаà§àŠšàŠ¿, "
+"\"àŠ¹à§àŠ¯àŠŸàŠ\" àŠšàŠ¿àŠ°à§àŠ¬àŠŸàŠàŠš àŠàаà§àŠšà¥€ àŠàŠàŠàŠ¿ àŠªà§àвà§àŠ¯àŠŸàŠà§àŠ¬àŠ² àŠà§àŠ°àŠŸàŠšà§àŠžàŠªà§àаà§àŠ àŠàŠšàŠ«àŠ¿àŠàŠŸàŠ° àŠàŠ°àŠŸàŠ° àŠàŠšà§àН àŠàŠªàŠšàŠ¿"
+" àŠ€àŠŸàŠ°àŠªàŠ° <link xref=\"circumvention\">àŠžàŠŸàŠ°à§àŠà§àŠ®àŠŸàŠ®à§àŠªàŠ¶àŠš</link> àŠžà§àŠà§àаà§àŠšà§ àŠšàŠ¿àŠ¯àŠŒà§ "
+"àŠ¯àŠŸàŠ¬à§àŠšà¥€"
+
+#: first-time.page:55
+msgid ""
+"The next screen asks if your connection uses a proxy. In most cases, this is"
+" not necessary. You will usually know if you need to answer âYesâ, as the "
+"same settings will be used for other browsers on your system. If possible, "
+"ask your network administrator for guidance. If your connection does not use"
+" a proxy, click âContinueâ."
+msgstr ""
+"àŠàŠªàŠšàŠŸàŠ° àŠžàŠàНà§àŠ àŠàŠàŠàŠ¿ àŠªà§àаàŠà§àŠžàŠ¿ àŠ¬à§àŠ¯àŠ¬àŠ¹àŠŸàŠ° àŠàŠ°à§ àŠªàŠ°à§àа àŠžà§àŠà§àŠ°àŠ¿àŠš àŠàŠ¿àŠà§àŠà§àŠž àŠàаà§à¥€ àŠ¬à§àŠ¶àŠ¿àŠ°àŠàŠŸàŠ "
+"àŠà§àŠ·à§àŠ€à§àаà§, àŠàŠàŠ¿ àŠªà§àŠ°àŠ¯àŠŒà§àŠàŠšà§àŠ¯àŠŒ àŠšàŠ¯àŠŒà¥€ àŠàŠªàŠšàŠ¿ àŠ¯àŠŠàŠ¿ \"àŠ¹à§àŠ¯àŠŸàŠ\" àŠàŠ€à§àŠ€àŠ° àŠŠàŠ¿àŠ€à§ àŠàŠŸàŠš àŠ€àŠ¬à§ àŠàŠªàŠšàŠ¿ "
+"àŠžàŠŸàŠ§àŠŸàŠ°àŠ£àŠ€ àŠàŠŸàŠšàŠ€à§ àŠªàŠŸàŠ°àŠ¬à§àŠš, àŠàŠàŠ àŠžà§àŠàŠ¿àŠàŠž àŠàŠªàŠšàŠŸàŠ° àŠžàŠ¿àŠžà§àŠà§àŠ®à§àа àŠ
àŠšà§àŠ¯àŠŸàŠšà§àН àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ°à§àа àŠàŠšà§àН "
+"àŠ¬à§àŠ¯àŠ¬àŠ¹àŠŸàŠ° àŠàŠ°àŠŸ àŠ¹àŠ¬à§à¥€ àŠ¯àŠŠàŠ¿ àŠžàŠ®à§àŠàЬ àŠ¹àŠ¯àŠŒ àŠ€àŠŸàŠ¹àŠ²à§, àŠšàŠ¿àŠ°à§àŠŠà§àŠ¶àŠ¿àŠàŠŸàŠàŠ¿àŠ° àŠàŠšà§àН àŠàŠªàŠšàŠŸàŠ° àŠšà§àŠàŠàŠ¯àŠŒàŠŸàŠ°à§àŠ "
+"àŠªà§àŠ°àŠ¶àŠŸàŠžàŠà§àа àŠàŠŸàŠà§ àŠàŠ¿àŠà§àŠàŠŸàŠžàŠŸ àŠàаà§àŠšà¥€ àŠ¯àŠŠàŠ¿ àŠàŠªàŠšàŠŸàŠ° àŠžàŠàНà§àŠ àŠà§àŠšàŠ àŠªà§àаàŠà§àŠžàŠ¿ àŠ¬à§àŠ¯àŠ¬àŠ¹àŠŸàŠ° àŠšàŠŸ àŠàаà§, "
+"\"àŠ
àŠ¬àŠ¿àŠ°àŠ€\" àŠà§àŠ²àŠ¿àŠ àŠàаà§àŠš"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: first-time.page:63
+msgctxt "_"
+msgid ""
+"external ref='media/first-time/proxy_question.png' "
+"md5='30853b3e86cfd386bbc32e5b8b45a378'"
+msgstr ""
+"àŠ¬àŠŸàŠ¹à§àŠ¯àŠ¿àŠ àŠ°à§àŠ«='media/first-time/proxy_question.png' "
+"md5='30853b3e86cfd386bbc32e5b8b45a378'"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: first-time.page:66
+msgctxt "_"
+msgid ""
+"external ref='media/first-time/proxy.png' "
+"md5='13f21a351cd0aa1cf11aada690f3dc90'"
+msgstr ""
+"àŠ¬àŠŸàŠ¹à§àŠ¯àŠ¿àŠ àŠ°à§àŠ«='media/first-time/proxy.png' "
+"md5='13f21a351cd0aa1cf11aada690f3dc90'"
+
+#: index.page:6
+msgid "Tor Browser User Manual"
+msgstr "àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ° àŠàŠàŠàŠŸàŠ° àŠ®à§àŠ¯àŠŸàŠšà§àŠ¯àŠŒàŠŸàŠ²"
+
+#: known-issues.page:6
+msgid "A list of known issues."
+msgstr "àŠªàŠ°àŠ¿àŠàŠ¿àŠ€ àŠ¬àŠ¿àŠ·àŠ¯àŠŒàŠà§àŠ²àŠ¿àŠ° àŠàŠàŠàŠ¿ àŠ€àŠŸàŠ²àŠ¿àŠàŠŸ"
+
+#: known-issues.page:10
+msgid "Known Issues"
+msgstr "àŠà§àŠàŠŸàŠ€ àŠžàŠ®àŠžà§àŠ¯àŠŸ"
+
+#: known-issues.page:14
+msgid ""
+"Tor needs your system clock (and your time zone) set to the correct time."
+msgstr "àŠàа àŠàŠªàŠšàŠŸàŠ° àŠžàŠ¿àŠžà§àŠà§àŠ® àŠàŠ¡àŠŒàŠ¿ àŠªà§àŠ°àŠ¯àŠŒà§àŠàŠš (àŠàŠ¬àŠ àŠàŠªàŠšàŠŸàŠ° àŠžàŠ®àŠ¯àŠŒ àŠ
àŠà§àŠàв) àŠžàŠ àŠ¿àŠ àŠžàŠ®àŠ¯àŠŒ àŠžà§àŠà¥€"
+
+#: known-issues.page:19
+msgid ""
+"The following firewall software have been known to interfere with Tor and "
+"may need to be temporarily disabled:"
+msgstr ""
+"àŠšàŠ¿àŠ®à§àŠšàŠ²àŠ¿àŠàŠ¿àŠ€ àŠ«àŠŸàŠ¯àŠŒàŠŸàŠ°àŠàŠ¯àŠŒàŠŸàŠ² àŠžàŠ«à§àŠàŠàŠ¯àŠŒà§àŠ¯àŠŸàŠ° àŠàа àŠ®àŠ§à§àŠ¯à§ àŠ¹àŠžà§àŠ€àŠà§àŠ·à§àŠª àŠªàŠ°àŠ¿àŠàŠ¿àŠ€ àŠ¹àŠ¯àŠŒà§àŠà§ àŠàŠ¬àŠ "
+"àŠžàŠŸàŠ®àŠ¯àŠŒàŠ¿àŠàŠàŠŸàŠ¬à§ àŠ
àŠà§àŠ·àŠ® àŠàŠ°àŠŸ àŠªà§àŠ°àŠ¯àŠŒà§àŠàŠš àŠ¹àŠ€à§ àŠªàŠŸàŠ°à§:"
+
+#: known-issues.page:23
+msgid "Webroot SecureAnywhere"
+msgstr "Webroot Secure Anywhere"
+
+#: known-issues.page:26
+msgid "Kaspersky Internet Security 2012"
+msgstr "Kaspersky Internet Security 2012"
+
+#: known-issues.page:29
+msgid "Sophos Antivirus for Mac"
+msgstr "àŠ®à§àŠ¯àŠŸàŠà§àа àŠàŠšà§àН àŠžà§àŠ«à§àŠž àŠ
à§àŠ¯àŠŸàŠšà§àŠàŠ¿àŠàŠŸàŠàŠ°àŠŸàŠž"
+
+#: known-issues.page:32
+msgid "Microsoft Security Essentials"
+msgstr "Microsoft Security Essentials"
+
+#: known-issues.page:37
+msgid ""
+"Videos that require Adobe Flash are unavailable. Flash is disabled for "
+"security reasons."
+msgstr ""
+"àŠàŠ®àŠš àŠàŠ¿àŠ¡àŠ¿àŠàŠà§àŠ²àŠ¿ àŠ¯àŠŸ Adobe Flash àŠàа àŠªà§àŠ°àŠ¯àŠŒà§àŠàŠš àŠ¹àŠ¯àŠŒ àŠ
àŠšà§àŠªàŠ²àŠ¬à§àŠ§à¥€ àŠšàŠ¿àŠ°àŠŸàŠªàŠ€à§àŠ€àŠŸàŠ° àŠàŠŸàŠ°àŠ£à§ "
+"àŠ«à§àвà§àŠ¯àŠŸàŠ¶ àŠ
àŠà§àŠ·àŠ® àŠàŠ°àŠŸ àŠ¹àŠ¯àŠŒà§àŠà§à¥€"
+
+#: known-issues.page:43
+msgid "Tor can not use a bridge if a proxy is set."
+msgstr "àŠàŠàŠàŠ¿ àŠªà§àаàŠà§àŠžàŠ¿ àŠžà§àŠ àŠàŠ°àŠŸ àŠ¹àŠ²à§ àŠàа àŠàŠàŠàŠ¿ àŠžà§àŠ€à§ àŠ¬à§àŠ¯àŠ¬àŠ¹àŠŸàŠ° àŠàŠ°àŠ€à§ àŠªàŠŸàŠ°àŠ¬à§àŠš àŠšàŠŸà¥€"
+
+#: known-issues.page:48
+msgid ""
+"The Tor Browser package is dated January 1, 2000 00:00:00 UTC. This is to "
+"ensure that each software build is exactly reproducible."
+msgstr ""
+"àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ° àŠªà§àŠ¯àŠŸàŠà§àŠ 1 àŠàŠŸàŠšà§àŠ¯àŠŒàŠŸàŠ°à§, 2000 00:00:00 àŠàŠàŠàŠ¿àŠžàŠ¿ àŠ€àŠŸàŠ°àŠ¿àŠà¥€ àŠàŠàŠ¿ àŠšàŠ¿àŠ¶à§àŠàŠ¿àŠ€ "
+"àŠàŠ°àŠ€à§ àŠ¹àŠ¬à§ àŠ¯à§ àŠªà§àŠ°àŠ€àŠ¿àŠàŠ¿ àŠžàŠ«à§àŠàŠàŠ¯àŠŒà§àŠ¯àŠŸàŠ° àŠ¬àŠ¿àŠ²à§àŠ¡àŠ àŠžàŠ àŠ¿àŠàŠàŠŸàŠ¬à§ àŠàŠ€à§àŠªàŠŸàŠŠàŠ¿àŠ€ àŠ¹àŠ¯àŠŒà¥€"
+
+#: known-issues.page:54
+msgid ""
+"To run Tor Browser on Ubuntu, users need to execute a shell script. Open "
+"\"Files\" (Unity's explorer), open Preferences â Behavior Tab â Set \"Run "
+"executable text files when they are opened\" to \"Ask every time\", then "
+"click OK."
+msgstr ""
+"àŠàЬà§àŠšà§àŠà§àŠ€à§ àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ° àŠàŠŸàŠ²àŠŸàŠšà§àа àŠàŠšà§àН, àŠ¬à§àŠ¯àŠ¬àŠ¹àŠŸàŠ°àŠàŠŸàŠ°à§àŠŠà§àа àŠàŠàŠàŠ¿ àŠ¶à§àв àŠžà§àŠà§àŠ°àŠ¿àŠªà§àŠ àŠàŠŸàŠ²àŠŸàŠšà§"
+" àŠªà§àŠ°àŠ¯àŠŒà§àŠàŠšà¥€ \"àŠ«àŠŸàŠàвàŠà§àŠ²àŠ¿\" (àŠàŠàŠšàŠ¿àŠàŠ¿ àŠàа àŠàŠà§àŠžàŠªà§àвà§àŠ°àŠŸàŠ°) àŠà§àвà§àŠš, àŠàŠªà§àŠš àŠªà§àаà§àŠ«àŠŸàŠ°à§àŠšà§àŠž â "
+"àŠàŠàŠ°àŠ£ àŠà§àŠ¯àŠŸàŠ¬ â àŠžà§àŠ àŠàаà§àŠš \"àŠàŠà§àŠžàŠ¿àŠàŠ¿àŠàŠà§àŠ¬àŠ² àŠà§àŠà§àŠžàŠ àŠ«àŠŸàŠàвàŠà§àŠ²àŠ¿ àŠ¯àŠàŠš àŠà§àŠ²àŠŸ àŠ¹àŠ¯àŠŒ àŠ€àŠàŠš\" "
+"\"àŠªà§àŠ°àŠ€à§àНà§àŠàŠ¬àŠŸàŠ° àŠàŠ¿àŠà§àŠàŠŸàŠžàŠŸ àŠàаà§àŠš\" -àŠ àŠà§àŠ²àŠ¿àŠ àŠàаà§àŠš, àŠ€àŠŸàŠ°àŠªàŠ° àŠ àŠ¿àŠ àŠàŠà§ àŠà§àŠ²àŠ¿àŠ àŠàаà§àŠšà¥€"
+
+#: known-issues.page:62
+msgid ""
+"Tor Browser can also be started from the command line by running the "
+"following command from inside the Tor Browser directory:"
+msgstr ""
+"àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ°à§àа àŠàŠ¿àŠ€àŠ° àŠ¥à§àŠà§ àŠšàŠ¿àŠ®à§àŠšà§àŠà§àŠ€ àŠàŠ®àŠŸàŠšà§àŠ¡àŠàŠ¿ àŠàŠŸàŠ²àŠŸàŠšà§àа àŠ®àŠŸàŠ§à§àŠ¯àŠ®à§ àŠàŠ®àŠŸàŠšà§àŠ¡ àŠ²àŠŸàŠàŠš àŠ¥à§àŠà§ "
+"àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ°àŠàŠ¿ àŠàŠŸàŠ²à§ àŠàŠ°àŠŸ àŠ¯àŠŸàŠ¯àŠŒ:"
+
+#: known-issues.page:66
+#, no-wrap
+msgid ""
+"\n"
+" ./start-tor-browser.desktop\n"
+" "
+msgstr ""
+"\n"
+" ./start-tor-browser.desktop\n"
+" "
+
+#: managing-identities.page:6
+msgid "Learn how to control personally-identifying information in Tor Browser"
+msgstr ""
+"àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ°à§ àŠ¬à§àНàŠà§àŠ€àŠ¿àŠàŠ€àŠàŠŸàŠ¬à§ àŠžàŠšàŠŸàŠà§àŠ€àŠàŠŸàŠ°à§ àŠ€àŠ¥à§àН àŠà§àŠàŠŸàŠ¬à§ àŠšàŠ¿àŠ¯àŠŒàŠšà§àŠ€à§àŠ°àŠ£ àŠàŠ°àŠ¬à§àŠš àŠ€àŠŸ àŠàŠŸàŠšà§àŠš"
+
+#: managing-identities.page:10
+msgid "Managing identities"
+msgstr "àŠžàŠšàŠŸàŠà§àŠ€àŠàŠ°àŠ£ àŠªàŠ°àŠ¿àŠàŠŸàŠ²àŠšàŠŸ"
+
+#: managing-identities.page:12
+msgid ""
+"When you connect to a website, it is not only the operators of that website "
+"who can record information about your visit. Most websites now use numerous "
+"third-party services, including social networking âLikeâ buttons, analytics "
+"trackers, and advertising beacons, all of which can link your activity "
+"across different sites."
+msgstr ""
+"àŠ¯àŠàŠš àŠàŠªàŠšàŠ¿ àŠà§àŠšàŠ àŠàŠ¯àŠŒà§àŠ¬àŠžàŠŸàŠàŠà§àа àŠžàŠŸàŠ¥à§ àŠžàŠàНà§àŠà§àŠ€ àŠ¹àŠš, àŠàŠàŠ¿ àŠà§àŠ¬àŠ² àŠžà§àŠ àŠàŠ¯àŠŒà§àŠ¬àŠžàŠŸàŠàŠà§àа àŠ
àŠªàŠŸàŠ°à§àŠàа "
+"àŠšàŠ¯àŠŒ àŠ¯àŠŸ àŠàŠªàŠšàŠŸàŠ° àŠŠàŠ°à§àŠ¶àŠš àŠžàŠ®à§àŠªàŠ°à§àŠà§ àŠ€àŠ¥à§àН àŠ°à§àŠàаà§àŠ¡ àŠàŠ°àŠ€à§ àŠªàŠŸàŠ°à§à¥€ àŠ¬à§àŠ¶àŠ¿àŠ°àŠàŠŸàŠ àŠàŠ¯àŠŒà§àŠ¬àŠžàŠŸàŠàŠ àŠàŠàŠš "
+"àŠžà§àжà§àŠ¯àŠŸàŠ² àŠšà§àŠàŠàŠ¯àŠŒàŠŸàŠ°à§àŠàŠ¿àŠ \"àŠ¬à§àŠ€àŠŸàŠ®àŠà§àŠ²àŠ¿\", àŠàŠšàŠŸàŠ²àŠ¿àŠàŠ¿àŠà§àŠž àŠà§àаà§àŠ¯àŠŸàŠàŠŸàŠ°à§àŠž àŠàŠ¬àŠ àŠ¬àŠ¿àŠà§àŠàŠŸàŠªàŠš àŠ¬à§àŠàŠš"
+" àŠžàŠ¹ àŠ¬àŠ¿àŠàŠ¿àŠšà§àŠš àŠ€à§àŠ€à§àŠ¯àŠŒ àŠªàŠà§àŠ·à§àа àŠªàŠ°àŠ¿àŠ·à§àŠ¬àŠŸàŠà§àŠ²àŠ¿ àŠ¬à§àŠ¯àŠ¬àŠ¹àŠŸàŠ° àŠàаà§, àŠ¯àŠŸ àŠžàŠ®àŠžà§àŠ€ àŠ¬àŠ¿àŠàŠ¿àŠšà§àŠš àŠžàŠŸàŠàŠ "
+"àŠà§àŠ¡àŠŒà§ àŠàŠªàŠšàŠŸàŠ° àŠàŠŸàŠ°à§àНàŠàŠ²àŠŸàŠª àŠ²àŠ¿àŠà§àŠ àŠàŠ°àŠ€à§ àŠªàŠŸàŠ°à§à¥€"
+
+#: managing-identities.page:20
+msgid ""
+"Using the Tor network stops observers from being able to discover your exact"
+" location and IP address, but even without this information they might be "
+"able to link different areas of your activity together. For this reason, Tor"
+" Browser includes some additional features that help you control what "
+"information can be tied to your identity."
+msgstr ""
+"àŠàа àŠšà§àŠàŠàŠ¯àŠŒàŠŸàŠ°à§àŠ àŠ¬à§àŠ¯àŠ¬àŠ¹àŠŸàŠ° àŠàŠ°à§ àŠàŠªàŠšàŠŸàŠ° àŠžàŠ àŠ¿àŠ àŠ
àŠ¬àŠžà§àŠ¥àŠŸàŠš àŠàŠ¬àŠ IP àŠ àŠ¿àŠàŠŸàŠšàŠŸ àŠàŠ¬àŠ¿àŠ·à§àŠàŠŸàŠ° àŠàŠ°àŠ€à§ "
+"àŠªàŠ°à§àŠ¯àŠ¬à§àŠà§àŠ·àŠàŠŠà§àа àŠžà§àŠàŠª àŠàаà§, àŠàŠ¿àŠšà§àŠ€à§ àŠàŠ àŠ€àŠ¥à§àН àŠàŠŸàŠ¡àŠŒàŠŸàŠ àŠ€àŠŸàŠ°àŠŸ àŠàŠªàŠšàŠŸàŠ° àŠàŠŸàŠ°à§àНàŠàŠ²àŠŸàŠªà§àа àŠ¬àŠ¿àŠàŠ¿àŠšà§àŠš"
+" àŠà§àŠ·à§àŠ€à§àаàŠà§àŠ²àŠ¿ àŠàŠàŠžàŠà§àŠà§ àŠžàŠàНà§àŠà§àŠ€ àŠàŠ°àŠ€à§ àŠžàŠà§àŠ·àŠ® àŠ¹àŠ€à§ àŠªàŠŸàŠ°à§à¥€ àŠàŠ àŠàŠŸàŠ°àŠ£à§, àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ°à§ "
+"àŠàŠ¿àŠà§ àŠ
àŠ€àŠ¿àŠ°àŠ¿àŠà§àŠ€ àŠ¬à§àŠ¶àŠ¿àŠ·à§àŠà§àН àŠ°àŠ¯àŠŒà§àŠà§ àŠ¯àŠŸ àŠàŠªàŠšàŠŸàŠà§ àŠàŠªàŠšàŠŸàŠ° àŠªàŠ°àŠ¿àŠàŠ¯àŠŒ àŠ¥à§àŠà§ àŠàŠ¿ àŠ€àŠ¥à§àН àŠžàŠàНà§àŠà§àŠ€ "
+"àŠàŠ°àŠ€à§ àŠªàŠŸàŠ°à§ àŠ€àŠŸ àŠšàŠ¿àŠ¯àŠŒàŠšà§àŠ€à§àŠ°àŠ£à§ àŠžàŠ¹àŠŸàŠ¯àŠŒàŠ€àŠŸ àŠàаà§à¥€"
+
+#: managing-identities.page:29
+msgid "The URL bar"
+msgstr "URL àŠ¬àŠŸàŠ°"
+
+#: managing-identities.page:30
+msgid ""
+"Tor Browser centers your web experience around your relationship with the "
+"website in the URL bar. Even if you connect to two different sites that use "
+"the same third-party tracking service, Tor Browser will force the content to"
+" be served over two different Tor circuits, so the tracker will not know "
+"that both connections originate from your browser."
+msgstr ""
+"àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ° àŠàŠàŠàаàŠàв àŠ¬àŠŸàŠ°à§ àŠàŠ¯àŠŒà§àŠ¬àŠžàŠŸàŠàŠà§àа àŠžàŠŸàŠ¥à§ àŠàŠªàŠšàŠŸàŠ° àŠžàŠ®à§àŠªàŠ°à§àŠà§àа àŠàŠŸàŠàŠŸàŠàŠŸàŠàŠ¿ àŠàŠªàŠšàŠŸàŠ° "
+"àŠàŠ¯àŠŒà§àЬ àŠ
àŠàŠ¿àŠà§àŠàŠ€àŠŸàŠà§ àŠà§àŠšà§àŠŠà§àа àŠàаà§à¥€ àŠàŠ®àŠšàŠàŠ¿ àŠ¯àŠŠàŠ¿ àŠàŠªàŠšàŠ¿ àŠàŠàŠ àŠ€à§àŠ€à§àŠ¯àŠŒ àŠªàŠà§àŠ·à§àа àŠà§àаà§àŠ¯àŠŸàŠàŠ¿àŠ "
+"àŠªàŠ°àŠ¿àŠ·à§àŠ¬àŠŸ àŠ¬à§àŠ¯àŠ¬àŠ¹àŠŸàŠ° àŠàŠ°à§ àŠàŠ®àŠš àŠŠà§àŠàŠ¿ àŠàŠ¿àŠšà§àŠš àŠžàŠŸàŠàŠàŠà§àŠ²àŠ¿àŠ° àŠžàŠŸàŠ¥à§ àŠžàŠàНà§àŠà§àŠ€ àŠ¹àŠš, àŠ€àŠ¬à§ àŠàа "
+"àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ°àŠàŠ¿ àŠžàŠŸàŠ®àŠà§àаà§àŠàŠ¿ àŠŠà§àŠàŠ¿ àŠàŠ¿àŠšà§àŠš àŠàа àŠžàŠŸàŠ°à§àŠàŠ¿àŠàŠà§àŠ²àŠ¿àŠ€à§ àŠªàŠ°àŠ¿àŠ¬à§àŠ¶àŠ¿àŠ€ àŠàŠ°àŠ€à§ àŠ¬àŠŸàŠ§à§àН àŠàŠ°àŠ¬à§, "
+"àŠ€àŠŸàŠ àŠà§àаà§àŠ¯àŠŸàŠàŠŸàŠ° àŠàŠŸàŠšà§àŠš àŠšàŠŸ àŠ¯à§ àŠàŠàŠ¯àŠŒ àŠžàŠàНà§àŠ àŠàŠªàŠšàŠŸàŠ° àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ° àŠ¥à§àŠà§ àŠàŠŠà§àŠà§àŠ€ àŠ¹àŠ¬à§à¥€"
+
+#: managing-identities.page:38
+msgid ""
+"On the other hand, all connections to a single website address will be made "
+"over the same Tor circuit, meaning you can browse different pages of a "
+"single website in separate tabs or windows, without any loss of "
+"functionality."
+msgstr ""
+"àŠ
àŠšà§àŠ¯àŠŠàŠ¿àŠà§, àŠàŠàŠ àŠàŠ¯àŠŒà§àŠ¬àŠžàŠŸàŠàŠà§àа àŠžàŠ®àŠžà§àŠ€ àŠ àŠ¿àŠàŠŸàŠšàŠŸ àŠàŠàŠ àŠàа àŠžàŠŸàŠ°à§àŠàŠ¿àŠà§ àŠ€à§àŠ°àŠ¿ àŠàŠ°àŠŸ àŠ¹àŠ¬à§, àŠ¯àŠŸàŠ° "
+"àŠ®àŠŸàŠšà§ àŠàŠªàŠšàŠ¿ àŠàŠŸàŠ°à§àНàŠàŠ°à§ àŠà§àŠš àŠà§àŠ·àŠ€àŠ¿ àŠàŠŸàŠ¡àŠŒàŠŸ àŠªà§àŠ¥àŠ àŠà§àŠ¯àŠŸàŠ¬ àŠ¬àŠŸ àŠàŠàŠšà§àŠ¡à§àŠ€à§ àŠàŠàŠ àŠàŠ¯àŠŒà§àŠ¬àŠžàŠŸàŠàŠà§àа "
+"àŠ¬àŠ¿àŠàŠ¿àŠšà§àŠš àŠªà§àŠ·à§àŠ àŠŸ àŠ¬à§àŠ°àŠŸàŠàŠ àŠàŠ°àŠ€à§ àŠªàŠŸàŠ°à§àŠšà¥€"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: managing-identities.page:46
+msgctxt "_"
+msgid ""
+"external ref='media/managing-identities/circuit_full.png' "
+"md5='bd46d22de952fee42643be46d3f95928'"
+msgstr ""
+"àŠ¬àŠŸàŠ¹à§àŠ¯àŠ¿àŠ àŠ°à§àŠ«='media/managing-identities/circuit_full.png' "
+"md5='bd46d22de952fee42643be46d3f95928'"
+
+#: managing-identities.page:48
+msgid ""
+"You can see a diagram of the circuit that Tor Browser is using for the "
+"current tab in the onion menu."
+msgstr ""
+"àŠàŠªàŠšàŠ¿ àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ° onion àŠ®à§àŠšà§àŠ€à§ àŠ¬àŠ°à§àŠ€àŠ®àŠŸàŠš àŠà§àŠ¯àŠŸàŠ¬à§àа àŠàŠšà§àН àŠ¬à§àŠ¯àŠ¬àŠ¹àŠŸàŠ° àŠàŠ°àŠŸ àŠ¹àŠ¯àŠŒ àŠ¯à§ "
+"àŠ¬àŠ°à§àŠ€àŠšà§ àŠàŠàŠàŠ¿ àŠ¡àŠŸàŠ¯àŠŒàŠŸàŠà§àŠ°àŠŸàŠ® àŠŠà§àŠàŠ€à§ àŠªàŠŸàŠ°à§àŠšà¥€"
+
+#: managing-identities.page:55
+msgid "Logging in over Tor"
+msgstr "Logging in over Tor"
+
+#: managing-identities.page:56
+msgid ""
+"Although Tor Browser is designed to enable total user anonymity on the web, "
+"there may be situations in which it makes sense to use Tor with websites "
+"that require usernames, passwords, or other identifying information."
+msgstr ""
+"àŠ¯àŠŠàŠ¿àŠ àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ°àŠàŠ¿ àŠàŠ¯àŠŒà§àŠ¬à§ àŠžàŠ°à§àЬàŠàŠšà§àŠš àŠ
àŠà§àŠàŠŸàŠ€àŠ€àŠŸ àŠžàŠà§àŠ·àŠ® àŠàŠ°àŠŸàŠ° àŠàŠšà§àН àŠ¡àŠ¿àŠàŠŸàŠàŠš àŠàŠ°àŠŸ "
+"àŠ¹àŠ¯àŠŒà§àŠà§, àŠ€àŠ¬à§ àŠàŠ®àŠš àŠªàŠ°àŠ¿àŠžà§àŠ¥àŠ¿àŠ€àŠ¿àŠ€à§ àŠ¥àŠŸàŠàŠ€à§ àŠªàŠŸàŠ°à§ àŠ¯à§àŠà§àŠ²àŠ¿ àŠàŠ®àŠš àŠàŠ¯àŠŒà§àŠ¬àŠžàŠŸàŠàŠàŠà§àŠ²àŠ¿àŠ° àŠžàŠŸàŠ¥à§ àŠàа "
+"àŠ¬à§àŠ¯àŠ¬àŠ¹àŠŸàŠ° àŠàŠ°àŠ€à§ àŠ¬à§àŠàŠŸàŠ¯àŠŒ àŠ¯àŠŸ àŠ¬à§àŠ¯àŠ¬àŠ¹àŠŸàŠ°àŠàŠŸàŠ°à§àа àŠšàŠŸàŠ®, àŠªàŠŸàŠžàŠàŠ¯àŠŒàŠŸàŠ°à§àŠ¡ àŠ¬àŠŸ àŠ
àŠšà§àН àŠžàŠšàŠŸàŠà§àŠ€àŠàŠŸàŠ°à§ "
+"àŠ€àŠ¥à§àНàŠà§àŠ²àŠ¿àŠ° àŠªà§àŠ°àŠ¯àŠŒà§àŠàŠšà¥€"
+
+#: managing-identities.page:62
+msgid ""
+"If you log into a website using a regular browser, you also reveal your IP "
+"address and geographical location in the process. The same is often true "
+"when you send an email. Logging into your social networking or email "
+"accounts using Tor Browser allows you to choose exactly which information "
+"you reveal to the websites you browse. Logging in using Tor Browser is also "
+"useful if the website you are trying to reach is censored on your network."
+msgstr ""
+"àŠ¯àŠŠàŠ¿ àŠàŠªàŠšàŠ¿ àŠàŠàŠàŠ¿ àŠšàŠ¿àŠ¯àŠŒàŠ®àŠ¿àŠ€ àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ° àŠ¬à§àŠ¯àŠ¬àŠ¹àŠŸàŠ° àŠàŠ°à§ àŠàŠàŠàŠ¿ àŠàŠ¯àŠŒà§àŠ¬àŠžàŠŸàŠàŠ àŠ²àŠ àŠàŠš, àŠàŠªàŠšàŠ¿ "
+"àŠªà§àаàŠà§àŠ°àŠ¿àŠ¯àŠŒàŠŸ àŠàŠªàŠšàŠŸàŠ° IP àŠ àŠ¿àŠàŠŸàŠšàŠŸ àŠàŠ¬àŠ àŠà§àŠàŠ²àŠ¿àŠ àŠ
àŠ¬àŠžà§àŠ¥àŠŸàŠš àŠªà§àаàŠàŠŸàŠ¶à¥€ àŠàŠªàŠšàŠ¿ àŠ¯àŠàŠš àŠàŠàŠàŠ¿ àŠàŠ®à§àв "
+"àŠªàŠŸàŠ àŠŸàŠš àŠ€àŠàŠš àŠàŠàŠ àŠàŠ¥àŠŸ àŠªà§àŠ°àŠŸàŠ¯àŠŒàŠ àŠžàŠ€à§àН àŠ¹àŠ¯àŠŒà¥€ àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ° àŠ¬à§àŠ¯àŠ¬àŠ¹àŠŸàŠ° àŠàŠ°à§ àŠàŠªàŠšàŠŸàŠ° àŠžà§àжà§àŠ¯àŠŸàŠ² "
+"àŠšà§àŠàŠàŠ¯àŠŒàŠŸàŠ°à§àŠàŠ¿àŠ àŠ¬àŠŸ àŠàŠ®à§àŠàв àŠ
à§àŠ¯àŠŸàŠàŠŸàŠàŠšà§àŠà§ àŠ²àŠàŠàŠš àŠàŠ°àŠŸàŠ° àŠ®àŠŸàŠ§à§àŠ¯àŠ®à§ àŠàŠªàŠšàŠ¿ àŠ¯à§ àŠàŠ¯àŠŒà§àŠ¬àŠžàŠŸàŠàŠàŠà§àŠ²àŠ¿ "
+"àŠ¬à§àŠ°àŠŸàŠàŠ àŠàаà§àŠš àŠžà§àŠ àŠ€àŠ¥à§àНàŠà§àŠ²àŠ¿ àŠàŠªàŠšàŠ¿ àŠªà§àаàŠàŠŸàŠ¶ àŠàŠ°àŠ€à§ àŠªàŠŸàŠ°àŠ¬à§àŠšà¥€ àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ° àŠ¬à§àŠ¯àŠ¬àŠ¹àŠŸàŠ° àŠàŠ°à§ àŠ²àŠ"
+" àŠàŠš àŠàŠ°àŠŸàŠ àŠŠàŠ°àŠàŠŸàŠ°à§ àŠ¯àŠŠàŠ¿ àŠàŠªàŠšàŠŸàŠ° àŠàŠŸàŠà§ àŠªà§àŠàŠàŠŸàŠšà§àа àŠà§àŠ·à§àŠàŠŸ àŠàŠ°àŠŸ àŠàŠ¯àŠŒà§àŠ¬àŠžàŠŸàŠàŠàŠàŠ¿ àŠàŠªàŠšàŠŸàŠ° "
+"àŠšà§àŠàŠàŠ¯àŠŒàŠŸàŠ°à§àŠà§àа àŠàŠªàŠ° àŠžà§àŠšà§àŠžàŠ° àŠàŠ°àŠŸ àŠ¹àŠ¯àŠŒà¥€"
+
+#: managing-identities.page:72
+msgid ""
+"When you log in to a website over Tor, there are several points you should "
+"bear in mind:"
+msgstr ""
+"àŠàŠªàŠšàŠ¿ àŠàа àŠàŠªàŠ° àŠàŠàŠàŠ¿ àŠàŠ¯àŠŒà§àŠ¬àŠžàŠŸàŠàŠà§ àŠ²àŠ àŠàŠš àŠàŠ°àŠŸàŠ° àŠžàŠ®àŠ¯àŠŒ, àŠàŠªàŠšàŠ¿ àŠ®àŠšà§ àŠàŠ°àŠŸ àŠàŠàŠ¿àŠ€ àŠ¬àŠ¿àŠàŠ¿àŠšà§àŠš "
+"àŠªàŠ¯àŠŒà§àŠšà§àŠ àŠàŠà§:"
+
+#: managing-identities.page:79
+msgid ""
+"See the <link xref=\"secure-connections\">Secure Connections</link> page for"
+" important information on how to secure your connection when logging in."
+msgstr ""
+"àŠ²àŠ àŠàŠš àŠàŠš àŠàŠ°àŠŸàŠ° àŠžàŠ®àŠ¯àŠŒ àŠà§àŠàŠŸàŠ¬à§ àŠàŠªàŠšàŠŸàŠ° àŠžàŠàНà§àŠ àŠžà§àаàŠà§àŠ·àŠ¿àŠ€ àŠ°àŠŸàŠàŠ€à§ àŠà§àаà§àŠ€à§àŠ¬àŠªà§àаà§àŠ£ àŠ€àŠ¥à§àНà§àа "
+"<link xref=\"secure-connections\">àŠšàŠ¿àŠ°àŠŸàŠªàŠŠ àŠžàŠàНà§àŠàŠà§àŠ²àŠ¿</link> àŠªà§àŠ·à§àŠ àŠŸàŠàŠ¿ àŠŠà§àŠà§àŠšà¥€"
+
+#: managing-identities.page:87
+msgid ""
+"Tor Browser often makes your connection appear as though it is coming from "
+"an entirely different part of the world. Some websites, such as banks or "
+"email providers, might interpret this as a sign that your account has been "
+"hacked or compromised, and lock you out. The only way to resolve this is by "
+"following the siteâs recommended procedure for account recovery, or "
+"contacting the operators and explaining the situation."
+msgstr ""
+"àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ° àŠªà§àŠ°àŠŸàŠ¯àŠŒàŠ àŠàŠªàŠšàŠŸàŠ° àŠžàŠàНà§àŠ àŠªà§àŠ°àŠŠàŠ°à§àŠ¶àŠ¿àŠ€ àŠ¹àŠ¯àŠŒ àŠ¯à§àŠš àŠàŠàŠ¿ àŠ¬àŠ¿àŠ¶à§àЬà§àа àŠàŠàŠàŠ¿ àŠžàŠ®à§àŠªà§àаà§àŠ£ "
+"àŠàŠ¿àŠšà§àŠš àŠ
àŠàж àŠ¥à§àŠà§ àŠàŠžàŠà§à¥€ àŠàŠ¿àŠà§ àŠàŠ¯àŠŒà§àŠ¬àŠžàŠŸàŠàŠ, àŠ¯à§àŠ®àŠš àŠ¬à§àŠ¯àŠŸàŠà§àŠ àŠ¬àŠŸ àŠàŠ®à§àв àŠªà§àŠ°àŠŠàŠŸàŠšàŠàŠŸàŠ°à§, àŠàŠªàŠšàŠŸàŠ° "
+"àŠ
à§àŠ¯àŠŸàŠàŠŸàŠàŠšà§àŠ àŠ¹à§àŠ¯àŠŸàŠ àŠ¬àŠŸ àŠàŠªà§àŠž àŠàŠ°àŠŸ àŠ¹àŠ¯àŠŒà§àŠà§ àŠàŠ®àŠš àŠàŠàŠàŠ¿ àŠàŠ¿àŠ¹à§àŠš àŠ¹àŠ¿àŠžàŠŸàŠ¬à§ àŠàŠàŠ¿ àŠ¬à§àŠ¯àŠŸàŠà§àŠ¯àŠŸ àŠàŠ°àŠ€à§ "
+"àŠªàŠŸàŠ°à§, àŠàŠ¬àŠ àŠàŠªàŠšàŠŸàŠà§ àŠ²àŠ àŠàŠàŠ àŠàŠàŠ¿ àŠžàŠ®àŠŸàŠ§àŠŸàŠš àŠàŠ°àŠŸàŠ° àŠàŠàŠ®àŠŸàŠ€à§àа àŠàŠªàŠŸàŠ¯àŠŒ àŠ
à§àŠ¯àŠŸàŠàŠŸàŠàŠšà§àŠ "
+"àŠªà§àŠšàŠ°à§àŠŠà§àŠ§àŠŸàŠ°à§àа àŠàŠšà§àН àŠžàŠŸàŠàŠà§àа àŠªà§àŠ°àŠžà§àŠ€àŠŸàŠ¬àŠ¿àŠ€ àŠªàŠŠà§àŠ§àŠ€àŠ¿ àŠ
àŠšà§àŠžàŠ°àŠ£ àŠàаà§, àŠ¬àŠŸ àŠ
àŠªàŠŸàŠ°à§àŠàŠ°àŠŠà§àа àŠžàŠŸàŠ¥à§ "
+"àŠ¯à§àŠàŠŸàŠ¯à§àŠ àŠàŠ°àŠŸ àŠàŠ¬àŠ àŠªàŠ°àŠ¿àŠžà§àŠ¥àŠ¿àŠ€àŠ¿ àŠ¬à§àŠ¯àŠŸàŠà§àŠ¯àŠŸ àŠàаà§à¥€"
+
+#: managing-identities.page:101
+msgid "Changing identities and circuits"
+msgstr "àŠžàŠšàŠŸàŠà§àŠ€àŠàŠ°àŠ£ àŠàŠ¬àŠ àŠžàŠŸàŠ°à§àŠàŠ¿àŠ àŠªàŠ°àŠ¿àŠ¬àŠ°à§àŠ€àŠš"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: managing-identities.page:103
+msgctxt "_"
+msgid ""
+"external ref='media/managing-identities/new_identity.png' "
+"md5='15b01e35fa83185d94b57bf0ccf09d76'"
+msgstr ""
+"àŠ¬àŠŸàŠ¹à§àŠ¯àŠ¿àŠ àŠ°à§àŠ«='media/managing-identities/new_identity.png' "
+"md5='15b01e35fa83185d94b57bf0ccf09d76'"
+
+#: managing-identities.page:105
+msgid ""
+"Tor Browser features âNew Identityâ and âNew Tor Circuit for this Siteâ "
+"options, located in the Torbutton menu."
+msgstr ""
+"àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ° àŠ¬à§àŠ¶àŠ¿àŠ·à§àŠà§àН \"àŠšàŠ€à§àŠš àŠªàŠ°àŠ¿àŠàŠ¯àŠŒ\" àŠàŠ¬àŠ \"àŠàŠ àŠžàŠŸàŠàŠà§àа àŠàŠšà§àН àŠšàŠ€à§àŠš àŠàа àŠžàŠŸàŠ°à§àŠàŠ¿àŠ\""
+" àŠ
àŠªàŠ¶àŠš, Torbutton àŠ®à§àŠšà§àŠ€à§ àŠ
àŠ¬àŠžà§àŠ¥àŠ¿àŠ€à¥€"
+
+#: managing-identities.page:111
+msgid "New Identity"
+msgstr "àŠšàŠ€à§àŠš àŠªàŠ°àŠ¿àŠàŠ¯àŠŒ"
+
+#: managing-identities.page:112
+msgid ""
+"This option is useful if you want to prevent your subsequent browser "
+"activity from being linkable to what you were doing before. Selecting it "
+"will close all your open tabs and windows, clear all private information "
+"such as cookies and browsing history, and use new Tor circuits for all "
+"connections. Tor Browser will warn you that all activity and downloads will "
+"be stopped, so take this into account before clicking âNew Identityâ."
+msgstr ""
+"àŠàŠ àŠ¬àŠ¿àŠàвà§àŠªàŠàŠ¿ àŠàŠªàŠàŠŸàŠ°à§ àŠ¯àŠŠàŠ¿ àŠàŠªàŠšàŠ¿ àŠàŠªàŠšàŠŸàŠ° àŠªàŠ°àŠ¬àŠ°à§àŠ€à§ àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ°à§àа àŠà§àŠ°àŠ¿àŠ¯àŠŒàŠŸàŠàŠ²àŠŸàŠªàŠà§ àŠàŠªàŠšàŠ¿ àŠàŠà§ "
+"àŠàŠ¿ àŠàаàŠà§àŠš àŠ€àŠŸ àŠ²àŠ¿àŠà§àŠàНà§àŠà§àН àŠ¹àŠ€à§ àŠªà§àŠ°àŠ€àŠ¿àŠ°à§àЧ àŠàŠ°àŠ€à§ àŠàŠŸàŠàŠ²à§ àŠàŠàŠ¿ àŠšàŠ¿àŠ°à§àŠ¬àŠŸàŠàŠš àŠàŠ°àŠ²à§ àŠàŠªàŠšàŠŸàŠ° àŠžàŠ¬ "
+"àŠà§àŠ²àŠŸ àŠà§àŠ¯àŠŸàŠ¬ àŠàŠ¬àŠ àŠàŠàŠšà§àŠ¡à§ àŠ¬àŠšà§àЧ àŠ¹àŠ¯àŠŒà§ àŠ¯àŠŸàŠ¬à§, àŠà§àŠàŠ¿àŠ àŠàŠ¬àŠ àŠ¬à§àŠ°àŠŸàŠàŠàŠ¿àŠàŠ¯àŠŒà§àа àŠàŠ€àŠ¿àŠ¹àŠŸàŠžà§àа àŠ®àŠ€à§ "
+"àŠžàŠ®àŠžà§àŠ€ àŠ¬à§àНàŠà§àŠ€àŠ¿àŠàŠ€ àŠ€àŠ¥à§àН àŠ®à§àŠà§ àŠ«à§àŠ²àŠŸ àŠ¹àŠ¬à§ àŠàŠ¬àŠ àŠžàŠ®àŠžà§àŠ€ àŠžàŠàНà§àŠàŠà§àŠ²àŠ¿àŠ° àŠàŠšà§àН àŠšàŠ€à§àŠš àŠàа àŠžàŠŸàŠ°à§àŠàŠ¿àŠ"
+" àŠ¬à§àŠ¯àŠ¬àŠ¹àŠŸàŠ° àŠàŠ°àŠ¬à§à¥€ àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ° àŠàŠªàŠšàŠŸàŠà§ àŠžàŠ€àŠ°à§àŠ àŠàŠ°àŠ¬à§ àŠ¯à§ àŠžàŠ®àŠžà§àŠ€ àŠàŠŸàŠ°à§àНàŠàŠ²àŠŸàŠª àŠàŠ¬àŠ "
+"àŠ¡àŠŸàŠàŠšàŠ²à§àŠ¡àŠà§àŠ²àŠ¿ àŠ¬àŠšà§àЧ àŠ¹àŠ¯àŠŒà§ àŠ¯àŠŸàŠ¬à§, àŠ€àŠŸàŠ \"àŠšàŠ€à§àŠš àŠªàŠ°àŠ¿àŠàŠ¯àŠŒ\" àŠà§àŠ²àŠ¿àŠ àŠàŠ°àŠŸàŠ° àŠªà§àаà§àŠ¬à§ àŠàŠàŠ¿ "
+"àŠ¬àŠ¿àŠ¬à§àŠàŠšàŠŸ àŠàаà§àŠšà¥€"
+
+#: managing-identities.page:123
+msgid "New Tor Circuit for this Site"
+msgstr "àŠàŠ àŠžàŠŸàŠàŠà§àа àŠàŠšà§àН àŠšàŠ€à§àŠš àŠàа àŠžàŠŸàŠ°à§àŠàŠ¿àŠ"
+
+#: managing-identities.page:124
+msgid ""
+"This option is useful if the <link xref=\"about-tor-browser#how-tor-"
+"works\">exit relay</link> you are using is unable to connect to the website "
+"you require, or is not loading it properly. Selecting it will cause the "
+"currently-active tab or window to be reloaded over a new Tor circuit. Other "
+"open tabs and windows from the same website will use the new circuit as well"
+" once they are reloaded. This option does not clear any private information "
+"or unlink your activity, nor does it affect your current connections to "
+"other websites."
+msgstr ""
+"àŠªà§àŠ°àŠžà§àŠ¥àŠŸàŠš àŠ°àŠ¿àŠ²à§ àŠàŠ àŠ¬àŠ¿àŠàвà§àŠªàŠàŠ¿ àŠ¯àŠŠàŠ¿ àŠŠàŠ°àŠàŠŸàŠ°à§\n"
+" àŠàŠªàŠšàŠ¿ àŠ¬à§àŠ¯àŠ¬àŠ¹àŠŸàŠ° àŠàаàŠà§àŠš àŠàŠªàŠšàŠŸàŠ° àŠªà§àŠ°àŠ¯àŠŒà§àŠàŠšà§àŠ¯àŠŒ àŠàŠ¯àŠŒà§àŠ¬àŠžàŠŸàŠàŠà§àа àŠžàŠŸàŠ¥à§ àŠžàŠàНà§àŠ àŠàŠ°àŠ€à§ àŠ
àŠà§àŠ·àŠ®, àŠ
àŠ¥àŠ¬àŠŸ àŠàŠàŠ¿ àŠžàŠ àŠ¿àŠàŠàŠŸàŠ¬à§ àŠ²à§àŠ¡ àŠàŠ°àŠŸ àŠ¹àŠà§àŠà§ àŠšàŠŸà¥€ àŠàŠàŠ¿ àŠšàŠ¿àŠ°à§àŠ¬àŠŸàŠàŠš àŠàŠ°àŠ²à§ àŠ¬àŠ°à§àŠ€àŠ®àŠŸàŠšà§-àŠžàŠà§àŠ°àŠ¿àŠ¯àŠŒ àŠà§àŠ¯àŠŸàŠ¬ àŠ¬àŠŸ àŠàŠàŠšà§àŠ¡à§àŠàŠ¿ àŠàŠàŠàŠ¿ àŠšàŠ€à§àŠš àŠàа àŠžàŠŸàŠ°à§àŠàŠ¿àŠà§ àŠªà§àŠšàŠ°àŠŸàŠ¯àŠŒ àŠ²à§àŠ¡ àŠ¹àŠ¬à§à¥€ àŠàŠàŠ àŠàŠ¯àŠŒà§àŠ¬àŠžàŠŸàŠàŠ àŠ¥à§àŠà§ àŠ
àŠšà§àН àŠà§àŠ²àŠŸ àŠà§àŠ¯àŠŸàŠ¬ àŠàŠ¬àŠ àŠàŠàŠšà§àŠ¡à§àŠà§àŠ²àŠ¿ àŠšàŠ€à§àŠš àŠžàŠŸàŠ°à§àŠàŠ¿àŠ àŠ¬à§àŠ¯àŠ¬àŠ¹àŠŸàŠ° àŠàŠ°à§ àŠàŠàŠ¬àŠŸàŠ° àŠžà§àŠà§àŠ²àŠ¿ àŠªà§àŠšàŠ°àŠŸàŠ¯àŠŒ àŠ²à§àŠ¡ àŠ¹àŠ¬à§à¥€ àŠàŠ àŠ¬àŠ¿àŠàвà§àŠªàŠàŠ¿ àŠà§àŠšàŠ àŠ¬à§àНàŠà§àŠ€àŠ¿àŠàŠ€ àŠ€àŠ¥à§àН àŠžàŠŸàŠ« àŠàŠ°à§ àŠšàŠŸ àŠ¬àŠŸ àŠàŠªàŠšàŠŸàŠ° àŠàŠŸàŠ°à§àНàŠàŠ²àŠŸàŠªàŠà§ àŠ²àŠ¿àŠà
§àŠàŠ®à§àŠà§àŠ€ àŠàŠ°à§ àŠšàŠŸ, àŠàŠàŠ¿ àŠàŠªàŠšàŠŸàŠ° àŠ¬àŠ°à§àŠ€àŠ®àŠŸàŠš àŠžàŠàНà§àŠàŠà§àŠ²àŠ¿ àŠ
àŠšà§àŠ¯àŠŸàŠšà§àН àŠàŠ¯àŠŒà§àŠ¬àŠžàŠŸàŠàŠàŠà§àŠ²àŠ¿àŠ€à§àŠ àŠªà§àаàŠàŠŸàŠ¬àŠ¿àŠ€ àŠàŠ°à§ àŠšàŠŸà¥€"
+
+#: onionsites.page:6
+msgid "Services that are only accessible using Tor"
+msgstr "àŠªàŠ°àŠ¿àŠ·à§àŠ¬àŠŸàŠà§àŠ²àŠ¿ àŠà§àŠ¬àŠ² àŠàа àŠ¬à§àŠ¯àŠ¬àŠ¹àŠŸàŠ° àŠàŠ°à§ àŠ
à§àŠ¯àŠŸàŠà§àŠžà§àŠžàŠ¯à§àŠà§àН"
+
+#: onionsites.page:10
+msgid "Onion Services"
+msgstr "Onion àŠžà§àŠ¬àŠŸ"
+
+#: onionsites.page:11
+msgid ""
+"Onion services (formerly known as âhidden servicesâ) are services (like "
+"websites) that are only accessible through the Tor network."
+msgstr ""
+"Onion àŠªàŠ°àŠ¿àŠ·à§àŠ¬àŠŸàŠà§àŠ²àŠ¿ (àŠªà§àаà§àŠ¬à§ \"àŠ²à§àŠàŠŸàŠšà§ àŠªàŠ°àŠ¿àŠ·à§àŠ¬àŠŸàŠà§àŠ²àŠ¿\" àŠšàŠŸàŠ®à§ àŠªàŠ°àŠ¿àŠàŠ¿àŠ€) àŠžà§àŠ¬àŠŸàŠà§àŠ²àŠ¿ (àŠ¯à§àŠ®àŠš"
+" àŠàŠ¯àŠŒà§àŠ¬àŠžàŠŸàŠàŠ) àŠ¯àŠŸ àŠàа àŠšà§àŠàŠàŠ¯àŠŒàŠŸàŠ°à§àŠ àŠàа àŠ®àŠŸàŠ§à§àŠ¯àŠ®à§ àŠ
à§àŠ¯àŠŸàŠà§àŠžà§àŠžàŠ¯à§àŠà§àŠ¯à¥€"
+
+#: onionsites.page:16
+msgid ""
+"Onion services offer several advantages over ordinary services on the non-"
+"private web:"
+msgstr ""
+"Onion àŠªàŠ°àŠ¿àŠ·à§àŠ¬àŠŸàŠà§àŠ²àŠ¿ àŠ
-àŠªà§àŠ°àŠŸàŠàŠà§àŠ àŠàŠ¯àŠŒà§àЬà§àа àŠžàŠŸàŠ§àŠŸàŠ°àŠ£ àŠªàŠ°àŠ¿àŠ·à§àŠ¬àŠŸàŠà§àŠ²àŠ¿àŠ° àŠàŠªàŠ° àŠ
àŠšà§àŠ àŠžà§àŠ¬àŠ¿àŠ§àŠŸ "
+"àŠªà§àŠ°àŠŠàŠŸàŠš àŠàаà§:"
+
+#: onionsites.page:23
+msgid ""
+"An onion servicesâs location and IP address are hidden, making it difficult "
+"for adversaries to censor it or identify its operators."
+msgstr ""
+"àŠàŠàŠàŠ¿ onion àŠªàŠ°àŠ¿àŠ·à§àŠ¬àŠŸàŠà§àŠ²àŠ¿àŠ° àŠ
àŠ¬àŠžà§àŠ¥àŠŸàŠš àŠàŠ¬àŠ IP àŠ àŠ¿àŠàŠŸàŠšàŠŸ àŠ²à§àŠàŠŸàŠšà§ àŠàŠà§, àŠ¬àŠ¿àŠ°à§àЧà§àŠŠà§àа àŠªàŠà§àŠ·à§ "
+"àŠàŠàŠ¿ àŠžà§àŠšà§àŠžàŠ° àŠàŠ°àŠŸ àŠ¬àŠŸ àŠ€àŠŸàŠ° àŠ
àŠªàŠŸàŠ°à§àŠàŠ°àŠŠà§àа àŠžàŠšàŠŸàŠà§àŠ€ àŠàŠ°àŠŸ àŠàŠ àŠ¿àŠš àŠàŠ°à§ àŠ€à§àвà§à¥€"
+
+#: onionsites.page:29
+msgid ""
+"All traffic between Tor users and onion services is end-to-end encrypted, so"
+" you do not need to worry about <link xref=\"secure-connections\">connecting"
+" over HTTPS</link>."
+msgstr ""
+"àŠàа àŠ¬à§àŠ¯àŠ¬àŠ¹àŠŸàŠ°àŠàŠŸàŠ°à§àŠŠà§àа àŠàŠ¬àŠ onion àŠªàŠ°àŠ¿àŠ·à§àŠ¬àŠŸàŠà§àŠ²àŠ¿àŠ° àŠ®àŠ§à§àŠ¯à§ àŠžàŠ®àŠžà§àŠ€ àŠà§àаà§àŠ¯àŠŸàŠ«àŠ¿àŠ àŠ¶à§àŠ·-àŠ¥à§àŠà§-àŠ¶à§àŠ· "
+"àŠàŠšàŠà§àŠ°àŠ¿àŠªà§àŠ àŠ¹àŠ¯àŠŒà§àŠà§, àŠ€àŠŸàŠ àŠàŠªàŠšàŠŸàŠà§ HTTPS àŠàа àŠžàŠŸàŠ¥à§ àŠžàŠàНà§àŠà§àа àŠ¬àŠ¿àŠ·àŠ¯àŠŒà§ àŠàŠ¿àŠšà§àŠ€àŠŸ àŠàŠ°àŠ€à§ àŠ¹àŠ¬à§ "
+"àŠšàŠŸà¥€"
+
+#: onionsites.page:36
+msgid ""
+"The address of an onion service is automatically generated, so the operators"
+" do not need to purchase a domain name; the .onion URL also helps Tor ensure"
+" that it is connecting to the right location and that the connection is not "
+"being tampered with."
+msgstr ""
+"àŠàŠàŠàŠ¿ onion àŠªàŠ°àŠ¿àŠ·à§àŠ¬àŠŸ àŠ àŠ¿àŠàŠŸàŠšàŠŸ àŠžà§àŠ¬àŠ¯àŠŒàŠàŠà§àŠ°àŠ¿àŠ¯àŠŒàŠàŠŸàŠ¬à§ àŠàŠ€à§àŠªàŠšà§àŠš àŠ¹àŠ¯àŠŒ, àŠ€àŠŸàŠ àŠ
àŠªàŠŸàŠ°à§àŠàа àŠàŠàŠàŠ¿ "
+"àŠ¡à§àŠ®à§àŠš àŠšàŠŸàŠ® àŠà§àŠ°àŠ¯àŠŒ àŠàŠ°àŠ€à§ àŠ¹àŠ¬à§ àŠšàŠŸ; .àŠàŠš àŠàŠàŠàаàŠàв àŠàаàŠà§ àŠšàŠ¿àŠ¶à§àŠàŠ¿àŠ€ àŠàŠ°à§ àŠ¯à§ àŠàŠàŠ¿ àŠžàŠ àŠ¿àŠ "
+"àŠ
àŠ¬àŠžà§àŠ¥àŠŸàŠšà§àа àŠžàŠŸàŠ¥à§ àŠžàŠàНà§àŠ àŠžà§àŠ¥àŠŸàŠªàŠš àŠàаàŠà§ àŠàŠ¬àŠ àŠžàŠàНà§àŠ àŠ¬àŠ¿àŠà§àŠàŠ¿àŠšà§àŠš àŠàŠ°àŠŸ àŠ¹àŠà§àŠà§ àŠšàŠŸà¥€"
+
+#: onionsites.page:46
+msgid "How to access an onion service"
+msgstr "àŠàŠàŠàŠ¿ onion àŠªàŠ°àŠ¿àŠ·à§àŠ¬àŠŸ àŠ
à§àŠ¯àŠŸàŠà§àŠžà§àŠž àŠàŠ¿àŠàŠŸàŠ¬à§"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: onionsites.page:48
+msgctxt "_"
+msgid ""
+"external ref='media/onionsites/onion_url.png' "
+"md5='f97f7fe10f07c3959c4430934974bbaa'"
+msgstr ""
+"àŠ¬àŠŸàŠ¹à§àŠ¯àŠ¿àŠ àŠ°à§àŠ«='media/onionsites/onion_url.png' "
+"md5='f97f7fe10f07c3959c4430934974bbaa'"
+
+#: onionsites.page:50
+msgid ""
+"Just like any other website, you will need to know the address of an onion "
+"service in order to connect to it. An onion address is a string of sixteen "
+"mostly random letters and numbers, followed by â.onionâ."
+msgstr ""
+"àŠ
àŠšà§àН àŠà§àŠšàŠ àŠàŠ¯àŠŒà§àŠ¬àŠžàŠŸàŠàŠà§àа àŠ®àŠ€àŠ, àŠàŠªàŠšàŠŸàŠ° àŠžàŠŸàŠ¥à§ àŠžàŠàНà§àŠ àŠžà§àŠ¥àŠŸàŠªàŠšà§àа àŠàŠšà§àН àŠàŠàŠàŠ¿ àŠªà§àŠàŠ¯àŠŒàŠŸàŠ "
+"àŠªàŠ°àŠ¿àŠ·à§àŠ¬àŠŸàŠàŠ¿àŠ° àŠ àŠ¿àŠàŠŸàŠšàŠŸ àŠàŠŸàŠšàŠ€à§ àŠ¹àŠ¬à§à¥€ àŠàŠàŠàŠ¿ onion àŠ àŠ¿àŠàŠŸàŠšàŠŸ àŠ¹àŠ² àŠ¬à§àŠ¶àŠ¿àŠ°àŠàŠŸàŠ àŠ°à§àŠ¯àŠŸàŠšà§àŠ¡àŠ® àŠ
àŠà§àŠ·àŠ° "
+"àŠàŠ¬àŠ àŠžàŠàŠà§àŠ¯àŠŸàŠ° àŠàŠàŠàŠ¿ àŠžà§àŠà§àŠ°àŠ¿àŠâ.onionâी"
+
+#: onionsites.page:58 troubleshooting.page:10
+msgid "Troubleshooting"
+msgstr "àŠžàŠ®àŠžà§àŠ¯àŠŸ àŠžàŠ®àŠŸàŠ§àŠŸàŠš"
+
+#: onionsites.page:59
+msgid ""
+"If you cannot reach the onion service you require, make sure that you have "
+"entered the 16-character onion address correctly: even a small mistake will "
+"stop Tor Browser from being able to reach the site."
+msgstr ""
+"àŠàŠªàŠšàŠ¿ àŠ¯àŠŠàŠ¿ àŠªà§àŠàŠ¯àŠŒàŠŸàŠ àŠªàŠ°àŠ¿àŠ·à§àŠ¬àŠŸàŠ€à§ àŠªà§àŠàŠàŠŸàŠ€à§ àŠšàŠŸ àŠªàŠŸàŠ°à§àŠš, àŠ€àŠ¬à§ àŠšàŠ¿àŠ¶à§àŠàŠ¿àŠ€ àŠàаà§àŠš àŠ¯à§ àŠàŠªàŠšàŠ¿ "
+"16-àŠ
àŠà§àŠ·àŠ°à§àа àŠªà§àŠàŠš àŠ àŠ¿àŠàŠŸàŠšàŠŸàŠàŠ¿ àŠžàŠ àŠ¿àŠàŠàŠŸàŠ¬à§ àŠ²àŠ¿àŠà§àŠà§àŠš: àŠàŠ®àŠšàŠàŠ¿ àŠàŠàŠàŠ¿ àŠà§àŠ àŠà§àв àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ°àŠàŠ¿ "
+"àŠžàŠŸàŠàŠà§ àŠªà§àŠàŠàŠŸàŠ€à§ àŠžàŠà§àŠ·àŠ® àŠ¹àŠ¬à§àŠšàŠŸà¥€"
+
+#: onionsites.page:64
+msgid ""
+"If you are still unable to connect to the onion service, please try again "
+"later. There may be a temporary connection issue, or the site operators may "
+"have allowed it to go offline without warning."
+msgstr ""
+"àŠ¯àŠŠàŠ¿ àŠàŠªàŠšàŠ¿ àŠàŠàŠšàŠ àŠªà§àŠàŠ¯àŠŒàŠŸàŠ àŠªàŠ°àŠ¿àŠ·à§àŠ¬àŠŸ àŠžàŠàНà§àŠ àŠàŠ°àŠ€à§ àŠ
àŠà§àŠ·àŠ® àŠ¹àŠš, àŠ€àŠŸàŠ¹àŠ²à§ àŠªàŠ°à§ àŠàŠ¬àŠŸàŠ° àŠà§àŠ·à§àŠàŠŸ "
+"àŠàаà§àŠšà¥€ àŠàŠàŠàŠ¿ àŠ
àŠžà§àŠ¥àŠŸàŠ¯àŠŒà§ àŠžàŠàНà§àŠ àŠžàŠ®àŠžà§àŠ¯àŠŸ àŠ¹àŠ€à§ àŠªàŠŸàŠ°à§, àŠ¬àŠŸ àŠžàŠŸàŠàŠ àŠ
àŠªàŠŸàŠ°à§àŠàа àŠàŠàŠ¿ àŠžàŠ€àŠ°à§àŠàŠ¬àŠŸàŠ°à§àŠ€àŠŸ "
+"àŠàŠŸàŠ¡àŠŒàŠŸ àŠ
àŠ«àŠ²àŠŸàŠàŠšà§ àŠ¯à§àŠ€à§ àŠ
àŠšà§àŠ®àŠ€àŠ¿ àŠŠà§àŠàŠ¯àŠŒàŠŸ àŠ¹àŠ€à§ àŠªàŠŸàŠ°à§à¥€"
+
+#: onionsites.page:69
+msgid ""
+"You can also ensure that you're able to access other onion services by "
+"connecting to <link href=\"http://3g2upl4pq6kufc4m.onion/\">DuckDuckGo's "
+"Onion Service</link>"
+msgstr ""
+"àŠàŠªàŠšàŠ¿ àŠšàŠ¿àŠ¶à§àŠàŠ¿àŠ€ àŠàŠ°àŠ€à§ àŠªàŠŸàŠ°à§àŠš àŠ¯à§ àŠàŠªàŠšàŠ¿ <link "
+"href=\"http://3g2upl4pq6kufc4m.onion/\">DuckDuckGo's Onion</link> àŠªàŠ°àŠ¿àŠ·à§àŠ¬àŠŸàŠ€à§ "
+"àŠžàŠàНà§àŠà§àŠ€ àŠàŠ°à§ àŠ
àŠšà§àŠ¯àŠŸàŠšà§àН àŠªà§àŠàŠ¯àŠŒàŠŸàŠ àŠªàŠ°àŠ¿àŠ·à§àŠ¬àŠŸàŠà§àŠ²àŠ¿ àŠ
à§àŠ¯àŠŸàŠà§àŠžà§àŠž àŠàŠ°àŠ€à§ àŠžàŠà§àŠ·àŠ® àŠ¹àŠà§àŠà§àŠš"
+
+#: plugins.page:6
+msgid "How Tor Browser handles add-ons, plugins and JavaScript"
+msgstr "àŠàŠ¿àŠàŠŸàŠ¬à§ àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ° àŠ
à§àŠ¯àŠŸàŠ¡-àŠ
àŠš, àŠªà§àŠ²àŠŸàŠàŠàŠš àŠàŠ¬àŠ àŠàŠŸàŠàŠŸàŠžà§àŠà§àŠ°àŠ¿àŠªà§àŠ àŠªàŠ°àŠ¿àŠàŠŸàŠ²àŠšàŠŸ àŠàаà§"
+
+#: plugins.page:10
+msgid "Plugins, add-ons and JavaScript"
+msgstr "àŠªà§àŠ²àŠŸàŠàŠàŠš, àŠ
à§àŠ¯àŠŸàŠ¡-àŠ
àŠš àŠàŠ¬àŠ àŠàŠŸàŠàŠŸàŠžà§àŠà§àŠ°àŠ¿àŠªà§àŠ"
+
+#: plugins.page:13
+msgid "Flash Player"
+msgstr "àŠ«à§àвà§àŠ¯àŠŸàŠ¶ àŠªà§àвà§àŠ¯àŠŒàŠŸàŠ°"
+
+#: plugins.page:14
+msgid ""
+"Video websites, such as Vimeo make use of the Flash Player plugin to display"
+" video content. Unfortunately, this software operates independently of Tor "
+"Browser and cannot easily be made to obey Tor Browserâs proxy settings. It "
+"can therefore reveal your real location and IP address to the website "
+"operators, or to an outside observer. For this reason, Flash is disabled by "
+"default in Tor Browser, and enabling it is not recommended."
+msgstr ""
+"àŠàŠ¿àŠ¡àŠ¿àŠ àŠàŠ¯àŠŒà§àŠ¬àŠžàŠŸàŠàŠàŠà§àŠ²àŠ¿, àŠ¯à§àŠ®àŠš àŠàŠ¿àŠ®àŠ¿àŠ àŠàŠ¿àŠ¡àŠ¿àŠ àŠžàŠŸàŠ®àŠà§àŠ°à§ àŠªà§àŠ°àŠŠàŠ°à§àŠ¶àŠšà§àа àŠàŠšà§àН àŠ«à§àвà§àŠ¯àŠŸàŠ¶ "
+"àŠªà§àвà§àŠ¯àŠŒàŠŸàŠ° àŠªà§àŠ²àŠŸàŠàŠàŠš àŠ¬à§àŠ¯àŠ¬àŠ¹àŠŸàŠ° àŠàаà§à¥€ àŠŠà§àаà§àŠàŠŸàŠà§àŠ¯àŠ¬àŠ¶àŠ€, àŠàŠ àŠžàŠ«àŠàŠàŠ¯àŠŒà§àŠ¯àŠŸàŠ°àŠàŠ¿ àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ°à§àа "
+"àŠžà§àŠ¬àŠŸàŠ§à§àŠšàŠàŠŸàŠ¬à§ àŠàŠŸàŠ àŠàŠ°à§ àŠàŠ¬àŠ àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ°à§àа àŠªà§àаàŠà§àŠžàŠ¿ àŠžà§àŠàŠ¿àŠàŠžàŠà§àŠ²àŠ¿ àŠªàŠŸàŠ²àŠš àŠàŠ°àŠ€à§ àŠžàŠ¹àŠà§àŠ àŠàŠ°àŠŸ"
+" àŠ¯àŠŸàŠ¯àŠŒ àŠšàŠŸà¥€ àŠàŠàŠ¿ àŠàŠªàŠšàŠŸàŠ° àŠàŠ¯àŠŒà§àŠ¬àŠžàŠŸàŠàŠ àŠàŠ¬àŠ àŠ
àŠªàŠŸàŠ°à§àŠàŠ°àŠŠà§àа àŠàŠŸàŠà§ àŠàŠªàŠšàŠŸàŠ° àŠªà§àаàŠà§àŠ€ àŠ
àŠ¬àŠžà§àŠ¥àŠŸàŠš àŠ IP "
+"àŠ àŠ¿àŠàŠŸàŠšàŠŸ àŠªà§àаàŠàŠŸàŠ¶ àŠàŠ°àŠ€à§ àŠªàŠŸàŠ°à§, àŠ
àŠ¥àŠ¬àŠŸ àŠ¬àŠŸàŠàаà§àа àŠªàŠ°à§àŠ¯àŠ¬à§àŠà§àŠ·àŠ àŠ¹àŠ€à§ àŠªàŠŸàŠ°à§à¥€ àŠàŠ àŠàŠŸàŠ°àŠ£à§, àŠàŠ°à§ "
+"àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ°à§ àŠ«à§àвà§àŠ¯àŠŸàŠ¶ àŠ¡àŠ¿àŠ«àŠ²à§àŠàŠàŠŸàŠ¬à§ àŠšàŠ¿àŠ·à§àŠà§àŠ°àŠ¿àŠ¯àŠŒ àŠàŠ°àŠŸ àŠ¹àŠ¯àŠŒà§àŠà§, àŠàŠ¬àŠ àŠžàŠà§àŠ·àŠ® àŠàŠ°àŠŸ àŠàŠàŠ¿àŠ° "
+"àŠªà§àŠ°àŠžà§àŠ€àŠŸàŠ¬àŠ¿àŠ€ àŠšàŠ¯àŠŒà¥€"
+
+#: plugins.page:23
+msgid ""
+"Some video websites (such as YouTube) offer alternative video delivery "
+"methods that do not use Flash. These methods may be compatible with Tor "
+"Browser."
+msgstr ""
+"àŠàŠ¿àŠà§ àŠàŠ¿àŠ¡àŠ¿àŠ àŠàŠ¯àŠŒà§àŠ¬àŠžàŠŸàŠàŠ (àŠ¯à§àŠ®àŠš àŠàŠàŠàŠ¿àŠàЬ) àŠ«à§àвà§àŠ¯àŠŸàŠ¶ àŠ¬à§àŠ¯àŠ¬àŠ¹àŠŸàŠ° àŠàŠ°à§ àŠšàŠŸ àŠàŠ®àŠš àŠ¬àŠ¿àŠàвà§àŠª àŠàŠ¿àŠ¡àŠ¿àŠ "
+"àŠ¬àŠ¿àŠ€àŠ°àŠ£ àŠªàŠŠà§àŠ§àŠ€àŠ¿ àŠªà§àŠ°àŠžà§àŠ€àŠŸàŠ¬ àŠàаà§à¥€ àŠàŠ àŠªàŠŠà§àŠ§àŠ€àŠ¿àŠà§àŠ²àŠ¿ àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ°à§àа àŠžàŠŸàŠ¥à§ àŠžàŠŸàŠ®àŠà§àŠàŠžà§àŠ¯àŠªà§àаà§àŠ£ "
+"àŠ¹àŠ€à§ àŠªàŠŸàŠ°à§à¥€"
+
+#: plugins.page:31
+msgid "JavaScript"
+msgstr "JavaScript"
+
+#: plugins.page:32
+msgid ""
+"JavaScript is a programming language that websites use to offer interactive "
+"elements such as video, animation, audio, and status timelines. "
+"Unfortunately, JavaScript can also enable attacks on the security of the "
+"browser, which might lead to deanonymization."
+msgstr ""
+"àŠàŠŸàŠàŠŸàŠžà§àŠà§àŠ°àŠ¿àŠªà§àŠ àŠàŠàŠàŠ¿ àŠªà§àаà§àŠà§àŠ°àŠŸàŠ®àŠ¿àŠ àŠàŠŸàŠ·àŠŸ àŠ¯àŠŸ àŠàŠ¯àŠŒà§àŠ¬àŠžàŠŸàŠàŠàŠà§àŠ²àŠ¿ àŠàŠšà§àŠàŠŸàŠ°àŠ
à§àŠ¯àŠŸàŠà§àŠàŠ¿àŠ "
+"àŠàŠªàŠŸàŠŠàŠŸàŠšàŠà§àŠ²àŠ¿ àŠ¯à§àŠ®àŠš àŠàŠ¿àŠ¡àŠ¿àŠ, àŠ
à§àŠ¯àŠŸàŠšàŠ¿àŠ®à§àŠ¶àŠš, àŠ
àŠ¡àŠ¿àŠ, àŠàŠ¬àŠ àŠžà§àŠ¥àŠ¿àŠ€àŠ¿ àŠžàŠ®àŠ¯àŠŒàŠžà§àŠ®àŠŸ àŠªà§àŠ°àŠŠàŠŸàŠš àŠàŠ°àŠ€à§ "
+"àŠ¬à§àŠ¯àŠ¬àŠ¹àŠŸàŠ° àŠàаà§à¥€ àŠŠà§àаà§àŠàŠŸàŠà§àŠ¯àŠ¬àŠ¶àŠ€, àŠàŠŸàŠàŠŸàŠžà§àŠà§àŠ°àŠ¿àŠªà§àŠ àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ°à§àа àŠšàŠ¿àŠ°àŠŸàŠªàŠ€à§àŠ€àŠŸàŠ° àŠàŠªàŠ° "
+"àŠàŠà§àŠ°àŠ®àŠ£àŠà§àŠ²àŠ¿ àŠžàŠà§àŠ°àŠ¿àŠ¯àŠŒ àŠàŠ°àŠ€à§ àŠªàŠŸàŠ°à§, àŠ¯àŠŸ àŠ¡àŠ¿àŠšàŠŸàŠ®àŠŸàŠàŠ®àŠŸàŠàŠà§àŠ¶àŠš àŠ¹àŠ€à§ àŠªàŠŸàŠ°à§à¥€"
+
+#: plugins.page:39
+msgid ""
+"Tor Browser includes an add-on called NoScript, accessed through the âSâ "
+"icon at the top-left of the window, which allows you to control the "
+"JavaScript that runs on individual web pages, or to block it entirely."
+msgstr ""
+"àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ°à§ àŠšà§àŠàŠªà§àŠ¯àŠŸàŠ¡ àŠšàŠŸàŠ®à§ àŠàŠàŠàŠ¿ àŠ
à§àŠ¯àŠŸàŠ¡-àŠ
àŠš àŠ°àŠ¯àŠŒà§àŠà§, àŠ¯àŠŸ àŠàŠàŠšà§àŠ¡à§àŠàŠ¿àŠ° àŠàŠªàŠ°à§ àŠ¬àŠŸàŠ®à§ "
+"\"àŠàŠž\" àŠàŠàŠàŠš àŠŠà§àŠ¬àŠŸàŠ°àŠŸ àŠ
à§àŠ¯àŠŸàŠà§àŠžà§àŠž àŠàаà§, àŠ¯àŠŸ àŠàŠªàŠšàŠŸàŠà§ àŠàŠŸàŠàŠŸàŠžà§àŠà§àŠ°àŠ¿àŠªà§àŠ àŠšàŠ¿àŠ¯àŠŒàŠšà§àŠ€à§àŠ°àŠ£ àŠàŠ°àŠ€à§ "
+"àŠŠà§àŠ¯àŠŒ àŠ¯àŠŸ àŠªà§àŠ¥àŠ àŠàŠ¯àŠŒà§àЬ àŠªà§àŠàŠà§àŠ²àŠ¿àŠ€à§ àŠàŠŸàŠ²àŠŸàŠ¯àŠŒ, àŠ
àŠ¥àŠ¬àŠŸ àŠàŠàŠ¿ àŠžàŠ®à§àŠªà§àаà§àŠ£àŠàŠŸàŠ¬à§ àŠ¬à§àŠ²àŠ àŠàŠ°àŠ€à§ àŠŠà§àŠ¯àŠŒà¥€"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: plugins.page:45
+msgctxt "_"
+msgid ""
+"external ref='media/plugins/noscript_menu.png' "
+"md5='df9e684b76a3c2e2bdcb879a19c20471'"
+msgstr ""
+"àŠ¬àŠŸàŠ¹à§àŠ¯àŠ¿àŠ àŠ°à§àŠ«='media/plugins/noscript_menu.png' "
+"md5='df9e684b76a3c2e2bdcb879a19c20471'"
+
+#: plugins.page:47
+msgid ""
+"Users who require a high degree of security in their web browsing should set"
+" Tor Browserâs <link xref=\"security-slider\">Security Slider</link> to "
+"âMedium-Highâ (which disables JavaScript for non-HTTPS websites) or âHighâ "
+"(which does so for all websites). However, disabling JavaScript will prevent"
+" many websites from displaying correctly, so Tor Browserâs default setting "
+"is to allow all websites to run scripts."
+msgstr ""
+"àŠ¬à§àŠ¯àŠ¬àŠ¹àŠŸàŠ°àŠàŠŸàŠ°à§àŠ°àŠŸ, àŠ¯àŠŸàŠ°àŠŸ àŠ€àŠŸàŠŠà§àа àŠàŠ¯àŠŒà§àЬ àŠ¬à§àŠ°àŠŸàŠàŠàŠ¿àŠàŠ¯àŠŒà§àа àŠ®àŠ§à§àŠ¯à§ àŠàŠà§àŠàŠ€àŠ° àŠšàŠ¿àŠ°àŠŸàŠªàŠ€à§àŠ€àŠŸ àŠªà§àŠ°àŠ¯àŠŒà§àŠàŠš"
+" àŠ€àŠŸàŠŠà§àа àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ°à§àа àŠžàŠ¿àŠàŠ¿àŠàŠ°àŠ¿àŠàŠ¿ àŠžà§àŠ²àŠŸàŠàŠ¡àŠŸàŠ°àŠà§ \"àŠ®àŠŸàŠàŠŸàŠ°àŠ¿ àŠàŠà§àŠ\" (àŠ¯àŠŸ àŠ
-HTTPS "
+"àŠàŠ¯àŠŒà§àŠ¬àŠžàŠŸàŠàŠà§àа àŠàŠšà§àН JavaScript àŠšàŠ¿àŠ·à§àŠà§àŠ°àŠ¿àŠ¯àŠŒ àŠàаà§) àŠ¬àŠŸ \"àŠ¹àŠŸàŠ\" (àŠ¯àŠŸ àŠžàŠ®àŠžà§àŠ€ "
+"àŠàŠ¯àŠŒà§àŠ¬àŠžàŠŸàŠàŠàŠà§àŠ²àŠ¿àŠ° àŠàŠšà§àН àŠ€àŠŸàŠ àŠàаà§) -àŠ àŠàŠ°àŠŸ àŠàŠàŠ¿àŠ€à¥€ àŠ¯àŠŸàŠàйà§àŠ, àŠàŠŸàŠàŠŸàŠžà§àŠà§àŠ°àŠ¿àŠªà§àŠ àŠšàŠ¿àŠ·à§àŠà§àŠ°àŠ¿àŠ¯àŠŒ "
+"àŠàŠ°àŠŸ àŠ
àŠšà§àŠ àŠàŠ¯àŠŒà§àŠ¬àŠžàŠŸàŠàŠ àŠžàŠ àŠ¿àŠàŠàŠŸàŠ¬à§ àŠªà§àŠ°àŠŠàŠ°à§àŠ¶àŠš àŠàŠ°àŠŸ àŠªà§àŠ°àŠ€àŠ¿àŠ°à§àЧ àŠàŠ°àŠ¬à§, àŠ€àŠŸàŠ àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ°à§àа "
+"àŠ¡àŠ¿àŠ«àŠ²à§àŠ àŠžà§àŠàŠ¿àŠ àŠžàŠ®àŠžà§àŠ€ àŠàŠ¯àŠŒà§àŠ¬àŠžàŠŸàŠàŠ àŠžà§àŠà§àŠ°àŠ¿àŠªà§àŠ àŠàŠŸàŠ²àŠŸàŠšà§àа àŠ
àŠšà§àŠ®àŠ€àŠ¿ àŠŠà§àŠ¯àŠŒà¥€"
+
+#: plugins.page:58
+msgid "Browser Add-ons"
+msgstr "àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ° àŠ
à§àŠ¯àŠŸàŠ¡-àŠ
àŠš"
+
+#: plugins.page:59
+msgid ""
+"Tor Browser is based on Firefox, and any browser add-ons or themes that are "
+"compatible with Firefox can also be installed in Tor Browser."
+msgstr ""
+"àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ° àŠ«àŠŸàŠ¯àŠŒàŠŸàŠ°àŠ«àŠà§àŠž àŠàŠ¿àŠ€à§àŠ€àŠ¿àŠ àŠàŠ¬àŠ àŠ«àŠŸàŠ¯àŠŒàŠŸàŠ°àŠ«àŠà§àŠžà§àа àŠžàŠŸàŠ¥à§ àŠžàŠŸàŠ®àŠà§àŠàŠžà§àŠ¯àŠªà§àаà§àŠ£ àŠà§àŠšà§ "
+"àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ° àŠ
à§àŠ¯àŠŸàŠ¡-àŠ
àŠš àŠ¬àŠŸ àŠ¥àŠ¿àŠ® àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ°à§ àŠàŠšàŠžà§àŠàв àŠàŠ°àŠŸ àŠ¯àŠŸàŠ¯àŠŒà¥€"
+
+#: plugins.page:64
+msgid ""
+"However, the only add-ons that have been tested for use with Tor Browser are"
+" those included by default. Installing any other browser add-ons may break "
+"functionality in Tor Browser or cause more serious problems that affect your"
+" privacy and security. It is strongly discouraged to install additional add-"
+"ons, and the Tor Project will not offer support for these configurations."
+msgstr ""
+"àŠ¯àŠŸàŠàйà§àŠ, àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ°à§àа àŠžàŠŸàŠ¥à§ àŠ¬à§àŠ¯àŠ¬àŠ¹àŠŸàŠ°à§àа àŠàŠšà§àН àŠ¶à§àЧà§àŠ®àŠŸàŠ€à§àа àŠ
à§àŠ¯àŠŸàŠ¡-àŠ
àŠšàŠà§àŠ²àŠ¿ àŠªàŠ°à§àŠà§àŠ·àŠŸ àŠàŠ°àŠŸ"
+" àŠ¹àŠ¯àŠŒà§àŠà§ àŠ¯àŠŸàŠ°àŠŸ àŠ¡àŠ¿àŠ«àŠ²à§àŠàŠàŠŸàŠ¬à§ àŠ
àŠšà§àŠ€àŠ°à§àŠà§àŠà§àŠ€à¥€ àŠ
àŠšà§àН àŠà§àŠšàŠ àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ° àŠ
à§àŠ¯àŠŸàŠ¡-àŠ
àŠš àŠàŠšàŠžà§àŠàв àŠàŠ°àŠ²à§"
+" àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ°à§àа àŠàŠŸàŠ°à§àНàŠàŠŸàŠ°àŠ¿àŠ€àŠŸ àŠà§àŠà§àŠà§ àŠ¯à§àŠ€à§ àŠªàŠŸàŠ°à§ àŠ¬àŠŸ àŠàŠªàŠšàŠŸàŠ° àŠà§àŠªàŠšà§àŠ¯àŠŒàŠ€àŠŸ àŠàŠ¬àŠ àŠšàŠ¿àŠ°àŠŸàŠªàŠ€à§àŠ€àŠŸ"
+" àŠªà§àаàŠàŠŸàŠ¬àŠ¿àŠ€ àŠàŠ°à§ àŠàŠ®àŠš àŠàŠ°à§ àŠà§àаà§àŠ€àŠ° àŠžàŠ®àŠžà§àŠ¯àŠŸàŠà§àŠ²àŠ¿àŠ° àŠàŠŸàŠ°àŠ£ àŠ¹àŠ€à§ àŠªàŠŸàŠ°à§à¥€ àŠ
àŠ€àŠ¿àŠ°àŠ¿àŠà§àŠ€ "
+"àŠ
à§àŠ¯àŠŸàŠ¡-àŠ
àŠšàŠà§àŠ²àŠ¿ àŠàŠšàŠžà§àŠàв àŠàŠ°àŠŸàŠ° àŠàŠšà§àН àŠàŠàŠ¿ àŠŠà§àŠ¢àŠŒàŠàŠŸàŠ¬à§ àŠšàŠ¿àŠ°à§à§àŠžàŠŸàŠ¹àŠ¿àŠ€ àŠ¹àŠ¯àŠŒ àŠàŠ¬àŠ àŠàа àŠªà§àаàŠàвà§àŠª àŠàŠ "
+"àŠàŠšàŠ«àŠ¿àŠàŠŸàŠ°à§àŠ¶àŠšà§àа àŠàŠšà§àН àŠžàŠ®àŠ°à§àŠ¥àŠš àŠªà§àŠ°àŠŠàŠŸàŠš àŠàŠ°àŠ¬à§ àŠšàŠŸà¥€"
+
+#: secure-connections.page:8
+msgid "Learn how to protect your data using Tor Browser and HTTPS"
+msgstr ""
+"àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ° àŠàŠ¬àŠ HTTPS àŠ¬à§àŠ¯àŠ¬àŠ¹àŠŸàŠ° àŠàŠ°à§ àŠàŠªàŠšàŠŸàŠ° àŠ¡à§àŠàŠŸ àŠžà§àаàŠà§àŠ·àŠ¿àŠ€ àŠàŠ°àŠŸàŠ° àŠªàŠŠà§àŠ§àŠ€àŠ¿ àŠ¶àŠ¿àŠà§àŠš"
+
+#: secure-connections.page:12
+msgid "Secure Connections"
+msgstr "àŠšàŠ¿àŠ°àŠŸàŠªàŠŠ àŠžàŠàНà§àŠàŠà§àŠ²àŠ¿"
+
+#: secure-connections.page:14
+msgid ""
+"If personal information such as a login password travels unencrypted over "
+"the Internet, it can very easily be intercepted by an eavesdropper. If you "
+"are logging into any website, you should make sure that the site offers "
+"HTTPS encryption, which protects against this kind of eavesdropping. You can"
+" verify this in the URL bar: if your connection is encrypted, the address "
+"will begin with âhttps://â, rather than âhttp://â."
+msgstr ""
+"àŠ¯àŠŠàŠ¿ àŠà§àŠšàŠ àŠ¬à§àНàŠà§àŠ€àŠ¿àŠàŠ€ àŠ€àŠ¥à§àН àŠ¯à§àŠ®àŠš àŠ²àŠàŠàŠš àŠªàŠŸàŠžàŠàŠ¯àŠŒàŠŸàŠ°à§àŠ¡ àŠàŠšà§àŠàŠŸàŠ°àŠšà§àŠà§ àŠ
à§àŠ¯àŠŸàŠšàŠà§àŠ°àŠ¿àŠªàŠà§àŠ¡ àŠà§àŠ°àŠ®àŠ£ "
+"àŠàаà§, àŠ€àŠ¬à§ àŠàŠàŠ¿ àŠà§àЬ àŠžàŠ¹àŠà§àŠ àŠàŠàŠàŠ¿ àŠàвàŠàŠŸàŠ€à§àŠ°à§ àŠŠà§àŠ¬àŠŸàŠ°àŠŸ àŠàŠàŠàŠŸàŠšà§ àŠ¯àŠŸàŠ¯àŠŒà¥€ àŠ¯àŠŠàŠ¿ àŠàŠªàŠšàŠ¿ àŠà§àŠšàŠ "
+"àŠàŠ¯àŠŒà§àŠ¬àŠžàŠŸàŠàŠà§ àŠ²àŠ àŠàŠš àŠàаà§àŠš, àŠ€àŠ¬à§ àŠàŠªàŠšàŠ¿ àŠšàŠ¿àŠ¶à§àŠàŠ¿àŠ€ àŠ¹àŠ¬à§àŠš àŠ¯à§ àŠàŠ àŠžàŠŸàŠàŠàŠàŠ¿ HTTPS àŠàŠšàŠà§àŠ°àŠ¿àŠªàŠ¶àŠš "
+"àŠ
àŠ«àŠŸàŠ° àŠàаà§, àŠ¯àŠŸ àŠàŠ àŠ§àŠ°àŠšà§àа eavesdropping àŠàа àŠ¬àŠ¿àŠ°à§àŠŠà§àŠ§à§ àŠ°àŠà§àŠ·àŠŸ àŠàаà§à¥€ àŠàŠªàŠšàŠ¿ URL àŠ¬àŠŸàŠ°à§ àŠàŠàŠ¿"
+" àŠ¯àŠŸàŠàŠŸàŠ àŠàŠ°àŠ€à§ àŠªàŠŸàŠ°à§àŠš: àŠàŠªàŠšàŠŸàŠ° àŠžàŠàНà§àŠ àŠàŠšàŠà§àŠ°àŠ¿àŠªà§àŠ àŠàŠ°àŠŸ àŠ¹àŠ²à§, àŠ àŠ¿àŠàŠŸàŠšàŠŸàŠàŠ¿ \"http: //\" àŠàа "
+"àŠªàŠ°àŠ¿àŠ¬àŠ°à§àŠ€à§ \"https: //\" àŠŠàŠ¿àŠ¯àŠŒà§ àŠ¶à§àŠ°à§ àŠ¹àŠ¬à§à¥€"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: secure-connections.page:24
+msgctxt "_"
+msgid ""
+"external ref='media/secure-connections/https.png' "
+"md5='364bcbde7a649b0cea9ae178007c1a50'"
+msgstr ""
+"àŠ¬àŠŸàŠ¹à§àŠ¯àŠ¿àŠ àŠ°à§àŠ«='media/secure-connections/https.png' "
+"md5='364bcbde7a649b0cea9ae178007c1a50'"
+
+#: secure-connections.page:26
+msgid ""
+"The following visualization shows what information is visible to "
+"eavesdroppers with and without Tor Browser and HTTPS encryption:"
+msgstr ""
+"àŠšà§àŠà§àа àŠàŠ¿àŠà§àНà§àŠ¯àŠŒàŠŸàŠ²àŠŸàŠàŠà§àŠ¶àŠŸàŠšàŠàŠ¿ àŠŠà§àŠàŠŸàŠ¯àŠŒ àŠ¯à§ àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ° àŠàŠ¬àŠ HTTPS àŠàŠšàŠà§àŠ°àŠ¿àŠªàŠ¶àŠšà§àа àŠžàŠŸàŠ¥à§ "
+"àŠàŠ¬àŠ àŠàŠŸàŠ¡àŠŒàŠŸ àŠàŠŸàŠ¡àŠŒàŠŸ àŠà§ eavesdroppers àŠŠà§àŠàŠ€à§ àŠ¹àŠ¯àŠŒ:"
+
+#: secure-connections.page:35
+msgid ""
+"Click the âTorâ button to see what data is visible to observers when you're "
+"using Tor. The button will turn green to indicate that Tor is on."
+msgstr ""
+"àŠàŠªàŠšàŠ¿ Tor àŠ¬à§àŠ¯àŠ¬àŠ¹àŠŸàŠ° àŠàаàŠà§àŠš àŠ¯àŠàŠš àŠªàŠ°à§àŠ¯àŠ¬à§àŠà§àŠ·àŠ àŠŠà§àжà§àŠ¯àŠ®àŠŸàŠš àŠàŠ¿ àŠŠà§àŠàŠ€à§ \"àŠàа\" àŠ¬à§àŠ€àŠŸàŠ® àŠà§àŠ²àŠ¿àŠ "
+"àŠàаà§àŠšà¥€ àŠ¯à§ àŠàаàŠàŠ¿ àŠàŠŸàŠ²à§ àŠàŠà§ àŠ€àŠŸ àŠšàŠ¿àŠ°à§àŠŠà§àж àŠàŠ°àŠŸàŠ° àŠàŠšà§àН àŠ¬à§àŠ€àŠŸàŠ®àŠàŠ¿ àŠžàŠ¬à§àŠ àŠ¹àŠ¯àŠŒà§ àŠ¯àŠŸàŠ¬à§à¥€"
+
+#: secure-connections.page:42
+msgid ""
+"Click the âHTTPSâ button to see what data is visible to observers when "
+"you're using HTTPS. The button will turn green to indicate that HTTPS is on."
+msgstr ""
+"àŠàŠªàŠšàŠ¿ àŠ¯àŠàŠš HTTPS àŠ¬à§àŠ¯àŠ¬àŠ¹àŠŸàŠ° àŠàаàŠà§àŠš àŠ€àŠàŠš àŠªàŠ°à§àŠ¯àŠ¬à§àŠà§àŠ·àŠàŠŠà§àа àŠàŠŸàŠà§ àŠ¯à§ àŠ¡à§àŠàŠŸ àŠŠà§àжà§àŠ¯àŠ®àŠŸàŠš àŠ€àŠŸ "
+"àŠŠà§àŠàŠ€à§ \"HTTPS\" àŠ¬à§àŠ€àŠŸàŠ®àŠàŠ¿ àŠà§àŠ²àŠ¿àŠ àŠàаà§àŠšà¥€ àŠ¯à§ HTTPS àŠàŠŸàŠ²à§ àŠàŠà§ àŠ€àŠŸ àŠšàŠ¿àŠ°à§àŠŠà§àж àŠàŠ°àŠŸàŠ° àŠàŠšà§àН "
+"àŠ¬à§àŠ€àŠŸàŠ®àŠàŠ¿ àŠžàŠ¬à§àŠ àŠ¹àŠ¯àŠŒà§ àŠ¯àŠŸàŠ¬à§à¥€"
+
+#: secure-connections.page:49
+msgid ""
+"When both buttons are green, you see the data that is visible to observers "
+"when you are using both tools."
+msgstr ""
+"àŠ¯àŠàŠš àŠàŠàŠ¯àŠŒ àŠ¬à§àŠ€àŠŸàŠ®àŠà§àŠ²àŠ¿ àŠžàŠ¬à§àŠ àŠ¹àŠ¯àŠŒ, àŠ€àŠàŠš àŠàŠªàŠšàŠ¿ àŠŠà§àŠàŠ€à§ àŠªàŠŸàŠš àŠ¯à§ àŠàŠªàŠšàŠ¿ àŠàŠàŠ¯àŠŒ àŠžàŠ°àŠà§àŠàŠŸàŠ®àŠà§àŠ²àŠ¿ "
+"àŠ¬à§àŠ¯àŠ¬àŠ¹àŠŸàŠ° àŠàаàŠà§àŠš àŠ€àŠàŠš àŠàŠªàŠšàŠ¿ àŠŠà§àŠàŠ€à§ àŠªàŠŸàŠ¬à§àŠš àŠàŠ®àŠš àŠ¡à§àŠàŠŸ àŠŠà§àŠà§àŠšà¥€"
+
+#: secure-connections.page:55
+msgid ""
+"When both buttons are grey, you see the data that is visible to observers "
+"when you don't use either tool."
+msgstr ""
+"àŠ¯àŠàŠš àŠàŠàŠ¯àŠŒ àŠ¬à§àŠ€àŠŸàŠ®àŠà§àŠ²àŠ¿ àŠžàŠ¬à§àŠ àŠ¹àŠ¯àŠŒ, àŠ€àŠàŠš àŠàŠªàŠšàŠ¿ àŠŠà§àŠàŠ€à§ àŠªàŠŸàŠš àŠ¯à§ àŠàŠªàŠšàŠ¿ àŠàŠàŠ¯àŠŒ àŠžàŠ°àŠà§àŠàŠŸàŠ®àŠà§àŠ²àŠ¿ "
+"àŠ¬à§àŠ¯àŠ¬àŠ¹àŠŸàŠ° àŠàаàŠà§àŠš àŠ€àŠàŠš àŠàŠªàŠšàŠ¿ àŠŠà§àŠàŠ€à§ àŠªàŠŸàŠ¬à§àŠš àŠàŠ®àŠš àŠ¡à§àŠàŠŸ àŠŠà§àŠà§àŠšà¥€"
+
+#: secure-connections.page:62
+msgid "Potentially visible data"
+msgstr "àŠžàŠ®à§àŠàŠŸàŠ¬à§àН àŠŠà§àжà§àŠ¯àŠ®àŠŸàŠš àŠ¡à§àŠàŠŸ"
+
+#: secure-connections.page:70
+msgid "The site being visited."
+msgstr "àŠžàŠŸàŠàŠ àŠªàŠ°àŠ¿àŠŠàŠ°à§àŠ¶àŠš àŠàŠ°àŠŸ àŠ¹àŠà§àŠà§à¥€"
+
+#: secure-connections.page:81
+msgid "Username and password used for authentication."
+msgstr "àŠ¬à§àŠ¯àŠ¬àŠ¹àŠŸàŠ°àŠàŠŸàŠ°à§àа àŠšàŠŸàŠ® àŠàŠ¬àŠ àŠªàŠŸàŠžàŠàŠ¯àŠŒàŠŸàŠ°à§àŠ¡ àŠªà§àŠ°àŠ®àŠŸàŠ£à§àŠàŠ°àŠ£à§àа àŠàŠšà§àН àŠ¬à§àŠ¯àŠ¬àŠ¹à§àŠ€à¥€"
+
+#: secure-connections.page:92
+msgid "Data being transmitted."
+msgstr "àŠ€àŠ¥à§àН àŠªà§àаà§àŠ°àŠ£ àŠàŠ°àŠŸ àŠ¹àŠà§àŠà§à¥€"
+
+#: secure-connections.page:103
+msgid ""
+"Network location of the computer used to visit the website (the public IP "
+"address)."
+msgstr ""
+"àŠàŠ¯àŠŒà§àŠ¬àŠžàŠŸàŠàŠà§àа àŠàŠšà§àН àŠ¬à§àŠ¯àŠ¬àŠ¹à§àŠ€ àŠàŠ®à§àŠªàŠ¿àŠàŠàŠŸàŠ°à§àа àŠšà§àŠàŠàŠ¯àŠŒàŠŸàŠ°à§àŠ àŠžà§àŠ¥àŠŸàŠš (àŠªàŠŸàŠ¬àŠ²àŠ¿àŠ àŠàŠàŠªàŠ¿ àŠ àŠ¿àŠàŠŸàŠšàŠŸ)ी"
+
+#: secure-connections.page:115
+msgid "Whether or not Tor is being used."
+msgstr "àŠàаà§àŠ àŠ¬à§àŠ¯àŠ¬àŠ¹àŠŸàŠ° àŠàŠ°àŠŸ àŠ¹àŠà§àŠà§ àŠàŠ¿àŠšàŠŸ àŠ¬àŠŸ àŠšàŠŸà¥€"
+
+#: security-slider.page:6
+msgid "Configuring Tor Browser for security and usability"
+msgstr "àŠšàŠ¿àŠ°àŠŸàŠªàŠ€à§àŠ€àŠŸ àŠàŠ¬àŠ àŠ¬à§àŠ¯àŠ¬àŠ¹àŠŸàŠ°àŠ¯à§àŠà§àŠ¯àŠ€àŠŸ àŠàŠšà§àН àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ° àŠàŠšàŠ«àŠ¿àŠàŠŸàŠ°"
+
+#: security-slider.page:10
+msgid "Security Slider"
+msgstr "àŠšàŠ¿àŠ°àŠŸàŠªàŠ€à§àŠ€àŠŸ àŠžà§àŠ²àŠŸàŠàŠ¡àŠŸàŠ°"
+
+#: security-slider.page:11
+msgid ""
+"Tor Browser includes a âSecurity Sliderâ that lets you increase your "
+"security by disabling certain web features that can be used to attack your "
+"security and anonymity. Increasing Tor Browserâs security level will stop "
+"some web pages from functioning properly, so you should weigh your security "
+"needs against the degree of usability you require."
+msgstr ""
+"àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ°àŠàŠ¿ àŠàŠàŠàŠ¿ \"àŠžàŠ¿àŠàŠ¿àŠàŠ°àŠ¿àŠàŠ¿ àŠžà§àŠ²àŠŸàŠàŠ¡àŠŸàŠ°\" àŠ
àŠšà§àŠ€àŠ°à§àŠà§àŠà§àŠ€ àŠàŠ°à§ àŠ¯àŠŸ àŠàŠªàŠšàŠŸàŠà§ àŠàŠªàŠšàŠŸàŠ° "
+"àŠžà§àаàŠà§àŠ·àŠŸ àŠàŠ¬àŠ àŠà§àŠªàŠšà§àŠ¯àŠŒàŠ€àŠŸ àŠàŠà§àŠ°àŠ®àŠ£à§àа àŠàŠšà§àН àŠ¬à§àŠ¯àŠ¬àŠ¹àŠŸàŠ° àŠàŠ°àŠŸ àŠ¯à§àŠ€à§ àŠªàŠŸàŠ°à§ àŠàŠ®àŠš àŠšàŠ¿àŠ°à§àŠŠàŠ¿àŠ·à§àŠ "
+"àŠàŠ¯àŠŒà§àЬ àŠ¬à§àŠ¶àŠ¿àŠ·à§àŠà§àН àŠ
àŠà§àŠ·àŠ® àŠàŠ°à§ àŠàŠªàŠšàŠŸàŠ° àŠšàŠ¿àŠ°àŠŸàŠªàŠ€à§àŠ€àŠŸ àŠ¬à§àŠŠà§àŠ§àŠ¿ àŠàаà§à¥€ àŠà§àŠ°àŠ®àŠ¬àŠ°à§àŠ§àŠ®àŠŸàŠš àŠàа "
+"àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ°à§àа àŠšàŠ¿àŠ°àŠŸàŠªàŠ€à§àŠ€àŠŸ àŠžà§àŠ€àŠ° àŠžàŠ àŠ¿àŠàŠàŠŸàŠ¬à§ àŠàŠŸàŠ àŠàŠ°àŠŸàŠ° àŠàŠ¿àŠà§ àŠàŠ¯àŠŒà§àЬ àŠªà§àŠ àŠ¬àŠšà§àЧ àŠàŠ°àŠ¬à§, àŠ€àŠŸàŠ "
+"àŠàŠªàŠšàŠŸàŠ° àŠªà§àŠ°àŠ¯àŠŒà§àŠàŠšà§àŠ¯àŠŒ àŠªà§àŠ°àŠ¯àŠŒà§àŠàŠšà§àŠ¯àŠŒàŠ€àŠŸàŠàŠ¿ àŠ¡àŠ¿àŠà§àŠ°àŠ¿àŠ° àŠ¬àŠ¿àŠ°à§àŠŠà§àŠ§à§ àŠàŠªàŠšàŠŸàŠ° àŠžà§àаàŠà§àŠ·àŠŸàŠ° "
+"àŠªà§àŠ°àŠ¯àŠŒà§àŠàŠšàŠà§àŠ²àŠ¿àŠ° àŠ€à§àŠ²àŠšàŠŸ àŠàŠ°àŠŸ àŠàŠàŠ¿àŠ€à¥€"
+
+#: security-slider.page:21
+msgid "Accessing the Security Slider"
+msgstr "Accessing the Security Slider"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: security-slider.page:23
+msgctxt "_"
+msgid ""
+"external ref='media/security-slider/slider.png' "
+"md5='3c469cd3ed9f60ebb6bbbc63daa90082'"
+msgstr ""
+"àŠ¬àŠŸàŠ¹à§àŠ¯àŠ¿àŠ àŠ°à§àŠ«='media/security-slider/slider.png' "
+"md5='3c469cd3ed9f60ebb6bbbc63daa90082'"
+
+#: security-slider.page:25
+msgid ""
+"The Security Slider is located in Torbuttonâs âPrivacy and Security "
+"Settingsâ menu."
+msgstr ""
+"àŠšàŠ¿àŠ°àŠŸàŠªàŠ€à§àŠ€àŠŸ àŠžà§àŠ²àŠŸàŠàŠ¡àŠŸàŠ° Torbutton àŠàа \"àŠà§àŠªàŠšà§àŠ¯àŠŒàŠ€àŠŸ àŠàŠ¬àŠ àŠšàŠ¿àŠ°àŠŸàŠªàŠ€à§àŠ€àŠŸ àŠžà§àŠàŠ¿àŠàŠž\" àŠ®à§àŠšà§àŠ€à§ "
+"àŠ
àŠ¬àŠžà§àŠ¥àŠ¿àŠ€à¥€"
+
+#: security-slider.page:32
+msgid "Security Levels"
+msgstr "àŠšàŠ¿àŠ°àŠŸàŠªàŠ€à§àŠ€àŠŸ àŠžà§àŠ€àŠ°"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: security-slider.page:34
+msgctxt "_"
+msgid ""
+"external ref='media/security-slider/slider_window.png' "
+"md5='c733bdccd1731ed1a772777b25bae7a1'"
+msgstr ""
+"àŠ¬àŠŸàŠ¹à§àŠ¯àŠ¿àŠ àŠ°à§àŠ«='media/security-slider/slider_window.png' "
+"md5='c733bdccd1731ed1a772777b25bae7a1'"
+
+#: security-slider.page:36
+msgid ""
+"Increasing the level of the Security Slider will disable or partially "
+"disable certain browser features to protect against possible attacks."
+msgstr ""
+"Increasing the level of the Security Slider will disable or partially "
+"disable certain browser features to protect against possible attacks."
+
+#: security-slider.page:42
+msgid "High"
+msgstr "àŠàŠà§àŠ"
+
+#: security-slider.page:43
+msgid ""
+"At this level, HTML5 video and audio media become click-to-play via "
+"NoScript; all JavaScript performance optimizations are disabled; some "
+"mathematical equations may not display properly; some font rendering "
+"features are disabled; some types of image are disabled; Javascript is "
+"disabled by default on all sites; most video and audio formats are disabled;"
+" and some fonts and icons may not display correctly."
+msgstr ""
+"àŠàŠ àŠžà§àŠ€àŠ°à§, HTML5 àŠàŠ¿àŠ¡àŠ¿àŠ àŠàŠ¬àŠ àŠ
àŠ¡àŠ¿àŠ àŠ®àŠ¿àŠ¡àŠ¿àŠ¯àŠŒàŠŸ àŠšà§àŠàŠžàŠªà§àа àŠ®àŠŸàŠ§à§àŠ¯àŠ®à§ àŠà§àŠ²àŠ¿àŠ àŠàŠ°àŠŸàŠ° àŠàŠšà§àН àŠà§àŠ²àŠ¿àŠ"
+" àŠàаà§; àŠžàŠ®àŠžà§àŠ€ àŠàŠŸàŠàŠŸàŠžà§àŠà§àŠ°àŠ¿àŠªà§àŠ àŠ
àŠªà§àŠàŠ¿àŠ®àŠŸàŠàŠà§àŠ¶àŠš àŠšàŠ¿àŠ·à§àŠà§àŠ°àŠ¿àŠ¯àŠŒ àŠàŠ°àŠŸ àŠ¹àŠ¯àŠŒ àŠàŠ¿àŠà§ àŠàŠŸàŠ£àŠ¿àŠ€àŠ¿àŠ "
+"àŠžàŠ®à§àŠàŠ°àŠ£ àŠžàŠ àŠ¿àŠàŠàŠŸàŠ¬à§ àŠªà§àŠ°àŠŠàŠ°à§àŠ¶àŠš àŠàŠ°àŠ€à§ àŠªàŠŸàŠ°à§ àŠšàŠŸ; àŠàŠ¿àŠà§ àŠ«àŠšà§àŠ àŠ°à§àŠšà§àŠ¡àŠŸàŠ°àŠ¿àŠ àŠ¬à§àŠ¶àŠ¿àŠ·à§àŠà§àН "
+"àŠšàŠ¿àŠ·à§àŠà§àŠ°àŠ¿àŠ¯àŠŒ àŠàŠ°àŠŸ àŠ¹àŠ¯àŠŒ; àŠàŠ¿àŠà§ àŠ§àŠ°àŠšà§àа àŠàŠ®à§àŠ àŠ
àŠà§àŠ·àŠ® àŠàŠ°àŠŸ àŠ¹àŠ¯àŠŒ; àŠàŠŸàŠàŠŸàŠžà§àŠà§àŠ°àŠ¿àŠªà§àŠ àŠžàŠ®àŠžà§àŠ€ àŠžàŠŸàŠàŠ "
+"àŠ¡àŠ¿àŠ«àŠ²à§àŠ àŠŠà§àŠ¬àŠŸàŠ°àŠŸ àŠ
àŠà§àŠ·àŠ® àŠàŠ°àŠŸ àŠ¹àŠ¯àŠŒ; àŠ
àŠ§àŠ¿àŠàŠŸàŠàж àŠàŠ¿àŠ¡àŠ¿àŠ àŠàŠ¬àŠ àŠ
àŠ¡àŠ¿àŠ àŠ«àŠ°àŠ®à§àŠ¯àŠŸàŠ àŠ
àŠà§àŠ·àŠ®; àŠàŠ¬àŠ àŠàŠ¿àŠà§ "
+"àŠ«àŠšà§àŠ àŠàŠ¬àŠ àŠàŠàŠàŠš àŠžàŠ àŠ¿àŠàŠàŠŸàŠ¬à§ àŠªà§àŠ°àŠŠàŠ°à§àŠ¶àŠš àŠàŠ°àŠ€à§ àŠªàŠŸàŠ°à§ àŠšàŠŸà¥€"
+
+#: security-slider.page:53
+msgid "Medium-High"
+msgstr "àŠ®à§àŠàŠŸàŠ®à§àŠàŠ¿ àŠàŠà§"
+
+#: security-slider.page:54
+msgid ""
+"At this level, HTML5 video and audio media become click-to-play via "
+"NoScript; all JavaScript performance optimizations are disabled; some "
+"mathematical equations may not display properly; some font rendering "
+"features are disabled; some types of image are disabled; and JavaScript is "
+"disabled by default on all non-<link xref=\"secure-"
+"connections\">HTTPS</link> sites."
+msgstr ""
+"àŠàŠ àŠžà§àŠ€àŠ°à§, HTML5 àŠàŠ¿àŠ¡àŠ¿àŠ àŠàŠ¬àŠ àŠ
àŠ¡àŠ¿àŠ àŠ®àŠ¿àŠ¡àŠ¿àŠ¯àŠŒàŠŸ àŠšà§àŠàŠžàŠªà§àа àŠ®àŠŸàŠ§à§àŠ¯àŠ®à§ àŠà§àŠ²àŠ¿àŠ àŠàŠ°àŠŸàŠ° àŠàŠšà§àН àŠà§àŠ²àŠ¿àŠ"
+" àŠàаà§; àŠžàŠ®àŠžà§àŠ€ àŠàŠŸàŠàŠŸàŠžà§àŠà§àŠ°àŠ¿àŠªà§àŠ àŠ
àŠªà§àŠàŠ¿àŠ®àŠŸàŠàŠà§àŠ¶àŠš àŠšàŠ¿àŠ·à§àŠà§àŠ°àŠ¿àŠ¯àŠŒ àŠàŠ°àŠŸ àŠ¹àŠ¯àŠŒ àŠàŠ¿àŠà§ àŠàŠŸàŠ£àŠ¿àŠ€àŠ¿àŠ "
+"àŠžàŠ®à§àŠàŠ°àŠ£ àŠžàŠ àŠ¿àŠàŠàŠŸàŠ¬à§ àŠªà§àŠ°àŠŠàŠ°à§àŠ¶àŠš àŠàŠ°àŠ€à§ àŠªàŠŸàŠ°à§ àŠšàŠŸ; àŠàŠ¿àŠà§ àŠ«àŠšà§àŠ àŠ°à§àŠšà§àŠ¡àŠŸàŠ°àŠ¿àŠ àŠ¬à§àŠ¶àŠ¿àŠ·à§àŠà§àН "
+"àŠšàŠ¿àŠ·à§àŠà§àŠ°àŠ¿àŠ¯àŠŒ àŠàŠ°àŠŸ àŠ¹àŠ¯àŠŒ; àŠàŠ¿àŠà§ àŠ§àŠ°àŠšà§àа àŠàŠ®à§àŠ àŠ
àŠà§àŠ·àŠ® àŠàŠ°àŠŸ àŠ¹àŠ¯àŠŒ; àŠàŠ¬àŠ àŠžàŠ®àŠžà§àŠ€ àŠ
-HTTPS "
+"àŠžàŠŸàŠàŠàŠà§àŠ²àŠ¿àŠ€à§ àŠ¡àŠ¿àŠ«àŠ²à§àŠàŠàŠŸàŠ¬à§ àŠàŠŸàŠàŠŸàŠžà§àŠà§àŠ°àŠ¿àŠªà§àŠ àŠšàŠ¿àŠ·à§àŠà§àŠ°àŠ¿àŠ¯àŠŒ àŠàŠ°àŠŸ àŠàŠà§à¥€"
+
+#: security-slider.page:64
+msgid "Medium-Low"
+msgstr "àŠ®àŠŸàŠàŠŸàŠ°àŠ¿ àŠšàŠ¿àŠ®à§àŠš"
+
+#: security-slider.page:65
+msgid ""
+"At this level, HTML5 video and audio media become click-to-play via "
+"NoScript; some <link xref=\"plugins\">JavaScript</link> performance "
+"optimizations are disabled, causing some websites to run more slowly; and "
+"some mathematical equations may not display properly."
+msgstr ""
+"àŠàŠ àŠžà§àŠ€àŠ°à§, HTML5 àŠàŠ¿àŠ¡àŠ¿àŠ àŠàŠ¬àŠ àŠ
àŠ¡àŠ¿àŠ àŠ®àŠ¿àŠ¡àŠ¿àŠ¯àŠŒàŠŸ àŠšà§àŠàŠžàŠªà§àа àŠ®àŠŸàŠ§à§àŠ¯àŠ®à§ àŠà§àŠ²àŠ¿àŠ àŠàŠ°àŠŸàŠ° àŠàŠšà§àН àŠà§àŠ²àŠ¿àŠ"
+" àŠàаà§; àŠàŠ¿àŠà§ àŠàŠŸàŠàŠŸàŠžà§àŠà§àŠ°àŠ¿àŠªà§àŠ àŠ
àŠªà§àŠàŠ¿àŠ®àŠŸàŠàŠà§àŠ¶àŠš àŠšàŠ¿àŠ·à§àŠà§àŠ°àŠ¿àŠ¯àŠŒ, àŠàŠ¿àŠà§ àŠàŠ¯àŠŒà§àŠ¬àŠžàŠŸàŠàŠ àŠàŠ°à§ àŠ§à§àŠ°à§ "
+"àŠ§à§àŠ°à§ àŠàŠŸàŠ²àŠŸàŠšà§àа àŠàŠŸàŠ°àŠ£à§; àŠàŠ¬àŠ àŠàŠ¿àŠà§ àŠàŠŸàŠ£àŠ¿àŠ€àŠ¿àŠ àŠžàŠ®à§àŠàŠ°àŠ£ àŠžàŠ àŠ¿àŠàŠàŠŸàŠ¬à§ àŠªà§àŠ°àŠŠàŠ°à§àŠ¶àŠ¿àŠ€ àŠ¹àŠ¬à§ àŠšàŠŸà¥€"
+
+#: security-slider.page:73
+msgid "Low"
+msgstr "àŠšàŠ¿àŠ®à§àŠš"
+
+#: security-slider.page:74
+msgid ""
+"At this level, all browser features are enabled. This is the most usable "
+"option."
+msgstr ""
+"àŠàŠ àŠžà§àŠ€àŠ°à§, àŠžàŠ®àŠžà§àŠ€ àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ° àŠ¬à§àŠ¶àŠ¿àŠ·à§àŠà§àН àŠžàŠà§àŠ·àŠ® àŠàŠ°àŠŸ àŠàŠà§à¥€ àŠàŠàŠ¿ àŠžàŠ¬àŠà§àŠ¯àŠŒà§ àŠ¬à§àŠ¯àŠ¬àŠ¹àŠŸàŠ°àŠ¯à§àŠà§àН "
+"àŠ¬àŠ¿àŠàвà§àŠªà¥€"
+
+#: transports.page:6 transports.page:20
+msgid "Types of pluggable transport"
+msgstr "àŠªà§àвà§àŠ¯àŠŸàŠà§àŠ¬àŠ² àŠà§àŠ°àŠŸàŠšà§àŠžàŠªà§àаà§àŠà§àа àŠ§àŠ°àŠš"
+
+#: transports.page:10
+msgid "Pluggable Transports"
+msgstr "àŠªà§àвà§àŠ¯àŠŸàŠà§àŠ¬àŠ² àŠà§àŠ°àŠŸàŠšà§àŠžàŠªà§àаà§àŠàŠà§àŠ²àŠ¿"
+
+#: transports.page:12
+msgid ""
+"Pluggable transports are tools that Tor can use to disguise the traffic it "
+"sends out. This can be useful in situations where an Internet Service "
+"Provider or other authority is actively blocking connections to the Tor "
+"network."
+msgstr ""
+"àŠªà§àвà§àŠ¯àŠŸàŠà§àŠ¬àŠ² àŠà§àŠ°àŠŸàŠšà§àŠžàŠ«àŠ°à§àŠ®àŠà§àŠ²àŠ¿ àŠàŠ®àŠš àŠžàŠ°àŠà§àŠàŠŸàŠ®àŠà§àŠ²àŠ¿ àŠ¯àŠŸ àŠàаàŠà§ àŠà§àаà§àŠ¯àŠŸàŠ«àŠ¿àŠà§àа àŠàŠŠà§àŠ®àŠ¬à§àŠ¶à§ "
+"àŠ¬à§àŠ¯àŠ¬àŠ¹àŠŸàŠ° àŠàŠ°àŠ€à§ àŠªàŠŸàŠ°à§à¥€ àŠàŠàŠ¿ àŠàŠàŠàŠ¿ àŠàŠšà§àŠàŠŸàŠ°àŠšà§àŠ àŠªàŠ°àŠ¿àŠ·à§àŠ¬àŠŸ àŠžàŠ°àŠ¬àŠ°àŠŸàŠ¹àŠàŠŸàŠ°à§ àŠ¬àŠŸ àŠ
àŠšà§àН àŠàаà§àŠ€à§àŠªàŠà§àŠ· "
+"àŠžàŠà§àŠ°àŠ¿àŠ¯àŠŒàŠàŠŸàŠ¬à§ àŠàа àŠšà§àŠàŠàŠ¯àŠŒàŠŸàŠ°à§àŠ àŠžàŠàНà§àŠ àŠžàŠàНà§àŠ àŠ
àŠ¬àŠ°à§àЧ àŠ¯à§àŠàŠŸàŠšà§ àŠªàŠ°àŠ¿àŠžà§àŠ¥àŠ¿àŠ€àŠ¿àŠ€à§ àŠŠàŠ°àŠàŠŸàŠ°à§ àŠ¹àŠ€à§ "
+"àŠªàŠŸàŠ°à§à¥€"
+
+#: transports.page:21
+msgid ""
+"Currently there are six pluggable transports available, but more are being "
+"developed."
+msgstr ""
+"àŠ¬àŠ°à§àŠ€àŠ®àŠŸàŠšà§ àŠàŠ¯àŠŒàŠàŠ¿ àŠªà§àвà§àŠ¯àŠŸàŠà§àŠ¬àŠ² àŠà§àŠ°àŠŸàŠšà§àŠžàŠªà§àаà§àŠàŠà§àŠ²àŠ¿ àŠªàŠŸàŠàŠ¯àŠŒàŠŸ àŠ¯àŠŸàŠ¯àŠŒ, àŠ€àŠ¬à§ àŠàŠ°à§ àŠàŠšà§àŠšàŠ€ àŠàŠ°àŠŸ "
+"àŠ¹àŠà§àŠà§à¥€"
+
+#: transports.page:28
+msgid "obfs3"
+msgstr "obfs3"
+
+#: transports.page:33
+msgid ""
+"obfs3 makes Tor traffic look random, so that it does not look like Tor or "
+"any other protocol. obfs3 bridges will work in most places."
+msgstr ""
+"obfs3 àŠàа àŠà§àаà§àŠ¯àŠŸàŠ«àŠ¿àŠ àŠ°à§àŠ¯àŠŸàŠšà§àŠ¡àŠ® àŠŠà§àŠàŠŸàŠ¯àŠŒ, àŠ¯àŠŸàŠ€à§ àŠàŠàŠ¿ àŠàа àŠ¬àŠŸ àŠ
àŠšà§àН àŠà§àŠšàŠ àŠªà§àаà§àŠà§àŠàвà§àа àŠ®àŠ€à§ "
+"àŠŠà§àŠàŠ€à§ àŠšàŠŸ àŠ¹àŠ¯àŠŒà¥€ obfs3 àŠžà§àŠ€à§ àŠ
àŠ§àŠ¿àŠàŠŸàŠàж àŠàŠŸàŠ¯àŠŒàŠàŠŸàŠ¯àŠŒ àŠàŠŸàŠ àŠàŠ°àŠ¬à§à¥€"
+
+#: transports.page:42
+msgid "obfs4"
+msgstr "obfs4"
+
+#: transports.page:47
+msgid ""
+"obfs4 makes Tor traffic look random like obfs3, and also prevents censors "
+"from finding bridges by Internet scanning. obfs4 bridges are less likely to "
+"be blocked than obfs3 bridges."
+msgstr ""
+"obfs4 àŠàа àŠà§àаà§àŠ¯àŠŸàŠ«àŠ¿àŠàŠàŠ¿ àŠ
à§àŠ¯àŠŸàŠ®àŠ«àŠž 3 àŠàа àŠ®àŠ€à§ àŠ°à§àŠ¯àŠŸàŠšà§àŠ¡àŠ® àŠŠà§àŠàŠŸàŠ¯àŠŒ, àŠàŠ¬àŠ àŠàŠšà§àŠàŠŸàŠ°àŠšà§àŠ "
+"àŠžà§àŠà§àŠ¯àŠŸàŠšàŠ¿àŠ àŠŠà§àŠ¬àŠŸàŠ°àŠŸ àŠ¬à§àŠ°àŠ¿àŠ àŠà§àŠàŠà§ àŠªà§àŠ€à§ àŠžà§àŠšà§àŠžàŠ°àŠà§àŠ²àŠ¿àŠà§àŠ àŠªà§àŠ°àŠ€àŠ¿àŠ°à§àЧ àŠàаà§à¥€ obfs4 àŠ¬à§àŠ°àŠ¿àŠ "
+"obfs3 àŠ¬à§àŠ°àŠ¿àŠà§àа àŠà§àŠ¯àŠŒà§ àŠ¬à§àŠ²àŠ àŠàŠ°àŠŸ àŠžàŠ®à§àŠàŠ¬àŠ€ àŠàŠ®à¥€"
+
+#: transports.page:56
+msgid "Scramblesuit"
+msgstr "Scramblesuit"
+
+#: transports.page:61
+msgid "ScrambleSuit is similar to obfs4 but has a different set of bridges."
+msgstr "ScrambleSuit obfs4 àŠ
àŠšà§àаà§àŠª àŠàŠ¿àŠšà§àŠ€à§ àŠ¬à§àŠ°àŠ¿àŠ àŠàŠàŠàŠ¿ àŠàŠ¿àŠšà§àŠš àŠžà§àŠ àŠàŠà§à¥€"
+
+#: transports.page:69
+msgid "FTE"
+msgstr "FTE"
+
+#: transports.page:74
+msgid ""
+"FTE (format-transforming encryption) disguises Tor traffic as ordinary web "
+"(HTTP) traffic."
+msgstr ""
+"FTE (àŠ«àŠ°àŠ®à§àŠ¯àŠŸàŠ-àŠ°à§àŠªàŠŸàŠšà§àŠ€àŠ° àŠàŠšàŠà§àŠ°àŠ¿àŠªàŠ¶àŠš) àŠžàŠŸàŠ§àŠŸàŠ°àŠ£ àŠàŠ¯àŠŒà§àЬ (HTTP) àŠà§àаà§àŠ¯àŠŸàŠ«àŠ¿àŠ àŠ¹àŠ¿àŠžàŠŸàŠ¬à§ àŠàа "
+"àŠà§àŠ°àŠŸàŠ«àŠ¿àŠ àŠàŠŠà§àŠ®àŠ¬à§àŠ¶à¥€"
+
+#: transports.page:82
+msgid "meek"
+msgstr "meek"
+
+#: transports.page:87
+msgid ""
+"These transports all make it look like you are browsing a major web site "
+"instead of using Tor. meek-amazon makes it look like you are using Amazon "
+"Web Services; meek-azure makes it look like you are using a Microsoft web "
+"site; and meek-google makes it look like you are using Google search."
+msgstr ""
+"àŠàŠ àŠžàŠ¬ transports àŠàŠªàŠšàŠ¿ àŠàа àŠ¬à§àŠ¯àŠ¬àŠ¹àŠŸàŠ° àŠàŠ°àŠŸàŠ° àŠªàŠ°àŠ¿àŠ¬àŠ°à§àŠ€à§ àŠàŠàŠàŠ¿ àŠªà§àŠ°àŠ§àŠŸàŠš àŠàŠ¯àŠŒà§àЬ àŠžàŠŸàŠàŠ àŠ¬à§àŠ°àŠŸàŠàŠ"
+" àŠàŠ°àŠŸ àŠ¹àŠ¯àŠŒ àŠ®àŠ€ àŠŠà§àŠàŠ€à§ àŠàŠàŠ¿à¥€ àŠšàŠ®àŠžà§àŠàŠŸàŠ°-àŠà§àŠ¯àŠŸàŠ®à§àŠàŠŸàŠš àŠàŠàŠ¿ àŠŠà§àŠàŠŸàŠ¯àŠŒ àŠ¯à§ àŠàŠªàŠšàŠ¿ àŠ
à§àŠ¯àŠŸàŠ®àŠŸàŠàŠš àŠàŠ¯àŠŒà§àЬ "
+"àŠªàŠ°àŠ¿àŠ·à§àŠ¬àŠŸ àŠ¬à§àŠ¯àŠ¬àŠ¹àŠŸàŠ° àŠàаàŠà§àŠš; àŠ®à§àŠàŠŸàŠ°-àŠ
àŠàа àŠàŠàŠ¿ àŠàŠàŠàŠ¿ àŠ®àŠŸàŠàŠà§àаà§àŠžàŠ«à§àŠ àŠàŠ¯àŠŒà§àЬ àŠžàŠŸàŠàŠ àŠ¬à§àŠ¯àŠ¬àŠ¹àŠŸàŠ° àŠàаà§"
+" àŠŠà§àŠàŠŸàŠ¯àŠŒ; àŠàŠ¬àŠ àŠšàŠ¿àŠà§àŠàŠ€-àŠà§àŠàв àŠàŠàŠ¿ àŠŠà§àŠàŠŸàŠ¯àŠŒ àŠ¯à§ àŠàŠªàŠšàŠ¿ àŠà§àŠàв àŠ
àŠšà§àŠžàŠšà§àŠ§àŠŸàŠš àŠ¬à§àŠ¯àŠ¬àŠ¹àŠŸàŠ° àŠàаàŠà§àŠšà¥€"
+
+#: troubleshooting.page:6
+msgid "What to do if Tor Browser doesnât work"
+msgstr "àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ° àŠàŠŸàŠ àŠšàŠŸ àŠàŠ°àŠ²à§ àŠàŠ¿ àŠàŠ°àŠ¬à§àŠš?"
+
+#: troubleshooting.page:12
+msgid ""
+"You should be able to start browsing the web using Tor Browser shortly after"
+" running the program, and clicking the âConnectâ button if you are using it "
+"for the first time."
+msgstr ""
+"àŠàŠªàŠšàŠ¿ àŠªà§àаà§àŠà§àŠ°àŠŸàŠ®àŠàŠ¿ àŠàŠŸàŠ²àŠŸàŠšà§àа àŠªàŠ°à§, àŠàŠ¬àŠ àŠàŠªàŠšàŠ¿ \"àŠªà§àŠ°àŠ¥àŠ®àŠ¬àŠŸàŠ°à§àа àŠ®àŠ€ àŠàŠàŠ¿ àŠ¬à§àŠ¯àŠ¬àŠ¹àŠŸàŠ° àŠàаà§\" àŠ¯àŠŠàŠ¿"
+" \"àŠžàŠàНà§àŠ\" àŠ¬à§àŠ€àŠŸàŠ®àŠàŠ¿ àŠà§àŠ²àŠ¿àŠ àŠàŠ°àŠŸàŠ° àŠªàŠ°à§ àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ° àŠ¬à§àŠ¯àŠ¬àŠ¹àŠŸàŠ° àŠàŠ°à§ àŠàŠ¯àŠŒà§àŠ¬à§ àŠ¬à§àŠ°àŠŸàŠàŠ àŠàŠ°àŠŸ "
+"àŠ¶à§àŠ°à§ àŠàŠ°àŠ€à§ àŠžàŠà§àŠ·àŠ® àŠ¹àŠàŠ¯àŠŒàŠŸ àŠàŠàŠ¿àŠ€à¥€"
+
+#: troubleshooting.page:21
+msgid "Quick fixes"
+msgstr "àŠŠà§àаà§àŠ€ àŠžàŠàжà§àŠ§àŠš"
+
+#: troubleshooting.page:22
+msgid ""
+"If Tor Browser doesnât connect, there may be a simple solution. Try each of "
+"the following:"
+msgstr ""
+"àŠ¯àŠŠàŠ¿ àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ° àŠžàŠàНà§àŠà§àŠ€ àŠšàŠŸ àŠ¹àŠ¯àŠŒ, àŠ€àŠ¬à§ àŠàŠàŠàŠ¿ àŠžàŠ¹àŠ àŠžàŠ®àŠŸàŠ§àŠŸàŠš àŠ¹àŠ€à§ àŠªàŠŸàŠ°à§à¥€ àŠšàŠ¿àŠ®à§àŠšàŠ²àŠ¿àŠàŠ¿àŠ€ "
+"àŠªà§àŠ°àŠ€àŠ¿àŠàŠ¿ àŠà§àŠ·à§àŠàŠŸ àŠàаà§àŠš:"
+
+#: troubleshooting.page:29
+msgid ""
+"Your computerâs system clock must be set correctly, or Tor will not be able "
+"to connect."
+msgstr ""
+"àŠàŠªàŠšàŠŸàŠ° àŠàŠ®à§àŠªàŠ¿àŠàŠàŠŸàŠ°à§àа àŠžàŠ¿àŠžà§àŠà§àŠ® àŠàŠ¡àŠŒàŠ¿ àŠžàŠ àŠ¿àŠàŠàŠŸàŠ¬à§ àŠžà§àŠ àŠàŠ°àŠŸ àŠàŠàŠ¿àŠ€, àŠ
àŠ¥àŠ¬àŠŸ Tor àŠžàŠàНà§àŠ àŠàŠ°àŠ€à§ "
+"àŠžàŠà§àŠ·àŠ® àŠ¹àŠ¬à§ àŠšàŠŸà¥€"
+
+#: troubleshooting.page:35
+msgid ""
+"Make sure another Tor Browser is not already running. If youâre not sure if "
+"Tor Browser is running, restart your computer."
+msgstr ""
+"àŠ
àŠšà§àН àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ° àŠàŠ€àŠ¿àŠ®àŠ§à§àŠ¯à§ àŠàвàŠà§ àŠšàŠŸ àŠšàŠ¿àŠ¶à§àŠàŠ¿àŠ€ àŠàаà§àŠšà¥€ àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ° àŠàвàŠà§ àŠàŠ¿àŠšàŠŸ àŠ€àŠŸ "
+"àŠšàŠ¿àŠ¶à§àŠàŠ¿àŠ€ àŠšàŠŸ àŠ¹àŠ²à§ àŠàŠªàŠšàŠŸàŠ° àŠàŠ®à§àŠªàŠ¿àŠàŠàŠŸàŠ° àŠªà§àŠšàŠ°àŠŸàŠ¯àŠŒ àŠàŠŸàŠ²à§ àŠàаà§àŠšà¥€"
+
+#: troubleshooting.page:41
+msgid ""
+"Make sure that any antivirus program you have installed is not preventing "
+"Tor from running. You may need to consult the documentation for your "
+"antivirus software if you do not know how to do this."
+msgstr ""
+"àŠšàŠ¿àŠ¶à§àŠàŠ¿àŠ€ àŠàаà§àŠš àŠ¯à§ àŠàŠªàŠšàŠ¿ àŠ¯à§ àŠà§àŠšàŠ àŠ
à§àŠ¯àŠŸàŠšà§àŠàŠ¿àŠàŠŸàŠàŠ°àŠŸàŠž àŠªà§àаà§àŠà§àŠ°àŠŸàŠ® àŠàŠšàŠžà§àŠàв àŠàаà§àŠà§àŠš àŠžà§àŠàŠ¿ "
+"àŠàаàŠà§ àŠàŠ²àŠ®àŠŸàŠš àŠ¥à§àŠà§ àŠ¬àŠ¿àŠ°àŠ€ àŠàŠ°àŠŸ àŠ¹àŠà§àŠà§ àŠšàŠŸà¥€ àŠàŠªàŠšàŠŸàŠ° àŠ
à§àŠ¯àŠŸàŠšà§àŠàŠ¿àŠàŠŸàŠàŠ°àŠŸàŠž àŠžàŠ«àŠàŠàŠ¯àŠŒà§àŠ¯àŠŸàŠ°à§àа àŠàŠšà§àН "
+"àŠ¡àŠà§àŠ®à§àŠšà§àŠà§àŠ¶àŠšà§àа àŠžàŠŸàŠ¥à§ àŠªàŠ°àŠŸàŠ®àŠ°à§àж àŠàŠ°àŠ€à§ àŠ¹àŠ¬à§ àŠ¯àŠŠàŠ¿ àŠàŠªàŠšàŠ¿ àŠàŠàŠ¿ àŠàŠ¿àŠàŠŸàŠ¬à§ àŠàŠ°àŠ€à§ àŠšàŠŸ àŠàŠŸàŠšà§àŠšà¥€"
+
+#: troubleshooting.page:49
+msgid "Temporarily disable your firewall."
+msgstr "àŠ
àŠžà§àŠ¥àŠŸàŠ¯àŠŒà§àŠàŠŸàŠ¬à§ àŠàŠªàŠšàŠŸàŠ° àŠ«àŠŸàŠ¯àŠŒàŠŸàŠ°àŠàŠ¯àŠŒàŠŸàŠ² àŠ
àŠà§àŠ·àŠ® àŠàаà§àŠšà¥€"
+
+#: troubleshooting.page:54
+msgid ""
+"Delete Tor Browser and install it again. If updating, do not just overwrite "
+"your previous Tor Browser files; ensure they are fully deleted beforehand."
+msgstr ""
+"àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ° àŠ®à§àŠà§àŠš àŠàŠ¬àŠ àŠàŠàŠ¿ àŠàŠ¬àŠŸàŠ° àŠàŠšàŠžà§àŠàв àŠàаà§àŠšà¥€ àŠàŠªàŠ¡à§àŠ àŠàŠ°àŠ²à§, àŠ¶à§àŠ§à§ àŠàŠªàŠšàŠŸàŠ° àŠªà§àаà§àЬà§àа "
+"àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ° àŠ«àŠŸàŠàвàŠà§àŠ²àŠ¿àŠà§ àŠàŠàŠŸàŠ°àŠ°àŠŸàŠàŠ àŠàŠ°àŠ¬à§àŠš àŠšàŠŸ; àŠ€àŠŸàŠ°àŠŸ àŠªà§àаà§àŠªà§àŠ°àŠ¿ àŠªà§àаà§àŠªà§àŠ°àŠ¿ àŠ®à§àŠà§ àŠ«à§àŠ²àŠŸ "
+"àŠ¹àŠ¯àŠŒ àŠšàŠ¿àŠ¶à§àŠàŠ¿àŠ€à¥€"
+
+#: troubleshooting.page:64
+msgid "Is your connection censored?"
+msgstr "àŠàŠªàŠšàŠŸàŠ° àŠžàŠàНà§àŠ àŠžà§àŠšà§àŠžàŠ° àŠ¹àŠ¯àŠŒ?"
+
+#: troubleshooting.page:65
+msgid ""
+"If you still canât connect, your Internet Service Provider might be "
+"censoring connections to the Tor network. Read the <link "
+"xref=\"circumvention\">Circumvention</link> section for possible solutions."
+msgstr ""
+"àŠàŠªàŠšàŠ¿ àŠ¯àŠŠàŠ¿ àŠàŠàŠšàŠ àŠžàŠàНà§àŠ àŠàŠ°àŠ€à§ àŠšàŠŸ àŠªàŠŸàŠ°à§àŠš, àŠ€àŠŸàŠ¹àŠ²à§ àŠàŠªàŠšàŠŸàŠ° àŠàŠšà§àŠàŠŸàŠ°àŠšà§àŠ àŠªàŠ°àŠ¿àŠ·à§àŠ¬àŠŸ àŠžàŠ°àŠ¬àŠ°àŠŸàŠ¹àŠàŠŸàŠ°à§ "
+"àŠàа àŠšà§àŠàŠàŠ¯àŠŒàŠŸàŠ°à§àŠà§ àŠžàŠàНà§àŠ àŠ¬àŠ¿àŠà§àŠàŠ¿àŠšà§àŠš àŠ¹àŠ€à§ àŠªàŠŸàŠ°à§à¥€ àŠžàŠ®à§àŠàЬ àŠžàŠ®àŠŸàŠ§àŠŸàŠš àŠàŠšà§àН àŠžà§àŠ®àŠŸàŠ¬àŠŠà§àŠ§àŠ€àŠŸ "
+"àŠ
àŠ§à§àŠ¯àŠŸàŠ¯àŠŒ àŠªàŠ¡àŠŒà§àŠš"
+
+#: troubleshooting.page:74
+msgid "Known issues"
+msgstr "àŠà§àŠàŠŸàŠ€ àŠžàŠ®àŠžà§àŠ¯àŠŸ"
+
+#: troubleshooting.page:75
+msgid ""
+"Tor Browser is under constant development, and some issues are known about "
+"but not yet fixed. Please check the <link xref=\"known-issues\">Known "
+"Issues</link> page to see if the problem you are experiencing is already "
+"listed there."
+msgstr ""
+"àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ° àŠ§à§àаà§àŠ¬àŠ àŠàŠšà§àŠšàŠ¯àŠŒàŠš àŠ
àŠ§à§àŠšà§, àŠàŠ¬àŠ àŠàŠ¿àŠà§ àŠ¬àŠ¿àŠ·àŠ¯àŠŒ àŠžàŠ®à§àŠªàŠ°à§àŠà§ àŠàŠŸàŠšàŠŸ àŠ¯àŠŸàŠ¯àŠŒ àŠàŠ¿àŠšà§àŠ€à§ "
+"àŠàŠàŠšà§ àŠžàŠàжà§àŠ§àŠš àŠàŠ°àŠŸ àŠ¹àŠ¯àŠŒ àŠšàŠ¿à¥€ àŠàŠªàŠšàŠ¿ àŠžàŠ®à§àŠ®à§àŠà§àŠš àŠžàŠ®àŠžà§àŠ¯àŠŸ àŠàŠ€àŠ¿àŠ®àŠ§à§àŠ¯à§ àŠžà§àŠàŠŸàŠšà§ àŠ€àŠŸàŠ²àŠ¿àŠàŠŸàŠà§àŠà§àŠ€ àŠàŠ°àŠŸ"
+" àŠ¹àŠ¯àŠŒ àŠàŠ¿àŠšàŠŸ àŠ€àŠŸ àŠàŠŸàŠšàŠŸàŠ° àŠàŠšà§àН àŠà§àŠàŠŸàŠ€ àŠžàŠ®àŠžà§àŠ¯àŠŸ àŠªà§àŠ·à§àŠ àŠŸ àŠà§àŠ àŠàаà§àŠšà¥€"
+
+#: uninstalling.page:6
+msgid "How to remove Tor Browser from your system"
+msgstr "àŠàŠªàŠšàŠŸàŠ° àŠžàŠ¿àŠžà§àŠà§àŠ® àŠ¥à§àŠà§ àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ° àŠ
àŠªàŠžàŠŸàŠ°àŠ£ àŠàŠ¿àŠàŠŸàŠ¬à§"
+
+#: uninstalling.page:10
+msgid "Uninstalling"
+msgstr "àŠàŠšàŠàŠšàŠžà§àŠàв àŠ¹àŠà§àŠà§"
+
+#: uninstalling.page:12
+msgid ""
+"Tor Browser does not affect any of the existing software or settings on your"
+" computer. Uninstalling Tor Browser will not affect your systemâs software "
+"or settings."
+msgstr ""
+"àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ° àŠà§àŠšàŠ àŠ¬àŠ¿àŠŠà§àŠ¯àŠ®àŠŸàŠš àŠžàŠ«àŠàŠàŠ¯àŠŒà§àŠ¯àŠŸàŠ° àŠ¬àŠŸ àŠàŠªàŠšàŠŸàŠ° àŠàŠ®à§àŠªàŠ¿àŠàŠàŠŸàŠ°à§àа àŠžà§àŠàŠ¿àŠàŠžàŠà§ àŠªà§àаàŠàŠŸàŠ¬àŠ¿àŠ€ "
+"àŠàŠ°à§ àŠšàŠŸà¥€ àŠàŠšàŠàŠšàŠžà§àŠàв àŠàŠ°àŠŸ àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ° àŠàŠªàŠšàŠŸàŠ° àŠžàŠ¿àŠžà§àŠà§àŠ®à§àа àŠžàŠ«à§àŠàŠàŠ¯àŠŒà§àŠ¯àŠŸàŠ° àŠ¬àŠŸ àŠžà§àŠàŠ¿àŠàŠž "
+"àŠªà§àаàŠàŠŸàŠ¬àŠ¿àŠ€ àŠàŠ°àŠ¬à§ àŠšàŠŸà¥€"
+
+#: uninstalling.page:18
+msgid "Removing Tor Browser from your system is simple:"
+msgstr "àŠàŠªàŠšàŠŸàŠ° àŠžàŠ¿àŠžà§àŠà§àŠ® àŠ¥à§àŠà§ àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ° àŠ
àŠªàŠžàŠŸàŠ°àŠ£ àŠžàŠ¹àŠ:"
+
+#: uninstalling.page:24
+msgid ""
+"Locate your Tor Browser folder. The default location on Windows is the "
+"Desktop; on Mac OS X it is the Applications folder. On Linux, there is no "
+"default location, however the folder will be named \"tor-browser_en-US\" if "
+"you are running the English Tor Browser."
+msgstr ""
+"àŠàŠªàŠšàŠŸàŠ° àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ° àŠ«à§àвà§àŠ¡àŠŸàŠ° àŠžàŠšàŠŸàŠà§àŠ€à¥€ àŠàŠàŠšà§àŠ¡à§àŠà§àа àŠ¡àŠ¿àŠ«àŠ²à§àŠ àŠ
àŠ¬àŠžà§àŠ¥àŠŸàŠšàŠàŠ¿ àŠ¡à§àŠžà§àŠàŠàŠª; àŠ®à§àŠ¯àŠŸàŠ "
+"àŠàŠàŠž àŠàŠà§àŠž àŠ àŠàŠàŠ¿ àŠ
à§àŠ¯àŠŸàŠªà§àŠ²àŠ¿àŠà§àŠ¶àŠš àŠ«à§àвà§àŠ¡àŠŸàŠ°à¥€ àŠ²àŠ¿àŠšàŠŸàŠà§àŠžà§, àŠà§àŠš àŠ¡àŠ¿àŠ«àŠ²à§àŠ àŠ
àŠ¬àŠžà§àŠ¥àŠŸàŠš àŠšà§àŠ, àŠ€àŠ¬à§ "
+"àŠ¯àŠŠàŠ¿ àŠàŠªàŠšàŠ¿ àŠàŠàаà§àŠ àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ° àŠàŠŸàŠ²àŠŸàŠà§àŠà§àŠš àŠ€àŠ¬à§ àŠ«à§àвà§àŠ¡àŠŸàŠ°àŠàŠ¿àŠ° àŠšàŠŸàŠ® \"tor-browser_en-"
+"US\" àŠ¥àŠŸàŠàЬà§à¥€"
+
+#: uninstalling.page:32
+msgid "Delete the Tor Browser folder."
+msgstr "àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ° àŠ«à§àвà§àŠ¡àŠŸàŠ°àŠàŠ¿ àŠ®à§àŠà§àŠš"
+
+#: uninstalling.page:35
+msgid "Empty your Trash"
+msgstr "àŠàŠªàŠšàŠŸàŠ° àŠà§àаà§àŠ¯àŠŸàŠ¶ àŠàŠŸàŠ²àŠ¿ àŠàаà§àŠš"
+
+#: uninstalling.page:39
+msgid ""
+"Note that your operating systemâs standard âUninstallâ utility is not used."
+msgstr ""
+"àŠàвà§àвà§àŠà§àН àŠàŠªàŠšàŠŸàŠ° àŠ
àŠªàŠŸàŠ°à§àŠàŠ¿àŠ àŠžàŠ¿àŠžà§àŠà§àŠ®à§àа àŠ®àŠŸàŠš \"àŠàŠšàŠàŠšàŠžà§àŠàв\" àŠàŠàŠàŠ¿àŠ²àŠ¿àŠàŠ¿ àŠ¬à§àŠ¯àŠ¬àŠ¹àŠŸàŠ° àŠàŠ°àŠŸ àŠ¹àŠ¯àŠŒ "
+"àŠšàŠŸà¥€"
+
+#: updating.page:6
+msgid "How to update Tor Browser"
+msgstr "àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ° àŠàŠªàŠ¡à§àŠ àŠàŠ¿àŠàŠŸàŠ¬à§"
+
+#: updating.page:10
+msgid "Updating"
+msgstr "àŠàŠªàŠ¡à§àŠ àŠàŠ°àŠŸ àŠ¹àŠà§àŠà§"
+
+#: updating.page:12
+msgid ""
+"Tor Browser must be kept updated at all times. If you continue to use an "
+"outdated version of the software, you may be vulnerable to serious security "
+"flaws that compromise your privacy and anonymity."
+msgstr ""
+"àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ° àŠžàŠ¬ àŠžàŠ®àŠ¯àŠŒà§ àŠàŠªàŠ¡à§àŠ àŠàŠ°àŠŸ àŠàŠ¬àŠ¶à§àНàŠà¥€ àŠàŠªàŠšàŠ¿ àŠ¯àŠŠàŠ¿ àŠžàŠ«à§àŠàŠàŠ¯àŠŒà§àŠ¯àŠŸàŠ°à§àа àŠàŠàŠàŠ¿ àŠªà§àаà§àŠšà§ "
+"àŠžàŠàŠžà§àŠàŠ°àŠ£ àŠ¬à§àŠ¯àŠ¬àŠ¹àŠŸàŠ° àŠàŠ°àŠŸ àŠàŠŸàŠ²àŠ¿àŠ¯àŠŒà§ àŠ¯àŠŸàŠš, àŠ€àŠŸàŠ¹àŠ²à§ àŠàŠªàŠšàŠŸàŠ° àŠà§àŠªàŠšà§àŠ¯àŠŒàŠ€àŠŸ àŠàŠ¬àŠ àŠà§àŠªàŠšà§àŠ¯àŠŒàŠ€àŠŸàŠ° àŠžàŠŸàŠ¥à§ "
+"àŠàŠªàŠž àŠàŠ°à§ àŠàŠ®àŠš àŠà§àаà§àŠ€àŠ° àŠšàŠ¿àŠ°àŠŸàŠªàŠ€à§àŠ€àŠŸ àŠ€à§àаà§àŠàŠ¿àŠà§àŠ²àŠ¿àŠ° àŠàŠšà§àН àŠàŠªàŠšàŠ¿ àŠŠà§àаà§àŠ¬àŠ² àŠ¹àŠ€à§ àŠªàŠŸàŠ°à§àŠšà¥€"
+
+#: updating.page:18
+msgid ""
+"Tor Browser will prompt you to update the software once a new version has "
+"been released: the Torbutton icon will display a yellow triangle, and you "
+"may see a written update indicator when Tor Browser opens. You can update "
+"either automatically or manually."
+msgstr ""
+"àŠàŠ°à§ àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ° àŠàŠªàŠšàŠŸàŠà§ àŠšàŠ€à§àŠš àŠžàŠ«à§àŠàŠàŠ¯àŠŒà§àŠ¯àŠŸàŠ° àŠàŠªàŠ¡à§àŠ àŠàŠ°àŠŸàŠ° àŠàŠšà§àН àŠžàŠ«à§àŠàŠàŠ¯àŠŒà§àŠ¯àŠŸàŠ°àŠàŠ¿ àŠàŠªàŠ¡à§àŠ "
+"àŠàŠ°àŠ€à§ àŠ¬àŠ²àŠ¬à§: Torbutton àŠàŠàŠàŠšàŠàŠ¿ àŠàŠàŠàŠ¿ àŠ¹àŠ²à§àŠŠ àŠ€à§àŠ°àŠ¿àŠà§àŠ àŠªà§àŠ°àŠŠàŠ°à§àŠ¶àŠš àŠàŠ°àŠ¬à§ àŠàŠ¬àŠ àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ° "
+"àŠà§àŠ²àŠŸàŠ° àŠªàŠ° àŠàŠªàŠšàŠ¿ àŠàŠàŠàŠ¿ àŠ²àŠ¿àŠàŠ¿àŠ€ àŠàŠªàŠ¡à§àŠ àŠšàŠ¿àŠ°à§àŠŠà§àŠ¶àŠ àŠŠà§àŠàŠ€à§ àŠªàŠŸàŠ¬à§àŠšà¥€ àŠàŠªàŠšàŠ¿ àŠžà§àŠ¬àŠ¯àŠŒàŠàŠà§àŠ°àŠ¿àŠ¯àŠŒàŠàŠŸàŠ¬à§ "
+"àŠ¬àŠŸ àŠ®à§àŠ¯àŠŸàŠšà§àŠ¯àŠŒàŠŸàŠ² àŠàŠªàŠ¡à§àŠ àŠàŠ°àŠ€à§ àŠªàŠŸàŠ°à§àŠšà¥€"
+
+#: updating.page:26
+msgid "Updating Tor Browser automatically"
+msgstr "àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ° àŠžà§àŠ¬àŠ¯àŠŒàŠàŠà§àŠ°àŠ¿àŠ¯àŠŒàŠàŠŸàŠ¬à§ àŠàŠªàŠ¡à§àŠ àŠ¹àŠà§àŠà§"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: updating.page:30
+msgctxt "_"
+msgid ""
+"external ref='media/updating/update1.png' "
+"md5='9ff01eb653d92124746fc31efde2bf07'"
+msgstr ""
+"àŠ¬àŠŸàŠ¹à§àŠ¯àŠ¿àŠ àŠ°à§àŠ«='media/updating/update1.png' "
+"md5='9ff01eb653d92124746fc31efde2bf07'"
+
+#: updating.page:32
+msgid ""
+"When you are prompted to update Tor Browser, click on the Torbutton icon, "
+"then select âCheck for Tor Browser Updateâ."
+msgstr ""
+"àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ° àŠàŠªàŠ¡à§àŠ àŠàŠ°àŠŸàŠ° àŠàŠšà§àН àŠàŠªàŠšàŠŸàŠà§ àŠªàŠ°àŠŸàŠ®àŠ°à§àж àŠŠà§àŠàŠ¯àŠŒàŠŸ àŠ¹àŠ²à§ Torbutton àŠàŠàŠàŠšà§ àŠà§àŠ²àŠ¿àŠ "
+"àŠàаà§àŠš, àŠ€àŠŸàŠ°àŠªàŠ° \"àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ° àŠàŠªàŠ¡à§àŠà§àа àŠàŠšà§àН àŠà§àŠ àŠàаà§àŠš\" àŠšàŠ¿àŠ°à§àŠ¬àŠŸàŠàŠš àŠàаà§àŠšà¥€"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: updating.page:39
+msgctxt "_"
+msgid ""
+"external ref='media/updating/update3.png' "
+"md5='4bd08622b0cacf20b13f75c432176ed3'"
+msgstr ""
+"àŠ¬àŠŸàŠ¹à§àŠ¯àŠ¿àŠ àŠ°à§àŠ«='media/updating/update3.png' "
+"md5='4bd08622b0cacf20b13f75c432176ed3'"
+
+#: updating.page:41
+msgid ""
+"When Tor Browser has finished checking for updates, click on the âUpdateâ "
+"button."
+msgstr ""
+"àŠ¯àŠàŠš àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ° àŠàŠªàŠ¡à§àŠàŠà§àŠ²àŠ¿àŠ° àŠàŠšà§àН àŠªàŠ°à§àŠà§àŠ·àŠŸ àŠžàŠ®àŠŸàŠªà§àŠ€ àŠàаà§, àŠ€àŠàŠš \"àŠàŠªàŠ¡à§àŠ\" àŠ¬à§àŠ€àŠŸàŠ®à§ "
+"àŠà§àŠ²àŠ¿àŠ àŠàаà§àŠšà¥€"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: updating.page:48
+msgctxt "_"
+msgid ""
+"external ref='media/updating/update4.png' "
+"md5='1d795e7b695738531db9d4b2b0fb5313'"
+msgstr ""
+"àŠ¬àŠŸàŠ¹à§àŠ¯àŠ¿àŠ àŠ°à§àŠ«='media/updating/update4.png' "
+"md5='1d795e7b695738531db9d4b2b0fb5313'"
+
+#: updating.page:50
+msgid ""
+"Wait for the update to download and install, then restart Tor Browser. You "
+"will now be running the latest version."
+msgstr ""
+"àŠ¡àŠŸàŠàŠšàŠ²à§àŠ¡ àŠàŠ¬àŠ àŠàŠšàŠžà§àŠàв àŠàŠ°àŠŸàŠ° àŠàŠªàŠ¡à§àŠà§àа àŠàŠšà§àН àŠ
àŠªà§àŠà§àŠ·àŠŸ àŠàаà§àŠš, àŠ€àŠŸàŠ°àŠªàŠ° àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ° àŠªà§àŠšàŠ°àŠŸàŠ¯àŠŒ"
+" àŠàŠŸàŠ²à§ àŠàаà§àŠšà¥€ àŠàŠªàŠšàŠ¿ àŠàŠàŠš àŠžàŠ°à§àŠ¬àŠ¶à§àŠ· àŠžàŠàŠžà§àŠàŠ°àŠ£ àŠàŠ²àŠ®àŠŸàŠš àŠ¹àŠ¬à§à¥€"
+
+#: updating.page:58
+msgid "Updating Tor Browser manually"
+msgstr "àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ° àŠàŠªàŠ¡à§àŠ àŠ¹àŠà§àŠà§ àŠ®à§àŠ¯àŠŸàŠšà§àŠ¯àŠŒàŠŸàŠ²àŠ¿"
+
+#: updating.page:61
+msgid ""
+"When you are prompted to update Tor Browser, finish the browsing session and"
+" close the program."
+msgstr ""
+"àŠàŠªàŠšàŠ¿ àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ° àŠàŠªàŠ¡à§àŠ àŠàŠ°àŠŸàŠ° àŠ
àŠšà§àаà§àЧ àŠàŠŸàŠšàŠŸàŠšà§ àŠ¹àŠ²à§, àŠ¬à§àŠ°àŠŸàŠàŠàŠ¿àŠ àŠ
àŠ§àŠ¿àŠ¬à§àŠ¶àŠš àŠ¶à§àŠ· àŠàаà§àŠš àŠàЬàŠ"
+" àŠªà§àаà§àŠà§àŠ°àŠŸàŠ® àŠ¬àŠšà§àЧ àŠàаà§àŠšà¥€"
+
+#: updating.page:67
+msgid ""
+"Remove Tor Browser from your system by deleting the folder that contains it "
+"(see the <link xref=\"uninstalling\">Uninstalling</link> section for more "
+"information)."
+msgstr ""
+"àŠàŠªàŠšàŠŸàŠ° àŠžàŠ¿àŠžà§àŠà§àŠ®à§ àŠ«à§àвà§àŠ¡àŠŸàŠ°àŠàŠ¿ àŠ®à§àŠà§ àŠŠàŠ¿àŠ¯àŠŒà§ àŠàа àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ°àŠàŠ¿ àŠžàŠ°àŠŸàŠš (àŠàŠ°àŠ àŠ€àŠ¥à§àНà§àа àŠàŠšà§àН "
+"àŠàŠšàŠàŠšàŠžà§àŠàв àŠ¬àŠ¿àŠàŠŸàŠ àŠŠà§àŠà§àŠš)ी"
+
+#: updating.page:74
+msgid ""
+"Visit <link href=\"https://www.torproject.org/projects/torbrowser.html.en\">"
+" https://www.torproject.org/projects/torbrowser.html.en</link> and download "
+"a copy of the latest Tor Browser release, then install it as before."
+msgstr ""
+"Https://www.torproject.org/projects/torbrowser.html àŠ àŠ¯àŠŸàŠš àŠàŠ¬àŠ àŠžàŠ°à§àŠ¬àŠ¶à§àŠ· àŠàа "
+"àŠ¬à§àŠ°àŠŸàŠàŠàŠŸàŠ° àŠ°àŠ¿àŠ²àŠ¿àŠà§àа àŠàŠàŠàŠ¿ àŠ
àŠšà§àŠ²àŠ¿àŠªàŠ¿ àŠ¡àŠŸàŠàŠšàŠ²à§àŠ¡ àŠàаà§àŠš, àŠ€àŠŸàŠ°àŠªàŠ°à§ àŠàŠàŠ¿ àŠàŠà§àа àŠ®àŠ€à§ àŠàŠšàŠžà§àŠàв àŠàаà§àŠš"
1
0
commit 517096c017eaf461abbc61f3c4ebb14de7ba2996
Author: Colin Childs <colin(a)torproject.org>
Date: Tue Sep 18 14:11:08 2018 -0500
Adding ga translations
---
Makefile.am | 2 +-
ga/ga.po | 2004 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 2005 insertions(+), 1 deletion(-)
diff --git a/Makefile.am b/Makefile.am
index 8b1db95..eb78a9d 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -8,7 +8,7 @@ TOR_AND_HTTPS = ../tor-and-https
HELP_ID = tor-browser-user-manual
HELP_FILES = $(shell cd $(srcdir)/C && git ls-files '*.page')
HELP_MEDIA = $(shell cd $(srcdir)/C && git ls-files 'media')
-HELP_LINGUAS = en-US ja sv @TOR_BROWSER_BUNDLE_LOCALES@
+HELP_LINGUAS = en-US ja sv ga @TOR_BROWSER_BUNDLE_LOCALES@
.PHONY: html
html: all media-symlinks.stamp
diff --git a/ga/ga.po b/ga/ga.po
new file mode 100644
index 0000000..1783f03
--- /dev/null
+++ b/ga/ga.po
@@ -0,0 +1,2004 @@
+# Translators:
+# Robbi McMillen <hi(a)roboplegic.com>, 2016
+# Kevin Scannell <kscanne(a)gmail.com>, 2016
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"POT-Creation-Date: 2018-09-07 16:48-0500\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Kevin Scannell <kscanne(a)gmail.com>, 2016\n"
+"Language-Team: Irish (https://www.transifex.com/otf/teams/1519/ga/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: ga\n"
+"Plural-Forms: nplurals=5; plural=(n==1 ? 0 : n==2 ? 1 : n<7 ? 2 : n<11 ? 3 : 4);\n"
+
+#. Put one translator per line, in the form NAME <EMAIL>, YEAR1, YEAR2
+msgctxt "_"
+msgid "translator-credits"
+msgstr "Kevin Scannell <kscanne at gmail>, 2017"
+
+#: about-tor-browser.page:7
+msgid "Learn what Tor Browser can do to protect your privacy and anonymity"
+msgstr ""
+"Foghlaim conas is féidir Brabhsálaí Tor a úsáid chun do phríobháideachas "
+"agus d'aitheantas a chosaint ar líne."
+
+#: about-tor-browser.page:10
+msgid "About Tor Browser"
+msgstr "Maidir le Brabhsálaí Tor"
+
+#: about-tor-browser.page:12
+msgid ""
+"Tor Browser uses the Tor network to protect your privacy and anonymity. "
+"Using the Tor network has two main properties:"
+msgstr ""
+"Úsáideann Brabhsálaí Tor líonra Tor chun do phríobháideachas a chosaint. "
+"Baineann dhá ghné speisialta le líonra Tor:"
+
+#: about-tor-browser.page:18
+msgid ""
+"Your internet service provider, and anyone watching your connection locally,"
+" will not be able to track your internet activity, including the names and "
+"addresses of the websites you visit."
+msgstr ""
+"Ní bheidh do sholáthraí seirbhíse Idirlín, ná aon duine atá ag faire ort go "
+"háitiúil, in ann do chuid gníomhaíochta ar líne a lorg, ainmneacha agus "
+"seoltaí na suíomh a dtugann tú cuairt orthu san áireamh."
+
+#: about-tor-browser.page:25
+msgid ""
+"The operators of the websites and services that you use, and anyone watching"
+" them, will see a connection coming from the Tor network instead of your "
+"real Internet (IP) address, and will not know who you are unless you "
+"explicitly identify yourself."
+msgstr ""
+"Feicfidh na daoine atá i gceannas ar na suímh agus ar na seirbhísí a "
+"úsáideann tú, agus na daoine ag breathnú orthu, ceangal ag teacht ó líonra "
+"Tor seachas ó d'fhíorsheoladh Idirlín (IP), agus ní bheidh a fhios acu cé "
+"thú féin mura ligeann tú d'aithne chucu d'aon turas."
+
+#: about-tor-browser.page:34
+msgid ""
+"In addition, Tor Browser is designed to prevent websites from "
+"“fingerprinting” or identifying you based on your browser configuration."
+msgstr ""
+"Chomh maith leis sin, déanann Brabhsálaí Tor a dhícheall cosc a chur ar "
+"“mhéarlorgaireacht”, is é sin bheith do d'aithint bunaithe ar chumraíocht do"
+" bhrabhsálaí."
+
+#: about-tor-browser.page:39
+msgid ""
+"By default, Tor Browser does not keep any browsing history. Cookies are only"
+" valid for a single session (until Tor Browser is exited or a <link xref"
+"=\"managing-identities#new-identity\">New Identity</link> is requested)."
+msgstr ""
+"De réir réamhshocraithe, ní choinníonn Brabhsálaí Tor aon stair bhrabhsála. "
+"Bíonn fianáin bailí ar feadh seisiúin amháin (go dtí go scoirfidh tú de Tor,"
+" nó go dtí go n-iarrfaidh tú <link xref=\"managing-identities#new-"
+"identity\">Aitheantas Nua</link>)."
+
+#: about-tor-browser.page:50
+msgid "How Tor works"
+msgstr "Cén chaoi a n-oibríonn Tor"
+
+#: about-tor-browser.page:52
+msgid ""
+"Tor is a network of virtual tunnels that allows you to improve your privacy "
+"and security on the Internet. Tor works by sending your traffic through "
+"three random servers (also known as <em>relays</em>) in the Tor network. The"
+" last relay in the circuit (the “exit relay”) then sends the traffic out "
+"onto the public Internet."
+msgstr ""
+"Is líonra tollán fíorúil é Tor a chabhraíonn leat do phríobháideachas agus "
+"do shlándáil ar an Idirlíon a fheabhsú. Seolann Tor do chuid tráchta trí trí"
+" fhreastalaí randamacha (a dtugtar <em>athsheachadáin</em> orthu) i líonra "
+"Tor. Ansin seolann an t-athsheachadán deireanach sa chiorcad (\"an "
+"t-athsheachadán amach\") an trácht amach go dtí an tIdirlíon poiblí."
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: about-tor-browser.page:59
+msgctxt "_"
+msgid ""
+"external ref='media/how-tor-works.png' "
+"md5='6fe4151a88b7a518466f0582e40ccc8c'"
+msgstr ""
+"external ref='media/how-tor-works.png' "
+"md5='6fe4151a88b7a518466f0582e40ccc8c'"
+
+#: about-tor-browser.page:60
+msgid ""
+"The image above illustrates a user browsing to different websites over Tor. "
+"The green middle computers represent relays in the Tor network, while the "
+"three keys represent the layers of encryption between the user and each "
+"relay."
+msgstr ""
+"Léiríonn an pictiúr thuas úsáideoir ag brabhsáil suíomhanna éagsúla thar "
+"Tor. Athsheachadáin i líonra Tor is ea na ríomhairí uaine sa lár, agus "
+"léiríonn na trí eochair na trí shraith chriptithe idir an úsáideoir agus "
+"gach athsheachadán."
+
+#: bridges.page:6
+msgid "Learn what bridges are and how to get them"
+msgstr "Foghlaim cad is droichead ann, agus conas is féidir droichid a fháil"
+
+#: bridges.page:10
+msgid "Bridges"
+msgstr "Droichid"
+
+#: bridges.page:12
+msgid ""
+"Most <link xref=\"transports\">Pluggable Transports</link>, such as obfs3 "
+"and obfs4, rely on the use of “bridge” relays. Like ordinary Tor relays, "
+"bridges are run by volunteers; unlike ordinary relays, however, they are not"
+" listed publicly, so an adversary cannot identify them easily. Using bridges"
+" in combination with pluggable transports helps to disguise the fact that "
+"you are using Tor."
+msgstr ""
+"Úsáideann an chuid is mó de na <link xref=\"transports\">Córais Iompair "
+"Ionphlugáilte</link>, mar shampla obfs3 agus obfs4, athsheachadáin "
+"\"droichid\". Cosúil le gnáth-athsheachadáin Tor, is iad saorálaithe atá i "
+"gceannas ar na droichid seo; ach, murab ionann is gnáth-athsheachadán, ní "
+"fhoilsítear go poiblí iad, sa chaoi nárbh fhéidir le namhaid iad a aithint "
+"go héasca. Nuair a úsáideann tú droichead in éineacht le córas iompair "
+"inphlugáilte, níl sé soiléir go bhfuil tú ag úsáid Tor."
+
+#: bridges.page:21
+msgid ""
+"Other pluggable transports, like meek, use different anti-censorship "
+"techniques that do not rely on bridges. You do not need to obtain bridge "
+"addresses in order to use these transports."
+msgstr ""
+"Úsáideann córais iompair ionphlugáilte eile, mar shampla meek, modhanna "
+"frithchinsireachta difriúla nach bhfuil ag brath ar dhroichid ar chor ar "
+"bith. Ní gá duit seoladh droichid a fháil chun na córais iompair seo a "
+"úsáid."
+
+#: bridges.page:28
+msgid "Getting bridge addresses"
+msgstr "Seoltaí droichid á bhfáil"
+
+#: bridges.page:29
+msgid ""
+"Because bridge addresses are not public, you will need to request them "
+"yourself. You have two options:"
+msgstr ""
+"Toisc nach bhfuil seoltaí droichid ar fáil go poiblí, caithfidh tú iad a "
+"iarraidh as do stuaim féin. Tá dhá rogha agat:"
+
+#: bridges.page:36
+msgid ""
+"Visit <link "
+"href=\"https://bridges.torproject.org/\">https://bridges.torproject.org/</link>"
+" and follow the instructions, or"
+msgstr ""
+"Tabhair cuairt ar <link "
+"href=\"https://bridges.torproject.org/\">https://bridges.torproject.org/</link>"
+" agus lean na treoracha, nó"
+
+#: bridges.page:42
+msgid ""
+"Email bridges(a)torproject.org from a Gmail, Yahoo, or Riseup email address, "
+"or"
+msgstr ""
+"Seol ríomhphost chuig bridges(a)torproject.org ó sheoladh Gmail, Yahoo, nó "
+"Riseup, nó"
+
+#: bridges.page:51
+msgid "Entering bridge addresses"
+msgstr "Seoltaí droichid a chur isteach"
+
+#: bridges.page:52
+msgid ""
+"Once you have obtained some bridge addresses, you will need to enter them "
+"into Tor Launcher."
+msgstr ""
+"Tar éis duit roinnt seoltaí droichid a fháil, caithfidh tú iad a chur "
+"isteach i dTosaitheoir Tor."
+
+#: bridges.page:57
+msgid ""
+"Choose “yes” when asked if your Internet Service Provider blocks connections"
+" to the Tor network. Select “Use custom bridges” and enter each bridge "
+"address on a separate line."
+msgstr ""
+"Roghnaigh \"tá\" nuair a fhiafraítear díot an bhfuil do Sholáthraí Seirbhíse"
+" Idirlín ag cur cosc ar cheangail le líonra Tor. Roghnaigh “Cuir isteach "
+"droichid saincheaptha” agus cuir gach seoladh droichid isteach ar a líne "
+"féin."
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: bridges.page:63
+msgctxt "_"
+msgid ""
+"external ref='media/tor-launcher-custom-bridges.png' "
+"md5='34b5e99516d297fcbb467209d8479f40'"
+msgstr ""
+"external ref='media/tor-launcher-custom-bridges.png' "
+"md5='34b5e99516d297fcbb467209d8479f40'"
+
+#: bridges.page:65
+msgid ""
+"Click “Connect”. Using bridges may slow down the connection compared to "
+"using ordinary Tor relays. If the connection fails, the bridges you received"
+" may be down. Please use one of the above methods to obtain more bridge "
+"addresses, and try again."
+msgstr ""
+"Cliceáil “Ceangail”. Seans go mbeidh an ceangal trí dhroichid níos moille ná"
+" gnáthcheangal Tor trí athsheachadáin. Má theipeann ar an gceangal, "
+"b'fhéidir go bhfuil na droichid a fuair tú as fearas. Sa chás sin, ba chóir "
+"duit tuilleadh droichead a fháil trí cheann de na modhanna thuas, ansin "
+"iarracht eile a dhéanamh."
+
+#: circumvention.page:6
+msgid "What to do if the Tor network is blocked"
+msgstr "Má tá cosc ar líonra Tor"
+
+#: circumvention.page:10
+msgid "Circumvention"
+msgstr "Timpeallú"
+
+#: circumvention.page:12
+msgid ""
+"Direct access to the Tor network may sometimes be blocked by your Internet "
+"Service Provider or by a government. Tor Browser includes some circumvention"
+" tools for getting around these blocks. These tools are called “pluggable "
+"transports”. See the <link xref=\"transports\">Pluggable Transports</link> "
+"page for more information on the types of transport that are currently "
+"available."
+msgstr ""
+"Uaireanta ní féidir leat rochtain dhíreach a fháil ar líonra Tor, mar gheall"
+" ar bhac a chuir do Sholáthraí Seirbhíse Idirlín nó rialtas romhat. Cuireann"
+" Brabhsálaí Tor roinnt uirlisí ar fáil a chabhraíonn leat na baic seo a "
+"sheachaint, darb ainm \"córais iompair ionphlugáilte\". Féach ar <link "
+"xref=\"transports\">an leathanach seo</link> chun tuilleadh eolais a fháil "
+"faoi na córais iompair atá ar fáil faoi láthair."
+
+#: circumvention.page:22
+msgid "Using pluggable transports"
+msgstr "Córais iompair ionphlugáilte a úsáid"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: circumvention.page:26 first-time.page:35
+msgctxt "_"
+msgid ""
+"external ref='media/circumvention/configure.png' "
+"md5='1107595d21fe90f2aab1263d7fb0abd3'"
+msgstr ""
+"external ref='media/circumvention/configure.png' "
+"md5='1107595d21fe90f2aab1263d7fb0abd3'"
+
+#: circumvention.page:28
+msgid ""
+"To use pluggable transports, click \"Configure\" in the Tor Launcher window "
+"that appears when you first run Tor Browser."
+msgstr ""
+"Chun córas iompair ionphlugáilte a úsáid, cliceáil \"Cumraigh\" i bhfuinneog"
+" Thosaitheoir Tor a fheiceann tú nuair a ritheann tú Brabhsálaí Tor den "
+"chéad uair."
+
+#: circumvention.page:33
+msgid ""
+"You can also configure pluggable transports while Tor Browser is running, by"
+" clicking on the green onion near your address bar and selecting “Tor "
+"Network Settings”."
+msgstr ""
+"Nó is féidir córais iompair ionphlugáilte a chumrú agus Brabhsálaí Tor ar "
+"siúl, tríd an oinniún glas in aice leis an mbarra suímh a chliceáil agus "
+"\"Socruithe Líonra Tor\" a roghnú."
+
+#: circumvention.page:41
+msgid ""
+"Select “yes” when asked if your Internet Service Provider blocks connections"
+" to the Tor network."
+msgstr ""
+"Roghnaigh \"tá\" nuair a fhiafraítear díot an bhfuil do Sholáthraí Seirbhíse"
+" Idirlín ag cur cosc ar cheangail le líonra Tor."
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: circumvention.page:49
+msgctxt "_"
+msgid ""
+"external ref='media/circumvention/bridges.png' "
+"md5='f5acc05bd9bacf6c69a31163d25a8778'"
+msgstr ""
+"external ref='media/circumvention/bridges.png' "
+"md5='f5acc05bd9bacf6c69a31163d25a8778'"
+
+#: circumvention.page:51
+msgid ""
+"Select “Connect with provided bridges”. Tor Browser currently has six "
+"pluggable transport options to choose from."
+msgstr ""
+"Roghnaigh \"Ceangail le droichead ionsuite\". Tá sé cinn de chórais iompair "
+"ionphlugáilte ar fáil i mbrabhsálaí Tor faoi láthair."
+
+#: circumvention.page:60
+msgid "Which transport should I use?"
+msgstr "Cén cineál iompair ba chóir dom a úsáid?"
+
+#: circumvention.page:61
+msgid ""
+"Each of the transports listed in Tor Launcher’s menu works in a different "
+"way (for more details, see the <link xref=\"transports\">Pluggable "
+"Transports</link> page), and their effectiveness depends on your individual "
+"circumstances."
+msgstr ""
+"Feidhmíonn gach ceann de na córais iompair i dTosaitheoir Tor ar bhealach "
+"difriúil (féach an leathanach <link xref=\"transports\">Córais Iompair "
+"Ionphlugáilte</link> chun tuilleadh eolais a fháil), agus braitheann a "
+"n-éifeachtacht ar na cúinsí speisialta a bhaineann leatsa féin."
+
+#: circumvention.page:67
+msgid ""
+"If you are trying to circumvent a blocked connection for the first time, you"
+" should try the different transports: obfs3, obfs4, ScrambleSuit, fte, meek-"
+"azure and Snowflake."
+msgstr ""
+"Má tá tú ag iarraidh bac a sheachaint den chéad uair, ba chóir duit triail a"
+" bhaint as na cineálacha iompair éagsúla: obfs3, obfs4, ScrambleSuit, fte, "
+"meek-azure, agus Snowflake."
+
+#: circumvention.page:72
+msgid ""
+"If you try all of these options, and none of them gets you online, you will "
+"need to enter bridge addresses manually. Read the <link "
+"xref=\"bridges\">Bridges</link> section to learn what bridges are and how to"
+" obtain them."
+msgstr ""
+"Má bhain tú triail as na roghanna seo go léir agus ní féidir leat dul ar "
+"líne fós, ní mór duit seoltaí droichid a chur isteach de láimh. Léigh an "
+"rannóg maidir le <link xref=\"bridges\">Droichid</link> le foghlaim cad is "
+"droichead ann agus conas is féidir iad a fháil."
+
+#: downloading.page:7
+msgid "How to download Tor Browser"
+msgstr "Conas Brabhsálaí Tor a íoslódáil"
+
+#: downloading.page:10
+msgid "Downloading"
+msgstr "Íoslódáil"
+
+#: downloading.page:12
+msgid ""
+"The safest and simplest way to download Tor Browser is from the official Tor"
+" Project website at https://www.torproject.org. Your connection to the site "
+"will be secured using <link xref=\"secure-connections\">HTTPS</link>, which "
+"makes it much harder for somebody to tamper with."
+msgstr ""
+"Is é íoslódáil ó shuíomh oifigiúil Tor https://www.torproject.org an bealach"
+" is fusa is sábháilte chun Brabhsálaí Tor a fháil. Ceanglóidh tú leis an "
+"suíomh trí <link xref=\"secure-connections\">HTTPS</link>, ionas go mbeidh "
+"sé níos deacra do bhradaí ionsaí a dhéanamh ar an gceangal. "
+
+#: downloading.page:19
+msgid ""
+"However, there may be times when you cannot access the Tor Project website: "
+"for example, it could be blocked on your network. If this happens, you can "
+"use one of the alternative download methods listed below."
+msgstr ""
+"Uaireanta ní bheidh tú in ann suíomh oifigiúil Thionscadal Tor a rochtain; "
+"mar shampla, dá mbeadh cosc air ar do líonra. Má tharlaíonn sé seo, is "
+"féidir leat ceann de na modhanna malartacha seo a leanas a úsáid chun Tor a "
+"íoslódáil."
+
+#: downloading.page:27
+msgid "GetTor"
+msgstr "GetTor"
+
+#: downloading.page:28
+msgid ""
+"GetTor is a service that automatically responds to messages with links to "
+"the latest version of Tor Browser, hosted at a variety of locations, such as"
+" Dropbox, Google Drive and GitHub."
+msgstr ""
+"Is éard atá in GetTor ná seirbhís a fhreagraíonn teachtaireachtaí le "
+"nascanna leis an leagan is déanaí de Bhrabhsálaí Tor, óstáilte in áiteanna "
+"éagsúla, ar nós Dropbox, Tiomántán Google, agus Github."
+
+#: downloading.page:33
+msgid "To use GetTor via email:"
+msgstr "Le GetTor a úsáid trí ríomhphost:"
+
+#: downloading.page:38
+msgid ""
+"Send an email to gettor(a)torproject.org, and in the body of the message "
+"simply write “windows”, “osx”, or “linux”, (without quotation marks) "
+"depending on your operating system."
+msgstr ""
+"Seol teachtaireacht rphoist chuig gettor(a)torproject.org agus cuir an focal "
+"amháín “windows”, “osx”, nó “linux” (gan comharthaí athfhriotail) i gcorp na"
+" teachtaireachta, ag brath ar an gcóras oibriúcháin atá agat."
+
+#: downloading.page:45
+msgid ""
+"GetTor will respond with an email containing links from which you can "
+"download the Tor Browser package, the cryptographic signature (needed for "
+"verifying the download), the fingerprint of the key used to make the "
+"signature, and the package’s checksum. You may be offered a choice of "
+"“32-bit” or “64-bit” software: this depends on the model of the computer you"
+" are using."
+msgstr ""
+"Seolfaidh GetTor ríomhphost ar ais chugat ina bhfuil nascanna le pacáiste "
+"Brabhsálaí Tor, leis an síniú cripteagrafach (chun an íoslódáil a "
+"dheimhniú), le méarlorg na heochrach a úsáideadh chun an síniú a dhéanamh, "
+"agus le suim sheiceála an phacáiste. Seans go mbeidh deis agat leagan "
+"“32-giotán” nó “64-giotán” a íoslódáil; braitheann sé ar an ríomhaire a "
+"úsáideann tú."
+
+#: downloading.page:56
+msgid "To use GetTor via Twitter:"
+msgstr "Le GetTor a úsáid trí Twitter:"
+
+#: downloading.page:61
+msgid ""
+"To get links for downloading Tor Browser in English for OS X, send a Direct "
+"Message to @get_tor with the words \"osx en\" in it (you don't need to "
+"follow the account)."
+msgstr ""
+"Más mian leat Brabhsálaí Tor i mBéarla ar OS X a íoslódáil, seol "
+"Teachtaireacht Dhíreach chuig @get_tor leis na focail \"osx en\" (ní gá duit"
+" an cuntas a leanúint), agus gheobhaidh tú nasc lena íoslódáil."
+
+#: downloading.page:69
+msgid "To use GetTor via Jabber/XMPP (Jitsi, CoyIM, etc.):"
+msgstr "Le GetTor a úsáid trí Jabber/XMPP (Jitsi, CoyIM, srl.)."
+
+#: downloading.page:74
+msgid ""
+"To get links for downloading Tor Browser in Chinese for Linux, send a "
+"message to gettor(a)torproject.org with the words \"linux zh\" in it."
+msgstr ""
+"Más mian leat Brabhsálaí Tor i Sínis ar Linux a íoslódáil, seol "
+"teachtaireacht chuig gettor(a)torproject.org leis na focail \"linux zh\" inti "
+"agus gheobhaidh tú nasc lena íoslódáil."
+
+#: downloading.page:83
+msgid "Satori"
+msgstr "Satori"
+
+#: downloading.page:84
+msgid ""
+"Satori is an add-on for the Chrome or Chromium browsers that allows you to "
+"download several security and privacy programs from different sources."
+msgstr ""
+"Is breiseán do bhrabhsálaí Chrome nó Chromium é Satori a ligeann duit roinnt"
+" feidhmchlár slándála agus uirlisí príobháideachais a íoslódáil ó fhoinsí "
+"éagsúla."
+
+#: downloading.page:89
+msgid "To download Tor Browser using Satori:"
+msgstr "Le Brabhsálaí Tor a íoslódáil trí Satori:"
+
+#: downloading.page:94
+msgid "Install Satori from the Chrome App Store."
+msgstr "Suiteáil Satori ó Shiopa Chrome."
+
+#: downloading.page:99
+msgid "Select Satori from your browser’s Apps menu."
+msgstr "Roghnaigh Satori sa roghchlár Apps i do bhrabhsálaí."
+
+#: downloading.page:104
+msgid ""
+"When Satori opens, click on your preferred language. A menu will open "
+"listing the available downloads for that language. Find the entry for Tor "
+"Browser under the name of your operating system. Select either “A” or “B” "
+"after the name of the program — each one represents a different source from "
+"which to get the software. Your download will then begin."
+msgstr ""
+"Nuair a osclaíonn Satori, cliceáil do rogha teanga. Osclóidh roghchlár a "
+"thaispeánann na híoslódálacha atá ar fáil don teanga sin. Aimsigh an "
+"iontráil do Bhrabhsálaí Tor faoi ainm do chórais oibriúcháin. Roghnaigh “A” "
+"nó “B” tar éis ainm an fheidhmchláir — seasann siad d'fhoinsí éagsúla ónar "
+"féidir leat an bogearra a fháil. Ansin tosóidh an íoslódáil."
+
+#: downloading.page:114
+msgid ""
+"Wait for your download to finish, then find the “Generate Hash” section in "
+"Satori’s menu and click “Select Files”."
+msgstr ""
+"Fan go gcríochnóidh an íoslódáil, ansin aimsigh an rannán “Generate Hash” i "
+"roghchlár Satori agus cliceáil “Select Files”."
+
+#: downloading.page:120
+msgid ""
+"Select the downloaded Tor Browser file. Satori will display the checksum of "
+"the file, which you should compare with the software’s original checksum: "
+"you can find this by clicking the word “checksum” after the link you clicked"
+" on to start the download. If the checksums match, your download was "
+"successful, and you can <link xref=\"first-time\">begin using Tor "
+"Browser</link>. If they do not match, you may need to try downloading again,"
+" or from a different source."
+msgstr ""
+"Roghnaigh an pacáiste do Bhrabhsálaí Tor a d'íoslódáil tú. Taispeánfaidh "
+"Satori suim sheiceála an phacáiste agus ba chóir duit í a chur i gcomparáid "
+"leis an tsuim sheiceála a tháinig leis an mbogearra féin. Is féidir leat an "
+"uimhir seo a fháil trí “checksum” a chliceáil in aice leis an nasc a d'úsáid"
+" tú chun an pacáiste a íoslódáil. Más ionann na suimeanna seiceála, d'éirigh"
+" leis an íoslódáil, agus tá tú in ann <link xref=\"first-time\">Brabhsálaí "
+"Tor a úsáid</link>. Murab ionann iad, ba chóir duit an pacáiste a íoslódáil "
+"arís, b'fhéidir ó fhoinse difriúil."
+
+#: first-time.page:7
+msgid "Learn how to use Tor Browser for the first time"
+msgstr "An chéad uair a úsáideann tú Tor"
+
+#: first-time.page:10
+msgid "Running Tor Browser for the first time"
+msgstr "An chéad uair a úsáideann tú Brabhsálaí Tor"
+
+#: first-time.page:12
+msgid ""
+"When you run Tor Browser for the first time, you will see the Tor Network "
+"Settings window. This offers you the option to connect directly to the Tor "
+"network, or to configure Tor Browser for your connection."
+msgstr ""
+"Nuair a úsáidfidh tú Brabhsálaí Tor den chéad uair, feicfidh tú an fhuinneog"
+" Socruithe Líonra Tor. Tugann seo rogha duit ceangal go díreach le líonra "
+"Tor, nó Brabhsálaí Tor a chur in oiriúint do do cheangal líonra féin."
+
+#: first-time.page:19
+msgid "Connect"
+msgstr "Ceangail"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: first-time.page:21 troubleshooting.page:18
+msgctxt "_"
+msgid ""
+"external ref='media/first-time/connect.png' "
+"md5='f6de80de01c8fa2a8f80857eb8213768'"
+msgstr ""
+"external ref='media/first-time/connect.png' "
+"md5='f6de80de01c8fa2a8f80857eb8213768'"
+
+#: first-time.page:23
+msgid ""
+"In most cases, choosing \"Connect\" will allow you to connect to the Tor "
+"network without any further configuration. Once clicked, a status bar will "
+"appear, showing Tor’s connection progress. If you are on a relatively fast "
+"connection, but this bar seems to get stuck at a certain point, see the "
+"<link xref=\"troubleshooting\">Troubleshooting</link> page for help solving "
+"the problem."
+msgstr ""
+"De ghnáth, bíonn tú ceangailte le líonra Tor tar éis duit \"Ceangail\" a "
+"chliceáil, gan chumraíocht sa bhreis a dhéanamh. Ansin, feicfidh tú barra "
+"stádais a thaispeánann dul chun cinn an cheangail. Má théann an barra seo in"
+" abar agus ceangal Idirlín measartha maith agat, féach ar an leathanach "
+"<link xref=\"troubleshooting\">Fabhtcheartú</link> chun cúnamh a fháil."
+
+#: first-time.page:33
+msgid "Configure"
+msgstr "Cumraigh"
+
+#: first-time.page:37
+msgid ""
+"If you know that your connection is censored, or uses a proxy, you should "
+"select this option. Tor Browser will take you through a series of "
+"configuration options."
+msgstr ""
+"Má tá a fhios agat go bhfuil do cheangal faoi chinsireacht, nó má úsáideann "
+"sé seachfhreastalaí, ba chóir duit é seo a roghnú. Treoróidh Brabhsálaí Tor "
+"tríd an bpróiseas cumraíochta thú."
+
+#: first-time.page:44
+msgid ""
+"The first screen asks if access to the Tor network is blocked or censored on"
+" your connection. If you do not believe this is the case, select “No”. If "
+"you know your connection is censored, or you have tried and failed to "
+"connect to the Tor network and no other solutions have worked, select “Yes”."
+" You will then be taken to the <link "
+"xref=\"circumvention\">Circumvention</link> screen to configure a pluggable "
+"transport."
+msgstr ""
+"Fiafraítear díot ar an chéad scáileán an bhfuil cosc ar líonra Tor nó an "
+"bhfuil sé faoi chinsireacht ar do cheangal. Mura gcreideann tú go bhfuil, "
+"roghnaigh “Níl”. Má tá a fhios agat go bhfuil do cheangal faoi chinsireacht,"
+" nó má theip ort ceangal a bhunú le líonra Tor gan aon réiteach ar an "
+"bhfadhb, roghnaigh “Tá”. Sa chás sin, osclófar an scáileán <link "
+"xref=\"circumvention\">Timpeallú</link>, áit ar féidir leat córas iompair "
+"ionphlugáilte a shocrú."
+
+#: first-time.page:55
+msgid ""
+"The next screen asks if your connection uses a proxy. In most cases, this is"
+" not necessary. You will usually know if you need to answer “Yes”, as the "
+"same settings will be used for other browsers on your system. If possible, "
+"ask your network administrator for guidance. If your connection does not use"
+" a proxy, click “Continue”."
+msgstr ""
+"Fiafraítear díot ar an chéad scáileán eile an úsáideann do cheangal "
+"seachfhreastalaí. Níl seachfhreastalaí ag teastáil an chuid is mó den am, "
+"agus dá mbeadh sé ag teastáil uaitse, is dócha go mbeadh a fhios agat "
+"cheana, toisc gur ghá na socruithe céanna a úsáid leis na brabhsálaithe eile"
+" ar do chóras. Más féidir, cuir ceist ar riarthóir do líonra. Mura "
+"n-úsáideann do cheangal seachfhreastalaí, cliceáil “Ar Aghaidh”."
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: first-time.page:63
+msgctxt "_"
+msgid ""
+"external ref='media/first-time/proxy_question.png' "
+"md5='f72753a963e3449129718e3d824a8ac8'"
+msgstr ""
+"external ref='media/first-time/proxy_question.png' "
+"md5='f72753a963e3449129718e3d824a8ac8'"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: first-time.page:66
+msgctxt "_"
+msgid ""
+"external ref='media/first-time/proxy.png' "
+"md5='9a5cf5c044b1dfc5f006a9d1ff77507b'"
+msgstr ""
+"external ref='media/first-time/proxy.png' "
+"md5='9a5cf5c044b1dfc5f006a9d1ff77507b'"
+
+#: index.page:8
+msgid "Tor Browser User Manual"
+msgstr "Lámhleabhar Úsáideora Bhrabhsálaí Tor"
+
+#: known-issues.page:6
+msgid "A list of known issues."
+msgstr "Liosta fadhbanna ar eolas."
+
+#: known-issues.page:10
+msgid "Known Issues"
+msgstr "Fadhbanna ar eolas"
+
+#: known-issues.page:14
+msgid ""
+"Tor needs your system clock (and your time zone) set to the correct time."
+msgstr ""
+"Teastaíonn an t-am ceart ar chlog an chórais (agus an crios ama ceart) ó "
+"Tor."
+
+#: known-issues.page:19
+msgid ""
+"The following firewall software have been known to interfere with Tor and "
+"may need to be temporarily disabled:"
+msgstr ""
+"Is eol dúinn go gcuireann na bogearraí balla dóiteáin seo isteach ar Tor, "
+"agus seans gur gá duit iad a dhíchumasú go sealadach:"
+
+#: known-issues.page:23
+msgid "Webroot SecureAnywhere"
+msgstr "Webroot SecureAnywhere"
+
+#: known-issues.page:26
+msgid "Kaspersky Internet Security 2012"
+msgstr "Kaspersky Internet Security 2012"
+
+#: known-issues.page:29
+msgid "Sophos Antivirus for Mac"
+msgstr "Bogearra Frithvíreas Sophos ar Mac"
+
+#: known-issues.page:32
+msgid "Microsoft Security Essentials"
+msgstr "Riachtanais Slándála Microsoft"
+
+#: known-issues.page:37
+msgid ""
+"Videos that require Adobe Flash are unavailable. Flash is disabled for "
+"security reasons."
+msgstr ""
+"Níl aon fháil ar fhíseáin a úsáideann Adobe Flash. Tá Flash díchumasaithe ar"
+" chúiseanna slándála."
+
+#: known-issues.page:43
+msgid "Tor can not use a bridge if a proxy is set."
+msgstr "Ní féidir le Tor droichead a úsáid má tá seachfhreastalaí ann."
+
+#: known-issues.page:48
+msgid ""
+"The Tor Browser package is dated January 1, 2000 00:00:00 UTC. This is to "
+"ensure that each software build is exactly reproducible."
+msgstr ""
+"Is é 1 Eanáir 2000 00:00:00 UTC an dáta ar phacáiste Bhrabhsálaí Tor. "
+"Cinntíonn sé seo gur féidir gach leagan den bhogearra a atáirgeadh go "
+"cruinn."
+
+#: known-issues.page:54
+msgid ""
+"To run Tor Browser on Ubuntu, users need to execute a shell script. Open "
+"\"Files\" (Unity's explorer), open Preferences → Behavior Tab → Set \"Run "
+"executable text files when they are opened\" to \"Ask every time\", then "
+"click OK."
+msgstr ""
+"Caithfidh tú script a rith chun Brabhsálaí Tor a úsáid ar chóras Ubuntu. "
+"Oscail \"File\" (taiscéalaí Unity), oscail Preferences → Behavior Tab agus "
+"faoi \"Run executable text files when they are opened\", roghnaigh \"Ask "
+"every time\", ansin cliceáil \"OK\"."
+
+#: known-issues.page:62
+msgid ""
+"Tor Browser can also be started from the command line by running the "
+"following command from inside the Tor Browser directory:"
+msgstr ""
+"Nó is féidir leat Brabhsálaí Tor a thosú ó líne na n-orduithe tríd an ordú "
+"seo a leanas a rith laistigh de chomhadlann Bhrabhsálaí Tor:"
+
+#: known-issues.page:66
+#, no-wrap
+msgid ""
+"\n"
+" ./start-tor-browser.desktop\n"
+" "
+msgstr ""
+"\n"
+" ./start-tor-browser.desktop\n"
+" "
+
+#: managing-identities.page:6
+msgid "Learn how to control personally-identifying information in Tor Browser"
+msgstr "Foghlaim conas is féidir sonraí pearsanta a rialú i mBrabhsálaí Tor"
+
+#: managing-identities.page:10
+msgid "Managing identities"
+msgstr "Aitheantais a bhainistiú"
+
+#: managing-identities.page:12
+msgid ""
+"When you connect to a website, it is not only the operators of that website "
+"who can record information about your visit. Most websites now use numerous "
+"third-party services, including social networking “Like” buttons, analytics "
+"trackers, and advertising beacons, all of which can link your activity "
+"across different sites."
+msgstr ""
+"Nuair a dhéanann tú ceangal le suíomh Gréasáin, ní iad oibreoirí an tsuímh "
+"amháin atá in ann eolas fútsa a bhailiú. Úsáideann go leor suíomh seirbhísí "
+"tríú páirtí, mar shampla cnaipí sóisialta \"Is maith liom é\", lorgairí "
+"anailísíochta, agus rabhcháin fógraíochta, iad ar fad in ann do chuid "
+"gníomhaíochta a lorg ó shuíomh go suíomh."
+
+#: managing-identities.page:20
+msgid ""
+"Using the Tor network stops observers from being able to discover your exact"
+" location and IP address, but even without this information they might be "
+"able to link different areas of your activity together. For this reason, Tor"
+" Browser includes some additional features that help you control what "
+"information can be tied to your identity."
+msgstr ""
+"Coisceann líonra Tor ar chúléisteoirí do láthair gheografach agus do "
+"sheoladh IP a fháil amach. Ach fiú gan an t-eolas seo, is féidir leo na "
+"rudaí a dhéanann tú in áiteanna éagsúla a nascadh le chéile. Dá bharr seo, "
+"chuireamar roinnt gnéithe i mBrabhsálaí Tor a chuidíonn leat sonraí a "
+"bhaineann leatsa go pearsanta a choinneáil faoi smacht."
+
+#: managing-identities.page:29
+msgid "The URL bar"
+msgstr "An barra URL"
+
+#: managing-identities.page:30
+msgid ""
+"Tor Browser centers your web experience around your relationship with the "
+"website in the URL bar. Even if you connect to two different sites that use "
+"the same third-party tracking service, Tor Browser will force the content to"
+" be served over two different Tor circuits, so the tracker will not know "
+"that both connections originate from your browser."
+msgstr ""
+"Díríonn Brabhsálaí Tor d'eispéireas Gréasáin ar an ngaol idir tusa agus an "
+"suíomh Gréasáin sa bharra URL. Fiú dá ndéanfá ceangal le dhá shuíomh "
+"dhifriúla a bhaineann úsáid as an tseirbhís lorgaireachta chéanna, "
+"d'iarrfadh Brabhsálaí Tor an t-ábhar ó na suímh trí dhá chiorcad Tor "
+"dhifriúla, ionas nach mbeadh a fhios ag an tseirbhís lorgaireachta gur "
+"tháinig an dá cheangal ó do bhrabhsálaí."
+
+#: managing-identities.page:38
+msgid ""
+"On the other hand, all connections to a single website address will be made "
+"over the same Tor circuit, meaning you can browse different pages of a "
+"single website in separate tabs or windows, without any loss of "
+"functionality."
+msgstr ""
+"Os a choinne sin, déanfar gach ceangal le suíomh amháin ar an gciorcad "
+"céanna Tor, rud a chiallaíonn gur féidir leat leathanaigh éagsúla ó shuíomh "
+"Gréasáin amháin a bhrabhsáil i gcluaisíní nó i bhfuinneoga éagsúla, gan chur"
+" isteach ar fheidhmiú an tsuímh."
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: managing-identities.page:46
+msgctxt "_"
+msgid ""
+"external ref='media/managing-identities/circuit_full.png' "
+"md5='bd46d22de952fee42643be46d3f95928'"
+msgstr ""
+"external ref='media/managing-identities/circuit_full.png' "
+"md5='bd46d22de952fee42643be46d3f95928'"
+
+#: managing-identities.page:48
+msgid ""
+"You can see a diagram of the circuit that Tor Browser is using for the "
+"current tab in the onion menu."
+msgstr ""
+"Is féidir leat léaráid den chiorcad atá in úsáid sa chluaisín reatha a fháil"
+" i roghchlár an oinniúin."
+
+#: managing-identities.page:55
+msgid "Logging in over Tor"
+msgstr "Logáil isteach trí Tor"
+
+#: managing-identities.page:56
+msgid ""
+"Although Tor Browser is designed to enable total user anonymity on the web, "
+"there may be situations in which it makes sense to use Tor with websites "
+"that require usernames, passwords, or other identifying information."
+msgstr ""
+"Cé cur dearadh Brabhsálaí Tor chun cabhrú leat d'aitheantas a choinneáil i "
+"bhfolach ar an nGréasán, uaireanta tá sé ciallmhar Tor a úsáid ar shuímh "
+"Ghréasáin a éilíonn ainm úsáideora, focal faire, nó faisnéis phearsanta "
+"eile. "
+
+#: managing-identities.page:62
+msgid ""
+"If you log into a website using a regular browser, you also reveal your IP "
+"address and geographical location in the process. The same is often true "
+"when you send an email. Logging into your social networking or email "
+"accounts using Tor Browser allows you to choose exactly which information "
+"you reveal to the websites you browse. Logging in using Tor Browser is also "
+"useful if the website you are trying to reach is censored on your network."
+msgstr ""
+"Nuair a logálann tú isteach i suíomh Gréasáin trí ghnáthbhrabhsálaí, "
+"nochtann tú do sheoladh IP agus do láthair gheografach sa phróiseas. Is "
+"ionann an cás nuair a sheolann tú ríomhphost. Ach nuair a úsáideann tú "
+"Brabhsálaí Tor chun logáil isteach i gcuntas ríomhphoist nó i suíomh "
+"sóisialta, bíonn tú in ann an t-eolas a nochtann tú don suíomh a rialú. Tá "
+"Brabhsálaí Tor áisiúil freisin sa chás go bhfuil an suíomh atá tú ag "
+"iarraidh baint amach faoi chinsireacht ar do líonra."
+
+#: managing-identities.page:72
+msgid ""
+"When you log in to a website over Tor, there are several points you should "
+"bear in mind:"
+msgstr ""
+"Roinnt pointí ba chóir duit a choinneáil i gcuimhne nuair a logálann tú "
+"isteach i suíomh Gréasáin trí Tor:"
+
+#: managing-identities.page:79
+msgid ""
+"See the <link xref=\"secure-connections\">Secure Connections</link> page for"
+" important information on how to secure your connection when logging in."
+msgstr ""
+"Féach ar an leathanach <link xref=\"secure-connections\">Ceangail "
+"Shlána</link> chun eolas tábhachtach a fháil maidir le conas is féidir do "
+"cheangal a dhaingniú nuair a logálann tú isteach."
+
+#: managing-identities.page:87
+msgid ""
+"Tor Browser often makes your connection appear as though it is coming from "
+"an entirely different part of the world. Some websites, such as banks or "
+"email providers, might interpret this as a sign that your account has been "
+"hacked or compromised, and lock you out. The only way to resolve this is by "
+"following the site’s recommended procedure for account recovery, or "
+"contacting the operators and explaining the situation."
+msgstr ""
+"Nuair a úsáideann tú Brabhsálaí Tor, is minic go ndealraíonn sé go bhfuil do"
+" cheangal ag teacht ó áit éigin go hiomlán difriúil ar domhan. Dá bharr seo,"
+" seans go gceapfaidh suímh áirithe, mar shampla bainc nó soláthraithe "
+"ríomhphoist, gur bhris bradaí isteach i do chuntas agus cuirfidh siad do "
+"chuntas faoi ghlas. Is é an bealach amháin leis seo a réiteach ná an "
+"próiseas athshlánaithe cuntais ar an suíomh a leanúint, nó dul i dteagmháil "
+"le stiúrthóirí an tsuímh chun cúrsaí a mhíniú."
+
+#: managing-identities.page:101
+msgid "Changing identities and circuits"
+msgstr "Aitheantais agus ciorcaid a athrú"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: managing-identities.page:103
+msgctxt "_"
+msgid ""
+"external ref='media/managing-identities/new_identity.png' "
+"md5='15b01e35fa83185d94b57bf0ccf09d76'"
+msgstr ""
+"external ref='media/managing-identities/new_identity.png' "
+"md5='15b01e35fa83185d94b57bf0ccf09d76'"
+
+#: managing-identities.page:105
+msgid ""
+"Tor Browser features “New Identity” and “New Tor Circuit for this Site” "
+"options, located in the Torbutton menu."
+msgstr ""
+"Tá roghanna \"Aitheantas Nua\" agus \"Ciorcad Nua Tor don Suíomh seo\" ar "
+"fáil, i roghchlár an chnaipe Tor."
+
+#: managing-identities.page:111
+msgid "New Identity"
+msgstr "Aitheantas Nua"
+
+#: managing-identities.page:112
+msgid ""
+"This option is useful if you want to prevent your subsequent browser "
+"activity from being linkable to what you were doing before. Selecting it "
+"will close all your open tabs and windows, clear all private information "
+"such as cookies and browsing history, and use new Tor circuits for all "
+"connections. Tor Browser will warn you that all activity and downloads will "
+"be stopped, so take this into account before clicking “New Identity”."
+msgstr ""
+"Tá an rogha seo úsáideach má tá tú ag iarraidh cosc a chur ar lorgairí do "
+"ghníomhaíocht bhrabhsála sa todhchaí a nascadh lena ndearna tú roimhe seo. "
+"Má roghnaíonn tú é seo, dúnfar gach cluaisín agus fuinneog oscailte, glanfar"
+" aon fhaisnéis phearsanta, ar nós fianán agus do stair bhrabhsála, agus "
+"bunófar ciorcaid nua Tor do gach ceangal. Tabharfaidh Brabhsálaí Tor rabhadh"
+" duit go bhfuil sé ar tí do ghníomhaíocht agus íoslódálacha a stopadh, rud "
+"le cur san áireamh sula gcliceálfaidh tú “Aitheantas Nua”."
+
+#: managing-identities.page:123
+msgid "New Tor Circuit for this Site"
+msgstr "Ciorcad Nua Tor don Suíomh seo"
+
+#: managing-identities.page:124
+msgid ""
+"This option is useful if the <link xref=\"about-tor-browser#how-tor-"
+"works\">exit relay</link> you are using is unable to connect to the website "
+"you require, or is not loading it properly. Selecting it will cause the "
+"currently-active tab or window to be reloaded over a new Tor circuit. Other "
+"open tabs and windows from the same website will use the new circuit as well"
+" once they are reloaded. This option does not clear any private information "
+"or unlink your activity, nor does it affect your current connections to "
+"other websites."
+msgstr ""
+"Tá an rogha seo úsáideach mura bhfuil <link xref=\"about-tor-browser#how-"
+"tor-works\">an t-athsheachadán amach</link> a úsáideann tú in ann ceangal a "
+"bhunú leis an suíomh atá uait, nó mura bhfuil sé ag lódáil i gceart. Má "
+"roghnaíonn tú é seo, athlódálfar an cluaisín nó an fhuinneog ghníomhach ar "
+"chiorcad nua Tor. Úsáidfidh cluaisíní nó fuinneoga oscailte eile ón suíomh "
+"céanna an ciorcad nua seo freisin chomh luath is a athlódálfar iad. Ní "
+"ghlanann an rogha seo aon fhaisnéis phríobháideach, ní dhínascann sé do "
+"ghníomhaíocht, agus ní théann sé i bhfeidhm ar cheangail le suímh eile."
+
+#: onionsites.page:6
+msgid "Services that are only accessible using Tor"
+msgstr "Seirbhísí ar fáil trí Tor amháin"
+
+#: onionsites.page:10
+msgid "Onion Services"
+msgstr "Seirbhísí Onion"
+
+#: onionsites.page:11
+msgid ""
+"Onion services (formerly known as “hidden services”) are services (like "
+"websites) that are only accessible through the Tor network."
+msgstr ""
+"Is éard atá i Seirbhísí Onion (\"seirbhísí folaithe\" roimhe seo) ná "
+"seirbhísí (ar nós suíomh Gréasáin) nach bhfuil ar fáil ach trí Líonra Tor."
+
+#: onionsites.page:16
+msgid ""
+"Onion services offer several advantages over ordinary services on the non-"
+"private web:"
+msgstr ""
+"Tá roinnt buntáistí ag seirbhísí Onion ar ghnáthsheirbhísí an Ghréasáin "
+"phoiblí:"
+
+#: onionsites.page:23
+msgid ""
+"An onion services’s location and IP address are hidden, making it difficult "
+"for adversaries to censor it or identify its operators."
+msgstr ""
+"Coinnítear an áit ina bhfuil an tseirbhís onion i bhfolach, chomh maith lena"
+" seoladh IP, sa chaoi go mbeadh sé níos deacra cinsireacht a dhéanamh "
+"uirthi, nó stiúrthóirí na seirbhíse a aithint."
+
+#: onionsites.page:29
+msgid ""
+"All traffic between Tor users and onion services is end-to-end encrypted, so"
+" you do not need to worry about <link xref=\"secure-connections\">connecting"
+" over HTTPS</link>."
+msgstr ""
+"Déantar criptiú ar an trácht go léir idir úsáideoirí Tor agus seirbhísí "
+"Onion ó cheann go ceann, sa dóigh nach gá duit <link xref=\"secure-"
+"connections\">ceangal HTTPS a úsáid</link> riamh."
+
+#: onionsites.page:36
+msgid ""
+"The address of an onion service is automatically generated, so the operators"
+" do not need to purchase a domain name; the .onion URL also helps Tor ensure"
+" that it is connecting to the right location and that the connection is not "
+"being tampered with."
+msgstr ""
+"Gintear seoladh na seirbhíse Onion go huathoibríoch. Mar sin, ní gá don "
+"oibreoir ainm fearainn a cheannach, agus cinntíonn an URL .onion go bhfuil "
+"Tor ag ceangal leis an suíomh ceart agus nach bhfuil aon duine ag cur "
+"isteach ar an gceangal."
+
+#: onionsites.page:46
+msgid "How to access an onion service"
+msgstr "Conas Seirbhís Onion a rochtain"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: onionsites.page:48
+msgctxt "_"
+msgid ""
+"external ref='media/onionsites/onion_url.png' "
+"md5='f97f7fe10f07c3959c4430934974bbaa'"
+msgstr ""
+"external ref='media/onionsites/onion_url.png' "
+"md5='f97f7fe10f07c3959c4430934974bbaa'"
+
+#: onionsites.page:50
+msgid ""
+"Just like any other website, you will need to know the address of an onion "
+"service in order to connect to it. An onion address is a string of 16 (and "
+"in V3 format, 56) mostly random letters and numbers, followed by “.onion”."
+msgstr ""
+"Go díreach cosúil le haon suíomh Gréasáin eile, teastaíonn uait seoladh na "
+"seirbhíse onion chun ceangal léi. Is éard atá i seoladh onion ná teaghrán de"
+" 16 (agus i bhformáid V3, 56) litir agus uimhir, randamach den chuid is mó, "
+"agus “.onion” ag an deireadh."
+
+#: onionsites.page:58 troubleshooting.page:10
+msgid "Troubleshooting"
+msgstr "Fabhtcheartú"
+
+#: onionsites.page:59
+msgid ""
+"If you cannot reach the onion service you require, make sure that you have "
+"entered the onion address correctly: even a small mistake will stop Tor "
+"Browser from being able to reach the site."
+msgstr ""
+"Murar féidir leat an tseirbhís onion atá uait a bhaint amach, deimhnigh gur "
+"chuir tú an seoladh onion isteach i gceart: chuirfeadh fiú botún beag "
+"Brabhsálaí Tor ar strae agus ní bheadh Brabhsálaí Tor in ann an tseirbhís a "
+"bhaint amach."
+
+#: onionsites.page:64
+msgid ""
+"If you are still unable to connect to the onion service, please try again "
+"later. There may be a temporary connection issue, or the site operators may "
+"have allowed it to go offline without warning."
+msgstr ""
+"Murar féidir leat ceangal leis an tseirbhís onion fós, bain triail eile as "
+"ar ball. B'fhéidir go bhfuil fadhb shealadach leis an líonra, nó b'fhéidir "
+"gur lig stiúrthóirí an tsuímh dó dul as líne gan rabhadh."
+
+#: onionsites.page:69
+msgid ""
+"You can also ensure that you're able to access other onion services by "
+"connecting to <link href=\"http://3g2upl4pq6kufc4m.onion/\">DuckDuckGo's "
+"Onion Service</link>"
+msgstr ""
+"Agus is féidir leat deimhniú go bhfuil tú in ann seirbhísí Onion eile a "
+"rochtain trí cheangal a bhunú le <link "
+"href=\"http://3g2upl4pq6kufc4m.onion/\">Seirbhís Onion DuckDuckGo</link>"
+
+#: plugins.page:6
+msgid "How Tor Browser handles add-ons, plugins and JavaScript"
+msgstr ""
+"Conas a láimhseálann Brabhsálaí Tor breiseáin, forlíontáin, agus JavaScript"
+
+#: plugins.page:10
+msgid "Plugins, add-ons and JavaScript"
+msgstr "Forlíontáin, breiseáin, agus JavaScript"
+
+#: plugins.page:13
+msgid "Flash Player"
+msgstr "Seinnteoir Flash"
+
+#: plugins.page:14
+msgid ""
+"Video websites, such as Vimeo make use of the Flash Player plugin to display"
+" video content. Unfortunately, this software operates independently of Tor "
+"Browser and cannot easily be made to obey Tor Browser’s proxy settings. It "
+"can therefore reveal your real location and IP address to the website "
+"operators, or to an outside observer. For this reason, Flash is disabled by "
+"default in Tor Browser, and enabling it is not recommended."
+msgstr ""
+"Úsáideann go leor suíomh comhroinnte físeán, mar shampla Vimeo, an "
+"forlíontán Flash Player chun ábhar físe a sheinm sa bhrabhsálaí. Faraor, tá "
+"an forlíontán seo neamhspleách ar Bhrabhsálaí Tor agus níl sé ró-éasca "
+"tabhairt air socruithe seachfhreastalaí Bhrabhsálaí Tor a úsáid. Mar sin, tá"
+" seans ann go nochtfadh sé do láthair gheografach nó do sheoladh IP do "
+"stiúrthóirí an tsuímh, nó do chúléisteoir seachtrach. Ar an ábhar seo, tá "
+"Flash díchumasaithe i mBrabhsálaí Tor de réir réamhshocraithe, agus "
+"mholfaimis duit gan é a chumasú."
+
+#: plugins.page:23
+msgid ""
+"Some video websites (such as YouTube) offer alternative video delivery "
+"methods that do not use Flash. These methods may be compatible with Tor "
+"Browser."
+msgstr ""
+"Cuireann suímh áirithe (mar shampla YouTube) modhanna malartacha le físeáin "
+"a thaispeáint ar fáil, modhanna nach mbaineann úsáid as Flash. Uaireanta "
+"bíonn siad comhoiriúnach le Brabhsálaí Tor."
+
+#: plugins.page:31
+msgid "JavaScript"
+msgstr "JavaScript"
+
+#: plugins.page:32
+msgid ""
+"JavaScript is a programming language that websites use to offer interactive "
+"elements such as video, animation, audio, and status timelines. "
+"Unfortunately, JavaScript can also enable attacks on the security of the "
+"browser, which might lead to deanonymization."
+msgstr ""
+"Is teanga ríomhchlárúcháin é JavaScript a úsáidtear ar shuímh Ghréasáin chun"
+" gnéithe idirghníomhacha a chur ar fáil, mar shampla físeáin, beochan, "
+"fuaim, agus amlínte stádas. Faraor, éascaíonn JavaScript ionsaithe áirithe "
+"ar shlándáil an bhrabhsálaí, ionsaithe a d'fhéadfadh d'aitheantas a "
+"nochtadh."
+
+#: plugins.page:39
+msgid ""
+"Tor Browser includes an add-on called NoScript, accessed through the “S” "
+"icon at the top-left of the window. NoScript allows you to control the "
+"JavaScript (and other scripts) that runs on individual web pages, or block "
+"it entirely."
+msgstr ""
+"Tá breiseán darb ainm NoScript ag gabháil le Brabhsálaí Tor, ar fáil tríd an"
+" deilbhín “S” ag barr na fuinneoige ar chlé. Ligeann NoScript duit smacht a "
+"choinneáil ar an gcód JavaScript (agus scripteanna eile) a ritheann ar "
+"leathanaigh ar leith, nó cosc iomlán a chur air."
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: plugins.page:46
+msgctxt "_"
+msgid ""
+"external ref='media/plugins/noscript_menu.png' "
+"md5='df9e684b76a3c2e2bdcb879a19c20471'"
+msgstr ""
+"external ref='media/plugins/noscript_menu.png' "
+"md5='df9e684b76a3c2e2bdcb879a19c20471'"
+
+#: plugins.page:48
+msgid ""
+"Users who require a high degree of security in their web browsing should set"
+" Tor Browser’s <link xref=\"security-slider\">Security Slider</link> to "
+"“Safer” (which disables JavaScript for non-HTTPS websites) or “Safest” "
+"(which does so for all websites). However, disabling JavaScript will prevent"
+" many websites from displaying correctly, so Tor Browser’s default setting "
+"is to allow all websites to run scripts in \"Standard\" mode."
+msgstr ""
+"Ba chóir d'úsáideoirí a dteastaíonn slándáil an-daingean uathu an <link xref"
+"=\"security-slider\">Sleamhnán Slándála</link> i mBrabhsálaí Tor a shocrú go"
+" dtí “Níos Sábháilte” (a dhíchumasaíonn JavaScript ar shuímh nach "
+"n-úsáideann HTTPS) nó “Is Sábháilte” (a dhíchumasaíonn ar gach suíomh é). "
+"Ach, má dhíchumasaíonn tú JavaScript, ní fheidhmeoidh go leor suíomh mar is "
+"ceart, agus dá bharr sin ligeann Brabhsálaí Tor do gach suíomh scripteanna a"
+" rith de réir réamhshocraithe."
+
+#: plugins.page:59
+msgid "Browser Add-ons"
+msgstr "Breiseáin Bhrabhsálaí"
+
+#: plugins.page:60
+msgid ""
+"Tor Browser is based on Firefox, and any browser add-ons or themes that are "
+"compatible with Firefox can also be installed in Tor Browser."
+msgstr ""
+"Tá Brabhsálaí Tor bunaithe ar Firefox, agus is féidir leat aon bhreiseán nó "
+"téama atá comhoiriúnach le Firefox a shuiteáil i mBrabhsálaí Tor freisin."
+
+#: plugins.page:65
+msgid ""
+"However, the only add-ons that have been tested for use with Tor Browser are"
+" those included by default. Installing any other browser add-ons may break "
+"functionality in Tor Browser or cause more serious problems that affect your"
+" privacy and security. It is strongly discouraged to install additional add-"
+"ons, and the Tor Project will not offer support for these configurations."
+msgstr ""
+"Ní dhearnadh tástáil ar bith ar bhreiseáin seachas ar na cinn a thagann le "
+"Brabhsálaí Tor de réir réamhshocraithe. Má shuiteálann tú aon bhreiseán "
+"eile, seans maith nach bhfeidhmeoidh Brabhsálaí Tor i gceart, agus go minic "
+"is cúis le fadhbanna níos tromchúisí na breiseáin seo, fadhbanna a dhéanann "
+"dochar don phríobháideachas agus don tslándáil. Molaimid go láidir duit gan "
+"breiseáin eile a shuiteáil, agus ní thacóidh Tionscadal Tor leis na "
+"cumraíochtaí malartacha seo."
+
+#: secure-connections.page:8
+msgid "Learn how to protect your data using Tor Browser and HTTPS"
+msgstr ""
+"Foghlaim conas is féidir do chuid sonraí a chosaint le Brabhsálaí Tor agus "
+"HTTPS"
+
+#: secure-connections.page:12
+msgid "Secure Connections"
+msgstr "Ceangail Shlána"
+
+#: secure-connections.page:14
+msgid ""
+"If personal information such as a login password travels unencrypted over "
+"the Internet, it can very easily be intercepted by an eavesdropper. If you "
+"are logging into any website, you should make sure that the site offers "
+"HTTPS encryption, which protects against this kind of eavesdropping. You can"
+" verify this in the URL bar: if your connection is encrypted, the address "
+"will begin with “https://”, rather than “http://”."
+msgstr ""
+"Má sheolann tú sonraí phearsanta, mar shampla focail fhaire, ar an Idirlíon "
+"gan chriptiú, tá sé an-éasca do chúléisteoir iad a idircheapadh. Má tá tú ag"
+" logáil isteach i suíomh Gréasáin, ba chóir duit deimhniú go n-úsáideann an "
+"suíomh criptiú HTTPS, rud a chosnaíonn ar an sórt seo cúléisteachta thú. Is"
+" féidir leat é seo a dheimhniú sa bharra URL: má tá do cheangal criptithe, "
+"tosóidh an seoladh le “https://”, in áit “http://”."
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: secure-connections.page:24
+msgctxt "_"
+msgid ""
+"external ref='media/secure-connections/https.png' "
+"md5='364bcbde7a649b0cea9ae178007c1a50'"
+msgstr ""
+"external ref='media/secure-connections/https.png' "
+"md5='364bcbde7a649b0cea9ae178007c1a50'"
+
+#: secure-connections.page:26
+msgid ""
+"The following visualization shows what information is visible to "
+"eavesdroppers with and without Tor Browser and HTTPS encryption:"
+msgstr ""
+"Taispeánann an pictiúr seo an t-eolas atá cúléisteoirí in ann a fheiceáil le"
+" Brabhsálaí Tor agus criptiú HTTPS, agus gan iad:"
+
+#: secure-connections.page:35
+msgid ""
+"Click the “Tor” button to see what data is visible to observers when you're "
+"using Tor. The button will turn green to indicate that Tor is on."
+msgstr ""
+"Tar éis duit an cnaipe “Tor” a chliceáil, taispeánfar na sonraí a bhíonn "
+"cúléisteoirí in ann a fheiceáil nuair a úsáideann tú Tor. Iompóidh an cnaipe"
+" uaine mar léiriú go bhfuil Tor ar siúl."
+
+#: secure-connections.page:42
+msgid ""
+"Click the “HTTPS” button to see what data is visible to observers when "
+"you're using HTTPS. The button will turn green to indicate that HTTPS is on."
+msgstr ""
+"Tar éis duit an cnaipe “HTTPS” a chliceáil, taispeánfar na sonraí a bhíonn "
+"cúléisteoirí in ann a fheiceáil nuair a úsáideann tú HTTPS. Iompóidh an "
+"cnaipe uaine mar léiriú go bhfuil HTTPS ar siúl."
+
+#: secure-connections.page:49
+msgid ""
+"When both buttons are green, you see the data that is visible to observers "
+"when you are using both tools."
+msgstr ""
+"Nuair a bhíonn an dá chnaipe uaine, léiríonn sé na sonraí a bhíonn "
+"cúléisteoirí in ann a fheiceáil nuair a úsáideann tú Tor agus HTTPS le "
+"chéile."
+
+#: secure-connections.page:55
+msgid ""
+"When both buttons are grey, you see the data that is visible to observers "
+"when you don't use either tool."
+msgstr ""
+"Nuair a bhíonn an dá chnaipe liath, léiríonn sé na sonraí a bhíonn "
+"cúléisteoirí in ann a fheiceáil nuair nach n-úsáideann tú Tor ná HTTPS."
+
+#: secure-connections.page:62
+msgid "Potentially visible data"
+msgstr "Sonraí a d'fhéadfadh a bheith infheicthe"
+
+#: secure-connections.page:70
+msgid "The site being visited."
+msgstr "An suíomh a dtugtar cuairt air."
+
+#: secure-connections.page:81
+msgid "Username and password used for authentication."
+msgstr "Ainm úsáideora agus focal faire a úsáidtear le fíordheimhniú."
+
+#: secure-connections.page:92
+msgid "Data being transmitted."
+msgstr "Na sonraí á n-aistriú."
+
+#: secure-connections.page:103
+msgid ""
+"Network location of the computer used to visit the website (the public IP "
+"address)."
+msgstr ""
+"Seoladh an ríomhaire a úsáideadh chun cuairt a thabhairt ar an suíomh (an "
+"seoladh IP poiblí)."
+
+#: secure-connections.page:115
+msgid "Whether or not Tor is being used."
+msgstr "An bhfuil Tor in úsáid nó nach bhfuil."
+
+#: security-slider.page:6
+msgid "Configuring Tor Browser for security and usability"
+msgstr "Brabhsálaí Tor a chumrú ar son slándála agus inúsáidteachta"
+
+#: security-slider.page:10
+msgid "Security Slider"
+msgstr "An Sleamhnán Slándála"
+
+#: security-slider.page:11
+msgid ""
+"Tor Browser includes a “Security Slider” that lets you increase your "
+"security by disabling certain web features that can be used to attack your "
+"security and anonymity. Increasing Tor Browser’s security level will stop "
+"some web pages from functioning properly, so you should weigh your security "
+"needs against the degree of usability you require."
+msgstr ""
+"Tá “Sleamhnán Slándála” ar fáil mar chuid de Bhrabhsálaí Tor, rud a "
+"neartaíonn do shlándáil trí ghnéithe áirithe sa bhrabhsálaí a dhíchumasú, go"
+" háirithe gnéithe a úsáidtear chun ionsaí a dhéanamh ort. Má ardaíonn tú an "
+"leibhéal slándála i mBrabhsálaí Tor, ní fheidhmeoidh leathanaigh áirithe mar"
+" is ceart, agus dá bharr sin caithfidh tú do shlándáil a mheas in aghaidh "
+"inúsáidteacht na suíomh a dtugann tú cuairt orthu."
+
+#: security-slider.page:21
+msgid "Accessing the Security Slider"
+msgstr "Rochtain ar an Sleamhnán Slándála"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: security-slider.page:23
+msgctxt "_"
+msgid ""
+"external ref='media/security-slider/slider.png' "
+"md5='026da7c021ba5b85caf04bbf45530667'"
+msgstr ""
+"external ref='media/security-slider/slider.png' "
+"md5='026da7c021ba5b85caf04bbf45530667'"
+
+#: security-slider.page:25
+msgid ""
+"The Security Slider is located in Torbutton’s “Security Settings” menu."
+msgstr ""
+"Gheobhaidh tú an Sleamhnán Slándála i roghchlár an chnaipe Tor faoi "
+"“Socruithe Slándála”."
+
+#: security-slider.page:32
+msgid "Security Levels"
+msgstr "Leibhéil Slándála"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: security-slider.page:34
+msgctxt "_"
+msgid ""
+"external ref='media/security-slider/slider_window.png' "
+"md5='d5faf391c99f88aff8541a68bdc6a776'"
+msgstr ""
+"external ref='media/security-slider/slider_window.png' "
+"md5='d5faf391c99f88aff8541a68bdc6a776'"
+
+#: security-slider.page:36
+msgid ""
+"Increasing the level of the Security Slider will disable or partially "
+"disable certain browser features to protect against possible attacks."
+msgstr ""
+"Má ardaíonn tú leibhéal an tSleamhnáin Slándála, díchumasófar gnéithe "
+"áirithe sa bhrabhsálaí mar chosaint ar ionsaithe."
+
+#: security-slider.page:42
+msgid "Safest"
+msgstr "Is Sábháilte"
+
+#: security-slider.page:43
+msgid ""
+"At this level, HTML5 video and audio media become click-to-play via "
+"NoScript; all JavaScript performance optimizations are disabled; some "
+"mathematical equations may not display properly; some font rendering "
+"features are disabled; some types of image are disabled; Javascript is "
+"disabled by default on all sites; most video and audio formats are disabled;"
+" and some fonts and icons may not display correctly."
+msgstr ""
+"Ag an leibhéal seo, caithfidh tú físeáin agus comhaid fuaime HTML5 a "
+"chliceáil chun iad a sheinm trí NoScript; ní chuirtear aon optamú JavaScript"
+" i bhfeidhm; seans nach dtaispeántar cothromóidí áirithe matamaiticiúla i "
+"gceart; ní úsáidtear gnéithe áirithe agus clófhoirne á dtarraingt ar an "
+"scáileán; ní thaispeántar cineálacha áirithe íomhá; tá JavaScript "
+"díchumasaithe de réir réamhshocraithe ar gach suíomh; tá an chuid is mó de "
+"na formáidí físe agus fuaime díchumasaithe; agus ní thaispeántar roinnt "
+"clófhoirne agus deilbhíní i gceart."
+
+#: security-slider.page:53
+msgid "Safer"
+msgstr "Níos Sábháilte"
+
+#: security-slider.page:54
+msgid ""
+"At this level, HTML5 video and audio media become click-to-play via "
+"NoScript; all JavaScript performance optimizations are disabled; some "
+"mathematical equations may not display properly; some font rendering "
+"features are disabled; some types of image are disabled; and JavaScript is "
+"disabled by default on all non-<link xref=\"secure-"
+"connections\">HTTPS</link> sites."
+msgstr ""
+"Ag an leibhéal seo, caithfidh tú físeáin agus comhaid fuaime HTML5 a "
+"chliceáil chun iad a sheinm trí NoScript; ní chuirtear aon optamú JavaScript"
+" i bhfeidhm; seans nach dtaispeántar cothromóidí áirithe matamaiticiúla i "
+"gceart; ní úsáidtear gnéithe áirithe agus clófhoirne á dtarraingt ar an "
+"scáileán; ní thaispeántar cineálacha áirithe íomhá; agus tá JavaScript "
+"díchumasaithe de réir réamhshocraithe ar gach suíomh nach mbaineann úsáid as"
+" <link xref=\"secure-connections\">HTTPS</link>."
+
+#: security-slider.page:64
+msgid "Standard"
+msgstr "Gnáthshlándáil"
+
+#: security-slider.page:65
+msgid ""
+"At this level, all browser features are enabled. This is the most usable "
+"option."
+msgstr ""
+"Ag an leibhéal seo, tá gach gné cumasaithe. Seo an rogha is inúsáidte."
+
+#: translate.page:6
+msgid "Becoming a translator for the Tor Project"
+msgstr "Bí i d'aistritheoir ar Thionscadal Tor"
+
+#: translate.page:10
+msgid "Becoming a Tor Translator"
+msgstr "Eolas maidir le haistriúchán Tor"
+
+#: translate.page:12
+msgid ""
+"If you are interested in helping out the project by translating the manual "
+"or the Tor Browser to your language, your help would be greatly appreciated!"
+" In order to begin contributing you will have to sign up with Transifex, the"
+" third-party that faciliates our translations. Below is an outline of how to"
+" sign up and begin."
+msgstr ""
+"Más mian leat cabhrú leis an tionscadal trí aistriúchán a dhéanamh ar an "
+"lámhleabhar nó ar bhrabhsálaí Tor féin, bheimis an-bhuíoch díot! Len é seo a"
+" dhéanamh, caithfidh tú clárú leis an suíomh Transifex, tríú páirtí a "
+"éascaíonn ár bpróiseas aistriúcháin. Seo duit na treoracha cláraithe."
+
+#: translate.page:21
+msgid "Signing up on Transifex"
+msgstr "Clárú le Transifex"
+
+#: translate.page:24
+msgid ""
+"Head over to the <link href=\"https://transifex.com/signup/\">Transifex "
+"signup page</link>."
+msgstr ""
+"Tabhair cuairt ar <link href=\"https://transifex.com/signup/\">leathanach "
+"cláraithe Transifex</link>."
+
+#: translate.page:30
+msgid "Enter your information into the fields and click the 'Sign Up' button:"
+msgstr "Cuir do shonraí isteach agus cliceáil an cnaipe 'Sign Up':"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: translate.page:34
+msgctxt "_"
+msgid ""
+"external ref='media/translate/tr1.png' "
+"md5='a94cfd90c9982916a987e2807ae5e4f6'"
+msgstr ""
+"external ref='media/translate/tr1.png' "
+"md5='a94cfd90c9982916a987e2807ae5e4f6'"
+
+#: translate.page:38
+msgid ""
+"Fill out the next page with your name and select \"Localization\" and "
+"\"Translator\" from the drop-down menus:"
+msgstr ""
+"Líon isteach an chéad leathanach eile agus roghnaigh \"Localization\" agus "
+"\"Translator\" ó na roghchláir aníos:"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: translate.page:43
+msgctxt "_"
+msgid ""
+"external ref='media/translate/tr2.png' "
+"md5='06debc9e9dbc7ac198103a89a6961774'"
+msgstr ""
+"external ref='media/translate/tr2.png' "
+"md5='06debc9e9dbc7ac198103a89a6961774'"
+
+#: translate.page:47
+msgid "On the next page, select 'Join an existing project' and continue."
+msgstr ""
+"Ar an chéad leathanach eile, roghnaigh 'Join an existing project' agus lean "
+"ar aghaidh."
+
+#: translate.page:52
+msgid ""
+"On the next page, select the languages you speak from the drop-down menu and"
+" continue."
+msgstr ""
+"Ar an chéad leathanach eile, roghnaigh na teangacha ar do thoil agat ón "
+"roghchlár aníos agus lean ar aghaidh."
+
+#: translate.page:58
+msgid ""
+"You are now signed up! Go to the <link "
+"href=\"https://www.transifex.com/otf/torproject/\">Tor Transifex "
+"page</link>."
+msgstr ""
+"Tá tú cláraithe anois! Tabhair cuairt ar <link "
+"href=\"https://www.transifex.com/otf/torproject/\">leathanach Tor ar "
+"Transifex</link>."
+
+#: translate.page:64
+msgid "Click the blue 'Join Team' button on the far right:"
+msgstr "Cliceáil an cnaipe gorm 'Join Team' ar dheis ar fad:"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: translate.page:68
+msgctxt "_"
+msgid ""
+"external ref='media/translate/tr3.png' "
+"md5='7da6c9968cabbe9c1ecc7cdf645407e8'"
+msgstr ""
+"external ref='media/translate/tr3.png' "
+"md5='7da6c9968cabbe9c1ecc7cdf645407e8'"
+
+#: translate.page:72
+msgid ""
+"Select the language you would like to translate from the dropdown menu:"
+msgstr "Roghnaigh do theanga ón roghchlár aníos:"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: translate.page:76
+msgctxt "_"
+msgid ""
+"external ref='media/translate/tr4.png' "
+"md5='835a266a5d4c368a2777cf171980f0b4'"
+msgstr ""
+"external ref='media/translate/tr4.png' "
+"md5='835a266a5d4c368a2777cf171980f0b4'"
+
+#: translate.page:80
+msgid "A notification will now show up on the top of the page like so:"
+msgstr "Feicfidh tú fógra ar bharr an leathanaigh mar seo:"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: translate.page:84
+msgctxt "_"
+msgid ""
+"external ref='media/translate/tr5.png' "
+"md5='935417a5d3b4a89e5d00508ea671a1fc'"
+msgstr ""
+"external ref='media/translate/tr5.png' "
+"md5='935417a5d3b4a89e5d00508ea671a1fc'"
+
+#: translate.page:88
+msgid ""
+"After your membership is approved you can begin translating; simply navigate"
+" back to the <link href=\"https://www.transifex.com/otf/torproject/\">Tor "
+"Transifex page</link> when you are ready to begin. Thanks for your interest "
+"in helping the project!"
+msgstr ""
+"Tar éis go nglacfar leat mar aistritheoir, is féidir leat tosú ag obair; níl"
+" i gceist ach cuairt a thabhairt ar <link "
+"href=\"https://www.transifex.com/otf/torproject/\">leathanach Tor ar "
+"Transifex</link> nuair a bheidh tú réidh. Go raibh maith agat as cabhrú "
+"linn!"
+
+#: transports.page:6 transports.page:20
+msgid "Types of pluggable transport"
+msgstr "Cineálacha iompair ionphlugáilte"
+
+#: transports.page:10
+msgid "Pluggable Transports"
+msgstr "Córais Iompair Ionphlugáilte"
+
+#: transports.page:12
+msgid ""
+"Pluggable transports are tools that Tor can use to disguise the traffic it "
+"sends out. This can be useful in situations where an Internet Service "
+"Provider or other authority is actively blocking connections to the Tor "
+"network."
+msgstr ""
+"Is éard atá i gcóras iompair ionphlugáilte ná uirlis a chuireann bréagriocht"
+" ar an trácht Idirlín a sheolann Tor amach. Tá sé seo úsáideach nuair a "
+"chuireann Soláthraí Seirbhíse Idirlín nó údarás eile bac ar cheangail le "
+"líonra Tor."
+
+#: transports.page:21
+msgid ""
+"Currently there are six pluggable transports available, but more are being "
+"developed."
+msgstr ""
+"Tá sé cinn de chórais iompair ionphlugáilte ar fáil faoi láthair, ach táimid"
+" i mbun oibre ar chinn eile."
+
+#: transports.page:28
+msgid "obfs3"
+msgstr "obfs3"
+
+#: transports.page:33
+msgid ""
+"obfs3 makes Tor traffic look random, so that it does not look like Tor or "
+"any other protocol. While still included by default, it is reccomended to "
+"use obfs4 instead, as it has several security improvements over obfs3."
+msgstr ""
+"Cuireann obfs3 cuma randamach ar thrácht Tor, sa dóigh nach mbeadh cosúlacht"
+" aige le gnáth-thrácht Tor ná le haon phrótacal eile. Cé go bhfuil obfs3 ar "
+"fáil fós de réir réamhshocraithe, molaimid duit obfs4 a úsáid ina áit, toisc"
+" go bhfuil sé níos fearr ná obfs3 ó thaobh slándála."
+
+#: transports.page:43
+msgid "obfs4"
+msgstr "obfs4"
+
+#: transports.page:48
+msgid ""
+"obfs4 makes Tor traffic look random like obfs3, and also prevents censors "
+"from finding bridges by Internet scanning. obfs4 bridges are less likely to "
+"be blocked than obfs3 bridges."
+msgstr ""
+"Cuireann obfs4 cuma randamach ar thrácht Tor go díreach cosúil le obfs3, "
+"agus cuireann sé cosc ar chinsirí droichid a aimsiú trí scanadh an Idirlín. "
+"Níos lú an seans go gcuirtear cosc ar dhroichead obfs4 ná ar dhroichead "
+"obfs3."
+
+#: transports.page:57
+msgid "Scramblesuit"
+msgstr "Scramblesuit"
+
+#: transports.page:62
+msgid "ScrambleSuit is similar to obfs4 but has a different set of bridges."
+msgstr ""
+"Córas cosúil le obfs4 é ScrambleSuit, ach úsáideann sé droichid dhifriúla."
+
+#: transports.page:70
+msgid "FTE"
+msgstr "FTE"
+
+#: transports.page:75
+msgid ""
+"FTE (format-transforming encryption) disguises Tor traffic as ordinary web "
+"(HTTP) traffic."
+msgstr ""
+"Cuireann FTE (criptiúchán trasfhoirmithe) cuma ghnáth-thrácht Gréasáin "
+"(HTTP) ar thrácht Tor."
+
+#: transports.page:83
+msgid "meek"
+msgstr "meek"
+
+#: transports.page:88
+msgid ""
+"These transports all make it look like you are browsing a major web site "
+"instead of using Tor. meek-amazon makes it look like you are using Amazon "
+"Web Services; meek-azure makes it look like you are using a Microsoft web "
+"site; and meek-google makes it look like you are using Google search."
+msgstr ""
+"Nuair a úsáideann tú na córais iompair seo, dealraíonn sé go bhfuil tú ag "
+"brabhsáil suíomh éigin mór-le-rá in áit Tor. Mar shampla, le meek-amazon, "
+"dealraíonn sé go bhfuil tú ag úsáid Seirbhísí Gréasáin Amazon; le meek-"
+"azure, go bhfuil tú ag úsáid suímh de chuid Microsoft; agus le meek-google, "
+"go bhfuil tú ag déanamh cuardaigh Google."
+
+#: transports.page:100
+msgid "Snowflake"
+msgstr "Snowflake"
+
+#: transports.page:105
+msgid ""
+"Snowflake is an improvement upon Flashproxy. It sends your traffic through "
+"WebRTC, a peer-to-peer protocol with built-in NAT punching."
+msgstr ""
+"Leagan feabhsaithe de Flashproxy is ea Snowflake. Seolann sé do chuid "
+"tráchta trí WebRTC, prótacal ó ríomhaire go ríomhaire a bhfuil cumas tollta "
+"NAT ionsuite ann."
+
+#: troubleshooting.page:6
+msgid "What to do if Tor Browser doesn’t work"
+msgstr "Cad is féidir a dhéanamh mura bhfuil Brabhsálaí Tor ag obair"
+
+#: troubleshooting.page:12
+msgid ""
+"You should be able to start browsing the web using Tor Browser shortly after"
+" running the program, and clicking the “Connect” button if you are using it "
+"for the first time."
+msgstr ""
+"Ba cheart go mbeifeá in ann an Gréasán a bhrabhsáil le Brabhsálaí Tor go "
+"díreach tar éis duit an clár a thosú, agus an cnaipe “Ceangail” a chliceáil "
+"an chéad uair a úsáideann tú é."
+
+#: troubleshooting.page:21
+msgid "Quick fixes"
+msgstr "Réiteach tapa"
+
+#: troubleshooting.page:22
+msgid ""
+"If Tor Browser doesn’t connect, there may be a simple solution. Try each of "
+"the following:"
+msgstr ""
+"Murar féidir le Brabhsálaí Tor ceangal leis an líonra, seans go bhfuil "
+"réiteach simplí ann. Bain triail as gach ceann de na moltaí seo:"
+
+#: troubleshooting.page:29
+msgid ""
+"Your computer’s system clock must be set correctly, or Tor will not be able "
+"to connect."
+msgstr ""
+"Ní mór do chlog an chórais a bheith socraithe i gceart, nó nach mbeidh Tor "
+"in ann ceangal leis an líonra."
+
+#: troubleshooting.page:35
+msgid ""
+"Make sure another Tor Browser is not already running. If you’re not sure if "
+"Tor Browser is running, restart your computer."
+msgstr ""
+"Deimhnigh nach bhfuil Brabhsálaí Tor eile ag rith cheana. Mura bhfuil tú "
+"cinnte faoi seo, atosaigh do ríomhaire."
+
+#: troubleshooting.page:41
+msgid ""
+"Make sure that any antivirus program you have installed is not preventing "
+"Tor from running. You may need to consult the documentation for your "
+"antivirus software if you do not know how to do this."
+msgstr ""
+"Deimhnigh nach bhfuil aon bhogearra frithvíreas ag cur cosc ar Tor. Seans "
+"gur gá duit doiciméadú an bhogearra frithvíreas a cheadú mura bhfuil a fhios"
+" agat conas é seo a dhéanamh."
+
+#: troubleshooting.page:49
+msgid "Temporarily disable your firewall."
+msgstr "Díchumasaigh do bhalla dóiteáin go sealadach."
+
+#: troubleshooting.page:54
+msgid ""
+"Delete Tor Browser and install it again. If updating, do not just overwrite "
+"your previous Tor Browser files; ensure they are fully deleted beforehand."
+msgstr ""
+"Scrios an Brabhsálaí Tor agus suiteáil arís é. Má tá leagan nua ar fáil, ná "
+"forscríobh na comhaid a bhí ann; deimhnigh gur scrios tú go hiomlán iad ar "
+"dtús."
+
+#: troubleshooting.page:64
+msgid "Is your connection censored?"
+msgstr "An bhfuil do cheangal faoi chinsireacht?"
+
+#: troubleshooting.page:65
+msgid ""
+"If you still can’t connect, your Internet Service Provider might be "
+"censoring connections to the Tor network. Read the <link "
+"xref=\"circumvention\">Circumvention</link> section for possible solutions."
+msgstr ""
+"Mura bhfuil tú in ann ceangal fós, b'fhéidir go bhfuil do Sholáthraí "
+"Seirbhíse Idirlín ag déanamh cinsireacht ar líonra Tor. Léigh an leathanach "
+"<link xref=\"circumvention\">Timpeallú</link>le foghlaim conas is féidir an "
+"fhadhb a réiteach."
+
+#: troubleshooting.page:74
+msgid "Known issues"
+msgstr "Fadhbanna ar eolas"
+
+#: troubleshooting.page:75
+msgid ""
+"Tor Browser is under constant development, and some issues are known about "
+"but not yet fixed. Please check the <link xref=\"known-issues\">Known "
+"Issues</link> page to see if the problem you are experiencing is already "
+"listed there."
+msgstr ""
+"Tá Brabhsálaí Tor á fhorbairt ar bhonn leanúnach, agus tá a fhios againn "
+"faoi roinnt fadhbanna nach bhfuil réiteach orthu fós. Féach ar an leathanach"
+" <link xref=\"known-issues\">Fadhbanna ar eolas</link> le féachaint an "
+"bhfuil an fhadhb a fheiceann tusa ann cheana."
+
+#: uninstalling.page:6
+msgid "How to remove Tor Browser from your system"
+msgstr "Conas Brabhsálaí Tor a bhaint de do chóras"
+
+#: uninstalling.page:10
+msgid "Uninstalling"
+msgstr "Díshuiteáil"
+
+#: uninstalling.page:12
+msgid ""
+"Tor Browser does not affect any of the existing software or settings on your"
+" computer. Uninstalling Tor Browser will not affect your system’s software "
+"or settings."
+msgstr ""
+"Ní théann Brabhsálaí Tor i bhfeidhm ar aon bhogearraí eile ar do ríomhaire, "
+"ná ar shocruithe do chórais. Má bhaineann tú Brabhsálaí Tor de do ríomhaire,"
+" ní rachaidh sé i bhfeidhm ar bhogearraí ná ar shocruithe do chórais."
+
+#: uninstalling.page:18
+msgid "Removing Tor Browser from your system is simple:"
+msgstr "Tá sé an-éasca Brabhsálaí Tor a bhaint de do chóras:"
+
+#: uninstalling.page:24
+msgid ""
+"Locate your Tor Browser folder. The default location on Windows is the "
+"Desktop; on Mac OS X it is the Applications folder. On Linux, there is no "
+"default location, however the folder will be named \"tor-browser_en-US\" if "
+"you are running the English Tor Browser."
+msgstr ""
+"Aimsigh fillteán Bhrabhsálaí Tor. Seo é an Deasc de réir réamhshocraithe ar "
+"Windows, agus an fillteán Applications ar Mac OS X. Níl aon suíomh "
+"réamhshocraithe ar Linux, ach is é \"tor-browser_en-US\" ainm an fhillteáin "
+"má tá an leagan Béarla agat."
+
+#: uninstalling.page:32
+msgid "Delete the Tor Browser folder."
+msgstr "Scrios fillteán Bhrabhsálaí Tor."
+
+#: uninstalling.page:35
+msgid "Empty your Trash"
+msgstr "Folmhaigh an Bruscar"
+
+#: uninstalling.page:39
+msgid ""
+"Note that your operating system’s standard “Uninstall” utility is not used."
+msgstr ""
+"Tabhair faoi deara nach mbaintear úsáid as an ngnáthuirlis \"Uninstall\" ar "
+"do chóras."
+
+#: updating.page:6
+msgid "How to update Tor Browser"
+msgstr "Conas Brabhsálaí Tor a nuashonrú"
+
+#: updating.page:10
+msgid "Updating"
+msgstr "Nuashonrú"
+
+#: updating.page:12
+msgid ""
+"Tor Browser must be kept updated at all times. If you continue to use an "
+"outdated version of the software, you may be vulnerable to serious security "
+"flaws that compromise your privacy and anonymity."
+msgstr ""
+"Caithfidh tú Brabhsálaí Tor a choinneáil cothrom le dáta i gcónaí. Má "
+"úsáideann tú leagan den bhogearra atá as dáta, is dócha go mbeidh tú i mbaol"
+" ionsaithe mar gheall ar lochtanna tromchúiseacha slándála a d'fhéadfadh "
+"d'aitheantas nó do chuid sonraí pearsanta a nochtadh."
+
+#: updating.page:18
+msgid ""
+"Tor Browser will prompt you to update the software once a new version has "
+"been released: the Torbutton icon will display a yellow triangle, and you "
+"may see a written update indicator when Tor Browser opens. You can update "
+"either automatically or manually."
+msgstr ""
+"Fiafróidh Brabhsálaí Tor díot ar mhaith leat an bogearra a nuashonrú chomh "
+"luath agus a bheidh leagan nua ar fáil: taispeánfaidh deilbhín an chnaipe "
+"Tor triantán buí, agus seans go bhfeicfidh tú táscaire scríofa faoin "
+"nuashonrú nuair a osclóidh Brabhsálaí Tor. Is féidir leat é a nuashonrú go "
+"huathoibríoch nó de láimh."
+
+#: updating.page:26
+msgid "Updating Tor Browser automatically"
+msgstr "Nuashonrú uathoibríoch ar Bhrabhsálaí Tor"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: updating.page:30
+msgctxt "_"
+msgid ""
+"external ref='media/updating/update1.png' "
+"md5='9ff01eb653d92124746fc31efde2bf07'"
+msgstr ""
+"external ref='media/updating/update1.png' "
+"md5='9ff01eb653d92124746fc31efde2bf07'"
+
+#: updating.page:32
+msgid ""
+"When you are prompted to update Tor Browser, click on the Torbutton icon, "
+"then select “Check for Tor Browser Update”."
+msgstr ""
+"Nuair a iarrfar ort Brabhsálaí Tor a nuashonrú, cliceáil an cnaipe Tor, "
+"ansin roghnaigh “Lorg Nuashonrú ar Bhrabhsálaí Tor”."
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: updating.page:39
+msgctxt "_"
+msgid ""
+"external ref='media/updating/update3.png' "
+"md5='19b1f46d748dbcd9250883044165d218'"
+msgstr ""
+"external ref='media/updating/update3.png' "
+"md5='19b1f46d748dbcd9250883044165d218'"
+
+#: updating.page:41
+msgid ""
+"When Tor Browser has finished checking for updates, click on the “Update” "
+"button."
+msgstr ""
+"Tar éis do Bhrabhsálaí Tor nuashonruithe a lorg, cliceáil an cnaipe "
+"“Nuashonraigh”."
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: updating.page:48
+msgctxt "_"
+msgid ""
+"external ref='media/updating/update4.png' "
+"md5='7e8ead67c03597f00c580c77c3103fbb'"
+msgstr ""
+"external ref='media/updating/update4.png' "
+"md5='7e8ead67c03597f00c580c77c3103fbb'"
+
+#: updating.page:50
+msgid ""
+"Wait for the update to download and install, then restart Tor Browser. You "
+"will now be running the latest version."
+msgstr ""
+"Fan go dtí go mbeidh an nuashonrú íoslódáilte agus suiteáilte, agus atosaigh"
+" Brabhsálaí Tor. Ansin, beidh an leagan is déanaí agat."
+
+#: updating.page:58
+msgid "Updating Tor Browser manually"
+msgstr "Nuashonrú de láimh ar Bhrabhsálaí Tor"
+
+#: updating.page:61
+msgid ""
+"When you are prompted to update Tor Browser, finish the browsing session and"
+" close the program."
+msgstr ""
+"Nuair a iarrfar ort Brabhsálaí Tor a nuashonrú, críochnaigh an seisiún "
+"brabhsála agus dún an ríomhchlár."
+
+#: updating.page:67
+msgid ""
+"Remove Tor Browser from your system by deleting the folder that contains it "
+"(see the <link xref=\"uninstalling\">Uninstalling</link> section for more "
+"information)."
+msgstr ""
+"Chun Brabhsálaí Tor a bhaint de do chóras, scrios an fillteán ina bhfuil sé "
+"(féach ar <link xref=\"uninstalling\">Díshuiteáil</link> le tuilleadh eolais"
+" a fháil)."
+
+#: updating.page:74
+msgid ""
+"Visit <link href=\"https://www.torproject.org/projects/torbrowser.html.en\">"
+" https://www.torproject.org/projects/torbrowser.html.en</link> and download "
+"a copy of the latest Tor Browser release, then install it as before."
+msgstr ""
+"Tabhair cuairt ar <link "
+"href=\"https://www.torproject.org/projects/torbrowser.html.en\"> "
+"https://www.torproject.org/projects/torbrowser.html.en</link> agus íoslódáil"
+" cóip den leagan is déanaí de Bhrabhsálaí Tor, agus suiteáil é mar a rinne "
+"tú roimhe seo."
1
0
commit 3f888664afcfe6f15299ae73b76e4e4983079112
Author: Colin Childs <colin(a)torproject.org>
Date: Tue Sep 18 14:08:40 2018 -0500
Pushing sv translations
---
Makefile.am | 2 +-
sv/sv.po | 1817 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 1818 insertions(+), 1 deletion(-)
diff --git a/Makefile.am b/Makefile.am
index 5c58dea..8b1db95 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -8,7 +8,7 @@ TOR_AND_HTTPS = ../tor-and-https
HELP_ID = tor-browser-user-manual
HELP_FILES = $(shell cd $(srcdir)/C && git ls-files '*.page')
HELP_MEDIA = $(shell cd $(srcdir)/C && git ls-files 'media')
-HELP_LINGUAS = en-US ja @TOR_BROWSER_BUNDLE_LOCALES@
+HELP_LINGUAS = en-US ja sv @TOR_BROWSER_BUNDLE_LOCALES@
.PHONY: html
html: all media-symlinks.stamp
diff --git a/sv/sv.po b/sv/sv.po
new file mode 100644
index 0000000..a469561
--- /dev/null
+++ b/sv/sv.po
@@ -0,0 +1,1817 @@
+# Translators:
+# cryptohead <cryptohead(a)gmail.com>, 2016
+# Alexandra <alexandra_fischer90(a)hotmail.com>, 2016
+# WinterFairy <winterfairy(a)riseup.net>, 2016
+# Jonatan Nyberg, 2016
+# Daniel Sjöberg <sjbrg(a)protonmail.com>, 2016
+# Yoga Andersson <yoga.andersson(a)gmail.com>, 2016
+# Nikolai Stenfors <nikolai.stenfors(a)bahnhof.se>, 2016
+# Jacob Andersson <jacob.c.andersson(a)protonmail.com>, 2016
+# Bo Serrander <bserrander(a)gmail.com>, 2017
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"POT-Creation-Date: 2016-12-06 16:36-0600\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Bo Serrander <bserrander(a)gmail.com>, 2017\n"
+"Language-Team: Swedish (https://www.transifex.com/otf/teams/1519/sv/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: sv\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#. Put one translator per line, in the form NAME <EMAIL>, YEAR1, YEAR2
+msgctxt "_"
+msgid "translator-credits"
+msgstr "Lista med översättare"
+
+#: about-tor-browser.page:7
+msgid "Learn what Tor Browser can do to protect your privacy and anonymity"
+msgstr ""
+"Ta reda på vad Tor-webbläsaren kan göra för att skydda din integritet och "
+"anonymitet"
+
+#: about-tor-browser.page:10
+msgid "About Tor Browser"
+msgstr "Om Tor-webbläsare"
+
+#: about-tor-browser.page:12
+msgid ""
+"Tor Browser uses the Tor network to protect your privacy and anonymity. "
+"Using the Tor network has two main properties:"
+msgstr ""
+"Tor webbläsare använder Tor nätverket för att skydda din integritet och din "
+"anonymitet. Tor nätverk har två huvudsakliga egenskaper:"
+
+#: about-tor-browser.page:18
+msgid ""
+"Your internet service provider, and anyone watching your connection locally,"
+" will not be able to track your internet activity, including the names and "
+"addresses of the websites you visit."
+msgstr ""
+"Din Internetleverantör, och alla som bevakar på din anslutning lokalt, "
+"kommer inte att kunna spåra din Internet-aktivitet, inklusive namn och "
+"adresser till de webbplatser du besöker."
+
+#: about-tor-browser.page:25
+msgid ""
+"The operators of the websites and services that you use, and anyone watching"
+" them, will see a connection coming from the Tor network instead of your "
+"real Internet (IP) address, and will not know who you are unless you "
+"explicitly identify yourself."
+msgstr ""
+"Operatörerna av de webbplatser och tjänster som du använder, och alla som "
+"bevakar dem, kommer att se en förbindelse som kommer från Tor-nätverket "
+"istället för din riktiga Internet (IP) adress, och kommer inte att veta vem "
+"du är om du inte uttryckligen identifiera dig."
+
+#: about-tor-browser.page:34
+msgid ""
+"In addition, Tor Browser is designed to prevent websites from "
+"“fingerprinting” or identifying you based on your browser configuration."
+msgstr ""
+"Dessutom är Tor Browser utformad för att förhindra webbplatser från "
+"\"fingeravtryck\" eller identifiera dig baserat på din "
+"webbläsarkonfiguration."
+
+#: about-tor-browser.page:39
+msgid ""
+"By default, Tor Browser does not keep any browsing history. Cookies are only"
+" valid for a single session (until Tor Browser is exited or a <link xref"
+"=\"managing-identities#new-identity\">New Identity</link> is requested)."
+msgstr ""
+"Som standard behåller Tor Browser inte någon webbhistorik . Cookies är "
+"endast giltig för en enda session (tills Tor Browser avslutas eller en <link"
+" xref=\"managing-identities#new-identity\">Ny identitet </link> begärs)."
+
+#: about-tor-browser.page:50
+msgid "How Tor works"
+msgstr "Hur Tor fungerar"
+
+#: about-tor-browser.page:52
+msgid ""
+"Tor is a network of virtual tunnels that allows you to improve your privacy "
+"and security on the Internet. Tor works by sending your traffic through "
+"three random servers (also known as <em>relays</em>) in the Tor network. The"
+" last relay in the circuit (the “exit relay”) then sends the traffic out "
+"onto the public Internet."
+msgstr ""
+"Tor är ett nätverk av virtuella tunnlar som tillåter dig att förbättra din "
+"integritet och säkerhet på Internet. Tor fungerar genom att skicka din "
+"trafik genom tre slump servrar (även känd som <em>reläer</em>) i Tor-"
+"nätverket. Den sista relän i kretsen (\"exit relä\") skickar sedan trafiken "
+"ut på det publika Internet."
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: about-tor-browser.page:59
+msgctxt "_"
+msgid ""
+"external ref='media/how-tor-works.png' "
+"md5='6fe4151a88b7a518466f0582e40ccc8c'"
+msgstr ""
+"extern ref='media/how-tor-works.png' md5='6fe4151a88b7a518466f0582e40ccc8c'"
+
+#: about-tor-browser.page:60
+msgid ""
+"The image above illustrates a user browsing to different websites over Tor. "
+"The green middle computers represent relays in the Tor network, while the "
+"three keys represent the layers of encryption between the user and each "
+"relay."
+msgstr ""
+"Bilden ovan visar en användare som surfar till olika webbplatser över Tor. "
+"De gröna mellan datorerna representerar reläer i Tor-nätverket, medan de tre"
+" knapparna representerar lagren av kryptering mellan användaren och varje "
+"relä."
+
+#: bridges.page:6
+msgid "Learn what bridges are and how to get them"
+msgstr "Lär dig vad bryggor är och hur man får tillgång till dem"
+
+#: bridges.page:10
+msgid "Bridges"
+msgstr "Broar"
+
+#: bridges.page:12
+msgid ""
+"Most <link xref=\"transports\">Pluggable Transports</link>, such as obfs3 "
+"and obfs4, rely on the use of “bridge” relays. Like ordinary Tor relays, "
+"bridges are run by volunteers; unlike ordinary relays, however, they are not"
+" listed publicly, so an adversary cannot identify them easily. Using bridges"
+" in combination with pluggable transports helps to disguise the fact that "
+"you are using Tor."
+msgstr ""
+"Flesta <link xref = \"transports\">Pluggbara transporter</link>, som obfs3 "
+"och obfs4, är beroende av användningen av \"bro\"-reläer. Som vanliga Tor-"
+"reläer körs broar av volontärer. Till skillnad från vanliga reläer är de "
+"inte listade offentligt, så en motståndare kan inte identifiera dem enkelt. "
+"Användning av broar i kombination med pluggbara transporter hjälper till att"
+" dölja det faktum att du använder Tor."
+
+#: bridges.page:21
+msgid ""
+"Other pluggable transports, like meek, use different anti-censorship "
+"techniques that do not rely on bridges. You do not need to obtain bridge "
+"addresses in order to use these transports."
+msgstr ""
+"Andra pluggbara transporter, som meek, använder olika anticensurtekniker som"
+" inte bygger på broar. Du behöver inte få broadresser för att kunna använda "
+"dessa transporter."
+
+#: bridges.page:28
+msgid "Getting bridge addresses"
+msgstr "Skaffar bryggadresser"
+
+#: bridges.page:29
+msgid ""
+"Because bridge addresses are not public, you will need to request them "
+"yourself. You have two options:"
+msgstr ""
+"Eftersom bryggadresser inte är offentliga, måste du begära dem själv. Du har"
+" två alternativ:"
+
+#: bridges.page:36
+msgid ""
+"Visit <link "
+"href=\"https://bridges.torproject.org/\">https://bridges.torproject.org/</link>"
+" and follow the instructions, or"
+msgstr ""
+"Besök <link "
+"href=\"https://bridges.torproject.org/\">https://bridges.torproject.org/</link>"
+" och följ instruktionerna, eller"
+
+#: bridges.page:42
+msgid ""
+"Email bridges(a)torproject.org from a Gmail, Yahoo, or Riseup email address, "
+"or"
+msgstr ""
+"Maila bridges(a)torproject.org från en Gmail, Yahoo eller RiseUp e-postadress "
+"eller"
+
+#: bridges.page:51
+msgid "Entering bridge addresses"
+msgstr "Skriver in broadresser"
+
+#: bridges.page:52
+msgid ""
+"Once you have obtained some bridge addresses, you will need to enter them "
+"into Tor Launcher."
+msgstr "När du har fått några broadresser, måste du ange dem i Tor Launcher."
+
+#: bridges.page:57
+msgid ""
+"Choose “yes” when asked if your Internet Service Provider blocks connections"
+" to the Tor network. Select “Use custom bridges” and enter each bridge "
+"address on a separate line."
+msgstr ""
+"Välj \"ja\" på frågan om din Internet-tjänsteleverantören blockerar "
+"anslutningar till Tor-nätverket. Välj \"Använd egna bryggor\" och ange en "
+"bryggadress per rad."
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: bridges.page:63
+msgctxt "_"
+msgid ""
+"external ref='media/tor-launcher-custom-bridges_en-US.png' "
+"md5='93365c2aa3fb4d627497e83f28a39b7e'"
+msgstr ""
+"extern ref='media/tor-launcher-custom-bridges_en-US.png' "
+"md5='93365c2aa3fb4d627497e83f28a39b7e'"
+
+#: bridges.page:65
+msgid ""
+"Click “Connect”. Using bridges may slow down the connection compared to "
+"using ordinary Tor relays. If the connection fails, the bridges you received"
+" may be down. Please use one of the above methods to obtain more bridge "
+"addresses, and try again."
+msgstr ""
+"Klicka på \"Anslut\". Det kan gå långsammare när du använder bryggor "
+"jämntemot vanliga Tor-reläer. Om anslutningen misslyckas kan broadressen du "
+"fick vara nere. Använd en av metoderna ovan för att få fler broadresser och "
+"försök igen."
+
+#: circumvention.page:6
+msgid "What to do if the Tor network is blocked"
+msgstr "Vad du ska göra ifall Tor nätverket är blockerat"
+
+#: circumvention.page:10
+msgid "Circumvention"
+msgstr "Kringgående"
+
+#: circumvention.page:12
+msgid ""
+"Direct access to the Tor network may sometimes be blocked by your Internet "
+"Service Provider or by a government. Tor Browser includes some circumvention"
+" tools for getting around these blocks. These tools are called “pluggable "
+"transports”. See the <link xref=\"transports\">Pluggable Transports</link> "
+"page for more information on the types of transport that are currently "
+"available."
+msgstr ""
+"Direktåtkomst till Tor-nätverket kan ibland blockeras av din "
+"Internetleverantör eller av en regering. Tor Browser innehåller några "
+"kringgående verktyg för att komma runt dessa blockeringar. Dessa verktyg "
+"kallas \"pluggbara transporter\". Se sidan <link "
+"xref=\"transports\">Pluggbara transporter</link> för mer information om "
+"vilka transporttyper som för närvarande finns tillgängliga."
+
+#: circumvention.page:22
+msgid "Using pluggable transports"
+msgstr "Använder pluggbara transporter"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: circumvention.page:26 first-time.page:35
+msgctxt "_"
+msgid ""
+"external ref='media/circumvention/configure.png' "
+"md5='519d888303eadfe4cb03f178aedd90f5'"
+msgstr ""
+"extern ref='media/circumvention/configure.png' "
+"md5='519d888303eadfe4cb03f178aedd90f5'"
+
+#: circumvention.page:28
+msgid ""
+"To use pluggable transports, click \"Configure\" in the Tor Launcher window "
+"that appears when you first run Tor Browser."
+msgstr ""
+"För att använda pluggbara transporter, klicka på \"Konfigurera\" i Tor "
+"Launcher-fönstret som visas när du först kör Tor Browser."
+
+#: circumvention.page:33
+msgid ""
+"You can also configure pluggable transports while Tor Browser is running, by"
+" clicking on the green onion near your address bar and selecting “Tor "
+"Network Settings”."
+msgstr ""
+"Du kan också konfigurera pluggbara transporter medan Tor Browser körs, genom"
+" att klicka på den gröna löken i närheten av adressfältet och välja \"Tor "
+"nätverk inställningar\"."
+
+#: circumvention.page:41
+msgid ""
+"Select “yes” when asked if your Internet Service Provider blocks connections"
+" to the Tor network."
+msgstr ""
+"Välj \"ja\" på frågan om din Internet-tjänsteleverantören blockerar "
+"anslutningar till Tor-nätverket."
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: circumvention.page:49
+msgctxt "_"
+msgid ""
+"external ref='media/circumvention/bridges.png' "
+"md5='910cdd5e45860b81a1ad4739c589a195'"
+msgstr ""
+"extern ref='media/circumvention/bridges.png' "
+"md5='910cdd5e45860b81a1ad4739c589a195'"
+
+#: circumvention.page:51
+msgid ""
+"Select “Connect with provided bridges”. Tor Browser currently has six "
+"pluggable transport options to choose from."
+msgstr ""
+"Välj \"Anslut med tillhandahållna broar\". Tor Browser har för närvarande "
+"sex pluggbara transport alternativ att välja mellan."
+
+#: circumvention.page:60
+msgid "Which transport should I use?"
+msgstr "Vilka transporter ska jag använda?"
+
+#: circumvention.page:61
+msgid ""
+"Each of the transports listed in Tor Launcher’s menu works in a different "
+"way (for more details, see the <link xref=\"transports\">Pluggable "
+"Transports</link> page), and their effectiveness depends on your individual "
+"circumstances."
+msgstr ""
+"Var och en av de transporter som anges i Tor Launcher-menyn fungerar på ett "
+"annat sätt (för mer information, se <link xref=\"transports\">Pluggbara "
+"transporter</link>-sidan) och deras effektivitet beror på dina individuella "
+"omständigheter."
+
+#: circumvention.page:67
+msgid ""
+"If you are trying to circumvent a blocked connection for the first time, you"
+" should try the different transports: obfs3, obfs4, ScrambleSuit, fte, meek-"
+"azure, meek-amazon."
+msgstr ""
+"Om du försöker att kringgå en blockerad anslutning för första gången, bör du"
+" prova olika transporter: obfs3, obfs4, ScrambleSuit, fte, meed-azure, meek-"
+"amazon."
+
+#: circumvention.page:72
+msgid ""
+"If you try all of these options, and none of them gets you online, you will "
+"need to enter bridge addresses manually. Read the <link "
+"xref=\"bridges\">Bridges</link> section to learn what bridges are and how to"
+" obtain them."
+msgstr ""
+"Om du försöker alla dessa alternativ, och ingen av dem får dig på nätet, "
+"måste du ange broadresser manuellt. Läs avsnittet <link "
+"xref=\"bridges\">Broar</link> för att lära dig vilka broar som finns och hur"
+" man hämtar dem."
+
+#: downloading.page:7
+msgid "How to download Tor Browser"
+msgstr "Hur du laddar ner Tor"
+
+#: downloading.page:10
+msgid "Downloading"
+msgstr "Hämtar"
+
+#: downloading.page:12
+msgid ""
+"The safest and simplest way to download Tor Browser is from the official Tor"
+" Project website at https://www.torproject.org. Your connection to the site "
+"will be secured using <link xref=\"secure-connections\">HTTPS</link>, which "
+"makes it much harder for somebody to tamper with."
+msgstr ""
+"Det säkraste och enklaste sättet att ladda ner Tor Browser är från den "
+"officiella Tor Project-webbplatsen på https://www.torproject.org. Din "
+"anslutning till webbplatsen kommer att säkras med hjälp av <link xref"
+"=\"secure-connections\">HTTPS</link>, vilket gör det mycket svårare för "
+"någon att manipulera med."
+
+#: downloading.page:19
+msgid ""
+"However, there may be times when you cannot access the Tor Project website: "
+"for example, it could be blocked on your network. If this happens, you can "
+"use one of the alternative download methods listed below."
+msgstr ""
+"Det kan dock finnas tillfällen då du inte kan komma åt Tor Project-"
+"webbplatsen. Det kan till exempel vara blockerat på ditt nätverk. Om det "
+"händer kan du använda en av de alternativa hämtningsmetoderna nedan."
+
+#: downloading.page:27
+msgid "GetTor"
+msgstr "GetTor"
+
+#: downloading.page:28
+msgid ""
+"GetTor is a service that automatically responds to messages with links to "
+"the latest version of Tor Browser, hosted at a variety of locations, such as"
+" Dropbox, Google Drive and Github.."
+msgstr ""
+"GetTor är en tjänst som automatiskt svarar på meddelanden med länkar till "
+"den senaste versionen av Tor Browser, som finns på flera olika platser, till"
+" exempel Dropbox, Google Drive och Github."
+
+#: downloading.page:34
+msgid "To use GetTor via email:"
+msgstr "För att använda GetTor via e-post:"
+
+#: downloading.page:39
+msgid ""
+"Send an email to gettor(a)torproject.org, and in the body of the message "
+"simply write “windows”, “osx”, or “linux”, (without quotation marks) "
+"depending on your operating system."
+msgstr ""
+"Skicka ett e-post till gettor(a)torproject.org med något av följande i "
+"meddelandetexten \"winows\", \"osx\" eller \"linux\" (ta inte med "
+"citattecken) beroende på ditt val av operativsystem."
+
+#: downloading.page:46
+msgid ""
+"GetTor will respond with an email containing links from which you can "
+"download the Tor Browser package, the cryptographic signature (needed for "
+"verifying the download), the fingerprint of the key used to make the "
+"signature, and the package’s checksum. You may be offered a choice of "
+"“32-bit” or “64-bit” software: this depends on the model of the computer you"
+" are using."
+msgstr ""
+"GetTor svarar med ett e-postmeddelande med länkar från vilka du kan hämta "
+"Tor Browser-paketet, kryptografiska signaturen (behövs för att verifiera "
+"hämtningen), fingeravtryck av den nyckel som används för att göra signaturen"
+" och paketets kontrollsumma. Du kan erbjudas ett val av \"32-bitars\" eller "
+"\"64-bitars\" programvara: detta beror på vilken modell av datorn du "
+"använder."
+
+#: downloading.page:57
+msgid "To use GetTor via Twitter:"
+msgstr "För att använda GetTor via Twitter:"
+
+#: downloading.page:62
+msgid ""
+"To get links for downloading Tor Browser in English for OS X, send a Direct "
+"Message to @get_tor with the words \"osx en\" in it (you don't need to "
+"follow the account)."
+msgstr ""
+"För att få länkar för att hämta Tor Browser på engelska för OS X, skicka ett"
+" direktmeddelande till @get_tor med orden \"osx en\" i det (du behöver inte "
+"följa kontot)."
+
+#: downloading.page:70
+msgid "To use GetTor via Jabber/XMPP (Tor Messenger, Jitsi, CoyIM):"
+msgstr "För att använda GetTor via Jabber/XMPP (Tor Messenger, Jitsi, CoyIM):"
+
+#: downloading.page:75
+msgid ""
+"To get links for downloading Tor Browser in Chinese for Linux, send a "
+"message to gettor(a)torproject.org with the words \"linux zh\" in it."
+msgstr ""
+"För att få länkar för att hämta Tor Browser på kinesiska för Linux, skicka "
+"ett meddelande till gettor(a)torproject.org med orden \"linux zh\" i det."
+
+#: downloading.page:84
+msgid "Satori"
+msgstr "Satori"
+
+#: downloading.page:85
+msgid ""
+"Satori is an add-on for the Chrome or Chromium browsers that allows you to "
+"download several security and privacy programs from different sources."
+msgstr ""
+"Satori är ett tillägg för Chrome eller Chromium webbläsarna som låter dig "
+"hämta flera säkerhets- och sekretessprogram från olika källor."
+
+#: downloading.page:90
+msgid "To download Tor Browser using Satori:"
+msgstr "Ladda ner Tor med Satori:"
+
+#: downloading.page:95
+msgid "Install Satori from the Chrome App Store."
+msgstr "Installera Satori med Chrome App Store."
+
+#: downloading.page:100
+msgid "Select Satori from your browser’s Apps menu."
+msgstr "Välj Satori från din webbläsares Appar-meny."
+
+#: downloading.page:105
+msgid ""
+"When Satori opens, click on your preferred language. A menu will open "
+"listing the available downloads for that language. Find the entry for Tor "
+"Browser under the name of your operating system. Select either “A” or “B” "
+"after the name of the program — each one represents a different source from "
+"which to get the software. Your download will then begin."
+msgstr ""
+"När Satori öppnas klickar du på ditt önskade språk. Kommer en meny öppnas "
+"med listan över tillgängliga hämtningar för det språket. Hitta posten för "
+"Tor Browser under namnet på ditt operativsystem. Välj antingen \"A\" eller "
+"\"B\" efter programmets namn - var och en representerar en annan källa för "
+"att hämta mjukvaran. Din nedladdning startar sedan."
+
+#: downloading.page:115
+msgid ""
+"Wait for your download to finish, then find the “Generate Hash” section in "
+"Satori’s menu and click “Select Files”."
+msgstr ""
+"Vänta på att din hämtning är klar och hitta sedan avsnittet \"Generera "
+"Hash\" i Satori-menyn och klicka på \"Välj filer\"."
+
+#: downloading.page:121
+msgid ""
+"Select the downloaded Tor Browser file. Satori will display the checksum of "
+"the file, which you should compare with the software’s original checksum: "
+"you can find this by clicking the word “checksum” after the link you clicked"
+" on to start the download. If the checksums match, your download was "
+"successful, and you can <link xref=\"first-time\">begin using Tor "
+"Browser</link>. If they do not match, you may need to try downloading again,"
+" or from a different source."
+msgstr ""
+"Välj den hämtade Tor Browser-filen. Satori kommer att visa kontrollsumma för"
+" filen, som du bör jämföra med programmets ursprungliga kontrollsumma: du "
+"kan hitta det genom att klicka på ordet \"checksum\" efter länken du "
+"klickade på för att starta hämtningen. Om kontrollsummorna matchar var din "
+"hämtning framgångsrik, och du kan <link xref=\"first-time\">börja använda "
+"Tor Browser</link>. Om de inte matchar kan du behöva försöka hämta igen, "
+"eller från en annan källa."
+
+#: first-time.page:7
+msgid "Learn how to use Tor Browser for the first time"
+msgstr "Lär dig använda Tor för första gången"
+
+#: first-time.page:10
+msgid "Running Tor Browser for the first time"
+msgstr "Att använda Tor för första gången"
+
+#: first-time.page:12
+msgid ""
+"When you run Tor Browser for the first time, you will see the Tor Network "
+"Settings window. This offers you the option to connect directly to the Tor "
+"network, or to configure Tor Browser for your connection."
+msgstr ""
+"När du kör Tor Browser för första gången ser du fönstret Tor Network "
+"Settings. Detta ger dig möjlighet att ansluta direkt till Tor-nätverket "
+"eller konfigurera Tor Browser för din anslutning."
+
+#: first-time.page:19
+msgid "Connect"
+msgstr "Anslut"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: first-time.page:21 troubleshooting.page:18
+msgctxt "_"
+msgid ""
+"external ref='media/first-time/connect.png' "
+"md5='9d07068f751a3bfd274365a4ba8d90ca'"
+msgstr ""
+"external ref='media/first-time/connect.png' "
+"md5='9d07068f751a3bfd274365a4ba8d90ca'"
+
+#: first-time.page:23
+msgid ""
+"In most cases, choosing \"Connect\" will allow you to connect to the Tor "
+"network without any further configuration. Once clicked, a status bar will "
+"appear, showing Tor’s connection progress. If you are on a relatively fast "
+"connection, but this bar seems to get stuck at a certain point, see the "
+"<link xref=\"troubleshooting\">Troubleshooting</link> page for help solving "
+"the problem."
+msgstr ""
+"I de flesta fall kan du välja \"Anslut\" så att du kan ansluta till Tor-"
+"nätverket utan ytterligare konfiguration. Efter att du klickat visas ett "
+"statusfält som visar Tors anslutningsframsteg. Om du har en relativt snabb "
+"anslutning, men den här fältet fastnar vid en viss punkt, se sidan <link "
+"xref=\"troubleshooting\">Felsökning</link> för att lösa problemet."
+
+#: first-time.page:33
+msgid "Configure"
+msgstr "Konfigurera"
+
+#: first-time.page:37
+msgid ""
+"If you know that your connection is censored, or uses a proxy, you should "
+"select this option. Tor Browser will take you through a series of "
+"configuration options."
+msgstr ""
+"Om du vet att din anslutning är censurerad eller använder en proxy, ska du "
+"välja det här alternativet. Tor Browser tar dig igenom en rad "
+"konfigurationsalternativ."
+
+#: first-time.page:44
+msgid ""
+"The first screen asks if access to the Tor network is blocked or censored on"
+" your connection. If you do not believe this is the case, select “No”. If "
+"you know your connection is censored, or you have tried and failed to "
+"connect to the Tor network and no other solutions have worked, select “Yes”."
+" You will then be taken to the <link "
+"xref=\"circumvention\">Circumvention</link> screen to configure a pluggable "
+"transport."
+msgstr ""
+"Den första skärmen frågar om åtkomst till Tor-nätverket är blockerat eller "
+"censurerat på din anslutning. Om du inte tror detta är fallet, välj \"Nej\"."
+" Om du vet att din anslutning är censurerad, eller om du har försökt och "
+"misslyckats med att ansluta till Tor-nätverket och inga andra lösningar har "
+"fungerat, välj \"Ja\". Du kommer då att tas till skärmen <link "
+"xref=\"circumvention\">Kringgående</link> för att konfigurera en pluggbar "
+"transport."
+
+#: first-time.page:55
+msgid ""
+"The next screen asks if your connection uses a proxy. In most cases, this is"
+" not necessary. You will usually know if you need to answer “Yes”, as the "
+"same settings will be used for other browsers on your system. If possible, "
+"ask your network administrator for guidance. If your connection does not use"
+" a proxy, click “Continue”."
+msgstr ""
+"Nästa skärm frågar om din anslutning använder en proxy. I de flesta fall är "
+"det inte nödvändigt. Du vet vanligen om du behöver svara \"Ja\", eftersom "
+"samma inställningar kommer att användas för andra webbläsare på ditt system."
+" Om möjligt, fråga din nätverksadministratör för vägledning. Om din "
+"anslutning inte använder en proxy, klicka på \"Fortsätt\"."
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: first-time.page:63
+msgctxt "_"
+msgid ""
+"external ref='media/first-time/proxy_question.png' "
+"md5='30853b3e86cfd386bbc32e5b8b45a378'"
+msgstr ""
+"external ref='media/first-time/proxy_question.png' "
+"md5='30853b3e86cfd386bbc32e5b8b45a378'"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: first-time.page:66
+msgctxt "_"
+msgid ""
+"external ref='media/first-time/proxy.png' "
+"md5='13f21a351cd0aa1cf11aada690f3dc90'"
+msgstr ""
+"external ref='media/first-time/proxy.png' "
+"md5='13f21a351cd0aa1cf11aada690f3dc90'"
+
+#: index.page:6
+msgid "Tor Browser User Manual"
+msgstr "Tor Browser bruksanvisning"
+
+#: known-issues.page:6
+msgid "A list of known issues."
+msgstr "En lista över kända problem"
+
+#: known-issues.page:10
+msgid "Known Issues"
+msgstr "Kända problem"
+
+#: known-issues.page:14
+msgid ""
+"Tor needs your system clock (and your time zone) set to the correct time."
+msgstr ""
+"Tor kräver att din systemklocka (och din tidszon) är inställd på rätt tid."
+
+#: known-issues.page:19
+msgid ""
+"The following firewall software have been known to interfere with Tor and "
+"may need to be temporarily disabled:"
+msgstr ""
+"Följande brandväggsprogram har varit känd för att störa Tor och kan behöva "
+"inaktiveras tillfälligt:"
+
+#: known-issues.page:23
+msgid "Webroot SecureAnywhere"
+msgstr "Webroot SecureAnywhere"
+
+#: known-issues.page:26
+msgid "Kaspersky Internet Security 2012"
+msgstr "Kaspersky Internet Security 2012"
+
+#: known-issues.page:29
+msgid "Sophos Antivirus for Mac"
+msgstr "Sophos Antivirus for Mac"
+
+#: known-issues.page:32
+msgid "Microsoft Security Essentials"
+msgstr "Microsoft säkerhetsväsentligheter"
+
+#: known-issues.page:37
+msgid ""
+"Videos that require Adobe Flash are unavailable. Flash is disabled for "
+"security reasons."
+msgstr ""
+"Videoklipp som kräver Adobe Flash är inte tillgängliga. Flash är inaktiverad"
+" av säkerhetsskäl."
+
+#: known-issues.page:43
+msgid "Tor can not use a bridge if a proxy is set."
+msgstr "Tor kan inte använda en bro om en proxy är inställd."
+
+#: known-issues.page:48
+msgid ""
+"The Tor Browser package is dated January 1, 2000 00:00:00 UTC. This is to "
+"ensure that each software build is exactly reproducible."
+msgstr ""
+"Tor Browser paketet är daterad 1 jan 2000 00:00:00 UTC. Detta för att "
+"säkerställa att varje byggd mjukvara är exakt reproducerbar."
+
+#: known-issues.page:54
+msgid ""
+"To run Tor Browser on Ubuntu, users need to execute a shell script. Open "
+"\"Files\" (Unity's explorer), open Preferences → Behavior Tab → Set \"Run "
+"executable text files when they are opened\" to \"Ask every time\", then "
+"click OK."
+msgstr ""
+"För att köra Tor Browser på Ubuntu måste användarna exekvera ett skalskript."
+" Öppna \"Filer\" (Unity explorer), öppna Inställningar → Beteendeflik → Ange"
+" \"Kör körbara textfiler när de öppnas\" till \"Fråga varje gång\" och "
+"klicka sedan på OK."
+
+#: known-issues.page:62
+msgid ""
+"Tor Browser can also be started from the command line by running the "
+"following command from inside the Tor Browser directory:"
+msgstr ""
+"Tor Browser kan också startas från kommandoraden genom att köra följande "
+"kommando från inuti Tor Browser-katalogen:"
+
+#: known-issues.page:66
+#, no-wrap
+msgid ""
+"\n"
+" ./start-tor-browser.desktop\n"
+" "
+msgstr ""
+"\n"
+" ./start-tor-browser.desktop\n"
+" "
+
+#: managing-identities.page:6
+msgid "Learn how to control personally-identifying information in Tor Browser"
+msgstr ""
+"Lär dig hur du kontrollerar personligt identifierande information i Tor "
+"Browser"
+
+#: managing-identities.page:10
+msgid "Managing identities"
+msgstr "Hantera identiteter"
+
+#: managing-identities.page:12
+msgid ""
+"When you connect to a website, it is not only the operators of that website "
+"who can record information about your visit. Most websites now use numerous "
+"third-party services, including social networking “Like” buttons, analytics "
+"trackers, and advertising beacons, all of which can link your activity "
+"across different sites."
+msgstr ""
+"När du ansluter till en webbplats är det inte bara operatörerna på den "
+"webbplatsen som kan spela in information om ditt besök. De flesta "
+"webbplatser använder nu många tredjepartstjänster, bland annat "
+"\"Gilla\"-knappar för sociala nätverk, analytikerspårare och reklamfiler, "
+"som alla kan länka din aktivitet på olika webbplatser."
+
+#: managing-identities.page:20
+msgid ""
+"Using the Tor network stops observers from being able to discover your exact"
+" location and IP address, but even without this information they might be "
+"able to link different areas of your activity together. For this reason, Tor"
+" Browser includes some additional features that help you control what "
+"information can be tied to your identity."
+msgstr ""
+"Med hjälp av Tor-nätverket hindras observatörer från att kunna upptäcka din "
+"exakta plats och IP-adress, men även utan denna information kan de "
+"eventuellt länka olika delar av din verksamhet tillsammans. Av denna "
+"anledning innehåller Tor Browser några ytterligare funktioner som hjälper "
+"dig att styra vilken information som kan kopplas till din identitet."
+
+#: managing-identities.page:29
+msgid "The URL bar"
+msgstr "Adressfältet"
+
+#: managing-identities.page:30
+msgid ""
+"Tor Browser centers your web experience around your relationship with the "
+"website in the URL bar. Even if you connect to two different sites that use "
+"the same third-party tracking service, Tor Browser will force the content to"
+" be served over two different Tor circuits, so the tracker will not know "
+"that both connections originate from your browser."
+msgstr ""
+"Tor Browser centrerar din webbupplevelse kring ditt förhållande till "
+"webbplatsen i webbläsarfältet. Även om du ansluter till två olika "
+"webbplatser som använder samma tredjeparts spårningstjänst, kommer Tor "
+"Browser att tvinga innehållet som ska serveras över två olika Tor-kretsar, "
+"så spåraren vet inte att båda anslutningarna kommer från din webbläsare."
+
+#: managing-identities.page:38
+msgid ""
+"On the other hand, all connections to a single website address will be made "
+"over the same Tor circuit, meaning you can browse different pages of a "
+"single website in separate tabs or windows, without any loss of "
+"functionality."
+msgstr ""
+"Å andra sidan kommer alla anslutningar till en enda webbplatsadress att "
+"göras över samma Tor-krets, vilket innebär att du kan bläddra i olika sidor "
+"på en enda webbplats i separata flikar eller fönster, utan att det går någon"
+" förlust av funktionaliteten."
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: managing-identities.page:46
+msgctxt "_"
+msgid ""
+"external ref='media/managing-identities/circuit_full.png' "
+"md5='bd46d22de952fee42643be46d3f95928'"
+msgstr ""
+"external ref='media/managing-identities/circuit_full.png' "
+"md5='bd46d22de952fee42643be46d3f95928'"
+
+#: managing-identities.page:48
+msgid ""
+"You can see a diagram of the circuit that Tor Browser is using for the "
+"current tab in the onion menu."
+msgstr ""
+"Du kan se ett diagram över den krets som Tor Browser använder för den "
+"aktuella fliken i onionmenyn."
+
+#: managing-identities.page:55
+msgid "Logging in over Tor"
+msgstr "Logga in över Tor"
+
+#: managing-identities.page:56
+msgid ""
+"Although Tor Browser is designed to enable total user anonymity on the web, "
+"there may be situations in which it makes sense to use Tor with websites "
+"that require usernames, passwords, or other identifying information."
+msgstr ""
+"Även om Tor Browser är utformad för att möjliggöra total användaranonymitet "
+"på webben kan det finnas situationer där det är vettigt att använda Tor med "
+"webbplatser som kräver användarnamn, lösenord eller annan identifierande "
+"information."
+
+#: managing-identities.page:62
+msgid ""
+"If you log into a website using a regular browser, you also reveal your IP "
+"address and geographical location in the process. The same is often true "
+"when you send an email. Logging into your social networking or email "
+"accounts using Tor Browser allows you to choose exactly which information "
+"you reveal to the websites you browse. Logging in using Tor Browser is also "
+"useful if the website you are trying to reach is censored on your network."
+msgstr ""
+"Om du loggar in på en webbplats med en vanlig webbläsare avslöjar du också "
+"din IP-adress och geografiska plats i processen. Detsamma är ofta sant när "
+"du skickar ett mail. Genom att logga in på dina sociala nätverk eller "
+"e-postkonton med hjälp av Tor Browser kan du välja exakt vilken information "
+"du avslöjar för de webbplatser du surfar på. Att logga in med Tor Browser är"
+" också användbart om webbplatsen du försöker nå är censurerad på ditt "
+"nätverk."
+
+#: managing-identities.page:72
+msgid ""
+"When you log in to a website over Tor, there are several points you should "
+"bear in mind:"
+msgstr ""
+"När du loggar in på en webbplats över Tor finns det flera punkter du bör "
+"tänka på: "
+
+#: managing-identities.page:79
+msgid ""
+"See the <link xref=\"secure-connections\">Secure Connections</link> page for"
+" important information on how to secure your connection when logging in."
+msgstr ""
+"Se <link xref=\"secure-connections\">Säkra anslutningar</link>-sidan för "
+"viktig information om hur du säkrar din anslutning när du loggar in."
+
+#: managing-identities.page:87
+msgid ""
+"Tor Browser often makes your connection appear as though it is coming from "
+"an entirely different part of the world. Some websites, such as banks or "
+"email providers, might interpret this as a sign that your account has been "
+"hacked or compromised, and lock you out. The only way to resolve this is by "
+"following the site’s recommended procedure for account recovery, or "
+"contacting the operators and explaining the situation."
+msgstr ""
+"Tor Browser gör att din anslutning ofta visas som om den kommer från en helt"
+" annan del av världen. Vissa webbplatser, till exempel banker eller "
+"e-postleverantörer, kan tolka detta som ett tecken på att ditt konto har "
+"hackats eller kompromissad och låser ut dig. Det enda sättet att lösa det "
+"här är att följa webbplatsens rekommenderade procedur för kontoåterställning"
+" eller kontakta operatörerna och förklara situationen."
+
+#: managing-identities.page:101
+msgid "Changing identities and circuits"
+msgstr "Ändra identiteter och kretsar"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: managing-identities.page:103
+msgctxt "_"
+msgid ""
+"external ref='media/managing-identities/new_identity.png' "
+"md5='15b01e35fa83185d94b57bf0ccf09d76'"
+msgstr ""
+"external ref='media/managing-identities/new_identity.png' "
+"md5='15b01e35fa83185d94b57bf0ccf09d76'"
+
+#: managing-identities.page:105
+msgid ""
+"Tor Browser features “New Identity” and “New Tor Circuit for this Site” "
+"options, located in the Torbutton menu."
+msgstr ""
+"Tor Browser har alternativet \"Ny identitet\" och \"Ny Tor krets för denna "
+"sida\", som finns i Torbutton-menyn."
+
+#: managing-identities.page:111
+msgid "New Identity"
+msgstr "Ny identitet"
+
+#: managing-identities.page:112
+msgid ""
+"This option is useful if you want to prevent your subsequent browser "
+"activity from being linkable to what you were doing before. Selecting it "
+"will close all your open tabs and windows, clear all private information "
+"such as cookies and browsing history, and use new Tor circuits for all "
+"connections. Tor Browser will warn you that all activity and downloads will "
+"be stopped, so take this into account before clicking “New Identity”."
+msgstr ""
+"Denna inställningen är användbar ifall du vill förebygga din föregående "
+"aktivitet ska vara länkbar med vad du har gjort innan. Vid val av denna "
+"inställningen kommer att stänga alla öppna flikar, fönster, all privat data "
+"som cookies och webbläsar historik kommer att tas bort, och nya Tor kretsar "
+"kommer användas för alla uppkopplingar. Tor webläsaren kommer att varna dig "
+"att all aktivitet och nedladdningar kommer att stoppas, tänk på detta innan "
+"du klicka \"Ny identitet\"."
+
+#: managing-identities.page:123
+msgid "New Tor Circuit for this Site"
+msgstr "Ny Tor-krets för den här webbplatsen"
+
+#: managing-identities.page:124
+msgid ""
+"This option is useful if the <link xref=\"about-tor-browser#how-tor-"
+"works\">exit relay</link> you are using is unable to connect to the website "
+"you require, or is not loading it properly. Selecting it will cause the "
+"currently-active tab or window to be reloaded over a new Tor circuit. Other "
+"open tabs and windows from the same website will use the new circuit as well"
+" once they are reloaded. This option does not clear any private information "
+"or unlink your activity, nor does it affect your current connections to "
+"other websites."
+msgstr ""
+"Det här alternativet är användbart om <link xref=\"about-tor-browser#how-"
+"tor-works\">utgångsrelän</link> du använder inte kan ansluta till "
+"webbplatsen du begär, eller den laddas inte ordentligt. Om du väljer det "
+"kommer den aktuella aktiva fliken eller fönstret att laddas om över en ny "
+"Tor-krets. Andra öppna flikar och fönster från samma webbplats kommer även "
+"att använda den nya kretsen när de laddas om. Det här alternativet rensar "
+"inte någon privat information eller kopplar bort din aktivitet, och det "
+"påverkar inte dina aktuella anslutningar till andra webbplatser."
+
+#: onionsites.page:6
+msgid "Services that are only accessible using Tor"
+msgstr "Tjänster som endast nås via Tor"
+
+#: onionsites.page:10
+msgid "Onion Services"
+msgstr "Onion tjänster"
+
+#: onionsites.page:11
+msgid ""
+"Onion services (formerly known as “hidden services”) are services (like "
+"websites) that are only accessible through the Tor network."
+msgstr ""
+"Onion tjänster (innan känt som \"gömda tjänster) är tjänster (t.ex "
+"webbplatser) som endast är synliga via Tor nätverket"
+
+#: onionsites.page:16
+msgid ""
+"Onion services offer several advantages over ordinary services on the non-"
+"private web:"
+msgstr ""
+"Onion tjänster har fler fördelar över vanliga tjänster för den icke privata "
+"webben."
+
+#: onionsites.page:23
+msgid ""
+"An onion services’s location and IP address are hidden, making it difficult "
+"for adversaries to censor it or identify its operators."
+msgstr ""
+"En Onions användares plats och IP adress är gömd, vilket gör det svårt för "
+"motståndare att censurera den eller identifiera användaren."
+
+#: onionsites.page:29
+msgid ""
+"All traffic between Tor users and onion services is end-to-end encrypted, so"
+" you do not need to worry about <link xref=\"secure-connections\">connecting"
+" over HTTPS</link>."
+msgstr ""
+"All trafik mellan Tor användaren och Onions tjänster är end-to-end "
+"krypterat, så du behöver inte oroa dig över <link xref=\"secure-"
+"connections\"> förbinder över HTTPS </link>."
+
+#: onionsites.page:36
+msgid ""
+"The address of an onion service is automatically generated, so the operators"
+" do not need to purchase a domain name; the .onion URL also helps Tor ensure"
+" that it is connecting to the right location and that the connection is not "
+"being tampered with."
+msgstr ""
+"Adressen för en Onion tjänst genereras automatisk, användaren behöver inte "
+"köpa ett domän namn; .onion URL som hjälper Tor säkerställa att förbindelsen"
+" är till rätt plats och att anslutningen inte blir manipuleras."
+
+#: onionsites.page:46
+msgid "How to access an onion service"
+msgstr "Hur du kan komma åt en onion tjänst"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: onionsites.page:48
+msgctxt "_"
+msgid ""
+"external ref='media/onionsites/onion_url.png' "
+"md5='f97f7fe10f07c3959c4430934974bbaa'"
+msgstr ""
+"external ref='media/onionsites/onion_url.png' "
+"md5='f97f7fe10f07c3959c4430934974bbaa'"
+
+#: onionsites.page:50
+msgid ""
+"Just like any other website, you will need to know the address of an onion "
+"service in order to connect to it. An onion address is a string of sixteen "
+"mostly random letters and numbers, followed by “.onion”."
+msgstr ""
+"Precis som vilken annan webbplats behöver du veta adressen till en onion "
+"tjänst för att kunna ansluta dig till den. En Onion adress är en sträng med "
+"sexton slumpmässigt valda bokstäver och nummer följt av .onion."
+
+#: onionsites.page:58 troubleshooting.page:10
+msgid "Troubleshooting"
+msgstr "Felsökning"
+
+#: onionsites.page:59
+msgid ""
+"If you cannot reach the onion service you require, make sure that you have "
+"entered the 16-character onion address correctly: even a small mistake will "
+"stop Tor Browser from being able to reach the site."
+msgstr ""
+"Ifall du inte kan nå Onion tjänsten du vill, dubbel kolla att de 16 tecken i"
+" onion adressen stämmer. Även ett lite misstag kan stoppa Tor webbläsaren "
+"från att kunna nå sidan."
+
+#: onionsites.page:64
+msgid ""
+"If you are still unable to connect to the onion service, please try again "
+"later. There may be a temporary connection issue, or the site operators may "
+"have allowed it to go offline without warning."
+msgstr ""
+"Om du fortfarande inte kan ansluta till Onion tjänsten, var god att försök "
+"senare. Det kan finnas tillfälliga anslutnings problem, eller har en sid "
+"operatör låtit den gå offline utan att ge en förvarning. "
+
+#: onionsites.page:69
+msgid ""
+"You can also ensure that you're able to access other onion services by "
+"connecting to <link href=\"http://3g2upl4pq6kufc4m.onion/\">DuckDuckGo's "
+"Onion Service</link>"
+msgstr ""
+"Du kan också se till att du har tillgång till andra onion-tjänster genom att"
+" ansluta till <link href=\"http://3g2upl4pq6kufc4m.onion/\">DuckDuckGo's "
+"Onion Service</link>"
+
+#: plugins.page:6
+msgid "How Tor Browser handles add-ons, plugins and JavaScript"
+msgstr "Hur Tor Browser hanterar add-ons, pluginsoch JavaScript"
+
+#: plugins.page:10
+msgid "Plugins, add-ons and JavaScript"
+msgstr "Plugins, add-ons och JavaScript"
+
+#: plugins.page:13
+msgid "Flash Player"
+msgstr "Flash Player"
+
+#: plugins.page:14
+msgid ""
+"Video websites, such as Vimeo make use of the Flash Player plugin to display"
+" video content. Unfortunately, this software operates independently of Tor "
+"Browser and cannot easily be made to obey Tor Browser’s proxy settings. It "
+"can therefore reveal your real location and IP address to the website "
+"operators, or to an outside observer. For this reason, Flash is disabled by "
+"default in Tor Browser, and enabling it is not recommended."
+msgstr ""
+"Video webbplatser, som Vimeo, använder sig av Flash Player för att kunna "
+"spela upp video innehållet. Tyvärr verkar detta programmet utanför Tor "
+"webbläsaren och det går inte att få det att lätt uppnå Tor webbläsarens "
+"proxy inställningar. Flash player kan därför visa din riktiga position och "
+"IP-adress till webbplatsens operatör eller andra observatörer. På grund av "
+"detta är Flash avstängt från början i Tor webbläsaren, men det går att slå "
+"på den fast det rekomenderas inte."
+
+#: plugins.page:23
+msgid ""
+"Some video websites (such as YouTube) offer alternative video delivery "
+"methods that do not use Flash. These methods may be compatible with Tor "
+"Browser."
+msgstr ""
+"En del video webbplatser (som Youtube) erbjuder andra alternativ för att "
+"kunna spela upp video innehållet som inte använder sig av Flash. Dessa "
+"alternativen kan vara kompatibla med Tor webbläsaren."
+
+#: plugins.page:31
+msgid "JavaScript"
+msgstr "JavaScript"
+
+#: plugins.page:32
+msgid ""
+"JavaScript is a programming language that websites use to offer interactive "
+"elements such as video, animation, audio, and status timelines. "
+"Unfortunately, JavaScript can also enable attacks on the security of the "
+"browser, which might lead to deanonymization."
+msgstr ""
+"JavaScript är ett programerings språk som används av webbplatser för att "
+"skapa interaktiva delar som video, animationer, ljud och status tidslinjer. "
+"Javascrupt kan tyvärr också göra det möjligt för attacker på webbläsarens "
+"säkerhet, vilket kan leda till att du inte är anonym längre. "
+
+#: plugins.page:39
+msgid ""
+"Tor Browser includes an add-on called NoScript, accessed through the “S” "
+"icon at the top-left of the window, which allows you to control the "
+"JavaScript that runs on individual web pages, or to block it entirely."
+msgstr ""
+"Tor webbläsaren inkluderar ett plug-in som heter NoScript, tillgängligt via "
+"\"S\" ikonen högst upp i fönstrets vänstra hörnan, vilket gör det möjligt "
+"för dig att kontrollera den JavaScript som körs på inviduella webbplatser "
+"eller att blocker allt helt. "
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: plugins.page:45
+msgctxt "_"
+msgid ""
+"external ref='media/plugins/noscript_menu.png' "
+"md5='df9e684b76a3c2e2bdcb879a19c20471'"
+msgstr ""
+"external ref='media/plugins/noscript_menu.png' "
+"md5='df9e684b76a3c2e2bdcb879a19c20471'"
+
+#: plugins.page:47
+msgid ""
+"Users who require a high degree of security in their web browsing should set"
+" Tor Browser’s <link xref=\"security-slider\">Security Slider</link> to "
+"“Medium-High” (which disables JavaScript for non-HTTPS websites) or “High” "
+"(which does so for all websites). However, disabling JavaScript will prevent"
+" many websites from displaying correctly, so Tor Browser’s default setting "
+"is to allow all websites to run scripts."
+msgstr ""
+"Användare som behöver en hög grad av säkerhet i sin webbläsning bör ställa "
+"in Tor Browsers <link xref=\"security-slider\">Säkerhetsreglage</link> till "
+"\"Medel-Hög\" (som inaktiverar JavaScript för webbplatser utan HTTPS) eller "
+"\"Hög\" (vilket gör det för alla webbplatser). Om du inaktiverar JavaScript "
+"kommer det dock att hindra att många webbplatser visas korrekt, så Tor "
+"Browsers standardinställning tillåter alla webbplatser att köra skript."
+
+#: plugins.page:58
+msgid "Browser Add-ons"
+msgstr "Add-ons till webläsaren"
+
+#: plugins.page:59
+msgid ""
+"Tor Browser is based on Firefox, and any browser add-ons or themes that are "
+"compatible with Firefox can also be installed in Tor Browser."
+msgstr ""
+"Tor Browser är baserad på Firefox, och alla webbläsartillägg eller teman som"
+" är kompatibla med Firefox kan också installeras i Tor Browser."
+
+#: plugins.page:64
+msgid ""
+"However, the only add-ons that have been tested for use with Tor Browser are"
+" those included by default. Installing any other browser add-ons may break "
+"functionality in Tor Browser or cause more serious problems that affect your"
+" privacy and security. It is strongly discouraged to install additional add-"
+"ons, and the Tor Project will not offer support for these configurations."
+msgstr ""
+"Men de enda tillägg som har testats för användning med Tor Browser är de som"
+" ingår som standard. Installera andra tilläggsprogram för webbläsare kan "
+"bryta funktionen i Tor Browser eller orsaka allvarligare problem som "
+"påverkar din integritet och säkerhet. Det är starkt avskräckt att installera"
+" ytterligare tillägg, och Tor Project erbjuder inte stöd för dessa "
+"konfigurationer."
+
+#: secure-connections.page:8
+msgid "Learn how to protect your data using Tor Browser and HTTPS"
+msgstr "Lär hur du skyddar din data med hjälp av Tor Browser och HTTPS"
+
+#: secure-connections.page:12
+msgid "Secure Connections"
+msgstr "Säkra anslutningar"
+
+#: secure-connections.page:14
+msgid ""
+"If personal information such as a login password travels unencrypted over "
+"the Internet, it can very easily be intercepted by an eavesdropper. If you "
+"are logging into any website, you should make sure that the site offers "
+"HTTPS encryption, which protects against this kind of eavesdropping. You can"
+" verify this in the URL bar: if your connection is encrypted, the address "
+"will begin with “https://”, rather than “http://”."
+msgstr ""
+"Om personuppgifter, t.ex. ett inloggningslösenord, körs okrypterat via "
+"Internet, kan det mycket enkelt avlyssas av en tjuvlyssnare. Om du loggar in"
+" på någon webbplats bör du se till att webbplatsen erbjuder HTTPS-"
+"kryptering, vilket skyddar mot denna typ av avlyssning. Du kan verifiera "
+"detta i adressfältet: Om din anslutning är krypterad börjar adressen med "
+"\"https://\", snarare än \"http://\"."
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: secure-connections.page:24
+msgctxt "_"
+msgid ""
+"external ref='media/secure-connections/https.png' "
+"md5='364bcbde7a649b0cea9ae178007c1a50'"
+msgstr ""
+"external ref='media/secure-connections/https.png' "
+"md5='364bcbde7a649b0cea9ae178007c1a50'"
+
+#: secure-connections.page:26
+msgid ""
+"The following visualization shows what information is visible to "
+"eavesdroppers with and without Tor Browser and HTTPS encryption:"
+msgstr ""
+"Följande visualisering visar vilken information som är synlig för "
+"tjuvlyssnare med och utan Tor Browser och HTTPS-kryptering:"
+
+#: secure-connections.page:35
+msgid ""
+"Click the “Tor” button to see what data is visible to observers when you're "
+"using Tor. The button will turn green to indicate that Tor is on."
+msgstr ""
+"Klicka på \"Tor\"-knappen för att se vilka data som är synliga för "
+"observatörer när du använder Tor. Knappen blir grön för att indikera att Tor"
+" är på."
+
+#: secure-connections.page:42
+msgid ""
+"Click the “HTTPS” button to see what data is visible to observers when "
+"you're using HTTPS. The button will turn green to indicate that HTTPS is on."
+msgstr ""
+"Klicka på knappen \"HTTPS\" för att se vilken data som är synlig för "
+"observatörer när du använder HTTPS. Knappen blir grön för att indikera att "
+"HTTPS är på."
+
+#: secure-connections.page:49
+msgid ""
+"When both buttons are green, you see the data that is visible to observers "
+"when you are using both tools."
+msgstr ""
+"När båda knapparna är gröna, ser du de data som är synliga för observatörer "
+"när du använder båda verktygen."
+
+#: secure-connections.page:55
+msgid ""
+"When both buttons are grey, you see the data that is visible to observers "
+"when you don't use either tool."
+msgstr ""
+"När båda knapparna är grå, ser du de data som är synliga för observatörer "
+"när du inte använder något av dessa verktyg."
+
+#: secure-connections.page:62
+msgid "Potentially visible data"
+msgstr "Potentiellt synliga data"
+
+#: secure-connections.page:70
+msgid "The site being visited."
+msgstr "Webbplatsen som besöks."
+
+#: secure-connections.page:81
+msgid "Username and password used for authentication."
+msgstr "Användarnamn och lösenord som används för autentisering"
+
+#: secure-connections.page:92
+msgid "Data being transmitted."
+msgstr "Data överförs"
+
+#: secure-connections.page:103
+msgid ""
+"Network location of the computer used to visit the website (the public IP "
+"address)."
+msgstr ""
+"Nätverksplats på datorn som används för att besöka webbplatsen (den publika "
+"IP-adress)."
+
+#: secure-connections.page:115
+msgid "Whether or not Tor is being used."
+msgstr "Om Tor används eller ej"
+
+#: security-slider.page:6
+msgid "Configuring Tor Browser for security and usability"
+msgstr "Konfigurera Tor Browser för säkerhet och användbarhet"
+
+#: security-slider.page:10
+msgid "Security Slider"
+msgstr "Säkerhetsreglage"
+
+#: security-slider.page:11
+msgid ""
+"Tor Browser includes a “Security Slider” that lets you increase your "
+"security by disabling certain web features that can be used to attack your "
+"security and anonymity. Increasing Tor Browser’s security level will stop "
+"some web pages from functioning properly, so you should weigh your security "
+"needs against the degree of usability you require."
+msgstr ""
+"Tor Browser innehåller en \"Säkerhetsreglage\" som låter dig öka säkerheten "
+"genom att inaktivera vissa webbfunktioner som kan användas för att attackera"
+" din säkerhet och anonymitet. Ökande av Tor Browserens säkerhetsnivå hindrar"
+" vissa webbplatser från att fungera korrekt, så du borde väga dina "
+"säkerhetsbehov mot den grad av användbarhet du behöver."
+
+#: security-slider.page:21
+msgid "Accessing the Security Slider"
+msgstr "Åtkomst till säkerhetsreglaget"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: security-slider.page:23
+msgctxt "_"
+msgid ""
+"external ref='media/security-slider/slider.png' "
+"md5='3c469cd3ed9f60ebb6bbbc63daa90082'"
+msgstr ""
+"external ref='media/security-slider/slider.png' "
+"md5='3c469cd3ed9f60ebb6bbbc63daa90082'"
+
+#: security-slider.page:25
+msgid ""
+"The Security Slider is located in Torbutton’s “Privacy and Security "
+"Settings” menu."
+msgstr ""
+"Säkerhetsreglaget finns i Torbuttons \"Sekretess och "
+"säkerhetsinställningar\"-meny."
+
+#: security-slider.page:32
+msgid "Security Levels"
+msgstr "Säkerhetsnivåer"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: security-slider.page:34
+msgctxt "_"
+msgid ""
+"external ref='media/security-slider/slider_window.png' "
+"md5='c733bdccd1731ed1a772777b25bae7a1'"
+msgstr ""
+"external ref='media/security-slider/slider_window.png' "
+"md5='c733bdccd1731ed1a772777b25bae7a1'"
+
+#: security-slider.page:36
+msgid ""
+"Increasing the level of the Security Slider will disable or partially "
+"disable certain browser features to protect against possible attacks."
+msgstr ""
+"Om du höjer nivån på säkerhetsreglaget kommer du att inaktivera eller delvis"
+" inaktivera vissa webbläsarfunktioner för att skydda mot eventuella "
+"attacker."
+
+#: security-slider.page:42
+msgid "High"
+msgstr "Hög"
+
+#: security-slider.page:43
+msgid ""
+"At this level, HTML5 video and audio media become click-to-play via "
+"NoScript; all JavaScript performance optimizations are disabled; some "
+"mathematical equations may not display properly; some font rendering "
+"features are disabled; some types of image are disabled; Javascript is "
+"disabled by default on all sites; most video and audio formats are disabled;"
+" and some fonts and icons may not display correctly."
+msgstr ""
+"På den här nivån blir HTML5-video och ljudmedia klicka-för-att-spela via "
+"NoScript; alla JavaScript-prestandaoptimeringar är inaktiverade; vissa "
+"matematiska ekvationer kanske inte visas korrekt; vissa typsnittsfunktioner "
+"är inaktiverade; vissa typer av bilder är inaktiverade; Javascript är "
+"inaktiverat som standard på alla webbplatser; De flesta video- och "
+"ljudformat är inaktiverade; och vissa typsnitt och ikoner kanske inte visas "
+"korrekt."
+
+#: security-slider.page:53
+msgid "Medium-High"
+msgstr "Medium-hög"
+
+#: security-slider.page:54
+msgid ""
+"At this level, HTML5 video and audio media become click-to-play via "
+"NoScript; all JavaScript performance optimizations are disabled; some "
+"mathematical equations may not display properly; some font rendering "
+"features are disabled; some types of image are disabled; and JavaScript is "
+"disabled by default on all non-<link xref=\"secure-"
+"connections\">HTTPS</link> sites."
+msgstr ""
+"På den här nivån blir HTML5-video och ljudmedia klicka-för-att-spela via "
+"NoScript; alla JavaScript-prestandaoptimeringar är inaktiverade; vissa "
+"matematiska ekvationer kanske inte visas korrekt; vissa typsnittsfunktioner "
+"är inaktiverade; vissa typer av bilder är inaktiverade; Javascript är "
+"inaktiverat som standard på alla webbplatser; De flesta video- och "
+"ljudformat är inaktiverade; och vissa typsnitt och ikoner kanske inte visas "
+"korrekt på alla <link xref=\"secure-connections\">HTTPS</link>-sidor."
+
+#: security-slider.page:64
+msgid "Medium-Low"
+msgstr "Medium-låg"
+
+#: security-slider.page:65
+msgid ""
+"At this level, HTML5 video and audio media become click-to-play via "
+"NoScript; some <link xref=\"plugins\">JavaScript</link> performance "
+"optimizations are disabled, causing some websites to run more slowly; and "
+"some mathematical equations may not display properly."
+msgstr ""
+"På den här nivån blir HTML5-video och ljudmedia klicka-för-att-spela via "
+"NoScript; vissa <link xref=\"plugins\">JavaScript</link> "
+"prestandaoptimeringar är inaktiverade, vilket gör att vissa webbplatser körs"
+" långsammare; och vissa matematiska ekvationer kanske inte visas korrekt."
+
+#: security-slider.page:73
+msgid "Low"
+msgstr "Låg"
+
+#: security-slider.page:74
+msgid ""
+"At this level, all browser features are enabled. This is the most usable "
+"option."
+msgstr ""
+"På den här säkerhetsnivån är webbläsarens alla funktioner aktiverade. Detta "
+"är det mest användbara alternativet. "
+
+#: transports.page:6 transports.page:20
+msgid "Types of pluggable transport"
+msgstr "Typer av pluggbara transporter"
+
+#: transports.page:10
+msgid "Pluggable Transports"
+msgstr "Pluggbara transporter"
+
+#: transports.page:12
+msgid ""
+"Pluggable transports are tools that Tor can use to disguise the traffic it "
+"sends out. This can be useful in situations where an Internet Service "
+"Provider or other authority is actively blocking connections to the Tor "
+"network."
+msgstr ""
+"Pluggbara transporter är verktyg som Tor kan använda för att dölja den "
+"trafik som den skickar ut. Detta kan vara användbart i situationer där en "
+"Internetleverantör eller annan myndighet aktivt blockerar anslutningar till "
+"Tor-nätverket."
+
+#: transports.page:21
+msgid ""
+"Currently there are six pluggable transports available, but more are being "
+"developed."
+msgstr ""
+"För närvarande finns sex pluggbara transporter tillgängliga, men fler "
+"utvecklas."
+
+#: transports.page:28
+msgid "obfs3"
+msgstr "obfs3"
+
+#: transports.page:33
+msgid ""
+"obfs3 makes Tor traffic look random, so that it does not look like Tor or "
+"any other protocol. obfs3 bridges will work in most places."
+msgstr ""
+"obfs3 gör att Tor-trafiken ser slumpmässig ut, så att den inte ser ut som "
+"Tor eller något annat protokoll. obfs3-broar kommer att fungera på de flesta"
+" platser."
+
+#: transports.page:42
+msgid "obfs4"
+msgstr "obfs4"
+
+#: transports.page:47
+msgid ""
+"obfs4 makes Tor traffic look random like obfs3, and also prevents censors "
+"from finding bridges by Internet scanning. obfs4 bridges are less likely to "
+"be blocked than obfs3 bridges."
+msgstr ""
+"obfs4 gör att Tor-trafiken ser slumpmässigt ut som obfs3, och hindrar också "
+"censorer från att hitta broar via Internet-skanning. obfs4-bryggor är mindre"
+" benägna att blockeras än obfs3-broar."
+
+#: transports.page:56
+msgid "Scramblesuit"
+msgstr "Scramblesuit"
+
+#: transports.page:61
+msgid "ScrambleSuit is similar to obfs4 but has a different set of bridges."
+msgstr "ScrambleSuit liknar obfs4 men har en annan uppsättning av bryggor."
+
+#: transports.page:69
+msgid "FTE"
+msgstr "FTE"
+
+#: transports.page:74
+msgid ""
+"FTE (format-transforming encryption) disguises Tor traffic as ordinary web "
+"(HTTP) traffic."
+msgstr ""
+"FTE (format-omvandlingskryptering) döljer Tor-trafik som vanlig webb (HTTP) "
+"trafik."
+
+#: transports.page:82
+msgid "meek"
+msgstr "meek"
+
+#: transports.page:87
+msgid ""
+"These transports all make it look like you are browsing a major web site "
+"instead of using Tor. meek-amazon makes it look like you are using Amazon "
+"Web Services; meek-azure makes it look like you are using a Microsoft web "
+"site; and meek-google makes it look like you are using Google search."
+msgstr ""
+"Dessa transporter gör att det ser ut som om du surfar på en större webbplats"
+" istället för att använda Tor. meek-amazon gör att det ser ut som om du "
+"använder Amazon Web Services; meek azure gör att det ser ut som om du "
+"använder en Microsoft-webbplats. och meek-google gör att det ser ut som om "
+"du använder Google-sökning."
+
+#: troubleshooting.page:6
+msgid "What to do if Tor Browser doesn’t work"
+msgstr "Vad du kan göra om Tor webbläsare inte fungerar"
+
+#: troubleshooting.page:12
+msgid ""
+"You should be able to start browsing the web using Tor Browser shortly after"
+" running the program, and clicking the “Connect” button if you are using it "
+"for the first time."
+msgstr ""
+"Du bör kunna börja surfa på webben med Tor Browser snart efter att du kör "
+"programmet och klickar på \"Anslut\"-knappen om du använder den för första "
+"gången."
+
+#: troubleshooting.page:21
+msgid "Quick fixes"
+msgstr "Snabba åtgärder"
+
+#: troubleshooting.page:22
+msgid ""
+"If Tor Browser doesn’t connect, there may be a simple solution. Try each of "
+"the following:"
+msgstr ""
+"Om Tor webbläsare inte ansluter, kan det finnas en enkel lösning. Prova "
+"följande alternativ:"
+
+#: troubleshooting.page:29
+msgid ""
+"Your computer’s system clock must be set correctly, or Tor will not be able "
+"to connect."
+msgstr ""
+"Datorns klocka måste vara korrekt inställd, annars kan Tor inte ansluta."
+
+#: troubleshooting.page:35
+msgid ""
+"Make sure another Tor Browser is not already running. If you’re not sure if "
+"Tor Browser is running, restart your computer."
+msgstr ""
+"Se till att en annan Tor Browser inte redan körs. Om du inte är säker på om "
+"Tor Browser körs startar du om datorn."
+
+#: troubleshooting.page:41
+msgid ""
+"Make sure that any antivirus program you have installed is not preventing "
+"Tor from running. You may need to consult the documentation for your "
+"antivirus software if you do not know how to do this."
+msgstr ""
+"Se till att alla antivirusprogram du har installerat inte hindrar Tor från "
+"att köras. Du kan behöva konsultera dokumentationen för ditt "
+"antivirusprogram om du inte vet hur du gör det här."
+
+#: troubleshooting.page:49
+msgid "Temporarily disable your firewall."
+msgstr "Stäng av din brandvägg tillfälligt"
+
+#: troubleshooting.page:54
+msgid ""
+"Delete Tor Browser and install it again. If updating, do not just overwrite "
+"your previous Tor Browser files; ensure they are fully deleted beforehand."
+msgstr ""
+"Ta bort Tor Browser och installera den igen. Om du uppdaterar, skriv inte "
+"bara över dina tidigare Tor Browser-filer; se till att de helt raderas i "
+"förväg."
+
+#: troubleshooting.page:64
+msgid "Is your connection censored?"
+msgstr "Är din anslutning censurerad?"
+
+#: troubleshooting.page:65
+msgid ""
+"If you still can’t connect, your Internet Service Provider might be "
+"censoring connections to the Tor network. Read the <link "
+"xref=\"circumvention\">Circumvention</link> section for possible solutions."
+msgstr ""
+"Om du fortfarande inte kan ansluta kan din Internetleverantör censurera "
+"anslutningar till Tor-nätverket. Läs avsnittet <link "
+"xref=\"circumvention\">Kringgående</link> för möjliga lösningar."
+
+#: troubleshooting.page:74
+msgid "Known issues"
+msgstr "Kända problem"
+
+#: troubleshooting.page:75
+msgid ""
+"Tor Browser is under constant development, and some issues are known about "
+"but not yet fixed. Please check the <link xref=\"known-issues\">Known "
+"Issues</link> page to see if the problem you are experiencing is already "
+"listed there."
+msgstr ""
+"Tor Browser är under konstant utveckling, och vissa problem är kända men "
+"ännu inte åtgärdaded. Kontrollera sidan med <link xref=\"known-"
+"issues\">kända problem</link> för att se om problemet du upplever är redan "
+"listat där."
+
+#: uninstalling.page:6
+msgid "How to remove Tor Browser from your system"
+msgstr "Hur du raderar Tor webbläsare från ditt system"
+
+#: uninstalling.page:10
+msgid "Uninstalling"
+msgstr "Avinstallera"
+
+#: uninstalling.page:12
+msgid ""
+"Tor Browser does not affect any of the existing software or settings on your"
+" computer. Uninstalling Tor Browser will not affect your system’s software "
+"or settings."
+msgstr ""
+"Tor Browser påverkar inte någon befintlig programvara eller inställningar på"
+" din dator. Avinstallation av Tor Browser påverkar inte ditt systems program"
+" eller inställningar."
+
+#: uninstalling.page:18
+msgid "Removing Tor Browser from your system is simple:"
+msgstr "Att radera Tor från ditt system är enkelt:"
+
+#: uninstalling.page:24
+msgid ""
+"Locate your Tor Browser folder. The default location on Windows is the "
+"Desktop; on Mac OS X it is the Applications folder. On Linux, there is no "
+"default location, however the folder will be named \"tor-browser_en-US\" if "
+"you are running the English Tor Browser."
+msgstr ""
+"Leta reda på din Tor Browser-mapp. Standardplatsen i Windows är skrivbordet;"
+" På Mac OS X är det mappen Program. På Linux finns ingen standardplats, men "
+"mappen kommer att benämnas \"tor-browser_en-US\" om du kör den engelska Tor "
+"Browser."
+
+#: uninstalling.page:32
+msgid "Delete the Tor Browser folder."
+msgstr "Radera Tor mappen"
+
+#: uninstalling.page:35
+msgid "Empty your Trash"
+msgstr "Töm din Skräpkorg"
+
+#: uninstalling.page:39
+msgid ""
+"Note that your operating system’s standard “Uninstall” utility is not used."
+msgstr ""
+"Observera att operativsystemets standard \"Avinstallera\"-verktyg inte "
+"används."
+
+#: updating.page:6
+msgid "How to update Tor Browser"
+msgstr "Hur du uppdaterar Tor Webläsare"
+
+#: updating.page:10
+msgid "Updating"
+msgstr "Uppdaterar"
+
+#: updating.page:12
+msgid ""
+"Tor Browser must be kept updated at all times. If you continue to use an "
+"outdated version of the software, you may be vulnerable to serious security "
+"flaws that compromise your privacy and anonymity."
+msgstr ""
+"Tor Browser måste hållas uppdaterad hela tiden. Om du fortsätter att använda"
+" en föråldrad version av programvaran, kan du vara utsatt för allvarliga "
+"säkerhetsbrister som äventyrar din integritet och anonymitet."
+
+#: updating.page:18
+msgid ""
+"Tor Browser will prompt you to update the software once a new version has "
+"been released: the Torbutton icon will display a yellow triangle, and you "
+"may see a written update indicator when Tor Browser opens. You can update "
+"either automatically or manually."
+msgstr ""
+"Tor Browser uppmanar dig att uppdatera programvaran när en ny version har "
+"släppts: Torbutton-ikonen kommer att visa en gul triangel och du kan se en "
+"skriftlig uppdateringsindikator när Tor Browser öppnas. Du kan uppdatera "
+"antingen automatiskt eller manuellt."
+
+#: updating.page:26
+msgid "Updating Tor Browser automatically"
+msgstr "Uppdatera Tor webbläsare automatiskt"
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: updating.page:30
+msgctxt "_"
+msgid ""
+"external ref='media/updating/update1.png' "
+"md5='9ff01eb653d92124746fc31efde2bf07'"
+msgstr ""
+"external ref='media/updating/update1.png' "
+"md5='9ff01eb653d92124746fc31efde2bf07'"
+
+#: updating.page:32
+msgid ""
+"When you are prompted to update Tor Browser, click on the Torbutton icon, "
+"then select “Check for Tor Browser Update”."
+msgstr ""
+"När du uppmanas att uppdatera Tor Browser, klicka på Torbutton-ikonen och "
+"välj sedan \"Kontrollera efter uppdatering av Tor Browser\"."
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: updating.page:39
+msgctxt "_"
+msgid ""
+"external ref='media/updating/update3.png' "
+"md5='4bd08622b0cacf20b13f75c432176ed3'"
+msgstr ""
+"external ref='media/updating/update3.png' "
+"md5='4bd08622b0cacf20b13f75c432176ed3'"
+
+#: updating.page:41
+msgid ""
+"When Tor Browser has finished checking for updates, click on the “Update” "
+"button."
+msgstr ""
+"När Tor webbläsare har granskat om tillgängliga uppdateringar finns, klicka "
+"på knappen \"Uppdatera\"."
+
+#. This is a reference to an external file such as an image or video. When
+#. the file changes, the md5 hash will change to let you know you need to
+#. update your localized copy. The msgstr is not used at all. Set it to
+#. whatever you like once you have updated your copy of the file.
+#: updating.page:48
+msgctxt "_"
+msgid ""
+"external ref='media/updating/update4.png' "
+"md5='1d795e7b695738531db9d4b2b0fb5313'"
+msgstr ""
+"external ref='media/updating/update4.png' "
+"md5='1d795e7b695738531db9d4b2b0fb5313'"
+
+#: updating.page:50
+msgid ""
+"Wait for the update to download and install, then restart Tor Browser. You "
+"will now be running the latest version."
+msgstr ""
+"Vänta på att uppdateringen ska hämtas och installeras, starta sedan om Tor "
+"Browser. Du kommer nu att köra den senaste versionen."
+
+#: updating.page:58
+msgid "Updating Tor Browser manually"
+msgstr "Uppdatera Tor webbläsaren manuellt"
+
+#: updating.page:61
+msgid ""
+"When you are prompted to update Tor Browser, finish the browsing session and"
+" close the program."
+msgstr ""
+"När du uppmanas att uppdatera Tor Browser, avsluta webbläsningssessionen och"
+" stäng programmet."
+
+#: updating.page:67
+msgid ""
+"Remove Tor Browser from your system by deleting the folder that contains it "
+"(see the <link xref=\"uninstalling\">Uninstalling</link> section for more "
+"information)."
+msgstr ""
+"Ta bort Tor Browser från ditt system genom att radera mappen som innehåller "
+"den (se avsnittet <link xref=\"uninstalling\">Avinstallera</link> för mer "
+"information)."
+
+#: updating.page:74
+msgid ""
+"Visit <link href=\"https://www.torproject.org/projects/torbrowser.html.en\">"
+" https://www.torproject.org/projects/torbrowser.html.en</link> and download "
+"a copy of the latest Tor Browser release, then install it as before."
+msgstr ""
+"Besök <link href=\"https://www.torproject.org/projects/torbrowser.html.en\">"
+" https://www.torproject.org/projects/torbrowser.html.en</link> och ladda ner"
+" en kopia av den senaste Tor Browser utgåvan, installera den sedan som "
+"förut."
1
0