Back to index

tor  0.2.3.19-rc
reasons.c
Go to the documentation of this file.
00001 /* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
00002  * Copyright (c) 2007-2012, The Tor Project, Inc. */
00003 /* See LICENSE for licensing information */
00004 
00011 #include "or.h"
00012 #include "config.h"
00013 #include "reasons.h"
00014 
00015 /***************************** Edge (stream) reasons **********************/
00016 
00019 const char *
00020 stream_end_reason_to_control_string(int reason)
00021 {
00022   reason &= END_STREAM_REASON_MASK;
00023   switch (reason) {
00024     case END_STREAM_REASON_MISC: return "MISC";
00025     case END_STREAM_REASON_RESOLVEFAILED: return "RESOLVEFAILED";
00026     case END_STREAM_REASON_CONNECTREFUSED: return "CONNECTREFUSED";
00027     case END_STREAM_REASON_EXITPOLICY: return "EXITPOLICY";
00028     case END_STREAM_REASON_DESTROY: return "DESTROY";
00029     case END_STREAM_REASON_DONE: return "DONE";
00030     case END_STREAM_REASON_TIMEOUT: return "TIMEOUT";
00031     case END_STREAM_REASON_NOROUTE: return "NOROUTE";
00032     case END_STREAM_REASON_HIBERNATING: return "HIBERNATING";
00033     case END_STREAM_REASON_INTERNAL: return "INTERNAL";
00034     case END_STREAM_REASON_RESOURCELIMIT: return "RESOURCELIMIT";
00035     case END_STREAM_REASON_CONNRESET: return "CONNRESET";
00036     case END_STREAM_REASON_TORPROTOCOL: return "TORPROTOCOL";
00037     case END_STREAM_REASON_NOTDIRECTORY: return "NOTDIRECTORY";
00038 
00039     case END_STREAM_REASON_CANT_ATTACH: return "CANT_ATTACH";
00040     case END_STREAM_REASON_NET_UNREACHABLE: return "NET_UNREACHABLE";
00041     case END_STREAM_REASON_SOCKSPROTOCOL: return "SOCKS_PROTOCOL";
00042 
00043     case END_STREAM_REASON_PRIVATE_ADDR: return "PRIVATE_ADDR";
00044 
00045     default: return NULL;
00046   }
00047 }
00048 
00053 const char *
00054 stream_end_reason_to_string(int reason)
00055 {
00056   switch (reason) {
00057     case -1:
00058       log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
00059              "End cell arrived with length 0. Should be at least 1.");
00060       return "MALFORMED";
00061     case END_STREAM_REASON_MISC:           return "misc error";
00062     case END_STREAM_REASON_RESOLVEFAILED:  return "resolve failed";
00063     case END_STREAM_REASON_CONNECTREFUSED: return "connection refused";
00064     case END_STREAM_REASON_EXITPOLICY:     return "exit policy failed";
00065     case END_STREAM_REASON_DESTROY:        return "destroyed";
00066     case END_STREAM_REASON_DONE:           return "closed normally";
00067     case END_STREAM_REASON_TIMEOUT:        return "gave up (timeout)";
00068     case END_STREAM_REASON_NOROUTE:        return "no route to host";
00069     case END_STREAM_REASON_HIBERNATING:    return "server is hibernating";
00070     case END_STREAM_REASON_INTERNAL:       return "internal error at server";
00071     case END_STREAM_REASON_RESOURCELIMIT:  return "server out of resources";
00072     case END_STREAM_REASON_CONNRESET:      return "connection reset";
00073     case END_STREAM_REASON_TORPROTOCOL:    return "Tor protocol error";
00074     case END_STREAM_REASON_NOTDIRECTORY:   return "not a directory";
00075     default:
00076       log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
00077              "Reason for ending (%d) not recognized.",reason);
00078       return "unknown";
00079   }
00080 }
00081 
00089 socks5_reply_status_t
00090 stream_end_reason_to_socks5_response(int reason)
00091 {
00092   switch (reason & END_STREAM_REASON_MASK) {
00093     case 0:
00094       return SOCKS5_SUCCEEDED;
00095     case END_STREAM_REASON_MISC:
00096       return SOCKS5_GENERAL_ERROR;
00097     case END_STREAM_REASON_RESOLVEFAILED:
00098       return SOCKS5_HOST_UNREACHABLE;
00099     case END_STREAM_REASON_CONNECTREFUSED:
00100       return SOCKS5_CONNECTION_REFUSED;
00101     case END_STREAM_REASON_ENTRYPOLICY:
00102       return SOCKS5_NOT_ALLOWED;
00103     case END_STREAM_REASON_EXITPOLICY:
00104       return SOCKS5_NOT_ALLOWED;
00105     case END_STREAM_REASON_DESTROY:
00106       return SOCKS5_GENERAL_ERROR;
00107     case END_STREAM_REASON_DONE:
00108       return SOCKS5_SUCCEEDED;
00109     case END_STREAM_REASON_TIMEOUT:
00110       return SOCKS5_TTL_EXPIRED;
00111     case END_STREAM_REASON_NOROUTE:
00112       return SOCKS5_HOST_UNREACHABLE;
00113     case END_STREAM_REASON_RESOURCELIMIT:
00114       return SOCKS5_GENERAL_ERROR;
00115     case END_STREAM_REASON_HIBERNATING:
00116       return SOCKS5_GENERAL_ERROR;
00117     case END_STREAM_REASON_INTERNAL:
00118       return SOCKS5_GENERAL_ERROR;
00119     case END_STREAM_REASON_CONNRESET:
00120       return SOCKS5_CONNECTION_REFUSED;
00121     case END_STREAM_REASON_TORPROTOCOL:
00122       return SOCKS5_GENERAL_ERROR;
00123 
00124     case END_STREAM_REASON_CANT_ATTACH:
00125       return SOCKS5_GENERAL_ERROR;
00126     case END_STREAM_REASON_NET_UNREACHABLE:
00127       return SOCKS5_NET_UNREACHABLE;
00128     case END_STREAM_REASON_SOCKSPROTOCOL:
00129       return SOCKS5_GENERAL_ERROR;
00130     case END_STREAM_REASON_PRIVATE_ADDR:
00131       return SOCKS5_GENERAL_ERROR;
00132 
00133     default:
00134       log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
00135              "Reason for ending (%d) not recognized; "
00136              "sending generic socks error.", reason);
00137       return SOCKS5_GENERAL_ERROR;
00138   }
00139 }
00140 
00141 /* We need to use a few macros to deal with the fact that Windows
00142  * decided that their sockets interface should be a permakludge.
00143  * E_CASE is for errors where windows has both a EFOO and a WSAEFOO
00144  * version, and S_CASE is for errors where windows has only a WSAEFOO
00145  * version.  (The E is for 'error', the S is for 'socket'). */
00146 #ifdef _WIN32
00147 #define E_CASE(s) case s: case WSA ## s
00148 #define S_CASE(s) case WSA ## s
00149 #else
00150 #define E_CASE(s) case s
00151 #define S_CASE(s) case s
00152 #endif
00153 
00156 uint8_t
00157 errno_to_stream_end_reason(int e)
00158 {
00159   /* To add new errors here, find out if they exist on Windows, and if a WSA*
00160    * equivalent exists on windows. Add a case, an S_CASE, or an E_CASE as
00161    * appropriate. */
00162   switch (e) {
00163     case EPIPE:
00164       return END_STREAM_REASON_DONE;
00165     E_CASE(EBADF):
00166     E_CASE(EFAULT):
00167     E_CASE(EINVAL):
00168     S_CASE(EISCONN):
00169     S_CASE(ENOTSOCK):
00170     S_CASE(EPROTONOSUPPORT):
00171     S_CASE(EAFNOSUPPORT):
00172     E_CASE(EACCES):
00173     S_CASE(ENOTCONN):
00174     S_CASE(ENETUNREACH):
00175       return END_STREAM_REASON_INTERNAL;
00176     S_CASE(EHOSTUNREACH):
00177       return END_STREAM_REASON_NOROUTE;
00178     S_CASE(ECONNREFUSED):
00179       return END_STREAM_REASON_CONNECTREFUSED;
00180     S_CASE(ECONNRESET):
00181       return END_STREAM_REASON_CONNRESET;
00182     S_CASE(ETIMEDOUT):
00183       return END_STREAM_REASON_TIMEOUT;
00184     S_CASE(ENOBUFS):
00185     case ENOMEM:
00186     case ENFILE:
00187     S_CASE(EADDRINUSE):
00188     S_CASE(EADDRNOTAVAIL):
00189     E_CASE(EMFILE):
00190       return END_STREAM_REASON_RESOURCELIMIT;
00191     default:
00192       log_info(LD_EXIT, "Didn't recognize errno %d (%s); telling the client "
00193                "that we are ending a stream for 'misc' reason.",
00194                e, tor_socket_strerror(e));
00195       return END_STREAM_REASON_MISC;
00196   }
00197 }
00198 
00199 /***************************** ORConn reasons *****************************/
00200 
00203 const char *
00204 orconn_end_reason_to_control_string(int r)
00205 {
00206   /* To add new errors here, find out if they exist on Windows, and if a WSA*
00207    * equivalent exists on windows. Add a case, an S_CASE, or an E_CASE as
00208    * appropriate. */
00209   switch (r) {
00210     case END_OR_CONN_REASON_DONE:
00211       return "DONE";
00212     case END_OR_CONN_REASON_REFUSED:
00213       return "CONNECTREFUSED";
00214     case END_OR_CONN_REASON_OR_IDENTITY:
00215       return "IDENTITY";
00216     case END_OR_CONN_REASON_CONNRESET:
00217       return "CONNECTRESET";
00218     case END_OR_CONN_REASON_TIMEOUT:
00219       return "TIMEOUT";
00220     case END_OR_CONN_REASON_NO_ROUTE:
00221       return "NOROUTE";
00222     case END_OR_CONN_REASON_IO_ERROR:
00223       return "IOERROR";
00224     case END_OR_CONN_REASON_RESOURCE_LIMIT:
00225       return "RESOURCELIMIT";
00226     case END_OR_CONN_REASON_MISC:
00227       return "MISC";
00228     case 0:
00229       return "";
00230     default:
00231       log_warn(LD_BUG, "Unrecognized or_conn reason code %d", r);
00232       return "UNKNOWN";
00233   }
00234 }
00235 
00237 int
00238 tls_error_to_orconn_end_reason(int e)
00239 {
00240   switch (e) {
00241     case TOR_TLS_ERROR_IO:
00242       return END_OR_CONN_REASON_IO_ERROR;
00243     case TOR_TLS_ERROR_CONNREFUSED:
00244       return END_OR_CONN_REASON_REFUSED;
00245     case TOR_TLS_ERROR_CONNRESET:
00246       return END_OR_CONN_REASON_CONNRESET;
00247     case TOR_TLS_ERROR_NO_ROUTE:
00248       return END_OR_CONN_REASON_NO_ROUTE;
00249     case TOR_TLS_ERROR_TIMEOUT:
00250       return END_OR_CONN_REASON_TIMEOUT;
00251     case TOR_TLS_WANTREAD:
00252     case TOR_TLS_WANTWRITE:
00253     case TOR_TLS_CLOSE:
00254     case TOR_TLS_DONE:
00255       return END_OR_CONN_REASON_DONE;
00256     default:
00257       return END_OR_CONN_REASON_MISC;
00258   }
00259 }
00260 
00263 int
00264 errno_to_orconn_end_reason(int e)
00265 {
00266   switch (e) {
00267     case EPIPE:
00268       return END_OR_CONN_REASON_DONE;
00269     S_CASE(ENOTCONN):
00270     S_CASE(ENETUNREACH):
00271     S_CASE(ENETDOWN):
00272     S_CASE(EHOSTUNREACH):
00273       return END_OR_CONN_REASON_NO_ROUTE;
00274     S_CASE(ECONNREFUSED):
00275       return END_OR_CONN_REASON_REFUSED;
00276     S_CASE(ECONNRESET):
00277       return END_OR_CONN_REASON_CONNRESET;
00278     S_CASE(ETIMEDOUT):
00279       return END_OR_CONN_REASON_TIMEOUT;
00280     S_CASE(ENOBUFS):
00281     case ENOMEM:
00282     case ENFILE:
00283     E_CASE(EMFILE):
00284     E_CASE(EACCES):
00285     E_CASE(EBADF):
00286     E_CASE(EFAULT):
00287     E_CASE(EINVAL):
00288       return END_OR_CONN_REASON_RESOURCE_LIMIT;
00289     default:
00290       log_info(LD_OR, "Didn't recognize errno %d (%s).",
00291                e, tor_socket_strerror(e));
00292       return END_OR_CONN_REASON_MISC;
00293   }
00294 }
00295 
00296 /***************************** Circuit reasons *****************************/
00297 
00300 const char *
00301 circuit_end_reason_to_control_string(int reason)
00302 {
00303   if (reason >= 0 && reason & END_CIRC_REASON_FLAG_REMOTE)
00304     reason &= ~END_CIRC_REASON_FLAG_REMOTE;
00305   switch (reason) {
00306     case END_CIRC_AT_ORIGIN:
00307       /* This shouldn't get passed here; it's a catch-all reason. */
00308       return "ORIGIN";
00309     case END_CIRC_REASON_NONE:
00310       /* This shouldn't get passed here; it's a catch-all reason. */
00311       return "NONE";
00312     case END_CIRC_REASON_TORPROTOCOL:
00313       return "TORPROTOCOL";
00314     case END_CIRC_REASON_INTERNAL:
00315       return "INTERNAL";
00316     case END_CIRC_REASON_REQUESTED:
00317       return "REQUESTED";
00318     case END_CIRC_REASON_HIBERNATING:
00319       return "HIBERNATING";
00320     case END_CIRC_REASON_RESOURCELIMIT:
00321       return "RESOURCELIMIT";
00322     case END_CIRC_REASON_CONNECTFAILED:
00323       return "CONNECTFAILED";
00324     case END_CIRC_REASON_OR_IDENTITY:
00325       return "OR_IDENTITY";
00326     case END_CIRC_REASON_OR_CONN_CLOSED:
00327       return "OR_CONN_CLOSED";
00328     case END_CIRC_REASON_FINISHED:
00329       return "FINISHED";
00330     case END_CIRC_REASON_TIMEOUT:
00331       return "TIMEOUT";
00332     case END_CIRC_REASON_DESTROYED:
00333       return "DESTROYED";
00334     case END_CIRC_REASON_NOPATH:
00335       return "NOPATH";
00336     case END_CIRC_REASON_NOSUCHSERVICE:
00337       return "NOSUCHSERVICE";
00338     case END_CIRC_REASON_MEASUREMENT_EXPIRED:
00339       return "MEASUREMENT_EXPIRED";
00340     default:
00341       log_warn(LD_BUG, "Unrecognized reason code %d", (int)reason);
00342       return NULL;
00343   }
00344 }
00345 
00347 const char *
00348 socks4_response_code_to_string(uint8_t code)
00349 {
00350   switch (code) {
00351     case 0x5a:
00352       return "connection accepted";
00353     case 0x5b:
00354       return "server rejected connection";
00355     case 0x5c:
00356       return "server cannot connect to identd on this client";
00357     case 0x5d:
00358       return "user id does not match identd";
00359     default:
00360       return "invalid SOCKS 4 response code";
00361   }
00362 }
00363 
00365 const char *
00366 socks5_response_code_to_string(uint8_t code)
00367 {
00368   switch (code) {
00369     case 0x00:
00370       return "connection accepted";
00371     case 0x01:
00372       return "general SOCKS server failure";
00373     case 0x02:
00374       return "connection not allowed by ruleset";
00375     case 0x03:
00376       return "Network unreachable";
00377     case 0x04:
00378       return "Host unreachable";
00379     case 0x05:
00380       return "Connection refused";
00381     case 0x06:
00382       return "TTL expired";
00383     case 0x07:
00384       return "Command not supported";
00385     case 0x08:
00386       return "Address type not supported";
00387     default:
00388       return "unknown reason";
00389   }
00390 }
00391 
00393 const char *
00394 bandwidth_weight_rule_to_string(bandwidth_weight_rule_t rule)
00395 {
00396   switch (rule)
00397     {
00398     case NO_WEIGHTING:
00399       return "no weighting";
00400     case WEIGHT_FOR_EXIT:
00401       return "weight as exit";
00402     case WEIGHT_FOR_MID:
00403       return "weight as middle node";
00404     case WEIGHT_FOR_GUARD:
00405       return "weight as guard";
00406     case WEIGHT_FOR_DIR:
00407       return "weight as directory";
00408     default:
00409       return "unknown rule";
00410   }
00411 }
00412