test_dns.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476
  1. #include "or.h"
  2. #include "test.h"
  3. #define DNS_PRIVATE
  4. #include "dns.h"
  5. #include "connection.h"
  6. #define NS_MODULE dns
  7. #define NS_SUBMODULE clip_ttl
  8. static void
  9. NS(test_main)(void *arg)
  10. {
  11. (void)arg;
  12. uint32_t ttl_mid = MIN_DNS_TTL / 2 + MAX_DNS_TTL / 2;
  13. tt_int_op(dns_clip_ttl(MIN_DNS_TTL - 1),==,MIN_DNS_TTL);
  14. tt_int_op(dns_clip_ttl(ttl_mid),==,ttl_mid);
  15. tt_int_op(dns_clip_ttl(MAX_DNS_TTL + 1),==,MAX_DNS_TTL);
  16. done:
  17. return;
  18. }
  19. #undef NS_SUBMODULE
  20. #define NS_SUBMODULE expiry_ttl
  21. static void
  22. NS(test_main)(void *arg)
  23. {
  24. (void)arg;
  25. uint32_t ttl_mid = MIN_DNS_TTL / 2 + MAX_DNS_ENTRY_AGE / 2;
  26. tt_int_op(dns_get_expiry_ttl(MIN_DNS_TTL - 1),==,MIN_DNS_TTL);
  27. tt_int_op(dns_get_expiry_ttl(ttl_mid),==,ttl_mid);
  28. tt_int_op(dns_get_expiry_ttl(MAX_DNS_ENTRY_AGE + 1),==,MAX_DNS_ENTRY_AGE);
  29. done:
  30. return;
  31. }
  32. #undef NS_SUBMODULE
  33. #define NS_SUBMODULE resolve
  34. static int resolve_retval = 0;
  35. static int resolve_made_conn_pending = 0;
  36. static char *resolved_name = NULL;
  37. static cached_resolve_t *cache_entry = NULL;
  38. static int n_fake_impl = 0;
  39. NS_DECL(int, dns_resolve_impl, (edge_connection_t *exitconn, int is_resolve,
  40. or_circuit_t *oncirc, char **hostname_out,
  41. int *made_connection_pending_out,
  42. cached_resolve_t **resolve_out));
  43. /** This will be our configurable substitute for <b>dns_resolve_impl</b> in
  44. * dns.c. It will return <b>resolve_retval</b>,
  45. * and set <b>resolve_made_conn_pending</b> to
  46. * <b>made_connection_pending_out</b>. It will set <b>hostname_out</b>
  47. * to a duplicate of <b>resolved_name</b> and it will set <b>resolve_out</b>
  48. * to <b>cache_entry</b>. Lastly, it will increment <b>n_fake_impl</b< by
  49. * 1.
  50. */
  51. static int
  52. NS(dns_resolve_impl)(edge_connection_t *exitconn, int is_resolve,
  53. or_circuit_t *oncirc, char **hostname_out,
  54. int *made_connection_pending_out,
  55. cached_resolve_t **resolve_out)
  56. {
  57. (void)oncirc;
  58. (void)exitconn;
  59. (void)is_resolve;
  60. if (made_connection_pending_out)
  61. *made_connection_pending_out = resolve_made_conn_pending;
  62. if (hostname_out && resolved_name)
  63. *hostname_out = tor_strdup(resolved_name);
  64. if (resolve_out && cache_entry)
  65. *resolve_out = cache_entry;
  66. n_fake_impl++;
  67. return resolve_retval;
  68. }
  69. static edge_connection_t *conn_for_resolved_cell = NULL;
  70. static int n_send_resolved_cell_replacement = 0;
  71. static uint8_t last_answer_type = 0;
  72. static cached_resolve_t *last_resolved;
  73. static void
  74. NS(send_resolved_cell)(edge_connection_t *conn, uint8_t answer_type,
  75. const cached_resolve_t *resolved)
  76. {
  77. conn_for_resolved_cell = conn;
  78. last_answer_type = answer_type;
  79. last_resolved = (cached_resolve_t *)resolved;
  80. n_send_resolved_cell_replacement++;
  81. }
  82. static int n_send_resolved_hostname_cell_replacement = 0;
  83. static char *last_resolved_hostname = NULL;
  84. static void
  85. NS(send_resolved_hostname_cell)(edge_connection_t *conn,
  86. const char *hostname)
  87. {
  88. conn_for_resolved_cell = conn;
  89. tor_free(last_resolved_hostname);
  90. last_resolved_hostname = tor_strdup(hostname);
  91. n_send_resolved_hostname_cell_replacement++;
  92. }
  93. static int n_dns_cancel_pending_resolve_replacement = 0;
  94. static void
  95. NS(dns_cancel_pending_resolve)(const char *address)
  96. {
  97. (void) address;
  98. n_dns_cancel_pending_resolve_replacement++;
  99. }
  100. static int n_connection_free = 0;
  101. static connection_t *last_freed_conn = NULL;
  102. static void
  103. NS(connection_free)(connection_t *conn)
  104. {
  105. n_connection_free++;
  106. last_freed_conn = conn;
  107. }
  108. static void
  109. NS(test_main)(void *arg)
  110. {
  111. (void) arg;
  112. int retval;
  113. int prev_n_send_resolved_hostname_cell_replacement;
  114. int prev_n_send_resolved_cell_replacement;
  115. int prev_n_connection_free;
  116. cached_resolve_t *fake_resolved = tor_malloc(sizeof(cached_resolve_t));
  117. edge_connection_t *exitconn = tor_malloc(sizeof(edge_connection_t));
  118. edge_connection_t *nextconn = tor_malloc(sizeof(edge_connection_t));
  119. or_circuit_t *on_circuit = tor_malloc(sizeof(or_circuit_t));
  120. memset(on_circuit,0,sizeof(or_circuit_t));
  121. on_circuit->base_.magic = OR_CIRCUIT_MAGIC;
  122. memset(fake_resolved,0,sizeof(cached_resolve_t));
  123. memset(exitconn,0,sizeof(edge_connection_t));
  124. memset(nextconn,0,sizeof(edge_connection_t));
  125. NS_MOCK(dns_resolve_impl);
  126. NS_MOCK(send_resolved_cell);
  127. NS_MOCK(send_resolved_hostname_cell);
  128. /*
  129. * CASE 1: dns_resolve_impl returns 1 and sets a hostname. purpose is
  130. * EXIT_PURPOSE_RESOLVE.
  131. *
  132. * We want dns_resolve() to call send_resolved_hostname_cell() for a
  133. * given exit connection (represented by edge_connection_t object)
  134. * with a hostname it received from _impl.
  135. */
  136. prev_n_send_resolved_hostname_cell_replacement =
  137. n_send_resolved_hostname_cell_replacement;
  138. exitconn->base_.purpose = EXIT_PURPOSE_RESOLVE;
  139. exitconn->on_circuit = &(on_circuit->base_);
  140. resolve_retval = 1;
  141. resolved_name = tor_strdup("www.torproject.org");
  142. retval = dns_resolve(exitconn);
  143. tt_int_op(retval,==,1);
  144. tt_str_op(resolved_name,==,last_resolved_hostname);
  145. tt_assert(conn_for_resolved_cell == exitconn);
  146. tt_int_op(n_send_resolved_hostname_cell_replacement,==,
  147. prev_n_send_resolved_hostname_cell_replacement + 1);
  148. tt_assert(exitconn->on_circuit == NULL);
  149. tor_free(last_resolved_hostname);
  150. // implies last_resolved_hostname = NULL;
  151. /* CASE 2: dns_resolve_impl returns 1, but does not set hostname.
  152. * Instead, it yields cached_resolve_t object.
  153. *
  154. * We want dns_resolve to call send_resolved_cell on exitconn with
  155. * RESOLVED_TYPE_AUTO and the cached_resolve_t object from _impl.
  156. */
  157. tor_free(resolved_name);
  158. resolved_name = NULL;
  159. exitconn->on_circuit = &(on_circuit->base_);
  160. cache_entry = fake_resolved;
  161. prev_n_send_resolved_cell_replacement =
  162. n_send_resolved_cell_replacement;
  163. retval = dns_resolve(exitconn);
  164. tt_int_op(retval,==,1);
  165. tt_assert(conn_for_resolved_cell == exitconn);
  166. tt_int_op(n_send_resolved_cell_replacement,==,
  167. prev_n_send_resolved_cell_replacement + 1);
  168. tt_assert(last_resolved == fake_resolved);
  169. tt_int_op(last_answer_type,==,0xff);
  170. tt_assert(exitconn->on_circuit == NULL);
  171. /* CASE 3: The purpose of exit connection is not EXIT_PURPOSE_RESOLVE
  172. * and _impl returns 1.
  173. *
  174. * We want dns_resolve to prepend exitconn to n_streams linked list.
  175. * We don't want it to send any cells about hostname being resolved.
  176. */
  177. exitconn->base_.purpose = EXIT_PURPOSE_CONNECT;
  178. exitconn->on_circuit = &(on_circuit->base_);
  179. on_circuit->n_streams = nextconn;
  180. prev_n_send_resolved_cell_replacement =
  181. n_send_resolved_cell_replacement;
  182. prev_n_send_resolved_hostname_cell_replacement =
  183. n_send_resolved_hostname_cell_replacement;
  184. retval = dns_resolve(exitconn);
  185. tt_int_op(retval,==,1);
  186. tt_assert(on_circuit->n_streams == exitconn);
  187. tt_assert(exitconn->next_stream == nextconn);
  188. tt_int_op(prev_n_send_resolved_cell_replacement,==,
  189. n_send_resolved_cell_replacement);
  190. tt_int_op(prev_n_send_resolved_hostname_cell_replacement,==,
  191. n_send_resolved_hostname_cell_replacement);
  192. /* CASE 4: _impl returns 0.
  193. *
  194. * We want dns_resolve() to set exitconn state to
  195. * EXIT_CONN_STATE_RESOLVING and prepend exitconn to resolving_streams
  196. * linked list.
  197. */
  198. exitconn->on_circuit = &(on_circuit->base_);
  199. resolve_retval = 0;
  200. exitconn->next_stream = NULL;
  201. on_circuit->resolving_streams = nextconn;
  202. retval = dns_resolve(exitconn);
  203. tt_int_op(retval,==,0);
  204. tt_int_op(exitconn->base_.state,==,EXIT_CONN_STATE_RESOLVING);
  205. tt_assert(on_circuit->resolving_streams == exitconn);
  206. tt_assert(exitconn->next_stream == nextconn);
  207. /* CASE 5: _impl returns -1 when purpose of exitconn is
  208. * EXIT_PURPOSE_RESOLVE. We want dns_resolve to call send_resolved_cell
  209. * on exitconn with type being RESOLVED_TYPE_ERROR.
  210. */
  211. NS_MOCK(dns_cancel_pending_resolve);
  212. NS_MOCK(connection_free);
  213. exitconn->on_circuit = &(on_circuit->base_);
  214. exitconn->base_.purpose = EXIT_PURPOSE_RESOLVE;
  215. resolve_retval = -1;
  216. prev_n_send_resolved_cell_replacement =
  217. n_send_resolved_cell_replacement;
  218. prev_n_connection_free = n_connection_free;
  219. retval = dns_resolve(exitconn);
  220. tt_int_op(retval,==,-1);
  221. tt_int_op(n_send_resolved_cell_replacement,==,
  222. prev_n_send_resolved_cell_replacement + 1);
  223. tt_int_op(last_answer_type,==,RESOLVED_TYPE_ERROR);
  224. tt_int_op(n_dns_cancel_pending_resolve_replacement,==,1);
  225. tt_int_op(n_connection_free,==,prev_n_connection_free + 1);
  226. tt_assert(last_freed_conn == TO_CONN(exitconn));
  227. done:
  228. NS_UNMOCK(dns_resolve_impl);
  229. NS_UNMOCK(send_resolved_cell);
  230. NS_UNMOCK(send_resolved_hostname_cell);
  231. NS_UNMOCK(dns_cancel_pending_resolve);
  232. NS_UNMOCK(connection_free);
  233. tor_free(on_circuit);
  234. tor_free(exitconn);
  235. tor_free(nextconn);
  236. tor_free(resolved_name);
  237. tor_free(fake_resolved);
  238. tor_free(last_resolved_hostname);
  239. return;
  240. }
  241. #undef NS_SUBMODULE
  242. /** Create an <b>edge_connection_t</b> instance that is considered a
  243. * valid exit connection by asserts in dns_resolve_impl.
  244. */
  245. static edge_connection_t *
  246. create_valid_exitconn(void)
  247. {
  248. edge_connection_t *exitconn = tor_malloc_zero(sizeof(edge_connection_t));
  249. TO_CONN(exitconn)->type = CONN_TYPE_EXIT;
  250. TO_CONN(exitconn)->magic = EDGE_CONNECTION_MAGIC;
  251. TO_CONN(exitconn)->purpose = EXIT_PURPOSE_RESOLVE;
  252. TO_CONN(exitconn)->state = EXIT_CONN_STATE_RESOLVING;
  253. exitconn->base_.s = TOR_INVALID_SOCKET;
  254. return exitconn;
  255. }
  256. #define NS_SUBMODULE ASPECT(resolve_impl, addr_is_ip_no_need_to_resolve)
  257. /*
  258. * Given that <b>exitconn->base_.address</b> is IP address string, we
  259. * want dns_resolve_impl() to parse it and store in
  260. * <b>exitconn->base_.addr</b>. We expect dns_resolve_impl to return 1.
  261. * Lastly, we want it to set the TTL value to default one for DNS queries.
  262. */
  263. static void
  264. NS(test_main)(void *arg)
  265. {
  266. int retval;
  267. int made_pending;
  268. const tor_addr_t *resolved_addr;
  269. tor_addr_t addr_to_compare;
  270. tor_addr_parse(&addr_to_compare, "8.8.8.8");
  271. or_circuit_t *on_circ = tor_malloc_zero(sizeof(or_circuit_t));
  272. edge_connection_t *exitconn = create_valid_exitconn();
  273. TO_CONN(exitconn)->address = tor_strdup("8.8.8.8");
  274. retval = dns_resolve_impl(exitconn, 1, on_circ, NULL, &made_pending,
  275. NULL);
  276. resolved_addr = &(exitconn->base_.addr);
  277. tt_int_op(retval,==,1);
  278. tt_assert(tor_addr_eq(resolved_addr, (const tor_addr_t *)&addr_to_compare));
  279. tt_int_op(exitconn->address_ttl,==,DEFAULT_DNS_TTL);
  280. done:
  281. tor_free(on_circ);
  282. tor_free(TO_CONN(exitconn)->address);
  283. tor_free(exitconn);
  284. return;
  285. }
  286. #undef NS_SUBMODULE
  287. #define NS_SUBMODULE ASPECT(resolve_impl, non_exit)
  288. static void
  289. NS(test_main)(void *arg)
  290. {
  291. tt_skip();
  292. done:
  293. return;
  294. }
  295. #undef NS_SUBMODULE
  296. #define NS_SUBMODULE ASPECT(resolve_impl, addr_is_invalid_dest)
  297. static void
  298. NS(test_main)(void *arg)
  299. {
  300. tt_skip();
  301. done:
  302. return;
  303. }
  304. #undef NS_SUBMODULE
  305. #define NS_SUBMODULE ASPECT(resolve_impl, malformed_ptr)
  306. static void
  307. NS(test_main)(void *arg)
  308. {
  309. tt_skip();
  310. done:
  311. return;
  312. }
  313. #undef NS_SUBMODULE
  314. #define NS_SUBMODULE ASPECT(resolve_impl, cache_hit_pending)
  315. static void
  316. NS(test_main)(void *arg)
  317. {
  318. tt_skip();
  319. done:
  320. return;
  321. }
  322. #undef NS_SUBMODULE
  323. #define NS_SUBMODULE ASPECT(resolve_impl, cache_hit_cached)
  324. static void
  325. NS(test_main)(void *arg)
  326. {
  327. tt_skip();
  328. done:
  329. return;
  330. }
  331. #undef NS_SUBMODULE
  332. #define NS_SUBMODULE ASPECT(resolve_impl, cache_miss)
  333. static void
  334. NS(test_main)(void *arg)
  335. {
  336. tt_skip();
  337. done:
  338. return;
  339. }
  340. #undef NS_SUBMODULE
  341. struct testcase_t dns_tests[] = {
  342. TEST_CASE(clip_ttl),
  343. TEST_CASE(expiry_ttl),
  344. TEST_CASE(resolve),
  345. TEST_CASE_ASPECT(resolve_impl, addr_is_ip_no_need_to_resolve),
  346. TEST_CASE_ASPECT(resolve_impl, non_exit),
  347. TEST_CASE_ASPECT(resolve_impl, addr_is_invalid_dest),
  348. TEST_CASE_ASPECT(resolve_impl, malformed_ptr),
  349. TEST_CASE_ASPECT(resolve_impl, cache_hit_pending),
  350. TEST_CASE_ASPECT(resolve_impl, cache_hit_cached),
  351. TEST_CASE_ASPECT(resolve_impl, cache_miss),
  352. END_OF_TESTCASES
  353. };
  354. #undef NS_MODULE