2 This file is part of GNUnet.
3 Copyright (C) 2015, 2016 GNUnet e.V.
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU 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.
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.
17 * @file src/nat/gnunet-nat.c
18 * @brief Command-line tool to interact with the NAT service
19 * @author Christian Grothoff
20 * @author Bruno Cabral
23 #include "gnunet_util_lib.h"
24 #include "gnunet_nat_service.h"
27 * Value to return from #main().
29 static int global_ret;
32 * Name of section in configuration file to use for
35 static char *section_name;
38 * Flag set to 1 if we use IPPROTO_UDP.
43 * Flag set to 1 if we are to listen for connection reversal requests.
45 static int listen_reversal;
48 * Flag set to 1 if we use IPPROTO_TCP.
58 * Local address to use for connection reversal request.
60 static char *local_addr;
63 * Remote address to use for connection reversal request.
65 static char *remote_addr;
68 * Should we actually bind to #bind_addr and receive and process STUN requests?
73 * Handle to NAT operation.
75 static struct GNUNET_NAT_Handle *nh;
78 * Listen socket for STUN processing.
80 static struct GNUNET_NETWORK_Handle *ls;
83 * Task for reading STUN packets.
85 static struct GNUNET_SCHEDULER_Task *rtask;
89 * Test if all activities have finished, and if so,
99 GNUNET_SCHEDULER_shutdown ();
104 * Signature of the callback passed to #GNUNET_NAT_register() for
105 * a function to call whenever our set of 'valid' addresses changes.
107 * @param cls closure, NULL
108 * @param add_remove #GNUNET_YES to add a new public IP address,
109 * #GNUNET_NO to remove a previous (now invalid) one
110 * @param ac address class the address belongs to
111 * @param addr either the previous or the new public IP address
112 * @param addrlen actual length of the @a addr
115 address_cb (void *cls,
117 enum GNUNET_NAT_AddressClass ac,
118 const struct sockaddr *addr,
123 add_remove ? "+" : "-",
131 * Signature of the callback passed to #GNUNET_NAT_register().
132 * for a function to call whenever someone asks us to do connection
135 * @param cls closure, NULL
136 * @param remote_addr public IP address of the other peer
137 * @param remote_addrlen actual length of the @a remote_addr
140 reversal_cb (void *cls,
141 const struct sockaddr *remote_addr,
142 socklen_t remote_addrlen)
144 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
145 "Connection reversal requested by %s\n",
146 GNUNET_a2s (remote_addr,
152 * Task run on shutdown.
157 do_shutdown (void *cls)
161 GNUNET_NAT_unregister (nh);
166 GNUNET_NETWORK_socket_close (ls);
171 GNUNET_SCHEDULER_cancel (rtask);
178 * Task to receive incoming packets for STUN processing.
181 stun_read_task (void *cls)
185 rtask = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
189 size = GNUNET_NETWORK_socket_recvfrom_amount (ls);
193 GNUNET_SCHEDULER_shutdown ();
199 struct sockaddr_storage sa;
200 socklen_t salen = sizeof (sa);
203 ret = GNUNET_NETWORK_socket_recvfrom (ls,
206 (struct sockaddr *) &sa,
211 GNUNET_SCHEDULER_shutdown ();
215 (void) GNUNET_NAT_stun_handle_packet (nh,
216 (const struct sockaddr *) &sa,
225 * Main function that will be run.
228 * @param args remaining command-line arguments
229 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
230 * @param c configuration
236 const struct GNUNET_CONFIGURATION_Handle *c)
239 struct sockaddr *local_sa;
240 struct sockaddr *remote_sa;
244 if (use_tcp && use_udp)
246 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
247 "Cannot use TCP and UDP\n");
257 GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
262 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
263 "Must specify either TCP or UDP\n");
271 if (NULL != local_addr)
273 local_len = (socklen_t) GNUNET_STRINGS_parse_socket_addr (local_addr,
278 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
279 "Invalid socket address `%s'\n",
281 goto fail_and_shutdown;
285 if (NULL != remote_addr)
287 remote_len = GNUNET_STRINGS_parse_socket_addr (remote_addr,
292 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
293 "Invalid socket address `%s'\n",
295 goto fail_and_shutdown;
299 if (NULL != local_addr)
301 if (NULL == section_name)
302 section_name = GNUNET_strdup ("undefined");
303 nh = GNUNET_NAT_register (c,
307 (const struct sockaddr **) &local_sa,
310 (listen_reversal) ? &reversal_cb : NULL,
313 else if (listen_reversal)
315 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
316 "Use of `-W` only effective in combination with `-i`\n");
317 goto fail_and_shutdown;
320 if (NULL != remote_addr)
325 (sizeof (struct sockaddr_in) != local_len) )
327 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
328 "Require IPv4 local address to initiate connection reversal\n");
329 goto fail_and_shutdown;
331 if (sizeof (struct sockaddr_in) != remote_len)
333 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
334 "Require IPv4 reversal target address\n");
335 goto fail_and_shutdown;
337 GNUNET_assert (AF_INET == local_sa->sa_family);
338 GNUNET_assert (AF_INET == remote_sa->sa_family);
339 ret = GNUNET_NAT_request_reversal (nh,
340 (const struct sockaddr_in *) local_sa,
341 (const struct sockaddr_in *) remote_sa);
345 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
346 "Connection reversal internal error\n");
349 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
350 "Connection reversal unavailable\n");
353 /* operation in progress */
360 if (NULL == local_addr)
362 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
363 "Require local address to support STUN requests\n");
364 goto fail_and_shutdown;
366 if (IPPROTO_UDP != proto)
368 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
369 "STUN only supported over UDP\n");
370 goto fail_and_shutdown;
372 ls = GNUNET_NETWORK_socket_create (af,
377 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
378 "Failed to create socket\n");
379 goto fail_and_shutdown;
382 GNUNET_NETWORK_socket_bind (ls,
386 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
387 "Failed to bind to %s: %s\n",
388 GNUNET_a2s (local_sa,
391 goto fail_and_shutdown;
393 rtask = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
398 GNUNET_free_non_null (remote_sa);
399 GNUNET_free_non_null (local_sa);
404 GNUNET_SCHEDULER_shutdown ();
405 GNUNET_free_non_null (remote_sa);
406 GNUNET_free_non_null (local_sa);
411 * Main function of gnunet-nat
413 * @param argc number of command-line arguments
414 * @param argv command line
415 * @return 0 on success, -1 on error
421 struct GNUNET_GETOPT_CommandLineOption options[] = {
423 GNUNET_GETOPT_option_string ('i',
426 gettext_noop ("which IP and port are we locally using to bind/listen to"),
429 GNUNET_GETOPT_option_string ('r',
432 gettext_noop ("which remote IP and port should be asked for connection reversal"),
435 GNUNET_GETOPT_option_string ('S',
438 gettext_noop ("name of configuration section to find additional options, such as manual host punching data"),
441 GNUNET_GETOPT_option_flag ('s',
443 gettext_noop ("enable STUN processing"),
446 GNUNET_GETOPT_option_flag ('t',
448 gettext_noop ("use TCP"),
451 GNUNET_GETOPT_option_flag ('u',
453 gettext_noop ("use UDP"),
456 GNUNET_GETOPT_option_flag ('W',
458 gettext_noop ("watch for connection reversal requests"),
460 GNUNET_GETOPT_OPTION_END
464 GNUNET_STRINGS_get_utf8_args (argc, argv,
468 GNUNET_PROGRAM_run (argc, argv,
469 "gnunet-nat [options]",
470 _("GNUnet NAT traversal autoconfigure daemon"),
477 GNUNET_free ((void*) argv);
482 /* end of gnunet-nat.c */