GNUnet  0.10.x
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 
34 static int global_ret;
35 
40 static char *section_name;
41 
45 static int use_udp;
46 
50 static int listen_reversal;
51 
55 static int use_tcp;
56 
60 static uint8_t proto;
61 
65 static char *local_addr;
66 
70 static char *remote_addr;
71 
75 static int do_stun;
76 
80 static struct GNUNET_NAT_Handle *nh;
81 
85 static struct GNUNET_NETWORK_Handle *ls;
86 
91 
92 
97 static void
99 {
100  if (NULL != nh)
101  return;
102  if (NULL != rtask)
103  return;
105 }
106 
107 
121 static void
122 address_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,
136  addrlen),
137  (int) ac);
138 }
139 
140 
150 static void
151 reversal_cb (void *cls,
152  const struct sockaddr *remote_addr,
153  socklen_t remote_addrlen)
154 {
156  "Connection reversal requested by %s\n",
157  GNUNET_a2s (remote_addr,
158  remote_addrlen));
159 }
160 
161 
167 static void
168 do_shutdown (void *cls)
169 {
170  if (NULL != nh)
171  {
173  nh = NULL;
174  }
175  if (NULL != ls)
176  {
178  ls = NULL;
179  }
180  if (NULL != rtask)
181  {
182  GNUNET_SCHEDULER_cancel (rtask);
183  rtask = NULL;
184  }
185 }
186 
187 
191 static void
192 stun_read_task (void *cls)
193 {
194  ssize_t size;
195 
197  ls,
199  NULL);
201  if (size > 0)
202  {
203  GNUNET_break (0);
205  global_ret = 1;
206  return;
207  }
208  {
209  char buf[size + 1];
210  struct sockaddr_storage sa;
211  socklen_t salen = sizeof (sa);
212  ssize_t ret;
213 
215  buf,
216  size + 1,
217  (struct sockaddr *) &sa,
218  &salen);
219  if (ret != size)
220  {
221  GNUNET_break (0);
223  global_ret = 1;
224  return;
225  }
227  (const struct sockaddr *) &sa,
228  salen,
229  buf,
230  ret);
231  }
232 }
233 
234 
243 static void
244 run (void *cls,
245  char *const *args,
246  const char *cfgfile,
247  const struct GNUNET_CONFIGURATION_Handle *c)
248 {
249  uint8_t af;
250  struct sockaddr *local_sa;
251  struct sockaddr *remote_sa;
252  socklen_t local_len;
253  size_t remote_len;
254 
255  if (use_tcp && use_udp)
256  {
258  "Cannot use TCP and UDP\n");
259  global_ret = 1;
260  return;
261  }
262  proto = 0;
263  if (use_tcp)
264  proto = IPPROTO_TCP;
265  if (use_udp)
266  proto = IPPROTO_UDP;
267 
269  NULL);
270 
271  if (0 == proto)
272  {
274  "Must specify either TCP or UDP\n");
275  global_ret = 1;
276  return;
277  }
278  local_len = 0;
279  local_sa = NULL;
280  remote_len = 0;
281  remote_sa = NULL;
282  if (NULL != local_addr)
283  {
284  local_len = (socklen_t) GNUNET_STRINGS_parse_socket_addr (local_addr,
285  &af,
286  &local_sa);
287  if (0 == local_len)
288  {
290  "Invalid socket address `%s'\n",
291  local_addr);
292  goto fail_and_shutdown;
293  }
294  }
295 
296  if (NULL != remote_addr)
297  {
299  &af,
300  &remote_sa);
301  if (0 == remote_len)
302  {
304  "Invalid socket address `%s'\n",
305  remote_addr);
306  goto fail_and_shutdown;
307  }
308  }
309 
310  if (NULL != local_addr)
311  {
312  if (NULL == section_name)
313  section_name = GNUNET_strdup ("undefined");
314  nh = GNUNET_NAT_register (c,
315  section_name,
316  proto,
317  1,
318  (const struct sockaddr **) &local_sa,
319  &local_len,
320  &address_cb,
321  (listen_reversal) ? &reversal_cb : NULL,
322  NULL);
323  }
324  else if (listen_reversal)
325  {
327  "Use of `-W` only effective in combination with `-i`\n");
328  goto fail_and_shutdown;
329  }
330 
331  if (NULL != remote_addr)
332  {
333  int ret;
334 
335  if ( (NULL == nh) ||
336  (sizeof (struct sockaddr_in) != local_len) )
337  {
339  "Require IPv4 local address to initiate connection reversal\n");
340  goto fail_and_shutdown;
341  }
342  if (sizeof (struct sockaddr_in) != remote_len)
343  {
345  "Require IPv4 reversal target address\n");
346  goto fail_and_shutdown;
347  }
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);
353  switch (ret)
354  {
355  case GNUNET_SYSERR:
357  "Connection reversal internal error\n");
358  break;
359  case GNUNET_NO:
361  "Connection reversal unavailable\n");
362  break;
363  case GNUNET_OK:
364  /* operation in progress */
365  break;
366  }
367  }
368 
369  if (do_stun)
370  {
371  if (NULL == local_addr)
372  {
374  "Require local address to support STUN requests\n");
375  goto fail_and_shutdown;
376  }
377  if (IPPROTO_UDP != proto)
378  {
380  "STUN only supported over UDP\n");
381  goto fail_and_shutdown;
382  }
384  SOCK_DGRAM,
385  IPPROTO_UDP);
386  if (NULL == ls)
387  {
389  "Failed to create socket\n");
390  goto fail_and_shutdown;
391  }
392  if (GNUNET_OK !=
394  local_sa,
395  local_len))
396  {
398  "Failed to bind to %s: %s\n",
399  GNUNET_a2s (local_sa,
400  local_len),
401  STRERROR (errno));
402  goto fail_and_shutdown;
403  }
405  ls,
407  NULL);
408  }
409  GNUNET_free_non_null (remote_sa);
410  GNUNET_free_non_null (local_sa);
411  test_finished ();
412  return;
413  fail_and_shutdown:
414  global_ret = 1;
416  GNUNET_free_non_null (remote_sa);
417  GNUNET_free_non_null (local_sa);
418 }
419 
420 
428 int
429 main (int argc,
430  char *const argv[])
431 {
432  struct GNUNET_GETOPT_CommandLineOption options[] = {
433 
435  "in",
436  "ADDRESS",
437  gettext_noop ("which IP and port are we locally using to bind/listen to"),
438  &local_addr),
439 
441  "remote",
442  "ADDRESS",
443  gettext_noop ("which remote IP and port should be asked for connection reversal"),
444  &remote_addr),
445 
447  "section",
448  NULL,
449  gettext_noop ("name of configuration section to find additional options, such as manual host punching data"),
450  &section_name),
451 
453  "stun",
454  gettext_noop ("enable STUN processing"),
455  &do_stun),
456 
458  "tcp",
459  gettext_noop ("use TCP"),
460  &use_tcp),
461 
463  "udp",
464  gettext_noop ("use UDP"),
465  &use_udp),
466 
468  "watch",
469  gettext_noop ("watch for connection reversal requests"),
470  &listen_reversal),
472  };
473 
474  if (GNUNET_OK !=
475  GNUNET_STRINGS_get_utf8_args (argc, argv,
476  &argc, &argv))
477  return 2;
478  if (GNUNET_OK !=
479  GNUNET_PROGRAM_run (argc, argv,
480  "gnunet-nat [options]",
481  _("GNUnet NAT traversal autoconfigure daemon"),
482  options,
483  &run,
484  NULL))
485  {
486  global_ret = 1;
487  }
488  GNUNET_free ((void*) argv);
489  return global_ret;
490 }
491 
492 
493 /* end of gnunet-nat.c */
static int listen_reversal
Flag set to 1 if we are to listen for connection reversal requests.
Definition: gnunet-nat.c:50
Handle for active NAT registrations.
Definition: nat_api.c:72
static void stun_read_task(void *cls)
Task to receive incoming packets for STUN processing.
Definition: gnunet-nat.c:192
static void do_shutdown(void *cls)
Task run on shutdown.
Definition: gnunet-nat.c:168
GNUNET_NAT_AddressClass
Some addresses contain sensitive information or are not suitable for global distribution.
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:655
static int use_udp
Flag set to 1 if we use IPPROTO_UDP.
Definition: gnunet-nat.c:45
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, or when GNUNET_SCHEDULER_shutdown() is being invoked.
Definition: scheduler.c:1293
int GNUNET_STRINGS_get_utf8_args(int argc, char *const *argv, int *u8argc, char *const **u8argv)
Returns utf-8 encoded arguments.
Definition: strings.c:1521
static uint8_t proto
Protocol to use.
Definition: gnunet-nat.c:60
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define STRERROR(i)
Definition: plibc.h:676
int 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:522
#define GNUNET_NO
Definition: gnunet_common.h:81
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
#define GNUNET_free_non_null(ptr)
Free the memory pointed to by ptr if ptr is not NULL.
Definition of a command line option.
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition: scheduler.c:524
static int ret
Final status code.
Definition: gnunet-arm.c:89
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
static int global_ret
Value to return from main().
Definition: gnunet-nat.c:34
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_OPTION_END
Definition: 002.c:13
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 _(String)
GNU gettext support macro.
Definition: platform.h:208
static void reversal_cb(void *cls, const struct sockaddr *remote_addr, socklen_t remote_addrlen)
Signature of the callback passed to GNUNET_NAT_register().
Definition: gnunet-nat.c:151
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 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:244
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:581
static void test_finished()
Test if all activities have finished, and if so, terminate.
Definition: gnunet-nat.c:98
static char buf[2048]
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
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)...
static char * local_addr
Local address to use for connection reversal request.
Definition: gnunet-nat.c:65
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:1433
static struct GNUNET_NAT_Handle * nh
Handle to NAT operation.
Definition: gnunet-nat.c:80
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:690
#define GNUNET_SYSERR
Definition: gnunet_common.h:79
static unsigned int size
Size of the "table".
Definition: peer.c:67
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:378
static struct GNUNET_MQ_Envelope * ac
Handle to current GNUNET_PEERINFO_add_peer() operation.
static struct GNUNET_NETWORK_Handle * ls
Listen socket for STUN processing.
Definition: gnunet-nat.c:85
static int use_tcp
Flag set to 1 if we use IPPROTO_TCP.
Definition: gnunet-nat.c:55
int main(int argc, char *const argv[])
Main function of gnunet-nat.
Definition: gnunet-nat.c:429
static char * remote_addr
Remote address to use for connection reversal request.
Definition: gnunet-nat.c:70
configuration data
Definition: configuration.c:85
static char * section_name
Name of section in configuration file to use for additional options.
Definition: gnunet-nat.c:40
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.
#define GNUNET_log(kind,...)
Entry in list of pending tasks.
Definition: scheduler.c:134
handle to a socket
Definition: network.c:46
int GNUNET_PROGRAM_run(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, parse options).
Definition: program.c:361
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:818
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:1478
static struct GNUNET_SCHEDULER_Task * rtask
Task for reading STUN packets.
Definition: gnunet-nat.c:90
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:856
static int do_stun
Should we actually bind to #bind_addr and receive and process STUN requests?
Definition: gnunet-nat.c:75
int GNUNET_NETWORK_socket_close(struct GNUNET_NETWORK_Handle *desc)
Close a socket.
Definition: network.c:604
#define GNUNET_free(ptr)
Wrapper around free.
#define gettext_noop(String)
Definition: gettext.h:69
struct GNUNET_NETWORK_Handle * GNUNET_NETWORK_socket_create(int domain, int type, int protocol)
Create a new socket.
Definition: network.c:1037
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:965