test_dns.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531
  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 = 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)
  66. *resolve_out = cache_entry;
  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 = 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. tor_addr_parse(&addr_to_compare, "8.8.8.8");
  272. or_circuit_t *on_circ = tor_malloc_zero(sizeof(or_circuit_t));
  273. edge_connection_t *exitconn = create_valid_exitconn();
  274. TO_CONN(exitconn)->address = tor_strdup("8.8.8.8");
  275. retval = dns_resolve_impl(exitconn, 1, on_circ, NULL, &made_pending,
  276. NULL);
  277. resolved_addr = &(exitconn->base_.addr);
  278. tt_int_op(retval,==,1);
  279. tt_assert(tor_addr_eq(resolved_addr, (const tor_addr_t *)&addr_to_compare));
  280. tt_int_op(exitconn->address_ttl,==,DEFAULT_DNS_TTL);
  281. done:
  282. tor_free(on_circ);
  283. tor_free(TO_CONN(exitconn)->address);
  284. tor_free(exitconn);
  285. return;
  286. }
  287. #undef NS_SUBMODULE
  288. #define NS_SUBMODULE ASPECT(resolve_impl, non_exit)
  289. /** Given that Tor instance is not configured as an exit node, we want
  290. * dns_resolve_impl() to fail with return value -1.
  291. */
  292. static int
  293. NS(router_my_exit_policy_is_reject_star)(void)
  294. {
  295. return 1;
  296. }
  297. static void
  298. NS(test_main)(void *arg)
  299. {
  300. int retval;
  301. int made_pending;
  302. edge_connection_t *exitconn = create_valid_exitconn();
  303. or_circuit_t *on_circ = tor_malloc_zero(sizeof(or_circuit_t));
  304. TO_CONN(exitconn)->address = tor_strdup("torproject.org");
  305. NS_MOCK(router_my_exit_policy_is_reject_star);
  306. retval = dns_resolve_impl(exitconn, 1, on_circ, NULL, &made_pending,
  307. NULL);
  308. tt_int_op(retval,==,-1);
  309. done:
  310. tor_free(TO_CONN(exitconn)->address);
  311. tor_free(exitconn);
  312. tor_free(on_circ);
  313. NS_UNMOCK(router_my_exit_policy_is_reject_star);
  314. return;
  315. }
  316. #undef NS_SUBMODULE
  317. #define NS_SUBMODULE ASPECT(resolve_impl, addr_is_invalid_dest)
  318. /** Given that address is not a valid destination (as judged by
  319. * address_is_invalid_destination() function), we want dns_resolve_impl()
  320. * function to fail with return value -1.
  321. */
  322. static int
  323. NS(router_my_exit_policy_is_reject_star)(void)
  324. {
  325. return 0;
  326. }
  327. static void
  328. NS(test_main)(void *arg)
  329. {
  330. int retval;
  331. int made_pending;
  332. edge_connection_t *exitconn = create_valid_exitconn();
  333. or_circuit_t *on_circ = tor_malloc_zero(sizeof(or_circuit_t));
  334. NS_MOCK(router_my_exit_policy_is_reject_star);
  335. TO_CONN(exitconn)->address = tor_strdup("invalid#@!.org");
  336. retval = dns_resolve_impl(exitconn, 1, on_circ, NULL, &made_pending,
  337. NULL);
  338. tt_int_op(retval,==,-1);
  339. done:
  340. NS_UNMOCK(router_my_exit_policy_is_reject_star);
  341. tor_free(TO_CONN(exitconn)->address);
  342. tor_free(exitconn);
  343. tor_free(on_circ);
  344. return;
  345. }
  346. #undef NS_SUBMODULE
  347. #define NS_SUBMODULE ASPECT(resolve_impl, malformed_ptr)
  348. static void
  349. NS(test_main)(void *arg)
  350. {
  351. tt_skip();
  352. done:
  353. return;
  354. }
  355. #undef NS_SUBMODULE
  356. #define NS_SUBMODULE ASPECT(resolve_impl, cache_hit_pending)
  357. static void
  358. NS(test_main)(void *arg)
  359. {
  360. tt_skip();
  361. done:
  362. return;
  363. }
  364. #undef NS_SUBMODULE
  365. #define NS_SUBMODULE ASPECT(resolve_impl, cache_hit_cached)
  366. static void
  367. NS(test_main)(void *arg)
  368. {
  369. tt_skip();
  370. done:
  371. return;
  372. }
  373. #undef NS_SUBMODULE
  374. #define NS_SUBMODULE ASPECT(resolve_impl, cache_miss)
  375. static void
  376. NS(test_main)(void *arg)
  377. {
  378. tt_skip();
  379. done:
  380. return;
  381. }
  382. #undef NS_SUBMODULE
  383. struct testcase_t dns_tests[] = {
  384. TEST_CASE(clip_ttl),
  385. TEST_CASE(expiry_ttl),
  386. TEST_CASE(resolve),
  387. TEST_CASE_ASPECT(resolve_impl, addr_is_ip_no_need_to_resolve),
  388. TEST_CASE_ASPECT(resolve_impl, non_exit),
  389. TEST_CASE_ASPECT(resolve_impl, addr_is_invalid_dest),
  390. TEST_CASE_ASPECT(resolve_impl, malformed_ptr),
  391. TEST_CASE_ASPECT(resolve_impl, cache_hit_pending),
  392. TEST_CASE_ASPECT(resolve_impl, cache_hit_cached),
  393. TEST_CASE_ASPECT(resolve_impl, cache_miss),
  394. END_OF_TESTCASES
  395. };
  396. #undef NS_MODULE