static void test_rend_cache_free_all(void *data) { rend_cache_failure_t *failure; rend_cache_entry_t *one; rend_service_descriptor_t *desc_one; (void)data; rend_cache_init(); failure = rend_cache_failure_entry_new(); strmap_set_lc(rend_cache_failure, "foo1", failure); one = tor_malloc_zero(sizeof(rend_cache_entry_t)); desc_one = tor_malloc_zero(sizeof(rend_service_descriptor_t)); one->parsed = desc_one; desc_one->timestamp = time(NULL) + TIME_IN_THE_PAST; desc_one->pk = pk_generate(0); strmap_set_lc(rend_cache, "foo1", one); rend_cache_free_all(); tt_assert(!rend_cache); tt_assert(!rend_cache_v2_dir); tt_assert(!rend_cache_failure); tt_assert(!rend_cache_total_allocation); done: rend_cache_free_all(); }
static void test_rend_cache_failure_clean(void *data) { rend_cache_failure_t *failure; rend_cache_failure_intro_t *ip_one, *ip_two; const char key_one[DIGEST_LEN] = "ip1"; const char key_two[DIGEST_LEN] = "ip2"; (void)data; rend_cache_init(); // Test with empty failure cache rend_cache_failure_clean(time(NULL)); tt_int_op(strmap_size(rend_cache_failure), OP_EQ, 0); // Test with one empty failure entry failure = rend_cache_failure_entry_new(); strmap_set_lc(rend_cache_failure, "foo1", failure); rend_cache_failure_clean(time(NULL)); tt_int_op(strmap_size(rend_cache_failure), OP_EQ, 0); // Test with one new intro point failure = rend_cache_failure_entry_new(); ip_one = rend_cache_failure_intro_entry_new(INTRO_POINT_FAILURE_TIMEOUT); digestmap_set(failure->intro_failures, key_one, ip_one); strmap_set_lc(rend_cache_failure, "foo1", failure); rend_cache_failure_clean(time(NULL)); tt_int_op(strmap_size(rend_cache_failure), OP_EQ, 1); // Test with one old intro point rend_cache_failure_purge(); failure = rend_cache_failure_entry_new(); ip_one = rend_cache_failure_intro_entry_new(INTRO_POINT_FAILURE_TIMEOUT); ip_one->created_ts = time(NULL) - 7*60; digestmap_set(failure->intro_failures, key_one, ip_one); strmap_set_lc(rend_cache_failure, "foo1", failure); rend_cache_failure_clean(time(NULL)); tt_int_op(strmap_size(rend_cache_failure), OP_EQ, 0); // Test with one old intro point and one new one rend_cache_failure_purge(); failure = rend_cache_failure_entry_new(); ip_one = rend_cache_failure_intro_entry_new(INTRO_POINT_FAILURE_TIMEOUT); ip_one->created_ts = time(NULL) - 7*60; digestmap_set(failure->intro_failures, key_one, ip_one); ip_two = rend_cache_failure_intro_entry_new(INTRO_POINT_FAILURE_TIMEOUT); ip_two->created_ts = time(NULL) - 2*60; digestmap_set(failure->intro_failures, key_two, ip_two); strmap_set_lc(rend_cache_failure, "foo1", failure); rend_cache_failure_clean(time(NULL)); tt_int_op(strmap_size(rend_cache_failure), OP_EQ, 1); tt_int_op(digestmap_size(failure->intro_failures), OP_EQ, 1); done: rend_cache_free_all(); }
static void test_rend_cache_validate_intro_point_failure(void *data) { (void)data; rend_service_descriptor_t *desc = NULL; char *service_id = NULL; rend_intro_point_t *intro = NULL; const char *identity = NULL; rend_cache_failure_t *failure; rend_cache_failure_intro_t *ip; rend_cache_init(); create_descriptor(&desc, &service_id, 3); desc->timestamp = time(NULL) + RECENT_TIME; intro = (rend_intro_point_t *)smartlist_get(desc->intro_nodes, 0); identity = intro->extend_info->identity_digest; failure = rend_cache_failure_entry_new(); ip = rend_cache_failure_intro_entry_new(INTRO_POINT_FAILURE_TIMEOUT); digestmap_set(failure->intro_failures, identity, ip); strmap_set_lc(rend_cache_failure, service_id, failure); // Test when we have an intro point in our cache validate_intro_point_failure(desc, service_id); tt_int_op(smartlist_len(desc->intro_nodes), OP_EQ, 2); done: rend_cache_free_all(); rend_service_descriptor_free(desc); tor_free(service_id); }
static void NS(test_main)(void *arg) { routerset_t *set = routerset_new(); smartlist_t *list = smartlist_new(); const char *nickname = "foo"; routerinfo_t ri; node_t mock_node; (void)arg; strmap_set_lc(set->names, nickname, (void *)1); ri.nickname = (char *)nickname; mock_node.rs = NULL; mock_node.ri = &ri; smartlist_add(list, (void *)&mock_node); tt_int_op(smartlist_len(list), !=, 0); routerset_subtract_nodes(list, set); tt_int_op(smartlist_len(list), ==, 0); done: routerset_free(set); smartlist_free(list); }
/** Add an entry to the GeoIP table, mapping all IPs between <b>low</b> and * <b>high</b>, inclusive, to the 2-letter country code <b>country</b>. */ static void geoip_add_entry(uint32_t low, uint32_t high, const char *country) { intptr_t idx; geoip_entry_t *ent; void *idxplus1_; if (high < low) return; idxplus1_ = strmap_get_lc(country_idxplus1_by_lc_code, country); if (!idxplus1_) { geoip_country_t *c = tor_malloc_zero(sizeof(geoip_country_t)); strlcpy(c->countrycode, country, sizeof(c->countrycode)); tor_strlower(c->countrycode); smartlist_add(geoip_countries, c); idx = smartlist_len(geoip_countries) - 1; strmap_set_lc(country_idxplus1_by_lc_code, country, (void*)(idx+1)); } else { idx = ((uintptr_t)idxplus1_)-1; } { geoip_country_t *c = smartlist_get(geoip_countries, idx); tor_assert(!strcasecmp(c->countrycode, country)); } ent = tor_malloc_zero(sizeof(geoip_entry_t)); ent->ip_low = low; ent->ip_high = high; ent->country = idx; smartlist_add(geoip_entries, ent); }
/** Parse the string <b>s</b> to create a set of routerset entries, and add * them to <b>target</b>. In log messages, refer to the string as * <b>description</b>. Return 0 on success, -1 on failure. * * Three kinds of elements are allowed in routersets: nicknames, IP address * patterns, and fingerprints. They may be surrounded by optional space, and * must be separated by commas. */ int routerset_parse(routerset_t *target, const char *s, const char *description) { int r = 0; 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 == '$') ++nick; log_debug(LD_CONFIG, "Adding identity %s to %s", nick, description); base16_decode(d, sizeof(d), nick, HEX_DIGEST_LEN); digestmap_set(target->digests, d, (void*)1); } else if (is_legal_nickname(nick)) { log_debug(LD_CONFIG, "Adding nickname %s to %s", nick, description); strmap_set_lc(target->names, nick, (void*)1); } else if ((countryname = routerset_get_countryname(nick)) != NULL) { log_debug(LD_CONFIG, "Adding country %s to %s", nick, description); smartlist_add(target->country_names, countryname); added_countries = 1; } 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 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);
/** Set up a new list of geoip countries with no countries (yet) set in it, * except for the unknown country. */ static void init_geoip_countries(void) { geoip_country_t *geoip_unresolved; geoip_countries = smartlist_new(); /* Add a geoip_country_t for requests that could not be resolved to a * country as first element (index 0) to geoip_countries. */ geoip_unresolved = tor_malloc_zero(sizeof(geoip_country_t)); strlcpy(geoip_unresolved->countrycode, "??", sizeof(geoip_unresolved->countrycode)); smartlist_add(geoip_countries, geoip_unresolved); country_idxplus1_by_lc_code = strmap_new(); strmap_set_lc(country_idxplus1_by_lc_code, "??", (void*)(1)); }
static void NS(test_main)(void *arg) { routerset_t *set = routerset_new(); int contains; (void)arg; strmap_set_lc(set->names, "bar", (void *)1); contains = routerset_contains(set, NULL, 0, "foo", NULL, 0); routerset_free(set); tt_int_op(contains, ==, 0); done: ; }
static void NS(test_main)(void *arg) { routerset_t *set = routerset_new(); const char *nickname; int contains; (void)arg; nickname = "Foo"; /* This tests the lowercase comparison as well. */ strmap_set_lc(set->names, nickname, (void *)1); contains = routerset_contains(set, NULL, 0, nickname, NULL, 0); routerset_free(set); tt_int_op(contains, ==, 4); done: ; }
/** Add an entry to a GeoIP table, mapping all IP addresses between <b>low</b> * and <b>high</b>, inclusive, to the 2-letter country code <b>country</b>. */ static void geoip_add_entry(const tor_addr_t *low, const tor_addr_t *high, const char *country) { intptr_t idx; void *idxplus1_; if (tor_addr_family(low) != tor_addr_family(high)) return; if (tor_addr_compare(high, low, CMP_EXACT) < 0) return; idxplus1_ = strmap_get_lc(country_idxplus1_by_lc_code, country); if (!idxplus1_) { geoip_country_t *c = tor_malloc_zero(sizeof(geoip_country_t)); strlcpy(c->countrycode, country, sizeof(c->countrycode)); tor_strlower(c->countrycode); smartlist_add(geoip_countries, c); idx = smartlist_len(geoip_countries) - 1; strmap_set_lc(country_idxplus1_by_lc_code, country, (void*)(idx+1)); } else { idx = ((uintptr_t)idxplus1_)-1; } { geoip_country_t *c = smartlist_get(geoip_countries, idx); tor_assert(!strcasecmp(c->countrycode, country)); } if (tor_addr_family(low) == AF_INET) { geoip_ipv4_entry_t *ent = tor_malloc_zero(sizeof(geoip_ipv4_entry_t)); ent->ip_low = tor_addr_to_ipv4h(low); ent->ip_high = tor_addr_to_ipv4h(high); ent->country = idx; smartlist_add(geoip_ipv4_entries, ent); } else if (tor_addr_family(low) == AF_INET6) { geoip_ipv6_entry_t *ent = tor_malloc_zero(sizeof(geoip_ipv6_entry_t)); ent->ip_low = *tor_addr_to_in6(low); ent->ip_high = *tor_addr_to_in6(high); ent->country = idx; smartlist_add(geoip_ipv6_entries, ent); } }
static void NS(test_main)(void *arg) { routerset_t *set = routerset_new(); routerinfo_t ri; country_t country = 1; int r; const char *nickname = "foo"; (void)arg; memset(&ri, 0, sizeof(ri)); strmap_set_lc(set->names, nickname, (void *)1); ri.nickname = (char *)nickname; r = routerset_contains_router(set, &ri, country); tt_int_op(r, ==, 4); done: routerset_free(set); }
static void NS(test_main)(void *arg) { routerset_t *set = routerset_new(); extend_info_t ei; int r; const char *nickname = "foo"; (void)arg; memset(&ei, 0, sizeof(ei)); strmap_set_lc(set->names, nickname, (void *)1); strncpy(ei.nickname, nickname, sizeof(ei.nickname) - 1); ei.nickname[sizeof(ei.nickname) - 1] = '\0'; r = routerset_contains_extendinfo(set, &ei); tt_int_op(r, ==, 4); done: routerset_free(set); }
static void NS(test_main)(void *arg) { routerset_t *set = routerset_new(); routerstatus_t rs; country_t country = 1; int r; const char *nickname = "foo"; (void)arg; memset(&rs, 0, sizeof(rs)); strmap_set_lc(set->names, nickname, (void *)1); strncpy(rs.nickname, nickname, sizeof(rs.nickname) - 1); rs.nickname[sizeof(rs.nickname) - 1] = '\0'; r = routerset_contains_routerstatus(set, &rs, country); tt_int_op(r, ==, 4); done: routerset_free(set); }
static void test_rend_cache_failure_intro_lookup(void *data) { (void)data; int ret; rend_cache_failure_t *failure; rend_cache_failure_intro_t *ip; rend_cache_failure_intro_t *entry; const char key_ip_one[DIGEST_LEN] = "ip1"; const char key_ip_two[DIGEST_LEN] = "ip2"; const char key_foo[DIGEST_LEN] = "foo1"; rend_cache_init(); failure = rend_cache_failure_entry_new(); ip = rend_cache_failure_intro_entry_new(INTRO_POINT_FAILURE_TIMEOUT); digestmap_set(failure->intro_failures, key_ip_one, ip); strmap_set_lc(rend_cache_failure, "foo1", failure); // Test not found ret = cache_failure_intro_lookup((const uint8_t *) key_foo, "foo2", NULL); tt_int_op(ret, OP_EQ, 0); // Test found with no intro failures in it ret = cache_failure_intro_lookup((const uint8_t *) key_ip_two, "foo1", NULL); tt_int_op(ret, OP_EQ, 0); // Test found ret = cache_failure_intro_lookup((const uint8_t *) key_ip_one, "foo1", NULL); tt_int_op(ret, OP_EQ, 1); // Test found and asking for entry cache_failure_intro_lookup((const uint8_t *) key_ip_one, "foo1", &entry); tt_assert(entry); tt_assert(entry == ip); done: rend_cache_free_all(); }
static void NS(test_main)(void *arg) { routerset_t *set = routerset_new(); int r; const char *nickname = "foo"; routerstatus_t rs; (void)arg; strmap_set_lc(set->names, nickname, (void *)1); strncpy(rs.nickname, nickname, sizeof(rs.nickname) - 1); rs.nickname[sizeof(rs.nickname) - 1] = '\0'; NS(mock_node).ri = NULL; NS(mock_node).rs = &rs; r = routerset_contains_node(set, &NS(mock_node)); tt_int_op(r, ==, 4); done: routerset_free(set); }
/** Parse the string <b>s</b> to create a set of routerset entries, and add * them to <b>target</b>. In log messages, refer to the string as * <b>description</b>. Return 0 on success, -1 on failure. * * Three kinds of elements are allowed in routersets: nicknames, IP address * patterns, and fingerprints. They may be surrounded by optional space, and * must be separated by commas. */ int routerset_parse(routerset_t *target, const char *s, const char *description) { int r = 0; int added_countries = 0; char *countryname; smartlist_t *list = smartlist_new(); smartlist_split_string(list, s, ",", SPLIT_SKIP_SPACE | SPLIT_IGNORE_BLANK, 0); SMARTLIST_FOREACH_BEGIN(list, char *, nick) { addr_policy_t *p; if (is_legal_hexdigest(nick)) { char d[DIGEST_LEN]; if (*nick == '$') ++nick; log_debug(LD_CONFIG, "Adding identity %s to %s", nick, description); base16_decode(d, sizeof(d), nick, HEX_DIGEST_LEN); digestmap_set(target->digests, d, (void*)1); } else if (is_legal_nickname(nick)) { log_debug(LD_CONFIG, "Adding nickname %s to %s", nick, description); strmap_set_lc(target->names, nick, (void*)1); } else if ((countryname = routerset_get_countryname(nick)) != NULL) { log_debug(LD_CONFIG, "Adding country %s to %s", nick, 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))) { 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); r = -1; tor_free(nick); SMARTLIST_DEL_CURRENT(list, nick); } } SMARTLIST_FOREACH_END(nick);
static void NS(test_main)(void *arg) { routerset_t *set = routerset_new(); int r; const char *nickname = "foo"; routerinfo_t ri; node_t mock_node; (void)arg; strmap_set_lc(set->names, nickname, (void *)1); ri.nickname = (char *)nickname; mock_node.ri = &ri; mock_node.rs = NULL; r = routerset_contains_node(set, &mock_node); tt_int_op(r, ==, 4); done: routerset_free(set); }
static void test_rend_cache_clean(void *data) { rend_cache_entry_t *one, *two; rend_service_descriptor_t *desc_one, *desc_two; strmap_iter_t *iter = NULL; const char *key; void *val; (void)data; rend_cache_init(); // Test with empty rendcache rend_cache_clean(time(NULL), REND_CACHE_TYPE_CLIENT); tt_int_op(strmap_size(rend_cache), OP_EQ, 0); // Test with two old entries one = tor_malloc_zero(sizeof(rend_cache_entry_t)); two = tor_malloc_zero(sizeof(rend_cache_entry_t)); desc_one = tor_malloc_zero(sizeof(rend_service_descriptor_t)); desc_two = tor_malloc_zero(sizeof(rend_service_descriptor_t)); one->parsed = desc_one; two->parsed = desc_two; desc_one->timestamp = time(NULL) + TIME_IN_THE_PAST; desc_two->timestamp = (time(NULL) + TIME_IN_THE_PAST) - 10; desc_one->pk = pk_generate(0); desc_two->pk = pk_generate(1); strmap_set_lc(rend_cache, "foo1", one); strmap_set_lc(rend_cache, "foo2", two); rend_cache_clean(time(NULL), REND_CACHE_TYPE_CLIENT); tt_int_op(strmap_size(rend_cache), OP_EQ, 0); // Test with one old entry and one newer entry one = tor_malloc_zero(sizeof(rend_cache_entry_t)); two = tor_malloc_zero(sizeof(rend_cache_entry_t)); desc_one = tor_malloc_zero(sizeof(rend_service_descriptor_t)); desc_two = tor_malloc_zero(sizeof(rend_service_descriptor_t)); one->parsed = desc_one; two->parsed = desc_two; desc_one->timestamp = (time(NULL) + TIME_IN_THE_PAST) - 10; desc_two->timestamp = time(NULL) - 100; desc_one->pk = pk_generate(0); desc_two->pk = pk_generate(1); strmap_set_lc(rend_cache, "foo1", one); strmap_set_lc(rend_cache, "foo2", two); rend_cache_clean(time(NULL), REND_CACHE_TYPE_CLIENT); tt_int_op(strmap_size(rend_cache), OP_EQ, 1); iter = strmap_iter_init(rend_cache); strmap_iter_get(iter, &key, &val); tt_str_op(key, OP_EQ, "foo2"); done: rend_cache_free_all(); }
/** Run unit tests for string-to-void* map functions */ static void test_container_strmap(void) { strmap_t *map; strmap_iter_t *iter; const char *k; void *v; char *visited = NULL; smartlist_t *found_keys = NULL; map = strmap_new(); test_assert(map); test_eq(strmap_size(map), 0); test_assert(strmap_isempty(map)); v = strmap_set(map, "K1", (void*)99); test_eq_ptr(v, NULL); test_assert(!strmap_isempty(map)); v = strmap_set(map, "K2", (void*)101); test_eq_ptr(v, NULL); v = strmap_set(map, "K1", (void*)100); test_eq_ptr(v, (void*)99); test_eq_ptr(strmap_get(map,"K1"), (void*)100); test_eq_ptr(strmap_get(map,"K2"), (void*)101); test_eq_ptr(strmap_get(map,"K-not-there"), NULL); strmap_assert_ok(map); v = strmap_remove(map,"K2"); strmap_assert_ok(map); test_eq_ptr(v, (void*)101); test_eq_ptr(strmap_get(map,"K2"), NULL); test_eq_ptr(strmap_remove(map,"K2"), NULL); strmap_set(map, "K2", (void*)101); strmap_set(map, "K3", (void*)102); strmap_set(map, "K4", (void*)103); test_eq(strmap_size(map), 4); strmap_assert_ok(map); strmap_set(map, "K5", (void*)104); strmap_set(map, "K6", (void*)105); strmap_assert_ok(map); /* Test iterator. */ iter = strmap_iter_init(map); found_keys = smartlist_new(); while (!strmap_iter_done(iter)) { strmap_iter_get(iter,&k,&v); smartlist_add(found_keys, tor_strdup(k)); test_eq_ptr(v, strmap_get(map, k)); if (!strcmp(k, "K2")) { iter = strmap_iter_next_rmv(map,iter); } else { iter = strmap_iter_next(map,iter); } } /* Make sure we removed K2, but not the others. */ test_eq_ptr(strmap_get(map, "K2"), NULL); test_eq_ptr(strmap_get(map, "K5"), (void*)104); /* Make sure we visited everyone once */ smartlist_sort_strings(found_keys); visited = smartlist_join_strings(found_keys, ":", 0, NULL); test_streq(visited, "K1:K2:K3:K4:K5:K6"); strmap_assert_ok(map); /* Clean up after ourselves. */ strmap_free(map, NULL); map = NULL; /* Now try some lc functions. */ map = strmap_new(); strmap_set_lc(map,"Ab.C", (void*)1); test_eq_ptr(strmap_get(map,"ab.c"), (void*)1); strmap_assert_ok(map); test_eq_ptr(strmap_get_lc(map,"AB.C"), (void*)1); test_eq_ptr(strmap_get(map,"AB.C"), NULL); test_eq_ptr(strmap_remove_lc(map,"aB.C"), (void*)1); strmap_assert_ok(map); test_eq_ptr(strmap_get_lc(map,"AB.C"), NULL); done: if (map) strmap_free(map,NULL); if (found_keys) { SMARTLIST_FOREACH(found_keys, char *, cp, tor_free(cp)); smartlist_free(found_keys); } tor_free(visited); }