GNUnet  0.10.x
gnunet-nat-auto_legacy.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet.
3  Copyright (C) 2011, 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 
26 #include "platform.h"
27 #include "gnunet_util_lib.h"
28 #include "gnunet_nat_lib.h"
29 #include "nat.h"
30 
31 #define LOG(kind,...) GNUNET_log_from (kind, "nat", __VA_ARGS__)
32 
33 #define NAT_SERVER_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
34 
39 {
43  struct NatActivity *next;
44 
48  struct NatActivity *prev;
49 
54 
58  struct GNUNET_NAT_Test *h;
59 
64 };
65 
66 
71 {
76 
81 
86 
90  struct GNUNET_NAT_Test *h;
91 
92 };
93 
94 
99 {
100 
105 
110 
114  void *report_cls;
115 
120 
125 
130 
135 
140 
145 
150 
155 
159  int is_tcp;
160 
164  uint16_t data;
165 
169  uint16_t adv_port;
170 
175 };
176 
177 
186 static void
187 reversal_cb (void *cls,
188  const struct sockaddr *addr,
189  socklen_t addrlen)
190 {
191  struct GNUNET_NAT_Test *h = cls;
192  const struct sockaddr_in *sa;
193 
194  if (sizeof (struct sockaddr_in) != addrlen)
195  return;
196  sa = (const struct sockaddr_in *) addr;
197  if (h->data != sa->sin_port)
198  {
200  "Received connection reversal request for wrong port\n");
201  return; /* wrong port */
202  }
203  /* report success */
204  h->report (h->report_cls,
206 }
207 
208 
215 static void
216 do_udp_read (void *cls)
217 {
218  struct GNUNET_NAT_Test *tst = cls;
219  uint16_t data;
220  const struct GNUNET_SCHEDULER_TaskContext *tc;
221 
223  tst->ltask =
225  tst->lsock,
226  &do_udp_read,
227  tst);
228  if ((NULL != tc->write_ready) &&
230  tst->lsock)) &&
231  (sizeof (data) ==
233  &data,
234  sizeof (data))))
235  {
236  if (data == tst->data)
237  tst->report (tst->report_cls,
239  else
241  "Received data mismatches expected value\n");
242  }
243  else
245  "Failed to receive data from inbound connection\n");
246 }
247 
248 
255 static void
256 do_read (void *cls)
257 {
258  struct NatActivity *na = cls;
259  struct GNUNET_NAT_Test *tst;
260  uint16_t data;
261  const struct GNUNET_SCHEDULER_TaskContext *tc;
262 
264  na->rtask = NULL;
265  tst = na->h;
267  tst->na_tail,
268  na);
269  if ((NULL != tc->write_ready) &&
271  na->sock)) &&
272  (sizeof (data) ==
274  &data,
275  sizeof (data))))
276  {
277  if (data == tst->data)
278  tst->report (tst->report_cls,
280  else
282  "Received data does not match expected value\n");
283  }
284  else
286  "Failed to receive data from inbound connection\n");
288  GNUNET_free (na);
289 }
290 
291 
298 static void
299 do_accept (void *cls)
300 {
301  struct GNUNET_NAT_Test *tst = cls;
302  struct GNUNET_NETWORK_Handle *s;
303  struct NatActivity *wl;
304 
306  tst->lsock,
307  &do_accept,
308  tst);
310  NULL,
311  NULL);
312  if (NULL == s)
313  {
315  "accept");
316  return; /* odd error */
317  }
319  "Got an inbound connection, waiting for data\n");
320  wl = GNUNET_new (struct NatActivity);
321  wl->sock = s;
322  wl->h = tst;
323  wl->rtask =
325  wl->sock,
326  &do_read,
327  wl);
329  tst->na_tail,
330  wl);
331 }
332 
333 
341 static void
342 mq_error_handler (void *cls,
343  enum GNUNET_MQ_Error error)
344 {
345  struct ClientActivity *ca = cls;
346  struct GNUNET_NAT_Test *tst = ca->h;
347 
349  tst->ca_tail,
350  ca);
351  GNUNET_MQ_destroy (ca->mq);
352  GNUNET_free (ca);
353 }
354 
355 
365 static void
366 addr_cb (void *cls,
367  int add_remove,
368  const struct sockaddr *addr,
369  socklen_t addrlen)
370 {
371  struct GNUNET_NAT_Test *h = cls;
372  struct ClientActivity *ca;
373  struct GNUNET_MQ_Envelope *env;
374  struct GNUNET_NAT_TestMessage *msg;
375  const struct sockaddr_in *sa;
376 
377  if (GNUNET_YES != add_remove)
378  return;
379  if (addrlen != sizeof (struct sockaddr_in))
380  {
382  "NAT test ignores IPv6 address `%s' returned from NAT library\n",
383  GNUNET_a2s (addr,
384  addrlen));
385  return; /* ignore IPv6 here */
386  }
388  "Asking gnunet-nat-server to connect to `%s'\n",
389  GNUNET_a2s (addr,
390  addrlen));
391 
392  ca = GNUNET_new (struct ClientActivity);
393  ca->h = h;
394  ca->mq = GNUNET_CLIENT_connect (h->cfg,
395  "gnunet-nat-server",
396  NULL,
398  ca);
399  if (NULL == ca->mq)
400  {
401  GNUNET_free (ca);
403  _("Failed to connect to `gnunet-nat-server'\n"));
404  return;
405  }
407  h->ca_tail,
408  ca);
409  sa = (const struct sockaddr_in *) addr;
410  env = GNUNET_MQ_msg (msg,
412  msg->dst_ipv4 = sa->sin_addr.s_addr;
413  msg->dport = sa->sin_port;
414  msg->data = h->data;
415  msg->is_tcp = htonl ((uint32_t) h->is_tcp);
416  GNUNET_MQ_send (ca->mq,
417  env);
418 }
419 
420 
429 static void
430 do_timeout (void *cls)
431 {
432  struct GNUNET_NAT_Test *nh = cls;
433 
434  nh->ttask = NULL;
435  nh->report (nh->report_cls,
438  : nh->status);
439 }
440 
441 
457 struct GNUNET_NAT_Test *
459  int is_tcp,
460  uint16_t bnd_port,
461  uint16_t adv_port,
464  void *report_cls)
465 {
466  struct GNUNET_NAT_Test *nh;
467  struct sockaddr_in sa;
468  const struct sockaddr *addrs[] = {
469  (const struct sockaddr *) &sa
470  };
471  const socklen_t addrlens[] = {
472  sizeof (sa)
473  };
474 
475  memset (&sa, 0, sizeof (sa));
476  sa.sin_family = AF_INET;
477  sa.sin_port = htons (bnd_port);
478 #if HAVE_SOCKADDR_IN_SIN_LEN
479  sa.sin_len = sizeof (sa);
480 #endif
481 
482  nh = GNUNET_new (struct GNUNET_NAT_Test);
483  nh->cfg = cfg;
484  nh->is_tcp = is_tcp;
485  nh->data = bnd_port;
486  nh->adv_port = adv_port;
487  nh->report = report;
488  nh->report_cls = report_cls;
490  if (0 == bnd_port)
491  {
492  nh->nat
493  = GNUNET_NAT_register (cfg,
494  is_tcp,
495  0,
496  0,
497  NULL,
498  NULL,
499  &addr_cb,
500  &reversal_cb,
501  nh,
502  NULL);
503  }
504  else
505  {
506  nh->lsock =
508  (is_tcp ==
509  GNUNET_YES) ? SOCK_STREAM : SOCK_DGRAM,
510  0);
511  if ((nh->lsock == NULL) ||
512  (GNUNET_OK !=
514  (const struct sockaddr *) &sa,
515  sizeof (sa))))
516  {
518  _("Failed to create listen socket bound to `%s' for NAT test: %s\n"),
519  GNUNET_a2s ((const struct sockaddr *) &sa,
520  sizeof (sa)),
521  STRERROR (errno));
522  if (NULL != nh->lsock)
523  {
525  nh->lsock = NULL;
526  }
529  nh);
530  return nh;
531  }
532  if (GNUNET_YES == is_tcp)
533  {
536  5));
537  nh->ltask =
539  nh->lsock,
540  &do_accept,
541  nh);
542  }
543  else
544  {
545  nh->ltask =
547  nh->lsock,
548  &do_udp_read,
549  nh);
550  }
552  "NAT test listens on port %u (%s)\n",
553  bnd_port,
554  (GNUNET_YES == is_tcp) ? "tcp" : "udp");
555  nh->nat = GNUNET_NAT_register (cfg,
556  is_tcp,
557  adv_port,
558  1,
559  addrs,
560  addrlens,
561  &addr_cb,
562  NULL,
563  nh,
564  NULL);
565  if (NULL == nh->nat)
566  {
568  _("NAT test failed to start NAT library\n"));
569  if (NULL != nh->ltask)
570  {
572  nh->ltask = NULL;
573  }
574  if (NULL != nh->lsock)
575  {
577  nh->lsock = NULL;
578  }
581  nh);
582  return nh;
583  }
584  }
585  nh->ttask = GNUNET_SCHEDULER_add_delayed (timeout,
586  &do_timeout,
587  nh);
588  return nh;
589 }
590 
591 
597 void
599 {
600  struct NatActivity *pos;
601  struct ClientActivity *cpos;
602 
604  "Stopping NAT test\n");
605  while (NULL != (cpos = tst->ca_head))
606  {
608  tst->ca_tail,
609  cpos);
610  GNUNET_MQ_destroy (cpos->mq);
611  GNUNET_free (cpos);
612  }
613  while (NULL != (pos = tst->na_head))
614  {
616  tst->na_tail,
617  pos);
620  GNUNET_free (pos);
621  }
622  if (NULL != tst->ttask)
623  {
625  tst->ttask = NULL;
626  }
627  if (NULL != tst->ltask)
628  {
630  tst->ltask = NULL;
631  }
632  if (NULL != tst->lsock)
633  {
635  tst->lsock = NULL;
636  }
637  if (NULL != tst->nat)
638  {
639  GNUNET_NAT_unregister (tst->nat);
640  tst->nat = NULL;
641  }
642  GNUNET_free (tst);
643 }
644 
645 /* end of nat_test.c */
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
int GNUNET_NETWORK_socket_listen(const struct GNUNET_NETWORK_Handle *desc, int backlog)
Listen on a socket.
Definition: network.c:796
NAT test failed to initiate.
const struct GNUNET_SCHEDULER_TaskContext * GNUNET_SCHEDULER_get_task_context(void)
Obtain the reasoning why the current task was started.
Definition: scheduler.c:746
Handle for active NAT registrations.
Definition: nat_api.c:72
struct ClientActivity * prev
This is a doubly-linked list.
const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration used.
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
uint32_t dst_ipv4
IPv4 target IP address.
Definition: nat.h:49
uint16_t data
Data that should be transmitted or source-port.
struct GNUNET_MQ_Handle * GNUNET_CLIENT_connect(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *service_name, const struct GNUNET_MQ_MessageHandler *handlers, GNUNET_MQ_ErrorHandler error_handler, void *error_handler_cls)
Create a message queue to connect to a GNUnet service.
Definition: client.c:901
Context information passed to each scheduler task.
GNUNET_MQ_Error
Error codes for the queue.
ssize_t GNUNET_NETWORK_socket_recv(const struct GNUNET_NETWORK_Handle *desc, void *buffer, size_t length)
Read data from a connected socket (always non-blocking).
Definition: network.c:894
struct GNUNET_MQ_Handle * mq
Socket of the incoming connection.
struct GNUNET_NETWORK_Handle * sock
Socket of the incoming connection.
int32_t is_tcp
GNUNET_YES for TCP, GNUNET_NO for UDP.
Definition: nat.h:64
#define STRERROR(i)
Definition: plibc.h:676
static struct GNUNET_SCHEDULER_TaskContext tc
Task context of the current task.
Definition: scheduler.c:417
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
void * report_cls
Closure for report.
const struct GNUNET_NETWORK_FDSet * write_ready
Set of file descriptors ready for writing; note that additional bits may be set that were not in the ...
#define GNUNET_MQ_msg(mvar, type)
Allocate a GNUNET_MQ_Envelope.
Definition: gnunet_mq_lib.h:67
#define GNUNET_MESSAGE_TYPE_NAT_TEST
Message to ask NAT server to perform traversal test.
static void do_read(void *cls)
Activity on our incoming socket.
void(* GNUNET_NAT_TestCallback)(void *cls, enum GNUNET_NAT_StatusCode result)
Function called to report success or failure for NAT configuration test.
struct NatActivity * na_tail
Tail of list of nat activities.
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
const struct GNUNET_NETWORK_FDSet * read_ready
Set of file descriptors ready for reading; note that additional bits may be set that were not in the ...
#define GNUNET_new(type)
Allocate a struct or union of the given type.
struct ClientActivity * next
This is a doubly-linked list.
GNUNET_NAT_TestCallback report
Function to call with success report.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
struct GNUNET_NAT_Handle * nat
Handle to NAT traversal in use.
struct GNUNET_SCHEDULER_Task * rtask
Task reading from the incoming connection.
#define _(String)
GNU gettext support macro.
Definition: platform.h:208
uint16_t dport
Port to use, 0 to send dummy ICMP response.
Definition: nat.h:54
Entry we keep for each incoming connection.
struct GNUNET_NAT_Test * GNUNET_NAT_test_start(const struct GNUNET_CONFIGURATION_Handle *cfg, int is_tcp, uint16_t bnd_port, uint16_t adv_port, struct GNUNET_TIME_Relative timeout, GNUNET_NAT_TestCallback report, void *report_cls)
Start testing if NAT traversal works using the given configuration (IPv4-only).
struct GNUNET_NETWORK_Handle * GNUNET_NETWORK_socket_accept(const struct GNUNET_NETWORK_Handle *desc, struct sockaddr *address, socklen_t *address_len)
Accept a new connection on a socket.
Definition: network.c:468
#define GNUNET_log_strerror(level, cmd)
Log an error message at log-level &#39;level&#39; that indicates a failure of the command &#39;cmd&#39; with the mess...
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition: scheduler.c:1246
static struct GNUNET_TIME_Relative timeout
User defined timestamp for completing operations.
Definition: gnunet-arm.c:114
uint16_t adv_port
Advertised port to the other peer.
struct ClientActivity * ca_tail
Tail of list of client activities.
struct ClientActivity * ca_head
Head of list of client activities.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run as soon as possible.
Definition: scheduler.c:1273
GNUNET_NAT_StatusCode
Error Types for the NAT subsystem (which can then later be converted/resolved to a string) ...
#define LOG(kind,...)
uint16_t status
See PRISM_STATUS_*-constants.
struct NatActivity * na_head
Head of list of nat activities.
#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 void do_udp_read(void *cls)
Activity on our incoming socket.
static struct GNUNET_NAT_Handle * nh
Handle to NAT operation.
Definition: gnunet-nat.c:80
static void mq_error_handler(void *cls, enum GNUNET_MQ_Error error)
We got disconnected from the NAT server.
Failure in network subsystem, check permissions.
static struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
Definition: gnunet-arm.c:104
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
static void do_accept(void *cls)
Activity on our listen socket.
void GNUNET_NAT_test_stop(struct GNUNET_NAT_Test *tst)
Stop an active NAT test.
static void addr_cb(void *cls, int add_remove, const struct sockaddr *addr, socklen_t addrlen)
Address-callback, used to send message to gnunet-nat-server.
struct GNUNET_SCHEDULER_Task * ttask
Task identifier for the timeout (if any)
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
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
struct GNUNET_NAT_Test * h
Handle to overall NAT test.
Handle to a NAT test.
Request to test NAT traversal, sent to the gnunet-nat-server (not the service!).
Definition: nat.h:39
Handle to a message queue.
Definition: mq.c:85
static void do_timeout(void *cls)
Timeout task for a nat test.
static void reversal_cb(void *cls, const struct sockaddr *addr, socklen_t addrlen)
Function called from GNUNET_NAT_register whenever someone asks us to do connection reversal...
struct GNUNET_SCHEDULER_Task * ltask
Identity of task for the listen socket (if any)
Messages for interaction with gnunet-nat-server and gnunet-nat-service.
configuration data
Definition: configuration.c:85
#define GNUNET_log(kind,...)
Entry in list of pending tasks.
Definition: scheduler.c:134
struct GNUNET_NETWORK_Handle * lsock
Handle to listen socket, or NULL.
handle to a socket
Definition: network.c:46
struct NatActivity * prev
This is a doubly-linked list.
struct GNUNET_NAT_Test * h
Handle of the master context.
enum GNUNET_NAT_StatusCode status
Status code to be reported to the timeout/status call.
void GNUNET_MQ_destroy(struct GNUNET_MQ_Handle *mq)
Destroy the message queue.
Definition: mq.c:824
#define GNUNET_YES
Definition: gnunet_common.h:80
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
void GNUNET_MQ_send(struct GNUNET_MQ_Handle *mq, struct GNUNET_MQ_Envelope *ev)
Send a message with the given message queue.
Definition: mq.c:353
Entry we keep for each connection to the gnunet-nat-service.
struct NatActivity * next
This is a doubly-linked list.
int is_tcp
GNUNET_YES if we&#39;re testing TCP
int GNUNET_NETWORK_fdset_isset(const struct GNUNET_NETWORK_FDSet *fds, const struct GNUNET_NETWORK_Handle *desc)
Check whether a socket is part of the fd set.
Definition: network.c:1181
uint32_t data
The data value.
int GNUNET_NETWORK_socket_close(struct GNUNET_NETWORK_Handle *desc)
Close a socket.
Definition: network.c:604
#define GNUNET_free(ptr)
Wrapper around free.
Time for relative time used by GNUnet, in microseconds.
uint16_t data
Data to send OR advertised-port (in NBO) to use for dummy ICMP.
Definition: nat.h:59
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