Merge branch 'maint-0.2.4' into release-0.2.4

This commit is contained in:
Roger Dingledine 2014-02-25 15:05:06 -05:00
commit 4ef52cc167
19 changed files with 17361 additions and 10370 deletions

7
changes/10777_netunreach Normal file
View File

@ -0,0 +1,7 @@
- Minor bugfixes:
- Treat ENETUNREACH, EACCES, and EPERM at an exit node as a
NOROUTE error, not an INTERNAL error, since they can apparently
happen when trying to connect to the wrong sort of
netblocks. Fixes a part of bug 10777; bugfix on 0.1.0.1-rc.

View File

@ -0,0 +1,4 @@
o Major bugfixes:
- Do not treat END_STREAM_REASON_INTERNAL as indicating a definite
circuit failure, since it could also indicate an ENETUNREACH
error. Fixes part of bug 10777; bugfix on 0.2.4.8-alpha.

5
changes/bug10904 Normal file
View File

@ -0,0 +1,5 @@
o Minor bugfixes (compilation):
- Build without warnings under clang 3.4. (We have some macros that
define static functions only some of which will get used later in
the module. Starting with clang 3.4, these give a warning unless the
unused attribute is set on them.)

6
changes/bug10929 Normal file
View File

@ -0,0 +1,6 @@
- Minor bugfixes:
- Fix build warnings about missing "a2x" comment when building the
manpages from scratch on OpenBSD; OpenBSD calls it "a2x.py".
Fixes bug 10929; bugfix on tor-0.2.2.9-alpha. Patch from
Dana Koch.

3
changes/feature9777 Normal file
View File

@ -0,0 +1,3 @@
o Minor features:
- Avoid using circuit paths if no node in the path supports the ntor
circuit extension handshake. Implements ticket 9777.

View File

@ -0,0 +1,3 @@
o Minor features:
- Update to the February 7 2014 Maxmind GeoLite2 Country database.

View File

@ -0,0 +1,3 @@
o Minor features:
- Fix our version of the February 7 2014 Maxmind GeoLite2 Country database.

View File

@ -0,0 +1,3 @@
o Minor features:
- Update geoip6 to the February 7 2014 Maxmind GeoLite2 Country
database.

View File

@ -167,7 +167,7 @@ AC_CHECK_PROG([SED],[sed],[sed],[/bin/false])
dnl check for asciidoc and a2x
AC_PATH_PROG([ASCIIDOC], [asciidoc], none)
AC_PATH_PROG([A2X], [a2x], none)
AC_PATH_PROGS([A2X], [a2x a2x.py], none)
AM_CONDITIONAL(USE_ASCIIDOC, test x$asciidoc = xtrue)

View File

