GNUnet 0.22.2
gnunet-nat.c
Go to the documentation of this file.
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
27#include "platform.h"
28#include "gnunet_util_lib.h"
29#include "gnunet_nat_service.h"
30
34static int global_ret;
35
40static char *section_name;
41
45static int use_udp;
46
50static int listen_reversal;
51
55static int use_tcp;
56
60static uint8_t proto;
61
65static char *local_addr;
66
70static char *remote_addr;
71
75static int do_stun;
76
80static struct GNUNET_NAT_Handle *nh;
81
86
91
92
97static void
99{
100 if (NULL != nh)
101 return;
102 if (NULL != rtask)
103 return;
105}
106
107
121static void
122address_cb (void *cls,
123 void **app_ctx,
124 int add_remove,
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
149static void
150reversal_cb (void *cls,
151 const struct sockaddr *addr,
152 socklen_t remote_addrlen)
153{
155 "Connection reversal requested by %s\n",
156 GNUNET_a2s (addr, remote_addrlen));
157}
158
159
165static void
166do_shutdown (void *cls)
167{
168 if (NULL != nh)
169 {
171 nh = NULL;
172 }
173 if (NULL != ls)
174 {
176 ls = NULL;
177 }
178 if (NULL != rtask)
179 {
181 rtask = NULL;
182 }
183}
184
185
189static void
190stun_read_task (void *cls)
191{
192 ssize_t size;
193
195 ls,
197 NULL);
199 if (size < 0)
200 {
201 GNUNET_break (0);
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
213 buf,
214 size + 1,
215 (struct sockaddr *) &sa,
216 &salen);
217 if (ret < size)
218 {
219 GNUNET_break (0);
221 global_ret = 1;
222 return;
223 }
225 (const struct sockaddr *) &sa,
226 salen,
227 buf,
228 ret);
229 }
230}
231
232
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
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 {
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 =
294 if (0 == remote_len)
295 {
297 "Invalid socket address `%s'\n",
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");
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 {
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 {
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 {
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);
343 (const struct sockaddr_in *) local_sa,
344 (const struct sockaddr_in *) remote_sa);
345 switch (ret)
346 {
347 case GNUNET_SYSERR:
349 "Connection reversal internal error\n");
350 break;
351
352 case GNUNET_NO:
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 {
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 {
385 "Failed to bind to %s: %s\n",
386 GNUNET_a2s (local_sa, local_len),
387 strerror (errno));
388 goto fail_and_shutdown;
389 }
391 ls,
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;
402 GNUNET_free (remote_sa);
403 GNUNET_free (local_sa);
404}
405
406
414int
415main (int argc, char *const argv[])
416{
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
426 'r',
427 "remote",
428 "ADDRESS",
430 "which remote IP and port should be asked for connection reversal"),
431 &remote_addr),
432
434 'S',
435 "section",
436 NULL,
438 "name of configuration section to find additional options, such as manual host punching data"),
439 &section_name),
440
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
451 "watch",
453 "watch for connection reversal requests"),
456 };
457
458 if (GNUNET_OK !=
460 argc,
461 argv,
462 "gnunet-nat [options]",
463 _ ("GNUnet NAT traversal autoconfigure daemon"),
464 options,
465 &run,
466 NULL))
467 {
468 global_ret = 1;
469 }
470 return global_ret;
471}
472
473
474/* end of gnunet-nat.c */
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_OPTION_END
Definition: 002.c:13
struct GNUNET_GETOPT_CommandLineOption options[]
Definition: 002.c:5
#define gettext_noop(String)
Definition: gettext.h:74
static int ret
Final status code.
Definition: gnunet-arm.c:93
static void reversal_cb(void *cls, const struct sockaddr *addr, socklen_t remote_addrlen)
Signature of the callback passed to GNUNET_NAT_register().
Definition: gnunet-nat.c:150
static struct GNUNET_NAT_Handle * nh
Handle to NAT operation.
Definition: gnunet-nat.c:80
static char * section_name
Name of section in configuration file to use for additional options.
Definition: gnunet-nat.c:40
static int global_ret
Value to return from main().
Definition: gnunet-nat.c:34
static int listen_reversal
Flag set to 1 if we are to listen for connection reversal requests.
Definition: gnunet-nat.c:50
static struct GNUNET_SCHEDULER_Task * rtask
Task for reading STUN packets.
Definition: gnunet-nat.c:90
static void do_shutdown(void *cls)
Task run on shutdown.
Definition: gnunet-nat.c:166
static void run(void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *c)
Main function that will be run.
Definition: gnunet-nat.c:242
static struct GNUNET_NETWORK_Handle * ls
Listen socket for STUN processing.
Definition: gnunet-nat.c:85
static int use_udp
Flag set to 1 if we use IPPROTO_UDP.
Definition: gnunet-nat.c:45
static char * remote_addr
Remote address to use for connection reversal request.
Definition: gnunet-nat.c:70
static char * local_addr
Local address to use for connection reversal request.
Definition: gnunet-nat.c:65
static int use_tcp
Flag set to 1 if we use IPPROTO_TCP.
Definition: gnunet-nat.c:55
static uint8_t proto
Protocol to use.
Definition: gnunet-nat.c:60
static void test_finished()
Test if all activities have finished, and if so, terminate.
Definition: gnunet-nat.c:98
static int do_stun
Should we actually bind to #bind_addr and receive and process STUN requests?
Definition: gnunet-nat.c:75
int main(int argc, char *const argv[])
Main function of gnunet-nat.
Definition: gnunet-nat.c:415
static void address_cb(void *cls, void **app_ctx, int add_remove, enum GNUNET_NAT_AddressClass ac, const struct sockaddr *addr, socklen_t addrlen)
Signature of the callback passed to GNUNET_NAT_register() for a function to call whenever our set of ...
Definition: gnunet-nat.c:122
static void stun_read_task(void *cls)
Task to receive incoming packets for STUN processing.
Definition: gnunet-nat.c:190
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_option_flag(char shortName, const char *name, const char *description, int *val)
Allow user to specify a flag (which internally means setting an integer to 1/GNUNET_YES/GNUNET_OK.
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_option_string(char shortName, const char *name, const char *argumentHelp, const char *description, char **str)
Allow user to specify a string.
#define GNUNET_log(kind,...)
@ GNUNET_OK
@ GNUNET_NO
@ GNUNET_SYSERR
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
const char * GNUNET_a2s(const struct sockaddr *addr, socklen_t addrlen)
Convert a "struct sockaddr*" (IPv4 or IPv6 address) to a string (for printing debug messages).
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_MESSAGE
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_free(ptr)
Wrapper around free.
int GNUNET_NAT_request_reversal(struct GNUNET_NAT_Handle *nh, const struct sockaddr_in *local_sa, const struct sockaddr_in *remote_sa)
We learned about a peer (possibly behind NAT) so run the gnunet-nat-client to send dummy ICMP respons...
Definition: nat_api.c:675
struct GNUNET_NAT_Handle * GNUNET_NAT_register(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *config_section, uint8_t proto, unsigned int num_addrs, const struct sockaddr **addrs, const socklen_t *addrlens, GNUNET_NAT_AddressCallback address_callback, GNUNET_NAT_ReversalCallback reversal_callback, void *callback_cls)
Attempt to enable port redirection and detect public IP address contacting UPnP or NAT-PMP routers on...
Definition: nat_api.c:366
void GNUNET_NAT_unregister(struct GNUNET_NAT_Handle *nh)
Stop port redirection and public IP address detection for the given handle.
Definition: nat_api.c:703
int GNUNET_NAT_stun_handle_packet(struct GNUNET_NAT_Handle *nh, const struct sockaddr *sender_addr, size_t sender_addr_len, const void *data, size_t data_size)
Handle an incoming STUN message.
Definition: nat_api.c:601
GNUNET_NAT_AddressClass
Some addresses contain sensitive information or are not suitable for global distribution.
enum GNUNET_GenericReturnValue GNUNET_NETWORK_socket_close(struct GNUNET_NETWORK_Handle *desc)
Close a socket.
Definition: network.c:508
ssize_t GNUNET_NETWORK_socket_recvfrom(const struct GNUNET_NETWORK_Handle *desc, void *buffer, size_t length, struct sockaddr *src_addr, socklen_t *addrlen)
Read data from a socket (always non-blocking).
Definition: network.c:688
struct GNUNET_NETWORK_Handle * GNUNET_NETWORK_socket_create(int domain, int type, int protocol)
Create a new socket.
Definition: network.c:833
ssize_t GNUNET_NETWORK_socket_recvfrom_amount(const struct GNUNET_NETWORK_Handle *desc)
How much data is available to be read on this descriptor?
Definition: network.c:671
enum GNUNET_GenericReturnValue GNUNET_NETWORK_socket_bind(struct GNUNET_NETWORK_Handle *desc, const struct sockaddr *address, socklen_t address_len)
Bind a socket to a particular address.
Definition: network.c:439
const struct GNUNET_OS_ProjectData * GNUNET_OS_project_data_gnunet(void)
Return default project data used by 'libgnunetutil' for GNUnet.
enum GNUNET_GenericReturnValue GNUNET_PROGRAM_run(const struct GNUNET_OS_ProjectData *pd, int argc, char *const *argv, const char *binaryName, const char *binaryHelp, const struct GNUNET_GETOPT_CommandLineOption *options, GNUNET_PROGRAM_Main task, void *task_cls)
Run a standard GNUnet command startup sequence (initialize loggers and configuration,...
Definition: program.c:407
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition: scheduler.c:567
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_read_net(struct GNUNET_TIME_Relative delay, struct GNUNET_NETWORK_Handle *rfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when the specified file descriptor is ready f...
Definition: scheduler.c:1511
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_shutdown(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run on shutdown, that is when a CTRL-C signal is received,...
Definition: scheduler.c:1339
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:980
size_t GNUNET_STRINGS_parse_socket_addr(const char *addr, uint8_t *af, struct sockaddr **sa)
Parse an address given as a string into a struct sockaddr.
Definition: strings.c:1179
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
static unsigned int size
Size of the "table".
Definition: peer.c:68
#define _(String)
GNU gettext support macro.
Definition: platform.h:178
Definition of a command line option.
Handle for active NAT registrations.
Definition: nat_api.c:72
handle to a socket
Definition: network.c:53
Entry in list of pending tasks.
Definition: scheduler.c:136