diff options
author | Nick Mathewson <nickm@torproject.org> | 2005-03-01 22:16:15 +0000 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2005-03-01 22:16:15 +0000 |
commit | 4ddf768a4fc98bfc2e18a7076bd0397967e3de5e (patch) | |
tree | 8049eb9dec027b429757925cce70f724c8151a8e /src/or | |
parent | 59ec8ca3f1bbc20a982d1047666cd9483bb07704 (diff) | |
download | tor-4ddf768a4fc98bfc2e18a7076bd0397967e3de5e.tar.gz tor-4ddf768a4fc98bfc2e18a7076bd0397967e3de5e.zip |
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
Diffstat (limited to 'src/or')
-rw-r--r-- | src/or/buffers.c | 4 | ||||
-rw-r--r-- | src/or/connection.c | 4 | ||||
-rw-r--r-- | src/or/connection_edge.c | 9 | ||||
-rw-r--r-- | src/or/or.h | 26 | ||||
-rw-r--r-- | src/or/relay.c | 108 |
5 files changed, 126 insertions, 25 deletions
diff --git a/src/or/buffers.c b/src/or/buffers.c index 0abcd9a828..a6e765eace 100644 --- a/src/or/buffers.c +++ b/src/or/buffers.c @@ -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; diff --git a/src/or/connection.c b/src/or/connection.c index f44185ac2d..79c98fd280 100644 --- a/src/or/connection.c +++ b/src/or/connection.c @@ -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); diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c index cfee2ac5e5..937b282e10 100644 --- a/src/or/connection_edge.c +++ b/src/or/connection_edge.c @@ -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; diff --git a/src/or/or.h b/src/or/or.h index 55dce9edbf..821d4e08a5 100644 --- a/src/or/or.h +++ b/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; diff --git a/src/or/relay.c b/src/or/relay.c index 866c3d8757..10be51228b 100644 --- a/src/or/relay.c +++ b/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,14 +802,16 @@ 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), - conn->stream_id, (int)conn->stream_size); + conn->s, + connection_edge_end_reason_str(cell->payload+RELAY_HEADER_SIZE, + rh.length), + conn->stream_id, (int)conn->stream_size); #ifdef HALF_OPEN conn->done_sending = 1; |