/** 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);
/* Using the given list of services, stage them into our global state. Every * service version are handled. This function can remove entries in the given * service_list. * * Staging a service means that we take all services in service_list and we * put them in the staging list (global) which acts as a temporary list that * is used by the service loading key process. In other words, staging a * service puts it in a list to be considered when loading the keys and then * moved to the main global list. */ static void stage_services(smartlist_t *service_list) { tor_assert(service_list); /* This is v2 specific. Trigger service pruning which will make sure the * just configured services end up in the main global list. It should only * be done in non validation mode because v2 subsystem handles service * object differently. */ rend_service_prune_list(); /* Cleanup v2 service from the list, we don't need those object anymore * because we validated them all against the others and we want to stage * only >= v3 service. And remember, v2 has a different object type which is * shadow copied from an hs_service_t type. */ SMARTLIST_FOREACH_BEGIN(service_list, hs_service_t *, s) { if (s->config.version == HS_VERSION_TWO) { SMARTLIST_DEL_CURRENT(service_list, s); hs_service_free(s); } } SMARTLIST_FOREACH_END(s); /* This is >= v3 specific. Using the newly configured service list, stage * them into our global state. Every object ownership is lost after. */ hs_service_stage_services(service_list); }
/** Remove every entry of the bridge list that was marked with * mark_bridge_list if it has not subsequently been un-marked. */ void sweep_bridge_list(void) { if (!bridge_list) bridge_list = smartlist_new(); SMARTLIST_FOREACH_BEGIN(bridge_list, bridge_info_t *, b) { if (b->marked_for_removal) { SMARTLIST_DEL_CURRENT(bridge_list, b); bridge_free(b); } } SMARTLIST_FOREACH_END(b); }
/** Remove every entry of the transport list that was marked with * mark_transport_list if it has not subsequently been un-marked. */ void sweep_transport_list(void) { if (!transport_list) transport_list = smartlist_new(); SMARTLIST_FOREACH_BEGIN(transport_list, transport_t *, t) { if (t->marked_for_removal) { SMARTLIST_DEL_CURRENT(transport_list, t); transport_free(t); } } SMARTLIST_FOREACH_END(t); }
/** * Take a list of uint16_t *, and remove every port in the list from the * current list of predicted ports. */ void rep_hist_remove_predicted_ports(const smartlist_t *rmv_ports) { /* Let's do this on O(N), not O(N^2). */ bitarray_t *remove_ports = bitarray_init_zero(UINT16_MAX); SMARTLIST_FOREACH(rmv_ports, const uint16_t *, p, bitarray_set(remove_ports, *p)); SMARTLIST_FOREACH_BEGIN(predicted_ports_list, predicted_port_t *, pp) { if (bitarray_is_set(remove_ports, pp->port)) { tor_free(pp); predicted_ports_total_alloc -= sizeof(*pp); SMARTLIST_DEL_CURRENT(predicted_ports_list, pp); } } SMARTLIST_FOREACH_END(pp); bitarray_free(remove_ports); }
/** 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);
/** Return a newly allocated pointer to a list of uint16_t * for ports that * are likely to be asked for in the near future. */ smartlist_t * rep_hist_get_predicted_ports(time_t now) { int predicted_circs_relevance_time; smartlist_t *out = smartlist_new(); tor_assert(predicted_ports_list); predicted_circs_relevance_time = (int)prediction_timeout; /* clean out obsolete entries */ SMARTLIST_FOREACH_BEGIN(predicted_ports_list, predicted_port_t *, pp) { if (pp->time + predicted_circs_relevance_time < now) { log_debug(LD_CIRC, "Expiring predicted port %d", pp->port); predicted_ports_total_alloc -= sizeof(predicted_port_t); tor_free(pp); SMARTLIST_DEL_CURRENT(predicted_ports_list, pp); } else { smartlist_add(out, tor_memdup(&pp->port, sizeof(uint16_t))); } } SMARTLIST_FOREACH_END(pp); return out; }