reasons.c
上传用户:awang829
上传日期:2019-07-14
资源大小:2356k
文件大小:11k
源码类别:

网络

开发平台:

Unix_Linux

  1. /* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
  2.  * Copyright (c) 2007-2009, The Tor Project, Inc. */
  3. /* See LICENSE for licensing information */
  4. /**
  5.  * file reasons.c
  6.  * brief Convert circuit, stream, and orconn error reasons to and/or from
  7.  * strings and errno values.
  8.  **/
  9. #include "or.h"
  10. /***************************** Edge (stream) reasons **********************/
  11. /** Convert the reason for ending a stream <b>reason</b> into the format used
  12.  * in STREAM events. Return NULL if the reason is unrecognized. */
  13. const char *
  14. stream_end_reason_to_control_string(int reason)
  15. {
  16.   reason &= END_STREAM_REASON_MASK;
  17.   switch (reason) {
  18.     case END_STREAM_REASON_MISC: return "MISC";
  19.     case END_STREAM_REASON_RESOLVEFAILED: return "RESOLVEFAILED";
  20.     case END_STREAM_REASON_CONNECTREFUSED: return "CONNECTREFUSED";
  21.     case END_STREAM_REASON_EXITPOLICY: return "EXITPOLICY";
  22.     case END_STREAM_REASON_DESTROY: return "DESTROY";
  23.     case END_STREAM_REASON_DONE: return "DONE";
  24.     case END_STREAM_REASON_TIMEOUT: return "TIMEOUT";
  25.     case END_STREAM_REASON_HIBERNATING: return "HIBERNATING";
  26.     case END_STREAM_REASON_INTERNAL: return "INTERNAL";
  27.     case END_STREAM_REASON_RESOURCELIMIT: return "RESOURCELIMIT";
  28.     case END_STREAM_REASON_CONNRESET: return "CONNRESET";
  29.     case END_STREAM_REASON_TORPROTOCOL: return "TORPROTOCOL";
  30.     case END_STREAM_REASON_NOTDIRECTORY: return "NOTDIRECTORY";
  31.     case END_STREAM_REASON_CANT_ATTACH: return "CANT_ATTACH";
  32.     case END_STREAM_REASON_NET_UNREACHABLE: return "NET_UNREACHABLE";
  33.     case END_STREAM_REASON_SOCKSPROTOCOL: return "SOCKS_PROTOCOL";
  34.     default: return NULL;
  35.   }
  36. }
  37. /** Translate <b>reason</b>, which came from a relay 'end' cell,
  38.  * into a static const string describing why the stream is closing.
  39.  * <b>reason</b> is -1 if no reason was provided.
  40.  */
  41. const char *
  42. stream_end_reason_to_string(int reason)
  43. {
  44.   switch (reason) {
  45.     case -1:
  46.       log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
  47.              "End cell arrived with length 0. Should be at least 1.");
  48.       return "MALFORMED";
  49.     case END_STREAM_REASON_MISC:           return "misc error";
  50.     case END_STREAM_REASON_RESOLVEFAILED:  return "resolve failed";
  51.     case END_STREAM_REASON_CONNECTREFUSED: return "connection refused";
  52.     case END_STREAM_REASON_EXITPOLICY:     return "exit policy failed";
  53.     case END_STREAM_REASON_DESTROY:        return "destroyed";
  54.     case END_STREAM_REASON_DONE:           return "closed normally";
  55.     case END_STREAM_REASON_TIMEOUT:        return "gave up (timeout)";
  56.     case END_STREAM_REASON_HIBERNATING:    return "server is hibernating";
  57.     case END_STREAM_REASON_INTERNAL:       return "internal error at server";
  58.     case END_STREAM_REASON_RESOURCELIMIT:  return "server out of resources";
  59.     case END_STREAM_REASON_CONNRESET:      return "connection reset";
  60.     case END_STREAM_REASON_TORPROTOCOL:    return "Tor protocol error";
  61.     case END_STREAM_REASON_NOTDIRECTORY:   return "not a directory";
  62.     default:
  63.       log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
  64.              "Reason for ending (%d) not recognized.",reason);
  65.       return "unknown";
  66.   }
  67. }
  68. /** Translate <b>reason</b> (as from a relay 'end' cell) into an
  69.  * appropriate SOCKS5 reply code.
  70.  *
  71.  * A reason of 0 means that we're not actually expecting to send
  72.  * this code back to the socks client; we just call it 'succeeded'
  73.  * to keep things simple.
  74.  */
  75. socks5_reply_status_t
  76. stream_end_reason_to_socks5_response(int reason)
  77. {
  78.   switch (reason & END_STREAM_REASON_MASK) {
  79.     case 0:
  80.       return SOCKS5_SUCCEEDED;
  81.     case END_STREAM_REASON_MISC:
  82.       return SOCKS5_GENERAL_ERROR;
  83.     case END_STREAM_REASON_RESOLVEFAILED:
  84.       return SOCKS5_HOST_UNREACHABLE;
  85.     case END_STREAM_REASON_CONNECTREFUSED:
  86.       return SOCKS5_CONNECTION_REFUSED;
  87.     case END_STREAM_REASON_ENTRYPOLICY:
  88.       return SOCKS5_NOT_ALLOWED;
  89.     case END_STREAM_REASON_EXITPOLICY:
  90.       return SOCKS5_NOT_ALLOWED;
  91.     case END_STREAM_REASON_DESTROY:
  92.       return SOCKS5_GENERAL_ERROR;
  93.     case END_STREAM_REASON_DONE:
  94.       return SOCKS5_SUCCEEDED;
  95.     case END_STREAM_REASON_TIMEOUT:
  96.       return SOCKS5_TTL_EXPIRED;
  97.     case END_STREAM_REASON_RESOURCELIMIT:
  98.       return SOCKS5_GENERAL_ERROR;
  99.     case END_STREAM_REASON_HIBERNATING:
  100.       return SOCKS5_GENERAL_ERROR;
  101.     case END_STREAM_REASON_INTERNAL:
  102.       return SOCKS5_GENERAL_ERROR;
  103.     case END_STREAM_REASON_CONNRESET:
  104.       return SOCKS5_CONNECTION_REFUSED;
  105.     case END_STREAM_REASON_TORPROTOCOL:
  106.       return SOCKS5_GENERAL_ERROR;
  107.     case END_STREAM_REASON_CANT_ATTACH:
  108.       return SOCKS5_GENERAL_ERROR;
  109.     case END_STREAM_REASON_NET_UNREACHABLE:
  110.       return SOCKS5_NET_UNREACHABLE;
  111.     case END_STREAM_REASON_SOCKSPROTOCOL:
  112.       return SOCKS5_GENERAL_ERROR;
  113.     default:
  114.       log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
  115.              "Reason for ending (%d) not recognized; "
  116.              "sending generic socks error.", reason);
  117.       return SOCKS5_GENERAL_ERROR;
  118.   }
  119. }
  120. /* We need to use a few macros to deal with the fact that Windows
  121.  * decided that their sockets interface should be a permakludge.
  122.  * E_CASE is for errors where windows has both a EFOO and a WSAEFOO
  123.  * version, and S_CASE is for errors where windows has only a WSAEFOO
  124.  * version.  (The E is for 'error', the S is for 'socket'). */
  125. #ifdef MS_WINDOWS
  126. #define E_CASE(s) case s: case WSA ## s
  127. #define S_CASE(s) case WSA ## s
  128. #else
  129. #define E_CASE(s) case s
  130. #define S_CASE(s) case s
  131. #endif
  132. /** Given an errno from a failed exit connection, return a reason code
  133.  * appropriate for use in a RELAY END cell. */
  134. uint8_t
  135. errno_to_stream_end_reason(int e)
  136. {
  137.   /* To add new errors here, find out if they exist on Windows, and if a WSA*
  138.    * equivalent exists on windows. Add a case, an S_CASE, or an E_CASE as
  139.    * appropriate. */
  140.   switch (e) {
  141.     case EPIPE:
  142.       return END_STREAM_REASON_DONE;
  143.     E_CASE(EBADF):
  144.     E_CASE(EFAULT):
  145.     E_CASE(EINVAL):
  146.     S_CASE(EISCONN):
  147.     S_CASE(ENOTSOCK):
  148.     S_CASE(EPROTONOSUPPORT):
  149.     S_CASE(EAFNOSUPPORT):
  150.     E_CASE(EACCES):
  151.     S_CASE(ENOTCONN):
  152.     S_CASE(ENETUNREACH):
  153.       return END_STREAM_REASON_INTERNAL;
  154.     S_CASE(ECONNREFUSED):
  155.       return END_STREAM_REASON_CONNECTREFUSED;
  156.     S_CASE(ECONNRESET):
  157.       return END_STREAM_REASON_CONNRESET;
  158.     S_CASE(ETIMEDOUT):
  159.       return END_STREAM_REASON_TIMEOUT;
  160.     S_CASE(ENOBUFS):
  161.     case ENOMEM:
  162.     case ENFILE:
  163.     E_CASE(EMFILE):
  164.       return END_STREAM_REASON_RESOURCELIMIT;
  165.     default:
  166.       log_info(LD_EXIT, "Didn't recognize errno %d (%s); telling the client "
  167.                "that we are ending a stream for 'misc' reason.",
  168.                e, tor_socket_strerror(e));
  169.       return END_STREAM_REASON_MISC;
  170.   }
  171. }
  172. /***************************** ORConn reasons *****************************/
  173. /** Convert the reason for ending an OR connection <b>r</b> into the format
  174.  * used in ORCONN events. Return "UNKNOWN" if the reason is unrecognized. */
  175. const char *
  176. orconn_end_reason_to_control_string(int r)
  177. {
  178.   /* To add new errors here, find out if they exist on Windows, and if a WSA*
  179.    * equivalent exists on windows. Add a case, an S_CASE, or an E_CASE as
  180.    * appropriate. */
  181.   switch (r) {
  182.     case END_OR_CONN_REASON_DONE:
  183.       return "DONE";
  184.     case END_OR_CONN_REASON_REFUSED:
  185.       return "CONNECTREFUSED";
  186.     case END_OR_CONN_REASON_OR_IDENTITY:
  187.       return "IDENTITY";
  188.     case END_OR_CONN_REASON_CONNRESET:
  189.       return "CONNECTRESET";
  190.     case END_OR_CONN_REASON_TIMEOUT:
  191.       return "TIMEOUT";
  192.     case END_OR_CONN_REASON_NO_ROUTE:
  193.       return "NOROUTE";
  194.     case END_OR_CONN_REASON_IO_ERROR:
  195.       return "IOERROR";
  196.     case END_OR_CONN_REASON_RESOURCE_LIMIT:
  197.       return "RESOURCELIMIT";
  198.     case END_OR_CONN_REASON_MISC:
  199.       return "MISC";
  200.     case 0:
  201.       return "";
  202.     default:
  203.       log_warn(LD_BUG, "Unrecognized or_conn reason code %d", r);
  204.       return "UNKNOWN";
  205.   }
  206. }
  207. /** Convert a TOR_TLS_* error code into an END_OR_CONN_* reason. */
  208. int
  209. tls_error_to_orconn_end_reason(int e)
  210. {
  211.   switch (e) {
  212.     case TOR_TLS_ERROR_IO:
  213.       return END_OR_CONN_REASON_IO_ERROR;
  214.     case TOR_TLS_ERROR_CONNREFUSED:
  215.       return END_OR_CONN_REASON_REFUSED;
  216.     case TOR_TLS_ERROR_CONNRESET:
  217.       return END_OR_CONN_REASON_CONNRESET;
  218.     case TOR_TLS_ERROR_NO_ROUTE:
  219.       return END_OR_CONN_REASON_NO_ROUTE;
  220.     case TOR_TLS_ERROR_TIMEOUT:
  221.       return END_OR_CONN_REASON_TIMEOUT;
  222.     case TOR_TLS_WANTREAD:
  223.     case TOR_TLS_WANTWRITE:
  224.     case TOR_TLS_CLOSE:
  225.     case TOR_TLS_DONE:
  226.       return END_OR_CONN_REASON_DONE;
  227.     default:
  228.       return END_OR_CONN_REASON_MISC;
  229.   }
  230. }
  231. /** Given an errno from a failed ORConn connection, return a reason code
  232.  * appropriate for use in the controller orconn events. */
  233. int
  234. errno_to_orconn_end_reason(int e)
  235. {
  236.   switch (e) {
  237.     case EPIPE:
  238.       return END_OR_CONN_REASON_DONE;
  239.     S_CASE(ENOTCONN):
  240.     S_CASE(ENETUNREACH):
  241.     S_CASE(ENETDOWN):
  242.     S_CASE(EHOSTUNREACH):
  243.       return END_OR_CONN_REASON_NO_ROUTE;
  244.     S_CASE(ECONNREFUSED):
  245.       return END_OR_CONN_REASON_REFUSED;
  246.     S_CASE(ECONNRESET):
  247.       return END_OR_CONN_REASON_CONNRESET;
  248.     S_CASE(ETIMEDOUT):
  249.       return END_OR_CONN_REASON_TIMEOUT;
  250.     S_CASE(ENOBUFS):
  251.     case ENOMEM:
  252.     case ENFILE:
  253.     E_CASE(EMFILE):
  254.     E_CASE(EACCES):
  255.     E_CASE(EBADF):
  256.     E_CASE(EFAULT):
  257.     E_CASE(EINVAL):
  258.       return END_OR_CONN_REASON_RESOURCE_LIMIT;
  259.     default:
  260.       log_info(LD_OR, "Didn't recognize errno %d (%s).",
  261.                e, tor_socket_strerror(e));
  262.       return END_OR_CONN_REASON_MISC;
  263.   }
  264. }
  265. /***************************** Circuit reasons *****************************/
  266. /** Convert a numeric reason for destroying a circuit into a string for a
  267.  * CIRCUIT event. */
  268. const char *
  269. circuit_end_reason_to_control_string(int reason)
  270. {
  271.   if (reason >= 0 && reason & END_CIRC_REASON_FLAG_REMOTE)
  272.     reason &= ~END_CIRC_REASON_FLAG_REMOTE;
  273.   switch (reason) {
  274.     case END_CIRC_AT_ORIGIN:
  275.       /* This shouldn't get passed here; it's a catch-all reason. */
  276.       return "ORIGIN";
  277.     case END_CIRC_REASON_NONE:
  278.       /* This shouldn't get passed here; it's a catch-all reason. */
  279.       return "NONE";
  280.     case END_CIRC_REASON_TORPROTOCOL:
  281.       return "TORPROTOCOL";
  282.     case END_CIRC_REASON_INTERNAL:
  283.       return "INTERNAL";
  284.     case END_CIRC_REASON_REQUESTED:
  285.       return "REQUESTED";
  286.     case END_CIRC_REASON_HIBERNATING:
  287.       return "HIBERNATING";
  288.     case END_CIRC_REASON_RESOURCELIMIT:
  289.       return "RESOURCELIMIT";
  290.     case END_CIRC_REASON_CONNECTFAILED:
  291.       return "CONNECTFAILED";
  292.     case END_CIRC_REASON_OR_IDENTITY:
  293.       return "OR_IDENTITY";
  294.     case END_CIRC_REASON_OR_CONN_CLOSED:
  295.       return "OR_CONN_CLOSED";
  296.     case END_CIRC_REASON_FINISHED:
  297.       return "FINISHED";
  298.     case END_CIRC_REASON_TIMEOUT:
  299.       return "TIMEOUT";
  300.     case END_CIRC_REASON_DESTROYED:
  301.       return "DESTROYED";
  302.     case END_CIRC_REASON_NOPATH:
  303.       return "NOPATH";
  304.     case END_CIRC_REASON_NOSUCHSERVICE:
  305.       return "NOSUCHSERVICE";
  306.     default:
  307.       log_warn(LD_BUG, "Unrecognized reason code %d", (int)reason);
  308.       return NULL;
  309.   }
  310. }