aboutsummaryrefslogtreecommitdiff
path: root/src/or/routerset.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/or/routerset.c')
-rw-r--r--src/or/routerset.c82
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,