test_dns.c 20 KB

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