GNUnet  0.19.4
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 \
34  GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
35 
40 {
44  struct NatActivity *next;
45 
49  struct NatActivity *prev;
50 
55 
59  struct GNUNET_NAT_Test *h;
60 
65 };
66 
67 
72 {
77 
82 
87 
91  struct GNUNET_NAT_Test *h;
92 };
93 
94 
99 {
104 
109 
113  void *report_cls;
114 
119 
124 
129 
134 
139 
144 
149 
154 
158  int is_tcp;
159 
163  uint16_t data;
164 
168  uint16_t adv_port;
169 
174 };
175 
176 
185 static void
186 reversal_cb (void *cls, const struct sockaddr *addr, socklen_t addrlen)
187 {
188  struct GNUNET_NAT_Test *h = cls;
189  const struct sockaddr_in *sa;
190 
191  if (sizeof(struct sockaddr_in) != addrlen)
192  return;
193  sa = (const struct sockaddr_in *) addr;
194  if (h->data != sa->sin_port)
195  {
197  "Received connection reversal request for wrong port\n");
198  return; /* wrong port */
199  }
200  /* report success */
201  h->report (h->report_cls, GNUNET_NAT_ERROR_SUCCESS);
202 }
203 
204 
211 static void
212 do_udp_read (void *cls)
213 {
214  struct GNUNET_NAT_Test *tst = cls;
215  uint16_t data;
216  const struct GNUNET_SCHEDULER_TaskContext *tc;
217 
220  tst->lsock,
221  &do_udp_read,
222  tst);
223  if ((NULL != tc->write_ready) &&
225  (sizeof(data) ==
226  GNUNET_NETWORK_socket_recv (tst->lsock, &data, sizeof(data))))
227  {
228  if (data == tst->data)
230  else
232  "Received data mismatches expected value\n");
233  }
234  else
236  "Failed to receive data from inbound connection\n");
237 }
238 
239 
246 static void
247 do_read (void *cls)
248 {
249  struct NatActivity *na = cls;
250  struct GNUNET_NAT_Test *tst;
251  uint16_t data;
252  const struct GNUNET_SCHEDULER_TaskContext *tc;
253 
255  na->rtask = NULL;
256  tst = na->h;
258  if ((NULL != tc->write_ready) &&
260  (sizeof(data) ==
261  GNUNET_NETWORK_socket_recv (na->sock, &data, sizeof(data))))
262  {
263  if (data == tst->data)
265  else
267  "Received data does not match expected value\n");
268  }
269  else
271  "Failed to receive data from inbound connection\n");
273  GNUNET_free (na);
274 }
275 
276 
283 static void
284 do_accept (void *cls)
285 {
286  struct GNUNET_NAT_Test *tst = cls;
287  struct GNUNET_NETWORK_Handle *s;
288  struct NatActivity *wl;
289 
291  tst->lsock,
292  &do_accept,
293  tst);
294  s = GNUNET_NETWORK_socket_accept (tst->lsock, NULL, NULL);
295  if (NULL == s)
296  {
298  return; /* odd error */
299  }
301  "Got an inbound connection, waiting for data\n");
302  wl = GNUNET_new (struct NatActivity);
303  wl->sock = s;
304  wl->h = tst;
306  wl->sock,
307  &do_read,
308  wl);
310 }
311 
312 
320 static void
321 mq_error_handler (void *cls, enum GNUNET_MQ_Error error)
322 {
323  struct ClientActivity *ca = cls;
324  struct GNUNET_NAT_Test *tst = ca->h;
325 
327  GNUNET_MQ_destroy (ca->mq);
328  GNUNET_free (ca);
329 }
330 
331 
341 static void
342 addr_cb (void *cls,
343  int add_remove,
344  const struct sockaddr *addr,
345  socklen_t addrlen)
346 {
347  struct GNUNET_NAT_Test *h = cls;
348  struct ClientActivity *ca;
349  struct GNUNET_MQ_Envelope *env;
350  struct GNUNET_NAT_TestMessage *msg;
351  const struct sockaddr_in *sa;
352 
353  if (GNUNET_YES != add_remove)
354  return;
355  if (addrlen != sizeof(struct sockaddr_in))
356  {
358  "NAT test ignores IPv6 address `%s' returned from NAT library\n",
359  GNUNET_a2s (addr, addrlen));
360  return; /* ignore IPv6 here */
361  }
363  "Asking gnunet-nat-server to connect to `%s'\n",
364  GNUNET_a2s (addr, addrlen));
365 
366  ca = GNUNET_new (struct ClientActivity);
367  ca->h = h;
368  ca->mq = GNUNET_CLIENT_connect (h->cfg,
369  "gnunet-nat-server",
370  NULL,
372  ca);
373  if (NULL == ca->mq)
374  {
375  GNUNET_free (ca);
377  _ ("Failed to connect to `gnunet-nat-server'\n"));
378  return;
379  }
380  GNUNET_CONTAINER_DLL_insert (h->ca_head, h->ca_tail, ca);
381  sa = (const struct sockaddr_in *) addr;
383  msg->dst_ipv4 = sa->sin_addr.s_addr;
384  msg->dport = sa->sin_port;
385  msg->data = h->data;
386  msg->is_tcp = htonl ((uint32_t) h->is_tcp);
387  GNUNET_MQ_send (ca->mq, env);
388 }
389 
390 
399 static void
400 do_timeout (void *cls)
401 {
402  struct GNUNET_NAT_Test *nh = cls;
403 
404  nh->ttask = NULL;
405  nh->report (nh->report_cls,
406  (GNUNET_NAT_ERROR_SUCCESS == nh->status)
408  : nh->status);
409 }
410 
411 
427 struct GNUNET_NAT_Test *
429  int is_tcp,
430  uint16_t bnd_port,
431  uint16_t adv_port,
434  void *report_cls)
435 {
436  struct GNUNET_NAT_Test *nh;
437  struct sockaddr_in sa;
438  const struct sockaddr *addrs[] = { (const struct sockaddr *) &sa };
439  const socklen_t addrlens[] = { sizeof(sa) };
440 
441  memset (&sa, 0, sizeof(sa));
442  sa.sin_family = AF_INET;
443  sa.sin_port = htons (bnd_port);
444 #if HAVE_SOCKADDR_IN_SIN_LEN
445  sa.sin_len = sizeof(sa);
446 #endif
447 
448  nh = GNUNET_new (struct GNUNET_NAT_Test);
449  nh->cfg = cfg;
450  nh->is_tcp = is_tcp;
451  nh->data = bnd_port;
452  nh->adv_port = adv_port;
453  nh->report = report;
454  nh->report_cls = report_cls;
455  nh->status = GNUNET_NAT_ERROR_SUCCESS;
456  if (0 == bnd_port)
457  {
458  nh->nat = GNUNET_NAT_register (cfg,
459  is_tcp,
460  0,
461  0,
462  NULL,
463  NULL,
464  &addr_cb,
465  &reversal_cb,
466  nh,
467  NULL);
468  }
469  else
470  {
471  nh->lsock =
473  (is_tcp == GNUNET_YES) ? SOCK_STREAM
474  : SOCK_DGRAM,
475  0);
476  if ((nh->lsock == NULL) ||
478  (const struct sockaddr *) &sa,
479  sizeof(sa))))
480  {
481  GNUNET_log (
483  _ ("Failed to create listen socket bound to `%s' for NAT test: %s\n"),
484  GNUNET_a2s ((const struct sockaddr *) &sa, sizeof(sa)),
485  strerror (errno));
486  if (NULL != nh->lsock)
487  {
489  nh->lsock = NULL;
490  }
493  return nh;
494  }
495  if (GNUNET_YES == is_tcp)
496  {
499  nh->lsock,
500  &do_accept,
501  nh);
502  }
503  else
504  {
506  nh->lsock,
507  &do_udp_read,
508  nh);
509  }
511  "NAT test listens on port %u (%s)\n",
512  bnd_port,
513  (GNUNET_YES == is_tcp) ? "tcp" : "udp");
514  nh->nat = GNUNET_NAT_register (cfg,
515  is_tcp,
516  adv_port,
517  1,
518  addrs,
519  addrlens,
520  &addr_cb,
521  NULL,
522  nh,
523  NULL);
524  if (NULL == nh->nat)
525  {
527  _ ("NAT test failed to start NAT library\n"));
528  if (NULL != nh->ltask)
529  {
530  GNUNET_SCHEDULER_cancel (nh->ltask);
531  nh->ltask = NULL;
532  }
533  if (NULL != nh->lsock)
534  {
536  nh->lsock = NULL;
537  }
540  return nh;
541  }
542  }
544  return nh;
545 }
546 
547 
553 void
555 {
556  struct NatActivity *pos;
557  struct ClientActivity *cpos;
558 
559  LOG (GNUNET_ERROR_TYPE_DEBUG, "Stopping NAT test\n");
560  while (NULL != (cpos = tst->ca_head))
561  {
562  GNUNET_CONTAINER_DLL_remove (tst->ca_head, tst->ca_tail, cpos);
563  GNUNET_MQ_destroy (cpos->mq);
564  GNUNET_free (cpos);
565  }
566  while (NULL != (pos = tst->na_head))
567  {
568  GNUNET_CONTAINER_DLL_remove (tst->na_head, tst->na_tail, pos);
571  GNUNET_free (pos);
572  }
573  if (NULL != tst->ttask)
574  {
576  tst->ttask = NULL;
577  }
578  if (NULL != tst->ltask)
579  {
581  tst->ltask = NULL;
582  }
583  if (NULL != tst->lsock)
584  {
586  tst->lsock = NULL;
587  }
588  if (NULL != tst->nat)
589  {
590  GNUNET_NAT_unregister (tst->nat);
591  tst->nat = NULL;
592  }
593  GNUNET_free (tst);
594 }
595 
596 
597 /* end of nat_test.c */
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
static const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration we are using.
Definition: gnunet-abd.c:36
static struct GNUNET_TIME_Relative timeout
Desired timeout for the lookup (default is no timeout).
Definition: gnunet-abd.c:61
static struct GNUNET_ARM_Handle * h
Connection with ARM.
Definition: gnunet-arm.c:99
uint32_t data
The data value.
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).
static void do_read(void *cls)
Activity on our incoming socket.
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.
static void mq_error_handler(void *cls, enum GNUNET_MQ_Error error)
We got disconnected from the NAT server.
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 do_udp_read(void *cls)
Activity on our incoming socket.
#define LOG(kind,...)
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.
static struct GNUNET_NAT_Handle * nh
Handle to NAT operation.
Definition: gnunet-nat.c:80
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:1057
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
#define GNUNET_log(kind,...)
@ GNUNET_OK
@ GNUNET_YES
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
#define GNUNET_log_strerror(level, cmd)
Log an error message at log-level 'level' that indicates a failure of the command 'cmd' with the mess...
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_DEBUG
@ GNUNET_ERROR_TYPE_INFO
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_free(ptr)
Wrapper around free.
GNUNET_MQ_Error
Error codes for the queue.
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:304
#define GNUNET_MQ_msg(mvar, type)
Allocate a GNUNET_MQ_Envelope.
Definition: gnunet_mq_lib.h:77
void GNUNET_MQ_destroy(struct GNUNET_MQ_Handle *mq)
Destroy the message queue.
Definition: mq.c:683
GNUNET_NAT_StatusCode
Error Types for the NAT subsystem (which can then later be converted/resolved to a string)
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:674
void(* GNUNET_NAT_TestCallback)(void *cls, enum GNUNET_NAT_StatusCode result)
Function called to report success or failure for NAT configuration test.
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
@ GNUNET_NAT_ERROR_SUCCESS
Just the default.
@ GNUNET_NAT_ERROR_INTERNAL_NETWORK_ERROR
Failure in network subsystem, check permissions.
@ GNUNET_NAT_ERROR_NAT_REGISTER_FAILED
NAT test failed to initiate.
@ GNUNET_NAT_ERROR_TIMEOUT
test timed out
enum GNUNET_GenericReturnValue GNUNET_NETWORK_socket_close(struct GNUNET_NETWORK_Handle *desc)
Close a socket.
Definition: network.c:508
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:716
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:392
struct GNUNET_NETWORK_Handle * GNUNET_NETWORK_socket_create(int domain, int type, int protocol)
Create a new socket.
Definition: network.c:832
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
enum GNUNET_GenericReturnValue GNUNET_NETWORK_socket_listen(const struct GNUNET_NETWORK_Handle *desc, int backlog)
Listen on a socket.
Definition: network.c:651
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:949
#define GNUNET_MESSAGE_TYPE_NAT_TEST
Message to ask NAT server to perform traversal test.
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:1299
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:1506
const struct GNUNET_SCHEDULER_TaskContext * GNUNET_SCHEDULER_get_task_context(void)
Obtain the reasoning why the current task was started.
Definition: scheduler.c:752
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:975
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:1272
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
Messages for interaction with gnunet-nat-server and gnunet-nat-service.
#define _(String)
GNU gettext support macro.
Definition: platform.h:177
static struct GNUNET_SCHEDULER_TaskContext tc
Task context of the current task.
Definition: scheduler.c:431
Entry we keep for each connection to the gnunet-nat-service.
struct GNUNET_MQ_Handle * mq
Socket of the incoming connection.
struct ClientActivity * next
This is a doubly-linked list.
struct GNUNET_NAT_Test * h
Handle to overall NAT test.
struct ClientActivity * prev
This is a doubly-linked list.
const struct GNUNET_CONFIGURATION_Handle * cfg
The configuration that we are using.
Definition: arm_api.c:112
Handle to a message queue.
Definition: mq.c:87
Handle for active NAT registrations.
Definition: nat_api.c:72
const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration we use.
Definition: nat_api.c:76
Request to test NAT traversal, sent to the gnunet-nat-server (not the service!).
Definition: nat.h:39
Handle to a NAT test.
struct ClientActivity * ca_tail
Tail of list of client activities.
const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration used.
GNUNET_NAT_TestCallback report
Function to call with success report.
uint16_t adv_port
Advertised port to the other peer.
void * report_cls
Closure for report.
struct GNUNET_NAT_Handle * nat
Handle to NAT traversal in use.
struct GNUNET_NETWORK_Handle * lsock
Handle to listen socket, or NULL.
uint16_t data
Data that should be transmitted or source-port.
struct NatActivity * na_head
Head of list of nat activities.
struct GNUNET_SCHEDULER_Task * ttask
Task identifier for the timeout (if any)
int is_tcp
GNUNET_YES if we're testing TCP
struct GNUNET_SCHEDULER_Task * ltask
Identity of task for the listen socket (if any)
struct ClientActivity * ca_head
Head of list of client activities.
enum GNUNET_NAT_StatusCode status
Status code to be reported to the timeout/status call.
struct NatActivity * na_tail
Tail of list of nat activities.
handle to a socket
Definition: network.c:53
Context information passed to each scheduler task.
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 ...
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 ...
Entry in list of pending tasks.
Definition: scheduler.c:136
Time for relative time used by GNUnet, in microseconds.
Entry we keep for each incoming connection.
struct NatActivity * prev
This is a doubly-linked list.
struct GNUNET_SCHEDULER_Task * rtask
Task reading from the incoming connection.
struct GNUNET_NAT_Test * h
Handle of the master context.
struct GNUNET_NETWORK_Handle * sock
Socket of the incoming connection.
struct NatActivity * next
This is a doubly-linked list.