@ -162,6 +162,7 @@ extern INLINE double U64_TO_DBL(uint64_t x) {
*
* #define ATTR_NONNULL(x) __attribute__((nonnull x)) */
#define ATTR_NONNULL(x)
#define ATTR_UNUSED __attribute__ ((unused))
/** Macro: Evaluates to <b>exp</b> and hints the compiler that the value
* of <b>exp</b> will probably be true.
@ -185,6 +186,7 @@ extern INLINE double U64_TO_DBL(uint64_t x) {
#define ATTR_MALLOC
#define ATTR_NORETURN
#define ATTR_NONNULL(x)
#define ATTR_UNUSED
#define PREDICT_LIKELY(exp) (exp)
#define PREDICT_UNLIKELY(exp) (exp)
#endif

View File

@ -471,64 +471,74 @@ void* strmap_remove_lc(strmap_t *map, const char *key);
#define DECLARE_TYPED_DIGESTMAP_FNS(prefix, maptype, valtype) \
typedef struct maptype maptype; \
typedef struct prefix##iter_t prefix##iter_t; \
static INLINE maptype* prefix##new(void) \
ATTR_UNUSED static INLINE maptype* \
prefix##new(void) \
{ \
return (maptype*)digestmap_new(); \
} \
static INLINE digestmap_t* prefix##to_digestmap(maptype *map) \
ATTR_UNUSED static INLINE digestmap_t* \
prefix##to_digestmap(maptype *map) \
{ \
return (digestmap_t*)map; \
} \
static INLINE valtype* prefix##get(maptype *map, const char *key) \
ATTR_UNUSED static INLINE valtype* \
prefix##get(maptype *map, const char *key) \
{ \
return (valtype*)digestmap_get((digestmap_t*)map, key); \
} \
static INLINE valtype* prefix##set(maptype *map, const char *key, \
valtype *val) \
ATTR_UNUSED static INLINE valtype* \
prefix##set(maptype *map, const char *key, valtype *val) \
{ \
return (valtype*)digestmap_set((digestmap_t*)map, key, val); \
} \
static INLINE valtype* prefix##remove(maptype *map, const char *key) \
ATTR_UNUSED static INLINE valtype* \
prefix##remove(maptype *map, const char *key) \
{ \
return (valtype*)digestmap_remove((digestmap_t*)map, key); \
} \
static INLINE void prefix##free(maptype *map, void (*free_val)(void*)) \
ATTR_UNUSED static INLINE void \
prefix##free(maptype *map, void (*free_val)(void*)) \
{ \
digestmap_free((digestmap_t*)map, free_val); \
} \
static INLINE int prefix##isempty(maptype *map) \
ATTR_UNUSED static INLINE int \
prefix##isempty(maptype *map) \
{ \
return digestmap_isempty((digestmap_t*)map); \
} \
static INLINE int prefix##size(maptype *map) \
ATTR_UNUSED static INLINE int \
prefix##size(maptype *map) \
{ \
return digestmap_size((digestmap_t*)map); \
} \
static INLINE prefix##iter_t *prefix##iter_init(maptype *map) \
ATTR_UNUSED static INLINE \
prefix##iter_t *prefix##iter_init(maptype *map) \
{ \
return (prefix##iter_t*) digestmap_iter_init((digestmap_t*)map); \
} \
static INLINE prefix##iter_t *prefix##iter_next(maptype *map, \
prefix##iter_t *iter) \
ATTR_UNUSED static INLINE \
prefix##iter_t *prefix##iter_next(maptype *map, prefix##iter_t *iter) \
{ \
return (prefix##iter_t*) digestmap_iter_next( \
(digestmap_t*)map, (digestmap_iter_t*)iter); \
} \
static INLINE prefix##iter_t *prefix##iter_next_rmv(maptype *map, \
prefix##iter_t *iter) \
ATTR_UNUSED static INLINE prefix##iter_t* \
prefix##iter_next_rmv(maptype *map, prefix##iter_t *iter) \
{ \
return (prefix##iter_t*) digestmap_iter_next_rmv( \
(digestmap_t*)map, (digestmap_iter_t*)iter); \
} \
static INLINE void prefix##iter_get(prefix##iter_t *iter, \
const char **keyp, \
valtype **valp) \
ATTR_UNUSED static INLINE void \
prefix##iter_get(prefix##iter_t *iter, \
const char **keyp, \
valtype **valp) \
{ \
void *v; \
digestmap_iter_get((digestmap_iter_t*) iter, keyp, &v); \
*valp = v; \
} \
static INLINE int prefix##iter_done(prefix##iter_t *iter) \
ATTR_UNUSED static INLINE int \
prefix##iter_done(prefix##iter_t *iter) \
{ \
return digestmap_iter_done((digestmap_iter_t*)iter); \
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -168,7 +168,7 @@ ht_string_hash(const char *s)
} \
/* Insert the element 'elm' into the table 'head'. Do not call this \
* function if the table might already contain a matching element. */ \
static INLINE void \
ATTR_UNUSED static INLINE void \
name##_HT_INSERT(struct name *head, struct type *elm) \
{ \
struct type **p; \
@ -183,7 +183,7 @@ ht_string_hash(const char *s)
/* Insert the element 'elm' into the table 'head'. If there already \
* a matching element in the table, replace that element and return \
* it. */ \
static INLINE struct type * \
ATTR_UNUSED static INLINE struct type * \
name##_HT_REPLACE(struct name *head, struct type *elm) \
{ \
struct type **p, *r; \
@ -204,7 +204,7 @@ ht_string_hash(const char *s)
} \
/* Remove any element matching 'elm' from the table 'head'. If such \
* an element is found, return it; otherwise return NULL. */ \
static INLINE struct type * \
ATTR_UNUSED static INLINE struct type * \
name##_HT_REMOVE(struct name *head, struct type *elm) \
{ \
struct type **p, *r; \
@ -222,11 +222,11 @@ ht_string_hash(const char *s)
* using 'data' as its second argument. If the function returns \
* nonzero, remove the most recently examined element before invoking \
* the function again. */ \
static INLINE void \
ATTR_UNUSED static INLINE void \
name##_HT_FOREACH_FN(struct name *head, \
int (*fn)(struct type *, void *), \
void *data) \
{ \
{ \
unsigned idx; \
struct type **p, **nextp, *next; \
if (!head->hth_table) \
@ -248,7 +248,7 @@ ht_string_hash(const char *s)
/* Return a pointer to the first element in the table 'head', under \
* an arbitrary order. This order is stable under remove operations, \
* but not under others. If the table is empty, return NULL. */ \
static INLINE struct type ** \
ATTR_UNUSED static INLINE struct type ** \
name##_HT_START(struct name *head) \
{ \
unsigned b = 0; \
@ -264,7 +264,7 @@ ht_string_hash(const char *s)
* NULL. If 'elm' is to be removed from the table, you must call \
* this function for the next value before you remove it. \
*/ \
static INLINE struct type ** \
ATTR_UNUSED static INLINE struct type ** \
name##_HT_NEXT(struct name *head, struct type **elm) \
{ \
if ((*elm)->field.hte_next) { \
@ -280,7 +280,7 @@ ht_string_hash(const char *s)
return NULL; \
} \
} \
static INLINE struct type ** \
ATTR_UNUSED static INLINE struct type ** \
name##_HT_NEXT_RMV(struct name *head, struct type **elm) \
{ \
unsigned h = HT_ELT_HASH_(*elm, field, hashfn); \

View File

@ -72,6 +72,9 @@ static void pathbias_count_use_failed(origin_circuit_t *circ);
static void pathbias_measure_use_rate(entry_guard_t *guard);
static void pathbias_measure_close_rate(entry_guard_t *guard);
static void pathbias_scale_use_rates(entry_guard_t *guard);
#ifdef CURVE25519_ENABLED
static int circuits_can_use_ntor(void);
#endif
/** This function tries to get a channel to the specified endpoint,
* and then calls command_setup_channel() to give it the right
@ -284,21 +287,74 @@ circuit_rep_hist_note_result(origin_circuit_t *circ)
} while (hop!=circ->cpath);
}
#ifdef CURVE25519_ENABLED
/** Return 1 iff at least one node in circ's cpath supports ntor. */
static int
circuit_cpath_supports_ntor(const origin_circuit_t *circ)
{
crypt_path_t *head = circ->cpath, *cpath = circ->cpath;
cpath = head;
do {
if (cpath->extend_info &&
!tor_mem_is_zero(
(const char*)cpath->extend_info->curve25519_onion_key.public_key,
CURVE25519_PUBKEY_LEN))
return 1;
cpath = cpath->next;
} while (cpath != head);
return 0;
}
#else
#define circuit_cpath_supports_ntor(circ) 0
#endif
/** Pick all the entries in our cpath. Stop and return 0 when we're
* happy, or return -1 if an error occurs. */
static int
onion_populate_cpath(origin_circuit_t *circ)
{
int r;
again:
r = onion_extend_cpath(circ);
if (r < 0) {
log_info(LD_CIRC,"Generating cpath hop failed.");
return -1;
int n_tries = 0;
#ifdef CURVE25519_ENABLED
const int using_ntor = circuits_can_use_ntor();
#else
const int using_ntor = 0;
#endif
#define MAX_POPULATE_ATTEMPTS 32
while (1) {
int r = onion_extend_cpath(circ);
if (r < 0) {
log_info(LD_CIRC,"Generating cpath hop failed.");
return -1;
}
if (r == 1) {
/* This circuit doesn't need/shouldn't be forced to have an ntor hop */
if (circ->build_state->desired_path_len <= 1 || ! using_ntor)
return 0;
/* This circuit has an ntor hop. great! */
if (circuit_cpath_supports_ntor(circ))
return 0;
/* No node in the circuit supports ntor. Have we already tried too many
* times? */
if (++n_tries >= MAX_POPULATE_ATTEMPTS)
break;
/* Clear the path and retry */
circuit_clear_cpath(circ);
}
}
if (r == 0)
goto again;
return 0; /* if r == 1 */
log_warn(LD_CIRC, "I tried for %d times, but I couldn't build a %d-hop "
"circuit with at least one node that supports ntor.",
MAX_POPULATE_ATTEMPTS,
circ->build_state->desired_path_len);
return -1;
}
/** Create and return a new origin circuit. Initialize its purpose and
@ -3475,6 +3531,9 @@ onion_next_hop_in_cpath(crypt_path_t *cpath)
/** Choose a suitable next hop in the cpath <b>head_ptr</b>,
* based on <b>state</b>. Append the hop info to head_ptr.
*
* Return 1 if the path is complete, 0 if we successfully added a hop,
* and -1 on error.
*/
static int
onion_extend_cpath(origin_circuit_t *circ)

View File

@ -709,7 +709,7 @@ circuit_free_cpath(crypt_path_t *cpath)
if (!cpath)
return;
/* it's a doubly linked list, so we have to notice when we've
/* 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;
@ -720,6 +720,14 @@ circuit_free_cpath(crypt_path_t *cpath)
circuit_free_cpath_node(cpath);
}
/** Remove all the items in the cpath on <b>circ</b>.*/
void
circuit_clear_cpath(origin_circuit_t *circ)
{
circuit_free_cpath(circ->cpath);
circ->cpath = NULL;
}
/** Release all storage held by circuits. */
void
circuit_free_all(void)

View File

@ -50,6 +50,7 @@ void circuit_mark_all_dirty_circs_as_unusable(void);
void circuit_mark_for_close_(circuit_t *circ, int reason,
int line, const char *file);
int circuit_get_cpath_len(origin_circuit_t *circ);
void circuit_clear_cpath(origin_circuit_t *circ);
crypt_path_t *circuit_get_cpath_hop(origin_circuit_t *circ, int hopnum);
void circuit_get_all_pending_on_channel(smartlist_t *out,
channel_t *chan);

View File

@ -174,11 +174,12 @@ errno_to_stream_end_reason(int e)
S_CASE(ENOTSOCK):
S_CASE(EPROTONOSUPPORT):
S_CASE(EAFNOSUPPORT):
E_CASE(EACCES):
S_CASE(ENOTCONN):
S_CASE(ENETUNREACH):
return END_STREAM_REASON_INTERNAL;
S_CASE(ENETUNREACH):
S_CASE(EHOSTUNREACH):
E_CASE(EACCES):
case EPERM:
return END_STREAM_REASON_NOROUTE;
S_CASE(ECONNREFUSED):
return END_STREAM_REASON_CONNECTREFUSED;

View File

@ -731,13 +731,15 @@ connection_ap_process_end_not_open(
if (rh->length > 0) {
if (reason == END_STREAM_REASON_TORPROTOCOL ||
reason == END_STREAM_REASON_INTERNAL ||
reason == END_STREAM_REASON_DESTROY) {
/* All three of these reasons could mean a failed tag
/* 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.