test_dns.c 19 KB

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