2010-07-22 10:43:02 +02:00
|
|
|
/* Copyright (c) 2001 Matej Pfajfar.
|
|
|
|
* Copyright (c) 2001-2004, Roger Dingledine.
|
|
|
|
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
2017-03-15 21:13:17 +01:00
|
|
|
* Copyright (c) 2007-2017, The Tor Project, Inc. */
|
2010-07-22 10:43:02 +02:00
|
|
|
/* See LICENSE for licensing information */
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \file connection_edge.h
|
|
|
|
* \brief Header file for connection_edge.c.
|
|
|
|
**/
|
|
|
|
|
2012-10-12 18:13:10 +02:00
|
|
|
#ifndef TOR_CONNECTION_EDGE_H
|
|
|
|
#define TOR_CONNECTION_EDGE_H
|
2010-07-22 10:43:02 +02:00
|
|
|
|
2013-06-06 23:58:28 +02:00
|
|
|
#include "testsupport.h"
|
|
|
|
|
2010-07-22 10:43:02 +02:00
|
|
|
#define connection_mark_unattached_ap(conn, endreason) \
|
2012-10-12 18:22:13 +02:00
|
|
|
connection_mark_unattached_ap_((conn), (endreason), __LINE__, SHORT_FILE__)
|
2010-07-22 10:43:02 +02:00
|
|
|
|
2014-04-02 19:38:50 +02:00
|
|
|
MOCK_DECL(void,connection_mark_unattached_ap_,
|
|
|
|
(entry_connection_t *conn, int endreason,
|
|
|
|
int line, const char *file));
|
2010-07-22 10:43:02 +02:00
|
|
|
int connection_edge_reached_eof(edge_connection_t *conn);
|
|
|
|
int connection_edge_process_inbuf(edge_connection_t *conn,
|
|
|
|
int package_partial);
|
|
|
|
int connection_edge_destroy(circid_t circ_id, edge_connection_t *conn);
|
|
|
|
int connection_edge_end(edge_connection_t *conn, uint8_t reason);
|
|
|
|
int connection_edge_end_errno(edge_connection_t *conn);
|
2011-03-14 22:48:45 +01:00
|
|
|
int connection_edge_flushed_some(edge_connection_t *conn);
|
2010-07-22 10:43:02 +02:00
|
|
|
int connection_edge_finished_flushing(edge_connection_t *conn);
|
|
|
|
int connection_edge_finished_connecting(edge_connection_t *conn);
|
|
|
|
|
2011-07-20 18:55:42 +02:00
|
|
|
void connection_ap_about_to_close(entry_connection_t *edge_conn);
|
2011-06-22 19:57:19 +02:00
|
|
|
void connection_exit_about_to_close(edge_connection_t *edge_conn);
|
|
|
|
|
2011-07-20 18:55:42 +02:00
|
|
|
int connection_ap_handshake_send_begin(entry_connection_t *ap_conn);
|
|
|
|
int connection_ap_handshake_send_resolve(entry_connection_t *ap_conn);
|
2010-07-22 10:43:02 +02:00
|
|
|
|
2011-07-20 18:55:42 +02:00
|
|
|
entry_connection_t *connection_ap_make_link(connection_t *partner,
|
2009-08-11 21:16:16 +02:00
|
|
|
char *address, uint16_t port,
|
2010-07-22 10:43:02 +02:00
|
|
|
const char *digest,
|
2011-07-08 21:54:30 +02:00
|
|
|
int session_group,
|
|
|
|
int isolation_flags,
|
2010-07-22 10:43:02 +02:00
|
|
|
int use_begindir, int want_onehop);
|
2011-07-20 18:55:42 +02:00
|
|
|
void connection_ap_handshake_socks_reply(entry_connection_t *conn, char *reply,
|
2010-07-22 10:43:02 +02:00
|
|
|
size_t replylen,
|
|
|
|
int endreason);
|
2014-04-02 19:38:50 +02:00
|
|
|
MOCK_DECL(void,connection_ap_handshake_socks_resolved,
|
|
|
|
(entry_connection_t *conn,
|
|
|
|
int answer_type,
|
|
|
|
size_t answer_len,
|
|
|
|
const uint8_t *answer,
|
|
|
|
int ttl,
|
|
|
|
time_t expires));
|
2014-03-28 03:24:48 +01:00
|
|
|
void connection_ap_handshake_socks_resolved_addr(entry_connection_t *conn,
|
2014-04-02 19:38:50 +02:00
|
|
|
const tor_addr_t *answer,
|
|
|
|
int ttl,
|
|
|
|
time_t expires);
|
2010-07-22 10:43:02 +02:00
|
|
|
|
|
|
|
int connection_exit_begin_conn(cell_t *cell, circuit_t *circ);
|
|
|
|
int connection_exit_begin_resolve(cell_t *cell, or_circuit_t *circ);
|
|
|
|
void connection_exit_connect(edge_connection_t *conn);
|
2017-01-10 14:35:15 +01:00
|
|
|
int connection_edge_is_rendezvous_stream(const edge_connection_t *conn);
|
2011-07-20 18:55:42 +02:00
|
|
|
int connection_ap_can_use_exit(const entry_connection_t *conn,
|
2011-04-27 20:36:30 +02:00
|
|
|
const node_t *exit);
|
2010-07-22 10:43:02 +02:00
|
|
|
void connection_ap_expire_beginning(void);
|
2015-11-13 19:38:01 +01:00
|
|
|
void connection_ap_rescan_and_attach_pending(void);
|
2015-11-17 14:49:30 +01:00
|
|
|
void connection_ap_attach_pending(int retry);
|
2015-11-26 18:44:12 +01:00
|
|
|
void connection_ap_mark_as_pending_circuit_(entry_connection_t *entry_conn,
|
|
|
|
const char *file, int line);
|
|
|
|
#define connection_ap_mark_as_pending_circuit(c) \
|
|
|
|
connection_ap_mark_as_pending_circuit_((c), __FILE__, __LINE__)
|
2015-11-27 18:54:57 +01:00
|
|
|
void connection_ap_mark_as_non_pending_circuit(entry_connection_t *entry_conn);
|
|
|
|
#define CONNECTION_AP_EXPECT_NONPENDING(c) do { \
|
|
|
|
if (ENTRY_TO_CONN(c)->state == AP_CONN_STATE_CIRCUIT_WAIT) { \
|
|
|
|
log_warn(LD_BUG, "At %s:%d: %p was unexpectedly in circuit_wait.", \
|
|
|
|
__FILE__, __LINE__, (c)); \
|
|
|
|
connection_ap_mark_as_non_pending_circuit(c); \
|
|
|
|
} \
|
|
|
|
} while (0)
|
2010-07-22 10:43:02 +02:00
|
|
|
void connection_ap_fail_onehop(const char *failed_digest,
|
|
|
|
cpath_build_state_t *build_state);
|
|
|
|
void circuit_discard_optional_exit_enclaves(extend_info_t *info);
|
2011-07-20 18:55:42 +02:00
|
|
|
int connection_ap_detach_retriable(entry_connection_t *conn,
|
2010-07-22 10:43:02 +02:00
|
|
|
origin_circuit_t *circ,
|
|
|
|
int reason);
|
2011-07-20 18:55:42 +02:00
|
|
|
int connection_ap_process_transparent(entry_connection_t *conn);
|
2010-07-22 10:43:02 +02:00
|
|
|
|
|
|
|
int address_is_invalid_destination(const char *address, int client);
|
|
|
|
|
2011-07-20 18:55:42 +02:00
|
|
|
int connection_ap_rewrite_and_attach_if_allowed(entry_connection_t *conn,
|
2010-08-06 21:29:15 +02:00
|
|
|
origin_circuit_t *circ,
|
|
|
|
crypt_path_t *cpath);
|
2011-07-20 18:55:42 +02:00
|
|
|
int connection_ap_handshake_rewrite_and_attach(entry_connection_t *conn,
|
2010-07-22 10:43:02 +02:00
|
|
|
origin_circuit_t *circ,
|
|
|
|
crypt_path_t *cpath);
|
|
|
|
|
|
|
|
/** Possible return values for parse_extended_hostname. */
|
|
|
|
typedef enum hostname_type_t {
|
|
|
|
NORMAL_HOSTNAME, ONION_HOSTNAME, EXIT_HOSTNAME, BAD_HOSTNAME
|
|
|
|
} hostname_type_t;
|
2012-05-11 23:00:41 +02:00
|
|
|
hostname_type_t parse_extended_hostname(char *address);
|
2010-07-22 10:43:02 +02:00
|
|
|
|
|
|
|
#if defined(HAVE_NET_IF_H) && defined(HAVE_NET_PFVAR_H)
|
|
|
|
int get_pf_socket(void);
|
|
|
|
#endif
|
|
|
|
|
2011-07-20 18:55:42 +02:00
|
|
|
int connection_edge_compatible_with_circuit(const entry_connection_t *conn,
|
2011-07-06 22:03:47 +02:00
|
|
|
const origin_circuit_t *circ);
|
2011-07-20 18:55:42 +02:00
|
|
|
int connection_edge_update_circuit_isolation(const entry_connection_t *conn,
|
2011-07-06 22:03:47 +02:00
|
|
|
origin_circuit_t *circ,
|
|
|
|
int dry_run);
|
Launch sufficient circuits to satisfy pending isolated streams
Our old "do we need to launch a circuit for stream S" logic was,
more or less, that if we had a pending circuit that could handle S,
we didn't need to launch a new one.
But now that we have streams isolated from one another, we need
something stronger here: It's possible that some pending C can
handle either S1 or S2, but not both.
This patch reuses the existing isolation logic for a simple
solution: when we decide during circuit launching that some pending
C would satisfy stream S1, we "hypothetically" mark C as though S1
had been connected to it. Now if S2 is incompatible with S1, it
won't be something that can attach to C, and so we'll launch a new
stream.
When the circuit becomes OPEN for the first time (with no streams
attached to it), we reset the circuit's isolation status. I'm not
too sure about this part: I wanted some way to be sure that, if all
streams that would have used a circuit die before the circuit is
done, the circuit can still get used. But I worry that this
approach could also lead to us launching too many circuits. Careful
thought needed here.
2011-07-07 16:40:23 +02:00
|
|
|
void circuit_clear_isolation(origin_circuit_t *circ);
|
2012-12-12 20:53:18 +01:00
|
|
|
streamid_t get_unique_stream_id_by_circ(origin_circuit_t *circ);
|
2011-07-06 22:03:47 +02:00
|
|
|
|
2015-11-17 15:06:47 +01:00
|
|
|
void connection_edge_free_all(void);
|
|
|
|
|
2015-12-17 01:16:07 +01:00
|
|
|
void connection_ap_warn_and_unmark_if_pending_circ(
|
|
|
|
entry_connection_t *entry_conn,
|
|
|
|
const char *where);
|
|
|
|
|
2012-11-14 21:20:28 +01:00
|
|
|
/** @name Begin-cell flags
|
|
|
|
*
|
|
|
|
* These flags are used in RELAY_BEGIN cells to change the default behavior
|
|
|
|
* of the cell.
|
|
|
|
*
|
|
|
|
* @{
|
|
|
|
**/
|
|
|
|
/** When this flag is set, the client is willing to get connected to IPv6
|
|
|
|
* addresses */
|
2012-10-25 06:20:41 +02:00
|
|
|
#define BEGIN_FLAG_IPV6_OK (1u<<0)
|
2012-11-14 21:20:28 +01:00
|
|
|
/** When this flag is set, the client DOES NOT support connecting to IPv4
|
|
|
|
* addresses. (The sense of this flag is inverted from IPV6_OK, so that the
|
|
|
|
* old default behavior of Tor is equivalent to having all flags set to 0.)
|
|
|
|
**/
|
2012-10-25 06:20:41 +02:00
|
|
|
#define BEGIN_FLAG_IPV4_NOT_OK (1u<<1)
|
2012-11-14 21:20:28 +01:00
|
|
|
/** When this flag is set, if we find both an IPv4 and an IPv6 address,
|
|
|
|
* we use the IPv6 address. Otherwise we use the IPv4 address. */
|
2012-10-25 06:20:41 +02:00
|
|
|
#define BEGIN_FLAG_IPV6_PREFERRED (1u<<2)
|
2012-11-14 21:20:28 +01:00
|
|
|
/**@}*/
|
2012-10-25 06:20:41 +02:00
|
|
|
|
Revise the DNS subsystem to handle IPv6 exits.
Now, every cached_resolve_t can remember an IPv4 result *and* an IPv6
result. As a light protection against timing-based distinguishers for
IPv6 users (and against complexity!), every forward request generates
an IPv4 *and* an IPv6 request, assuming that we're an IPv6 exit. Once
we have answers or errors for both, we act accordingly.
This patch additionally makes some useful refactorings in the dns.c
code, though there is quite a bit more of useful refactoring that could
be done.
Additionally, have a new interface for the argument passed to the
evdns_callback function. Previously, it was just the original address
we were resolving. But it turns out that, on error, evdns doesn't
tell you the type of the query, so on a failure we didn't know whether
IPv4 or IPv6 queries were failing.
The new convention is to have the first byte of that argument include
the query type. I've refactored the code a bit to make that simpler.
2012-11-05 19:26:29 +01:00
|
|
|
#ifdef CONNECTION_EDGE_PRIVATE
|
|
|
|
|
2012-11-14 21:20:28 +01:00
|
|
|
/** A parsed BEGIN or BEGIN_DIR cell */
|
2012-10-22 17:28:37 +02:00
|
|
|
typedef struct begin_cell_t {
|
2012-11-14 21:20:28 +01:00
|
|
|
/** The address the client has asked us to connect to, or NULL if this is
|
|
|
|
* a BEGIN_DIR cell*/
|
2012-10-22 17:28:37 +02:00
|
|
|
char *address;
|
2012-11-14 21:20:28 +01:00
|
|
|
/** The flags specified in the BEGIN cell's body. One or more of
|
|
|
|
* BEGIN_FLAG_*. */
|
2012-10-22 17:28:37 +02:00
|
|
|
uint32_t flags;
|
2012-11-14 21:20:28 +01:00
|
|
|
/** The client's requested port. */
|
2012-10-22 17:28:37 +02:00
|
|
|
uint16_t port;
|
2012-11-14 21:20:28 +01:00
|
|
|
/** The client's requested Stream ID */
|
2012-10-22 17:28:37 +02:00
|
|
|
uint16_t stream_id;
|
2012-11-14 21:20:28 +01:00
|
|
|
/** True iff this is a BEGIN_DIR cell. */
|
2012-10-22 17:28:37 +02:00
|
|
|
unsigned is_begindir : 1;
|
|
|
|
} begin_cell_t;
|
|
|
|
|
2013-06-06 23:58:28 +02:00
|
|
|
STATIC int begin_cell_parse(const cell_t *cell, begin_cell_t *bcell,
|
2012-10-22 17:28:37 +02:00
|
|
|
uint8_t *end_reason_out);
|
2013-06-06 23:58:28 +02:00
|
|
|
STATIC int connected_cell_format_payload(uint8_t *payload_out,
|
2012-11-14 16:48:58 +01:00
|
|
|
const tor_addr_t *addr,
|
|
|
|
uint32_t ttl);
|
2015-01-11 02:14:55 +01:00
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
/** Original address, after we lowercased it but before we started
|
|
|
|
* mapping it.
|
|
|
|
*/
|
|
|
|
char orig_address[MAX_SOCKS_ADDR_LEN];
|
|
|
|
/** True iff the address has been automatically remapped to a local
|
2015-01-18 21:10:35 +01:00
|
|
|
* address in VirtualAddrNetwork. (Only set true when we do a resolve
|
|
|
|
* and get a virtual address; not when we connect to the address.) */
|
2015-01-11 02:14:55 +01:00
|
|
|
int automap;
|
|
|
|
/** If this connection has a .exit address, who put it there? */
|
|
|
|
addressmap_entry_source_t exit_source;
|
|
|
|
/** If we've rewritten the address, when does this map expire? */
|
|
|
|
time_t map_expires;
|
|
|
|
/** If we should close the connection, this is the end_reason to pass
|
|
|
|
* to connection_mark_unattached_ap */
|
|
|
|
int end_reason;
|
|
|
|
/** True iff we should close the connection, either because of error or
|
|
|
|
* because of successful early RESOLVED reply. */
|
|
|
|
int should_close;
|
|
|
|
} rewrite_result_t;
|
|
|
|
|
|
|
|
STATIC void connection_ap_handshake_rewrite(entry_connection_t *conn,
|
|
|
|
rewrite_result_t *out);
|
2012-10-22 17:28:37 +02:00
|
|
|
#endif
|
|
|
|
|
2010-07-22 10:43:02 +02:00
|
|
|
#endif
|
|
|
|
|