test_dns.c 19 KB

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