test_relaycell.c 37 KB

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