diff --git a/src/or/circuituse.c b/src/or/circuituse.c index 672c858a7a..2b34f7e6ee 100644 --- a/src/or/circuituse.c +++ b/src/or/circuituse.c @@ -212,6 +212,34 @@ circuit_get_best(edge_connection_t *conn, int must_be_open, uint8_t purpose, return best ? TO_ORIGIN_CIRCUIT(best) : NULL; } +/** Check whether, according to the policies in options, the + * circuit circ makes sense. */ +/* XXXX021 currently only checks Exclude{Exit}Nodes. */ +int +circuit_conforms_to_options(const origin_circuit_t *circ, + const or_options_t *options) +{ + const crypt_path_t *cpath, *cpath_next = NULL; + + for (cpath = circ->cpath; cpath && cpath_next != circ->cpath; + cpath = cpath_next) { + cpath_next = cpath->next; + + if (routerset_contains_extendinfo(options->ExcludeNodes, + cpath->extend_info)) + return 0; + + if (cpath->next == circ->cpath) { + /* This is apparently the exit node. */ + + if (routerset_contains_extendinfo(options->ExcludeExitNodes, + cpath->extend_info)) + return 0; + } + } + return 1; +} + /** Close all circuits that start at us, aren't open, and were born * at least CircuitBuildTimeout seconds ago. */ diff --git a/src/or/or.h b/src/or/or.h index 5ad3d59b21..09abeb50e9 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -2701,6 +2701,8 @@ void circuit_expire_building(time_t now); void circuit_remove_handled_ports(smartlist_t *needed_ports); int circuit_stream_is_being_handled(edge_connection_t *conn, uint16_t port, int min); +int circuit_conforms_to_options(const origin_circuit_t *circ, + const or_options_t *options); void circuit_build_needed_circs(time_t now); void circuit_detach_stream(circuit_t *circ, edge_connection_t *conn); @@ -4257,6 +4259,7 @@ void routerset_union(routerset_t *target, const routerset_t *source); int routerset_contains_router(const routerset_t *set, routerinfo_t *ri); int routerset_contains_routerstatus(const routerset_t *set, routerstatus_t *rs); +int routerset_contains_extendinfo(const routerset_t *set, extend_info_t *ei); void routerset_get_all_routers(smartlist_t *out, const routerset_t *routerset, int running_only); void routerset_subtract_routers(smartlist_t *out, diff --git a/src/or/routerlist.c b/src/or/routerlist.c index 32595b8080..66ca2bf479 100644 --- a/src/or/routerlist.c +++ b/src/or/routerlist.c @@ -4782,27 +4782,42 @@ routerset_union(routerset_t *target, const routerset_t *source) /** Helper. Return true iff set contains a router based on the other * provided fields. */ static int -routerset_contains(const routerset_t *set, uint32_t addr, uint16_t orport, +routerset_contains(const routerset_t *set, const tor_addr_t *addr, + uint16_t orport, const char *nickname, const char *id_digest, int is_named) { if (!set || !set->list) return 0; (void) is_named; /* not supported */ - if (strmap_get_lc(set->names, nickname)) + if (nickname && strmap_get_lc(set->names, nickname)) return 1; - if (digestmap_get(set->digests, id_digest)) + if (id_digest && digestmap_get(set->digests, id_digest)) return 1; - if (compare_addr_to_addr_policy(addr, orport, set->policies) + if (addr && compare_tor_addr_to_addr_policy(addr, orport, set->policies) == ADDR_POLICY_REJECTED) return 1; return 0; } +/** Return true iff we can tell that ei is a member of set. */ +int +routerset_contains_extendinfo(const routerset_t *set, extend_info_t *ei) +{ + return routerset_contains(set, + &ei->addr, + ei->port, + ei->nickname, + ei->identity_digest, + -1); +} + /** Return true iff ri is in set. */ int routerset_contains_router(const routerset_t *set, routerinfo_t *ri) { + tor_addr_t addr; + tor_addr_from_ipv4h(&addr, ri->addr); return routerset_contains(set, - ri->addr, + &addr, ri->or_port, ri->nickname, ri->cache_info.identity_digest, @@ -4813,8 +4828,10 @@ routerset_contains_router(const routerset_t *set, routerinfo_t *ri) int routerset_contains_routerstatus(const routerset_t *set, routerstatus_t *rs) { + tor_addr_t addr; + tor_addr_from_ipv4h(&addr, rs->addr); return routerset_contains(set, - rs->addr, + &addr, rs->or_port, rs->nickname, rs->identity_digest,