From 05053561b92fc457f72c40cae5225a7b3c524d04 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Sun, 14 Oct 2007 08:48:56 +0000 Subject: [PATCH] r15763@catbus: nickm | 2007-10-14 04:40:00 -0400 Backport r11886 and r11887: Fix for the reported case of bug 438: check families as well as identities in circuit_find_to_cannibalize(). Code audit STILL pending. ;) svn:r11928 --- ChangeLog | 3 +++ doc/TODO.012 | 2 +- src/or/circuitlist.c | 6 ++++++ src/or/or.h | 1 + src/or/routerlist.c | 43 ++++++++++++++++++++++++++++++++++++++++++- 5 files changed, 53 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 494f56bdb6..0b3c7196ec 100644 --- a/ChangeLog +++ b/ChangeLog @@ -13,6 +13,9 @@ Changes in version 0.1.2.18 - 2007-??-?? happened inside connection_flushed_some(), do not call connection_finished_flushing(). Should fix bug 451. Bugfix on 0.1.2.7-alpha. + - When looking for a circuit to cannibalize, consider family as well + as identity. Fixes bug 438. Bugfix on 0.1.0.x (which introduced + circuit cannibalization). o Minor bugfixes: - Don't try to access (or alter) the state file when running diff --git a/doc/TODO.012 b/doc/TODO.012 index 9a03d4ba52..01fe212b10 100644 --- a/doc/TODO.012 +++ b/doc/TODO.012 @@ -5,7 +5,7 @@ Backport items for 0.1.2: o r11166: Don't believe future dates from the state file. o r11828+: Detect bad sa_family from accept(). o r11882: Avoid crash-bug 451. -N - r11886: Consider family as well as identity when cannibalizing circuits. + o r11886: Consider family as well as identity when cannibalizing circuits. Backport for 0.1.2.x once better tested: diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c index fedd4169b8..1d5e77171d 100644 --- a/src/or/circuitlist.c +++ b/src/or/circuitlist.c @@ -779,10 +779,16 @@ circuit_find_to_cannibalize(uint8_t purpose, extend_info_t *info, if (info) { /* need to make sure we don't duplicate hops */ crypt_path_t *hop = circ->cpath; + routerinfo_t *ri1 = router_get_by_digest(info->identity_digest); do { + routerinfo_t *ri2; if (!memcmp(hop->extend_info->identity_digest, info->identity_digest, DIGEST_LEN)) goto next; + if (ri1 && + (ri2 = router_get_by_digest(hop->extend_info->identity_digest)) + && routers_in_same_family(ri1, ri2)) + goto next; hop=hop->next; } while (hop!=circ->cpath); } diff --git a/src/or/or.h b/src/or/or.h index e3334996f9..50e73c0263 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -2891,6 +2891,7 @@ routerstatus_t *router_pick_trusteddirserver(authority_type_t type, trusted_dir_server_t *router_get_trusteddirserver_by_digest( const char *digest); void routerlist_add_family(smartlist_t *sl, routerinfo_t *router); +int routers_in_same_family(routerinfo_t *r1, routerinfo_t *r2); void add_nickname_list_to_smartlist(smartlist_t *sl, const char *list, int must_be_running); int router_nickname_is_in_list(routerinfo_t *router, const char *list); diff --git a/src/or/routerlist.c b/src/or/routerlist.c index ac1c4e755e..bf8ed69bf5 100644 --- a/src/or/routerlist.c +++ b/src/or/routerlist.c @@ -765,6 +765,47 @@ routerlist_add_family(smartlist_t *sl, routerinfo_t *router) } } +/** Return true iff r is named by some nickname in lst. */ +static INLINE int +router_in_nickname_smartlist(smartlist_t *lst, routerinfo_t *r) +{ + if (!lst) return 0; + SMARTLIST_FOREACH(lst, const char *, name, + if (router_nickname_matches(r, name)) + return 1;); + return 0; +} + +/** Return true iff router1 and router2 have the same /16 network. */ +static INLINE int +routers_in_same_network_family(routerinfo_t *r1, routerinfo_t *r2) +{ + return (r1->addr & 0xffff0000) == (r2->addr & 0xffff0000); +} + +/** Return true iff r1 and r2 are in the same family, but not the same + * router. */ +int +routers_in_same_family(routerinfo_t *r1, routerinfo_t *r2) +{ + or_options_t *options = get_options(); + config_line_t *cl; + + if (options->EnforceDistinctSubnets && routers_in_same_network_family(r1,r2)) + return 1; + + if (router_in_nickname_smartlist(r1->declared_family, r2) && + router_in_nickname_smartlist(r2->declared_family, r1)) + return 1; + + for (cl = options->NodeFamilies; cl; cl = cl->next) { + if (router_nickname_is_in_list(r1, cl->value) && + router_nickname_is_in_list(r2, cl->value)) + return 1; + } + return 0; +} + /** Given a (possibly NULL) comma-and-whitespace separated list of nicknames, * see which nicknames in list name routers in our routerlist, and add * the routerinfos for those routers to sl. If must_be_running, @@ -1059,7 +1100,7 @@ smartlist_choose_by_bandwidth(smartlist_t *sl, int for_exit, int for_guard, } /* Figure out how to weight exits and guards. */ - { + { double all_bw = U64_TO_DBL(total_exit_bw+total_nonexit_bw); double exit_bw = U64_TO_DBL(total_exit_bw); double guard_bw = U64_TO_DBL(total_guard_bw); -- 2.11.4.GIT