test_dns.c 21 KB

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