test_stun.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. /*
  2. This file is part of GNUnet.
  3. Copyright (C) 2009, 2015 GNUnet e.V.
  4. GNUnet is free software: you can redistribute it and/or modify it
  5. under the terms of the GNU Affero General Public License as published
  6. by the Free Software Foundation, either version 3 of the License,
  7. or (at your option) any later version.
  8. GNUnet is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Affero General Public License for more details.
  12. You should have received a copy of the GNU Affero General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. SPDX-License-Identifier: AGPL3.0-or-later
  15. */
  16. /**
  17. * Testcase for STUN server resolution
  18. *
  19. * @file nat/test_stun.c
  20. * @brief Testcase for STUN library
  21. * @author Bruno Souza Cabral
  22. * @author Christian Grothoff
  23. */
  24. #include "platform.h"
  25. #include "gnunet_util_lib.h"
  26. #include "gnunet_program_lib.h"
  27. #include "gnunet_scheduler_lib.h"
  28. #include "gnunet_nat_lib.h"
  29. #define LOG(kind,...) GNUNET_log_from (kind, "test-stun", __VA_ARGS__)
  30. /**
  31. * Time to wait before stopping NAT, in seconds
  32. */
  33. #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
  34. /**
  35. * The port the test service is running on (default 7895)
  36. */
  37. static unsigned long port = 7895;
  38. static int ret = 1;
  39. static const char *stun_server = "stun.gnunet.org";
  40. static int stun_port = 3478;
  41. /**
  42. * The listen socket of the service for IPv4
  43. */
  44. static struct GNUNET_NETWORK_Handle *lsock4;
  45. /**
  46. * The listen task ID for IPv4
  47. */
  48. static struct GNUNET_SCHEDULER_Task *ltask4;
  49. /**
  50. * Handle for the STUN request.
  51. */
  52. static struct GNUNET_NAT_STUN_Handle *rh;
  53. static void
  54. print_answer(struct sockaddr_in* answer)
  55. {
  56. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  57. "External IP is: %s , with port %d\n",
  58. inet_ntoa (answer->sin_addr),
  59. ntohs (answer->sin_port));
  60. }
  61. /**
  62. * Function that terminates the test.
  63. */
  64. static void
  65. stop ()
  66. {
  67. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  68. "Stopping NAT and quitting...\n");
  69. if (NULL != ltask4)
  70. {
  71. GNUNET_SCHEDULER_cancel (ltask4);
  72. ltask4 = NULL;
  73. }
  74. if(NULL != lsock4)
  75. {
  76. GNUNET_NETWORK_socket_close(lsock4);
  77. lsock4 = NULL;
  78. }
  79. if (NULL != rh)
  80. {
  81. GNUNET_NAT_stun_make_request_cancel (rh);
  82. rh = NULL;
  83. }
  84. }
  85. /**
  86. * Activity on our incoming socket. Read data from the
  87. * incoming connection.
  88. *
  89. * @param cls
  90. */
  91. static void
  92. do_udp_read (void *cls)
  93. {
  94. //struct GNUNET_NAT_Test *tst = cls;
  95. unsigned char reply_buf[1024];
  96. ssize_t rlen;
  97. struct sockaddr_in answer;
  98. const struct GNUNET_SCHEDULER_TaskContext *tc;
  99. ltask4 = NULL;
  100. tc = GNUNET_SCHEDULER_get_task_context ();
  101. if ( (0 == (tc->reason & GNUNET_SCHEDULER_REASON_READ_READY)) ||
  102. (! GNUNET_NETWORK_fdset_isset (tc->read_ready,
  103. lsock4)) )
  104. {
  105. fprintf (stderr,
  106. "Timeout waiting for STUN response\n");
  107. stop();
  108. }
  109. rlen = GNUNET_NETWORK_socket_recv (lsock4,
  110. reply_buf,
  111. sizeof (reply_buf));
  112. memset (&answer,
  113. 0,
  114. sizeof(struct sockaddr_in));
  115. if (GNUNET_OK !=
  116. GNUNET_NAT_stun_handle_packet (reply_buf,
  117. rlen,
  118. &answer))
  119. {
  120. fprintf (stderr,
  121. "Unexpected UDP packet, trying to read more\n");
  122. ltask4 = GNUNET_SCHEDULER_add_read_net (TIMEOUT,
  123. lsock4,
  124. &do_udp_read, NULL);
  125. return;
  126. }
  127. ret = 0;
  128. print_answer (&answer);
  129. stop ();
  130. }
  131. /**
  132. * Create an IPv4 listen socket bound to our port.
  133. *
  134. * @return NULL on error
  135. */
  136. static struct GNUNET_NETWORK_Handle *
  137. bind_v4 ()
  138. {
  139. struct GNUNET_NETWORK_Handle *ls;
  140. struct sockaddr_in sa4;
  141. int eno;
  142. memset (&sa4, 0, sizeof (sa4));
  143. sa4.sin_family = AF_INET;
  144. sa4.sin_port = htons (port);
  145. #if HAVE_SOCKADDR_IN_SIN_LEN
  146. sa4.sin_len = sizeof (sa4);
  147. #endif
  148. ls = GNUNET_NETWORK_socket_create (AF_INET,
  149. SOCK_DGRAM,
  150. 0);
  151. if (NULL == ls)
  152. return NULL;
  153. if (GNUNET_OK !=
  154. GNUNET_NETWORK_socket_bind (ls,
  155. (const struct sockaddr *) &sa4,
  156. sizeof (sa4)))
  157. {
  158. eno = errno;
  159. GNUNET_NETWORK_socket_close (ls);
  160. errno = eno;
  161. return NULL;
  162. }
  163. return ls;
  164. }
  165. /**
  166. * Function called with the result of the STUN request transmission attempt.
  167. *
  168. * @param cls unused
  169. * @param error status code from STUN
  170. */
  171. static void
  172. request_callback (void *cls,
  173. enum GNUNET_NAT_StatusCode error)
  174. {
  175. rh = NULL;
  176. if (GNUNET_NAT_ERROR_SUCCESS == error)
  177. {
  178. /* all good, start to receive */
  179. ltask4 = GNUNET_SCHEDULER_add_read_net (TIMEOUT,
  180. lsock4,
  181. &do_udp_read,
  182. NULL);
  183. return;
  184. }
  185. if (error == GNUNET_NAT_ERROR_NOT_ONLINE)
  186. {
  187. ret = 77; /* report 'skip' */
  188. fprintf (stderr,
  189. "System is offline, cannot test STUN request.\n");
  190. }
  191. else
  192. {
  193. ret = error;
  194. }
  195. stop();
  196. }
  197. /**
  198. * Main function run with scheduler.
  199. */
  200. static void
  201. run (void *cls,
  202. char *const *args,
  203. const char *cfgfile,
  204. const struct GNUNET_CONFIGURATION_Handle *cfg)
  205. {
  206. //Lets create the socket
  207. lsock4 = bind_v4 ();
  208. if (NULL == lsock4)
  209. {
  210. GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
  211. "bind");
  212. GNUNET_SCHEDULER_shutdown ();
  213. return;
  214. }
  215. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  216. "Service listens on port %u\n",
  217. (unsigned int) port);
  218. rh = GNUNET_NAT_stun_make_request (stun_server,
  219. stun_port,
  220. lsock4,
  221. &request_callback, NULL);
  222. GNUNET_SCHEDULER_add_delayed (TIMEOUT,
  223. &stop, NULL);
  224. }
  225. int
  226. main (int argc, char *const argv[])
  227. {
  228. struct GNUNET_GETOPT_CommandLineOption options[] = {
  229. GNUNET_GETOPT_OPTION_END
  230. };
  231. char *const argv_prog[] = {
  232. "test-stun",
  233. "-c",
  234. "test_stun.conf",
  235. NULL
  236. };
  237. char *fn;
  238. struct GNUNET_OS_Process *proc;
  239. GNUNET_log_setup ("test-stun",
  240. "WARNING",
  241. NULL);
  242. /* Lets start resolver */
  243. fn = GNUNET_OS_get_libexec_binary_path ("gnunet-service-resolver");
  244. proc = GNUNET_OS_start_process (GNUNET_YES,
  245. GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
  246. NULL, NULL, NULL,
  247. fn,
  248. "gnunet-service-resolver",
  249. "-c", "test_stun.conf", NULL);
  250. if (NULL == proc)
  251. {
  252. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  253. "This test was unable to start gnunet-service-resolver, and it is required to run ...\n");
  254. exit(1);
  255. }
  256. GNUNET_PROGRAM_run (3, argv_prog,
  257. "test-stun", "nohelp",
  258. options,
  259. &run, NULL);
  260. /* Now kill the resolver */
  261. if (0 != GNUNET_OS_process_kill (proc, GNUNET_TERM_SIG))
  262. {
  263. GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill");
  264. }
  265. GNUNET_OS_process_wait (proc);
  266. GNUNET_OS_process_destroy (proc);
  267. proc = NULL;
  268. GNUNET_free (fn);
  269. return ret;
  270. }
  271. /* end of test_stun.c */