gnunet-vpn.c 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  1. /*
  2. This file is part of GNUnet.
  3. Copyright (C) 2012 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. * @file src/vpn/gnunet-vpn.c
  18. * @brief Tool to manually request VPN tunnels to be created
  19. * @author Christian Grothoff
  20. */
  21. #include "platform.h"
  22. #include "gnunet_util_lib.h"
  23. #include "gnunet_tun_lib.h"
  24. #include "gnunet_vpn_service.h"
  25. /**
  26. * Handle to vpn service.
  27. */
  28. static struct GNUNET_VPN_Handle *handle;
  29. /**
  30. * Opaque redirection request handle.
  31. */
  32. static struct GNUNET_VPN_RedirectionRequest *request;
  33. /**
  34. * Option -p: destination peer identity for service
  35. */
  36. static char *peer_id;
  37. /**
  38. * Option -s: service name (hash to get service descriptor)
  39. */
  40. static char *service_name;
  41. /**
  42. * Option -i: target IP
  43. */
  44. static char *target_ip;
  45. /**
  46. * Option -4: IPv4 requested.
  47. */
  48. static int ipv4;
  49. /**
  50. * Option -6: IPv6 requested.
  51. */
  52. static int ipv6;
  53. /**
  54. * Option -t: TCP requested.
  55. */
  56. static int tcp;
  57. /**
  58. * Option -u: UDP requested.
  59. */
  60. static int udp;
  61. /**
  62. * Selected level of verbosity.
  63. */
  64. static unsigned int verbosity;
  65. /**
  66. * Global return value.
  67. */
  68. static int ret;
  69. /**
  70. * Option '-d': duration of the mapping
  71. */
  72. static struct GNUNET_TIME_Relative duration = { 5 * 60 * 1000} ;
  73. /**
  74. * Shutdown.
  75. */
  76. static void
  77. do_disconnect (void *cls)
  78. {
  79. if (NULL != request)
  80. {
  81. GNUNET_VPN_cancel_request (request);
  82. request = NULL;
  83. }
  84. if (NULL != handle)
  85. {
  86. GNUNET_VPN_disconnect (handle);
  87. handle = NULL;
  88. }
  89. GNUNET_free_non_null (peer_id);
  90. GNUNET_free_non_null (service_name);
  91. GNUNET_free_non_null (target_ip);
  92. }
  93. /**
  94. * Callback invoked from the VPN service once a redirection is
  95. * available. Provides the IP address that can now be used to
  96. * reach the requested destination.
  97. *
  98. * @param cls closure
  99. * @param af address family, AF_INET or AF_INET6; AF_UNSPEC on error;
  100. * will match 'result_af' from the request
  101. * @param address IP address (struct in_addr or struct in_addr6, depending on 'af')
  102. * that the VPN allocated for the redirection;
  103. * traffic to this IP will now be redirected to the
  104. * specified target peer; NULL on error
  105. */
  106. static void
  107. allocation_cb (void *cls,
  108. int af,
  109. const void *address)
  110. {
  111. char buf[INET6_ADDRSTRLEN];
  112. request = NULL;
  113. switch (af)
  114. {
  115. case AF_INET6:
  116. case AF_INET:
  117. FPRINTF (stdout,
  118. "%s\n",
  119. inet_ntop (af, address, buf, sizeof (buf)));
  120. break;
  121. case AF_UNSPEC:
  122. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  123. _("Error creating tunnel\n"));
  124. ret = 1;
  125. break;
  126. default:
  127. break;
  128. }
  129. GNUNET_SCHEDULER_shutdown ();
  130. }
  131. /**
  132. * Main function that will be run by the scheduler.
  133. *
  134. * @param cls closure
  135. * @param args remaining command-line arguments
  136. * @param cfgfile name of the configuration file used (for saving, can be NULL!)
  137. * @param cfg configuration
  138. */
  139. static void
  140. run (void *cls,
  141. char *const *args,
  142. const char *cfgfile,
  143. const struct GNUNET_CONFIGURATION_Handle *cfg)
  144. {
  145. int dst_af;
  146. int req_af;
  147. struct GNUNET_PeerIdentity peer;
  148. struct GNUNET_HashCode sd;
  149. const void *addr;
  150. struct in_addr v4;
  151. struct in6_addr v6;
  152. uint8_t protocol;
  153. struct GNUNET_TIME_Absolute etime;
  154. etime = GNUNET_TIME_relative_to_absolute (duration);
  155. GNUNET_SCHEDULER_add_shutdown (&do_disconnect, NULL);
  156. handle = GNUNET_VPN_connect (cfg);
  157. if (NULL == handle)
  158. goto error;
  159. req_af = AF_UNSPEC;
  160. if (ipv4)
  161. {
  162. if (ipv6)
  163. {
  164. FPRINTF (stderr, _("Option `%s' makes no sense with option `%s'.\n"),
  165. "-4", "-6");
  166. goto error;
  167. }
  168. req_af = AF_INET;
  169. }
  170. if (ipv6)
  171. req_af = AF_INET6;
  172. if (NULL == target_ip)
  173. {
  174. if (NULL == service_name)
  175. {
  176. FPRINTF (stderr, _("Option `%s' or `%s' is required.\n"),
  177. "-i", "-s");
  178. goto error;
  179. }
  180. if (NULL == peer_id)
  181. {
  182. FPRINTF (stderr, _("Option `%s' is required when using option `%s'.\n"),
  183. "-p", "-s");
  184. goto error;
  185. }
  186. if (! (tcp | udp) )
  187. {
  188. FPRINTF (stderr, _("Option `%s' or `%s' is required when using option `%s'.\n"),
  189. "-t", "-u", "-s");
  190. goto error;
  191. }
  192. if (tcp & udp)
  193. {
  194. FPRINTF (stderr, _("Option `%s' makes no sense with option `%s'.\n"),
  195. "-t", "-u");
  196. goto error;
  197. }
  198. if (tcp)
  199. protocol = IPPROTO_TCP;
  200. if (udp)
  201. protocol = IPPROTO_UDP;
  202. if (GNUNET_OK !=
  203. GNUNET_CRYPTO_eddsa_public_key_from_string (peer_id,
  204. strlen (peer_id),
  205. &peer.public_key))
  206. {
  207. FPRINTF (stderr,
  208. _("`%s' is not a valid peer identifier.\n"),
  209. peer_id);
  210. goto error;
  211. }
  212. GNUNET_TUN_service_name_to_hash (service_name,
  213. &sd);
  214. request = GNUNET_VPN_redirect_to_peer (handle,
  215. req_af,
  216. protocol,
  217. &peer,
  218. &sd,
  219. etime,
  220. &allocation_cb, NULL);
  221. }
  222. else
  223. {
  224. if (1 != inet_pton (AF_INET6, target_ip, &v6))
  225. {
  226. if (1 != inet_pton (AF_INET, target_ip, &v4))
  227. {
  228. FPRINTF (stderr, _("`%s' is not a valid IP address.\n"),
  229. target_ip);
  230. goto error;
  231. }
  232. else
  233. {
  234. dst_af = AF_INET;
  235. addr = &v4;
  236. }
  237. }
  238. else
  239. {
  240. dst_af = AF_INET6;
  241. addr = &v6;
  242. }
  243. request = GNUNET_VPN_redirect_to_ip (handle,
  244. req_af,
  245. dst_af,
  246. addr,
  247. etime,
  248. &allocation_cb, NULL);
  249. }
  250. return;
  251. error:
  252. GNUNET_SCHEDULER_shutdown ();
  253. ret = 1;
  254. }
  255. int
  256. main (int argc, char *const *argv)
  257. {
  258. struct GNUNET_GETOPT_CommandLineOption options[] = {
  259. GNUNET_GETOPT_option_flag ('4',
  260. "ipv4",
  261. gettext_noop ("request that result should be an IPv4 address"),
  262. &ipv4),
  263. GNUNET_GETOPT_option_flag ('6',
  264. "ipv6",
  265. gettext_noop ("request that result should be an IPv6 address"),
  266. &ipv6),
  267. GNUNET_GETOPT_option_relative_time ('d',
  268. "duration",
  269. "TIME",
  270. gettext_noop ("how long should the mapping be valid for new tunnels?"),
  271. &duration),
  272. GNUNET_GETOPT_option_string ('i',
  273. "ip",
  274. "IP",
  275. gettext_noop ("destination IP for the tunnel"),
  276. &target_ip),
  277. GNUNET_GETOPT_option_string ('p',
  278. "peer",
  279. "PEERID",
  280. gettext_noop ("peer offering the service we would like to access"),
  281. &peer_id),
  282. GNUNET_GETOPT_option_string ('s',
  283. "service",
  284. "NAME",
  285. gettext_noop ("name of the service we would like to access"),
  286. &service_name),
  287. GNUNET_GETOPT_option_flag ('t',
  288. "tcp",
  289. gettext_noop ("service is offered via TCP"),
  290. &tcp),
  291. GNUNET_GETOPT_option_flag ('u',
  292. "udp",
  293. gettext_noop ("service is offered via UDP"),
  294. &udp),
  295. GNUNET_GETOPT_option_verbose (&verbosity),
  296. GNUNET_GETOPT_OPTION_END
  297. };
  298. if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
  299. return 2;
  300. ret = (GNUNET_OK ==
  301. GNUNET_PROGRAM_run (argc, argv, "gnunet-vpn",
  302. gettext_noop
  303. ("Setup tunnels via VPN."), options,
  304. &run, NULL)) ? ret : 1;
  305. GNUNET_free ((void *) argv);
  306. return ret;
  307. }
  308. /* end of gnunet-vpn.c */