mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-20 10:12:15 +01:00
Forward-port new reasons; clean up code more; add code to convert new reasons to SOCKS5 reply codes; add code to convert errnos to reasons. New code still needs to get invoked.
svn:r3719
This commit is contained in:
parent
59ec8ca3f1
commit
4ddf768a4f
12
doc/TODO
12
doc/TODO
@ -73,17 +73,15 @@ R . HTTPS proxy for OR CONNECT stuff. (For outgoing SSL connections to
|
||||
o If a version is later than the last in its series, but a version
|
||||
in the next series is recommended, that doesn't mean it's bad.
|
||||
- Do end reasons better
|
||||
- Start using RESOURCELIMIT more.
|
||||
- Try to use MISC a lot less.
|
||||
. Start using RESOURCELIMIT more.
|
||||
. Try to use MISC a lot less.
|
||||
- bug: if the exit node fails to create a socket (e.g. because it
|
||||
has too many open), we will get a generic stream end response.
|
||||
- niels's "did it fail because conn refused or timeout or what"
|
||||
. niels's "did it fail because conn refused or timeout or what"
|
||||
relay end feature.
|
||||
N - Realize that unrecognized end reasons are probably features rather than
|
||||
o Realize that unrecognized end reasons are probably features rather than
|
||||
bugs. (backport to 009x)
|
||||
N - Start recognizing, but maybe not yet generating, more reasons and
|
||||
needed -- aim to eliminate misc. (backport to 009x)
|
||||
N - Feed end reason back into SOCK5 as reasonable.
|
||||
N . Feed end reason back into SOCK5 as reasonable.
|
||||
R o cache .foo.exit names better, or differently, or not.
|
||||
N - make !advertised_server_mode() ORs fetch dirs less often.
|
||||
N - Clean up NT service code even more. Document it. Enable it by default.
|
||||
|
@ -472,7 +472,7 @@ int fetch_from_buf_socks(buf_t *buf, socks_request_t *req) {
|
||||
if (!nummethods || !memchr(buf->mem+2, 0, nummethods)) {
|
||||
log_fn(LOG_WARN,"socks5: offered methods don't include 'no auth'. Rejecting.");
|
||||
req->replylen = 2; /* 2 bytes of response */
|
||||
req->reply[0] = 5; /* socks5 reply */
|
||||
req->reply[0] = 5;
|
||||
req->reply[1] = '\xFF'; /* reject all methods */
|
||||
return -1;
|
||||
}
|
||||
@ -480,7 +480,7 @@ int fetch_from_buf_socks(buf_t *buf, socks_request_t *req) {
|
||||
|
||||
req->replylen = 2; /* 2 bytes of response */
|
||||
req->reply[0] = 5; /* socks5 reply */
|
||||
req->reply[1] = 0; /* choose the 'no auth' method */
|
||||
req->reply[1] = SOCKS5_SUCCEEDED;
|
||||
req->socks_version = 5; /* remember that we've already negotiated auth */
|
||||
log_fn(LOG_DEBUG,"socks5: accepted method 0");
|
||||
return 0;
|
||||
|
@ -914,7 +914,7 @@ loop_again:
|
||||
connection_close_immediate(conn); /* Don't flush; connection is dead. */
|
||||
if (CONN_IS_EDGE(conn)) {
|
||||
connection_edge_end(conn, (char)(connection_state_is_open(conn) ?
|
||||
END_STREAM_REASON_MISC : END_STREAM_REASON_CONNECTFAILED),
|
||||
END_STREAM_REASON_MISC : END_STREAM_REASON_CONNECTREFUSED),
|
||||
conn->cpath_layer);
|
||||
}
|
||||
connection_mark_for_close(conn);
|
||||
@ -1092,7 +1092,7 @@ int connection_handle_write(connection_t *conn) {
|
||||
if (!ERRNO_IS_CONN_EINPROGRESS(e)) {
|
||||
log_fn(LOG_INFO,"in-progress connect failed. Removing.");
|
||||
if (CONN_IS_EDGE(conn))
|
||||
connection_edge_end(conn, END_STREAM_REASON_CONNECTFAILED,
|
||||
connection_edge_end(conn, END_STREAM_REASON_CONNECTREFUSED,
|
||||
conn->cpath_layer);
|
||||
|
||||
connection_close_immediate(conn);
|
||||
|
@ -875,21 +875,21 @@ void connection_ap_handshake_socks_resolved(connection_t *conn,
|
||||
/* SOCKS5 */
|
||||
buf[0] = 0x05; /* version */
|
||||
if (answer_type == RESOLVED_TYPE_IPV4 && answer_len == 4) {
|
||||
buf[1] = 0; /* succeeded */
|
||||
buf[1] = SOCKS5_SUCCEEDED;
|
||||
buf[2] = 0; /* reserved */
|
||||
buf[3] = 0x01; /* IPv4 address type */
|
||||
memcpy(buf+4, answer, 4); /* address */
|
||||
set_uint16(buf+8, 0); /* port == 0. */
|
||||
replylen = 10;
|
||||
} else if (answer_type == RESOLVED_TYPE_IPV6 && answer_len == 16) {
|
||||
buf[1] = 0; /* succeeded */
|
||||
buf[1] = SOCKS5_SUCCEEDED;
|
||||
buf[2] = 0; /* reserved */
|
||||
buf[3] = 0x04; /* IPv6 address type */
|
||||
memcpy(buf+4, answer, 16); /* address */
|
||||
set_uint16(buf+20, 0); /* port == 0. */
|
||||
replylen = 22;
|
||||
} else {
|
||||
buf[1] = 0x04; /* host unreachable */
|
||||
buf[1] = SOCKS5_HOST_UNREACHABLE;
|
||||
memset(buf+2, 0, 8);
|
||||
replylen = 10;
|
||||
}
|
||||
@ -1156,7 +1156,8 @@ connection_exit_connect(connection_t *conn) {
|
||||
log_fn(LOG_DEBUG,"about to try connecting");
|
||||
switch (connection_connect(conn, conn->address, addr, port)) {
|
||||
case -1:
|
||||
connection_edge_end(conn, END_STREAM_REASON_CONNECTFAILED, conn->cpath_layer);
|
||||
connection_edge_end(conn, END_STREAM_REASON_CONNECTREFUSED,
|
||||
conn->cpath_layer);
|
||||
circuit_detach_stream(circuit_get_by_conn(conn), conn);
|
||||
connection_free(conn);
|
||||
return;
|
||||
|
26
src/or/or.h
26
src/or/or.h
@ -413,16 +413,18 @@ typedef enum {
|
||||
#define RELAY_COMMAND_RENDEZVOUS_ESTABLISHED 39
|
||||
#define RELAY_COMMAND_INTRODUCE_ACK 40
|
||||
|
||||
#define _MIN_END_STREAM_REASON 1
|
||||
#define END_STREAM_REASON_MISC 1
|
||||
#define END_STREAM_REASON_RESOLVEFAILED 2
|
||||
#define END_STREAM_REASON_CONNECTFAILED 3
|
||||
#define END_STREAM_REASON_CONNECTREFUSED 3
|
||||
#define END_STREAM_REASON_EXITPOLICY 4
|
||||
#define END_STREAM_REASON_DESTROY 5
|
||||
#define END_STREAM_REASON_DONE 6
|
||||
#define END_STREAM_REASON_TIMEOUT 7
|
||||
#define END_STREAM_REASON_RESOURCELIMIT 8
|
||||
#define _MAX_END_STREAM_REASON 8
|
||||
/* 8 is unallocated. */
|
||||
#define END_STREAM_REASON_HIBERNATING 9
|
||||
#define END_STREAM_REASON_INTERNAL 10
|
||||
#define END_STREAM_REASON_RESOURCELIMIT 11
|
||||
#define END_STREAM_REASON_CONNRESET 12
|
||||
|
||||
#define RESOLVED_TYPE_IPV4 4
|
||||
#define RESOLVED_TYPE_IPV6 6
|
||||
@ -466,6 +468,18 @@ typedef enum {
|
||||
|
||||
#define SOCKS4_NETWORK_LEN 8
|
||||
|
||||
typedef enum {
|
||||
SOCKS5_SUCCEEDED = 0x00,
|
||||
SOCKS5_GENERAL_ERROR = 0x01,
|
||||
SOCKS5_NOT_ALLOWED = 0x02,
|
||||
SOCKS5_NET_UNREACHABLE = 0x03,
|
||||
SOCKS5_HOST_UNREACHABLE = 0x04,
|
||||
SOCKS5_CONNECTION_REFUSED = 0x05,
|
||||
SOCKS5_TTL_EXPIRED = 0x06,
|
||||
SOCKS5_COMMAND_NOT_SUPPORTED = 0x07,
|
||||
SOCKS5_ADDRESS_TYPE_NOT_SUPPORTED = 0x08,
|
||||
} socks5_reply_status_t;
|
||||
|
||||
/*
|
||||
* Relay payload:
|
||||
* Relay command [1 byte]
|
||||
@ -1512,6 +1526,10 @@ int connection_edge_send_command(connection_t *fromconn, circuit_t *circ,
|
||||
size_t payload_len, crypt_path_t *cpath_layer);
|
||||
int connection_edge_package_raw_inbuf(connection_t *conn, int package_partial);
|
||||
void connection_edge_consider_sending_sendme(connection_t *conn);
|
||||
socks5_reply_status_t connection_edge_end_reason_sock5_response(char *payload, uint16_t length);
|
||||
int errno_to_end_reasaon(int e);
|
||||
|
||||
|
||||
|
||||
extern uint64_t stats_n_data_cells_packaged;
|
||||
extern uint64_t stats_n_data_bytes_packaged;
|
||||
|
104
src/or/relay.c
104
src/or/relay.c
@ -457,26 +457,105 @@ int connection_edge_send_command(connection_t *fromconn, circuit_t *circ,
|
||||
* why the stream is closing.
|
||||
*/
|
||||
static const char *
|
||||
connection_edge_end_reason(char *payload, uint16_t length) {
|
||||
connection_edge_end_reason_str(char *payload, uint16_t length) {
|
||||
if (length < 1) {
|
||||
log_fn(LOG_WARN,"End cell arrived with length 0. Should be at least 1.");
|
||||
return "MALFORMED";
|
||||
}
|
||||
if (*payload < _MIN_END_STREAM_REASON || *payload > _MAX_END_STREAM_REASON) {
|
||||
log_fn(LOG_WARN,"Reason for ending (%d) not recognized.",*payload);
|
||||
return "MALFORMED";
|
||||
}
|
||||
switch (*payload) {
|
||||
case END_STREAM_REASON_MISC: return "misc error";
|
||||
case END_STREAM_REASON_RESOLVEFAILED: return "resolve failed";
|
||||
case END_STREAM_REASON_CONNECTFAILED: return "connect failed";
|
||||
case END_STREAM_REASON_CONNECTREFUSED: return "connection refused";
|
||||
case END_STREAM_REASON_EXITPOLICY: return "exit policy failed";
|
||||
case END_STREAM_REASON_DESTROY: return "destroyed";
|
||||
case END_STREAM_REASON_DONE: return "closed normally";
|
||||
case END_STREAM_REASON_TIMEOUT: return "gave up (timeout)";
|
||||
case END_STREAM_REASON_HIBERNATING: return "server is hibernating";
|
||||
case END_STREAM_REASON_INTERNAL: return "internal error at server";
|
||||
case END_STREAM_REASON_RESOURCELIMIT: return "server out of resources";
|
||||
case END_STREAM_REASON_CONNRESET: return "connection reset";
|
||||
default:
|
||||
log_fn(LOG_WARN,"Reason for ending (%d) not recognized.",*payload);
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
socks5_reply_status_t
|
||||
connection_edge_end_reason_sock5_response(char *payload, uint16_t length) {
|
||||
if (length < 1) {
|
||||
log_fn(LOG_WARN,"End cell arrived with length 0. Should be at least 1.");
|
||||
return SOCKS5_GENERAL_ERROR;
|
||||
}
|
||||
switch (*payload) {
|
||||
case END_STREAM_REASON_MISC:
|
||||
return SOCKS5_GENERAL_ERROR;
|
||||
case END_STREAM_REASON_RESOLVEFAILED:
|
||||
return SOCKS5_HOST_UNREACHABLE;
|
||||
case END_STREAM_REASON_CONNECTREFUSED:
|
||||
return SOCKS5_CONNECTION_REFUSED;
|
||||
case END_STREAM_REASON_EXITPOLICY:
|
||||
return SOCKS5_CONNECTION_REFUSED;
|
||||
case END_STREAM_REASON_DESTROY:
|
||||
return SOCKS5_GENERAL_ERROR;
|
||||
case END_STREAM_REASON_DONE:
|
||||
return SOCKS5_SUCCEEDED;
|
||||
case END_STREAM_REASON_TIMEOUT:
|
||||
return SOCKS5_TTL_EXPIRED;
|
||||
case END_STREAM_REASON_RESOURCELIMIT:
|
||||
return SOCKS5_GENERAL_ERROR;
|
||||
case END_STREAM_REASON_HIBERNATING:
|
||||
return SOCKS5_GENERAL_ERROR;
|
||||
case END_STREAM_REASON_INTERNAL:
|
||||
return SOCKS5_GENERAL_ERROR;
|
||||
case END_STREAM_REASON_CONNRESET:
|
||||
return SOCKS5_CONNECTION_REFUSED;
|
||||
default:
|
||||
log_fn(LOG_WARN,"Reason for ending (%d) not recognized.",*payload);
|
||||
return SOCKS5_GENERAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MS_WINDOWS
|
||||
#define E_CASE(s) case s: case WSA ## s
|
||||
#define W_CASE(s) case s:
|
||||
#else
|
||||
#define E_CASE(s) case s
|
||||
#define W_CASE(s)
|
||||
#endif
|
||||
|
||||
int
|
||||
errno_to_end_reasaon(int e)
|
||||
{
|
||||
switch (e) {
|
||||
E_CASE(EPIPE):
|
||||
return END_STREAM_REASON_DONE;
|
||||
E_CASE(EBADF):
|
||||
E_CASE(EFAULT):
|
||||
E_CASE(EINVAL):
|
||||
E_CASE(EISCONN):
|
||||
E_CASE(ENOTSOCK):
|
||||
E_CASE(EPROTONOSUPPORT):
|
||||
E_CASE(EAFNOSUPPORT):
|
||||
E_CASE(EACCES):
|
||||
E_CASE(ENOTCONN):
|
||||
E_CASE(ENETUNREACH):
|
||||
return END_STREAM_REASON_INTERNAL;
|
||||
E_CASE(ECONNREFUSED):
|
||||
return END_STREAM_REASON_CONNECTREFUSED;
|
||||
E_CASE(ECONNRESET):
|
||||
return END_STREAM_REASON_CONNRESET;
|
||||
E_CASE(ETIMEDOUT):
|
||||
return END_STREAM_REASON_TIMEOUT;
|
||||
E_CASE(ENOBUFS):
|
||||
E_CASE(ENOMEM):
|
||||
E_CASE(ENFILE):
|
||||
E_CASE(EMFILE):
|
||||
return END_STREAM_REASON_RESOURCELIMIT;
|
||||
default:
|
||||
log_fn(LOG_INFO, "Didn't recognize errno %d (%s); telling the OP that we are ending a stream for 'misc' reason.",
|
||||
e, tor_socket_strerror(e));
|
||||
return END_STREAM_REASON_MISC;
|
||||
}
|
||||
tor_assert(0);
|
||||
return "";
|
||||
}
|
||||
|
||||
/** How many times will I retry a stream that fails due to DNS
|
||||
@ -567,7 +646,8 @@ connection_edge_process_relay_cell_not_open(
|
||||
}
|
||||
}
|
||||
log_fn(LOG_INFO,"Edge got end (%s) before we're connected. Marking for close.",
|
||||
connection_edge_end_reason(cell->payload+RELAY_HEADER_SIZE, rh->length));
|
||||
connection_edge_end_reason_str(cell->payload+RELAY_HEADER_SIZE,
|
||||
rh->length));
|
||||
if (CIRCUIT_IS_ORIGIN(circ))
|
||||
circuit_log_path(LOG_INFO,circ);
|
||||
conn->has_sent_end = 1; /* we just got an 'end', don't need to send one */
|
||||
@ -722,13 +802,15 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
|
||||
case RELAY_COMMAND_END:
|
||||
if (!conn) {
|
||||
log_fn(LOG_INFO,"end cell (%s) dropped, unknown stream.",
|
||||
connection_edge_end_reason(cell->payload+RELAY_HEADER_SIZE, rh.length));
|
||||
connection_edge_end_reason_str(cell->payload+RELAY_HEADER_SIZE,
|
||||
rh.length));
|
||||
return 0;
|
||||
}
|
||||
/* XXX add to this log_fn the exit node's nickname? */
|
||||
log_fn(LOG_INFO,"%d: end cell (%s) for stream %d. Removing stream. Size %d.",
|
||||
conn->s,
|
||||
connection_edge_end_reason(cell->payload+RELAY_HEADER_SIZE, rh.length),
|
||||
connection_edge_end_reason_str(cell->payload+RELAY_HEADER_SIZE,
|
||||
rh.length),
|
||||
conn->stream_id, (int)conn->stream_size);
|
||||
|
||||
#ifdef HALF_OPEN
|
||||
|
Loading…
Reference in New Issue
Block a user