tor

The Tor anonymity network
git clone https://git.dasho.dev/tor.git
Log | Files | Refs | README | LICENSE

test_relaycell.c (39902B)


      1 /* Copyright (c) 2014-2021, The Tor Project, Inc. */
      2 /* See LICENSE for licensing information */
      3 
      4 /* Unit tests for handling different kinds of relay cell */
      5 
      6 #define RELAY_PRIVATE
      7 #define CIRCUITLIST_PRIVATE
      8 #define CONNECTION_EDGE_PRIVATE
      9 #define CONNECTION_PRIVATE
     10 
     11 #include "core/or/or.h"
     12 #include "core/mainloop/mainloop.h"
     13 #include "app/config/config.h"
     14 #include "core/mainloop/connection.h"
     15 #include "lib/crypt_ops/crypto_cipher.h"
     16 #include "lib/crypt_ops/crypto_rand.h"
     17 #include "core/or/circuitbuild.h"
     18 #include "core/or/circuitlist.h"
     19 #include "core/or/connection_edge.h"
     20 #include "core/or/sendme.h"
     21 #include "core/or/relay.h"
     22 #include "core/or/relay_msg.h"
     23 #include "test/test.h"
     24 #include "test/log_test_helpers.h"
     25 
     26 #include "core/or/cell_st.h"
     27 #include "core/or/crypt_path_st.h"
     28 #include "core/or/entry_connection_st.h"
     29 #include "core/or/origin_circuit_st.h"
     30 #include "core/or/socks_request_st.h"
     31 #include "core/or/half_edge_st.h"
     32 
     33 #include "feature/client/circpathbias.h"
     34 
     35 static int srm_ncalls;
     36 static entry_connection_t *srm_conn;
     37 static int srm_atype;
     38 static size_t srm_alen;
     39 static int srm_answer_is_set;
     40 static uint8_t srm_answer[512];
     41 static int srm_ttl;
     42 static time_t srm_expires;
     43 
     44 /* Mock replacement for connection_ap_hannshake_socks_resolved() */
     45 static void
     46 socks_resolved_mock(entry_connection_t *conn,
     47                    int answer_type,
     48                    size_t answer_len,
     49                    const uint8_t *answer,
     50                    int ttl,
     51                    time_t expires)
     52 {
     53  srm_ncalls++;
     54  srm_conn = conn;
     55  srm_atype = answer_type;
     56  srm_alen = answer_len;
     57  if (answer) {
     58    memset(srm_answer, 0, sizeof(srm_answer));
     59    memcpy(srm_answer, answer, answer_len < 512 ? answer_len : 512);
     60    srm_answer_is_set = 1;
     61  } else {
     62    srm_answer_is_set = 0;
     63  }
     64  srm_ttl = ttl;
     65  srm_expires = expires;
     66 }
     67 
     68 static int mum_ncalls;
     69 static entry_connection_t *mum_conn;
     70 static int mum_endreason;
     71 
     72 /* Mock replacement for connection_mark_unattached_ap_() */
     73 static void
     74 mark_unattached_mock(entry_connection_t *conn, int endreason,
     75                     int line, const char *file)
     76 {
     77  ++mum_ncalls;
     78  mum_conn = conn;
     79  mum_endreason = endreason;
     80  (void) line;
     81  (void) file;
     82 }
     83 
     84 /* Helper: Return a newly allocated and initialized origin circuit with
     85 * purpose and flags. A default HS identifier is set to an ed25519
     86 * authentication key for introduction point. */
     87 static origin_circuit_t *
     88 helper_create_origin_circuit(int purpose, int flags)
     89 {
     90  origin_circuit_t *circ = NULL;
     91 
     92  circ = origin_circuit_init(purpose, flags);
     93  tor_assert(circ);
     94  circ->cpath = tor_malloc_zero(sizeof(crypt_path_t));
     95  circ->cpath->magic = CRYPT_PATH_MAGIC;
     96  circ->cpath->state = CPATH_STATE_OPEN;
     97  circ->cpath->package_window = circuit_initial_package_window();
     98  circ->cpath->deliver_window = CIRCWINDOW_START;
     99  circ->cpath->prev = circ->cpath;
    100  /* Create a default HS identifier. */
    101  circ->hs_ident = tor_malloc_zero(sizeof(hs_ident_circuit_t));
    102 
    103  return circ;
    104 }
    105 
    106 static void
    107 mock_connection_mark_unattached_ap_(entry_connection_t *conn, int endreason,
    108                                    int line, const char *file)
    109 {
    110  (void) line;
    111  (void) file;
    112  conn->edge_.end_reason = endreason;
    113 }
    114 
    115 static void
    116 mock_mark_circ_for_close(circuit_t *circ, int reason, int line,
    117                          const char *file)
    118 {
    119  (void)reason; (void)line; (void)file;
    120 
    121  circ->marked_for_close = 1;
    122  return;
    123 }
    124 
    125 static void
    126 mock_mark_for_close(connection_t *conn,
    127                        int line, const char *file)
    128 {
    129  (void)line;
    130  (void)file;
    131 
    132  conn->marked_for_close = 1;
    133  return;
    134 }
    135 
    136 static void
    137 mock_start_reading(connection_t *conn)
    138 {
    139  (void)conn;
    140  return;
    141 }
    142 
    143 static int
    144 mock_send_command(streamid_t stream_id, circuit_t *circ,
    145                               uint8_t relay_command, const char *payload,
    146                               size_t payload_len, crypt_path_t *cpath_layer,
    147                               const char *filename, int lineno)
    148 {
    149 (void)stream_id; (void)circ;
    150 (void)relay_command; (void)payload;
    151 (void)payload_len; (void)cpath_layer;
    152 (void)filename; (void)lineno;
    153 
    154 return 0;
    155 }
    156 
    157 static entry_connection_t *
    158 fake_entry_conn(origin_circuit_t *oncirc, streamid_t id)
    159 {
    160  edge_connection_t *edgeconn;
    161  entry_connection_t *entryconn;
    162 
    163  entryconn = entry_connection_new(CONN_TYPE_AP, AF_INET);
    164  edgeconn = ENTRY_TO_EDGE_CONN(entryconn);
    165  edgeconn->base_.state = AP_CONN_STATE_CONNECT_WAIT;
    166  edgeconn->deliver_window = STREAMWINDOW_START;
    167  edgeconn->package_window = STREAMWINDOW_START;
    168 
    169  edgeconn->stream_id = id;
    170  edgeconn->on_circuit = TO_CIRCUIT(oncirc);
    171  edgeconn->cpath_layer = oncirc->cpath;
    172 
    173  return entryconn;
    174 }
    175 
    176 #define PACK_CELL(id, cmd, body_s) do {                                 \
    177    len_tmp = sizeof(body_s)-1;                                         \
    178    relay_msg_free(msg);                                                \
    179    msg = tor_malloc_zero(sizeof(relay_msg_t));                         \
    180    msg->command = (cmd);                                               \
    181    msg->stream_id = (id);                                              \
    182    msg->body = cell_buf;                                               \
    183    msg->length = len_tmp;                                              \
    184    memcpy(cell_buf, (body_s), len_tmp);                                \
    185  } while (0)
    186 #define ASSERT_COUNTED_BW() do { \
    187    tt_int_op(circ->n_delivered_read_circ_bw, OP_EQ, delivered+msg->length); \
    188    tt_int_op(circ->n_overhead_read_circ_bw, OP_EQ,                      \
    189              overhead+RELAY_PAYLOAD_SIZE-msg->length);               \
    190    delivered = circ->n_delivered_read_circ_bw;                          \
    191    overhead = circ->n_overhead_read_circ_bw;                            \
    192 } while (0)
    193 #define ASSERT_UNCOUNTED_BW() do { \
    194    tt_int_op(circ->n_delivered_read_circ_bw, OP_EQ, delivered); \
    195    tt_int_op(circ->n_overhead_read_circ_bw, OP_EQ, overhead); \
    196 } while (0)
    197 
    198 static int
    199 subtest_circbw_halfclosed(origin_circuit_t *circ, streamid_t init_id)
    200 {
    201  relay_msg_t *msg = NULL;
    202  size_t len_tmp;
    203  edge_connection_t *edgeconn;
    204  entry_connection_t *entryconn2=NULL;
    205  entry_connection_t *entryconn3=NULL;
    206  entry_connection_t *entryconn4=NULL;
    207  int delivered = circ->n_delivered_read_circ_bw;
    208  int overhead = circ->n_overhead_read_circ_bw;
    209  uint8_t cell_buf[RELAY_PAYLOAD_SIZE_MAX];
    210 
    211  /* Make new entryconns */
    212  entryconn2 = fake_entry_conn(circ, init_id);
    213  entryconn2->socks_request->has_finished = 1;
    214  entryconn3 = fake_entry_conn(circ, init_id+1);
    215  entryconn3->socks_request->has_finished = 1;
    216  entryconn4 = fake_entry_conn(circ, init_id+2);
    217  entryconn4->socks_request->has_finished = 1;
    218  edgeconn = ENTRY_TO_EDGE_CONN(entryconn2);
    219  edgeconn->package_window = 23;
    220  edgeconn->base_.state = AP_CONN_STATE_OPEN;
    221 
    222  int data_cells = edgeconn->deliver_window;
    223  int sendme_cells = (STREAMWINDOW_START-edgeconn->package_window)
    224                             /STREAMWINDOW_INCREMENT;
    225  ENTRY_TO_CONN(entryconn2)->marked_for_close = 0;
    226  connection_edge_reached_eof(edgeconn);
    227 
    228  /* Data cell not in the half-opened list */
    229  PACK_CELL(4000, RELAY_COMMAND_DATA, "Data1234");
    230  if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING)
    231    pathbias_count_valid_cells(TO_CIRCUIT(circ), msg);
    232  else
    233    connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), NULL,
    234                                       circ->cpath);
    235  ASSERT_UNCOUNTED_BW();
    236 
    237  /* Sendme cell not in the half-opened list */
    238  PACK_CELL(4000, RELAY_COMMAND_SENDME, "Data1234");
    239  if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING)
    240    pathbias_count_valid_cells(TO_CIRCUIT(circ), msg);
    241  else
    242    connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), NULL,
    243                                     circ->cpath);
    244  ASSERT_UNCOUNTED_BW();
    245 
    246  /* Connected cell not in the half-opened list */
    247  PACK_CELL(4000, RELAY_COMMAND_CONNECTED, "Data1234");
    248  if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING)
    249    pathbias_count_valid_cells(TO_CIRCUIT(circ), msg);
    250  else
    251    connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), NULL,
    252                                     circ->cpath);
    253  ASSERT_UNCOUNTED_BW();
    254 
    255  /* Resolved cell not in the half-opened list */
    256  PACK_CELL(4000, RELAY_COMMAND_RESOLVED, "Data1234");
    257  if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING)
    258    pathbias_count_valid_cells(TO_CIRCUIT(circ), msg);
    259  else
    260    connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), NULL,
    261                                     circ->cpath);
    262  ASSERT_UNCOUNTED_BW();
    263 
    264  /* Connected cell: not counted -- we were open */
    265  edgeconn = ENTRY_TO_EDGE_CONN(entryconn2);
    266  PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_CONNECTED, "Data1234");
    267  if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING)
    268    pathbias_count_valid_cells(TO_CIRCUIT(circ), msg);
    269  else
    270    connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), NULL,
    271                                     circ->cpath);
    272  ASSERT_UNCOUNTED_BW();
    273 
    274  /* DATA cells up to limit */
    275  while (data_cells > 0) {
    276    ENTRY_TO_CONN(entryconn2)->marked_for_close = 0;
    277    PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_DATA, "Data1234");
    278    if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING)
    279      pathbias_count_valid_cells(TO_CIRCUIT(circ), msg);
    280    else
    281      connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), NULL,
    282                                       circ->cpath);
    283    ASSERT_COUNTED_BW();
    284    data_cells--;
    285  }
    286  ENTRY_TO_CONN(entryconn2)->marked_for_close = 0;
    287  PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_DATA, "Data1234");
    288  if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING)
    289    pathbias_count_valid_cells(TO_CIRCUIT(circ), msg);
    290  else
    291    connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), NULL,
    292                                     circ->cpath);
    293  ASSERT_UNCOUNTED_BW();
    294 
    295  /* SENDME cells up to limit */
    296  while (sendme_cells > 0) {
    297    ENTRY_TO_CONN(entryconn2)->marked_for_close = 0;
    298    PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_SENDME, "Data1234");
    299    if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING)
    300      pathbias_count_valid_cells(TO_CIRCUIT(circ), msg);
    301    else
    302      connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), NULL,
    303                                       circ->cpath);
    304    ASSERT_COUNTED_BW();
    305    sendme_cells--;
    306  }
    307  ENTRY_TO_CONN(entryconn2)->marked_for_close = 0;
    308  PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_SENDME, "Data1234");
    309  if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING)
    310    pathbias_count_valid_cells(TO_CIRCUIT(circ), msg);
    311  else
    312    connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), NULL,
    313                                     circ->cpath);
    314  ASSERT_UNCOUNTED_BW();
    315 
    316  /* Only one END cell */
    317  ENTRY_TO_CONN(entryconn2)->marked_for_close = 0;
    318  PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_END, "Data1234");
    319  if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING)
    320    pathbias_count_valid_cells(TO_CIRCUIT(circ), msg);
    321  else
    322    connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), NULL,
    323                                     circ->cpath);
    324  ASSERT_COUNTED_BW();
    325 
    326  ENTRY_TO_CONN(entryconn2)->marked_for_close = 0;
    327  PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_END, "Data1234");
    328  if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING)
    329    pathbias_count_valid_cells(TO_CIRCUIT(circ), msg);
    330  else
    331    connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), NULL,
    332                                     circ->cpath);
    333  ASSERT_UNCOUNTED_BW();
    334 
    335  edgeconn = ENTRY_TO_EDGE_CONN(entryconn3);
    336  edgeconn->base_.state = AP_CONN_STATE_OPEN;
    337  ENTRY_TO_CONN(entryconn3)->marked_for_close = 0;
    338  /* sendme cell on open entryconn with full window */
    339  PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_SENDME, "Data1234");
    340  int ret =
    341    connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), edgeconn,
    342                                     circ->cpath);
    343  tt_int_op(ret, OP_EQ, -END_CIRC_REASON_TORPROTOCOL);
    344  ASSERT_UNCOUNTED_BW();
    345 
    346  /* connected cell on a after EOF */
    347  ENTRY_TO_CONN(entryconn3)->marked_for_close = 0;
    348  edgeconn->base_.state = AP_CONN_STATE_CONNECT_WAIT;
    349  connection_edge_reached_eof(edgeconn);
    350  PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_CONNECTED, "Data1234");
    351  if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING)
    352    pathbias_count_valid_cells(TO_CIRCUIT(circ), msg);
    353  else
    354    connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ),  NULL,
    355                                     circ->cpath);
    356  ASSERT_COUNTED_BW();
    357 
    358  ENTRY_TO_CONN(entryconn3)->marked_for_close = 0;
    359  PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_CONNECTED, "Data1234");
    360  if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING)
    361    pathbias_count_valid_cells(TO_CIRCUIT(circ), msg);
    362  else
    363    connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ),  NULL,
    364                                     circ->cpath);
    365  ASSERT_UNCOUNTED_BW();
    366 
    367  /* DATA and SENDME after END cell */
    368  ENTRY_TO_CONN(entryconn3)->marked_for_close = 0;
    369  PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_END, "Data1234");
    370  if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING)
    371    pathbias_count_valid_cells(TO_CIRCUIT(circ), msg);
    372  else
    373    connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ),  NULL,
    374                                     circ->cpath);
    375  ASSERT_COUNTED_BW();
    376 
    377  ENTRY_TO_CONN(entryconn3)->marked_for_close = 0;
    378  PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_SENDME, "Data1234");
    379  ret =
    380    connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), NULL,
    381                                     circ->cpath);
    382  tt_int_op(ret, OP_NE, -END_CIRC_REASON_TORPROTOCOL);
    383  ASSERT_UNCOUNTED_BW();
    384 
    385  ENTRY_TO_CONN(entryconn3)->marked_for_close = 0;
    386  PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_DATA, "Data1234");
    387  if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING)
    388    pathbias_count_valid_cells(TO_CIRCUIT(circ), msg);
    389  else
    390    connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), NULL,
    391                                     circ->cpath);
    392  ASSERT_UNCOUNTED_BW();
    393 
    394  /* Resolved: 1 counted, more not */
    395  edgeconn = ENTRY_TO_EDGE_CONN(entryconn4);
    396  entryconn4->socks_request->command = SOCKS_COMMAND_RESOLVE;
    397  edgeconn->base_.state = AP_CONN_STATE_RESOLVE_WAIT;
    398  edgeconn->on_circuit = TO_CIRCUIT(circ);
    399  ENTRY_TO_CONN(entryconn4)->marked_for_close = 0;
    400  connection_edge_reached_eof(edgeconn);
    401 
    402  ENTRY_TO_CONN(entryconn4)->marked_for_close = 0;
    403  PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_RESOLVED,
    404            "\x04\x04\x12\x00\x00\x01\x00\x00\x02\x00");
    405  if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING)
    406    pathbias_count_valid_cells(TO_CIRCUIT(circ), msg);
    407  else
    408    connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), NULL,
    409                                     circ->cpath);
    410  ASSERT_COUNTED_BW();
    411 
    412  ENTRY_TO_CONN(entryconn4)->marked_for_close = 0;
    413  PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_RESOLVED,
    414            "\x04\x04\x12\x00\x00\x01\x00\x00\x02\x00");
    415  connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), NULL,
    416                                     circ->cpath);
    417  ASSERT_UNCOUNTED_BW();
    418 
    419  /* Data not counted after resolved */
    420  ENTRY_TO_CONN(entryconn4)->marked_for_close = 0;
    421  PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_DATA, "Data1234");
    422  if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING)
    423    pathbias_count_valid_cells(TO_CIRCUIT(circ), msg);
    424  else
    425    connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), NULL,
    426                                     circ->cpath);
    427  ASSERT_UNCOUNTED_BW();
    428 
    429  /* End not counted after resolved */
    430  ENTRY_TO_CONN(entryconn4)->marked_for_close = 0;
    431  PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_END, "Data1234");
    432  if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING)
    433    pathbias_count_valid_cells(TO_CIRCUIT(circ), msg);
    434  else
    435    connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), NULL,
    436                                     circ->cpath);
    437  ASSERT_UNCOUNTED_BW();
    438 
    439  relay_msg_free(msg);
    440  connection_free_minimal(ENTRY_TO_CONN(entryconn2));
    441  connection_free_minimal(ENTRY_TO_CONN(entryconn3));
    442  connection_free_minimal(ENTRY_TO_CONN(entryconn4));
    443  return 1;
    444 done:
    445  relay_msg_free(msg);
    446  connection_free_minimal(ENTRY_TO_CONN(entryconn2));
    447  connection_free_minimal(ENTRY_TO_CONN(entryconn3));
    448  connection_free_minimal(ENTRY_TO_CONN(entryconn4));
    449  return 0;
    450 }
    451 
    452 static int
    453 halfstream_insert(origin_circuit_t *circ, edge_connection_t *edgeconn,
    454                  streamid_t *streams, int num, int random)
    455 {
    456  int inserted = 0;
    457 
    458  /* Insert num random elements */
    459  while (inserted < num) {
    460    streamid_t id;
    461 
    462    if (random)
    463      id = (streamid_t)crypto_rand_int(65535)+1;
    464    else
    465      id = get_unique_stream_id_by_circ(circ);
    466 
    467    edgeconn->stream_id = id;
    468 
    469    /* Ensure it isn't there */
    470    if (connection_half_edge_find_stream_id(circ->half_streams, id)) {
    471      continue;
    472    }
    473 
    474    connection_half_edge_add(edgeconn, circ);
    475    if (streams)
    476      streams[inserted] = id;
    477    inserted++;
    478  }
    479 
    480  return inserted;
    481 }
    482 
    483 static void
    484 subtest_halfstream_insertremove(int num)
    485 {
    486  origin_circuit_t *circ =
    487      helper_create_origin_circuit(CIRCUIT_PURPOSE_C_GENERAL, 0);
    488  edge_connection_t *edgeconn;
    489  entry_connection_t *entryconn;
    490  streamid_t *streams = tor_malloc_zero(num*sizeof(streamid_t));
    491  int i = 0;
    492 
    493  circ->cpath->state = CPATH_STATE_AWAITING_KEYS;
    494  circ->cpath->deliver_window = CIRCWINDOW_START;
    495 
    496  entryconn = fake_entry_conn(circ, 23);
    497  edgeconn = ENTRY_TO_EDGE_CONN(entryconn);
    498 
    499  /* Explicitly test all operations on an absent stream list */
    500  tt_int_op(connection_half_edge_is_valid_data(circ->half_streams,
    501            23), OP_EQ, 0);
    502  tt_int_op(connection_half_edge_is_valid_connected(circ->half_streams,
    503            23), OP_EQ, 0);
    504  tt_int_op(connection_half_edge_is_valid_sendme(circ->half_streams,
    505            23), OP_EQ, 0);
    506  tt_int_op(connection_half_edge_is_valid_resolved(circ->half_streams,
    507            23), OP_EQ, 0);
    508  tt_int_op(connection_half_edge_is_valid_end(circ->half_streams,
    509            23), OP_EQ, 0);
    510 
    511  /* Insert a duplicate element; verify that other elements absent;
    512   * ensure removing it once works */
    513  edgeconn->stream_id = 23;
    514  connection_half_edge_add(edgeconn, circ);
    515  connection_half_edge_add(edgeconn, circ);
    516  connection_half_edge_add(edgeconn, circ);
    517 
    518  /* Verify that other elements absent */
    519  tt_int_op(connection_half_edge_is_valid_data(circ->half_streams,
    520            22), OP_EQ, 0);
    521  tt_int_op(connection_half_edge_is_valid_connected(circ->half_streams,
    522            22), OP_EQ, 0);
    523  tt_int_op(connection_half_edge_is_valid_sendme(circ->half_streams,
    524            22), OP_EQ, 0);
    525  tt_int_op(connection_half_edge_is_valid_resolved(circ->half_streams,
    526            22), OP_EQ, 0);
    527  tt_int_op(connection_half_edge_is_valid_end(circ->half_streams,
    528            22), OP_EQ, 0);
    529 
    530  tt_int_op(connection_half_edge_is_valid_data(circ->half_streams,
    531            24), OP_EQ, 0);
    532  tt_int_op(connection_half_edge_is_valid_connected(circ->half_streams,
    533            24), OP_EQ, 0);
    534  tt_int_op(connection_half_edge_is_valid_sendme(circ->half_streams,
    535            24), OP_EQ, 0);
    536  tt_int_op(connection_half_edge_is_valid_resolved(circ->half_streams,
    537            24), OP_EQ, 0);
    538  tt_int_op(connection_half_edge_is_valid_end(circ->half_streams,
    539            24), OP_EQ, 0);
    540 
    541  /* Verify we only remove it once */
    542  tt_int_op(connection_half_edge_is_valid_end(circ->half_streams,
    543            23), OP_EQ, 1);
    544  tt_int_op(connection_half_edge_is_valid_end(circ->half_streams,
    545            23), OP_EQ, 0);
    546 
    547  halfstream_insert(circ, edgeconn, streams, num, 1);
    548 
    549  /* Remove half of them */
    550  for (i = 0; i < num/2; i++) {
    551    tt_int_op(connection_half_edge_is_valid_end(circ->half_streams,
    552                                                streams[i]),
    553              OP_EQ, 1);
    554  }
    555 
    556  /* Verify first half of list is gone */
    557  for (i = 0; i < num/2; i++) {
    558    tt_ptr_op(connection_half_edge_find_stream_id(circ->half_streams,
    559                                                  streams[i]),
    560              OP_EQ, NULL);
    561  }
    562 
    563  /* Verify second half of list is present */
    564  for (; i < num; i++) {
    565    tt_ptr_op(connection_half_edge_find_stream_id(circ->half_streams,
    566                                                  streams[i]),
    567              OP_NE, NULL);
    568  }
    569 
    570  /* Remove other half. Verify list is empty. */
    571  for (i = num/2; i < num; i++) {
    572    tt_int_op(connection_half_edge_is_valid_end(circ->half_streams,
    573                                                streams[i]),
    574              OP_EQ, 1);
    575  }
    576  tt_int_op(smartlist_len(circ->half_streams), OP_EQ, 0);
    577 
    578  /* Explicitly test all operations on an empty stream list */
    579  tt_int_op(connection_half_edge_is_valid_data(circ->half_streams,
    580            23), OP_EQ, 0);
    581  tt_int_op(connection_half_edge_is_valid_connected(circ->half_streams,
    582            23), OP_EQ, 0);
    583  tt_int_op(connection_half_edge_is_valid_sendme(circ->half_streams,
    584            23), OP_EQ, 0);
    585  tt_int_op(connection_half_edge_is_valid_resolved(circ->half_streams,
    586            23), OP_EQ, 0);
    587  tt_int_op(connection_half_edge_is_valid_end(circ->half_streams,
    588            23), OP_EQ, 0);
    589 
    590  /* For valgrind, leave some around then free the circ */
    591  halfstream_insert(circ, edgeconn, NULL, 10, 0);
    592 
    593 done:
    594  tor_free(streams);
    595  circuit_free_(TO_CIRCUIT(circ));
    596  connection_free_minimal(ENTRY_TO_CONN(entryconn));
    597 }
    598 
    599 static void
    600 test_halfstream_insertremove(void *arg)
    601 {
    602  (void)arg;
    603 
    604  /* Suppress the WARN message we generate in this test */
    605  setup_full_capture_of_logs(LOG_WARN);
    606 
    607  /* Test insertion and removal with a few different sizes */
    608  subtest_halfstream_insertremove(10);
    609  subtest_halfstream_insertremove(100);
    610  subtest_halfstream_insertremove(1000);
    611 }
    612 
    613 static void
    614 test_halfstream_wrap(void *arg)
    615 {
    616  origin_circuit_t *circ =
    617      helper_create_origin_circuit(CIRCUIT_PURPOSE_C_GENERAL, 0);
    618  edge_connection_t *edgeconn;
    619  entry_connection_t *entryconn;
    620 
    621  circ->cpath->state = CPATH_STATE_AWAITING_KEYS;
    622  circ->cpath->deliver_window = CIRCWINDOW_START;
    623 
    624  entryconn = fake_entry_conn(circ, 23);
    625  edgeconn = ENTRY_TO_EDGE_CONN(entryconn);
    626 
    627  (void)arg;
    628 
    629  /* Suppress the WARN message we generate in this test */
    630  setup_full_capture_of_logs(LOG_WARN);
    631  MOCK(connection_mark_for_close_internal_, mock_mark_for_close);
    632 
    633  /* Verify that get_unique_stream_id_by_circ() can wrap uint16_t */
    634  circ->next_stream_id = 65530;
    635  halfstream_insert(circ, edgeconn, NULL, 7, 0);
    636  tt_int_op(circ->next_stream_id, OP_EQ, 2);
    637  tt_int_op(smartlist_len(circ->half_streams), OP_EQ, 7);
    638 
    639  /* Insert full-1 */
    640  halfstream_insert(circ, edgeconn, NULL,
    641                    65534-smartlist_len(circ->half_streams), 0);
    642  tt_int_op(smartlist_len(circ->half_streams), OP_EQ, 65534);
    643 
    644  /* Verify that we can get_unique_stream_id_by_circ() successfully */
    645  edgeconn->stream_id = get_unique_stream_id_by_circ(circ);
    646  tt_int_op(edgeconn->stream_id, OP_NE, 0); /* 0 is failure */
    647 
    648  /* Insert an opened stream on the circ with that id */
    649  ENTRY_TO_CONN(entryconn)->marked_for_close = 0;
    650  edgeconn->base_.state = AP_CONN_STATE_CONNECT_WAIT;
    651  circ->p_streams = edgeconn;
    652 
    653  /* Verify that get_unique_stream_id_by_circ() fails */
    654  tt_int_op(get_unique_stream_id_by_circ(circ), OP_EQ, 0); /* 0 is failure */
    655 
    656  /* eof the one opened stream. Verify it is now in half-closed */
    657  tt_int_op(smartlist_len(circ->half_streams), OP_EQ, 65534);
    658  connection_edge_reached_eof(edgeconn);
    659  tt_int_op(smartlist_len(circ->half_streams), OP_EQ, 65535);
    660 
    661  /* Verify get_unique_stream_id_by_circ() fails due to full half-closed */
    662  circ->p_streams = NULL;
    663  tt_int_op(get_unique_stream_id_by_circ(circ), OP_EQ, 0); /* 0 is failure */
    664 
    665 done:
    666  circuit_free_(TO_CIRCUIT(circ));
    667  connection_free_minimal(ENTRY_TO_CONN(entryconn));
    668  UNMOCK(connection_mark_for_close_internal_);
    669 }
    670 
    671 static void
    672 test_circbw_relay(void *arg)
    673 {
    674  relay_msg_t *msg = NULL;
    675  size_t len_tmp;
    676  tor_addr_t addr;
    677  edge_connection_t *edgeconn;
    678  entry_connection_t *entryconn1=NULL;
    679  origin_circuit_t *circ;
    680  int delivered = 0;
    681  int overhead = 0;
    682  uint8_t cell_buf[RELAY_PAYLOAD_SIZE_MAX];
    683 
    684  (void)arg;
    685 
    686  MOCK(connection_mark_unattached_ap_, mock_connection_mark_unattached_ap_);
    687  MOCK(connection_start_reading, mock_start_reading);
    688  MOCK(connection_mark_for_close_internal_, mock_mark_for_close);
    689  MOCK(relay_send_command_from_edge_, mock_send_command);
    690  MOCK(circuit_mark_for_close_, mock_mark_circ_for_close);
    691 
    692  circ = helper_create_origin_circuit(CIRCUIT_PURPOSE_C_GENERAL, 0);
    693  circ->cpath->state = CPATH_STATE_AWAITING_KEYS;
    694  circ->cpath->deliver_window = CIRCWINDOW_START;
    695 
    696  entryconn1 = fake_entry_conn(circ, 1);
    697  edgeconn = ENTRY_TO_EDGE_CONN(entryconn1);
    698 
    699  /* Stream id 0: Not counted */
    700  PACK_CELL(0, RELAY_COMMAND_END, "Data1234");
    701  connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), edgeconn,
    702                                     circ->cpath);
    703  ASSERT_UNCOUNTED_BW();
    704 
    705  /* Stream id 1: Counted */
    706  PACK_CELL(1, RELAY_COMMAND_END, "Data1234");
    707  connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), edgeconn,
    708                                     circ->cpath);
    709  ASSERT_COUNTED_BW();
    710 
    711  /* Properly formatted connect cell: counted */
    712  PACK_CELL(1, RELAY_COMMAND_CONNECTED, "Data1234");
    713  tor_addr_parse(&addr, "30.40.50.60");
    714  msg->length = connected_cell_format_payload(cell_buf,
    715                                              &addr, 1024);
    716  connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), edgeconn,
    717                                     circ->cpath);
    718  ASSERT_COUNTED_BW();
    719 
    720  /* Properly formatted resolved cell in correct state: counted */
    721  edgeconn->base_.state = AP_CONN_STATE_RESOLVE_WAIT;
    722  entryconn1->socks_request->command = SOCKS_COMMAND_RESOLVE;
    723  edgeconn->on_circuit = TO_CIRCUIT(circ);
    724  PACK_CELL(1, RELAY_COMMAND_RESOLVED,
    725            "\x04\x04\x12\x00\x00\x01\x00\x00\x02\x00");
    726  connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), edgeconn,
    727                                     circ->cpath);
    728  ASSERT_COUNTED_BW();
    729 
    730  edgeconn->base_.state = AP_CONN_STATE_OPEN;
    731  entryconn1->socks_request->has_finished = 1;
    732 
    733  /* Connected cell after open: not counted */
    734  PACK_CELL(1, RELAY_COMMAND_CONNECTED, "Data1234");
    735  connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), edgeconn,
    736                                     circ->cpath);
    737  ASSERT_UNCOUNTED_BW();
    738 
    739  /* Resolved cell after open: not counted */
    740  PACK_CELL(1, RELAY_COMMAND_RESOLVED, "Data1234");
    741  connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), edgeconn,
    742                                     circ->cpath);
    743  ASSERT_UNCOUNTED_BW();
    744 
    745  /* Drop cell: not counted */
    746  PACK_CELL(1, RELAY_COMMAND_DROP, "Data1234");
    747  connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), edgeconn,
    748                                     circ->cpath);
    749  ASSERT_UNCOUNTED_BW();
    750 
    751  /* Data cell on stream 0: not counted */
    752  PACK_CELL(0, RELAY_COMMAND_DATA, "Data1234");
    753  connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), edgeconn,
    754                                     circ->cpath);
    755  ASSERT_UNCOUNTED_BW();
    756 
    757  /* Data cell on open connection: counted */
    758  ENTRY_TO_CONN(entryconn1)->marked_for_close = 0;
    759  PACK_CELL(1, RELAY_COMMAND_DATA, "Data1234");
    760  connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), edgeconn,
    761                                     circ->cpath);
    762  ASSERT_COUNTED_BW();
    763 
    764  /* Empty Data cell on open connection: not counted */
    765  ENTRY_TO_CONN(entryconn1)->marked_for_close = 0;
    766  PACK_CELL(1, RELAY_COMMAND_DATA, "");
    767  connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), edgeconn,
    768                                     circ->cpath);
    769  ASSERT_UNCOUNTED_BW();
    770 
    771  /* Sendme on valid stream: counted */
    772  edgeconn->package_window -= STREAMWINDOW_INCREMENT;
    773  PACK_CELL(1, RELAY_COMMAND_SENDME, "Data1234");
    774  connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), edgeconn,
    775                                     circ->cpath);
    776  ASSERT_COUNTED_BW();
    777 
    778  /* Sendme on valid stream with full window: not counted */
    779  PACK_CELL(1, RELAY_COMMAND_SENDME, "Data1234");
    780  edgeconn->package_window = STREAMWINDOW_START;
    781  connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), edgeconn,
    782                                     circ->cpath);
    783  ASSERT_UNCOUNTED_BW();
    784 
    785  /* Sendme on unknown stream: not counted */
    786  PACK_CELL(1, RELAY_COMMAND_SENDME, "Data1234");
    787  connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), NULL,
    788                                     circ->cpath);
    789  ASSERT_UNCOUNTED_BW();
    790 
    791  /* Sendme on circuit with full window: not counted */
    792  PACK_CELL(0, RELAY_COMMAND_SENDME, "Data1234");
    793  connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), edgeconn,
    794                                     circ->cpath);
    795  ASSERT_UNCOUNTED_BW();
    796 
    797  /* Sendme on circuit with non-full window: counted */
    798  PACK_CELL(0, RELAY_COMMAND_SENDME, "");
    799  /* Recording a cell, the window is updated after decryption so off by one in
    800   * order to record and then we process it with the proper window. */
    801  circ->cpath->package_window = 901;
    802  sendme_record_cell_digest_on_circ(TO_CIRCUIT(circ), circ->cpath);
    803  circ->cpath->package_window = 900;
    804  connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), edgeconn,
    805                                     circ->cpath);
    806  ASSERT_COUNTED_BW();
    807 
    808  /* Invalid extended cell: not counted */
    809  PACK_CELL(1, RELAY_COMMAND_EXTENDED2, "Data1234");
    810  connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), NULL,
    811                                     circ->cpath);
    812  ASSERT_UNCOUNTED_BW();
    813 
    814  /* Invalid extended cell: not counted */
    815  PACK_CELL(1, RELAY_COMMAND_EXTENDED, "Data1234");
    816  connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), NULL,
    817                                     circ->cpath);
    818  ASSERT_UNCOUNTED_BW();
    819 
    820  /* Invalid HS cell: not counted */
    821  PACK_CELL(1, RELAY_COMMAND_ESTABLISH_INTRO, "Data1234");
    822  connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), NULL,
    823                                     circ->cpath);
    824  ASSERT_UNCOUNTED_BW();
    825 
    826  /* "Valid" HS cell in expected state: counted */
    827  TO_CIRCUIT(circ)->purpose = CIRCUIT_PURPOSE_C_ESTABLISH_REND;
    828  PACK_CELL(1, RELAY_COMMAND_RENDEZVOUS_ESTABLISHED, "Data1234");
    829  connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), NULL,
    830                                     circ->cpath);
    831  ASSERT_COUNTED_BW();
    832 
    833  /* End cell on non-closed connection: counted */
    834  PACK_CELL(1, RELAY_COMMAND_END, "Data1234");
    835  connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), edgeconn,
    836                                     circ->cpath);
    837  ASSERT_COUNTED_BW();
    838 
    839  /* End cell on connection that already got one: not counted */
    840  PACK_CELL(1, RELAY_COMMAND_END, "Data1234");
    841  connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), NULL,
    842                                     circ->cpath);
    843  ASSERT_UNCOUNTED_BW();
    844 
    845  /* Simulate closed stream on entryconn, then test: */
    846  if (!subtest_circbw_halfclosed(circ, 2))
    847    goto done;
    848 
    849  circ->base_.purpose = CIRCUIT_PURPOSE_PATH_BIAS_TESTING;
    850  if (!subtest_circbw_halfclosed(circ, 6))
    851    goto done;
    852 
    853  /* Path bias: truncated */
    854  tt_int_op(circ->base_.marked_for_close, OP_EQ, 0);
    855  PACK_CELL(0, RELAY_COMMAND_TRUNCATED, "Data1234");
    856  pathbias_count_valid_cells(TO_CIRCUIT(circ), msg);
    857  tt_int_op(circ->base_.marked_for_close, OP_EQ, 1);
    858 
    859 done:
    860  relay_msg_free(msg);
    861  UNMOCK(connection_start_reading);
    862  UNMOCK(connection_mark_unattached_ap_);
    863  UNMOCK(connection_mark_for_close_internal_);
    864  UNMOCK(relay_send_command_from_edge_);
    865  UNMOCK(circuit_mark_for_close_);
    866  circuit_free_(TO_CIRCUIT(circ));
    867  connection_free_minimal(ENTRY_TO_CONN(entryconn1));
    868 }
    869 
    870 /* Tests for connection_edge_process_resolved_cell().
    871 
    872   The point of ..process_resolved_cell() is to handle an incoming cell
    873   on an entry connection, and call connection_mark_unattached_ap() and/or
    874   connection_ap_handshake_socks_resolved().
    875 */
    876 static void
    877 test_relaycell_resolved(void *arg)
    878 {
    879  entry_connection_t *entryconn;
    880  edge_connection_t *edgeconn;
    881  relay_msg_t *msg = NULL;
    882  int r;
    883  or_options_t *options = get_options_mutable();
    884  size_t len_tmp;
    885  uint8_t cell_buf[RELAY_PAYLOAD_SIZE_MAX];
    886 
    887 #define SET_CELL(s) do {                                                \
    888    relay_msg_free(msg);                                                \
    889    msg = tor_malloc_zero(sizeof(relay_msg_t));                         \
    890    len_tmp = sizeof(s) - 1;                                            \
    891    msg->body = cell_buf;                                               \
    892    msg->length = len_tmp;                                              \
    893    memcpy(cell_buf, s, len_tmp);                                      \
    894  } while (0)
    895 #define MOCK_RESET() do {                       \
    896    srm_ncalls = mum_ncalls = 0;                \
    897  } while (0)
    898 #define ASSERT_MARK_CALLED(reason) do {         \
    899    tt_int_op(mum_ncalls, OP_EQ, 1);               \
    900    tt_ptr_op(mum_conn, OP_EQ, entryconn);         \
    901    tt_int_op(mum_endreason, OP_EQ, (reason));     \
    902  } while (0)
    903 #define ASSERT_RESOLVED_CALLED(atype, answer, ttl, expires) do {        \
    904    tt_int_op(srm_ncalls, OP_EQ, 1);                                    \
    905    tt_ptr_op(srm_conn, OP_EQ, entryconn);                              \
    906    tt_int_op(srm_atype, OP_EQ, (atype));                               \
    907    if ((answer) != NULL) {                                             \
    908      tt_int_op(srm_alen, OP_EQ, sizeof(answer)-1);                     \
    909      tt_int_op(srm_alen, OP_LT, 512);                                  \
    910      tt_int_op(srm_answer_is_set, OP_EQ, 1);                           \
    911      tt_mem_op(srm_answer, OP_EQ, answer, sizeof(answer)-1);           \
    912    } else {                                                            \
    913      tt_int_op(srm_answer_is_set, OP_EQ, 0);                           \
    914    }                                                                   \
    915    tt_int_op(srm_ttl, OP_EQ, ttl);                                     \
    916    tt_i64_op(srm_expires, OP_EQ, expires);                             \
    917  } while (0)
    918 
    919  (void)arg;
    920 
    921  MOCK(connection_mark_unattached_ap_, mark_unattached_mock);
    922  MOCK(connection_ap_handshake_socks_resolved, socks_resolved_mock);
    923 
    924  options->ClientDNSRejectInternalAddresses = 0;
    925 
    926  SET_CELL(/* IPv4: 127.0.1.2, ttl 256 */
    927           "\x04\x04\x7f\x00\x01\x02\x00\x00\x01\x00"
    928           /* IPv4: 18.0.0.1, ttl 512 */
    929           "\x04\x04\x12\x00\x00\x01\x00\x00\x02\x00"
    930           /* IPv6: 2003::3, ttl 1024 */
    931           "\x06\x10"
    932           "\x20\x02\x00\x00\x00\x00\x00\x00"
    933           "\x00\x00\x00\x00\x00\x00\x00\x03"
    934           "\x00\x00\x04\x00");
    935 
    936  entryconn = entry_connection_new(CONN_TYPE_AP, AF_INET);
    937  edgeconn = ENTRY_TO_EDGE_CONN(entryconn);
    938 
    939  /* Try with connection in non-RESOLVE_WAIT state: cell gets ignored */
    940  MOCK_RESET();
    941  r = connection_edge_process_resolved_cell(edgeconn, msg);
    942  tt_int_op(r, OP_EQ, 0);
    943  tt_int_op(srm_ncalls, OP_EQ, 0);
    944  tt_int_op(mum_ncalls, OP_EQ, 0);
    945 
    946  /* Now put it in the right state. */
    947  ENTRY_TO_CONN(entryconn)->state = AP_CONN_STATE_RESOLVE_WAIT;
    948  entryconn->socks_request->command = SOCKS_COMMAND_RESOLVE;
    949  entryconn->entry_cfg.ipv4_traffic = 1;
    950  entryconn->entry_cfg.ipv6_traffic = 1;
    951  entryconn->entry_cfg.prefer_ipv6 = 0;
    952 
    953  /* We prefer ipv4, so we should get the first ipv4 answer */
    954  MOCK_RESET();
    955  r = connection_edge_process_resolved_cell(edgeconn, msg);
    956  tt_int_op(r, OP_EQ, 0);
    957  ASSERT_MARK_CALLED(END_STREAM_REASON_DONE|
    958                     END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED);
    959  ASSERT_RESOLVED_CALLED(RESOLVED_TYPE_IPV4, "\x7f\x00\x01\x02", 256, -1);
    960 
    961  /* But we may be discarding private answers. */
    962  MOCK_RESET();
    963  options->ClientDNSRejectInternalAddresses = 1;
    964  r = connection_edge_process_resolved_cell(edgeconn, msg);
    965  tt_int_op(r, OP_EQ, 0);
    966  ASSERT_MARK_CALLED(END_STREAM_REASON_DONE|
    967                     END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED);
    968  ASSERT_RESOLVED_CALLED(RESOLVED_TYPE_IPV4, "\x12\x00\x00\x01", 512, -1);
    969 
    970  /* now prefer ipv6, and get the first ipv6 answer */
    971  entryconn->entry_cfg.prefer_ipv6 = 1;
    972  MOCK_RESET();
    973  r = connection_edge_process_resolved_cell(edgeconn, msg);
    974  tt_int_op(r, OP_EQ, 0);
    975  ASSERT_MARK_CALLED(END_STREAM_REASON_DONE|
    976                     END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED);
    977  ASSERT_RESOLVED_CALLED(RESOLVED_TYPE_IPV6,
    978                         "\x20\x02\x00\x00\x00\x00\x00\x00"
    979                         "\x00\x00\x00\x00\x00\x00\x00\x03",
    980                         1024, -1);
    981 
    982  /* With a cell that only has IPv4, we report IPv4 even if we prefer IPv6 */
    983  MOCK_RESET();
    984  SET_CELL("\x04\x04\x12\x00\x00\x01\x00\x00\x02\x00");
    985  r = connection_edge_process_resolved_cell(edgeconn, msg);
    986  tt_int_op(r, OP_EQ, 0);
    987  ASSERT_MARK_CALLED(END_STREAM_REASON_DONE|
    988                     END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED);
    989  ASSERT_RESOLVED_CALLED(RESOLVED_TYPE_IPV4, "\x12\x00\x00\x01", 512, -1);
    990 
    991  /* But if we don't allow IPv4, we report nothing if the cell contains only
    992   * ipv4 */
    993  MOCK_RESET();
    994  entryconn->entry_cfg.ipv4_traffic = 0;
    995  r = connection_edge_process_resolved_cell(edgeconn, msg);
    996  tt_int_op(r, OP_EQ, 0);
    997  ASSERT_MARK_CALLED(END_STREAM_REASON_DONE|
    998                     END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED);
    999  ASSERT_RESOLVED_CALLED(RESOLVED_TYPE_NOERROR, NULL, -1, -1);
   1000 
   1001  /* If we wanted hostnames, we report nothing, since we only had IPs. */
   1002  MOCK_RESET();
   1003  entryconn->entry_cfg.ipv4_traffic = 1;
   1004  entryconn->socks_request->command = SOCKS_COMMAND_RESOLVE_PTR;
   1005  r = connection_edge_process_resolved_cell(edgeconn, msg);
   1006  tt_int_op(r, OP_EQ, 0);
   1007  ASSERT_MARK_CALLED(END_STREAM_REASON_DONE|
   1008                     END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED);
   1009  ASSERT_RESOLVED_CALLED(RESOLVED_TYPE_ERROR, NULL, -1, -1);
   1010 
   1011  /* A hostname cell is fine though. */
   1012  MOCK_RESET();
   1013  SET_CELL("\x00\x0fwww.example.com\x00\x01\x00\x00");
   1014  r = connection_edge_process_resolved_cell(edgeconn, msg);
   1015  tt_int_op(r, OP_EQ, 0);
   1016  ASSERT_MARK_CALLED(END_STREAM_REASON_DONE|
   1017                     END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED);
   1018  ASSERT_RESOLVED_CALLED(RESOLVED_TYPE_HOSTNAME, "www.example.com", 65536, -1);
   1019 
   1020  /* error on malformed cell */
   1021  MOCK_RESET();
   1022  entryconn->socks_request->command = SOCKS_COMMAND_RESOLVE;
   1023  SET_CELL("\x04\x04\x01\x02\x03\x04"); /* no ttl */
   1024  r = connection_edge_process_resolved_cell(edgeconn, msg);
   1025  tt_int_op(r, OP_EQ, 0);
   1026  ASSERT_MARK_CALLED(END_STREAM_REASON_TORPROTOCOL);
   1027  tt_int_op(srm_ncalls, OP_EQ, 0);
   1028 
   1029  /* error on all addresses private */
   1030  MOCK_RESET();
   1031  SET_CELL(/* IPv4: 127.0.1.2, ttl 256 */
   1032           "\x04\x04\x7f\x00\x01\x02\x00\x00\x01\x00"
   1033           /* IPv4: 192.168.1.1, ttl 256 */
   1034           "\x04\x04\xc0\xa8\x01\x01\x00\x00\x01\x00");
   1035  r = connection_edge_process_resolved_cell(edgeconn, msg);
   1036  tt_int_op(r, OP_EQ, 0);
   1037  ASSERT_MARK_CALLED(END_STREAM_REASON_TORPROTOCOL);
   1038  ASSERT_RESOLVED_CALLED(RESOLVED_TYPE_ERROR_TRANSIENT, NULL, 0, TIME_MAX);
   1039 
   1040  /* Legit error code */
   1041  MOCK_RESET();
   1042  SET_CELL("\xf0\x15" "quiet and meaningless" "\x00\x00\x0f\xff");
   1043  r = connection_edge_process_resolved_cell(edgeconn, msg);
   1044  tt_int_op(r, OP_EQ, 0);
   1045  ASSERT_MARK_CALLED(END_STREAM_REASON_DONE|
   1046                     END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED);
   1047  ASSERT_RESOLVED_CALLED(RESOLVED_TYPE_ERROR_TRANSIENT, NULL, -1, -1);
   1048 
   1049 done:
   1050  relay_msg_free(msg);
   1051  UNMOCK(connection_mark_unattached_ap_);
   1052  UNMOCK(connection_ap_handshake_socks_resolved);
   1053 }
   1054 
   1055 struct testcase_t relaycell_tests[] = {
   1056  { "resolved", test_relaycell_resolved, TT_FORK, NULL, NULL },
   1057  { "circbw", test_circbw_relay, TT_FORK, NULL, NULL },
   1058  { "halfstream", test_halfstream_insertremove, TT_FORK, NULL, NULL },
   1059  { "streamwrap", test_halfstream_wrap, TT_FORK, NULL, NULL },
   1060  END_OF_TESTCASES
   1061 };