mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-28 14:23:30 +01:00
Skeleton ExtORPort implementation. Needs testing, documentation.
Does not implement TransportControlPort yet.
This commit is contained in:
parent
f45e1fbd5b
commit
8bf0382b22
@ -1702,6 +1702,54 @@ fetch_from_evbuffer_socks(struct evbuffer *buf, socks_request_t *req,
|
||||
}
|
||||
#endif
|
||||
|
||||
/*DOCDOC*/
|
||||
#define EXT_OR_CMD_HEADER_SIZE 4
|
||||
/*DOCDOC*/
|
||||
int
|
||||
fetch_ext_or_command_from_buf(buf_t *buf, ext_or_cmd_t **out)
|
||||
{
|
||||
char hdr[EXT_OR_CMD_HEADER_SIZE];
|
||||
uint16_t len;
|
||||
|
||||
check();
|
||||
if (buf->datalen < EXT_OR_CMD_HEADER_SIZE)
|
||||
return 0;
|
||||
peek_from_buf(hdr, sizeof(hdr), buf);
|
||||
len = ntohs(get_uint16(hdr+2));
|
||||
if (buf->datalen < (unsigned)len + EXT_OR_CMD_HEADER_SIZE)
|
||||
return 0;
|
||||
*out = ext_or_cmd_new(len);
|
||||
(*out)->cmd = ntohs(get_uint16(hdr));
|
||||
(*out)->len = len;
|
||||
buf_remove_from_front(buf, EXT_OR_CMD_HEADER_SIZE);
|
||||
fetch_from_buf((*out)->body, len, buf);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef USE_BUFFEREVENTS
|
||||
/*DOCDOC*/
|
||||
int
|
||||
fetch_ext_or_command_from_evbuffer(struct evbuffer *buf, ext_or_cmd_t **out)
|
||||
{
|
||||
char hdr[EXT_OR_CMD_HEADER_SIZE];
|
||||
uint16_t len;
|
||||
size_t buf_len = evbuffer_get_length(buf);
|
||||
|
||||
if (buf_len < EXT_OR_CMD_HEADER_SIZE)
|
||||
return 0;
|
||||
evbuffer_copyout(buf, hdr, EXT_OR_CMD_HEADER_SIZE);
|
||||
len = ntohs(get_uint16(hdr+2));
|
||||
if (buf_len < (unsigned)len + EXT_OR_CMD_HEADER_SIZE)
|
||||
return 0;
|
||||
*out = ext_or_cmd_new(len);
|
||||
(*out)->cmd = ntohs(get_uint16(hdr));
|
||||
(*out)->len = len;
|
||||
evbuffer_drain(buf, EXT_OR_CMD_HEADER_SIZE);
|
||||
evbuffer_remove(buf, (*out)->body, len);
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
/** Implementation helper to implement fetch_from_*_socks. Instead of looking
|
||||
* at a buffer's contents, we look at the <b>datalen</b> bytes of data in
|
||||
* <b>data</b>. Instead of removing data from the buffer, we set
|
||||
|
@ -53,6 +53,8 @@ int fetch_from_buf_line(buf_t *buf, char *data_out, size_t *data_len);
|
||||
|
||||
int peek_buf_has_control0_command(buf_t *buf);
|
||||
|
||||
int fetch_ext_or_command_from_buf(buf_t *buf, ext_or_cmd_t **out);
|
||||
|
||||
#ifdef USE_BUFFEREVENTS
|
||||
int fetch_var_cell_from_evbuffer(struct evbuffer *buf, var_cell_t **out,
|
||||
int linkproto);
|
||||
@ -68,6 +70,8 @@ int peek_evbuffer_has_control0_command(struct evbuffer *buf);
|
||||
int write_to_evbuffer_zlib(struct evbuffer *buf, tor_zlib_state_t *state,
|
||||
const char *data, size_t data_len,
|
||||
int done);
|
||||
int fetch_ext_or_command_from_evbuffer(struct evbuffer *buf,
|
||||
ext_or_cmd_t **out);
|
||||
#endif
|
||||
|
||||
#ifdef USE_BUFFEREVENTS
|
||||
|
@ -230,6 +230,7 @@ static config_var_t option_vars_[] = {
|
||||
V(ExitPolicyRejectPrivate, BOOL, "1"),
|
||||
V(ExitPortStatistics, BOOL, "0"),
|
||||
V(ExtendAllowPrivateAddresses, BOOL, "0"),
|
||||
VPORT(ExtORPort, LINELIST, NULL),
|
||||
V(ExtraInfoStatistics, BOOL, "1"),
|
||||
V(FallbackDir, LINELIST, NULL),
|
||||
|
||||
@ -5687,6 +5688,14 @@ parse_ports(or_options_t *options, int validate_only,
|
||||
*msg = tor_strdup("Invalid ORPort/ORListenAddress configuration");
|
||||
goto err;
|
||||
}
|
||||
if (parse_port_config(ports,
|
||||
options->ExtORPort_lines, NULL,
|
||||
"ExtOR", CONN_TYPE_EXT_OR_LISTENER,
|
||||
"127.0.0.1", 0,
|
||||
CL_PORT_SERVER_OPTIONS) < 0) {
|
||||
*msg = tor_strdup("Invalid ExtORPort configuration");
|
||||
goto err;
|
||||
}
|
||||
if (parse_port_config(ports,
|
||||
options->DirPort_lines, options->DirListenAddress,
|
||||
"Dir", CONN_TYPE_DIR_LISTENER,
|
||||
|
@ -98,6 +98,7 @@ static smartlist_t *outgoing_addrs = NULL;
|
||||
|
||||
#define CASE_ANY_LISTENER_TYPE \
|
||||
case CONN_TYPE_OR_LISTENER: \
|
||||
case CONN_TYPE_EXT_OR_LISTENER: \
|
||||
case CONN_TYPE_AP_LISTENER: \
|
||||
case CONN_TYPE_DIR_LISTENER: \
|
||||
case CONN_TYPE_CONTROL_LISTENER: \
|
||||
@ -129,6 +130,8 @@ conn_type_to_string(int type)
|
||||
case CONN_TYPE_CPUWORKER: return "CPU worker";
|
||||
case CONN_TYPE_CONTROL_LISTENER: return "Control listener";
|
||||
case CONN_TYPE_CONTROL: return "Control";
|
||||
case CONN_TYPE_EXT_OR: return "Extended OR";
|
||||
case CONN_TYPE_EXT_OR_LISTENER: return "Extended OR listener";
|
||||
default:
|
||||
log_warn(LD_BUG, "unknown connection type %d", type);
|
||||
tor_snprintf(buf, sizeof(buf), "unknown [%d]", type);
|
||||
@ -165,6 +168,12 @@ conn_state_to_string(int type, int state)
|
||||
case OR_CONN_STATE_OPEN: return "open";
|
||||
}
|
||||
break;
|
||||
case CONN_TYPE_EXT_OR:
|
||||
switch (state) {
|
||||
case EXT_OR_CONN_STATE_OPEN: return "open";
|
||||
case EXT_OR_CONN_STATE_FLUSHING: return "flushing final OKAY";
|
||||
}
|
||||
break;
|
||||
case CONN_TYPE_EXIT:
|
||||
switch (state) {
|
||||
case EXIT_CONN_STATE_RESOLVING: return "waiting for dest info";
|
||||
@ -229,6 +238,7 @@ connection_type_uses_bufferevent(connection_t *conn)
|
||||
case CONN_TYPE_DIR:
|
||||
case CONN_TYPE_CONTROL:
|
||||
case CONN_TYPE_OR:
|
||||
case CONN_TYPE_EXT_OR:
|
||||
case CONN_TYPE_CPUWORKER:
|
||||
return 1;
|
||||
default:
|
||||
@ -259,14 +269,18 @@ dir_connection_new(int socket_family)
|
||||
* Set active_circuit_pqueue_last_recalibrated to current cell_ewma tick.
|
||||
*/
|
||||
or_connection_t *
|
||||
or_connection_new(int socket_family)
|
||||
or_connection_new(int type, int socket_family)
|
||||
{
|
||||
or_connection_t *or_conn = tor_malloc_zero(sizeof(or_connection_t));
|
||||
time_t now = time(NULL);
|
||||
connection_init(now, TO_CONN(or_conn), CONN_TYPE_OR, socket_family);
|
||||
tor_assert(type == CONN_TYPE_OR || type == CONN_TYPE_EXT_OR);
|
||||
connection_init(now, TO_CONN(or_conn), type, socket_family);
|
||||
|
||||
or_conn->timestamp_last_added_nonpadding = time(NULL);
|
||||
|
||||
if (type == CONN_TYPE_EXT_OR)
|
||||
connection_or_set_ext_or_identifier(or_conn);
|
||||
|
||||
return or_conn;
|
||||
}
|
||||
|
||||
@ -335,7 +349,8 @@ connection_new(int type, int socket_family)
|
||||
{
|
||||
switch (type) {
|
||||
case CONN_TYPE_OR:
|
||||
return TO_CONN(or_connection_new(socket_family));
|
||||
case CONN_TYPE_EXT_OR:
|
||||
return TO_CONN(or_connection_new(type, socket_family));
|
||||
|
||||
case CONN_TYPE_EXIT:
|
||||
return TO_CONN(edge_connection_new(type, socket_family));
|
||||
@ -377,6 +392,7 @@ connection_init(time_t now, connection_t *conn, int type, int socket_family)
|
||||
|
||||
switch (type) {
|
||||
case CONN_TYPE_OR:
|
||||
case CONN_TYPE_EXT_OR:
|
||||
conn->magic = OR_CONNECTION_MAGIC;
|
||||
break;
|
||||
case CONN_TYPE_EXIT:
|
||||
@ -445,6 +461,7 @@ connection_free_(connection_t *conn)
|
||||
|
||||
switch (conn->type) {
|
||||
case CONN_TYPE_OR:
|
||||
case CONN_TYPE_EXT_OR:
|
||||
tor_assert(conn->magic == OR_CONNECTION_MAGIC);
|
||||
mem = TO_OR_CONN(conn);
|
||||
memlen = sizeof(or_connection_t);
|
||||
@ -575,6 +592,9 @@ connection_free_(connection_t *conn)
|
||||
log_warn(LD_BUG, "called on OR conn with non-zeroed identity_digest");
|
||||
connection_or_remove_from_identity_map(TO_OR_CONN(conn));
|
||||
}
|
||||
if (conn->type == CONN_TYPE_OR || conn->type == CONN_TYPE_EXT_OR)
|
||||
connection_or_remove_from_ext_or_id_map(TO_OR_CONN(conn));
|
||||
|
||||
#ifdef USE_BUFFEREVENTS
|
||||
if (conn->type == CONN_TYPE_OR && TO_OR_CONN(conn)->bucket_cfg) {
|
||||
ev_token_bucket_cfg_free(TO_OR_CONN(conn)->bucket_cfg);
|
||||
@ -638,6 +658,7 @@ connection_about_to_close_connection(connection_t *conn)
|
||||
connection_dir_about_to_close(TO_DIR_CONN(conn));
|
||||
break;
|
||||
case CONN_TYPE_OR:
|
||||
case CONN_TYPE_EXT_OR:
|
||||
connection_or_about_to_close(TO_OR_CONN(conn));
|
||||
break;
|
||||
case CONN_TYPE_AP:
|
||||
@ -1374,6 +1395,9 @@ connection_init_accepted_conn(connection_t *conn,
|
||||
connection_start_reading(conn);
|
||||
|
||||
switch (conn->type) {
|
||||
case CONN_TYPE_EXT_OR:
|
||||
conn->state = EXT_OR_CONN_STATE_OPEN;
|
||||
break;
|
||||
case CONN_TYPE_OR:
|
||||
control_event_or_conn_status(TO_OR_CONN(conn), OR_CONN_EVENT_NEW, 0);
|
||||
rv = connection_tls_start_handshake(TO_OR_CONN(conn), 1);
|
||||
@ -2886,6 +2910,8 @@ connection_handle_read_impl(connection_t *conn)
|
||||
switch (conn->type) {
|
||||
case CONN_TYPE_OR_LISTENER:
|
||||
return connection_handle_listener_read(conn, CONN_TYPE_OR);
|
||||
case CONN_TYPE_EXT_OR_LISTENER:
|
||||
return connection_handle_listener_read(conn, CONN_TYPE_EXT_OR);
|
||||
case CONN_TYPE_AP_LISTENER:
|
||||
case CONN_TYPE_AP_TRANS_LISTENER:
|
||||
case CONN_TYPE_AP_NATD_LISTENER:
|
||||
@ -3918,6 +3944,7 @@ int
|
||||
connection_is_listener(connection_t *conn)
|
||||
{
|
||||
if (conn->type == CONN_TYPE_OR_LISTENER ||
|
||||
conn->type == CONN_TYPE_EXT_OR_LISTENER ||
|
||||
conn->type == CONN_TYPE_AP_LISTENER ||
|
||||
conn->type == CONN_TYPE_AP_TRANS_LISTENER ||
|
||||
conn->type == CONN_TYPE_AP_DNS_LISTENER ||
|
||||
@ -3940,6 +3967,7 @@ connection_state_is_open(connection_t *conn)
|
||||
return 0;
|
||||
|
||||
if ((conn->type == CONN_TYPE_OR && conn->state == OR_CONN_STATE_OPEN) ||
|
||||
(conn->type == CONN_TYPE_EXT_OR) ||
|
||||
(conn->type == CONN_TYPE_AP && conn->state == AP_CONN_STATE_OPEN) ||
|
||||
(conn->type == CONN_TYPE_EXIT && conn->state == EXIT_CONN_STATE_OPEN) ||
|
||||
(conn->type == CONN_TYPE_CONTROL &&
|
||||
@ -4109,6 +4137,8 @@ connection_process_inbuf(connection_t *conn, int package_partial)
|
||||
switch (conn->type) {
|
||||
case CONN_TYPE_OR:
|
||||
return connection_or_process_inbuf(TO_OR_CONN(conn));
|
||||
case CONN_TYPE_EXT_OR:
|
||||
return connection_ext_or_process_inbuf(TO_OR_CONN(conn));
|
||||
case CONN_TYPE_EXIT:
|
||||
case CONN_TYPE_AP:
|
||||
return connection_edge_process_inbuf(TO_EDGE_CONN(conn),
|
||||
@ -4169,6 +4199,8 @@ connection_finished_flushing(connection_t *conn)
|
||||
switch (conn->type) {
|
||||
case CONN_TYPE_OR:
|
||||
return connection_or_finished_flushing(TO_OR_CONN(conn));
|
||||
case CONN_TYPE_EXT_OR:
|
||||
return connection_ext_or_finished_flushing(TO_OR_CONN(conn));
|
||||
case CONN_TYPE_AP:
|
||||
case CONN_TYPE_EXIT:
|
||||
return connection_edge_finished_flushing(TO_EDGE_CONN(conn));
|
||||
@ -4224,6 +4256,7 @@ connection_reached_eof(connection_t *conn)
|
||||
{
|
||||
switch (conn->type) {
|
||||
case CONN_TYPE_OR:
|
||||
case CONN_TYPE_EXT_OR:
|
||||
return connection_or_reached_eof(TO_OR_CONN(conn));
|
||||
case CONN_TYPE_AP:
|
||||
case CONN_TYPE_EXIT:
|
||||
|
@ -19,7 +19,7 @@ const char *conn_type_to_string(int type);
|
||||
const char *conn_state_to_string(int type, int state);
|
||||
|
||||
dir_connection_t *dir_connection_new(int socket_family);
|
||||
or_connection_t *or_connection_new(int socket_family);
|
||||
or_connection_t *or_connection_new(int type, int socket_family);
|
||||
edge_connection_t *edge_connection_new(int type, int socket_family);
|
||||
entry_connection_t *entry_connection_new(int type, int socket_family);
|
||||
control_connection_t *control_connection_new(int socket_family);
|
||||
|
@ -75,6 +75,9 @@ static void connection_or_handle_event_cb(struct bufferevent *bufev,
|
||||
* they form a linked list, with next_with_same_id as the next pointer. */
|
||||
static digestmap_t *orconn_identity_map = NULL;
|
||||
|
||||
/**DOCDOC */
|
||||
static digestmap_t *orconn_ext_or_id_map = NULL;
|
||||
|
||||
/** If conn is listed in orconn_identity_map, remove it, and clear
|
||||
* conn->identity_digest. Otherwise do nothing. */
|
||||
void
|
||||
@ -174,6 +177,52 @@ connection_or_set_identity_digest(or_connection_t *conn, const char *digest)
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
connection_or_remove_from_ext_or_id_map(or_connection_t *conn)
|
||||
{
|
||||
or_connection_t *tmp;
|
||||
if (!orconn_identity_map)
|
||||
orconn_identity_map = digestmap_new();
|
||||
|
||||
tmp = digestmap_remove(orconn_ext_or_id_map, conn->ext_or_conn_id);
|
||||
if (!tor_digest_is_zero(conn->ext_or_conn_id))
|
||||
tor_assert(tmp == conn);
|
||||
|
||||
memset(conn->ext_or_conn_id, 0, EXT_OR_CONN_ID_LEN);
|
||||
}
|
||||
|
||||
|
||||
/*DOCDOC*/
|
||||
void
|
||||
connection_or_clear_ext_or_id_map(void)
|
||||
{
|
||||
digestmap_free(orconn_ext_or_id_map, NULL);
|
||||
}
|
||||
|
||||
/*DOCDOC
|
||||
sets it to a random value */
|
||||
void
|
||||
connection_or_set_ext_or_identifier(or_connection_t *conn)
|
||||
{
|
||||
char random_id[EXT_OR_CONN_ID_LEN];
|
||||
or_connection_t *tmp;
|
||||
|
||||
if (!orconn_ext_or_id_map)
|
||||
orconn_ext_or_id_map = digestmap_new();
|
||||
|
||||
if (!tor_digest_is_zero(conn->ext_or_conn_id))
|
||||
connection_or_remove_from_ext_or_id_map(conn);
|
||||
|
||||
do {
|
||||
crypto_rand(random_id, sizeof(random_id));
|
||||
} while (digestmap_get(orconn_ext_or_id_map, random_id));
|
||||
|
||||
memcpy(conn->ext_or_conn_id, random_id, EXT_OR_CONN_ID_LEN);
|
||||
|
||||
tmp = digestmap_set(orconn_ext_or_id_map, random_id, conn);
|
||||
tor_assert(!tmp);
|
||||
}
|
||||
|
||||
/**************************************************************/
|
||||
|
||||
/** Map from a string describing what a non-open OR connection was doing when
|
||||
@ -228,7 +277,7 @@ connection_or_get_state_description(or_connection_t *orconn,
|
||||
const char *conn_state;
|
||||
char tls_state[256];
|
||||
|
||||
tor_assert(conn->type == CONN_TYPE_OR);
|
||||
tor_assert(conn->type == CONN_TYPE_OR || conn->type == CONN_TYPE_EXT_OR);
|
||||
|
||||
conn_state = conn_state_to_string(conn->type, conn->state);
|
||||
tor_tls_get_state_description(orconn->tls, tls_state, sizeof(tls_state));
|
||||
@ -423,6 +472,23 @@ var_cell_free(var_cell_t *cell)
|
||||
tor_free(cell);
|
||||
}
|
||||
|
||||
/*DOCDOC*/
|
||||
ext_or_cmd_t *
|
||||
ext_or_cmd_new(uint16_t len)
|
||||
{
|
||||
size_t size = STRUCT_OFFSET(ext_or_cmd_t, body) + len;
|
||||
ext_or_cmd_t *cmd = tor_malloc(size);
|
||||
cmd->len = len;
|
||||
return cmd;
|
||||
}
|
||||
|
||||
/*DOCDOC*/
|
||||
void
|
||||
ext_or_cmd_free(ext_or_cmd_t *cmd)
|
||||
{
|
||||
tor_free(cmd);
|
||||
}
|
||||
|
||||
/** We've received an EOF from <b>conn</b>. Mark it for close and return. */
|
||||
int
|
||||
connection_or_reached_eof(or_connection_t *conn)
|
||||
@ -1077,7 +1143,7 @@ connection_or_connect(const tor_addr_t *_addr, uint16_t port,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
conn = or_connection_new(tor_addr_family(&addr));
|
||||
conn = or_connection_new(CONN_TYPE_OR, tor_addr_family(&addr));
|
||||
|
||||
/*
|
||||
* Set up conn so it's got all the data we need to remember for channels
|
||||
@ -1470,7 +1536,8 @@ connection_or_handle_event_cb(struct bufferevent *bufev, short event,
|
||||
int
|
||||
connection_or_nonopen_was_started_here(or_connection_t *conn)
|
||||
{
|
||||
tor_assert(conn->base_.type == CONN_TYPE_OR);
|
||||
tor_assert(conn->base_.type == CONN_TYPE_OR ||
|
||||
conn->base_.type == CONN_TYPE_EXT_OR);
|
||||
if (!conn->tls)
|
||||
return 1; /* it's still in proxy states or something */
|
||||
if (conn->handshake_state)
|
||||
@ -2365,3 +2432,132 @@ connection_or_send_authenticate_cell(or_connection_t *conn, int authtype)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*DOCDOC*/
|
||||
static int
|
||||
connection_fetch_ext_or_cmd_from_buf(connection_t *conn, ext_or_cmd_t **out)
|
||||
{
|
||||
IF_HAS_BUFFEREVENT(conn, {
|
||||
struct evbuffer *input = bufferevent_get_input(conn->bufev);
|
||||
return fetch_ext_or_command_from_evbuffer(input, out);
|
||||
}) ELSE_IF_NO_BUFFEREVENT {
|
||||
return fetch_ext_or_command_from_buf(conn->inbuf, out);
|
||||
}
|
||||
}
|
||||
|
||||
/*DOCDOC*/
|
||||
static int
|
||||
connection_write_ext_or_command(connection_t *conn,
|
||||
uint16_t command,
|
||||
const char *body,
|
||||
size_t bodylen)
|
||||
{
|
||||
char header[4];
|
||||
if (bodylen > UINT16_MAX)
|
||||
return -1;
|
||||
set_uint16(header, htons(command));
|
||||
set_uint16(header+2, htons(bodylen));
|
||||
connection_write_to_buf(header, 4, conn);
|
||||
if (bodylen) {
|
||||
tor_assert(body);
|
||||
connection_write_to_buf(body, bodylen, conn);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*DOCDOC*/
|
||||
static void
|
||||
connection_ext_or_transition(or_connection_t *conn)
|
||||
{
|
||||
tor_assert(conn->base_.type == CONN_TYPE_EXT_OR);
|
||||
|
||||
conn->base_.type = CONN_TYPE_OR;
|
||||
control_event_or_conn_status(conn, OR_CONN_EVENT_NEW, 0);
|
||||
connection_tls_start_handshake(conn, 1);
|
||||
}
|
||||
|
||||
/*XXXX make these match the spec .*/
|
||||
#define EXT_OR_CMD_DONE 0x0001
|
||||
#define EXT_OR_CMD_USERADDR 0x0002
|
||||
#define EXT_OR_CMD_WANT_CONTROL 0x0003
|
||||
#define EXT_OR_CMD_OKAY 0x1001
|
||||
|
||||
/*DOCDOC*/
|
||||
int
|
||||
connection_ext_or_process_inbuf(or_connection_t *or_conn)
|
||||
{
|
||||
connection_t *conn = TO_CONN(or_conn);
|
||||
ext_or_cmd_t *command;
|
||||
int r;
|
||||
|
||||
while (1) {
|
||||
command = NULL;
|
||||
r = connection_fetch_ext_or_cmd_from_buf(conn, &command);
|
||||
if (r < 0)
|
||||
return -1;
|
||||
else if (r == 0)
|
||||
return 0; /* need to wait for more data */
|
||||
|
||||
/* Got a command! */
|
||||
tor_assert(command);
|
||||
|
||||
if (command->cmd == EXT_OR_CMD_DONE) {
|
||||
if (connection_get_inbuf_len(conn)) {
|
||||
/* The inbuf isn't empty; the client is misbehaving. */
|
||||
goto err;
|
||||
}
|
||||
connection_write_ext_or_command(conn, EXT_OR_CMD_OKAY, NULL, 0);
|
||||
|
||||
/* can't transition immediately; need to flush first. */
|
||||
conn->state = EXT_OR_CONN_STATE_FLUSHING;
|
||||
connection_stop_reading(conn);
|
||||
} else if (command->cmd == EXT_OR_CMD_USERADDR) {
|
||||
/* Copy address string. */
|
||||
tor_addr_t addr;
|
||||
uint16_t port;
|
||||
char *addr_str;
|
||||
char *address_part=NULL;
|
||||
int res;
|
||||
addr_str = tor_malloc(command->len + 1);
|
||||
memcpy(addr_str, command->body, command->len);
|
||||
addr_str[command->len] = 0;
|
||||
|
||||
res = tor_addr_port_split(LOG_INFO, addr_str, &address_part, &port);
|
||||
tor_free(addr_str);
|
||||
if (res<0)
|
||||
goto err;
|
||||
|
||||
res = tor_addr_parse(&addr, address_part);
|
||||
tor_free(address_part);
|
||||
if (res<0)
|
||||
goto err;
|
||||
|
||||
/* record the address */
|
||||
tor_addr_copy(&conn->addr, &addr);
|
||||
conn->port = port;
|
||||
} else if (command->cmd == EXT_OR_CMD_WANT_CONTROL) {
|
||||
char response[128];
|
||||
char *cp;
|
||||
memcpy(response, or_conn->ext_or_conn_id, EXT_OR_CONN_ID_LEN);
|
||||
cp = response+EXT_OR_CONN_ID_LEN;
|
||||
/* XXXX write the TransportControlPort; advance cp. */
|
||||
connection_write_ext_or_command(conn, EXT_OR_CMD_OKAY, response,
|
||||
cp-response);
|
||||
}
|
||||
|
||||
ext_or_cmd_free(command);
|
||||
}
|
||||
|
||||
err:
|
||||
ext_or_cmd_free(command);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
connection_ext_or_finished_flushing(or_connection_t *conn)
|
||||
{
|
||||
if (conn->base_.state == EXT_OR_CONN_STATE_FLUSHING) {
|
||||
connection_start_reading(TO_CONN(conn));
|
||||
connection_ext_or_transition(conn);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -95,5 +95,14 @@ void var_cell_free(var_cell_t *cell);
|
||||
/** DOCDOC */
|
||||
#define MIN_LINK_PROTO_FOR_WIDE_CIRC_IDS 4
|
||||
|
||||
ext_or_cmd_t *ext_or_cmd_new(uint16_t len);
|
||||
void ext_or_cmd_free(ext_or_cmd_t *cmd);
|
||||
void connection_or_set_ext_or_identifier(or_connection_t *conn);
|
||||
void connection_or_remove_from_ext_or_id_map(or_connection_t *conn);
|
||||
void connection_or_clear_ext_or_id_map(void);
|
||||
|
||||
int connection_ext_or_finished_flushing(or_connection_t *conn);
|
||||
int connection_ext_or_process_inbuf(or_connection_t *or_conn);
|
||||
|
||||
#endif
|
||||
|
||||
|
31
src/or/or.h
31
src/or/or.h
@ -228,8 +228,13 @@ typedef enum {
|
||||
#define CONN_TYPE_AP_NATD_LISTENER 14
|
||||
/** Type for sockets listening for DNS requests. */
|
||||
#define CONN_TYPE_AP_DNS_LISTENER 15
|
||||
#define CONN_TYPE_MAX_ 15
|
||||
/* !!!! If CONN_TYPE_MAX_ is ever over 15, we must grow the type field in
|
||||
|
||||
/** DOCDOC */
|
||||
#define CONN_TYPE_EXT_OR 16
|
||||
#define CONN_TYPE_EXT_OR_LISTENER 17
|
||||
|
||||
#define CONN_TYPE_MAX_ 17
|
||||
/* !!!! If _CONN_TYPE_MAX is ever over 31, we must grow the type field in
|
||||
* connection_t. */
|
||||
|
||||
/* Proxy client types */
|
||||
@ -309,6 +314,12 @@ typedef enum {
|
||||
#define OR_CONN_STATE_OPEN 8
|
||||
#define OR_CONN_STATE_MAX_ 8
|
||||
|
||||
/*DOCDOC*/
|
||||
#define _EXT_OR_CONN_STATE_MIN 1
|
||||
#define EXT_OR_CONN_STATE_OPEN 1
|
||||
#define EXT_OR_CONN_STATE_FLUSHING 2
|
||||
#define _EXT_OR_CONN_STATE_MAX 2
|
||||
|
||||
#define EXIT_CONN_STATE_MIN_ 1
|
||||
/** State for an exit connection: waiting for response from DNS farm. */
|
||||
#define EXIT_CONN_STATE_RESOLVING 1
|
||||
@ -1082,6 +1093,13 @@ typedef struct var_cell_t {
|
||||
uint8_t payload[FLEXIBLE_ARRAY_MEMBER];
|
||||
} var_cell_t;
|
||||
|
||||
/* DOCDOC */
|
||||
typedef struct ext_or_cmd_t {
|
||||
uint16_t cmd;
|
||||
uint16_t len;
|
||||
char body[FLEXIBLE_ARRAY_MEMBER];
|
||||
} ext_or_cmd_t;
|
||||
|
||||
/** A cell as packed for writing to the network. */
|
||||
typedef struct packed_cell_t {
|
||||
/** Next cell queued on this circuit. */
|
||||
@ -1163,7 +1181,7 @@ typedef struct connection_t {
|
||||
* *_CONNECTION_MAGIC. */
|
||||
|
||||
uint8_t state; /**< Current state of this connection. */
|
||||
unsigned int type:4; /**< What kind of connection is this? */
|
||||
unsigned int type:5; /**< What kind of connection is this? */
|
||||
unsigned int purpose:5; /**< Only used for DIR and EXIT types currently. */
|
||||
|
||||
/* The next fields are all one-bit booleans. Some are only applicable to
|
||||
@ -1405,6 +1423,9 @@ typedef struct or_handshake_state_t {
|
||||
/**@}*/
|
||||
} or_handshake_state_t;
|
||||
|
||||
/* DOCDOC */
|
||||
#define EXT_OR_CONN_ID_LEN 20
|
||||
|
||||
/** Subtype of connection_t for an "OR connection" -- that is, one that speaks
|
||||
* cells over TLS. */
|
||||
typedef struct or_connection_t {
|
||||
@ -1413,6 +1434,8 @@ typedef struct or_connection_t {
|
||||
/** Hash of the public RSA key for the other side's identity key, or zeroes
|
||||
* if the other side hasn't shown us a valid identity key. */
|
||||
char identity_digest[DIGEST_LEN];
|
||||
/*DOCDOC*/
|
||||
char ext_or_conn_id[EXT_OR_CONN_ID_LEN];
|
||||
char *nickname; /**< Nickname of OR on other side (if any). */
|
||||
|
||||
tor_tls_t *tls; /**< TLS connection state. */
|
||||
@ -3428,6 +3451,8 @@ typedef struct {
|
||||
char *User; /**< Name of user to run Tor as. */
|
||||
char *Group; /**< Name of group to run Tor as. */
|
||||
config_line_t *ORPort_lines; /**< Ports to listen on for OR connections. */
|
||||
/** Ports to listen on for extended OR connections. */
|
||||
config_line_t *ExtORPort_lines;
|
||||
/** Ports to listen on for SOCKS connections. */
|
||||
config_line_t *SocksPort_lines;
|
||||
/** Ports to listen on for transparent pf/netfilter connections. */
|
||||
|
Loading…
Reference in New Issue
Block a user