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, addrlen),
136  (int)ac);
137 }
138 
139 
149 static void
150 reversal_cb(void *cls,
151  const struct sockaddr *remote_addr,
152  socklen_t remote_addrlen)
153 {
155  "Connection reversal requested by %s\n",
156  GNUNET_a2s(remote_addr, remote_addrlen));
157 }
158 
159 
165 static void
166 do_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 
189 static void
190 stun_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 
241 static void
242 run(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",
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  {
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_non_null(remote_sa);
396  GNUNET_free_non_null(local_sa);
397  test_finished();
398  return;
399 fail_and_shutdown:
400  global_ret = 1;
402  GNUNET_free_non_null(remote_sa);
403  GNUNET_free_non_null(local_sa);
404 }
405 
406 
414 int
415 main(int argc, char *const argv[])
416 {
417  struct GNUNET_GETOPT_CommandLineOption options[] = {
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",
429  gettext_noop(
430  "which remote IP and port should be asked for connection reversal"),
431  &remote_addr),
432 
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 
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",
452  gettext_noop(
453  "watch for connection reversal requests"),
454  &listen_reversal),
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((void *)argv);
472  return global_ret;
473 }
474 
475 
476 /* 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:70
static void stun_read_task(void *cls)
Task to receive incoming packets for STUN processing.
Definition: gnunet-nat.c:190
static void do_shutdown(void *cls)
Task run on shutdown.
Definition: gnunet-nat.c:166
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:1284
int GNUNET_STRINGS_get_utf8_args(int argc, char *const *argv, int *u8argc, char *const **u8argv)
Returns utf-8 encoded arguments.
Definition: strings.c:1439
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.
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:474
#define GNUNET_NO
Definition: gnunet_common.h:78
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
#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:517
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:181
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:150
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:242
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:1351
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:76
static unsigned int size
Size of the "table".
Definition: peer.c:66
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:376
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:415
static char * remote_addr
Remote address to use for connection reversal request.
Definition: gnunet-nat.c:70
configuration data
Definition: configuration.c:83
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:131
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:367
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:715
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:1467
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:742
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:548
#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:900
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:956