test_dns.c 20 KB

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