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); }
/** Return a circuit that is open, is CIRCUIT_PURPOSE_C_GENERAL, * has a timestamp_dirty value of 0, has flags matching the CIRCLAUNCH_* * flags in <b>flags</b>, and if info is defined, does not already use info * as any of its hops; or NULL if no circuit fits this description. * * The <b>purpose</b> argument (currently ignored) refers to the purpose of * the circuit we want to create, not the purpose of the circuit we want to * cannibalize. * * If !CIRCLAUNCH_NEED_UPTIME, prefer returning non-uptime circuits. */ origin_circuit_t * circuit_find_to_cannibalize(uint8_t purpose, extend_info_t *info, int flags) { circuit_t *_circ; origin_circuit_t *best=NULL; int need_uptime = (flags & CIRCLAUNCH_NEED_UPTIME) != 0; int need_capacity = (flags & CIRCLAUNCH_NEED_CAPACITY) != 0; int internal = (flags & CIRCLAUNCH_IS_INTERNAL) != 0; const or_options_t *options = get_options(); /* Make sure we're not trying to create a onehop circ by * cannibalization. */ tor_assert(!(flags & CIRCLAUNCH_ONEHOP_TUNNEL)); log_debug(LD_CIRC, "Hunting for a circ to cannibalize: purpose %d, uptime %d, " "capacity %d, internal %d", purpose, need_uptime, need_capacity, internal); for (_circ=global_circuitlist; _circ; _circ = _circ->next) { if (CIRCUIT_IS_ORIGIN(_circ) && _circ->state == CIRCUIT_STATE_OPEN && !_circ->marked_for_close && _circ->purpose == CIRCUIT_PURPOSE_C_GENERAL && !_circ->timestamp_dirty) { origin_circuit_t *circ = TO_ORIGIN_CIRCUIT(_circ); if ((!need_uptime || circ->build_state->need_uptime) && (!need_capacity || circ->build_state->need_capacity) && (internal == circ->build_state->is_internal) && circ->remaining_relay_early_cells && circ->build_state->desired_path_len == DEFAULT_ROUTE_LEN && !circ->build_state->onehop_tunnel && !circ->isolation_values_set) { if (info) { /* need to make sure we don't duplicate hops */ crypt_path_t *hop = circ->cpath; const node_t *ri1 = node_get_by_id(info->identity_digest); do { const node_t *ri2; if (tor_memeq(hop->extend_info->identity_digest, info->identity_digest, DIGEST_LEN)) goto next; if (ri1 && (ri2 = node_get_by_id(hop->extend_info->identity_digest)) && nodes_in_same_family(ri1, ri2)) goto next; hop=hop->next; } while (hop!=circ->cpath); } if (options->ExcludeNodes) { /* Make sure no existing nodes in the circuit are excluded for * general use. (This may be possible if StrictNodes is 0, and we * thought we needed to use an otherwise excluded node for, say, a * directory operation.) */ crypt_path_t *hop = circ->cpath; do { if (routerset_contains_extendinfo(options->ExcludeNodes, hop->extend_info)) goto next; hop = hop->next; } while (hop != circ->cpath); } if (!best || (best->build_state->need_uptime && !need_uptime)) best = circ; next: ; } } } return best; }