test_dns.c 19 KB

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