unit1607.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. /***************************************************************************
  2. * _ _ ____ _
  3. * Project ___| | | | _ \| |
  4. * / __| | | | |_) | |
  5. * | (__| |_| | _ <| |___
  6. * \___|\___/|_| \_\_____|
  7. *
  8. * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
  9. *
  10. * This software is licensed as described in the file COPYING, which
  11. * you should have received as part of this distribution. The terms
  12. * are also available at https://curl.se/docs/copyright.html.
  13. *
  14. * You may opt to use, copy, modify, merge, publish, distribute and/or sell
  15. * copies of the Software, and permit persons to whom the Software is
  16. * furnished to do so, under the terms of the COPYING file.
  17. *
  18. * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
  19. * KIND, either express or implied.
  20. *
  21. * SPDX-License-Identifier: curl
  22. *
  23. ***************************************************************************/
  24. #include "curlcheck.h"
  25. #include "urldata.h"
  26. #include "connect.h"
  27. #include "share.h"
  28. #include "memdebug.h" /* LAST include file */
  29. static void unit_stop(void)
  30. {
  31. curl_global_cleanup();
  32. }
  33. static CURLcode unit_setup(void)
  34. {
  35. CURLcode res = CURLE_OK;
  36. global_init(CURL_GLOBAL_ALL);
  37. return res;
  38. }
  39. struct testcase {
  40. /* host:port:address[,address]... */
  41. const char *optval;
  42. /* lowercase host and port to retrieve the addresses from hostcache */
  43. const char *host;
  44. int port;
  45. /* whether we expect a permanent or non-permanent cache entry */
  46. bool permanent;
  47. /* 0 to 9 addresses expected from hostcache */
  48. const char *address[10];
  49. };
  50. /* In builds without IPv6 support CURLOPT_RESOLVE should skip over those
  51. addresses, so we have to do that as well. */
  52. static const char skip = 0;
  53. #ifdef USE_IPV6
  54. #define IPV6ONLY(x) x
  55. #else
  56. #define IPV6ONLY(x) &skip
  57. #endif
  58. /* CURLOPT_RESOLVE address parsing tests */
  59. static const struct testcase tests[] = {
  60. /* spaces aren't allowed, for now */
  61. { "test.com:80:127.0.0.1, 127.0.0.2",
  62. "test.com", 80, TRUE, { NULL, }
  63. },
  64. { "TEST.com:80:,,127.0.0.1,,,127.0.0.2,,,,::1,,,",
  65. "test.com", 80, TRUE, { "127.0.0.1", "127.0.0.2", IPV6ONLY("::1"), }
  66. },
  67. { "test.com:80:::1,127.0.0.1",
  68. "test.com", 80, TRUE, { IPV6ONLY("::1"), "127.0.0.1", }
  69. },
  70. { "test.com:80:[::1],127.0.0.1",
  71. "test.com", 80, TRUE, { IPV6ONLY("::1"), "127.0.0.1", }
  72. },
  73. { "test.com:80:::1",
  74. "test.com", 80, TRUE, { IPV6ONLY("::1"), }
  75. },
  76. { "test.com:80:[::1]",
  77. "test.com", 80, TRUE, { IPV6ONLY("::1"), }
  78. },
  79. { "test.com:80:127.0.0.1",
  80. "test.com", 80, TRUE, { "127.0.0.1", }
  81. },
  82. { "test.com:80:,127.0.0.1",
  83. "test.com", 80, TRUE, { "127.0.0.1", }
  84. },
  85. { "test.com:80:127.0.0.1,",
  86. "test.com", 80, TRUE, { "127.0.0.1", }
  87. },
  88. { "test.com:0:127.0.0.1",
  89. "test.com", 0, TRUE, { "127.0.0.1", }
  90. },
  91. { "+test.com:80:127.0.0.1,",
  92. "test.com", 80, FALSE, { "127.0.0.1", }
  93. },
  94. };
  95. UNITTEST_START
  96. {
  97. int i;
  98. int testnum = sizeof(tests) / sizeof(struct testcase);
  99. struct Curl_multi *multi = NULL;
  100. struct Curl_easy *easy = NULL;
  101. struct curl_slist *list = NULL;
  102. for(i = 0; i < testnum; ++i) {
  103. int j;
  104. int addressnum = sizeof(tests[i].address) / sizeof(*tests[i].address);
  105. struct Curl_addrinfo *addr;
  106. struct Curl_dns_entry *dns;
  107. void *entry_id;
  108. bool problem = false;
  109. easy = curl_easy_init();
  110. if(!easy)
  111. goto error;
  112. /* create a multi handle and add the easy handle to it so that the
  113. hostcache is setup */
  114. multi = curl_multi_init();
  115. curl_multi_add_handle(multi, easy);
  116. list = curl_slist_append(NULL, tests[i].optval);
  117. if(!list)
  118. goto error;
  119. curl_easy_setopt(easy, CURLOPT_RESOLVE, list);
  120. Curl_loadhostpairs(easy);
  121. entry_id = (void *)aprintf("%s:%d", tests[i].host, tests[i].port);
  122. if(!entry_id)
  123. goto error;
  124. dns = Curl_hash_pick(easy->dns.hostcache, entry_id, strlen(entry_id) + 1);
  125. free(entry_id);
  126. entry_id = NULL;
  127. addr = dns ? dns->addr : NULL;
  128. for(j = 0; j < addressnum; ++j) {
  129. int port = 0;
  130. char ipaddress[MAX_IPADR_LEN] = {0};
  131. if(!addr && !tests[i].address[j])
  132. break;
  133. if(tests[i].address[j] == &skip)
  134. continue;
  135. if(addr && !Curl_addr2string(addr->ai_addr, addr->ai_addrlen,
  136. ipaddress, &port)) {
  137. fprintf(stderr, "%s:%d tests[%d] failed. getaddressinfo failed.\n",
  138. __FILE__, __LINE__, i);
  139. problem = true;
  140. break;
  141. }
  142. if(addr && !tests[i].address[j]) {
  143. fprintf(stderr, "%s:%d tests[%d] failed. the retrieved addr "
  144. "is %s but tests[%d].address[%d] is NULL.\n",
  145. __FILE__, __LINE__, i, ipaddress, i, j);
  146. problem = true;
  147. break;
  148. }
  149. if(!addr && tests[i].address[j]) {
  150. fprintf(stderr, "%s:%d tests[%d] failed. the retrieved addr "
  151. "is NULL but tests[%d].address[%d] is %s.\n",
  152. __FILE__, __LINE__, i, i, j, tests[i].address[j]);
  153. problem = true;
  154. break;
  155. }
  156. if(!curl_strequal(ipaddress, tests[i].address[j])) {
  157. fprintf(stderr, "%s:%d tests[%d] failed. the retrieved addr "
  158. "%s is not equal to tests[%d].address[%d] %s.\n",
  159. __FILE__, __LINE__, i, ipaddress, i, j, tests[i].address[j]);
  160. problem = true;
  161. break;
  162. }
  163. if(port != tests[i].port) {
  164. fprintf(stderr, "%s:%d tests[%d] failed. the retrieved port "
  165. "for tests[%d].address[%d] is %d but tests[%d].port is %d.\n",
  166. __FILE__, __LINE__, i, i, j, port, i, tests[i].port);
  167. problem = true;
  168. break;
  169. }
  170. if(dns->timestamp && tests[i].permanent) {
  171. fprintf(stderr, "%s:%d tests[%d] failed. the timestamp is not zero "
  172. "but tests[%d].permanent is TRUE\n",
  173. __FILE__, __LINE__, i, i);
  174. problem = true;
  175. break;
  176. }
  177. if(dns->timestamp == 0 && !tests[i].permanent) {
  178. fprintf(stderr, "%s:%d tests[%d] failed. the timestamp is zero "
  179. "but tests[%d].permanent is FALSE\n",
  180. __FILE__, __LINE__, i, i);
  181. problem = true;
  182. break;
  183. }
  184. addr = addr->ai_next;
  185. }
  186. curl_easy_cleanup(easy);
  187. easy = NULL;
  188. curl_multi_cleanup(multi);
  189. multi = NULL;
  190. curl_slist_free_all(list);
  191. list = NULL;
  192. if(problem) {
  193. unitfail++;
  194. continue;
  195. }
  196. }
  197. error:
  198. curl_easy_cleanup(easy);
  199. curl_multi_cleanup(multi);
  200. curl_slist_free_all(list);
  201. }
  202. UNITTEST_STOP