diff options
Diffstat (limited to 'src/or/routerset.c')
-rw-r--r-- | src/or/routerset.c | 82 |
1 files changed, 40 insertions, 42 deletions
diff --git a/src/or/routerset.c b/src/or/routerset.c index 7aee90d6db..f260914f4b 100644 --- a/src/or/routerset.c +++ b/src/or/routerset.c @@ -1,9 +1,18 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2013, The Tor Project, Inc. */ + * Copyright (c) 2007-2016, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * \file routerset.c + * + * \brief Functions and structures to handle set-type selection of routers + * by name, ID, address, etc. + */ + +#define ROUTERSET_PRIVATE + #include "or.h" #include "geoip.h" #include "nodelist.h" @@ -12,39 +21,6 @@ #include "routerparse.h" #include "routerset.h" -/** A routerset specifies constraints on a set of possible routerinfos, based - * on their names, identities, or addresses. It is optimized for determining - * whether a router is a member or not, in O(1+P) time, where P is the number - * of address policy constraints. */ -struct routerset_t { - /** A list of strings for the elements of the policy. Each string is either - * a nickname, a hexadecimal identity fingerprint, or an address policy. A - * router belongs to the set if its nickname OR its identity OR its address - * matches an entry here. */ - smartlist_t *list; - /** A map from lowercase nicknames of routers in the set to (void*)1 */ - strmap_t *names; - /** A map from identity digests routers in the set to (void*)1 */ - digestmap_t *digests; - /** An address policy for routers in the set. For implementation reasons, - * a router belongs to the set if it is _rejected_ by this policy. */ - smartlist_t *policies; - - /** A human-readable description of what this routerset is for. Used in - * log messages. */ - char *description; - - /** A list of the country codes in this set. */ - smartlist_t *country_names; - /** Total number of countries we knew about when we built <b>countries</b>.*/ - int n_countries; - /** Bit array mapping the return value of geoip_get_country() to 1 iff the - * country is a member of this routerset. Note that we MUST call - * routerset_refresh_countries() whenever the geoip country list is - * reloaded. */ - bitarray_t *countries; -}; - /** Return a new empty routerset. */ routerset_t * routerset_new(void) @@ -60,7 +36,7 @@ routerset_new(void) /** If <b>c</b> is a country code in the form {cc}, return a newly allocated * string holding the "cc" part. Else, return NULL. */ -static char * +STATIC char * routerset_get_countryname(const char *c) { char *country; @@ -116,10 +92,13 @@ routerset_parse(routerset_t *target, const char *s, const char *description) int added_countries = 0; char *countryname; smartlist_t *list = smartlist_new(); + int malformed_list; smartlist_split_string(list, s, ",", SPLIT_SKIP_SPACE | SPLIT_IGNORE_BLANK, 0); SMARTLIST_FOREACH_BEGIN(list, char *, nick) { addr_policy_t *p; + /* if it doesn't pass our validation, assume it's malformed */ + malformed_list = 1; if (is_legal_hexdigest(nick)) { char d[DIGEST_LEN]; if (*nick == '$') @@ -135,17 +114,25 @@ routerset_parse(routerset_t *target, const char *s, const char *description) description); smartlist_add(target->country_names, countryname); added_countries = 1; - } else if ((strchr(nick,'.') || strchr(nick, '*')) && - (p = router_parse_addr_policy_item_from_string( - nick, ADDR_POLICY_REJECT))) { + } else if ((strchr(nick,'.') || strchr(nick, ':') || strchr(nick, '*')) + && (p = router_parse_addr_policy_item_from_string( + nick, ADDR_POLICY_REJECT, + &malformed_list))) { + /* IPv4 addresses contain '.', IPv6 addresses contain ':', + * and wildcard addresses contain '*'. */ log_debug(LD_CONFIG, "Adding address %s to %s", nick, description); smartlist_add(target->policies, p); - } else { - log_warn(LD_CONFIG, "Entry '%s' in %s is malformed.", nick, - description); + } else if (malformed_list) { + log_warn(LD_CONFIG, "Entry '%s' in %s is malformed. Discarding entire" + " list.", nick, description); r = -1; tor_free(nick); SMARTLIST_DEL_CURRENT(list, nick); + } else { + log_notice(LD_CONFIG, "Entry '%s' in %s is ignored. Using the" + " remainder of the list.", nick, description); + tor_free(nick); + SMARTLIST_DEL_CURRENT(list, nick); } } SMARTLIST_FOREACH_END(nick); policy_expand_unspec(&target->policies); @@ -193,6 +180,17 @@ routerset_is_empty(const routerset_t *set) return !set || smartlist_len(set->list) == 0; } +/** Return the number of entries in <b>set</b>. This does NOT return a + * negative value. */ +int +routerset_len(const routerset_t *set) +{ + if (!set) { + return 0; + } + return smartlist_len(set->list); +} + /** Helper. Return true iff <b>set</b> contains a router based on the other * provided fields. Return higher values for more specific subentries: a * single router is more specific than an address range of routers, which is @@ -200,7 +198,7 @@ routerset_is_empty(const routerset_t *set) * * (If country is -1, then we take the country * from addr.) */ -static int +STATIC int routerset_contains(const routerset_t *set, const tor_addr_t *addr, uint16_t orport, const char *nickname, const char *id_digest, |