switch (purpose) {
/* These purposes connect to a router that we chose, so DEFAULT_ROUTE_LEN
* is safe: */
+ case CIRCUIT_PURPOSE_CONFLUX_UNLINKED:
case CIRCUIT_PURPOSE_TESTING:
/* router reachability testing */
known_purpose = 1;
* since it should be random. */
tor_assert_nonfatal(is_internal);
FALLTHROUGH;
+ case CIRCUIT_PURPOSE_CONFLUX_UNLINKED:
case CIRCUIT_PURPOSE_C_GENERAL:
if (is_internal) /* pick it like a middle hop */
return router_choose_random_node(NULL, options->ExcludeNodes, flags);
case CIRCUIT_PURPOSE_S_HSDIR_POST:
case CIRCUIT_PURPOSE_C_HSDIR_GET:
case CIRCUIT_PURPOSE_C_GENERAL:
+ case CIRCUIT_PURPOSE_CONFLUX_UNLINKED:
+ case CIRCUIT_PURPOSE_CONFLUX_LINKED:
if (circ->build_state->is_internal)
return;
description = "requested exit node";
}
exit_ei = extend_info_from_node(node, state->onehop_tunnel,
/* for_exit_use */
- !state->is_internal && TO_CIRCUIT(circ)->purpose ==
- CIRCUIT_PURPOSE_C_GENERAL);
+ !state->is_internal && (
+ TO_CIRCUIT(circ)->purpose ==
+ CIRCUIT_PURPOSE_C_GENERAL ||
+ TO_CIRCUIT(circ)->purpose ==
+ CIRCUIT_PURPOSE_CONFLUX_UNLINKED));
if (BUG(exit_ei == NULL))
return -1;
}
case CIRCUIT_PURPOSE_C_CIRCUIT_PADDING:
return "CIRCUIT_PADDING";
+ case CIRCUIT_PURPOSE_CONFLUX_UNLINKED:
+ return "CONFLUX_UNLINKED";
+ case CIRCUIT_PURPOSE_CONFLUX_LINKED:
+ return "CONFLUX_LINKED";
+
default:
tor_snprintf(buf, sizeof(buf), "UNKNOWN_%d", (int)purpose);
return buf;
case CIRCUIT_PURPOSE_PATH_BIAS_TESTING:
case CIRCUIT_PURPOSE_HS_VANGUARDS:
case CIRCUIT_PURPOSE_C_CIRCUIT_PADDING:
+ case CIRCUIT_PURPOSE_CONFLUX_UNLINKED:
+ case CIRCUIT_PURPOSE_CONFLUX_LINKED:
return NULL;
case CIRCUIT_PURPOSE_INTRO_POINT:
case CIRCUIT_PURPOSE_C_CIRCUIT_PADDING:
return "Circuit kept open for padding";
+ case CIRCUIT_PURPOSE_CONFLUX_UNLINKED:
+ return "Unlinked conflux circuit";
+
+ case CIRCUIT_PURPOSE_CONFLUX_LINKED:
+ return "Linked conflux circuit";
+
default:
tor_snprintf(buf, sizeof(buf), "UNKNOWN_%d", (int)purpose);
return buf;
* circuits so that we get the same path construction logic. */
return CIRCUIT_PURPOSE_HS_VANGUARDS;
} else {
+ /* Conflux purposes should never get here */
+ tor_assert_nonfatal(purpose != CIRCUIT_PURPOSE_CONFLUX_UNLINKED &&
+ purpose != CIRCUIT_PURPOSE_CONFLUX_LINKED);
/* If no vanguards are used just get a general circuit! */
return CIRCUIT_PURPOSE_C_GENERAL;
}
tor_assert_nonfatal(purpose_to_search_for == CIRCUIT_PURPOSE_C_GENERAL ||
purpose_to_search_for == CIRCUIT_PURPOSE_HS_VANGUARDS);
+ tor_assert_nonfatal(purpose_to_search_for !=
+ CIRCUIT_PURPOSE_CONFLUX_UNLINKED);
+ tor_assert_nonfatal(purpose_to_produce != CIRCUIT_PURPOSE_CONFLUX_UNLINKED);
+
log_debug(LD_CIRC,
"Hunting for a circ to cannibalize: purpose %d, uptime %d, "
"capacity %d, internal %d",
* actual needed HS purpose. */
#define CIRCUIT_PURPOSE_HS_VANGUARDS 24
-#define CIRCUIT_PURPOSE_MAX_ 24
+/**
+ * These two purposes are for conflux. The first is for circuits that are
+ * being built, but not yet linked. The second is for circuits that are
+ * linked and ready to use for streams. */
+#define CIRCUIT_PURPOSE_CONFLUX_UNLINKED 25
+#define CIRCUIT_PURPOSE_CONFLUX_LINKED 26
+
+#define CIRCUIT_PURPOSE_MAX_ 26
/** A catch-all for unrecognized purposes. Currently we don't expect
* to make or see any circuits with this purpose. */
#define CIRCUIT_PURPOSE_UNKNOWN 255
purpose == CIRCUIT_PURPOSE_C_HSDIR_GET ||
purpose == CIRCUIT_PURPOSE_S_HSDIR_POST ||
purpose == CIRCUIT_PURPOSE_HS_VANGUARDS ||
- purpose == CIRCUIT_PURPOSE_C_REND_JOINED) {
+ purpose == CIRCUIT_PURPOSE_C_REND_JOINED ||
+ purpose == CIRCUIT_PURPOSE_CONFLUX_LINKED) {
if (circ->timestamp_dirty &&
circ->timestamp_dirty+get_options()->MaxCircuitDirtiness <= now)
return 0;
return 0;
if (purpose == CIRCUIT_PURPOSE_C_GENERAL ||
+ purpose == CIRCUIT_PURPOSE_CONFLUX_UNLINKED ||
+ purpose == CIRCUIT_PURPOSE_CONFLUX_LINKED ||
purpose == CIRCUIT_PURPOSE_S_HSDIR_POST ||
purpose == CIRCUIT_PURPOSE_C_HSDIR_GET) {
tor_addr_t addr;
SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) {
if (CIRCUIT_IS_ORIGIN(circ) &&
!circ->marked_for_close &&
- circ->purpose == CIRCUIT_PURPOSE_C_GENERAL &&
+ (circ->purpose == CIRCUIT_PURPOSE_C_GENERAL ||
+ circ->purpose == CIRCUIT_PURPOSE_CONFLUX_LINKED) &&
(!circ->timestamp_dirty ||
circ->timestamp_dirty + get_options()->MaxCircuitDirtiness > now)) {
origin_circuit_t *origin_circ = TO_ORIGIN_CIRCUIT(circ);
if (timercmp(&circ->timestamp_began, &cutoff, OP_LT)) {
if (circ->purpose == CIRCUIT_PURPOSE_C_GENERAL ||
circ->purpose == CIRCUIT_PURPOSE_C_HSDIR_GET ||
+ circ->purpose == CIRCUIT_PURPOSE_CONFLUX_UNLINKED ||
+ circ->purpose == CIRCUIT_PURPOSE_CONFLUX_LINKED ||
circ->purpose == CIRCUIT_PURPOSE_S_HSDIR_POST ||
circ->purpose == CIRCUIT_PURPOSE_HS_VANGUARDS ||
circ->purpose == CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT ||
hs_client_circuit_has_opened(circ);
break;
case CIRCUIT_PURPOSE_C_GENERAL:
+ circuit_try_attaching_streams(circ);
+ break;
case CIRCUIT_PURPOSE_C_HSDIR_GET:
case CIRCUIT_PURPOSE_S_HSDIR_POST:
/* Tell any AP connections that have been waiting for a new
return 0;
}
+ /* Do not cannibalize for conflux circuits */
+ if (purpose_to_build == CIRCUIT_PURPOSE_CONFLUX_UNLINKED) {
+ return 0;
+ }
+
return 1;
}
exitnode = node_get_by_id(cpath->extend_info->identity_digest);
/* See if we can use optimistic data on this circuit */
+ // TODO-329-PURPOSE: Can conflux use optimistic data? Does
+ // anything use optimistic data? Does anything use this?
if (circ->base_.purpose == CIRCUIT_PURPOSE_C_GENERAL ||
circ->base_.purpose == CIRCUIT_PURPOSE_C_HSDIR_GET ||
circ->base_.purpose == CIRCUIT_PURPOSE_S_HSDIR_POST ||
}
if (circ->purpose != CIRCUIT_PURPOSE_C_GENERAL &&
+ circ->purpose != CIRCUIT_PURPOSE_CONFLUX_LINKED &&
circ->purpose != CIRCUIT_PURPOSE_CONTROLLER &&
circ->purpose != CIRCUIT_PURPOSE_C_HSDIR_GET &&
circ->purpose != CIRCUIT_PURPOSE_S_HSDIR_POST &&
const edge_connection_t *edge_conn = ENTRY_TO_EDGE_CONN(conn);
/* We can only send optimistic data if we're connected to an open
general circuit. */
+ // TODO-329-PURPOSE: Can conflux circuits use optimistic data?
+ // Does anything use optimistic data?
if (edge_conn->on_circuit == NULL ||
edge_conn->on_circuit->state != CIRCUIT_STATE_OPEN ||
(edge_conn->on_circuit->purpose != CIRCUIT_PURPOSE_C_GENERAL &&
return 0;
/* No flags for hidden services. */
- if (edge_conn->on_circuit->purpose != CIRCUIT_PURPOSE_C_GENERAL)
+ if (edge_conn->on_circuit->purpose != CIRCUIT_PURPOSE_C_GENERAL &&
+ edge_conn->on_circuit->purpose != CIRCUIT_PURPOSE_CONFLUX_LINKED)
return 0;
/* If only IPv4 is supported, no flags */
tor_snprintf(payload,RELAY_PAYLOAD_SIZE, "%s:%d",
(circ->base_.purpose == CIRCUIT_PURPOSE_C_GENERAL ||
+ circ->base_.purpose == CIRCUIT_PURPOSE_CONFLUX_LINKED ||
circ->base_.purpose == CIRCUIT_PURPOSE_CONTROLLER) ?
ap_conn->socks_request->address : "",
ap_conn->socks_request->port);
tor_assert(base_conn->type == CONN_TYPE_AP);
tor_assert(base_conn->state == AP_CONN_STATE_CIRCUIT_WAIT);
tor_assert(ap_conn->socks_request);
- tor_assert(circ->base_.purpose == CIRCUIT_PURPOSE_C_GENERAL);
+ tor_assert(circ->base_.purpose == CIRCUIT_PURPOSE_C_GENERAL ||
+ circ->base_.purpose == CIRCUIT_PURPOSE_CONFLUX_LINKED);
command = ap_conn->socks_request->command;
tor_assert(SOCKS_COMMAND_IS_RESOLVE(command));
* endpoint could be chosen maliciously.
* Similarly, we can't count client-side intro attempts,
* because clients can be manipulated into connecting to
- * malicious intro points. */
+ * malicious intro points.
+ *
+ * Finally, avoid counting conflux circuits for now, because
+ * a malicious exit could cause us to reconnect and blame
+ * our guard...
+ *
+ * TODO-329-PURPOSE: This is not quite right, we could
+ * instead avoid sending usable probes on conflux circs,
+ * and count only linked circs as failures, but it is
+ * not 100% clear that would result in accurate counts. */
if (get_options()->UseEntryGuards == 0 ||
circ->base_.purpose == CIRCUIT_PURPOSE_TESTING ||
circ->base_.purpose == CIRCUIT_PURPOSE_CONTROLLER ||
circ->base_.purpose == CIRCUIT_PURPOSE_S_CONNECT_REND ||
circ->base_.purpose == CIRCUIT_PURPOSE_S_REND_JOINED ||
+ circ->base_.purpose == CIRCUIT_PURPOSE_CONFLUX_UNLINKED ||
+ circ->base_.purpose == CIRCUIT_PURPOSE_CONFLUX_LINKED ||
(circ->base_.purpose >= CIRCUIT_PURPOSE_C_INTRODUCING &&
circ->base_.purpose <= CIRCUIT_PURPOSE_C_INTRODUCE_ACKED)) {