LCOV - code coverage report
Current view: top level - core/or - reasons.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 30 264 11.4 %
Date: 2021-11-24 03:28:48 Functions: 7 12 58.3 %

          Line data    Source code
       1             : /* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
       2             :  * Copyright (c) 2007-2021, The Tor Project, Inc. */
       3             : /* See LICENSE for licensing information */
       4             : 
       5             : /**
       6             :  * \file reasons.c
       7             :  * \brief Convert circuit, stream, and orconn error reasons to and/or from
       8             :  * strings and errno values.
       9             :  *
      10             :  * This module is just a bunch of functions full of case statements that
      11             :  * convert from one representation of our error codes to another. These are
      12             :  * mainly used in generating log messages, in sending messages to the
      13             :  * controller in control.c, and in converting errors from one protocol layer
      14             :  * to another.
      15             :  **/
      16             : 
      17             : #include "core/or/or.h"
      18             : #include "app/config/config.h"
      19             : #include "core/or/reasons.h"
      20             : #include "feature/nodelist/node_select.h"
      21             : #include "lib/tls/tortls.h"
      22             : 
      23             : /***************************** Edge (stream) reasons **********************/
      24             : 
      25             : /** Convert the reason for ending a stream <b>reason</b> into the format used
      26             :  * in STREAM events. Return NULL if the reason is unrecognized. */
      27             : const char *
      28           0 : stream_end_reason_to_control_string(int reason)
      29             : {
      30           0 :   reason &= END_STREAM_REASON_MASK;
      31           0 :   switch (reason) {
      32             :     case END_STREAM_REASON_MISC: return "MISC";
      33           0 :     case END_STREAM_REASON_RESOLVEFAILED: return "RESOLVEFAILED";
      34           0 :     case END_STREAM_REASON_CONNECTREFUSED: return "CONNECTREFUSED";
      35           0 :     case END_STREAM_REASON_EXITPOLICY: return "EXITPOLICY";
      36           0 :     case END_STREAM_REASON_DESTROY: return "DESTROY";
      37           0 :     case END_STREAM_REASON_DONE: return "DONE";
      38           0 :     case END_STREAM_REASON_TIMEOUT: return "TIMEOUT";
      39           0 :     case END_STREAM_REASON_NOROUTE: return "NOROUTE";
      40           0 :     case END_STREAM_REASON_HIBERNATING: return "HIBERNATING";
      41           0 :     case END_STREAM_REASON_INTERNAL: return "INTERNAL";
      42           0 :     case END_STREAM_REASON_RESOURCELIMIT: return "RESOURCELIMIT";
      43           0 :     case END_STREAM_REASON_CONNRESET: return "CONNRESET";
      44           0 :     case END_STREAM_REASON_TORPROTOCOL: return "TORPROTOCOL";
      45           0 :     case END_STREAM_REASON_NOTDIRECTORY: return "NOTDIRECTORY";
      46             : 
      47           0 :     case END_STREAM_REASON_CANT_ATTACH: return "CANT_ATTACH";
      48           0 :     case END_STREAM_REASON_NET_UNREACHABLE: return "NET_UNREACHABLE";
      49           0 :     case END_STREAM_REASON_SOCKSPROTOCOL: return "SOCKS_PROTOCOL";
      50             :     // XXXX Controlspec
      51           0 :     case END_STREAM_REASON_HTTPPROTOCOL: return "HTTP_PROTOCOL";
      52             : 
      53           0 :     case END_STREAM_REASON_PRIVATE_ADDR: return "PRIVATE_ADDR";
      54             : 
      55           0 :     default: return NULL;
      56             :   }
      57             : }
      58             : 
      59             : /** Translate <b>reason</b>, which came from a relay 'end' cell,
      60             :  * into a static const string describing why the stream is closing.
      61             :  * <b>reason</b> is -1 if no reason was provided.
      62             :  */
      63             : const char *
      64           8 : stream_end_reason_to_string(int reason)
      65             : {
      66           8 :   switch (reason) {
      67           0 :     case -1:
      68           0 :       log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
      69             :              "End cell arrived with length 0. Should be at least 1.");
      70           0 :       return "MALFORMED";
      71             :     case END_STREAM_REASON_MISC:           return "misc error";
      72           1 :     case END_STREAM_REASON_RESOLVEFAILED:  return "resolve failed";
      73           0 :     case END_STREAM_REASON_CONNECTREFUSED: return "connection refused";
      74           0 :     case END_STREAM_REASON_EXITPOLICY:     return "exit policy failed";
      75           0 :     case END_STREAM_REASON_DESTROY:        return "destroyed";
      76           0 :     case END_STREAM_REASON_DONE:           return "closed normally";
      77           0 :     case END_STREAM_REASON_TIMEOUT:        return "gave up (timeout)";
      78           0 :     case END_STREAM_REASON_NOROUTE:        return "no route to host";
      79           0 :     case END_STREAM_REASON_HIBERNATING:    return "server is hibernating";
      80           0 :     case END_STREAM_REASON_INTERNAL:       return "internal error at server";
      81           0 :     case END_STREAM_REASON_RESOURCELIMIT:  return "server out of resources";
      82           0 :     case END_STREAM_REASON_CONNRESET:      return "connection reset";
      83           0 :     case END_STREAM_REASON_TORPROTOCOL:    return "Tor protocol error";
      84           0 :     case END_STREAM_REASON_NOTDIRECTORY:   return "not a directory";
      85           7 :     default:
      86           7 :       log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
      87             :              "Reason for ending (%d) not recognized.",reason);
      88           7 :       return "unknown";
      89             :   }
      90             : }
      91             : 
      92             : /** Translate <b>reason</b> (as from a relay 'end' cell) into an
      93             :  * appropriate SOCKS5 reply code.
      94             :  *
      95             :  * A reason of 0 means that we're not actually expecting to send
      96             :  * this code back to the socks client; we just call it 'succeeded'
      97             :  * to keep things simple.
      98             :  */
      99             : socks5_reply_status_t
     100           1 : stream_end_reason_to_socks5_response(int reason)
     101             : {
     102           1 :   switch (reason & END_STREAM_REASON_MASK) {
     103             :     case 0:
     104             :       return SOCKS5_SUCCEEDED;
     105           0 :     case END_STREAM_REASON_MISC:
     106           0 :       return SOCKS5_GENERAL_ERROR;
     107           0 :     case END_STREAM_REASON_RESOLVEFAILED:
     108           0 :       return SOCKS5_HOST_UNREACHABLE;
     109           0 :     case END_STREAM_REASON_CONNECTREFUSED:
     110           0 :       return SOCKS5_CONNECTION_REFUSED;
     111           0 :     case END_STREAM_REASON_ENTRYPOLICY:
     112           0 :       return SOCKS5_NOT_ALLOWED;
     113           0 :     case END_STREAM_REASON_EXITPOLICY:
     114           0 :       return SOCKS5_NOT_ALLOWED;
     115           0 :     case END_STREAM_REASON_DESTROY:
     116           0 :       return SOCKS5_GENERAL_ERROR;
     117           0 :     case END_STREAM_REASON_DONE:
     118             :       /* Note that 'DONE' usually indicates a successful close from the other
     119             :        * side of the stream... but if we receive it before a connected cell --
     120             :        * that is, before we have sent a SOCKS reply -- that means that the
     121             :        * other side of the circuit closed the connection before telling us it
     122             :        * was complete. */
     123           0 :       return SOCKS5_CONNECTION_REFUSED;
     124           0 :     case END_STREAM_REASON_TIMEOUT:
     125           0 :       return SOCKS5_TTL_EXPIRED;
     126           0 :     case END_STREAM_REASON_NOROUTE:
     127           0 :       return SOCKS5_HOST_UNREACHABLE;
     128           0 :     case END_STREAM_REASON_RESOURCELIMIT:
     129           0 :       return SOCKS5_GENERAL_ERROR;
     130           0 :     case END_STREAM_REASON_HIBERNATING:
     131           0 :       return SOCKS5_GENERAL_ERROR;
     132           0 :     case END_STREAM_REASON_INTERNAL:
     133           0 :       return SOCKS5_GENERAL_ERROR;
     134           0 :     case END_STREAM_REASON_CONNRESET:
     135           0 :       return SOCKS5_CONNECTION_REFUSED;
     136           0 :     case END_STREAM_REASON_TORPROTOCOL:
     137           0 :       return SOCKS5_GENERAL_ERROR;
     138             : 
     139           0 :     case END_STREAM_REASON_CANT_ATTACH:
     140           0 :       return SOCKS5_GENERAL_ERROR;
     141           0 :     case END_STREAM_REASON_NET_UNREACHABLE:
     142           0 :       return SOCKS5_NET_UNREACHABLE;
     143           0 :     case END_STREAM_REASON_SOCKSPROTOCOL:
     144           0 :       return SOCKS5_GENERAL_ERROR;
     145           0 :     case END_STREAM_REASON_HTTPPROTOCOL:
     146             :       // LCOV_EXCL_START
     147             :       tor_assert_nonfatal_unreached();
     148             :       return SOCKS5_GENERAL_ERROR;
     149             :       // LCOV_EXCL_STOP
     150           0 :     case END_STREAM_REASON_PRIVATE_ADDR:
     151           0 :       return SOCKS5_GENERAL_ERROR;
     152             : 
     153           0 :     default:
     154           0 :       log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
     155             :              "Reason for ending (%d) not recognized; "
     156             :              "sending generic socks error.", reason);
     157           0 :       return SOCKS5_GENERAL_ERROR;
     158             :   }
     159             : }
     160             : 
     161             : /* We need to use a few macros to deal with the fact that Windows
     162             :  * decided that their sockets interface should be a permakludge.
     163             :  * E_CASE is for errors where windows has both a EFOO and a WSAEFOO
     164             :  * version, and S_CASE is for errors where windows has only a WSAEFOO
     165             :  * version.  (The E is for 'error', the S is for 'socket'). */
     166             : #ifdef _WIN32
     167             : #define E_CASE(s) case s: case WSA ## s
     168             : #define S_CASE(s) case WSA ## s
     169             : #else
     170             : #define E_CASE(s) case s
     171             : #define S_CASE(s) case s
     172             : #endif /* defined(_WIN32) */
     173             : 
     174             : /** Given an errno from a failed exit connection, return a reason code
     175             :  * appropriate for use in a RELAY END cell. */
     176             : uint8_t
     177           0 : errno_to_stream_end_reason(int e)
     178             : {
     179             :   /* To add new errors here, find out if they exist on Windows, and if a WSA*
     180             :    * equivalent exists on windows. Add a case, an S_CASE, or an E_CASE as
     181             :    * appropriate. */
     182           0 :   switch (e) {
     183             :     case EPIPE:
     184             :       return END_STREAM_REASON_DONE;
     185           0 :     E_CASE(EBADF):
     186             :     E_CASE(EFAULT):
     187             :     E_CASE(EINVAL):
     188             :     S_CASE(EISCONN):
     189             :     S_CASE(ENOTSOCK):
     190             :     S_CASE(EPROTONOSUPPORT):
     191             :     S_CASE(EAFNOSUPPORT):
     192             :     S_CASE(ENOTCONN):
     193           0 :       return END_STREAM_REASON_INTERNAL;
     194           0 :     S_CASE(ENETUNREACH):
     195             :     S_CASE(EHOSTUNREACH):
     196             :     E_CASE(EACCES):
     197             :     case EPERM:
     198           0 :       return END_STREAM_REASON_NOROUTE;
     199           0 :     S_CASE(ECONNREFUSED):
     200           0 :       return END_STREAM_REASON_CONNECTREFUSED;
     201           0 :     S_CASE(ECONNRESET):
     202           0 :       return END_STREAM_REASON_CONNRESET;
     203           0 :     S_CASE(ETIMEDOUT):
     204           0 :       return END_STREAM_REASON_TIMEOUT;
     205           0 :     S_CASE(ENOBUFS):
     206             :     case ENOMEM:
     207             :     case ENFILE:
     208             :     S_CASE(EADDRINUSE):
     209             :     S_CASE(EADDRNOTAVAIL):
     210             :     E_CASE(EMFILE):
     211           0 :       return END_STREAM_REASON_RESOURCELIMIT;
     212           0 :     default:
     213           0 :       log_info(LD_EXIT, "Didn't recognize errno %d (%s); telling the client "
     214             :                "that we are ending a stream for 'misc' reason.",
     215             :                e, tor_socket_strerror(e));
     216           0 :       return END_STREAM_REASON_MISC;
     217             :   }
     218             : }
     219             : 
     220             : /***************************** ORConn reasons *****************************/
     221             : 
     222             : /** Convert the reason for ending an OR connection <b>r</b> into the format
     223             :  * used in ORCONN events. Return "UNKNOWN" if the reason is unrecognized. */
     224             : const char *
     225           4 : orconn_end_reason_to_control_string(int r)
     226             : {
     227             :   /* To add new errors here, find out if they exist on Windows, and if a WSA*
     228             :    * equivalent exists on windows. Add a case, an S_CASE, or an E_CASE as
     229             :    * appropriate. */
     230           4 :   switch (r) {
     231             :     case END_OR_CONN_REASON_DONE:
     232             :       return "DONE";
     233           0 :     case END_OR_CONN_REASON_REFUSED:
     234           0 :       return "CONNECTREFUSED";
     235           0 :     case END_OR_CONN_REASON_OR_IDENTITY:
     236           0 :       return "IDENTITY";
     237           0 :     case END_OR_CONN_REASON_CONNRESET:
     238           0 :       return "CONNECTRESET";
     239           0 :     case END_OR_CONN_REASON_TIMEOUT:
     240           0 :       return "TIMEOUT";
     241           0 :     case END_OR_CONN_REASON_NO_ROUTE:
     242           0 :       return "NOROUTE";
     243           0 :     case END_OR_CONN_REASON_IO_ERROR:
     244           0 :       return "IOERROR";
     245           0 :     case END_OR_CONN_REASON_RESOURCE_LIMIT:
     246           0 :       return "RESOURCELIMIT";
     247           0 :     case END_OR_CONN_REASON_TLS_ERROR:
     248           0 :       return "TLS_ERROR";
     249           0 :     case END_OR_CONN_REASON_MISC:
     250           0 :       return "MISC";
     251           0 :     case END_OR_CONN_REASON_PT_MISSING:
     252           0 :       return "PT_MISSING";
     253           0 :     case 0:
     254           0 :       return "";
     255           0 :     default:
     256           0 :       log_warn(LD_BUG, "Unrecognized or_conn reason code %d", r);
     257           0 :       return "UNKNOWN";
     258             :   }
     259             : }
     260             : 
     261             : /** Convert a TOR_TLS_* error code into an END_OR_CONN_* reason. */
     262             : int
     263           4 : tls_error_to_orconn_end_reason(int e)
     264             : {
     265           4 :   switch (e) {
     266             :     case TOR_TLS_ERROR_IO:
     267             :       return END_OR_CONN_REASON_IO_ERROR;
     268             :     case TOR_TLS_ERROR_CONNREFUSED:
     269             :       return END_OR_CONN_REASON_REFUSED;
     270             :     case TOR_TLS_ERROR_CONNRESET:
     271             :       return END_OR_CONN_REASON_CONNRESET;
     272             :     case TOR_TLS_ERROR_NO_ROUTE:
     273             :       return END_OR_CONN_REASON_NO_ROUTE;
     274             :     case TOR_TLS_ERROR_TIMEOUT:
     275             :       return END_OR_CONN_REASON_TIMEOUT;
     276             :     case TOR_TLS_WANTREAD:
     277             :     case TOR_TLS_WANTWRITE:
     278             :     case TOR_TLS_CLOSE:
     279             :     case TOR_TLS_DONE:
     280             :       return END_OR_CONN_REASON_DONE;
     281             :     case TOR_TLS_ERROR_MISC:
     282             :       return END_OR_CONN_REASON_TLS_ERROR;
     283             :     default:
     284             :       return END_OR_CONN_REASON_MISC;
     285             :   }
     286             : }
     287             : 
     288             : /** Given an errno from a failed ORConn connection, return a reason code
     289             :  * appropriate for use in the controller orconn events. */
     290             : int
     291           0 : errno_to_orconn_end_reason(int e)
     292             : {
     293           0 :   switch (e) {
     294             :     case EPIPE:
     295             :       return END_OR_CONN_REASON_DONE;
     296           0 :     S_CASE(ENOTCONN):
     297             :     S_CASE(ENETUNREACH):
     298             :     S_CASE(ENETDOWN):
     299             :     S_CASE(EHOSTUNREACH):
     300           0 :       return END_OR_CONN_REASON_NO_ROUTE;
     301           0 :     S_CASE(ECONNREFUSED):
     302           0 :       return END_OR_CONN_REASON_REFUSED;
     303           0 :     S_CASE(ECONNRESET):
     304           0 :       return END_OR_CONN_REASON_CONNRESET;
     305           0 :     S_CASE(ETIMEDOUT):
     306           0 :       return END_OR_CONN_REASON_TIMEOUT;
     307           0 :     S_CASE(ENOBUFS):
     308             :     case ENOMEM:
     309             :     case ENFILE:
     310             :     E_CASE(EMFILE):
     311             :     E_CASE(EACCES):
     312             :     E_CASE(EBADF):
     313             :     E_CASE(EFAULT):
     314             :     E_CASE(EINVAL):
     315           0 :       return END_OR_CONN_REASON_RESOURCE_LIMIT;
     316           0 :     default:
     317           0 :       log_info(LD_OR, "Didn't recognize errno %d (%s).",
     318             :                e, tor_socket_strerror(e));
     319           0 :       return END_OR_CONN_REASON_MISC;
     320             :   }
     321             : }
     322             : 
     323             : /***************************** Circuit reasons *****************************/
     324             : 
     325             : /** Convert a numeric reason for destroying a circuit into a string for a
     326             :  * CIRCUIT event. */
     327             : const char *
     328           0 : circuit_end_reason_to_control_string(int reason)
     329             : {
     330           0 :   int is_remote = 0;
     331             : 
     332           0 :   if (reason >= 0 && reason & END_CIRC_REASON_FLAG_REMOTE) {
     333           0 :     reason &= ~END_CIRC_REASON_FLAG_REMOTE;
     334           0 :     is_remote = 1;
     335             :   }
     336             : 
     337           0 :   switch (reason) {
     338             :     case END_CIRC_AT_ORIGIN:
     339             :       /* This shouldn't get passed here; it's a catch-all reason. */
     340             :       return "ORIGIN";
     341           0 :     case END_CIRC_REASON_NONE:
     342             :       /* This shouldn't get passed here; it's a catch-all reason. */
     343           0 :       return "NONE";
     344           0 :     case END_CIRC_REASON_TORPROTOCOL:
     345           0 :       return "TORPROTOCOL";
     346           0 :     case END_CIRC_REASON_INTERNAL:
     347           0 :       return "INTERNAL";
     348           0 :     case END_CIRC_REASON_REQUESTED:
     349           0 :       return "REQUESTED";
     350           0 :     case END_CIRC_REASON_HIBERNATING:
     351           0 :       return "HIBERNATING";
     352           0 :     case END_CIRC_REASON_RESOURCELIMIT:
     353           0 :       return "RESOURCELIMIT";
     354           0 :     case END_CIRC_REASON_CONNECTFAILED:
     355           0 :       return "CONNECTFAILED";
     356           0 :     case END_CIRC_REASON_OR_IDENTITY:
     357           0 :       return "OR_IDENTITY";
     358           0 :     case END_CIRC_REASON_CHANNEL_CLOSED:
     359           0 :       return "CHANNEL_CLOSED";
     360           0 :     case END_CIRC_REASON_FINISHED:
     361           0 :       return "FINISHED";
     362           0 :     case END_CIRC_REASON_TIMEOUT:
     363           0 :       return "TIMEOUT";
     364           0 :     case END_CIRC_REASON_DESTROYED:
     365           0 :       return "DESTROYED";
     366           0 :     case END_CIRC_REASON_NOPATH:
     367           0 :       return "NOPATH";
     368           0 :     case END_CIRC_REASON_NOSUCHSERVICE:
     369           0 :       return "NOSUCHSERVICE";
     370           0 :     case END_CIRC_REASON_MEASUREMENT_EXPIRED:
     371           0 :       return "MEASUREMENT_EXPIRED";
     372           0 :     case END_CIRC_REASON_IP_NOW_REDUNDANT:
     373           0 :       return "IP_NOW_REDUNDANT";
     374           0 :     default:
     375           0 :       if (is_remote) {
     376             :         /*
     377             :          * If it's remote, it's not a bug *here*, so don't use LD_BUG, but
     378             :          * do note that the someone we're talking to is speaking the Tor
     379             :          * protocol with a weird accent.
     380             :          */
     381           0 :         log_warn(LD_PROTOCOL,
     382             :                  "Remote server sent bogus reason code %d", reason);
     383             :       } else {
     384           0 :         log_warn(LD_BUG,
     385             :                  "Unrecognized reason code %d", reason);
     386             :       }
     387             :       return NULL;
     388             :   }
     389             : }
     390             : 
     391             : /** Return a string corresponding to a SOCKS4 response code. */
     392             : const char *
     393           1 : socks4_response_code_to_string(uint8_t code)
     394             : {
     395           1 :   switch (code) {
     396             :     case 0x5a:
     397             :       return "connection accepted";
     398           1 :     case 0x5b:
     399           1 :       return "server rejected connection";
     400           0 :     case 0x5c:
     401           0 :       return "server cannot connect to identd on this client";
     402           0 :     case 0x5d:
     403           0 :       return "user id does not match identd";
     404           0 :     default:
     405           0 :       return "invalid SOCKS 4 response code";
     406             :   }
     407             : }
     408             : 
     409             : /** Return a string corresponding to a SOCKS5 response code. */
     410             : const char *
     411           1 : socks5_response_code_to_string(uint8_t code)
     412             : {
     413           1 :   switch (code) {
     414             :     case 0x00:
     415             :       return "connection accepted";
     416           0 :     case 0x01:
     417           0 :       return "general SOCKS server failure";
     418           0 :     case 0x02:
     419           0 :       return "connection not allowed by ruleset";
     420           1 :     case 0x03:
     421           1 :       return "Network unreachable";
     422           0 :     case 0x04:
     423           0 :       return "Host unreachable";
     424           0 :     case 0x05:
     425           0 :       return "Connection refused";
     426           0 :     case 0x06:
     427           0 :       return "TTL expired";
     428           0 :     case 0x07:
     429           0 :       return "Command not supported";
     430           0 :     case 0x08:
     431           0 :       return "Address type not supported";
     432           0 :     default:
     433           0 :       return "unknown reason";
     434             :   }
     435             : }
     436             : 
     437             : /** Return a string corresponding to a bandwidth_weight_rule_t */
     438             : const char *
     439        2746 : bandwidth_weight_rule_to_string(bandwidth_weight_rule_t rule)
     440             : {
     441        2746 :   switch (rule)
     442             :     {
     443             :     case NO_WEIGHTING:
     444             :       return "no weighting";
     445          63 :     case WEIGHT_FOR_EXIT:
     446          63 :       return "weight as exit";
     447         827 :     case WEIGHT_FOR_MID:
     448         827 :       return "weight as middle node";
     449        1847 :     case WEIGHT_FOR_GUARD:
     450        1847 :       return "weight as guard";
     451           9 :     case WEIGHT_FOR_DIR:
     452           9 :       return "weight as directory";
     453           0 :     default:
     454           0 :       return "unknown rule";
     455             :   }
     456             : }
     457             : 
     458             : /** Given a RELAY_END reason value, convert it to an HTTP response to be
     459             :  * send over an HTTP tunnel connection. */
     460             : const char *
     461           0 : end_reason_to_http_connect_response_line(int endreason)
     462             : {
     463           0 :   endreason &= END_STREAM_REASON_MASK;
     464             :   /* XXXX these are probably all wrong. Should they all be 502? */
     465           0 :   switch (endreason) {
     466             :     case 0:
     467             :       return "HTTP/1.0 200 OK\r\n\r\n";
     468           0 :     case END_STREAM_REASON_MISC:
     469           0 :       return "HTTP/1.0 500 Internal Server Error\r\n\r\n";
     470           0 :     case END_STREAM_REASON_RESOLVEFAILED:
     471           0 :       return "HTTP/1.0 404 Not Found (resolve failed)\r\n\r\n";
     472           0 :     case END_STREAM_REASON_NOROUTE:
     473           0 :       return "HTTP/1.0 404 Not Found (no route)\r\n\r\n";
     474           0 :     case END_STREAM_REASON_CONNECTREFUSED:
     475           0 :       return "HTTP/1.0 403 Forbidden (connection refused)\r\n\r\n";
     476           0 :     case END_STREAM_REASON_EXITPOLICY:
     477           0 :       return "HTTP/1.0 403 Forbidden (exit policy)\r\n\r\n";
     478           0 :     case END_STREAM_REASON_DESTROY:
     479           0 :       return "HTTP/1.0 502 Bad Gateway (destroy cell received)\r\n\r\n";
     480           0 :     case END_STREAM_REASON_DONE:
     481           0 :       return "HTTP/1.0 502 Bad Gateway (unexpected close)\r\n\r\n";
     482           0 :     case END_STREAM_REASON_TIMEOUT:
     483           0 :       return "HTTP/1.0 504 Gateway Timeout\r\n\r\n";
     484           0 :     case END_STREAM_REASON_HIBERNATING:
     485           0 :       return "HTTP/1.0 502 Bad Gateway (hibernating server)\r\n\r\n";
     486           0 :     case END_STREAM_REASON_INTERNAL:
     487           0 :       return "HTTP/1.0 502 Bad Gateway (internal error)\r\n\r\n";
     488           0 :     case END_STREAM_REASON_RESOURCELIMIT:
     489           0 :       return "HTTP/1.0 502 Bad Gateway (resource limit)\r\n\r\n";
     490           0 :     case END_STREAM_REASON_CONNRESET:
     491           0 :       return "HTTP/1.0 403 Forbidden (connection reset)\r\n\r\n";
     492           0 :     case END_STREAM_REASON_TORPROTOCOL:
     493           0 :       return "HTTP/1.0 502 Bad Gateway (tor protocol violation)\r\n\r\n";
     494           0 :     case END_STREAM_REASON_ENTRYPOLICY:
     495           0 :       return "HTTP/1.0 403 Forbidden (entry policy violation)\r\n\r\n";
     496           0 :     case END_STREAM_REASON_NOTDIRECTORY: FALLTHROUGH;
     497             :     default:
     498           0 :       tor_assert_nonfatal_unreached();
     499           0 :       return "HTTP/1.0 500 Internal Server Error (weird end reason)\r\n\r\n";
     500             :   }
     501             : }

Generated by: LCOV version 1.14