aboutsummaryrefslogtreecommitdiff
path: root/src/nat/gnunet-nat.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nat/gnunet-nat.c')
-rw-r--r--src/nat/gnunet-nat.c476
1 files changed, 0 insertions, 476 deletions
diff --git a/src/nat/gnunet-nat.c b/src/nat/gnunet-nat.c
deleted file mode 100644
index 0743a478d..000000000
--- a/src/nat/gnunet-nat.c
+++ /dev/null
@@ -1,476 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2015, 2016 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/nat/gnunet-nat.c
23 * @brief Command-line tool to interact with the NAT service
24 * @author Christian Grothoff
25 * @author Bruno Cabral
26 */
27#include "platform.h"
28#include "gnunet_util_lib.h"
29#include "gnunet_nat_service.h"
30
31/**
32 * Value to return from #main().
33 */
34static int global_ret;
35
36/**
37 * Name of section in configuration file to use for
38 * additional options.
39 */
40static char *section_name;
41
42/**
43 * Flag set to 1 if we use IPPROTO_UDP.
44 */
45static int use_udp;
46
47/**
48 * Flag set to 1 if we are to listen for connection reversal requests.
49 */
50static int listen_reversal;
51
52/**
53 * Flag set to 1 if we use IPPROTO_TCP.
54 */
55static int use_tcp;
56
57/**
58 * Protocol to use.
59 */
60static uint8_t proto;
61
62/**
63 * Local address to use for connection reversal request.
64 */
65static char *local_addr;
66
67/**
68 * Remote address to use for connection reversal request.
69 */
70static char *remote_addr;
71
72/**
73 * Should we actually bind to #bind_addr and receive and process STUN requests?
74 */
75static int do_stun;
76
77/**
78 * Handle to NAT operation.
79 */
80static struct GNUNET_NAT_Handle *nh;
81
82/**
83 * Listen socket for STUN processing.
84 */
85static struct GNUNET_NETWORK_Handle *ls;
86
87/**
88 * Task for reading STUN packets.
89 */
90static struct GNUNET_SCHEDULER_Task *rtask;
91
92
93/**
94 * Test if all activities have finished, and if so,
95 * terminate.
96 */
97static void
98test_finished ()
99{
100 if (NULL != nh)
101 return;
102 if (NULL != rtask)
103 return;
104 GNUNET_SCHEDULER_shutdown ();
105}
106
107
108/**
109 * Signature of the callback passed to #GNUNET_NAT_register() for
110 * a function to call whenever our set of 'valid' addresses changes.
111 *
112 * @param cls closure, NULL
113 * @param app_ctx[in,out] location where the app can store stuff
114 * on add and retrieve it on remove
115 * @param add_remove #GNUNET_YES to add a new public IP address,
116 * #GNUNET_NO to remove a previous (now invalid) one
117 * @param ac address class the address belongs to
118 * @param addr either the previous or the new public IP address
119 * @param addrlen actual length of the @a addr
120 */
121static void
122address_cb (void *cls,
123 void **app_ctx,
124 int add_remove,
125 enum GNUNET_NAT_AddressClass ac,
126 const struct sockaddr *addr,
127 socklen_t addrlen)
128{
129 (void) cls;
130 (void) app_ctx;
131
132 fprintf (stdout,
133 "%s %s (%d)\n",
134 add_remove ? "+" : "-",
135 GNUNET_a2s (addr, addrlen),
136 (int) ac);
137}
138
139
140/**
141 * Signature of the callback passed to #GNUNET_NAT_register().
142 * for a function to call whenever someone asks us to do connection
143 * reversal.
144 *
145 * @param cls closure, NULL
146 * @param remote_addr public IP address of the other peer
147 * @param remote_addrlen actual length of the @a remote_addr
148 */
149static void
150reversal_cb (void *cls,
151 const struct sockaddr *remote_addr,
152 socklen_t remote_addrlen)
153{
154 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
155 "Connection reversal requested by %s\n",
156 GNUNET_a2s (remote_addr, remote_addrlen));
157}
158
159
160/**
161 * Task run on shutdown.
162 *
163 * @param cls NULL
164 */
165static void
166do_shutdown (void *cls)
167{
168 if (NULL != nh)
169 {
170 GNUNET_NAT_unregister (nh);
171 nh = NULL;
172 }
173 if (NULL != ls)
174 {
175 GNUNET_NETWORK_socket_close (ls);
176 ls = NULL;
177 }
178 if (NULL != rtask)
179 {
180 GNUNET_SCHEDULER_cancel (rtask);
181 rtask = NULL;
182 }
183}
184
185
186/**
187 * Task to receive incoming packets for STUN processing.
188 */
189static void
190stun_read_task (void *cls)
191{
192 ssize_t size;
193
194 rtask = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
195 ls,
196 &stun_read_task,
197 NULL);
198 size = GNUNET_NETWORK_socket_recvfrom_amount (ls);
199 if (size > 0)
200 {
201 GNUNET_break (0);
202 GNUNET_SCHEDULER_shutdown ();
203 global_ret = 1;
204 return;
205 }
206 {
207 char buf[size + 1];
208 struct sockaddr_storage sa;
209 socklen_t salen = sizeof(sa);
210 ssize_t ret;
211
212 ret = GNUNET_NETWORK_socket_recvfrom (ls,
213 buf,
214 size + 1,
215 (struct sockaddr *) &sa,
216 &salen);
217 if (ret != size)
218 {
219 GNUNET_break (0);
220 GNUNET_SCHEDULER_shutdown ();
221 global_ret = 1;
222 return;
223 }
224 (void) GNUNET_NAT_stun_handle_packet (nh,
225 (const struct sockaddr *) &sa,
226 salen,
227 buf,
228 ret);
229 }
230}
231
232
233/**
234 * Main function that will be run.
235 *
236 * @param cls closure
237 * @param args remaining command-line arguments
238 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
239 * @param c configuration
240 */
241static void
242run (void *cls,
243 char *const *args,
244 const char *cfgfile,
245 const struct GNUNET_CONFIGURATION_Handle *c)
246{
247 uint8_t af;
248 struct sockaddr *local_sa;
249 struct sockaddr *remote_sa;
250 socklen_t local_len;
251 size_t remote_len;
252
253 if (use_tcp && use_udp)
254 {
255 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, "Cannot use TCP and UDP\n");
256 global_ret = 1;
257 return;
258 }
259 proto = 0;
260 if (use_tcp)
261 proto = IPPROTO_TCP;
262 if (use_udp)
263 proto = IPPROTO_UDP;
264
265 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
266
267 if (0 == proto)
268 {
269 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, "Must specify either TCP or UDP\n");
270 global_ret = 1;
271 return;
272 }
273 local_len = 0;
274 local_sa = NULL;
275 remote_len = 0;
276 remote_sa = NULL;
277 if (NULL != local_addr)
278 {
279 local_len =
280 (socklen_t) GNUNET_STRINGS_parse_socket_addr (local_addr, &af, &local_sa);
281 if (0 == local_len)
282 {
283 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
284 "Invalid socket address `%s'\n",
285 local_addr);
286 goto fail_and_shutdown;
287 }
288 }
289
290 if (NULL != remote_addr)
291 {
292 remote_len =
293 GNUNET_STRINGS_parse_socket_addr (remote_addr, &af, &remote_sa);
294 if (0 == remote_len)
295 {
296 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
297 "Invalid socket address `%s'\n",
298 remote_addr);
299 goto fail_and_shutdown;
300 }
301 }
302
303 if (NULL != local_addr)
304 {
305 if (NULL == section_name)
306 section_name = GNUNET_strdup ("undefined");
307 nh = GNUNET_NAT_register (c,
308 section_name,
309 proto,
310 1,
311 (const struct sockaddr **) &local_sa,
312 &local_len,
313 &address_cb,
314 (listen_reversal) ? &reversal_cb : NULL,
315 NULL);
316 }
317 else if (listen_reversal)
318 {
319 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
320 "Use of `-W` only effective in combination with `-i`\n");
321 goto fail_and_shutdown;
322 }
323
324 if (NULL != remote_addr)
325 {
326 int ret;
327
328 if ((NULL == nh) || (sizeof(struct sockaddr_in) != local_len))
329 {
330 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
331 "Require IPv4 local address to initiate connection reversal\n");
332 goto fail_and_shutdown;
333 }
334 if (sizeof(struct sockaddr_in) != remote_len)
335 {
336 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
337 "Require IPv4 reversal target address\n");
338 goto fail_and_shutdown;
339 }
340 GNUNET_assert (AF_INET == local_sa->sa_family);
341 GNUNET_assert (AF_INET == remote_sa->sa_family);
342 ret = GNUNET_NAT_request_reversal (nh,
343 (const struct sockaddr_in *) local_sa,
344 (const struct sockaddr_in *) remote_sa);
345 switch (ret)
346 {
347 case GNUNET_SYSERR:
348 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
349 "Connection reversal internal error\n");
350 break;
351
352 case GNUNET_NO:
353 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
354 "Connection reversal unavailable\n");
355 break;
356
357 case GNUNET_OK:
358 /* operation in progress */
359 break;
360 }
361 }
362
363 if (do_stun)
364 {
365 if (NULL == local_addr)
366 {
367 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
368 "Require local address to support STUN requests\n");
369 goto fail_and_shutdown;
370 }
371 if (IPPROTO_UDP != proto)
372 {
373 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, "STUN only supported over UDP\n");
374 goto fail_and_shutdown;
375 }
376 ls = GNUNET_NETWORK_socket_create (af, SOCK_DGRAM, IPPROTO_UDP);
377 if (NULL == ls)
378 {
379 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, "Failed to create socket\n");
380 goto fail_and_shutdown;
381 }
382 if (GNUNET_OK != GNUNET_NETWORK_socket_bind (ls, local_sa, local_len))
383 {
384 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
385 "Failed to bind to %s: %s\n",
386 GNUNET_a2s (local_sa, local_len),
387 strerror (errno));
388 goto fail_and_shutdown;
389 }
390 rtask = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
391 ls,
392 &stun_read_task,
393 NULL);
394 }
395 GNUNET_free (remote_sa);
396 GNUNET_free (local_sa);
397 test_finished ();
398 return;
399fail_and_shutdown:
400 global_ret = 1;
401 GNUNET_SCHEDULER_shutdown ();
402 GNUNET_free (remote_sa);
403 GNUNET_free (local_sa);
404}
405
406
407/**
408 * Main function of gnunet-nat
409 *
410 * @param argc number of command-line arguments
411 * @param argv command line
412 * @return 0 on success, -1 on error
413 */
414int
415main (int argc, char *const argv[])
416{
417 struct GNUNET_GETOPT_CommandLineOption options[] = {
418 GNUNET_GETOPT_option_string (
419 'i',
420 "in",
421 "ADDRESS",
422 gettext_noop ("which IP and port are we locally using to bind/listen to"),
423 &local_addr),
424
425 GNUNET_GETOPT_option_string (
426 'r',
427 "remote",
428 "ADDRESS",
429 gettext_noop (
430 "which remote IP and port should be asked for connection reversal"),
431 &remote_addr),
432
433 GNUNET_GETOPT_option_string (
434 'S',
435 "section",
436 NULL,
437 gettext_noop (
438 "name of configuration section to find additional options, such as manual host punching data"),
439 &section_name),
440
441 GNUNET_GETOPT_option_flag ('s',
442 "stun",
443 gettext_noop ("enable STUN processing"),
444 &do_stun),
445
446 GNUNET_GETOPT_option_flag ('t', "tcp", gettext_noop ("use TCP"), &use_tcp),
447
448 GNUNET_GETOPT_option_flag ('u', "udp", gettext_noop ("use UDP"), &use_udp),
449
450 GNUNET_GETOPT_option_flag ('W',
451 "watch",
452 gettext_noop (
453 "watch for connection reversal requests"),
454 &listen_reversal),
455 GNUNET_GETOPT_OPTION_END
456 };
457
458 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
459 return 2;
460 if (GNUNET_OK !=
461 GNUNET_PROGRAM_run (argc,
462 argv,
463 "gnunet-nat [options]",
464 _ ("GNUnet NAT traversal autoconfigure daemon"),
465 options,
466 &run,
467 NULL))
468 {
469 global_ret = 1;
470 }
471 GNUNET_free_nz ((void *) argv);
472 return global_ret;
473}
474
475
476/* end of gnunet-nat.c */