summaryrefslogtreecommitdiff
path: root/src/or/connection_edge.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/or/connection_edge.c')
-rw-r--r--src/or/connection_edge.c141
1 files changed, 141 insertions, 0 deletions
diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c
index f2ddfc76dc..6d247dcebd 100644
--- a/src/or/connection_edge.c
+++ b/src/or/connection_edge.c
@@ -3266,3 +3266,144 @@ parse_extended_hostname(char *address, int allowdotexit)
return BAD_HOSTNAME;
}
+/** Return true iff <b>a</b> and <b>b</b> have isolation rules and fields that
+ * make it permissible to put them on the same circuit.*/
+int
+connection_edge_streams_are_compatible(const edge_connection_t *a,
+ const edge_connection_t *b)
+{
+ const uint8_t iso = a->isolation_flags | b->isolation_flags;
+
+ if ((iso & ISO_DESTPORT) && a->socks_request->port != b->socks_request->port)
+ return 0;
+ /* XXXX023 Not quite right: we care about addresses that resolve to the same
+ place */
+ if ((iso & ISO_DESTADDR) &&
+ strcasecmp(a->socks_request->address, b->socks_request->address))
+ return 0;
+ /* XXXX023 Waititing for ticket #1666 */
+ /*
+ if ((iso & ISO_SOCKSAUTH) &&
+ strcasecmp(a->socks_request->auth, b->socks_request->auth))
+ return 0;
+ */
+ if ((iso & ISO_CLIENTPROTO) &&
+ (TO_CONN(a)->type != TO_CONN(b)->type ||
+ a->socks_request->socks_version != b->socks_request->socks_version))
+ return 0;
+ if ((iso & ISO_CLIENTADDR) &&
+ !tor_addr_eq(&TO_CONN(a)->addr, &TO_CONN(b)->addr))
+ return 0;
+ if ((iso & ISO_SESSIONGRP) && a->session_group != b->session_group)
+ return 0;
+
+ return 1;
+}
+
+/**
+ * Return true iff none of the isolation flags and fields in <b>conn</b>
+ * should prevent it from being attached to <b>circ</b>.
+ */
+int
+connection_edge_compatible_with_circuit(const edge_connection_t *conn,
+ const origin_circuit_t *circ)
+{
+ const uint8_t iso = conn->isolation_flags;
+
+ /* If circ has never been used for an isolated connection, we can
+ * totally use it for this one. */
+ if (!circ->isolation_values_set)
+ return 1;
+
+ /* If circ has been used for connections having more than one value
+ * for some field f, it will have the corresponding bit set in
+ * isolation_flags_mixed. If isolation_flags_mixed has any bits
+ * in common with iso, then conn must be isolated from at least
+ * one stream that has been attached to circ. */
+ if ((iso & circ->isolation_flags_mixed) != 0) {
+ /* For at least one field where conn is isolated, the circuit
+ * already has mixed streams. */
+ return 0;
+ }
+
+ if ((iso & ISO_DESTPORT) && conn->socks_request->port != circ->dest_port)
+ return 0;
+ /* XXXX023 Not quite right: we care about addresses that resolve to the same
+ place */
+ if ((iso & ISO_DESTADDR) &&
+ strcasecmp(conn->socks_request->address, circ->dest_address))
+ return 0;
+ /* XXXX023 Waititing for ticket #1666 */
+ /*
+ if ((iso & ISO_SOCKSAUTH) &&
+ strcasecmp(a->socks_request->auth, b->socks_request->auth))
+ return 0;
+ */
+ if ((iso & ISO_CLIENTPROTO) &&
+ (TO_CONN(conn)->type != circ->client_proto_type ||
+ conn->socks_request->socks_version != circ->client_proto_socksver))
+ return 0;
+ if ((iso & ISO_CLIENTADDR) &&
+ !tor_addr_eq(&TO_CONN(conn)->addr, &circ->client_addr))
+ return 0;
+ if ((iso & ISO_SESSIONGRP) && conn->session_group != circ->session_group)
+ return 0;
+
+ return 1;
+}
+
+/**
+ * If <b>dry_run</b> is false, update <b>circ</b>'s isolation flags and fields
+ * to reflect having had <b>conn</b> attached to it, and return 0. Otherwise,
+ * if <b>dry_run</b> is true, then make no changes to <b>circ</b>, and return
+ * a bitfield of isolation flags that we would have to set in
+ * isolation_flags_mixed to add <b>conn</b> to <b>circ</b>, or -1 if
+ * <b>circ</b> has had no streams attached to it.
+ */
+int
+connection_edge_update_circuit_isolation(const edge_connection_t *conn,
+ origin_circuit_t *circ,
+ int dry_run)
+{
+ if (!circ->isolation_values_set) {
+ if (dry_run)
+ return -1;
+ circ->dest_port = conn->socks_request->port;
+ circ->dest_address = tor_strdup(conn->socks_request->address);
+ circ->client_proto_type = TO_CONN(conn)->type;
+ circ->client_proto_socksver = conn->socks_request->socks_version;
+ tor_addr_copy(&circ->client_addr, &TO_CONN(conn)->addr);
+ circ->session_group = conn->session_group;
+ /* XXXX023 auth too, once #1666 is in. */
+
+ circ->isolation_values_set = 1;
+ return 0;
+ } else {
+ uint8_t mixed = 0;
+ if (conn->socks_request->port != circ->dest_port)
+ mixed |= ISO_DESTPORT;
+ /* XXXX023 Not quite right: we care about addresses that resolve to the
+ same place */
+ if (strcasecmp(conn->socks_request->address, circ->dest_address))
+ mixed |= ISO_DESTADDR;
+ /* XXXX023 auth too, once #1666 is in. */
+ if ((TO_CONN(conn)->type != circ->client_proto_type ||
+ conn->socks_request->socks_version != circ->client_proto_socksver))
+ mixed |= ISO_CLIENTPROTO;
+ if (!tor_addr_eq(&TO_CONN(conn)->addr, &circ->client_addr))
+ mixed |= ISO_CLIENTADDR;
+ if (conn->session_group != circ->session_group)
+ mixed |= ISO_SESSIONGRP;
+
+ if (dry_run)
+ return mixed;
+
+ if ((mixed & conn->isolation_flags) != 0) {
+ log_warn(LD_BUG, "Updating a circuit with seemingly incomaptible "
+ "isolation flags.");
+ }
+ circ->isolation_flags_mixed |= mixed;
+ return 0;
+ }
+}
+