55#include "feature/client/circpathbias.h"
97#include "core/or/or_circuit_st.h"
145uint64_t stats_n_circ_max_cell_outq_reached = 0;
207 if (BUG(!or_circ->
p_chan))
212 if (cell->
command == CELL_RELAY_EARLY) {
216 }
else if (cell->
command == CELL_RELAY) {
251 if (relay_decrypt_cell(circ, cell, cell_direction, &layer_hint, &recognized)
254 "relay crypt failed. Dropping connection.");
255 return -END_CIRC_REASON_INTERNAL;
267 "Received undecodable relay cell");
268 return -END_CIRC_REASON_TORPROTOCOL;
285 log_debug(
LD_OR,
"Sending away from origin.");
289 "connection_edge_process_relay_cell (away from origin) "
295 log_debug(
LD_OR,
"Sending to origin.");
304 "connection_edge_process_relay_cell (at origin) failed.");
323 "Dropping unrecognized inbound cell on origin circuit.");
329 return -END_CIRC_REASON_TORPROTOCOL;
347 log_info(
LD_REND,
"Error relaying cell across rendezvous; closing "
355 return -END_CIRC_REASON_TORPROTOCOL;
361 "Didn't recognize a cell, but circ stops here! Closing circuit. "
362 "It was created %ld seconds ago.", (
long)seconds_open);
364 return -END_CIRC_REASON_TORPROTOCOL;
367 log_debug(
LD_OR,
"Passing on unrecognized cell.");
374 return -END_CIRC_REASON_RESOURCELIMIT;
390 const char *filename,
int lineno))
402 log_warn(
LD_BUG,
"outgoing relay cell sent from %s:%d has n_chan==NULL."
403 " Dropping. Circuit is in state %s (%d), and is "
404 "%smarked for close. (%s:%d, %d)", filename, lineno,
416 log_warn(
LD_BUG,
"outgoing relay cell sent from %s:%d on non-origin "
417 "circ. Dropping.", filename, lineno);
433 log_warn(
LD_BUG,
"incoming relay cell at origin circuit. Dropping.");
438 if (relay_encrypt_cell_inbound(cell, or_circ) < 0) {
446 cell_direction, on_stream);
467 if (msg->stream_id == tmpconn->
stream_id &&
470 log_debug(
LD_APP,
"found conn for stream %d.", msg->stream_id);
477 if (msg->stream_id == tmpconn->
stream_id &&
479 log_debug(LD_EXIT,
"found conn for stream %d.", msg->stream_id);
485 for (tmpconn =
TO_OR_CIRCUIT(circ)->resolving_streams; tmpconn;
487 if (msg->stream_id == tmpconn->
stream_id &&
489 log_debug(LD_EXIT,
"found conn for stream %d.", msg->stream_id);
503relay_header_pack(uint8_t *dest,
const relay_header_t *src)
508 memcpy(dest+5, src->integrity, 4);
516relay_header_unpack(relay_header_t *dest,
const uint8_t *src)
521 memcpy(dest->integrity, src+5, 4);
532 case RELAY_COMMAND_BEGIN:
return "BEGIN";
533 case RELAY_COMMAND_DATA:
return "DATA";
534 case RELAY_COMMAND_END:
return "END";
535 case RELAY_COMMAND_CONNECTED:
return "CONNECTED";
536 case RELAY_COMMAND_SENDME:
return "SENDME";
537 case RELAY_COMMAND_EXTEND:
return "EXTEND";
538 case RELAY_COMMAND_EXTENDED:
return "EXTENDED";
539 case RELAY_COMMAND_TRUNCATE:
return "TRUNCATE";
540 case RELAY_COMMAND_TRUNCATED:
return "TRUNCATED";
541 case RELAY_COMMAND_DROP:
return "DROP";
542 case RELAY_COMMAND_RESOLVE:
return "RESOLVE";
543 case RELAY_COMMAND_RESOLVED:
return "RESOLVED";
544 case RELAY_COMMAND_BEGIN_DIR:
return "BEGIN_DIR";
545 case RELAY_COMMAND_ESTABLISH_INTRO:
return "ESTABLISH_INTRO";
546 case RELAY_COMMAND_ESTABLISH_RENDEZVOUS:
return "ESTABLISH_RENDEZVOUS";
547 case RELAY_COMMAND_INTRODUCE1:
return "INTRODUCE1";
548 case RELAY_COMMAND_INTRODUCE2:
return "INTRODUCE2";
549 case RELAY_COMMAND_RENDEZVOUS1:
return "RENDEZVOUS1";
550 case RELAY_COMMAND_RENDEZVOUS2:
return "RENDEZVOUS2";
551 case RELAY_COMMAND_INTRO_ESTABLISHED:
return "INTRO_ESTABLISHED";
552 case RELAY_COMMAND_RENDEZVOUS_ESTABLISHED:
553 return "RENDEZVOUS_ESTABLISHED";
554 case RELAY_COMMAND_INTRODUCE_ACK:
return "INTRODUCE_ACK";
555 case RELAY_COMMAND_EXTEND2:
return "EXTEND2";
556 case RELAY_COMMAND_EXTENDED2:
return "EXTENDED2";
557 case RELAY_COMMAND_PADDING_NEGOTIATE:
return "PADDING_NEGOTIATE";
558 case RELAY_COMMAND_PADDING_NEGOTIATED:
return "PADDING_NEGOTIATED";
559 case RELAY_COMMAND_CONFLUX_LINK:
return "CONFLUX_LINK";
560 case RELAY_COMMAND_CONFLUX_LINKED:
return "CONFLUX_LINKED";
561 case RELAY_COMMAND_CONFLUX_LINKED_ACK:
return "CONFLUX_LINKED_ACK";
562 case RELAY_COMMAND_CONFLUX_SWITCH:
return "CONFLUX_SWITCH";
564 tor_snprintf(buf,
sizeof(buf),
"Unrecognized relay command %u",
581 uint8_t relay_command,
const char *payload,
583 const char *filename,
int lineno))
620 log_warn(
LD_BUG,
"Tried to send a command %d of length %d in "
621 "a v%d cell, from %s:%d",
622 (
int)relay_command, (
int)payload_len, (
int)cell_format,
624 circuit_mark_for_close(circ, END_CIRC_REASON_INTERNAL);
628 msg.command = relay_command;
629 msg.stream_id = stream_id;
630 msg.length = payload_len;
631 msg.body = (
const uint8_t *) payload;
632 msg_body_len = msg.length;
635 msg.is_relay_early =
false;
639 circuit_mark_for_close(circ, END_CIRC_REASON_INTERNAL);
655 log_debug(
LD_OR,
"delivering %d cell %s.", relay_command,
663 if (relay_command == RELAY_COMMAND_END && circ->
dirreq_id)
664 geoip_change_dirreq_state(circ->
dirreq_id, DIRREQ_TUNNELED,
675 (relay_command == RELAY_COMMAND_EXTEND ||
676 relay_command == RELAY_COMMAND_EXTEND2 ||
677 cpath_layer != origin_circ->
cpath)) {
682 cell.
command = CELL_RELAY_EARLY;
686 log_debug(
LD_OR,
"Sending a RELAY_EARLY cell; %d remaining.",
692 }
else if (relay_command == RELAY_COMMAND_EXTEND ||
693 relay_command == RELAY_COMMAND_EXTEND2) {
699 char *commands = NULL;
704 log_warn(
LD_BUG,
"Uh-oh. We're sending a RELAY_COMMAND_EXTEND cell, "
705 "but we have run out of RELAY_EARLY cells on that circuit. "
706 "Commands sent before: %s", commands);
708 smartlist_free(commands_list);
717 cpath_layer, stream_id, filename,
720 circuit_mark_for_close(circ, END_CIRC_REASON_INTERNAL);
722 }
else if (ret == 0) {
740 if (relay_command == RELAY_COMMAND_DATA) {
741 sendme_record_cell_digest_on_circ(circ, cpath_layer);
744 if (sendme_note_circuit_data_packaged(circ, cpath_layer) < 0) {
747 "Circuit package window is below 0. Closing circuit.");
748 circuit_mark_for_close(circ, END_CIRC_REASON_TORPROTOCOL);
767 uint8_t relay_command,
const char *payload,
779 "called on conn that's already marked for close at %s:%d.",
787 log_info(
LD_APP,
"no circ. Closing conn.");
789 END_STREAM_REASON_INTERNAL);
791 log_info(LD_EXIT,
"no circ. Closing conn.");
793 fromconn->
end_reason = END_STREAM_REASON_INTERNAL;
794 connection_mark_for_close(
TO_CONN(fromconn));
805#ifdef MEASUREMENTS_21206
815 return relay_send_command_from_edge(fromconn->
stream_id, circ,
816 relay_command, payload,
817 payload_len, cpath_layer);
823#define MAX_RESOLVE_FAILURES 3
830 return reason == END_STREAM_REASON_HIBERNATING ||
831 reason == END_STREAM_REASON_RESOURCELIMIT ||
832 reason == END_STREAM_REASON_EXITPOLICY ||
833 reason == END_STREAM_REASON_RESOLVEFAILED ||
834 reason == END_STREAM_REASON_MISC ||
835 reason == END_STREAM_REASON_NOROUTE;
850 if (msg->length == 0) {
851 return -END_CIRC_REASON_TORPROTOCOL;
858 if (msg->length > 0) {
859 if (reason == END_STREAM_REASON_TORPROTOCOL ||
860 reason == END_STREAM_REASON_DESTROY) {
865 return -END_CIRC_REASON_TORPROTOCOL;
866 }
else if (reason == END_STREAM_REASON_INTERNAL) {
890 control_reason = (reason ? reason : END_STREAM_REASON_MISC) |
900 const char *chosen_exit_digest =
902 log_info(
LD_APP,
"Address '%s' refused due to '%s'. Considering retrying.",
907 case END_STREAM_REASON_EXITPOLICY: {
910 if (msg->length >= 5) {
913 if (msg->length == 5 || msg->length == 9) {
915 if (msg->length == 9)
917 }
else if (msg->length == 17 || msg->length == 21) {
919 if (msg->length == 21)
923 log_info(
LD_APP,
"Address '%s' resolved to 0.0.0.0. Closing,",
925 connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL);
930 !conn->entry_cfg.ipv4_traffic) ||
932 !conn->entry_cfg.ipv6_traffic)) {
934 "Got an EXITPOLICY failure on a connection with a "
935 "mismatched family. Closing.");
936 connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL);
939 if (
get_options()->ClientDNSRejectInternalAddresses &&
940 tor_addr_is_internal(&addr, 0)) {
941 log_info(
LD_APP,
"Address '%s' resolved to internal. Closing,",
943 connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL);
987 case END_STREAM_REASON_CONNECTREFUSED:
993 case END_STREAM_REASON_RESOLVEFAILED:
994 case END_STREAM_REASON_TIMEOUT:
995 case END_STREAM_REASON_MISC:
996 case END_STREAM_REASON_NOROUTE:
1014 "Have tried resolving or connecting to address '%s' "
1015 "at %d different places. Giving up.",
1022 case END_STREAM_REASON_HIBERNATING:
1023 case END_STREAM_REASON_RESOURCELIMIT:
1037 log_info(
LD_APP,
"Giving up on retrying; conn can't be handled.");
1041 "Edge got end (%s) before we're connected. Marking for close.",
1046 connection_mark_unattached_ap(conn, control_reason);
1065 int make_reject_all = 0;
1071 if (family == AF_UNSPEC) {
1072 make_reject_all = 1;
1075 make_reject_all = 1;
1078 if (make_reject_all) {
1080 "Exitrouter %s seems to be more restrictive than its exit "
1081 "policy. Not using this router as exit for now.",
1087 if (family != AF_UNSPEC)
1119 const uint8_t *payload = msg->body;
1123 if (msg->length == 0)
1125 if (msg->length < 4)
1133 if (msg->length >= 8) {
1135 if (bytes <= INT32_MAX)
1139 if (msg->length < 25)
1145 if (bytes <= INT32_MAX)
1146 *ttl_out = (int) bytes;
1171 uint8_t answer_type;
1173 address_ttl_t *addr;
1191 remaining = msg->length;
1193 const uint8_t *cp_orig = cp;
1196 answer_type = *cp++;
1198 if (remaining < 2 + answer_len + 4) {
1201 if (answer_type == RESOLVED_TYPE_IPV4) {
1202 if (answer_len != 4) {
1205 addr = tor_malloc_zero(
sizeof(*addr));
1211 }
else if (answer_type == RESOLVED_TYPE_IPV6) {
1212 if (answer_len != 16)
1214 addr = tor_malloc_zero(
sizeof(*addr));
1220 }
else if (answer_type == RESOLVED_TYPE_HOSTNAME) {
1221 if (answer_len == 0) {
1224 addr = tor_malloc_zero(
sizeof(*addr));
1225 addr->hostname = tor_memdup_nulterm(cp, answer_len);
1230 }
else if (answer_type == RESOLVED_TYPE_ERROR_TRANSIENT ||
1231 answer_type == RESOLVED_TYPE_ERROR) {
1232 errcode = answer_type;
1234 cp += answer_len + 4;
1236 cp += answer_len + 4;
1238 tor_assert(((ssize_t)remaining) >= (cp - cp_orig));
1239 remaining -= (cp - cp_orig);
1242 if (errcode && smartlist_len(addrs) == 0) {
1244 *errcode_out = errcode;
1248 smartlist_free(addrs);
1255 smartlist_free(addrs);
1267 address_ttl_t *addr_ipv4 = NULL;
1268 address_ttl_t *addr_ipv6 = NULL;
1269 address_ttl_t *addr_hostname = NULL;
1270 address_ttl_t *addr_best = NULL;
1274 tor_assert(error_code == RESOLVED_TYPE_ERROR ||
1275 error_code == RESOLVED_TYPE_ERROR_TRANSIENT);
1277 error_code,0,NULL,-1,-1);
1283 if (addr->hostname) {
1284 if (!addr_hostname) {
1285 addr_hostname = addr;
1288 if (!addr_ipv4 && conn->entry_cfg.ipv4_traffic) {
1292 if (!addr_ipv6 && conn->entry_cfg.ipv6_traffic) {
1296 } SMARTLIST_FOREACH_END(addr);
1300 if (addr_hostname) {
1302 RESOLVED_TYPE_HOSTNAME,
1303 strlen(addr_hostname->hostname),
1304 (uint8_t*)addr_hostname->hostname,
1305 addr_hostname->ttl,-1);
1308 RESOLVED_TYPE_ERROR,0,NULL,-1,-1);
1313 if (conn->entry_cfg.prefer_ipv6) {
1314 addr_best = addr_ipv6 ? addr_ipv6 : addr_ipv4;
1316 addr_best = addr_ipv4 ? addr_ipv4 : addr_ipv6;
1322 RESOLVED_TYPE_NOERROR,0,NULL,-1,-1);
1345 log_fn(LOG_PROTOCOL_WARN,
LD_APP,
"Got a 'resolved' cell while "
1346 "not in state resolve_wait. Dropping.");
1354 "Dropping malformed 'resolved' cell");
1355 connection_mark_unattached_ap(entry_conn, END_STREAM_REASON_TORPROTOCOL);
1359 if (
get_options()->ClientDNSRejectInternalAddresses) {
1360 int orig_len = smartlist_len(resolved_addresses);
1362 if (addr->hostname == NULL && tor_addr_is_internal(&addr->addr, 0)) {
1363 log_info(
LD_APP,
"Got a resolved cell with answer %s; dropping that "
1365 safe_str_client(
fmt_addr(&addr->addr)));
1366 address_ttl_free(addr);
1369 } SMARTLIST_FOREACH_END(addr);
1370 if (orig_len && smartlist_len(resolved_addresses) == 0) {
1371 log_info(
LD_APP,
"Got a resolved cell with only private addresses; "
1374 RESOLVED_TYPE_ERROR_TRANSIENT,
1375 0, NULL, 0, TIME_MAX);
1376 connection_mark_unattached_ap(entry_conn,
1377 END_STREAM_REASON_TORPROTOCOL);
1390 resolved_addresses);
1392 connection_mark_unattached_ap(entry_conn,
1393 END_STREAM_REASON_DONE |
1398 address_ttl_free(addr));
1399 smartlist_free(resolved_addresses);
1415 if (msg->command == RELAY_COMMAND_END) {
1417 if (msg->length == 0) {
1418 return -END_CIRC_REASON_TORPROTOCOL;
1429 connection_mark_for_close(
TO_CONN(conn));
1435 msg->command == RELAY_COMMAND_CONNECTED) {
1442 "Got 'connected' while not in state connect_wait. Dropping.");
1445 CONNECTION_AP_EXPECT_NONPENDING(entry_conn);
1447 log_info(
LD_APP,
"'connected' received for circid %u streamid %d "
1448 "after %d seconds.",
1454 "Got a badly formatted connected cell. Closing.");
1456 connection_mark_unattached_ap(entry_conn, END_STREAM_REASON_TORPROTOCOL);
1465 (
get_options()->ClientDNSRejectInternalAddresses &&
1466 tor_addr_is_internal(&addr, 0))) {
1467 log_info(
LD_APP,
"...but it claims the IP address was %s. Closing.",
1470 connection_mark_unattached_ap(entry_conn,
1471 END_STREAM_REASON_TORPROTOCOL);
1475 if ((family == AF_INET && ! entry_conn->entry_cfg.ipv4_traffic) ||
1476 (family == AF_INET6 && ! entry_conn->entry_cfg.ipv6_traffic)) {
1478 "Got a connected cell to %s with unsupported address family."
1479 " Closing.", safe_str(
fmt_addr(&addr)));
1481 connection_mark_unattached_ap(entry_conn,
1482 END_STREAM_REASON_TORPROTOCOL);
1501 log_debug(
LD_APP,
"considering");
1502 if (
TO_CONN(conn)->linked_conn &&
1535 connection_mark_for_close(
TO_CONN(conn));
1541 msg->command == RELAY_COMMAND_RESOLVED) {
1546 "Got an unexpected relay command %d, in state %d (%s). Dropping.",
1547 msg->command, conn->base_.
state,
1571 if (!msg->stream_id) {
1573 ret = sendme_process_circuit_level(layer_hint, circ, msg->body,
1592 log_info(domain,
"Sendme cell on circ %u valid on half-closed "
1598 log_info(domain,
"SENDME cell dropped, unknown stream (streamid %d).",
1605 ret = sendme_process_stream_level(conn, circ, msg->length);
1624 connection_mark_for_close(
TO_CONN(conn));
1641 int optimistic_data)
1643 unsigned domain = layer_hint?
LD_APP:LD_EXIT;
1651 log_debug(domain,
"Cell handled as circuit padding");
1656 switch (msg->command) {
1657 case RELAY_COMMAND_CONFLUX_LINK:
1660 case RELAY_COMMAND_CONFLUX_LINKED:
1663 case RELAY_COMMAND_CONFLUX_LINKED_ACK:
1666 case RELAY_COMMAND_CONFLUX_SWITCH:
1668 case RELAY_COMMAND_BEGIN:
1669 case RELAY_COMMAND_BEGIN_DIR:
1673 "Relay begin request unsupported at AP. Dropping.");
1679 "Relay begin request to Hidden Service "
1680 "from intermediary node. Dropping.");
1684 log_fn(LOG_PROTOCOL_WARN, domain,
1685 "Begin cell for known stream. Dropping.");
1688 if (msg->command == RELAY_COMMAND_BEGIN_DIR &&
1694 static uint64_t next_id = 0;
1699 case RELAY_COMMAND_DATA:
1702 if (msg->stream_id == 0) {
1704 "stream_id. Dropping.");
1713 "data cell on circ %u valid on half-closed "
1718 log_info(domain,
"data cell dropped, unknown stream (streamid %d).",
1726 if (sendme_stream_data_received(conn) < 0) {
1728 "(relay data) conn deliver_window below 0. Killing.");
1730 return -END_CIRC_REASON_TORPROTOCOL;
1738 if (conn->hs_ident) {
1745 connection_buf_add((
char*) msg->body, msg->length,
TO_CONN(conn));
1747#ifdef MEASUREMENTS_21206
1753 ++(
TO_DIR_CONN(linked_conn)->data_cells_received);
1757 if (!optimistic_data) {
1765 case RELAY_COMMAND_XOFF:
1784 case RELAY_COMMAND_XON:
1803 case RELAY_COMMAND_END:
1805 if (msg->length == 0) {
1806 return -END_CIRC_REASON_TORPROTOCOL;
1812 reason = END_STREAM_REASON_MISC;
1823 "end cell (%s) on circ %u valid on half-closed "
1830 log_info(domain,
"end cell (%s) dropped, unknown stream.",
1835 log_info(domain,TOR_SOCKET_T_FORMAT
": end cell (%s) for stream %d. "
1845 "open stream hasn't sent socks answer yet? Closing.");
1854 connection_mark_and_flush(
TO_CONN(conn));
1862 case RELAY_COMMAND_EXTEND:
1863 case RELAY_COMMAND_EXTEND2: {
1864 static uint64_t total_n_extend=0, total_nonearly=0;
1866 if (msg->stream_id) {
1867 log_fn(LOG_PROTOCOL_WARN, domain,
1868 "'extend' cell received for non-zero stream. Dropping.");
1871 if (!msg->is_relay_early &&
1873#define EARLY_WARNING_INTERVAL 3600
1875 RATELIM_INIT(EARLY_WARNING_INTERVAL);
1877 if (!msg->is_relay_early) {
1880 double percentage = ((double)total_nonearly)/total_n_extend;
1882 log_fn(LOG_PROTOCOL_WARN, domain,
"EXTEND cell received, "
1883 "but not via RELAY_EARLY. Dropping.%s", m);
1884 log_fn(LOG_PROTOCOL_WARN, domain,
" (We have dropped %.02f%% of "
1885 "all EXTEND cells for this reason)", percentage);
1890 "EXTEND cell received, in a cell with type %d! Dropping.",
1897 case RELAY_COMMAND_EXTENDED:
1898 case RELAY_COMMAND_EXTENDED2:
1901 "'extended' unsupported at non-origin. Dropping.");
1904 log_debug(domain,
"Got an extended cell! Yay.");
1908 msg->body, msg->length) < 0) {
1910 "Can't parse EXTENDED cell; killing circuit.");
1911 return -END_CIRC_REASON_TORPROTOCOL;
1915 circuit_mark_for_close(circ, -reason);
1921 log_info(domain,
"circuit_send_next_onion_skin() failed.");
1929 case RELAY_COMMAND_TRUNCATE:
1932 "'truncate' unsupported at origin. Dropping.");
1937 log_warn(
LD_BUG,
"n_chan and n_hop set on the same circuit!");
1938 extend_info_free(circ->
n_hop);
1945 if (msg->length == 0) {
1946 return -END_CIRC_REASON_TORPROTOCOL;
1948 uint8_t trunc_reason =
get_uint8(msg->body);
1955 log_debug(LD_EXIT,
"Processed 'truncate', replying.");
1958 payload[0] = (char)END_CIRC_REASON_REQUESTED;
1959 relay_send_command_from_edge(0, circ, RELAY_COMMAND_TRUNCATED,
1960 payload,
sizeof(payload), NULL);
1963 case RELAY_COMMAND_TRUNCATED:
1965 log_fn(LOG_PROTOCOL_WARN, LD_EXIT,
1966 "'truncated' unsupported at non-origin. Dropping.");
1976 if (msg->length == 0) {
1977 return -END_CIRC_REASON_TORPROTOCOL;
1981 case RELAY_COMMAND_CONNECTED:
1984 "'connected' unsupported while open. Closing circ.");
1985 return -END_CIRC_REASON_TORPROTOCOL;
1994 "connected cell on circ %u valid on half-closed "
2001 "'connected' received on circid %u for streamid %d, "
2002 "no conn attached anymore. Ignoring.",
2003 (
unsigned)circ->
n_circ_id, msg->stream_id);
2005 case RELAY_COMMAND_SENDME:
2007 case RELAY_COMMAND_RESOLVE:
2010 "resolve request unsupported at AP; dropping.");
2013 log_fn(LOG_PROTOCOL_WARN, domain,
2014 "resolve request for known stream; dropping.");
2017 log_fn(LOG_PROTOCOL_WARN, domain,
2018 "resolve request on circ with purpose %d; dropping",
2023 case RELAY_COMMAND_RESOLVED:
2025 log_fn(LOG_PROTOCOL_WARN, domain,
2026 "'resolved' unsupported while open. Closing circ.");
2027 return -END_CIRC_REASON_TORPROTOCOL;
2037 "resolved cell on circ %u valid on half-closed "
2044 "'resolved' received, no conn attached anymore. Ignoring.");
2046 case RELAY_COMMAND_ESTABLISH_INTRO:
2047 case RELAY_COMMAND_ESTABLISH_RENDEZVOUS:
2048 case RELAY_COMMAND_INTRODUCE1:
2049 case RELAY_COMMAND_INTRODUCE2:
2050 case RELAY_COMMAND_INTRODUCE_ACK:
2051 case RELAY_COMMAND_RENDEZVOUS1:
2052 case RELAY_COMMAND_RENDEZVOUS2:
2053 case RELAY_COMMAND_INTRO_ESTABLISHED:
2054 case RELAY_COMMAND_RENDEZVOUS_ESTABLISHED:
2056 msg->command, msg->length, msg->body);
2060 "Received unknown relay command %d. Perhaps the other side is using "
2061 "a newer version of Tor? Dropping.",
2080 static int num_seen=0;
2081 unsigned domain = layer_hint?
LD_APP:LD_EXIT;
2088 log_debug(domain,
"Now seen %d relay cells here (command %d, stream %d).",
2089 num_seen, msg->command, msg->stream_id);
2091 if (msg->stream_id == 0) {
2092 switch (msg->command) {
2093 case RELAY_COMMAND_BEGIN:
2094 case RELAY_COMMAND_CONNECTED:
2095 case RELAY_COMMAND_END:
2096 case RELAY_COMMAND_RESOLVE:
2097 case RELAY_COMMAND_RESOLVED:
2098 case RELAY_COMMAND_BEGIN_DIR:
2100 "stream_id. Dropping.", msg->command);
2110 if (msg->command == RELAY_COMMAND_DATA) {
2114 if (sendme_circuit_data_received(circ, layer_hint) < 0) {
2116 "(relay data) circ deliver_window below 0. Killing.");
2118 return -END_CIRC_REASON_TORPROTOCOL;
2147 msg, circ, conn, layer_hint);
2162 conflux_relay_msg_free(c_msg);
2165 conflux_relay_msg_free(c_msg);
2182 int optimistic_data = 0;
2195 msg->command == RELAY_COMMAND_DATA) {
2199 optimistic_data = 1;
2200 }
else if (msg->stream_id == 0 && msg->command == RELAY_COMMAND_DATA) {
2201 log_warn(
LD_BUG,
"Somehow I had a connection that matched a "
2202 "data cell with stream ID 0.");
2205 msg, circ, conn, layer_hint);
2245 int package_partial,
2253 const bool force_random_bytes =
2258 size_t target_length =
2261#define RELAY_CELL_PADDING_GAP 4
2265 size_t target_length_with_random = target_length -
2266 RELAY_CELL_PADDING_GAP - 16;
2267 if (force_random_bytes) {
2268 target_length = target_length_with_random;
2272 size_t package_length;
2273 if (n_available >= target_length) {
2274 package_length = target_length;
2276 if (package_partial)
2277 package_length = n_available;
2283 tor_assert_nonfatal(package_length > 0);
2285 if (package_length <= target_length_with_random) {
2301 return package_length;
2318 size_t bytes_to_process, length;
2322 int sending_from_optimistic = 0;
2325 const int sending_optimistically =
2335 "called on conn that's already marked for close at %s:%d.",
2340 if (max_cells && *max_cells <= 0)
2343 repeat_connection_edge_package_raw_inbuf:
2347 log_info(domain,
"conn has no circuit! Closing.");
2356 log_info(domain,
"called with package_window %d. Skipping.",
2362 sending_from_optimistic = entry_conn &&
2363 entry_conn->sending_optimistic_data != NULL;
2365 if (PREDICT_UNLIKELY(sending_from_optimistic)) {
2366 bytes_to_process =
buf_datalen(entry_conn->sending_optimistic_data);
2367 if (PREDICT_UNLIKELY(!bytes_to_process)) {
2368 log_warn(
LD_BUG,
"sending_optimistic_data was non-NULL but empty");
2369 bytes_to_process = connection_get_inbuf_len(
TO_CONN(conn));
2370 sending_from_optimistic = 0;
2373 bytes_to_process = connection_get_inbuf_len(
TO_CONN(conn));
2377 package_partial, circ,
2388 if (PREDICT_UNLIKELY(sending_from_optimistic)) {
2392 buf_get_bytes(entry_conn->sending_optimistic_data, payload, length);
2393 if (!
buf_datalen(entry_conn->sending_optimistic_data)) {
2394 buf_free(entry_conn->sending_optimistic_data);
2395 entry_conn->sending_optimistic_data = NULL;
2401 log_debug(domain,TOR_SOCKET_T_FORMAT
": Packaging %d bytes (%d waiting).",
2403 (
int)length, (
int)connection_get_inbuf_len(
TO_CONN(conn)));
2405 if (sending_optimistically && !sending_from_optimistic) {
2415 payload, length) < 0 ) {
2421 if (sendme_note_stream_data_packaged(conn, length) < 0) {
2423 log_debug(domain,
"conn->package_window reached 0.");
2427 log_debug(domain,
"conn->package_window is now %d",conn->
package_window);
2431 if (*max_cells <= 0)
2436 goto repeat_connection_edge_package_raw_inbuf;
2448 log_debug(layer_hint?
LD_APP:LD_EXIT,
"Too big queue, no resuming");
2455 log_debug(layer_hint?
LD_APP:LD_EXIT,
2456 "Conflux can't send, not resuming edges");
2460 log_debug(layer_hint?
LD_APP:LD_EXIT,
"resuming");
2480 int n_packaging_streams, n_streams_left;
2481 int packaged_this_round;
2487 if (first_conn == NULL) {
2505 int num_streams = 0;
2506 for (conn = first_conn; conn; conn = conn->
next_stream) {
2510 chosen_stream = conn;
2527 n_packaging_streams = 0;
2529 for (conn=chosen_stream; conn; conn = conn->
next_stream) {
2539 if (connection_get_inbuf_len(
TO_CONN(conn)) > 0)
2540 ++n_packaging_streams;
2544 for (conn = first_conn; conn != chosen_stream; conn = conn->
next_stream) {
2553 if (connection_get_inbuf_len(
TO_CONN(conn)) > 0)
2554 ++n_packaging_streams;
2558 if (n_packaging_streams == 0)
2589 cells_per_conn = CEIL_DIV(max_to_package, n_packaging_streams);
2591 packaged_this_round = 0;
2599 for (conn=first_conn; conn; conn=conn->
next_stream) {
2603 int n = cells_per_conn, r;
2608 packaged_this_round += (cells_per_conn-n);
2613 connection_mark_for_close(
TO_CONN(conn));
2618 if (connection_get_inbuf_len(
TO_CONN(conn)))
2634 if (packaged_this_round && packaged_this_round < max_to_package &&
2636 n_packaging_streams = n_streams_left;
2653 unsigned domain = layer_hint ?
LD_APP : LD_EXIT;
2657 log_debug(domain,
"considering circ->package_window %d",
2660 log_debug(domain,
"yes, not-at-origin. stopped.");
2668 log_debug(domain,
"considering layer_hint->package_window %d",
2671 log_debug(domain,
"yes, at-origin. stopped.");
2718 n_cells += c->n_chan_cells.n;
2723 SMARTLIST_FOREACH_END(c);
2725 "%d cells allocated on %d circuits. %d cells leaked.",
2742 TOR_SIMPLEQ_INSERT_TAIL(&queue->head, cell, next);
2752 int exitward,
const cell_t *cell,
2753 int wide_circ_ids,
int use_stats)
2770 TOR_SIMPLEQ_INIT(&queue->head);
2778 while ((cell = TOR_SIMPLEQ_FIRST(&queue->head))) {
2779 TOR_SIMPLEQ_REMOVE_HEAD(&queue->head, next);
2782 TOR_SIMPLEQ_INIT(&queue->head);
2794 TOR_SIMPLEQ_REMOVE_HEAD(&queue->head, next);
2804 TOR_SIMPLEQ_INIT(&queue->head);
2812 while ((cell = TOR_SIMPLEQ_FIRST(&queue->head))) {
2813 TOR_SIMPLEQ_REMOVE_HEAD(&queue->head, next);
2816 TOR_SIMPLEQ_INIT(&queue->head);
2828 TOR_SIMPLEQ_REMOVE_HEAD(&queue->head, next);
2840 cell->circid = circid;
2841 cell->reason = reason;
2845 TOR_SIMPLEQ_INSERT_TAIL(&queue->head, cell, next);
2855 memset(&cell, 0,
sizeof(cell));
2858 cell.
payload[0] = inp->reason;
2859 cell_pack(packed, &cell, wide_circ_ids);
2875cell_queues_get_total_allocation(
void)
2881#define MEMORY_PRESSURE_INTERVAL (30*60)
2888uint64_t oom_stats_n_bytes_removed_cell = 0;
2889uint64_t oom_stats_n_bytes_removed_geoip = 0;
2890uint64_t oom_stats_n_bytes_removed_hsdir = 0;
2903 time_t now = time(NULL);
2904 size_t alloc = cell_queues_get_total_allocation();
2906 alloc += buf_get_total_allocation();
2908 const size_t hs_cache_total = hs_cache_get_total_allocation();
2909 alloc += hs_cache_total;
2910 const size_t geoip_client_cache_total =
2911 geoip_client_cache_total_allocation();
2912 alloc += geoip_client_cache_total;
2913 const size_t dns_cache_total = dns_cache_total_allocation();
2914 alloc += dns_cache_total;
2916 alloc += conflux_total;
2918 if (alloc >=
get_options()->MaxMemInQueues_low_threshold) {
2921 if (alloc >=
get_options()->MaxMemInQueues && ! reclaim_immediately) {
2934 }
else if (alloc >=
get_options()->MaxMemInQueues && reclaim_immediately) {
2943 const size_t bytes_to_remove =
2946 oom_stats_n_bytes_removed_hsdir += removed;
2948 static ratelim_t hs_cache_oom_ratelim = RATELIM_INIT(600);
2950 "HSDir cache exceeded limit "
2951 "(%"TOR_PRIuSZ
" > %"PRIu64
" bytes). "
2952 "Pruned %"TOR_PRIuSZ
" bytes during cell_queues_check_size.",
2955 if (geoip_client_cache_total >
get_options()->MaxMemInQueues / 5) {
2956 const size_t bytes_to_remove =
2957 geoip_client_cache_total -
2959 removed = geoip_client_cache_handle_oom(now, bytes_to_remove);
2960 oom_stats_n_bytes_removed_geoip += removed;
2963 if (dns_cache_total >
get_options()->MaxMemInQueues / 5) {
2964 const size_t bytes_to_remove =
2965 dns_cache_total - (size_t)(
get_options()->MaxMemInQueues / 10);
2966 removed = dns_cache_handle_oom(now, bytes_to_remove);
2971 if (conflux_total >
get_options()->MaxMemInQueues / 5) {
2972 const size_t bytes_to_remove =
2973 conflux_total - (size_t)(
get_options()->MaxMemInQueues / 10);
2975 oom_stats_n_bytes_removed_cell += removed;
2979 oom_stats_n_bytes_removed_cell += removed;
3025 const char *file,
int lineno)
3029 circuitmux_t *cmux = NULL;
3049 log_warn(
LD_BUG,
"called on non-attached circuit from %s:%d",
3076 chan->num_p_circuits = 0;
3091 if (circ->
n_chan == chan) {
3119 if (block && can_send) {
3122 }
else if (!block && !can_send) {
3130 if (stream_id && edge->stream_id != stream_id)
3133 if (!conn->
read_event || edge->xoff_received ||
3154 if (wide_circ_ids) {
3165 if (wide_circ_ids) {
3179 circuitmux_t *cmux = NULL;
3194 while (n_flushed < max) {
3196 if (destroy_queue) {
3223 if (circ->
n_chan == chan) {
3249 if (queue->
n == 0) {
3252 circuit_mark_for_close(circ, END_CIRC_REASON_INTERNAL);
3269 uint32_t msec_waiting =
3287 if (circ->
n_chan == chan)
3298 geoip_change_dirreq_state(chan->
dirreq_id,
3327 log_debug(
LD_GENERAL,
"Made a circuit inactive.");
3368#define RELAY_CIRC_CELL_QUEUE_SIZE_MIN 50
3370#define RELAY_CIRC_CELL_QUEUE_SIZE_MAX INT32_MAX
3374#define RELAY_CIRC_CELL_QUEUE_SIZE_DEFAULT \
3375 (50 * RELAY_CIRC_CELL_QUEUE_SIZE_MIN)
3379static int32_t max_circuit_cell_queue_size =
3380 RELAY_CIRC_CELL_QUEUE_SIZE_DEFAULT;
3385 RELAY_CIRC_CELL_QUEUE_SIZE_DEFAULT;
3393 RELAY_CIRC_CELL_QUEUE_SIZE_DEFAULT,
3394 RELAY_CIRC_CELL_QUEUE_SIZE_MIN,
3395 RELAY_CIRC_CELL_QUEUE_SIZE_MAX);
3405 RELAY_CIRC_CELL_QUEUE_SIZE_MIN,
3406 RELAY_CIRC_CELL_QUEUE_SIZE_MAX);
3418 max_circuit_cell_queue_size =
3444 int32_t max_queue_size;
3462 max_queue_size = max_circuit_cell_queue_size;
3466 if (PREDICT_UNLIKELY(queue->
n >= max_queue_size)) {
3470 stats_n_circ_max_cell_outq_reached++;
3471 dos_note_circ_max_outq(CONST_TO_OR_CIRCUIT(circ)->p_chan);
3475 "%s circuit has %d cells in its queue, maximum allowed is %d. "
3476 "Closing circuit for safety reasons.",
3477 (exitward) ?
"Outbound" :
"Inbound", queue->
n,
3486 chan->wide_circ_ids, 1);
3501 if (circ_blocked && fromstream) {
3508 update_circuit_on_cmux(circ, direction);
3509 if (queue->
n == 1) {
3512 log_debug(
LD_GENERAL,
"Made a circuit active.");
3533 payload_out[0] = RESOLVED_TYPE_IPV4;
3536 memcpy(payload_out+2, &a, 4);
3539 payload_out[0] = RESOLVED_TYPE_IPV6;
3540 payload_out[1] = 16;
3557 if (payload_len < 2)
3559 if (payload_len < 2+payload[1])
3562 switch (payload[0]) {
3563 case RESOLVED_TYPE_IPV4:
3564 if (payload[1] != 4)
3568 case RESOLVED_TYPE_IPV6:
3569 if (payload[1] != 16)
3577 return payload + 2 + payload[1];
3587 if (circ->
n_chan == chan) {
3602 update_circuit_on_cmux(circ, direction);
3631 tor_assert_unreached();
3641 uint8_t relay_command)
void tor_addr_from_ipv4n(tor_addr_t *dest, uint32_t v4addr)
void tor_addr_make_unspec(tor_addr_t *a)
int tor_addr_parse(tor_addr_t *addr, const char *src)
int tor_addr_is_null(const tor_addr_t *addr)
const char * tor_addr_to_str(char *dest, const tor_addr_t *addr, size_t len, int decorate)
void tor_addr_from_ipv6_bytes(tor_addr_t *dest, const uint8_t *ipv6_bytes)
static uint32_t tor_addr_to_ipv4n(const tor_addr_t *a)
static sa_family_t tor_addr_family(const tor_addr_t *a)
#define tor_addr_to_in6_addr8(x)
#define tor_addr_from_ipv4h(dest, v4addr)
int client_dns_incr_failures(const char *address)
void client_dns_set_addressmap(entry_connection_t *for_conn, const char *address, const tor_addr_t *val, const char *exitname, int ttl)
void client_dns_clear_failures(const char *address)
int buf_add(buf_t *buf, const char *string, size_t string_len)
size_t buf_datalen(const buf_t *buf)
int buf_get_bytes(buf_t *buf, char *string, size_t string_len)
Header file for buffers.c.
static void set_uint16(void *cp, uint16_t v)
static uint16_t get_uint16(const void *cp)
static uint8_t get_uint8(const void *cp)
static void set_uint8(void *cp, uint8_t v)
static uint32_t get_uint32(const void *cp)
Fixed-size cell structure.
void channel_timestamp_client(channel_t *chan)
int channel_send_destroy(circid_t circ_id, channel_t *chan, int reason)
int channel_is_client(const channel_t *chan)
void channel_mark_for_close(channel_t *chan)
int channel_write_packed_cell(channel_t *chan, packed_cell_t *cell)
Header file for channel.c.
void pathbias_count_valid_cells(circuit_t *circ, const relay_msg_t *msg)
int pathbias_check_probe_response(circuit_t *circ, const relay_msg_t *msg)
void pathbias_mark_use_success(origin_circuit_t *circ)
void circuit_log_path(int severity, unsigned int domain, origin_circuit_t *circ)
int circuit_send_next_onion_skin(origin_circuit_t *circ)
int circuit_finish_handshake(origin_circuit_t *circ, const created_cell_t *reply)
int circuit_truncated(origin_circuit_t *circ, int reason)
Header file for circuitbuild.c.
int circuit_extend(const relay_msg_t *rmsg, struct circuit_t *circ)
Header for feature/relay/circuitbuild_relay.c.
void circuit_synchronize_written_or_bandwidth(const circuit_t *c, circuit_channel_direction_t dir)
void circuit_set_n_circid_chan(circuit_t *circ, circid_t id, channel_t *chan)
void circuit_set_state(circuit_t *circ, uint8_t state)
circuit_t * circuit_get_by_edge_conn(edge_connection_t *conn)
origin_circuit_t * TO_ORIGIN_CIRCUIT(circuit_t *x)
void assert_circuit_ok(const circuit_t *c)
const char * circuit_state_to_string(int state)
size_t circuits_handle_oom(size_t current_allocation)
or_circuit_t * TO_OR_CIRCUIT(circuit_t *x)
smartlist_t * circuit_get_global_list(void)
Header file for circuitlist.c.
#define CIRCUIT_PURPOSE_PATH_BIAS_TESTING
#define CIRCUIT_STATE_OPEN
#define CIRCUIT_IS_ORCIRC(c)
#define CIRCUIT_IS_ORIGIN(c)
#define CIRCUIT_PURPOSE_OR
#define CIRCUIT_PURPOSE_S_REND_JOINED
#define CIRCUIT_PURPOSE_REND_ESTABLISHED
cell_direction_t circuitmux_attached_circuit_direction(circuitmux_t *cmux, circuit_t *circ)
void circuitmux_notify_xmit_destroy(circuitmux_t *cmux)
void circuitmux_detach_all_circuits(circuitmux_t *cmux, smartlist_t *detached_out)
void circuitmux_notify_xmit_cells(circuitmux_t *cmux, circuit_t *circ, unsigned int n_cells)
int circuitmux_is_circuit_attached(circuitmux_t *cmux, circuit_t *circ)
void circuitmux_set_num_cells(circuitmux_t *cmux, circuit_t *circ, unsigned int n_cells)
circuit_t * circuitmux_get_first_active_circuit(circuitmux_t *cmux, destroy_cell_queue_t **destroy_queue_out)
int circpad_check_received_cell(const relay_msg_t *msg, circuit_t *circ, crypt_path_t *layer_hint)
void circpad_deliver_sent_relay_cell_events(circuit_t *circ, uint8_t relay_command)
void circpad_deliver_unrecognized_cell_events(circuit_t *circ, cell_direction_t dir)
void circpad_machine_event_circ_has_no_relay_early(origin_circuit_t *circ)
void circpad_deliver_recognized_relay_cell_events(circuit_t *circ, uint8_t relay_command, crypt_path_t *layer_hint)
Header file for circuitpadding.c.
void circuit_sent_valid_data(origin_circuit_t *circ, uint16_t relay_body_len)
void circuit_read_valid_data(origin_circuit_t *circ, uint16_t relay_body_len)
void mark_circuit_unusable_for_new_conns(origin_circuit_t *circ)
Header file for circuituse.c.
void tor_libevent_exit_loop_after_callback(struct event_base *base)
struct event_base * tor_libevent_get_base(void)
uint64_t monotime_coarse_stamp_units_to_approx_msec(uint64_t units)
uint32_t monotime_coarse_get_stamp(void)
size_t tor_compress_get_total_allocation(void)
const or_options_t * get_options(void)
tor_cmdline_mode_t command
Header file for config.c.
void conflux_note_cell_sent(conflux_t *cfx, circuit_t *circ, uint8_t relay_command)
bool conflux_should_multiplex(int relay_command)
circuit_t * conflux_decide_next_circ(conflux_t *cfx)
conflux_msg_t * conflux_dequeue_relay_msg(circuit_t *circ)
circuit_t * conflux_decide_circ_for_send(conflux_t *cfx, circuit_t *orig_circ, uint8_t relay_command)
bool conflux_process_relay_msg(conflux_t *cfx, circuit_t *in_circ, crypt_path_t *layer_hint, const relay_msg_t *msg)
int conflux_process_switch_command(circuit_t *in_circ, crypt_path_t *layer_hint, const relay_msg_t *msg)
size_t conflux_handle_oom(size_t bytes_to_remove)
uint64_t conflux_get_total_bytes_allocation(void)
Public APIs for conflux multipath support.
void conflux_process_linked_ack(circuit_t *circ)
void conflux_process_link(circuit_t *circ, const relay_msg_t *msg)
void conflux_process_linked(circuit_t *circ, crypt_path_t *layer_hint, const relay_msg_t *msg)
Header file for conflux_pool.c.
crypt_path_t * conflux_get_destination_hop(circuit_t *circ)
int circuit_get_package_window(circuit_t *circ, const crypt_path_t *cpath)
bool conflux_can_send(conflux_t *cfx)
bool relay_crypt_from_last_hop(const origin_circuit_t *circ, const crypt_path_t *layer_hint)
bool edge_uses_cpath(const edge_connection_t *conn, const crypt_path_t *cpath)
Header file for conflux_util.c.
int congestion_control_get_package_window(const circuit_t *circ, const crypt_path_t *cpath)
Public APIs for congestion control.
static int32_t cell_queue_highwatermark(void)
static int32_t cell_queue_lowwatermark(void)
bool circuit_process_stream_xoff(edge_connection_t *conn, const crypt_path_t *layer_hint)
bool circuit_process_stream_xon(edge_connection_t *conn, const crypt_path_t *layer_hint, const relay_msg_t *msg)
APIs for stream flow control on congestion controlled circuits.
int connection_buf_get_bytes(char *string, size_t len, connection_t *conn)
int connection_state_is_open(connection_t *conn)
const char * conn_state_to_string(int type, int state)
Header file for connection.c.
int connection_half_edge_is_valid_data(const smartlist_t *half_conns, streamid_t stream_id)
int connection_exit_begin_resolve(const relay_msg_t *msg, or_circuit_t *circ)
int connection_ap_detach_retriable(entry_connection_t *conn, origin_circuit_t *circ, int reason)
void connection_ap_handshake_socks_reply(entry_connection_t *conn, char *reply, size_t replylen, int endreason)
int connection_half_edge_is_valid_end(smartlist_t *half_conns, streamid_t stream_id)
void connection_edge_end_close(edge_connection_t *conn, uint8_t reason)
int connection_half_edge_is_valid_connected(const smartlist_t *half_conns, streamid_t stream_id)
int connection_exit_begin_conn(const relay_msg_t *msg, circuit_t *circ)
entry_connection_t * EDGE_TO_ENTRY_CONN(edge_connection_t *c)
void connection_ap_handshake_socks_resolved_addr(entry_connection_t *conn, const tor_addr_t *answer, int ttl, time_t expires)
int connection_half_edge_is_valid_resolved(smartlist_t *half_conns, streamid_t stream_id)
int connection_edge_end(edge_connection_t *conn, uint8_t reason)
size_t half_streams_get_total_allocation(void)
int connection_half_edge_is_valid_sendme(const smartlist_t *half_conns, streamid_t stream_id)
int connection_edge_is_rendezvous_stream(const edge_connection_t *conn)
void connection_ap_handshake_socks_resolved(entry_connection_t *conn, int answer_type, size_t answer_len, const uint8_t *answer, int ttl, time_t expires)
Header file for connection_edge.c.
#define EXIT_CONN_STATE_CONNECTING
#define AP_CONN_STATE_CONNECT_WAIT
#define AP_CONN_STATE_OPEN
#define AP_CONN_STATE_RESOLVE_WAIT
#define EXIT_CONN_STATE_RESOLVING
void cell_pack(packed_cell_t *dst, const cell_t *src, int wide_circ_ids)
Header file for connection_or.c.
void control_event_boot_dir(bootstrap_status_t status, int progress)
void control_event_bootstrap(bootstrap_status_t status, int progress)
int control_event_stream_status(entry_connection_t *conn, stream_status_event_t tp, int reason_code)
Header file for control_events.c.
#define REMAP_STREAM_SOURCE_EXIT
Circuit-build-stse structure.
Common functions for using (pseudo-)random number generators.
#define crypto_fast_rng_one_in_n(rng, n)
crypto_fast_rng_t * get_thread_fast_rng(void)
unsigned crypto_fast_rng_get_uint(crypto_fast_rng_t *rng, unsigned limit)
Common functions for cryptographic routines.
const char * node_describe(const node_t *node)
Header file for describe.c.
Destroy-cell queue structures.
Client/server directory connection structure.
dir_connection_t * TO_DIR_CONN(connection_t *c)
Header file for directory.c.
#define DIR_PURPOSE_FETCH_CERTIFICATE
#define DIR_PURPOSE_FETCH_MICRODESC
#define DIR_PURPOSE_FETCH_CONSENSUS
#define DIR_PURPOSE_FETCH_SERVERDESC
Entry connection structure.
#define ENTRY_TO_EDGE_CONN(c)
Header for core/or/extendinfo.c.
Header file for geoip_stats.c.
@ DIRREQ_CIRC_QUEUE_FLUSHED
uint64_t hs_cache_get_max_bytes(void)
size_t hs_cache_handle_oom(size_t min_remove_bytes)
Header file for hs_cache.c.
Header for feature/hs/hs_metrics.c.
#define hs_metrics_app_write_bytes(i, port, n)
void tor_log(int severity, log_domain_mask_t domain, const char *format,...)
#define log_fn(severity, domain, args,...)
#define log_fn_ratelim(ratelim, severity, domain, args,...)
void connection_stop_reading(connection_t *conn)
void connection_start_reading(connection_t *conn)
int connection_is_reading(const connection_t *conn)
Header file for mainloop.c.
int32_t networkstatus_get_param(const networkstatus_t *ns, const char *param_name, int32_t default_val, int32_t min_val, int32_t max_val)
int consensus_is_waiting_for_certs(void)
Header file for networkstatus.c.
int node_exit_policy_is_exact(const node_t *node, sa_family_t family)
node_t * node_get_mutable_by_id(const char *identity_digest)
int count_loading_descriptors_progress(void)
Header file for nodelist.c.
int extended_cell_parse(extended_cell_t *cell_out, const uint8_t command, const uint8_t *payload, size_t payload_len)
Master header file for Tor-specific functionality.
#define CELL_PAYLOAD_SIZE
#define END_STREAM_REASON_CANT_ATTACH
#define END_STREAM_REASON_FLAG_REMOTE
#define END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED
#define RELAY_PAYLOAD_SIZE_MAX
#define END_CIRC_AT_ORIGIN
#define CIRCWINDOW_INCREMENT
Origin circuit structure.
void addr_policy_append_reject_addr(smartlist_t **dest, const tor_addr_t *addr)
void policies_set_node_exitpolicy_to_reject_all(node_t *node)
Header file for policies.c.
int tor_snprintf(char *str, size_t size, const char *format,...)
char * rate_limit_log(ratelim_t *lim, time_t now)
const char * stream_end_reason_to_string(int reason)
Header file for reasons.c.
int channel_flush_from_first_active_circuit(channel_t *chan, int max)
static int connection_edge_process_relay_cell_not_open(const relay_msg_t *msg, circuit_t *circ, edge_connection_t *conn, crypt_path_t *layer_hint)
void destroy_cell_queue_init(destroy_cell_queue_t *queue)
void cell_queues_reclaim_memory(void)
static int connection_ap_process_end_not_open(const relay_msg_t *msg, origin_circuit_t *circ, entry_connection_t *conn, crypt_path_t *layer_hint)
static int circuit_resume_edge_reading_helper(edge_connection_t *conn, circuit_t *circ, crypt_path_t *layer_hint)
int append_address_to_payload(uint8_t *payload_out, const tor_addr_t *addr)
STATIC int resolved_cell_parse(const relay_msg_t *msg, smartlist_t *addresses_out, int *errcode_out)
uint64_t stats_n_data_cells_received
void packed_cell_free_(packed_cell_t *cell)
STATIC int connection_edge_process_resolved_cell(edge_connection_t *conn, const relay_msg_t *msg)
void destroy_cell_queue_clear(destroy_cell_queue_t *queue)
void destroy_cell_queue_append(destroy_cell_queue_t *queue, circid_t circid, uint8_t reason)
relay_cell_fmt_t circuit_get_relay_format(const circuit_t *circ, const crypt_path_t *cpath)
void channel_unlink_all_circuits(channel_t *chan, smartlist_t *circuits_out)
int append_cell_to_circuit_queue(circuit_t *circ, channel_t *chan, cell_t *cell, cell_direction_t direction, streamid_t fromstream)
void cell_queue_append_packed_copy(circuit_t *circ, cell_queue_t *queue, int exitward, const cell_t *cell, int wide_circ_ids, int use_stats)
uint64_t oom_stats_n_bytes_removed_dns
static packed_cell_t * destroy_cell_to_packed_cell(destroy_cell_t *inp, int wide_circ_ids)
void dump_cell_pool_usage(int severity)
STATIC int connection_edge_process_relay_cell(const relay_msg_t *msg, circuit_t *circ, edge_connection_t *conn, crypt_path_t *layer_hint)
void circuit_reset_sendme_randomness(circuit_t *circ)
uint64_t stats_n_relay_cells_relayed
size_t circuit_max_relay_payload(const circuit_t *circ, const crypt_path_t *cpath, uint8_t relay_command)
uint64_t stats_n_circ_max_cell_reached
#define MAX_RESOLVE_FAILURES
static void remap_event_helper(entry_connection_t *conn, const tor_addr_t *new_addr)
static int circuit_queue_streams_are_blocked(circuit_t *circ)
static void connection_ap_handshake_socks_got_resolved_cell(entry_connection_t *conn, int error_code, smartlist_t *results)
static void adjust_exit_policy_from_exitpolicy_failure(origin_circuit_t *circ, entry_connection_t *conn, node_t *node, const tor_addr_t *addr)
static void circuit_update_channel_usage(circuit_t *circ, cell_t *cell)
uint64_t stats_n_data_cells_packaged
STATIC packed_cell_t * packed_cell_new(void)
void cell_queue_clear(cell_queue_t *queue)
void circuit_clear_cell_queue(circuit_t *circ, channel_t *chan)
void cell_queue_init(cell_queue_t *queue)
int circuit_package_relay_cell(cell_t *cell, circuit_t *circ, cell_direction_t cell_direction, crypt_path_t *layer_hint, streamid_t on_stream, const char *filename, int lineno)
STATIC packed_cell_t * cell_queue_pop(cell_queue_t *queue)
uint64_t stats_n_data_bytes_received
circid_t packed_cell_get_circid(const packed_cell_t *cell, int wide_circ_ids)
static int connection_edge_process_ordered_relay_cell(const relay_msg_t *msg, circuit_t *circ, edge_connection_t *conn, crypt_path_t *layer_hint)
const uint8_t * decode_address_from_payload(tor_addr_t *addr_out, const uint8_t *payload, int payload_len)
static uint32_t get_param_max_circuit_cell_queue_size(const networkstatus_t *ns)
void update_circuit_on_cmux_(circuit_t *circ, cell_direction_t direction, const char *file, int lineno)
STATIC destroy_cell_t * destroy_cell_queue_pop(destroy_cell_queue_t *queue)
bool mainloop_must_free_memory
uint8_t packed_cell_get_command(const packed_cell_t *cell, int wide_circ_ids)
uint64_t stats_n_relay_cells_delivered
STATIC int cell_queues_check_size(void)
STATIC int connected_cell_parse(const relay_msg_t *msg, tor_addr_t *addr_out, int *ttl_out)
static size_t total_cells_allocated
static int32_t max_circuit_cell_queue_size_out
bool have_been_under_memory_pressure(void)
int relay_send_command_from_edge_(streamid_t stream_id, circuit_t *orig_circ, uint8_t relay_command, const char *payload, size_t payload_len, crypt_path_t *cpath_layer, const char *filename, int lineno)
static void packed_cell_free_unchecked(packed_cell_t *cell)
static int edge_reason_is_retriable(int reason)
STATIC size_t connection_edge_get_inbuf_bytes_to_package(size_t n_available, int package_partial, circuit_t *on_circuit, crypt_path_t *cpath)
static void circuit_resume_edge_reading(circuit_t *circ, crypt_path_t *layer_hint)
static void set_circuit_blocked_on_chan(circuit_t *circ, channel_t *chan, int block)
STATIC void address_ttl_free_(address_ttl_t *addr)
static uint32_t get_param_max_circuit_cell_queue_size_out(const networkstatus_t *ns)
STATIC int handle_relay_msg(const relay_msg_t *msg, circuit_t *circ, edge_connection_t *conn, crypt_path_t *layer_hint, int optimistic_data)
static int process_sendme_cell(const relay_msg_t *msg, circuit_t *circ, edge_connection_t *conn, crypt_path_t *layer_hint, int domain)
const char * relay_command_to_string(uint8_t command)
#define MEMORY_PRESSURE_INTERVAL
static void set_block_state_for_streams(circuit_t *circ, edge_connection_t *stream_list, int block, streamid_t stream_id)
void cell_queue_append(cell_queue_t *queue, packed_cell_t *cell)
static edge_connection_t * relay_lookup_conn(circuit_t *circ, const relay_msg_t *msg, cell_direction_t cell_direction, crypt_path_t *layer_hint)
static packed_cell_t * packed_cell_copy(const cell_t *cell, int wide_circ_ids)
int circuit_receive_relay_cell(cell_t *cell, circuit_t *circ, cell_direction_t cell_direction)
int connection_edge_package_raw_inbuf(edge_connection_t *conn, int package_partial, int *max_cells)
int connection_edge_send_command(edge_connection_t *fromconn, uint8_t relay_command, const char *payload, size_t payload_len)
uint64_t stats_n_data_bytes_packaged
size_t packed_cell_mem_cost(void)
static int cell_queues_check_reclaim_impl(bool reclaim_immediately)
static time_t last_time_under_memory_pressure
static int circuit_consider_stop_edge_reading(circuit_t *circ, crypt_path_t *layer_hint)
Header for relay_crypto.c.
int relay_msg_encode_cell(relay_cell_fmt_t format, const relay_msg_t *msg, cell_t *cell_out)
int relay_msg_decode_cell_in_place(relay_cell_fmt_t format, const cell_t *cell, relay_msg_t *msg_out)
Header file for relay_msg.c.
static size_t relay_cell_max_payload_size(relay_cell_fmt_t format, uint8_t relay_command)
A relay message which contains a relay command and parameters, if any, that is from a relay cell.
void rend_process_relay_cell(circuit_t *circ, const crypt_path_t *layer_hint, int command, size_t length, const uint8_t *payload)
Header file for rendcommon.c.
void rep_hist_note_overload(overload_type_t overload)
Header file for rephist.c.
Router descriptor structure.
#define ROUTER_PURPOSE_GENERAL
Header file for routerlist.c.
void scheduler_channel_has_waiting_cells(channel_t *chan)
Header file for scheduler*.c.
void sendme_connection_edge_consider_sending(edge_connection_t *conn)
void sendme_circuit_consider_sending(circuit_t *circ, crypt_path_t *layer_hint)
Header file for sendme.c.
char * smartlist_join_strings(smartlist_t *sl, const char *join, int terminate, size_t *len_out)
void smartlist_add_all(smartlist_t *s1, const smartlist_t *s2)
smartlist_t * smartlist_new(void)
void smartlist_add(smartlist_t *sl, void *element)
#define SMARTLIST_FOREACH_BEGIN(sl, type, var)
#define SMARTLIST_FOREACH(sl, type, var, cmd)
#define SMARTLIST_DEL_CURRENT(sl, var)
Client request structure.
#define SOCKS_COMMAND_RESOLVE_PTR
uint8_t payload[CELL_PAYLOAD_SIZE]
unsigned int num_n_circuits
channel_usage_info_t channel_usage
int marked_for_close_reason
unsigned int circuit_blocked_on_n_chan
uint16_t send_randomness_after_n_cells
struct create_cell_t * n_chan_create_cell
unsigned int circuit_blocked_on_p_chan
unsigned int have_sent_sufficiently_random_cell
cell_queue_t n_chan_cells
uint16_t marked_for_close
struct conflux_t * conflux
const char * marked_for_close_file
smartlist_t * testing_cell_stats
struct timeval timestamp_created
time_t timestamp_last_read_allowed
struct connection_t * linked_conn
uint16_t marked_for_close
const char * marked_for_close_file
struct event * read_event
extend_info_t * chosen_exit
relay_cell_fmt_t relay_cell_format
uint32_t inserted_timestamp
struct crypt_path_t * cpath_layer
struct edge_connection_t * next_stream
unsigned int edge_has_sent_end
struct circuit_t * on_circuit
socks_request_t * socks_request
unsigned int chosen_exit_optional
unsigned int chosen_exit_retries
struct buf_t * pending_optimistic_data
unsigned int use_begindir
char identity_digest[DIGEST_LEN]
created_cell_t created_cell
ed25519_public_key_t identity_pk
uint16_t orig_virtual_port
uint64_t total_cell_waiting_time
uint32_t n_cells_discarded_at_end
relay_cell_fmt_t relay_cell_format
cell_queue_t p_chan_cells
struct or_circuit_t * rend_splice
edge_connection_t * n_streams
uint32_t n_written_circ_bw
uint32_t global_identifier
edge_connection_t * p_streams
uint8_t relay_early_commands[MAX_RELAY_EARLY_CELLS_PER_CIRCUIT]
int relay_early_cells_sent
unsigned int remaining_relay_early_cells
path_state_bitfield_t path_state
smartlist_t * prepend_policy
cpath_build_state_t * build_state
smartlist_t * half_streams
uint32_t inserted_timestamp
char body[CELL_MAX_NETWORK_SIZE]
unsigned int has_finished
char address[MAX_SOCKS_ADDR_LEN]
unsigned int waiting_time
#define MOCK_IMPL(rv, funcname, arglist)