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
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 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 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
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
28 #include "gnunet_util_lib.h"
29 #include "gnunet_nat_service.h"
32 * Value to return from #main().
34 static int global_ret;
37 * Name of section in configuration file to use for
40 static char *section_name;
43 * Flag set to 1 if we use IPPROTO_UDP.
48 * Flag set to 1 if we are to listen for connection reversal requests.
50 static int listen_reversal;
53 * Flag set to 1 if we use IPPROTO_TCP.
63 * Local address to use for connection reversal request.
65 static char *local_addr;
68 * Remote address to use for connection reversal request.
70 static char *remote_addr;
73 * Should we actually bind to #bind_addr and receive and process STUN requests?
75 static unsigned int do_stun;
78 * Handle to NAT operation.
80 static struct GNUNET_NAT_Handle *nh;
83 * Listen socket for STUN processing.
85 static struct GNUNET_NETWORK_Handle *ls;
88 * Task for reading STUN packets.
90 static struct GNUNET_SCHEDULER_Task *rtask;
94 * Test if all activities have finished, and if so,
104 GNUNET_SCHEDULER_shutdown ();
109 * Signature of the callback passed to #GNUNET_NAT_register() for
110 * a function to call whenever our set of 'valid' addresses changes.
112 * @param cls closure, NULL
113 * @param add_remove #GNUNET_YES to add a new public IP address,
114 * #GNUNET_NO to remove a previous (now invalid) one
115 * @param ac address class the address belongs to
116 * @param addr either the previous or the new public IP address
117 * @param addrlen actual length of the @a addr
120 address_cb (void *cls,
122 enum GNUNET_NAT_AddressClass ac,
123 const struct sockaddr *addr,
126 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
128 add_remove ? "+" : "-",
136 * Signature of the callback passed to #GNUNET_NAT_register().
137 * for a function to call whenever someone asks us to do connection
140 * @param cls closure, NULL
141 * @param remote_addr public IP address of the other peer
142 * @param remote_addrlen actual length of the @a remote_addr
145 reversal_cb (void *cls,
146 const struct sockaddr *remote_addr,
147 socklen_t remote_addrlen)
149 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
150 "Connection reversal requested by %s\n",
151 GNUNET_a2s (remote_addr,
157 * Task run on shutdown.
162 do_shutdown (void *cls)
166 GNUNET_NAT_unregister (nh);
171 GNUNET_NETWORK_socket_close (ls);
176 GNUNET_SCHEDULER_cancel (rtask);
183 * Task to receive incoming packets for STUN processing.
186 stun_read_task (void *cls)
190 rtask = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
194 size = GNUNET_NETWORK_socket_recvfrom_amount (ls);
198 GNUNET_SCHEDULER_shutdown ();
204 struct sockaddr_storage sa;
205 socklen_t salen = sizeof (sa);
208 ret = GNUNET_NETWORK_socket_recvfrom (ls,
211 (struct sockaddr *) &sa,
216 GNUNET_SCHEDULER_shutdown ();
220 (void) GNUNET_NAT_stun_handle_packet (nh,
221 (const struct sockaddr *) &sa,
230 * Main function that will be run.
233 * @param args remaining command-line arguments
234 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
235 * @param c configuration
241 const struct GNUNET_CONFIGURATION_Handle *c)
244 struct sockaddr *local_sa;
245 struct sockaddr *remote_sa;
249 if (use_tcp && use_udp)
251 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
252 "Cannot use TCP and UDP\n");
262 GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
267 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
268 "Must specify either TCP or UDP\n");
272 if (NULL != local_addr)
274 local_len = (socklen_t) GNUNET_STRINGS_parse_socket_addr (local_addr,
279 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
280 "Invalid socket address `%s'\n",
289 if (NULL != remote_addr)
291 remote_len = GNUNET_STRINGS_parse_socket_addr (remote_addr,
296 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
297 "Invalid socket address `%s'\n",
304 if (NULL != local_addr)
306 if (NULL == section_name)
307 section_name = GNUNET_strdup ("undefined");
308 nh = GNUNET_NAT_register (c,
312 (const struct sockaddr **) &local_sa,
315 (listen_reversal) ? &reversal_cb : NULL,
318 else if (listen_reversal)
320 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
321 "Use of `-W` only effective in combination with `-i`\n");
323 GNUNET_SCHEDULER_shutdown ();
327 if (NULL != remote_addr)
332 (sizeof (struct sockaddr_in) != local_len) )
334 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
335 "Require IPv4 local address to initiate connection reversal\n");
337 GNUNET_SCHEDULER_shutdown ();
340 if (sizeof (struct sockaddr_in) != remote_len)
342 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
343 "Require IPv4 reversal target address\n");
345 GNUNET_SCHEDULER_shutdown ();
348 GNUNET_assert (AF_INET == local_sa->sa_family);
349 GNUNET_assert (AF_INET == remote_sa->sa_family);
350 ret = GNUNET_NAT_request_reversal (nh,
351 (const struct sockaddr_in *) local_sa,
352 (const struct sockaddr_in *) remote_sa);
356 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
357 "Connection reversal internal error\n");
360 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
361 "Connection reversal unavailable\n");
364 /* operation in progress */
371 if (NULL == local_addr)
373 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
374 "Require local address to support STUN requests\n");
376 GNUNET_SCHEDULER_shutdown ();
379 if (IPPROTO_UDP != proto)
381 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
382 "STUN only supported over UDP\n");
384 GNUNET_SCHEDULER_shutdown ();
387 ls = GNUNET_NETWORK_socket_create (af,
391 GNUNET_NETWORK_socket_bind (ls,
395 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
396 "Failed to bind to %s: %s\n",
397 GNUNET_a2s (local_sa,
401 GNUNET_SCHEDULER_shutdown ();
404 rtask = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
415 * Main function of gnunet-nat
417 * @param argc number of command-line arguments
418 * @param argv command line
419 * @return 0 on success, -1 on error
425 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
426 {'i', "in", "ADDRESS",
427 gettext_noop ("which IP and port are we locally using to bind/listen to"),
428 GNUNET_YES, &GNUNET_GETOPT_set_string, &local_addr },
429 {'r', "remote", "ADDRESS",
430 gettext_noop ("which remote IP and port should be asked for connection reversal"),
431 GNUNET_YES, &GNUNET_GETOPT_set_string, &remote_addr },
432 {'S', "section", NULL,
433 gettext_noop ("name of configuration section to find additional options, such as manual host punching data"),
434 GNUNET_YES, &GNUNET_GETOPT_set_string, §ion_name },
436 gettext_noop ("enable STUN processing"),
437 GNUNET_NO, &GNUNET_GETOPT_set_one, &do_stun },
439 gettext_noop ("use TCP"),
440 GNUNET_NO, &GNUNET_GETOPT_set_one, &use_tcp },
442 gettext_noop ("use UDP"),
443 GNUNET_NO, &GNUNET_GETOPT_set_one, &use_udp },
445 gettext_noop ("watch for connection reversal requests"),
446 GNUNET_NO, &GNUNET_GETOPT_set_one, &listen_reversal },
447 GNUNET_GETOPT_OPTION_END
451 GNUNET_STRINGS_get_utf8_args (argc, argv,
455 GNUNET_PROGRAM_run (argc, argv,
456 "gnunet-nat [options]",
457 _("GNUnet NAT traversal autoconfigure daemon"),
464 GNUNET_free ((void*) argv);
469 /* end of gnunet-nat.c */