diff options
Diffstat (limited to 'src/cli/vpn')
-rw-r--r-- | src/cli/vpn/.gitignore | 1 | ||||
-rw-r--r-- | src/cli/vpn/Makefile.am | 22 | ||||
-rw-r--r-- | src/cli/vpn/gnunet-vpn.c | 364 | ||||
-rw-r--r-- | src/cli/vpn/meson.build | 13 |
4 files changed, 400 insertions, 0 deletions
diff --git a/src/cli/vpn/.gitignore b/src/cli/vpn/.gitignore new file mode 100644 index 000000000..dbd75eb25 --- /dev/null +++ b/src/cli/vpn/.gitignore | |||
@@ -0,0 +1 @@ | |||
gnunet-vpn | |||
diff --git a/src/cli/vpn/Makefile.am b/src/cli/vpn/Makefile.am new file mode 100644 index 000000000..0c7c459ef --- /dev/null +++ b/src/cli/vpn/Makefile.am | |||
@@ -0,0 +1,22 @@ | |||
1 | # This Makefile.am is in the public domain | ||
2 | AM_CPPFLAGS = -I$(top_srcdir)/src/include -I$(top_builddir)/src/include | ||
3 | |||
4 | if USE_COVERAGE | ||
5 | AM_CFLAGS = --coverage -O0 | ||
6 | endif | ||
7 | |||
8 | pkgcfgdir= $(pkgdatadir)/config.d/ | ||
9 | |||
10 | libexecdir= $(pkglibdir)/libexec/ | ||
11 | |||
12 | plugindir = $(libdir)/gnunet | ||
13 | |||
14 | bin_PROGRAMS = \ | ||
15 | gnunet-vpn | ||
16 | |||
17 | gnunet_vpn_SOURCES = \ | ||
18 | gnunet-vpn.c | ||
19 | gnunet_vpn_LDADD = \ | ||
20 | $(top_builddir)/src/service/vpn/libgnunetvpn.la \ | ||
21 | $(top_builddir)/src/lib/util/libgnunetutil.la \ | ||
22 | $(GN_LIBINTL) | ||
diff --git a/src/cli/vpn/gnunet-vpn.c b/src/cli/vpn/gnunet-vpn.c new file mode 100644 index 000000000..a67e17016 --- /dev/null +++ b/src/cli/vpn/gnunet-vpn.c | |||
@@ -0,0 +1,364 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2012 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file src/vpn/gnunet-vpn.c | ||
23 | * @brief Tool to manually request VPN tunnels to be created | ||
24 | * @author Christian Grothoff | ||
25 | */ | ||
26 | |||
27 | #include "platform.h" | ||
28 | #include "gnunet_util_lib.h" | ||
29 | #include "gnunet_vpn_service.h" | ||
30 | |||
31 | |||
32 | /** | ||
33 | * Handle to vpn service. | ||
34 | */ | ||
35 | static struct GNUNET_VPN_Handle *handle; | ||
36 | |||
37 | /** | ||
38 | * Opaque redirection request handle. | ||
39 | */ | ||
40 | static struct GNUNET_VPN_RedirectionRequest *request; | ||
41 | |||
42 | /** | ||
43 | * Option -p: destination peer identity for service | ||
44 | */ | ||
45 | static char *peer_id; | ||
46 | |||
47 | /** | ||
48 | * Option -s: service name (hash to get service descriptor) | ||
49 | */ | ||
50 | static char *service_name; | ||
51 | |||
52 | /** | ||
53 | * Option -i: target IP | ||
54 | */ | ||
55 | static char *target_ip; | ||
56 | |||
57 | /** | ||
58 | * Option -4: IPv4 requested. | ||
59 | */ | ||
60 | static int ipv4; | ||
61 | |||
62 | /** | ||
63 | * Option -6: IPv6 requested. | ||
64 | */ | ||
65 | static int ipv6; | ||
66 | |||
67 | /** | ||
68 | * Option -t: TCP requested. | ||
69 | */ | ||
70 | static int tcp; | ||
71 | |||
72 | /** | ||
73 | * Option -u: UDP requested. | ||
74 | */ | ||
75 | static int udp; | ||
76 | |||
77 | /** | ||
78 | * Selected level of verbosity. | ||
79 | */ | ||
80 | static unsigned int verbosity; | ||
81 | |||
82 | /** | ||
83 | * Global return value. | ||
84 | */ | ||
85 | static int ret; | ||
86 | |||
87 | /** | ||
88 | * Option '-d': duration of the mapping | ||
89 | */ | ||
90 | static struct GNUNET_TIME_Relative duration = { 5 * 60 * 1000 }; | ||
91 | |||
92 | |||
93 | /** | ||
94 | * Shutdown. | ||
95 | */ | ||
96 | static void | ||
97 | do_disconnect (void *cls) | ||
98 | { | ||
99 | if (NULL != request) | ||
100 | { | ||
101 | GNUNET_VPN_cancel_request (request); | ||
102 | request = NULL; | ||
103 | } | ||
104 | if (NULL != handle) | ||
105 | { | ||
106 | GNUNET_VPN_disconnect (handle); | ||
107 | handle = NULL; | ||
108 | } | ||
109 | GNUNET_free (peer_id); | ||
110 | GNUNET_free (service_name); | ||
111 | GNUNET_free (target_ip); | ||
112 | } | ||
113 | |||
114 | |||
115 | /** | ||
116 | * Callback invoked from the VPN service once a redirection is | ||
117 | * available. Provides the IP address that can now be used to | ||
118 | * reach the requested destination. | ||
119 | * | ||
120 | * @param cls closure | ||
121 | * @param af address family, AF_INET or AF_INET6; AF_UNSPEC on error; | ||
122 | * will match 'result_af' from the request | ||
123 | * @param address IP address (struct in_addr or struct in_addr6, depending on 'af') | ||
124 | * that the VPN allocated for the redirection; | ||
125 | * traffic to this IP will now be redirected to the | ||
126 | * specified target peer; NULL on error | ||
127 | */ | ||
128 | static void | ||
129 | allocation_cb (void *cls, int af, const void *address) | ||
130 | { | ||
131 | char buf[INET6_ADDRSTRLEN]; | ||
132 | |||
133 | request = NULL; | ||
134 | switch (af) | ||
135 | { | ||
136 | case AF_INET6: | ||
137 | case AF_INET: | ||
138 | fprintf (stdout, "%s\n", inet_ntop (af, address, buf, sizeof(buf))); | ||
139 | break; | ||
140 | |||
141 | case AF_UNSPEC: | ||
142 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _ ("Error creating tunnel\n")); | ||
143 | ret = 1; | ||
144 | break; | ||
145 | |||
146 | default: | ||
147 | break; | ||
148 | } | ||
149 | GNUNET_SCHEDULER_shutdown (); | ||
150 | } | ||
151 | |||
152 | |||
153 | /** | ||
154 | * Main function that will be run by the scheduler. | ||
155 | * | ||
156 | * @param cls closure | ||
157 | * @param args remaining command-line arguments | ||
158 | * @param cfgfile name of the configuration file used (for saving, can be NULL!) | ||
159 | * @param cfg configuration | ||
160 | */ | ||
161 | static void | ||
162 | run (void *cls, | ||
163 | char *const *args, | ||
164 | const char *cfgfile, | ||
165 | const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
166 | { | ||
167 | int dst_af; | ||
168 | int req_af; | ||
169 | struct GNUNET_PeerIdentity peer; | ||
170 | struct GNUNET_HashCode sd; | ||
171 | const void *addr; | ||
172 | struct in_addr v4; | ||
173 | struct in6_addr v6; | ||
174 | uint8_t protocol; | ||
175 | struct GNUNET_TIME_Absolute etime; | ||
176 | |||
177 | etime = GNUNET_TIME_relative_to_absolute (duration); | ||
178 | GNUNET_SCHEDULER_add_shutdown (&do_disconnect, NULL); | ||
179 | handle = GNUNET_VPN_connect (cfg); | ||
180 | if (NULL == handle) | ||
181 | goto error; | ||
182 | req_af = AF_UNSPEC; | ||
183 | if (ipv4) | ||
184 | { | ||
185 | if (ipv6) | ||
186 | { | ||
187 | fprintf (stderr, | ||
188 | _ ("Option `%s' makes no sense with option `%s'.\n"), | ||
189 | "-4", | ||
190 | "-6"); | ||
191 | goto error; | ||
192 | } | ||
193 | req_af = AF_INET; | ||
194 | } | ||
195 | if (ipv6) | ||
196 | req_af = AF_INET6; | ||
197 | |||
198 | if (NULL == target_ip) | ||
199 | { | ||
200 | if (NULL == service_name) | ||
201 | { | ||
202 | fprintf (stderr, _ ("Option `%s' or `%s' is required.\n"), "-i", "-s"); | ||
203 | goto error; | ||
204 | } | ||
205 | if (NULL == peer_id) | ||
206 | { | ||
207 | fprintf (stderr, | ||
208 | _ ("Option `%s' is required when using option `%s'.\n"), | ||
209 | "-p", | ||
210 | "-s"); | ||
211 | goto error; | ||
212 | } | ||
213 | if (! (tcp | udp)) | ||
214 | { | ||
215 | fprintf (stderr, | ||
216 | _ ("Option `%s' or `%s' is required when using option `%s'.\n"), | ||
217 | "-t", | ||
218 | "-u", | ||
219 | "-s"); | ||
220 | goto error; | ||
221 | } | ||
222 | if (tcp & udp) | ||
223 | { | ||
224 | fprintf (stderr, | ||
225 | _ ("Option `%s' makes no sense with option `%s'.\n"), | ||
226 | "-t", | ||
227 | "-u"); | ||
228 | goto error; | ||
229 | } | ||
230 | if (tcp) | ||
231 | protocol = IPPROTO_TCP; | ||
232 | if (udp) | ||
233 | protocol = IPPROTO_UDP; | ||
234 | if (GNUNET_OK != | ||
235 | GNUNET_CRYPTO_eddsa_public_key_from_string (peer_id, | ||
236 | strlen (peer_id), | ||
237 | &peer.public_key)) | ||
238 | { | ||
239 | fprintf (stderr, _ ("`%s' is not a valid peer identifier.\n"), peer_id); | ||
240 | goto error; | ||
241 | } | ||
242 | GNUNET_TUN_service_name_to_hash (service_name, &sd); | ||
243 | request = GNUNET_VPN_redirect_to_peer (handle, | ||
244 | req_af, | ||
245 | protocol, | ||
246 | &peer, | ||
247 | &sd, | ||
248 | etime, | ||
249 | &allocation_cb, | ||
250 | NULL); | ||
251 | } | ||
252 | else | ||
253 | { | ||
254 | if (1 != inet_pton (AF_INET6, target_ip, &v6)) | ||
255 | { | ||
256 | if (1 != inet_pton (AF_INET, target_ip, &v4)) | ||
257 | { | ||
258 | fprintf (stderr, _ ("`%s' is not a valid IP address.\n"), target_ip); | ||
259 | goto error; | ||
260 | } | ||
261 | else | ||
262 | { | ||
263 | dst_af = AF_INET; | ||
264 | addr = &v4; | ||
265 | } | ||
266 | } | ||
267 | else | ||
268 | { | ||
269 | dst_af = AF_INET6; | ||
270 | addr = &v6; | ||
271 | } | ||
272 | request = GNUNET_VPN_redirect_to_ip (handle, | ||
273 | req_af, | ||
274 | dst_af, | ||
275 | addr, | ||
276 | etime, | ||
277 | &allocation_cb, | ||
278 | NULL); | ||
279 | } | ||
280 | return; | ||
281 | |||
282 | error: | ||
283 | GNUNET_SCHEDULER_shutdown (); | ||
284 | ret = 1; | ||
285 | } | ||
286 | |||
287 | |||
288 | int | ||
289 | main (int argc, char *const *argv) | ||
290 | { | ||
291 | struct GNUNET_GETOPT_CommandLineOption options[] = | ||
292 | { GNUNET_GETOPT_option_flag ('4', | ||
293 | "ipv4", | ||
294 | gettext_noop ( | ||
295 | "request that result should be an IPv4 address"), | ||
296 | &ipv4), | ||
297 | |||
298 | GNUNET_GETOPT_option_flag ('6', | ||
299 | "ipv6", | ||
300 | gettext_noop ( | ||
301 | "request that result should be an IPv6 address"), | ||
302 | &ipv6), | ||
303 | |||
304 | GNUNET_GETOPT_option_relative_time ( | ||
305 | 'd', | ||
306 | "duration", | ||
307 | "TIME", | ||
308 | gettext_noop ("how long should the mapping be valid for new tunnels?"), | ||
309 | &duration), | ||
310 | |||
311 | GNUNET_GETOPT_option_string ('i', | ||
312 | "ip", | ||
313 | "IP", | ||
314 | gettext_noop ( | ||
315 | "destination IP for the tunnel"), | ||
316 | &target_ip), | ||
317 | |||
318 | GNUNET_GETOPT_option_string ( | ||
319 | 'p', | ||
320 | "peer", | ||
321 | "PEERID", | ||
322 | gettext_noop ("peer offering the service we would like to access"), | ||
323 | &peer_id), | ||
324 | |||
325 | GNUNET_GETOPT_option_string ('s', | ||
326 | "service", | ||
327 | "NAME", | ||
328 | gettext_noop ( | ||
329 | "name of the service we would like to access"), | ||
330 | &service_name), | ||
331 | |||
332 | GNUNET_GETOPT_option_flag ('t', | ||
333 | "tcp", | ||
334 | gettext_noop ("service is offered via TCP"), | ||
335 | &tcp), | ||
336 | |||
337 | GNUNET_GETOPT_option_flag ('u', | ||
338 | "udp", | ||
339 | gettext_noop ("service is offered via UDP"), | ||
340 | &udp), | ||
341 | |||
342 | GNUNET_GETOPT_option_verbose (&verbosity), | ||
343 | |||
344 | GNUNET_GETOPT_OPTION_END }; | ||
345 | |||
346 | if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) | ||
347 | return 2; | ||
348 | |||
349 | ret = | ||
350 | (GNUNET_OK == GNUNET_PROGRAM_run (argc, | ||
351 | argv, | ||
352 | "gnunet-vpn", | ||
353 | gettext_noop ("Setup tunnels via VPN."), | ||
354 | options, | ||
355 | &run, | ||
356 | NULL)) | ||
357 | ? ret | ||
358 | : 1; | ||
359 | GNUNET_free_nz ((void *) argv); | ||
360 | return ret; | ||
361 | } | ||
362 | |||
363 | |||
364 | /* end of gnunet-vpn.c */ | ||
diff --git a/src/cli/vpn/meson.build b/src/cli/vpn/meson.build new file mode 100644 index 000000000..477551f1d --- /dev/null +++ b/src/cli/vpn/meson.build | |||
@@ -0,0 +1,13 @@ | |||
1 | executable ('gnunet-vpn', | ||
2 | ['gnunet-vpn.c'], | ||
3 | dependencies: [libgnunetvpn_dep, | ||
4 | libgnunetutil_dep, | ||
5 | libgnunetstatistics_dep, | ||
6 | libgnunetregex_dep, | ||
7 | libgnunetcore_dep, | ||
8 | libgnunetcadet_dep, | ||
9 | libgnunetblock_dep], | ||
10 | include_directories: [incdir, configuration_inc, exitdir], | ||
11 | install: true, | ||
12 | install_dir: get_option('bindir')) | ||
13 | |||