From 8bf0382b220b31605fb5a542f36a842bdd7a6ed0 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Fri, 16 Mar 2012 09:40:44 -0400 Subject: [PATCH] Skeleton ExtORPort implementation. Needs testing, documentation. Does not implement TransportControlPort yet. --- src/or/buffers.c | 48 ++++++++++ src/or/buffers.h | 4 + src/or/config.c | 9 ++ src/or/connection.c | 39 +++++++- src/or/connection.h | 2 +- src/or/connection_or.c | 202 ++++++++++++++++++++++++++++++++++++++++- src/or/connection_or.h | 9 ++ src/or/or.h | 31 ++++++- 8 files changed, 334 insertions(+), 10 deletions(-) diff --git a/src/or/buffers.c b/src/or/buffers.c index cc5890416f..a79d17bbea 100644 --- a/src/or/buffers.c +++ b/src/or/buffers.c @@ -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 datalen bytes of data in * data. Instead of removing data from the buffer, we set diff --git a/src/or/buffers.h b/src/or/buffers.h index 910494a874..50ac3dc3f2 100644 --- a/src/or/buffers.h +++ b/src/or/buffers.h @@ -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 diff --git a/src/or/config.c b/src/or/config.c index 2218e5078b..afdee3d3d4 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -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, diff --git a/src/or/connection.c b/src/or/connection.c index 6a3cc7bec4..130b1ecefb 100644 --- a/src/or/connection.c +++ b/src/or/connection.c @@ -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: diff --git a/src/or/connection.h b/src/or/connection.h index 3e656ec06e..5ca8ca3430 100644 --- a/src/or/connection.h +++ b/src/or/connection.h @@ -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); diff --git a/src/or/connection_or.c b/src/or/connection_or.c index 3616363505..a6d1a8d7ec 100644 --- a/src/or/connection_or.c +++ b/src/or/connection_or.c @@ -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 conn. 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; +} diff --git a/src/or/connection_or.h b/src/or/connection_or.h index 85e68f1a33..a80871d5c9 100644 --- a/src/or/connection_or.h +++ b/src/or/connection_or.h @@ -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 diff --git a/src/or/or.h b/src/or/or.h index 06363fa360..2811f66e1d 100644 --- a/src/or/or.h +++ b/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. */