test_dns.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751
  1. /* Copyright (c) 2015-2018, The Tor Project, Inc. */
  2. /* See LICENSE for licensing information */
  3. #include "core/or/or.h"
  4. #include "test/test.h"
  5. #define DNS_PRIVATE
  6. #include "feature/relay/dns.h"
  7. #include "core/mainloop/connection.h"
  8. #include "core/or/connection_edge.h"
  9. #include "feature/relay/router.h"
  10. #include "core/or/edge_connection_st.h"
  11. #include "core/or/or_circuit_st.h"
  12. #define NS_MODULE dns
  13. #define NS_SUBMODULE clip_ttl
  14. static void
  15. NS(test_main)(void *arg)
  16. {
  17. (void)arg;
  18. uint32_t ttl_mid = MIN_DNS_TTL_AT_EXIT / 2 + MAX_DNS_TTL_AT_EXIT / 2;
  19. tt_int_op(dns_clip_ttl(MIN_DNS_TTL_AT_EXIT - 1),OP_EQ,MIN_DNS_TTL_AT_EXIT);
  20. tt_int_op(dns_clip_ttl(ttl_mid),OP_EQ,MAX_DNS_TTL_AT_EXIT);
  21. tt_int_op(dns_clip_ttl(MAX_DNS_TTL_AT_EXIT + 1),OP_EQ,MAX_DNS_TTL_AT_EXIT);
  22. done:
  23. return;
  24. }
  25. #undef NS_SUBMODULE
  26. #define NS_SUBMODULE resolve
  27. static int resolve_retval = 0;
  28. static int resolve_made_conn_pending = 0;
  29. static char *resolved_name = NULL;
  30. static cached_resolve_t *cache_entry_mock = NULL;
  31. static int n_fake_impl = 0;
  32. NS_DECL(int, dns_resolve_impl, (edge_connection_t *exitconn, int is_resolve,
  33. or_circuit_t *oncirc, char **hostname_out,
  34. int *made_connection_pending_out,
  35. cached_resolve_t **resolve_out));
  36. /** This will be our configurable substitute for <b>dns_resolve_impl</b> in
  37. * dns.c. It will return <b>resolve_retval</b>,
  38. * and set <b>resolve_made_conn_pending</b> to
  39. * <b>made_connection_pending_out</b>. It will set <b>hostname_out</b>
  40. * to a duplicate of <b>resolved_name</b> and it will set <b>resolve_out</b>
  41. * to <b>cache_entry</b>. Lastly, it will increment <b>n_fake_impl</b< by
  42. * 1.
  43. */
  44. static int
  45. NS(dns_resolve_impl)(edge_connection_t *exitconn, int is_resolve,
  46. or_circuit_t *oncirc, char **hostname_out,
  47. int *made_connection_pending_out,
  48. cached_resolve_t **resolve_out)
  49. {
  50. (void)oncirc;
  51. (void)exitconn;
  52. (void)is_resolve;
  53. if (made_connection_pending_out)
  54. *made_connection_pending_out = resolve_made_conn_pending;
  55. if (hostname_out && resolved_name)
  56. *hostname_out = tor_strdup(resolved_name);
  57. if (resolve_out && cache_entry_mock)
  58. *resolve_out = cache_entry_mock;
  59. n_fake_impl++;
  60. return resolve_retval;
  61. }
  62. static edge_connection_t *conn_for_resolved_cell = NULL;
  63. static int n_send_resolved_cell_replacement = 0;
  64. static uint8_t last_answer_type = 0;
  65. static cached_resolve_t *last_resolved;
  66. static void
  67. NS(send_resolved_cell)(edge_connection_t *conn, uint8_t answer_type,
  68. const cached_resolve_t *resolved)
  69. {
  70. conn_for_resolved_cell = conn;
  71. last_answer_type = answer_type;
  72. last_resolved = (cached_resolve_t *)resolved;
  73. n_send_resolved_cell_replacement++;
  74. }
  75. static int n_send_resolved_hostname_cell_replacement = 0;
  76. static char *last_resolved_hostname = NULL;
  77. static void
  78. NS(send_resolved_hostname_cell)(edge_connection_t *conn,
  79. const char *hostname)
  80. {
  81. conn_for_resolved_cell = conn;
  82. tor_free(last_resolved_hostname);
  83. last_resolved_hostname = tor_strdup(hostname);
  84. n_send_resolved_hostname_cell_replacement++;
  85. }
  86. static int n_dns_cancel_pending_resolve_replacement = 0;
  87. static void
  88. NS(dns_cancel_pending_resolve)(const char *address)
  89. {
  90. (void) address;
  91. n_dns_cancel_pending_resolve_replacement++;
  92. }
  93. static int n_connection_free = 0;
  94. static connection_t *last_freed_conn = NULL;
  95. static void
  96. NS(connection_free_)(connection_t *conn)
  97. {
  98. n_connection_free++;
  99. last_freed_conn = conn;
  100. }
  101. static void
  102. NS(test_main)(void *arg)
  103. {
  104. (void) arg;
  105. int retval;
  106. int prev_n_send_resolved_hostname_cell_replacement;
  107. int prev_n_send_resolved_cell_replacement;
  108. int prev_n_connection_free;
  109. cached_resolve_t *fake_resolved = tor_malloc(sizeof(cached_resolve_t));
  110. edge_connection_t *exitconn = tor_malloc(sizeof(edge_connection_t));
  111. edge_connection_t *nextconn = tor_malloc(sizeof(edge_connection_t));
  112. or_circuit_t *on_circuit = tor_malloc(sizeof(or_circuit_t));
  113. memset(on_circuit,0,sizeof(or_circuit_t));
  114. on_circuit->base_.magic = OR_CIRCUIT_MAGIC;
  115. memset(fake_resolved,0,sizeof(cached_resolve_t));
  116. memset(exitconn,0,sizeof(edge_connection_t));
  117. memset(nextconn,0,sizeof(edge_connection_t));
  118. NS_MOCK(dns_resolve_impl);
  119. NS_MOCK(send_resolved_cell);
  120. NS_MOCK(send_resolved_hostname_cell);
  121. /*
  122. * CASE 1: dns_resolve_impl returns 1 and sets a hostname. purpose is
  123. * EXIT_PURPOSE_RESOLVE.
  124. *
  125. * We want dns_resolve() to call send_resolved_hostname_cell() for a
  126. * given exit connection (represented by edge_connection_t object)
  127. * with a hostname it received from _impl.
  128. */
  129. prev_n_send_resolved_hostname_cell_replacement =
  130. n_send_resolved_hostname_cell_replacement;
  131. exitconn->base_.purpose = EXIT_PURPOSE_RESOLVE;
  132. exitconn->on_circuit = &(on_circuit->base_);
  133. resolve_retval = 1;
  134. resolved_name = tor_strdup("www.torproject.org");
  135. retval = dns_resolve(exitconn);
  136. tt_int_op(retval,OP_EQ,1);
  137. tt_str_op(resolved_name,OP_EQ,last_resolved_hostname);
  138. tt_assert(conn_for_resolved_cell == exitconn);
  139. tt_int_op(n_send_resolved_hostname_cell_replacement,OP_EQ,
  140. prev_n_send_resolved_hostname_cell_replacement + 1);
  141. tt_assert(exitconn->on_circuit == NULL);
  142. tor_free(last_resolved_hostname);
  143. // implies last_resolved_hostname = NULL;
  144. /* CASE 2: dns_resolve_impl returns 1, but does not set hostname.
  145. * Instead, it yields cached_resolve_t object.
  146. *
  147. * We want dns_resolve to call send_resolved_cell on exitconn with
  148. * RESOLVED_TYPE_AUTO and the cached_resolve_t object from _impl.
  149. */
  150. tor_free(resolved_name);
  151. resolved_name = NULL;
  152. exitconn->on_circuit = &(on_circuit->base_);
  153. cache_entry_mock = fake_resolved;
  154. prev_n_send_resolved_cell_replacement =
  155. n_send_resolved_cell_replacement;
  156. retval = dns_resolve(exitconn);
  157. tt_int_op(retval,OP_EQ,1);
  158. tt_assert(conn_for_resolved_cell == exitconn);
  159. tt_int_op(n_send_resolved_cell_replacement,OP_EQ,
  160. prev_n_send_resolved_cell_replacement + 1);
  161. tt_assert(last_resolved == fake_resolved);
  162. tt_int_op(last_answer_type,OP_EQ,0xff);
  163. tt_assert(exitconn->on_circuit == NULL);
  164. /* CASE 3: The purpose of exit connection is not EXIT_PURPOSE_RESOLVE
  165. * and _impl returns 1.
  166. *
  167. * We want dns_resolve to prepend exitconn to n_streams linked list.
  168. * We don't want it to send any cells about hostname being resolved.
  169. */
  170. exitconn->base_.purpose = EXIT_PURPOSE_CONNECT;
  171. exitconn->on_circuit = &(on_circuit->base_);
  172. on_circuit->n_streams = nextconn;
  173. prev_n_send_resolved_cell_replacement =
  174. n_send_resolved_cell_replacement;
  175. prev_n_send_resolved_hostname_cell_replacement =
  176. n_send_resolved_hostname_cell_replacement;
  177. retval = dns_resolve(exitconn);
  178. tt_int_op(retval,OP_EQ,1);
  179. tt_assert(on_circuit->n_streams == exitconn);
  180. tt_assert(exitconn->next_stream == nextconn);
  181. tt_int_op(prev_n_send_resolved_cell_replacement,OP_EQ,
  182. n_send_resolved_cell_replacement);
  183. tt_int_op(prev_n_send_resolved_hostname_cell_replacement,OP_EQ,
  184. n_send_resolved_hostname_cell_replacement);
  185. /* CASE 4: _impl returns 0.
  186. *
  187. * We want dns_resolve() to set exitconn state to
  188. * EXIT_CONN_STATE_RESOLVING and prepend exitconn to resolving_streams
  189. * linked list.
  190. */
  191. exitconn->on_circuit = &(on_circuit->base_);
  192. resolve_retval = 0;
  193. exitconn->next_stream = NULL;
  194. on_circuit->resolving_streams = nextconn;
  195. retval = dns_resolve(exitconn);
  196. tt_int_op(retval,OP_EQ,0);
  197. tt_int_op(exitconn->base_.state,OP_EQ,EXIT_CONN_STATE_RESOLVING);
  198. tt_assert(on_circuit->resolving_streams == exitconn);
  199. tt_assert(exitconn->next_stream == nextconn);
  200. /* CASE 5: _impl returns -1 when purpose of exitconn is
  201. * EXIT_PURPOSE_RESOLVE. We want dns_resolve to call send_resolved_cell
  202. * on exitconn with type being RESOLVED_TYPE_ERROR.
  203. */
  204. NS_MOCK(dns_cancel_pending_resolve);
  205. NS_MOCK(connection_free_);
  206. exitconn->on_circuit = &(on_circuit->base_);
  207. exitconn->base_.purpose = EXIT_PURPOSE_RESOLVE;
  208. resolve_retval = -1;
  209. prev_n_send_resolved_cell_replacement =
  210. n_send_resolved_cell_replacement;
  211. prev_n_connection_free = n_connection_free;
  212. retval = dns_resolve(exitconn);
  213. tt_int_op(retval,OP_EQ,-1);
  214. tt_int_op(n_send_resolved_cell_replacement,OP_EQ,
  215. prev_n_send_resolved_cell_replacement + 1);
  216. tt_int_op(last_answer_type,OP_EQ,RESOLVED_TYPE_ERROR);
  217. tt_int_op(n_dns_cancel_pending_resolve_replacement,OP_EQ,1);
  218. tt_int_op(n_connection_free,OP_EQ,prev_n_connection_free + 1);
  219. tt_assert(last_freed_conn == TO_CONN(exitconn));
  220. done:
  221. NS_UNMOCK(dns_resolve_impl);
  222. NS_UNMOCK(send_resolved_cell);
  223. NS_UNMOCK(send_resolved_hostname_cell);
  224. NS_UNMOCK(dns_cancel_pending_resolve);
  225. NS_UNMOCK(connection_free_);
  226. tor_free(on_circuit);
  227. tor_free(exitconn);
  228. tor_free(nextconn);
  229. tor_free(resolved_name);
  230. tor_free(fake_resolved);
  231. tor_free(last_resolved_hostname);
  232. return;
  233. }
  234. #undef NS_SUBMODULE
  235. /** Create an <b>edge_connection_t</b> instance that is considered a
  236. * valid exit connection by asserts in dns_resolve_impl.
  237. */
  238. static edge_connection_t *
  239. create_valid_exitconn(void)
  240. {
  241. edge_connection_t *exitconn = tor_malloc_zero(sizeof(edge_connection_t));
  242. TO_CONN(exitconn)->type = CONN_TYPE_EXIT;
  243. TO_CONN(exitconn)->magic = EDGE_CONNECTION_MAGIC;
  244. TO_CONN(exitconn)->purpose = EXIT_PURPOSE_RESOLVE;
  245. TO_CONN(exitconn)->state = EXIT_CONN_STATE_RESOLVING;
  246. exitconn->base_.s = TOR_INVALID_SOCKET;
  247. return exitconn;
  248. }
  249. #define NS_SUBMODULE ASPECT(resolve_impl, addr_is_ip_no_need_to_resolve)
  250. /*
  251. * Given that <b>exitconn->base_.address</b> is IP address string, we
  252. * want dns_resolve_impl() to parse it and store in
  253. * <b>exitconn->base_.addr</b>. We expect dns_resolve_impl to return 1.
  254. * Lastly, we want it to set the TTL value to default one for DNS queries.
  255. */
  256. static void
  257. NS(test_main)(void *arg)
  258. {
  259. int retval;
  260. int made_pending;
  261. const tor_addr_t *resolved_addr;
  262. tor_addr_t addr_to_compare;
  263. (void)arg;
  264. tor_addr_parse(&addr_to_compare, "8.8.8.8");
  265. or_circuit_t *on_circ = tor_malloc_zero(sizeof(or_circuit_t));
  266. edge_connection_t *exitconn = create_valid_exitconn();
  267. TO_CONN(exitconn)->address = tor_strdup("8.8.8.8");
  268. retval = dns_resolve_impl(exitconn, 1, on_circ, NULL, &made_pending,
  269. NULL);
  270. resolved_addr = &(exitconn->base_.addr);
  271. tt_int_op(retval,OP_EQ,1);
  272. tt_assert(tor_addr_eq(resolved_addr, (const tor_addr_t *)&addr_to_compare));
  273. tt_int_op(exitconn->address_ttl,OP_EQ,DEFAULT_DNS_TTL);
  274. done:
  275. tor_free(on_circ);
  276. tor_free(TO_CONN(exitconn)->address);
  277. tor_free(exitconn);
  278. return;
  279. }
  280. #undef NS_SUBMODULE
  281. #define NS_SUBMODULE ASPECT(resolve_impl, non_exit)
  282. /** Given that Tor instance is not configured as an exit node, we want
  283. * dns_resolve_impl() to fail with return value -1.
  284. */
  285. static int
  286. NS(router_my_exit_policy_is_reject_star)(void)
  287. {
  288. return 1;
  289. }
  290. static void
  291. NS(test_main)(void *arg)
  292. {
  293. int retval;
  294. int made_pending;
  295. edge_connection_t *exitconn = create_valid_exitconn();
  296. or_circuit_t *on_circ = tor_malloc_zero(sizeof(or_circuit_t));
  297. (void)arg;
  298. TO_CONN(exitconn)->address = tor_strdup("torproject.org");
  299. NS_MOCK(router_my_exit_policy_is_reject_star);
  300. retval = dns_resolve_impl(exitconn, 1, on_circ, NULL, &made_pending,
  301. NULL);
  302. tt_int_op(retval,OP_EQ,-1);
  303. done:
  304. tor_free(TO_CONN(exitconn)->address);
  305. tor_free(exitconn);
  306. tor_free(on_circ);
  307. NS_UNMOCK(router_my_exit_policy_is_reject_star);
  308. return;
  309. }
  310. #undef NS_SUBMODULE
  311. #define NS_SUBMODULE ASPECT(resolve_impl, addr_is_invalid_dest)
  312. /** Given that address is not a valid destination (as judged by
  313. * address_is_invalid_destination() function), we want dns_resolve_impl()
  314. * function to fail with return value -1.
  315. */
  316. static int
  317. NS(router_my_exit_policy_is_reject_star)(void)
  318. {
  319. return 0;
  320. }
  321. static void
  322. NS(test_main)(void *arg)
  323. {
  324. int retval;
  325. int made_pending;
  326. edge_connection_t *exitconn = create_valid_exitconn();
  327. or_circuit_t *on_circ = tor_malloc_zero(sizeof(or_circuit_t));
  328. (void)arg;
  329. NS_MOCK(router_my_exit_policy_is_reject_star);
  330. TO_CONN(exitconn)->address = tor_strdup("invalid#@!.org");
  331. retval = dns_resolve_impl(exitconn, 1, on_circ, NULL, &made_pending,
  332. NULL);
  333. tt_int_op(retval,OP_EQ,-1);
  334. done:
  335. NS_UNMOCK(router_my_exit_policy_is_reject_star);
  336. tor_free(TO_CONN(exitconn)->address);
  337. tor_free(exitconn);
  338. tor_free(on_circ);
  339. return;
  340. }
  341. #undef NS_SUBMODULE
  342. #define NS_SUBMODULE ASPECT(resolve_impl, malformed_ptr)
  343. /** Given that address is a malformed PTR name, we want dns_resolve_impl to
  344. * fail.
  345. */
  346. static int
  347. NS(router_my_exit_policy_is_reject_star)(void)
  348. {
  349. return 0;
  350. }
  351. static void
  352. NS(test_main)(void *arg)
  353. {
  354. int retval;
  355. int made_pending;
  356. edge_connection_t *exitconn = create_valid_exitconn();
  357. or_circuit_t *on_circ = tor_malloc_zero(sizeof(or_circuit_t));
  358. (void)arg;
  359. TO_CONN(exitconn)->address = tor_strdup("1.0.0.127.in-addr.arpa");
  360. NS_MOCK(router_my_exit_policy_is_reject_star);
  361. retval = dns_resolve_impl(exitconn, 1, on_circ, NULL, &made_pending,
  362. NULL);
  363. tt_int_op(retval,OP_EQ,-1);
  364. tor_free(TO_CONN(exitconn)->address);
  365. TO_CONN(exitconn)->address =
  366. tor_strdup("z01234567890123456789.in-addr.arpa");
  367. retval = dns_resolve_impl(exitconn, 1, on_circ, NULL, &made_pending,
  368. NULL);
  369. tt_int_op(retval,OP_EQ,-1);
  370. done:
  371. NS_UNMOCK(router_my_exit_policy_is_reject_star);
  372. tor_free(TO_CONN(exitconn)->address);
  373. tor_free(exitconn);
  374. tor_free(on_circ);
  375. return;
  376. }
  377. #undef NS_SUBMODULE
  378. #define NS_SUBMODULE ASPECT(resolve_impl, cache_hit_pending)
  379. /* Given that there is already a pending resolve for the given address,
  380. * we want dns_resolve_impl to append our exit connection to list
  381. * of pending connections for the pending DNS request and return 0.
  382. */
  383. static int
  384. NS(router_my_exit_policy_is_reject_star)(void)
  385. {
  386. return 0;
  387. }
  388. static void
  389. NS(test_main)(void *arg)
  390. {
  391. int retval;
  392. int made_pending = 0;
  393. pending_connection_t *pending_conn = NULL;
  394. edge_connection_t *exitconn = create_valid_exitconn();
  395. or_circuit_t *on_circ = tor_malloc_zero(sizeof(or_circuit_t));
  396. cached_resolve_t *cache_entry = tor_malloc_zero(sizeof(cached_resolve_t));
  397. cache_entry->magic = CACHED_RESOLVE_MAGIC;
  398. cache_entry->state = CACHE_STATE_PENDING;
  399. cache_entry->minheap_idx = -1;
  400. cache_entry->expire = time(NULL) + 60 * 60;
  401. (void)arg;
  402. TO_CONN(exitconn)->address = tor_strdup("torproject.org");
  403. strlcpy(cache_entry->address, TO_CONN(exitconn)->address,
  404. sizeof(cache_entry->address));
  405. NS_MOCK(router_my_exit_policy_is_reject_star);
  406. dns_init();
  407. dns_insert_cache_entry(cache_entry);
  408. retval = dns_resolve_impl(exitconn, 1, on_circ, NULL, &made_pending,
  409. NULL);
  410. tt_int_op(retval,OP_EQ,0);
  411. tt_int_op(made_pending,OP_EQ,1);
  412. pending_conn = cache_entry->pending_connections;
  413. tt_assert(pending_conn != NULL);
  414. tt_assert(pending_conn->conn == exitconn);
  415. done:
  416. NS_UNMOCK(router_my_exit_policy_is_reject_star);
  417. tor_free(on_circ);
  418. tor_free(TO_CONN(exitconn)->address);
  419. tor_free(cache_entry->pending_connections);
  420. tor_free(cache_entry);
  421. tor_free(exitconn);
  422. return;
  423. }
  424. #undef NS_SUBMODULE
  425. #define NS_SUBMODULE ASPECT(resolve_impl, cache_hit_cached)
  426. /* Given that a finished DNS resolve is available in our cache, we want
  427. * dns_resolve_impl() return it to called via resolve_out and pass the
  428. * handling to set_exitconn_info_from_resolve function.
  429. */
  430. static int
  431. NS(router_my_exit_policy_is_reject_star)(void)
  432. {
  433. return 0;
  434. }
  435. static edge_connection_t *last_exitconn = NULL;
  436. static cached_resolve_t *last_resolve = NULL;
  437. static int
  438. NS(set_exitconn_info_from_resolve)(edge_connection_t *exitconn,
  439. const cached_resolve_t *resolve,
  440. char **hostname_out)
  441. {
  442. last_exitconn = exitconn;
  443. last_resolve = (cached_resolve_t *)resolve;
  444. (void)hostname_out;
  445. return 0;
  446. }
  447. static void
  448. NS(test_main)(void *arg)
  449. {
  450. int retval;
  451. int made_pending = 0;
  452. edge_connection_t *exitconn = create_valid_exitconn();
  453. or_circuit_t *on_circ = tor_malloc_zero(sizeof(or_circuit_t));
  454. cached_resolve_t *resolve_out = NULL;
  455. cached_resolve_t *cache_entry = tor_malloc_zero(sizeof(cached_resolve_t));
  456. cache_entry->magic = CACHED_RESOLVE_MAGIC;
  457. cache_entry->state = CACHE_STATE_CACHED;
  458. cache_entry->minheap_idx = -1;
  459. cache_entry->expire = time(NULL) + 60 * 60;
  460. (void)arg;
  461. TO_CONN(exitconn)->address = tor_strdup("torproject.org");
  462. strlcpy(cache_entry->address, TO_CONN(exitconn)->address,
  463. sizeof(cache_entry->address));
  464. NS_MOCK(router_my_exit_policy_is_reject_star);
  465. NS_MOCK(set_exitconn_info_from_resolve);
  466. dns_init();
  467. dns_insert_cache_entry(cache_entry);
  468. retval = dns_resolve_impl(exitconn, 1, on_circ, NULL, &made_pending,
  469. &resolve_out);
  470. tt_int_op(retval,OP_EQ,0);
  471. tt_int_op(made_pending,OP_EQ,0);
  472. tt_assert(resolve_out == cache_entry);
  473. tt_assert(last_exitconn == exitconn);
  474. tt_assert(last_resolve == cache_entry);
  475. done:
  476. NS_UNMOCK(router_my_exit_policy_is_reject_star);
  477. NS_UNMOCK(set_exitconn_info_from_resolve);
  478. tor_free(on_circ);
  479. tor_free(TO_CONN(exitconn)->address);
  480. tor_free(cache_entry->pending_connections);
  481. tor_free(cache_entry);
  482. return;
  483. }
  484. #undef NS_SUBMODULE
  485. #define NS_SUBMODULE ASPECT(resolve_impl, cache_miss)
  486. /* Given that there are neither pending nor pre-cached resolve for a given
  487. * address, we want dns_resolve_impl() to create a new cached_resolve_t
  488. * object, mark it as pending, insert it into the cache, attach the exit
  489. * connection to list of pending connections and call launch_resolve()
  490. * with the cached_resolve_t object it created.
  491. */
  492. static int
  493. NS(router_my_exit_policy_is_reject_star)(void)
  494. {
  495. return 0;
  496. }
  497. static cached_resolve_t *last_launched_resolve = NULL;
  498. static int
  499. NS(launch_resolve)(cached_resolve_t *resolve)
  500. {
  501. last_launched_resolve = resolve;
  502. return 0;
  503. }
  504. static void
  505. NS(test_main)(void *arg)
  506. {
  507. int retval;
  508. int made_pending = 0;
  509. pending_connection_t *pending_conn = NULL;
  510. edge_connection_t *exitconn = create_valid_exitconn();
  511. or_circuit_t *on_circ = tor_malloc_zero(sizeof(or_circuit_t));
  512. cached_resolve_t *cache_entry = NULL;
  513. cached_resolve_t query;
  514. (void)arg;
  515. TO_CONN(exitconn)->address = tor_strdup("torproject.org");
  516. strlcpy(query.address, TO_CONN(exitconn)->address, sizeof(query.address));
  517. NS_MOCK(router_my_exit_policy_is_reject_star);
  518. NS_MOCK(launch_resolve);
  519. dns_init();
  520. retval = dns_resolve_impl(exitconn, 1, on_circ, NULL, &made_pending,
  521. NULL);
  522. tt_int_op(retval,OP_EQ,0);
  523. tt_int_op(made_pending,OP_EQ,1);
  524. cache_entry = dns_get_cache_entry(&query);
  525. tt_assert(cache_entry);
  526. pending_conn = cache_entry->pending_connections;
  527. tt_assert(pending_conn != NULL);
  528. tt_assert(pending_conn->conn == exitconn);
  529. tt_assert(last_launched_resolve == cache_entry);
  530. tt_str_op(cache_entry->address,OP_EQ,TO_CONN(exitconn)->address);
  531. done:
  532. NS_UNMOCK(router_my_exit_policy_is_reject_star);
  533. NS_UNMOCK(launch_resolve);
  534. tor_free(on_circ);
  535. tor_free(TO_CONN(exitconn)->address);
  536. if (cache_entry)
  537. tor_free(cache_entry->pending_connections);
  538. tor_free(cache_entry);
  539. tor_free(exitconn);
  540. return;
  541. }
  542. #undef NS_SUBMODULE
  543. struct testcase_t dns_tests[] = {
  544. TEST_CASE(clip_ttl),
  545. TEST_CASE(resolve),
  546. TEST_CASE_ASPECT(resolve_impl, addr_is_ip_no_need_to_resolve),
  547. TEST_CASE_ASPECT(resolve_impl, non_exit),
  548. TEST_CASE_ASPECT(resolve_impl, addr_is_invalid_dest),
  549. TEST_CASE_ASPECT(resolve_impl, malformed_ptr),
  550. TEST_CASE_ASPECT(resolve_impl, cache_hit_pending),
  551. TEST_CASE_ASPECT(resolve_impl, cache_hit_cached),
  552. TEST_CASE_ASPECT(resolve_impl, cache_miss),
  553. END_OF_TESTCASES
  554. };
  555. #undef NS_MODULE