aboutsummaryrefslogtreecommitdiff
path: root/src/nat
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2017-01-06 13:26:38 +0100
committerChristian Grothoff <christian@grothoff.org>2017-01-06 13:26:38 +0100
commit80e1315b56f559db60499f5373e90c293c5ab065 (patch)
tree3b279e6ac8e6298d7d9d96d12868f628a413939b /src/nat
parent1b7f6eea0a06abab9b75b30f021aa6313fccfcd4 (diff)
downloadgnunet-80e1315b56f559db60499f5373e90c293c5ab065.tar.gz
gnunet-80e1315b56f559db60499f5373e90c293c5ab065.zip
separate service for autoconfiguration from NAT traversal
Diffstat (limited to 'src/nat')
-rw-r--r--src/nat/Makefile.am9
-rw-r--r--src/nat/gnunet-nat-server.c384
-rw-r--r--src/nat/gnunet-nat.c279
-rw-r--r--src/nat/gnunet-service-nat.c355
-rw-r--r--src/nat/nat.conf.in5
-rw-r--r--src/nat/nat.h39
-rw-r--r--src/nat/nat_api_auto.c274
-rw-r--r--src/nat/nat_api_test.c644
8 files changed, 0 insertions, 1989 deletions
diff --git a/src/nat/Makefile.am b/src/nat/Makefile.am
index b2b9c4f50..456ddfb62 100644
--- a/src/nat/Makefile.am
+++ b/src/nat/Makefile.am
@@ -34,7 +34,6 @@ install-exec-hook:
34endif 34endif
35 35
36bin_PROGRAMS = \ 36bin_PROGRAMS = \
37 gnunet-nat-server \
38 gnunet-nat 37 gnunet-nat
39 38
40libexec_PROGRAMS = \ 39libexec_PROGRAMS = \
@@ -42,12 +41,6 @@ libexec_PROGRAMS = \
42 gnunet-service-nat 41 gnunet-service-nat
43 42
44 43
45gnunet_nat_server_SOURCES = \
46 gnunet-nat-server.c nat.h
47gnunet_nat_server_LDADD = \
48 libgnunetnat.la \
49 $(top_builddir)/src/util/libgnunetutil.la
50
51gnunet_helper_nat_server_SOURCES = \ 44gnunet_helper_nat_server_SOURCES = \
52 $(NATSERVER) 45 $(NATSERVER)
53 46
@@ -85,9 +78,7 @@ libgnunetnat_la_LDFLAGS = \
85 78
86libgnunetnatnew_la_SOURCES = \ 79libgnunetnatnew_la_SOURCES = \
87 nat_api.c \ 80 nat_api.c \
88 nat_api_auto.c \
89 nat_api_stun.c nat_stun.h \ 81 nat_api_stun.c nat_stun.h \
90 nat_api_test.c \
91 nat.h 82 nat.h
92libgnunetnatnew_la_LIBADD = \ 83libgnunetnatnew_la_LIBADD = \
93 $(top_builddir)/src/util/libgnunetutil.la \ 84 $(top_builddir)/src/util/libgnunetutil.la \
diff --git a/src/nat/gnunet-nat-server.c b/src/nat/gnunet-nat-server.c
deleted file mode 100644
index 1692a8ef1..000000000
--- a/src/nat/gnunet-nat-server.c
+++ /dev/null
@@ -1,384 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2011 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 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 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21/**
22 * @file src/nat/gnunet-nat-server.c
23 * @brief Daemon to run on 'gnunet.org' to help test NAT traversal code
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_nat_lib.h"
29#include "gnunet_protocols.h"
30#include "nat.h"
31
32
33/**
34 * Our server.
35 */
36static struct GNUNET_SERVER_Handle *server;
37
38/**
39 * Our configuration.
40 */
41static const struct GNUNET_CONFIGURATION_Handle *cfg;
42
43
44/**
45 * Try contacting the peer using autonomous NAT traveral method.
46 *
47 * @param dst_ipv4 IPv4 address to send the fake ICMP message
48 * @param dport destination port to include in ICMP message
49 * @param is_tcp mark for TCP (#GNUNET_YES) or UDP (#GNUNET_NO)
50 */
51static void
52try_anat (uint32_t dst_ipv4,
53 uint16_t dport,
54 int is_tcp)
55{
56 struct GNUNET_NAT_Handle *h;
57 struct sockaddr_in sa;
58
59 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
60 "Asking for connection reversal with %x and code %u\n",
61 (unsigned int) dst_ipv4,
62 (unsigned int) dport);
63 h = GNUNET_NAT_register (cfg,
64 is_tcp,
65 dport,
66 0,
67 NULL, NULL, NULL, NULL, NULL, NULL);
68 memset (&sa, 0, sizeof (sa));
69 sa.sin_family = AF_INET;
70#if HAVE_SOCKADDR_IN_SIN_LEN
71 sa.sin_len = sizeof (sa);
72#endif
73 sa.sin_addr.s_addr = dst_ipv4;
74 GNUNET_NAT_run_client (h, &sa);
75 GNUNET_NAT_unregister (h);
76}
77
78
79/**
80 * Closure for #tcp_send.
81 */
82struct TcpContext
83{
84 /**
85 * TCP socket.
86 */
87 struct GNUNET_NETWORK_Handle *s;
88
89 /**
90 * Data to transmit.
91 */
92 uint16_t data;
93};
94
95
96/**
97 * Task called by the scheduler once we can do the TCP send
98 * (or once we failed to connect...).
99 *
100 * @param cls the `struct TcpContext`
101 */
102static void
103tcp_send (void *cls)
104{
105 struct TcpContext *ctx = cls;
106 const struct GNUNET_SCHEDULER_TaskContext *tc;
107
108 tc = GNUNET_SCHEDULER_get_task_context ();
109 if ((NULL != tc->write_ready) &&
110 (GNUNET_NETWORK_fdset_isset (tc->write_ready, ctx->s)))
111 {
112 if (-1 ==
113 GNUNET_NETWORK_socket_send (ctx->s, &ctx->data, sizeof (ctx->data)))
114 {
115 GNUNET_log_strerror (GNUNET_ERROR_TYPE_DEBUG, "send");
116 }
117 GNUNET_NETWORK_socket_shutdown (ctx->s, SHUT_RDWR);
118 }
119 GNUNET_NETWORK_socket_close (ctx->s);
120 GNUNET_free (ctx);
121}
122
123
124/**
125 * Try to send @a data to the
126 * IP @a dst_ipv4' at port @a dport via TCP.
127 *
128 * @param dst_ipv4 target IP
129 * @param dport target port
130 * @param data data to send
131 */
132static void
133try_send_tcp (uint32_t dst_ipv4,
134 uint16_t dport,
135 uint16_t data)
136{
137 struct GNUNET_NETWORK_Handle *s;
138 struct sockaddr_in sa;
139 struct TcpContext *ctx;
140
141 s = GNUNET_NETWORK_socket_create (AF_INET,
142 SOCK_STREAM,
143 0);
144 if (NULL == s)
145 {
146 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
147 "socket");
148 return;
149 }
150 memset (&sa, 0, sizeof (sa));
151 sa.sin_family = AF_INET;
152#if HAVE_SOCKADDR_IN_SIN_LEN
153 sa.sin_len = sizeof (sa);
154#endif
155 sa.sin_addr.s_addr = dst_ipv4;
156 sa.sin_port = htons (dport);
157 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
158 "Sending TCP message to `%s'\n",
159 GNUNET_a2s ((struct sockaddr *) &sa,
160 sizeof (sa)));
161 if ( (GNUNET_OK !=
162 GNUNET_NETWORK_socket_connect (s,
163 (const struct sockaddr *) &sa,
164 sizeof (sa))) &&
165 (errno != EINPROGRESS) )
166 {
167 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
168 "connect");
169 GNUNET_NETWORK_socket_close (s);
170 return;
171 }
172 ctx = GNUNET_new (struct TcpContext);
173 ctx->s = s;
174 ctx->data = data;
175 GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_SECONDS,
176 s,
177 &tcp_send,
178 ctx);
179}
180
181
182/**
183 * Try to send @a data to the
184 * IP @a dst_ipv4 at port @a dport via UDP.
185 *
186 * @param dst_ipv4 target IP
187 * @param dport target port
188 * @param data data to send
189 */
190static void
191try_send_udp (uint32_t dst_ipv4,
192 uint16_t dport,
193 uint16_t data)
194{
195 struct GNUNET_NETWORK_Handle *s;
196 struct sockaddr_in sa;
197
198 s = GNUNET_NETWORK_socket_create (AF_INET,
199 SOCK_DGRAM,
200 0);
201 if (NULL == s)
202 {
203 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
204 "socket");
205 return;
206 }
207 memset (&sa, 0, sizeof (sa));
208 sa.sin_family = AF_INET;
209#if HAVE_SOCKADDR_IN_SIN_LEN
210 sa.sin_len = sizeof (sa);
211#endif
212 sa.sin_addr.s_addr = dst_ipv4;
213 sa.sin_port = htons (dport);
214 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
215 "Sending UDP packet to `%s'\n",
216 GNUNET_a2s ((struct sockaddr *) &sa,
217 sizeof (sa)));
218 if (-1 ==
219 GNUNET_NETWORK_socket_sendto (s,
220 &data,
221 sizeof (data),
222 (const struct sockaddr *) &sa,
223 sizeof (sa)))
224 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
225 "sendto");
226 GNUNET_NETWORK_socket_close (s);
227}
228
229
230/**
231 * We've received a request to probe a NAT
232 * traversal. Do it.
233 *
234 * @param cls unused
235 * @param client handle to client (we always close)
236 * @param msg message with details about what to test
237 */
238static void
239test (void *cls,
240 struct GNUNET_SERVER_Client *client,
241 const struct GNUNET_MessageHeader *msg)
242{
243 const struct GNUNET_NAT_TestMessage *tm;
244 uint16_t dport;
245
246 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
247 "Received test request\n");
248 tm = (const struct GNUNET_NAT_TestMessage *) msg;
249 dport = ntohs (tm->dport);
250 if (0 == dport)
251 try_anat (tm->dst_ipv4,
252 ntohs (tm->data),
253 (int) ntohl (tm->is_tcp));
254 else if (GNUNET_YES == ntohl (tm->is_tcp))
255 try_send_tcp (tm->dst_ipv4,
256 dport,
257 tm->data);
258 else
259 try_send_udp (tm->dst_ipv4,
260 dport,
261 tm->data);
262 GNUNET_SERVER_receive_done (client,
263 GNUNET_NO);
264}
265
266
267/**
268 * Task run during shutdown.
269 *
270 * @param cls unused
271 */
272static void
273shutdown_task (void *cls)
274{
275 GNUNET_SERVER_destroy (server);
276 server = NULL;
277}
278
279
280/**
281 * Main function that will be run.
282 *
283 * @param cls closure
284 * @param args remaining command-line arguments
285 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
286 * @param c configuration
287 */
288static void
289run (void *cls,
290 char *const *args,
291 const char *cfgfile,
292 const struct GNUNET_CONFIGURATION_Handle *c)
293{
294 static const struct GNUNET_SERVER_MessageHandler handlers[] = {
295 {&test, NULL, GNUNET_MESSAGE_TYPE_NAT_TEST,
296 sizeof (struct GNUNET_NAT_TestMessage)},
297 {NULL, NULL, 0, 0}
298 };
299 unsigned int port;
300 struct sockaddr_in in4;
301 struct sockaddr_in6 in6;
302
303 socklen_t slen[] = {
304 sizeof (in4),
305 sizeof (in6),
306 0
307 };
308 struct sockaddr *sa[] = {
309 (struct sockaddr *) &in4,
310 (struct sockaddr *) &in6,
311 NULL
312 };
313
314 cfg = c;
315 if ( (NULL == args[0]) ||
316 (1 != SSCANF (args[0], "%u", &port)) ||
317 (0 == port) ||
318 (65536 <= port) )
319 {
320 FPRINTF (stderr,
321 _("Please pass valid port number as the first argument! (got `%s')\n"),
322 args[0]);
323 return;
324 }
325 memset (&in4, 0, sizeof (in4));
326 memset (&in6, 0, sizeof (in6));
327 in4.sin_family = AF_INET;
328 in4.sin_port = htons ((uint16_t) port);
329 in6.sin6_family = AF_INET6;
330 in6.sin6_port = htons ((uint16_t) port);
331#if HAVE_SOCKADDR_IN_SIN_LEN
332 in4.sin_len = sizeof (in4);
333 in6.sin6_len = sizeof (in6);
334#endif
335 server = GNUNET_SERVER_create (NULL,
336 NULL,
337 (struct sockaddr * const *) sa,
338 slen,
339 GNUNET_TIME_UNIT_SECONDS,
340 GNUNET_YES);
341 GNUNET_SERVER_add_handlers (server,
342 handlers);
343 GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
344 NULL);
345}
346
347
348/**
349 * Main function of gnunet-nat-server.
350 *
351 * @param argc number of command-line arguments
352 * @param argv command line
353 * @return 0 on success, -1 on error
354 */
355int
356main (int argc, char *const argv[])
357{
358 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
359 GNUNET_GETOPT_OPTION_END
360 };
361
362 if (GNUNET_OK !=
363 GNUNET_STRINGS_get_utf8_args (argc, argv,
364 &argc, &argv))
365 return 2;
366
367 if (GNUNET_OK !=
368 GNUNET_PROGRAM_run (argc,
369 argv,
370 "gnunet-nat-server [options] PORT",
371 _("GNUnet NAT traversal test helper daemon"),
372 options,
373 &run,
374 NULL))
375 {
376 GNUNET_free ((void*) argv);
377 return 1;
378 }
379 GNUNET_free ((void*) argv);
380 return 0;
381}
382
383
384/* end of gnunet-nat-server.c */
diff --git a/src/nat/gnunet-nat.c b/src/nat/gnunet-nat.c
index 4171babf9..02d68d787 100644
--- a/src/nat/gnunet-nat.c
+++ b/src/nat/gnunet-nat.c
@@ -34,11 +34,6 @@
34static int global_ret; 34static int global_ret;
35 35
36/** 36/**
37 * Handle to ongoing autoconfiguration.
38 */
39static struct GNUNET_NAT_AutoHandle *ah;
40
41/**
42 * Name of section in configuration file to use for 37 * Name of section in configuration file to use for
43 * additional options. 38 * additional options.
44 */ 39 */
@@ -60,39 +55,11 @@ static int listen_reversal;
60static int use_tcp; 55static int use_tcp;
61 56
62/** 57/**
63 * If we do auto-configuration, should we write the result
64 * to a file?
65 */
66static int write_cfg;
67
68/**
69 * Configuration filename.
70 */
71static const char *cfg_file;
72
73/**
74 * Original configuration.
75 */
76static const struct GNUNET_CONFIGURATION_Handle *cfg;
77
78/**
79 * Protocol to use. 58 * Protocol to use.
80 */ 59 */
81static uint8_t proto; 60static uint8_t proto;
82 61
83/** 62/**
84 * Address we are bound to (in test), or should bind to
85 * (if #do_stun is set).
86 */
87static char *bind_addr;
88
89/**
90 * External IP address and port to use for the test.
91 * If not set, use #bind_addr.
92 */
93static char *extern_addr;
94
95/**
96 * Local address to use for connection reversal request. 63 * Local address to use for connection reversal request.
97 */ 64 */
98static char *local_addr; 65static char *local_addr;
@@ -108,16 +75,6 @@ static char *remote_addr;
108static unsigned int do_stun; 75static unsigned int do_stun;
109 76
110/** 77/**
111 * Should we run autoconfiguration?
112 */
113static unsigned int do_auto;
114
115/**
116 * Handle to a NAT test operation.
117 */
118static struct GNUNET_NAT_Test *nt;
119
120/**
121 * Handle to NAT operation. 78 * Handle to NAT operation.
122 */ 79 */
123static struct GNUNET_NAT_Handle *nh; 80static struct GNUNET_NAT_Handle *nh;
@@ -140,10 +97,6 @@ static struct GNUNET_SCHEDULER_Task *rtask;
140static void 97static void
141test_finished () 98test_finished ()
142{ 99{
143 if (NULL != ah)
144 return;
145 if (NULL != nt)
146 return;
147 if (NULL != nh) 100 if (NULL != nh)
148 return; 101 return;
149 if (NULL != rtask) 102 if (NULL != rtask)
@@ -153,160 +106,6 @@ test_finished ()
153 106
154 107
155/** 108/**
156 * Function to iterate over sugested changes options
157 *
158 * @param cls closure
159 * @param section name of the section
160 * @param option name of the option
161 * @param value value of the option
162 */
163static void
164auto_conf_iter (void *cls,
165 const char *section,
166 const char *option,
167 const char *value)
168{
169 struct GNUNET_CONFIGURATION_Handle *new_cfg = cls;
170
171 PRINTF ("%s: %s\n",
172 option,
173 value);
174 if (NULL != new_cfg)
175 GNUNET_CONFIGURATION_set_value_string (new_cfg,
176 section,
177 option,
178 value);
179}
180
181
182/**
183 * Function called with the result from the autoconfiguration.
184 *
185 * @param cls closure
186 * @param diff minimal suggested changes to the original configuration
187 * to make it work (as best as we can)
188 * @param result #GNUNET_NAT_ERROR_SUCCESS on success, otherwise the specific error code
189 * @param type what the situation of the NAT
190 */
191static void
192auto_config_cb (void *cls,
193 const struct GNUNET_CONFIGURATION_Handle *diff,
194 enum GNUNET_NAT_StatusCode result,
195 enum GNUNET_NAT_Type type)
196{
197 const char *nat_type;
198 char unknown_type[64];
199 struct GNUNET_CONFIGURATION_Handle *new_cfg;
200
201 ah = NULL;
202 switch (type)
203 {
204 case GNUNET_NAT_TYPE_NO_NAT:
205 nat_type = "NO NAT";
206 break;
207 case GNUNET_NAT_TYPE_UNREACHABLE_NAT:
208 nat_type = "NAT but we can traverse";
209 break;
210 case GNUNET_NAT_TYPE_STUN_PUNCHED_NAT:
211 nat_type = "NAT but STUN is able to identify the correct information";
212 break;
213 case GNUNET_NAT_TYPE_UPNP_NAT:
214 nat_type = "NAT but UPNP opened the ports";
215 break;
216 default:
217 SPRINTF (unknown_type,
218 "NAT unknown, type %u",
219 type);
220 nat_type = unknown_type;
221 break;
222 }
223
224 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
225 "NAT status: %s/%s\n",
226 GNUNET_NAT_status2string (result),
227 nat_type);
228
229 /* Shortcut: if there are no changes suggested, bail out early. */
230 if (GNUNET_NO ==
231 GNUNET_CONFIGURATION_is_dirty (diff))
232 {
233 test_finished ();
234 return;
235 }
236
237 /* Apply diff to original configuration and show changes
238 to the user */
239 new_cfg = write_cfg ? GNUNET_CONFIGURATION_dup (cfg) : NULL;
240
241 if (NULL != diff)
242 {
243 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
244 _("Suggested configuration changes:\n"));
245 GNUNET_CONFIGURATION_iterate_section_values (diff,
246 "nat",
247 &auto_conf_iter,
248 new_cfg);
249 }
250
251 /* If desired, write configuration to file; we write only the
252 changes to the defaults to keep things compact. */
253 if ( (write_cfg) &&
254 (NULL != diff) )
255 {
256 struct GNUNET_CONFIGURATION_Handle *def_cfg;
257
258 GNUNET_CONFIGURATION_set_value_string (new_cfg,
259 "ARM",
260 "CONFIG",
261 NULL);
262 def_cfg = GNUNET_CONFIGURATION_create ();
263 GNUNET_break (GNUNET_OK ==
264 GNUNET_CONFIGURATION_load (def_cfg,
265 NULL));
266 if (GNUNET_OK !=
267 GNUNET_CONFIGURATION_write_diffs (def_cfg,
268 new_cfg,
269 cfg_file))
270 {
271 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
272 _("Failed to write configuration to `%s'\n"),
273 cfg_file);
274 global_ret = 1;
275 }
276 else
277 {
278 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
279 _("Wrote updated configuration to `%s'\n"),
280 cfg_file);
281 }
282 GNUNET_CONFIGURATION_destroy (def_cfg);
283 }
284
285 if (NULL != new_cfg)
286 GNUNET_CONFIGURATION_destroy (new_cfg);
287 test_finished ();
288}
289
290
291/**
292 * Function called to report success or failure for
293 * NAT configuration test.
294 *
295 * @param cls closure
296 * @param result #GNUNET_NAT_ERROR_SUCCESS on success, otherwise the specific error code
297 */
298static void
299test_report_cb (void *cls,
300 enum GNUNET_NAT_StatusCode result)
301{
302 nt = NULL;
303 PRINTF ("NAT test result: %s\n",
304 GNUNET_NAT_status2string (result));
305 test_finished ();
306}
307
308
309/**
310 * Signature of the callback passed to #GNUNET_NAT_register() for 109 * Signature of the callback passed to #GNUNET_NAT_register() for
311 * a function to call whenever our set of 'valid' addresses changes. 110 * a function to call whenever our set of 'valid' addresses changes.
312 * 111 *
@@ -362,16 +161,6 @@ reversal_cb (void *cls,
362static void 161static void
363do_shutdown (void *cls) 162do_shutdown (void *cls)
364{ 163{
365 if (NULL != ah)
366 {
367 GNUNET_NAT_autoconfig_cancel (ah);
368 ah = NULL;
369 }
370 if (NULL != nt)
371 {
372 GNUNET_NAT_test_stop (nt);
373 nt = NULL;
374 }
375 if (NULL != nh) 164 if (NULL != nh)
376 { 165 {
377 GNUNET_NAT_unregister (nh); 166 GNUNET_NAT_unregister (nh);
@@ -452,16 +241,11 @@ run (void *cls,
452 const struct GNUNET_CONFIGURATION_Handle *c) 241 const struct GNUNET_CONFIGURATION_Handle *c)
453{ 242{
454 uint8_t af; 243 uint8_t af;
455 struct sockaddr_in bind_sa;
456 struct sockaddr_in extern_sa;
457 struct sockaddr *local_sa; 244 struct sockaddr *local_sa;
458 struct sockaddr *remote_sa; 245 struct sockaddr *remote_sa;
459 socklen_t local_len; 246 socklen_t local_len;
460 size_t remote_len; 247 size_t remote_len;
461 248
462 cfg_file = cfgfile;
463 cfg = c;
464
465 if (use_tcp && use_udp) 249 if (use_tcp && use_udp)
466 { 250 {
467 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, 251 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
@@ -478,50 +262,13 @@ run (void *cls,
478 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, 262 GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
479 NULL); 263 NULL);
480 264
481 if (do_auto)
482 {
483 ah = GNUNET_NAT_autoconfig_start (c,
484 &auto_config_cb,
485 NULL);
486 }
487
488 if (0 == proto) 265 if (0 == proto)
489 { 266 {
490 if (do_auto)
491 return; /* all good, we just run auto config */
492 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, 267 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
493 "Must specify either TCP or UDP\n"); 268 "Must specify either TCP or UDP\n");
494 global_ret = 1; 269 global_ret = 1;
495 return; 270 return;
496 } 271 }
497 if (NULL != bind_addr)
498 {
499 if (GNUNET_OK !=
500 GNUNET_STRINGS_to_address_ipv4 (bind_addr,
501 strlen (bind_addr),
502 &bind_sa))
503 {
504 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
505 "Invalid socket address `%s'\n",
506 bind_addr);
507 global_ret = 1;
508 return;
509 }
510 }
511 if (NULL != extern_addr)
512 {
513 if (GNUNET_OK !=
514 GNUNET_STRINGS_to_address_ipv4 (extern_addr,
515 strlen (extern_addr),
516 &extern_sa))
517 {
518 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
519 "Invalid socket address `%s'\n",
520 extern_addr);
521 global_ret = 1;
522 return;
523 }
524 }
525 if (NULL != local_addr) 272 if (NULL != local_addr)
526 { 273 {
527 local_len = (socklen_t) GNUNET_STRINGS_parse_socket_addr (local_addr, 274 local_len = (socklen_t) GNUNET_STRINGS_parse_socket_addr (local_addr,
@@ -551,20 +298,6 @@ run (void *cls,
551 } 298 }
552 } 299 }
553 300
554 if (NULL != bind_addr)
555 {
556 if (NULL == extern_addr)
557 extern_sa = bind_sa;
558 nt = GNUNET_NAT_test_start (c,
559 proto,
560 bind_sa.sin_addr,
561 ntohs (bind_sa.sin_port),
562 extern_sa.sin_addr,
563 ntohs (extern_sa.sin_port),
564 &test_report_cb,
565 NULL);
566 }
567
568 if (NULL != local_addr) 301 if (NULL != local_addr)
569 { 302 {
570 nh = GNUNET_NAT_register (c, 303 nh = GNUNET_NAT_register (c,
@@ -683,15 +416,6 @@ main (int argc,
683 char *const argv[]) 416 char *const argv[])
684{ 417{
685 static const struct GNUNET_GETOPT_CommandLineOption options[] = { 418 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
686 {'a', "auto", NULL,
687 gettext_noop ("run autoconfiguration"),
688 GNUNET_NO, &GNUNET_GETOPT_set_one, &do_auto },
689 {'b', "bind", "ADDRESS",
690 gettext_noop ("which IP and port are we bound to"),
691 GNUNET_YES, &GNUNET_GETOPT_set_string, &bind_addr },
692 {'e', "external", "ADDRESS",
693 gettext_noop ("which external IP and port should be used to test"),
694 GNUNET_YES, &GNUNET_GETOPT_set_string, &extern_addr },
695 {'i', "in", "ADDRESS", 419 {'i', "in", "ADDRESS",
696 gettext_noop ("which IP and port are we locally using to bind/listen to"), 420 gettext_noop ("which IP and port are we locally using to bind/listen to"),
697 GNUNET_YES, &GNUNET_GETOPT_set_string, &local_addr }, 421 GNUNET_YES, &GNUNET_GETOPT_set_string, &local_addr },
@@ -710,9 +434,6 @@ main (int argc,
710 {'u', "udp", NULL, 434 {'u', "udp", NULL,
711 gettext_noop ("use UDP"), 435 gettext_noop ("use UDP"),
712 GNUNET_NO, &GNUNET_GETOPT_set_one, &use_udp }, 436 GNUNET_NO, &GNUNET_GETOPT_set_one, &use_udp },
713 {'w', "write", NULL,
714 gettext_noop ("write configuration file (for autoconfiguration)"),
715 GNUNET_NO, &GNUNET_GETOPT_set_one, &write_cfg },
716 {'W', "watch", NULL, 437 {'W', "watch", NULL,
717 gettext_noop ("watch for connection reversal requests"), 438 gettext_noop ("watch for connection reversal requests"),
718 GNUNET_NO, &GNUNET_GETOPT_set_one, &listen_reversal }, 439 GNUNET_NO, &GNUNET_GETOPT_set_one, &listen_reversal },
diff --git a/src/nat/gnunet-service-nat.c b/src/nat/gnunet-service-nat.c
index 79f806f27..2cb2b30ff 100644
--- a/src/nat/gnunet-service-nat.c
+++ b/src/nat/gnunet-service-nat.c
@@ -284,80 +284,6 @@ struct StunExternalIP
284 284
285 285
286/** 286/**
287 * Context for autoconfiguration operations.
288 */
289struct AutoconfigContext
290{
291 /**
292 * Kept in a DLL.
293 */
294 struct AutoconfigContext *prev;
295
296 /**
297 * Kept in a DLL.
298 */
299 struct AutoconfigContext *next;
300
301 /**
302 * Which client asked the question.
303 */
304 struct ClientHandle *ch;
305
306 /**
307 * Configuration we are creating.
308 */
309 struct GNUNET_CONFIGURATION_Handle *c;
310
311 /**
312 * Original configuration (for diffing).
313 */
314 struct GNUNET_CONFIGURATION_Handle *orig;
315
316 /**
317 * Timeout task to force termination.
318 */
319 struct GNUNET_SCHEDULER_Task *timeout_task;
320
321 /**
322 * What type of system are we on?
323 */
324 char *system_type;
325
326 /**
327 * Handle to activity to probe for our external IP.
328 */
329 struct GNUNET_NAT_ExternalHandle *probe_external;
330
331 /**
332 * #GNUNET_YES if upnpc should be used,
333 * #GNUNET_NO if upnpc should not be used,
334 * #GNUNET_SYSERR if we should simply not change the option.
335 */
336 int enable_upnpc;
337
338 /**
339 * Status code to return to the client.
340 */
341 enum GNUNET_NAT_StatusCode status_code;
342
343 /**
344 * NAT type to return to the client.
345 */
346 enum GNUNET_NAT_Type type;
347};
348
349
350/**
351 * DLL of our autoconfiguration operations.
352 */
353static struct AutoconfigContext *ac_head;
354
355/**
356 * DLL of our autoconfiguration operations.
357 */
358static struct AutoconfigContext *ac_tail;
359
360/**
361 * Timeout to use when STUN data is considered stale. 287 * Timeout to use when STUN data is considered stale.
362 */ 288 */
363static struct GNUNET_TIME_Relative stun_stale_timeout; 289static struct GNUNET_TIME_Relative stun_stale_timeout;
@@ -1920,274 +1846,6 @@ handle_request_connection_reversal (void *cls,
1920 1846
1921 1847
1922/** 1848/**
1923 * Check validity of #GNUNET_MESSAGE_TYPE_NAT_REQUEST_AUTO_CFG message
1924 * from client.
1925 *
1926 * @param cls client who sent the message
1927 * @param message the message received
1928 * @return #GNUNET_OK if message is well-formed
1929 */
1930static int
1931check_autoconfig_request (void *cls,
1932 const struct GNUNET_NAT_AutoconfigRequestMessage *message)
1933{
1934 return GNUNET_OK; /* checked later */
1935}
1936
1937
1938/**
1939 * Stop all pending activities with respect to the @a ac
1940 *
1941 * @param ac autoconfiguration to terminate activities for
1942 */
1943static void
1944terminate_ac_activities (struct AutoconfigContext *ac)
1945{
1946 if (NULL != ac->probe_external)
1947 {
1948 GNUNET_NAT_mini_get_external_ipv4_cancel_ (ac->probe_external);
1949 ac->probe_external = NULL;
1950 }
1951 if (NULL != ac->timeout_task)
1952 {
1953 GNUNET_SCHEDULER_cancel (ac->timeout_task);
1954 ac->timeout_task = NULL;
1955 }
1956}
1957
1958
1959/**
1960 * Finish handling the autoconfiguration request and send
1961 * the response to the client.
1962 *
1963 * @param cls the `struct AutoconfigContext` to conclude
1964 */
1965static void
1966conclude_autoconfig_request (void *cls)
1967{
1968 struct AutoconfigContext *ac = cls;
1969 struct ClientHandle *ch = ac->ch;
1970 struct GNUNET_NAT_AutoconfigResultMessage *arm;
1971 struct GNUNET_MQ_Envelope *env;
1972 size_t c_size;
1973 char *buf;
1974 struct GNUNET_CONFIGURATION_Handle *diff;
1975
1976 ac->timeout_task = NULL;
1977 terminate_ac_activities (ac);
1978
1979 /* Send back response */
1980 diff = GNUNET_CONFIGURATION_get_diff (ac->orig,
1981 ac->c);
1982 buf = GNUNET_CONFIGURATION_serialize (diff,
1983 &c_size);
1984 GNUNET_CONFIGURATION_destroy (diff);
1985 env = GNUNET_MQ_msg_extra (arm,
1986 c_size,
1987 GNUNET_MESSAGE_TYPE_NAT_AUTO_CFG_RESULT);
1988 arm->status_code = htonl ((uint32_t) ac->status_code);
1989 arm->type = htonl ((uint32_t) ac->type);
1990 GNUNET_memcpy (&arm[1],
1991 buf,
1992 c_size);
1993 GNUNET_free (buf);
1994 GNUNET_MQ_send (ch->mq,
1995 env);
1996
1997 /* clean up */
1998 GNUNET_free (ac->system_type);
1999 GNUNET_CONFIGURATION_destroy (ac->orig);
2000 GNUNET_CONFIGURATION_destroy (ac->c);
2001 GNUNET_CONTAINER_DLL_remove (ac_head,
2002 ac_tail,
2003 ac);
2004 GNUNET_free (ac);
2005 GNUNET_SERVICE_client_continue (ch->client);
2006}
2007
2008
2009/**
2010 * Check if all autoconfiguration operations have concluded,
2011 * and if they have, send the result back to the client.
2012 *
2013 * @param ac autoconfiguation context to check
2014 */
2015static void
2016check_autoconfig_finished (struct AutoconfigContext *ac)
2017{
2018 if (NULL != ac->probe_external)
2019 return;
2020 GNUNET_SCHEDULER_cancel (ac->timeout_task);
2021 ac->timeout_task
2022 = GNUNET_SCHEDULER_add_now (&conclude_autoconfig_request,
2023 ac);
2024}
2025
2026
2027/**
2028 * Update ENABLE_UPNPC configuration option.
2029 *
2030 * @param ac autoconfiguration to update
2031 */
2032static void
2033update_enable_upnpc_option (struct AutoconfigContext *ac)
2034{
2035 switch (ac->enable_upnpc)
2036 {
2037 case GNUNET_YES:
2038 GNUNET_CONFIGURATION_set_value_string (ac->c,
2039 "NAT",
2040 "ENABLE_UPNP",
2041 "YES");
2042 break;
2043 case GNUNET_NO:
2044 GNUNET_CONFIGURATION_set_value_string (ac->c,
2045 "NAT",
2046 "ENABLE_UPNP",
2047 "NO");
2048 break;
2049 case GNUNET_SYSERR:
2050 /* We are unsure, do not change option */
2051 break;
2052 }
2053}
2054
2055
2056/**
2057 * Handle result from external IP address probe during
2058 * autoconfiguration.
2059 *
2060 * @param cls our `struct AutoconfigContext`
2061 * @param addr the address, NULL on errors
2062 * @param result #GNUNET_NAT_ERROR_SUCCESS on success, otherwise the specific error code
2063 */
2064static void
2065auto_external_result_cb (void *cls,
2066 const struct in_addr *addr,
2067 enum GNUNET_NAT_StatusCode result)
2068{
2069 struct AutoconfigContext *ac = cls;
2070
2071 ac->probe_external = NULL;
2072 switch (result)
2073 {
2074 case GNUNET_NAT_ERROR_SUCCESS:
2075 ac->enable_upnpc = GNUNET_YES;
2076 break;
2077 case GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_OUTPUT_INVALID:
2078 case GNUNET_NAT_ERROR_EXTERNAL_IP_ADDRESS_INVALID:
2079 case GNUNET_NAT_ERROR_IPC_FAILURE:
2080 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2081 "Disabling UPNPC: %d\n",
2082 (int) result);
2083 ac->enable_upnpc = GNUNET_NO; /* did not work */
2084 break;
2085 default:
2086 GNUNET_break (0); /* unexpected */
2087 ac->enable_upnpc = GNUNET_SYSERR;
2088 break;
2089 }
2090 update_enable_upnpc_option (ac);
2091 check_autoconfig_finished (ac);
2092}
2093
2094
2095/**
2096 * Handler for #GNUNET_MESSAGE_TYPE_NAT_REQUEST_AUTO_CFG message from
2097 * client.
2098 *
2099 * @param cls client who sent the message
2100 * @param message the message received
2101 */
2102static void
2103handle_autoconfig_request (void *cls,
2104 const struct GNUNET_NAT_AutoconfigRequestMessage *message)
2105{
2106 struct ClientHandle *ch = cls;
2107 size_t left = ntohs (message->header.size) - sizeof (*message);
2108 struct LocalAddressList *lal;
2109 struct AutoconfigContext *ac;
2110
2111 ac = GNUNET_new (struct AutoconfigContext);
2112 ac->status_code = GNUNET_NAT_ERROR_SUCCESS;
2113 ac->ch = ch;
2114 ac->c = GNUNET_CONFIGURATION_create ();
2115 if (GNUNET_OK !=
2116 GNUNET_CONFIGURATION_deserialize (ac->c,
2117 (const char *) &message[1],
2118 left,
2119 GNUNET_NO))
2120 {
2121 GNUNET_break (0);
2122 GNUNET_SERVICE_client_drop (ch->client);
2123 GNUNET_CONFIGURATION_destroy (ac->c);
2124 GNUNET_free (ac);
2125 return;
2126 }
2127 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2128 "Received REQUEST_AUTO_CONFIG message from client\n");
2129
2130 if (GNUNET_OK !=
2131 GNUNET_CONFIGURATION_get_value_string (ac->c,
2132 "PEER",
2133 "SYSTEM_TYPE",
2134 &ac->system_type))
2135 ac->system_type = GNUNET_strdup ("UNKNOWN");
2136
2137 GNUNET_CONTAINER_DLL_insert (ac_head,
2138 ac_tail,
2139 ac);
2140 ac->orig
2141 = GNUNET_CONFIGURATION_dup (ac->c);
2142 ac->timeout_task
2143 = GNUNET_SCHEDULER_add_delayed (AUTOCONFIG_TIMEOUT,
2144 &conclude_autoconfig_request,
2145 ac);
2146 ac->enable_upnpc = GNUNET_SYSERR; /* undecided */
2147
2148 /* Probe for upnpc */
2149 if (GNUNET_SYSERR ==
2150 GNUNET_OS_check_helper_binary ("upnpc",
2151 GNUNET_NO,
2152 NULL))
2153 {
2154 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2155 _("UPnP client `upnpc` command not found, disabling UPnP\n"));
2156 ac->enable_upnpc = GNUNET_NO;
2157 }
2158 else
2159 {
2160 for (lal = lal_head; NULL != lal; lal = lal->next)
2161 if (GNUNET_NAT_AC_LAN == (lal->ac & GNUNET_NAT_AC_LAN))
2162 /* we are behind NAT, useful to try upnpc */
2163 ac->enable_upnpc = GNUNET_YES;
2164 }
2165 if (GNUNET_YES == ac->enable_upnpc)
2166 {
2167 /* If we are a mobile device, always leave it on as the network
2168 may change to one that supports UPnP anytime. If we are
2169 stationary, check if our network actually supports UPnP, and if
2170 not, disable it. */
2171 if ( (0 == strcasecmp (ac->system_type,
2172 "INFRASTRUCTURE")) ||
2173 (0 == strcasecmp (ac->system_type,
2174 "DESKTOP")) )
2175 {
2176 /* Check if upnpc gives us an external IP */
2177 ac->probe_external
2178 = GNUNET_NAT_mini_get_external_ipv4_ (&auto_external_result_cb,
2179 ac);
2180 }
2181 }
2182 if (NULL == ac->probe_external)
2183 update_enable_upnpc_option (ac);
2184
2185 /* Finally, check if we are already done */
2186 check_autoconfig_finished (ac);
2187}
2188
2189
2190/**
2191 * Task run during shutdown. 1849 * Task run during shutdown.
2192 * 1850 *
2193 * @param cls unused 1851 * @param cls unused
@@ -2196,16 +1854,7 @@ static void
2196shutdown_task (void *cls) 1854shutdown_task (void *cls)
2197{ 1855{
2198 struct StunExternalIP *se; 1856 struct StunExternalIP *se;
2199 struct AutoconfigContext *ac;
2200 1857
2201 while (NULL != (ac = ac_head))
2202 {
2203 GNUNET_CONTAINER_DLL_remove (ac_head,
2204 ac_tail,
2205 ac);
2206 terminate_ac_activities (ac);
2207 GNUNET_free (ac);
2208 }
2209 while (NULL != (se = se_head)) 1858 while (NULL != (se = se_head))
2210 { 1859 {
2211 GNUNET_CONTAINER_DLL_remove (se_head, 1860 GNUNET_CONTAINER_DLL_remove (se_head,
@@ -2386,10 +2035,6 @@ GNUNET_SERVICE_MAIN
2386 GNUNET_MESSAGE_TYPE_NAT_REQUEST_CONNECTION_REVERSAL, 2035 GNUNET_MESSAGE_TYPE_NAT_REQUEST_CONNECTION_REVERSAL,
2387 struct GNUNET_NAT_RequestConnectionReversalMessage, 2036 struct GNUNET_NAT_RequestConnectionReversalMessage,
2388 NULL), 2037 NULL),
2389 GNUNET_MQ_hd_var_size (autoconfig_request,
2390 GNUNET_MESSAGE_TYPE_NAT_REQUEST_AUTO_CFG,
2391 struct GNUNET_NAT_AutoconfigRequestMessage,
2392 NULL),
2393 GNUNET_MQ_handler_end ()); 2038 GNUNET_MQ_handler_end ());
2394 2039
2395 2040
diff --git a/src/nat/nat.conf.in b/src/nat/nat.conf.in
index 304db3c15..88975c424 100644
--- a/src/nat/nat.conf.in
+++ b/src/nat/nat.conf.in
@@ -67,8 +67,3 @@ STUN_SERVERS = stun.gnunet.org stun.services.mozilla.com:3478 stun.ekiga.net:347
67# After how long do we consider STUN data stale? 67# After how long do we consider STUN data stale?
68STUN_STALE = 60 min 68STUN_STALE = 60 min
69 69
70
71[gnunet-nat-server]
72HOSTNAME = gnunet.org
73PORT = 5724
74NOARMBIND = YES
diff --git a/src/nat/nat.h b/src/nat/nat.h
index 02bae71e9..d34900bd1 100644
--- a/src/nat/nat.h
+++ b/src/nat/nat.h
@@ -224,45 +224,6 @@ struct GNUNET_NAT_AddressChangeNotificationMessage
224}; 224};
225 225
226 226
227/**
228 * Client requesting automatic configuration.
229 */
230struct GNUNET_NAT_AutoconfigRequestMessage
231{
232 /**
233 * Header with type #GNUNET_MESSAGE_TYPE_NAT_REQUEST_AUTO_CFG
234 */
235 struct GNUNET_MessageHeader header;
236
237 /* Followed by configuration (diff, serialized, compressed) */
238
239};
240
241
242/**
243 * Service responding with proposed configuration.
244 */
245struct GNUNET_NAT_AutoconfigResultMessage
246{
247 /**
248 * Header with type #GNUNET_MESSAGE_TYPE_NAT_AUTO_CFG_RESULT
249 */
250 struct GNUNET_MessageHeader header;
251
252 /**
253 * An `enum GNUNET_NAT_StatusCode` in NBO.
254 */
255 int32_t status_code GNUNET_PACKED;
256
257 /**
258 * An `enum GNUNET_NAT_Type` in NBO.
259 */
260 int32_t type GNUNET_PACKED;
261
262 /* Followed by configuration (diff, serialized, compressed) */
263};
264
265
266GNUNET_NETWORK_STRUCT_END 227GNUNET_NETWORK_STRUCT_END
267 228
268#endif 229#endif
diff --git a/src/nat/nat_api_auto.c b/src/nat/nat_api_auto.c
deleted file mode 100644
index c5c5fa67a..000000000
--- a/src/nat/nat_api_auto.c
+++ /dev/null
@@ -1,274 +0,0 @@
1
2/*
3 This file is part of GNUnet.
4 Copyright (C) 2007-2016 GNUnet e.V.
5
6 GNUnet is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published
8 by the Free Software Foundation; either version 3, or (at your
9 option) any later version.
10
11 GNUnet is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNUnet; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 Boston, MA 02110-1301, USA.
20*/
21
22/**
23 * @author Christian Grothoff
24 * @author Milan Bouchet-Valat
25 *
26 * @file nat/nat_api_auto.c
27 * Routines for NAT auto configuration.
28 */
29#include "platform.h"
30#include "gnunet_nat_service.h"
31#include "nat.h"
32#include "nat_stun.h"
33
34
35
36/**
37 * Handle to auto-configuration in progress.
38 */
39struct GNUNET_NAT_AutoHandle
40{
41
42 /**
43 * Configuration we use.
44 */
45 const struct GNUNET_CONFIGURATION_Handle *cfg;
46
47 /**
48 * Message queue for communicating with the NAT service.
49 */
50 struct GNUNET_MQ_Handle *mq;
51
52 /**
53 * Function called with the result from the autoconfiguration.
54 */
55 GNUNET_NAT_AutoResultCallback arc;
56
57 /**
58 * Closure for @e arc.
59 */
60 void *arc_cls;
61
62};
63
64
65/**
66 * Converts `enum GNUNET_NAT_StatusCode` to string
67 *
68 * @param err error code to resolve to a string
69 * @return point to a static string containing the error code
70 */
71const char *
72GNUNET_NAT_status2string (enum GNUNET_NAT_StatusCode err)
73{
74 switch (err)
75 {
76 case GNUNET_NAT_ERROR_SUCCESS:
77 return _ ("Operation Successful");
78 case GNUNET_NAT_ERROR_IPC_FAILURE:
79 return _ ("IPC failure");
80 case GNUNET_NAT_ERROR_INTERNAL_NETWORK_ERROR:
81 return _ ("Failure in network subsystem, check permissions.");
82 case GNUNET_NAT_ERROR_TIMEOUT:
83 return _ ("Encountered timeout while performing operation");
84 case GNUNET_NAT_ERROR_NOT_ONLINE:
85 return _ ("detected that we are offline");
86 case GNUNET_NAT_ERROR_UPNPC_NOT_FOUND:
87 return _ ("`upnpc` command not found");
88 case GNUNET_NAT_ERROR_UPNPC_FAILED:
89 return _ ("Failed to run `upnpc` command");
90 case GNUNET_NAT_ERROR_UPNPC_TIMEOUT:
91 return _ ("`upnpc' command took too long, process killed");
92 case GNUNET_NAT_ERROR_UPNPC_PORTMAP_FAILED:
93 return _ ("`upnpc' command failed to establish port mapping");
94 case GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_NOT_FOUND:
95 return _ ("`external-ip' command not found");
96 case GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_FAILED:
97 return _ ("Failed to run `external-ip` command");
98 case GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_OUTPUT_INVALID:
99 return _ ("`external-ip' command output invalid");
100 case GNUNET_NAT_ERROR_EXTERNAL_IP_ADDRESS_INVALID:
101 return _ ("no valid address was returned by `external-ip'");
102 case GNUNET_NAT_ERROR_NO_VALID_IF_IP_COMBO:
103 return _ ("Could not determine interface with internal/local network address");
104 case GNUNET_NAT_ERROR_HELPER_NAT_SERVER_NOT_FOUND:
105 return _ ("No functioning gnunet-helper-nat-server installation found");
106 case GNUNET_NAT_ERROR_NAT_TEST_START_FAILED:
107 return _ ("NAT test could not be initialized");
108 case GNUNET_NAT_ERROR_NAT_TEST_TIMEOUT:
109 return _ ("NAT test timeout reached");
110 case GNUNET_NAT_ERROR_NAT_REGISTER_FAILED:
111 return _ ("could not register NAT");
112 case GNUNET_NAT_ERROR_HELPER_NAT_CLIENT_NOT_FOUND:
113 return _ ("No working gnunet-helper-nat-client installation found");
114 default:
115 return "unknown status code";
116 }
117}
118
119
120/**
121 * Check result from autoconfiguration attempt.
122 *
123 * @param cls the `struct GNUNET_NAT_AutoHandle`
124 * @param res the result
125 * @return #GNUNET_OK if @a res is well-formed (always for now)
126 */
127static int
128check_auto_result (void *cls,
129 const struct GNUNET_NAT_AutoconfigResultMessage *res)
130{
131 return GNUNET_OK;
132}
133
134
135/**
136 * Handle result from autoconfiguration attempt.
137 *
138 * @param cls the `struct GNUNET_NAT_AutoHandle`
139 * @param res the result
140 */
141static void
142handle_auto_result (void *cls,
143 const struct GNUNET_NAT_AutoconfigResultMessage *res)
144{
145 struct GNUNET_NAT_AutoHandle *ah = cls;
146 size_t left;
147 struct GNUNET_CONFIGURATION_Handle *cfg;
148 enum GNUNET_NAT_Type type
149 = (enum GNUNET_NAT_Type) ntohl (res->type);
150 enum GNUNET_NAT_StatusCode status
151 = (enum GNUNET_NAT_StatusCode) ntohl (res->status_code);
152
153 left = ntohs (res->header.size) - sizeof (*res);
154 cfg = GNUNET_CONFIGURATION_create ();
155 if (GNUNET_OK !=
156 GNUNET_CONFIGURATION_deserialize (cfg,
157 (const char *) &res[1],
158 left,
159 GNUNET_NO))
160 {
161 GNUNET_break (0);
162 ah->arc (ah->arc_cls,
163 NULL,
164 GNUNET_NAT_ERROR_IPC_FAILURE,
165 type);
166 }
167 else
168 {
169 ah->arc (ah->arc_cls,
170 cfg,
171 status,
172 type);
173 }
174 GNUNET_CONFIGURATION_destroy (cfg);
175 GNUNET_NAT_autoconfig_cancel (ah);
176}
177
178
179/**
180 * Handle queue errors by reporting autoconfiguration failure.
181 *
182 * @param cls the `struct GNUNET_NAT_AutoHandle *`
183 * @param error details about the error
184 */
185static void
186ah_error_handler (void *cls,
187 enum GNUNET_MQ_Error error)
188{
189 struct GNUNET_NAT_AutoHandle *ah = cls;
190
191 ah->arc (ah->arc_cls,
192 NULL,
193 GNUNET_NAT_ERROR_IPC_FAILURE,
194 GNUNET_NAT_TYPE_UNKNOWN);
195 GNUNET_NAT_autoconfig_cancel (ah);
196}
197
198
199/**
200 * Start auto-configuration routine. The transport adapters should
201 * be stopped while this function is called.
202 *
203 * @param cfg initial configuration
204 * @param cb function to call with autoconfiguration result
205 * @param cb_cls closure for @a cb
206 * @return handle to cancel operation
207 */
208struct GNUNET_NAT_AutoHandle *
209GNUNET_NAT_autoconfig_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
210 GNUNET_NAT_AutoResultCallback cb,
211 void *cb_cls)
212{
213 struct GNUNET_NAT_AutoHandle *ah = GNUNET_new (struct GNUNET_NAT_AutoHandle);
214 struct GNUNET_MQ_MessageHandler handlers[] = {
215 GNUNET_MQ_hd_var_size (auto_result,
216 GNUNET_MESSAGE_TYPE_NAT_AUTO_CFG_RESULT,
217 struct GNUNET_NAT_AutoconfigResultMessage,
218 ah),
219 GNUNET_MQ_handler_end ()
220 };
221 struct GNUNET_MQ_Envelope *env;
222 struct GNUNET_NAT_AutoconfigRequestMessage *req;
223 char *buf;
224 size_t size;
225
226 buf = GNUNET_CONFIGURATION_serialize (cfg,
227 &size);
228 if (size > GNUNET_SERVER_MAX_MESSAGE_SIZE - sizeof (*req))
229 {
230 GNUNET_break (0);
231 GNUNET_free (buf);
232 GNUNET_free (ah);
233 return NULL;
234 }
235 ah->arc = cb;
236 ah->arc_cls = cb_cls;
237 ah->mq = GNUNET_CLIENT_connecT (cfg,
238 "nat",
239 handlers,
240 &ah_error_handler,
241 ah);
242 if (NULL == ah->mq)
243 {
244 GNUNET_break (0);
245 GNUNET_free (buf);
246 GNUNET_free (ah);
247 return NULL;
248 }
249 env = GNUNET_MQ_msg_extra (req,
250 size,
251 GNUNET_MESSAGE_TYPE_NAT_REQUEST_AUTO_CFG);
252 GNUNET_memcpy (&req[1],
253 buf,
254 size);
255 GNUNET_free (buf);
256 GNUNET_MQ_send (ah->mq,
257 env);
258 return ah;
259}
260
261
262/**
263 * Abort autoconfiguration.
264 *
265 * @param ah handle for operation to abort
266 */
267void
268GNUNET_NAT_autoconfig_cancel (struct GNUNET_NAT_AutoHandle *ah)
269{
270 GNUNET_MQ_destroy (ah->mq);
271 GNUNET_free (ah);
272}
273
274/* end of nat_api_auto.c */
diff --git a/src/nat/nat_api_test.c b/src/nat/nat_api_test.c
deleted file mode 100644
index d47c14094..000000000
--- a/src/nat/nat_api_test.c
+++ /dev/null
@@ -1,644 +0,0 @@
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
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 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 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20/**
21 * @file nat/nat_api_test.c
22 * @brief functions to test if the NAT configuration is successful at achieving NAT traversal (with the help of a gnunet-nat-server)
23 * @author Christian Grothoff
24 */
25#include "platform.h"
26#include "gnunet_util_lib.h"
27#include "gnunet_nat_lib.h"
28#include "nat.h"
29
30#define LOG(kind,...) GNUNET_log_from (kind, "nat", __VA_ARGS__)
31
32#define NAT_SERVER_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
33
34/**
35 * Entry we keep for each incoming connection.
36 */
37struct NatActivity
38{
39 /**
40 * This is a doubly-linked list.
41 */
42 struct NatActivity *next;
43
44 /**
45 * This is a doubly-linked list.
46 */
47 struct NatActivity *prev;
48
49 /**
50 * Socket of the incoming connection.
51 */
52 struct GNUNET_NETWORK_Handle *sock;
53
54 /**
55 * Handle of the master context.
56 */
57 struct GNUNET_NAT_Test *h;
58
59 /**
60 * Task reading from the incoming connection.
61 */
62 struct GNUNET_SCHEDULER_Task *rtask;
63};
64
65
66/**
67 * Entry we keep for each connection to the gnunet-nat-service.
68 */
69struct ClientActivity
70{
71 /**
72 * This is a doubly-linked list.
73 */
74 struct ClientActivity *next;
75
76 /**
77 * This is a doubly-linked list.
78 */
79 struct ClientActivity *prev;
80
81 /**
82 * Socket of the incoming connection.
83 */
84 struct GNUNET_MQ_Handle *mq;
85
86 /**
87 * Handle to overall NAT test.
88 */
89 struct GNUNET_NAT_Test *h;
90
91};
92
93
94/**
95 * Handle to a NAT test.
96 */
97struct GNUNET_NAT_Test
98{
99
100 /**
101 * Configuration used
102 */
103 const struct GNUNET_CONFIGURATION_Handle *cfg;
104
105 /**
106 * Function to call with success report
107 */
108 GNUNET_NAT_TestCallback report;
109
110 /**
111 * Closure for @e report.
112 */
113 void *report_cls;
114
115 /**
116 * Handle to NAT traversal in use
117 */
118 struct GNUNET_NAT_Handle *nat;
119
120 /**
121 * Handle to listen socket, or NULL
122 */
123 struct GNUNET_NETWORK_Handle *lsock;
124
125 /**
126 * Head of list of nat activities.
127 */
128 struct NatActivity *na_head;
129
130 /**
131 * Tail of list of nat activities.
132 */
133 struct NatActivity *na_tail;
134
135 /**
136 * Head of list of client activities.
137 */
138 struct ClientActivity *ca_head;
139
140 /**
141 * Tail of list of client activities.
142 */
143 struct ClientActivity *ca_tail;
144
145 /**
146 * Identity of task for the listen socket (if any)
147 */
148 struct GNUNET_SCHEDULER_Task *ltask;
149
150 /**
151 * Task identifier for the timeout (if any)
152 */
153 struct GNUNET_SCHEDULER_Task *ttask;
154
155 /**
156 * #GNUNET_YES if we're testing TCP
157 */
158 int is_tcp;
159
160 /**
161 * Data that should be transmitted or source-port.
162 */
163 uint16_t data;
164
165 /**
166 * Advertised port to the other peer.
167 */
168 uint16_t adv_port;
169
170 /**
171 * Status code to be reported to the timeout/status call
172 */
173 enum GNUNET_NAT_StatusCode status;
174};
175
176
177/**
178 * Function called from #GNUNET_NAT_register whenever someone asks us
179 * to do connection reversal.
180 *
181 * @param cls closure, our `struct GNUNET_NAT_Handle`
182 * @param addr public IP address of the other peer
183 * @param addrlen actual lenght of the @a addr
184 */
185static void
186reversal_cb (void *cls,
187 const struct sockaddr *addr,
188 socklen_t addrlen)
189{
190 struct GNUNET_NAT_Test *h = cls;
191 const struct sockaddr_in *sa;
192
193 if (sizeof (struct sockaddr_in) != addrlen)
194 return;
195 sa = (const struct sockaddr_in *) addr;
196 if (h->data != sa->sin_port)
197 {
198 LOG (GNUNET_ERROR_TYPE_DEBUG,
199 "Received connection reversal request for wrong port\n");
200 return; /* wrong port */
201 }
202 /* report success */
203 h->report (h->report_cls,
204 GNUNET_NAT_ERROR_SUCCESS);
205}
206
207
208/**
209 * Activity on our incoming socket. Read data from the
210 * incoming connection.
211 *
212 * @param cls the `struct GNUNET_NAT_Test`
213 */
214static void
215do_udp_read (void *cls)
216{
217 struct GNUNET_NAT_Test *tst = cls;
218 uint16_t data;
219 const struct GNUNET_SCHEDULER_TaskContext *tc;
220
221 tc = GNUNET_SCHEDULER_get_task_context ();
222 tst->ltask =
223 GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
224 tst->lsock,
225 &do_udp_read,
226 tst);
227 if ((NULL != tc->write_ready) &&
228 (GNUNET_NETWORK_fdset_isset (tc->read_ready,
229 tst->lsock)) &&
230 (sizeof (data) ==
231 GNUNET_NETWORK_socket_recv (tst->lsock,
232 &data,
233 sizeof (data))))
234 {
235 if (data == tst->data)
236 tst->report (tst->report_cls,
237 GNUNET_NAT_ERROR_SUCCESS);
238 else
239 LOG (GNUNET_ERROR_TYPE_DEBUG,
240 "Received data mismatches expected value\n");
241 }
242 else
243 LOG (GNUNET_ERROR_TYPE_DEBUG,
244 "Failed to receive data from inbound connection\n");
245}
246
247
248/**
249 * Activity on our incoming socket. Read data from the
250 * incoming connection.
251 *
252 * @param cls the `struct NatActivity`
253 */
254static void
255do_read (void *cls)
256{
257 struct NatActivity *na = cls;
258 struct GNUNET_NAT_Test *tst;
259 uint16_t data;
260 const struct GNUNET_SCHEDULER_TaskContext *tc;
261
262 tc = GNUNET_SCHEDULER_get_task_context ();
263 na->rtask = NULL;
264 tst = na->h;
265 GNUNET_CONTAINER_DLL_remove (tst->na_head,
266 tst->na_tail,
267 na);
268 if ((NULL != tc->write_ready) &&
269 (GNUNET_NETWORK_fdset_isset (tc->read_ready,
270 na->sock)) &&
271 (sizeof (data) ==
272 GNUNET_NETWORK_socket_recv (na->sock,
273 &data,
274 sizeof (data))))
275 {
276 if (data == tst->data)
277 tst->report (tst->report_cls,
278 GNUNET_NAT_ERROR_SUCCESS);
279 else
280 LOG (GNUNET_ERROR_TYPE_DEBUG,
281 "Received data does not match expected value\n");
282 }
283 else
284 LOG (GNUNET_ERROR_TYPE_DEBUG,
285 "Failed to receive data from inbound connection\n");
286 GNUNET_NETWORK_socket_close (na->sock);
287 GNUNET_free (na);
288}
289
290
291/**
292 * Activity on our listen socket. Accept the
293 * incoming connection.
294 *
295 * @param cls the `struct GNUNET_NAT_Test`
296 */
297static void
298do_accept (void *cls)
299{
300 struct GNUNET_NAT_Test *tst = cls;
301 struct GNUNET_NETWORK_Handle *s;
302 struct NatActivity *wl;
303
304 tst->ltask = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
305 tst->lsock,
306 &do_accept,
307 tst);
308 s = GNUNET_NETWORK_socket_accept (tst->lsock,
309 NULL,
310 NULL);
311 if (NULL == s)
312 {
313 GNUNET_log_strerror (GNUNET_ERROR_TYPE_INFO,
314 "accept");
315 return; /* odd error */
316 }
317 LOG (GNUNET_ERROR_TYPE_DEBUG,
318 "Got an inbound connection, waiting for data\n");
319 wl = GNUNET_new (struct NatActivity);
320 wl->sock = s;
321 wl->h = tst;
322 wl->rtask =
323 GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
324 wl->sock,
325 &do_read,
326 wl);
327 GNUNET_CONTAINER_DLL_insert (tst->na_head,
328 tst->na_tail,
329 wl);
330}
331
332
333/**
334 * We got disconnected from the NAT server. Stop
335 * waiting for a reply.
336 *
337 * @param cls the `struct ClientActivity`
338 * @param error error code
339 */
340static void
341mq_error_handler (void *cls,
342 enum GNUNET_MQ_Error error)
343{
344 struct ClientActivity *ca = cls;
345 struct GNUNET_NAT_Test *tst = ca->h;
346
347 GNUNET_CONTAINER_DLL_remove (tst->ca_head,
348 tst->ca_tail,
349 ca);
350 GNUNET_MQ_destroy (ca->mq);
351 GNUNET_free (ca);
352}
353
354
355/**
356 * Address-callback, used to send message to gnunet-nat-server.
357 *
358 * @param cls closure
359 * @param add_remove #GNUNET_YES to mean the new public IP address, #GNUNET_NO to mean
360 * the previous (now invalid) one
361 * @param addr either the previous or the new public IP address
362 * @param addrlen actual length of the @a addr
363 */
364static void
365addr_cb (void *cls,
366 int add_remove,
367 const struct sockaddr *addr,
368 socklen_t addrlen)
369{
370 struct GNUNET_NAT_Test *h = cls;
371 struct ClientActivity *ca;
372 struct GNUNET_MQ_Envelope *env;
373 struct GNUNET_NAT_TestMessage *msg;
374 const struct sockaddr_in *sa;
375
376 if (GNUNET_YES != add_remove)
377 return;
378 if (addrlen != sizeof (struct sockaddr_in))
379 {
380 LOG (GNUNET_ERROR_TYPE_DEBUG,
381 "NAT test ignores IPv6 address `%s' returned from NAT library\n",
382 GNUNET_a2s (addr,
383 addrlen));
384 return; /* ignore IPv6 here */
385 }
386 LOG (GNUNET_ERROR_TYPE_INFO,
387 "Asking gnunet-nat-server to connect to `%s'\n",
388 GNUNET_a2s (addr,
389 addrlen));
390
391 ca = GNUNET_new (struct ClientActivity);
392 ca->h = h;
393 ca->mq = GNUNET_CLIENT_connecT (h->cfg,
394 "gnunet-nat-server",
395 NULL,
396 &mq_error_handler,
397 ca);
398 if (NULL == ca->mq)
399 {
400 GNUNET_free (ca);
401 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
402 _("Failed to connect to `gnunet-nat-server'\n"));
403 return;
404 }
405 GNUNET_CONTAINER_DLL_insert (h->ca_head,
406 h->ca_tail,
407 ca);
408 sa = (const struct sockaddr_in *) addr;
409 env = GNUNET_MQ_msg (msg,
410 GNUNET_MESSAGE_TYPE_NAT_TEST);
411 msg->dst_ipv4 = sa->sin_addr.s_addr;
412 msg->dport = sa->sin_port;
413 msg->data = h->data;
414 msg->is_tcp = htonl ((uint32_t) h->is_tcp);
415 GNUNET_MQ_send (ca->mq,
416 env);
417}
418
419
420/**
421 * Timeout task for a nat test.
422 * Calls the report-callback with a timeout return value
423 *
424 * Destroys the nat handle after the callback has been processed.
425 *
426 * @param cls handle to the timed out NAT test
427 */
428static void
429do_timeout (void *cls)
430{
431 struct GNUNET_NAT_Test *nh = cls;
432
433 nh->ttask = NULL;
434 nh->report (nh->report_cls,
435 (GNUNET_NAT_ERROR_SUCCESS == nh->status)
436 ? GNUNET_NAT_ERROR_TIMEOUT
437 : nh->status);
438}
439
440
441/**
442 * Start testing if NAT traversal works using the
443 * given configuration (IPv4-only).
444 *
445 * ALL failures are reported directly to the report callback
446 *
447 * @param cfg configuration for the NAT traversal
448 * @param is_tcp #GNUNET_YES to test TCP, #GNUNET_NO to test UDP
449 * @param bnd_port port to bind to, 0 for connection reversal
450 * @param adv_port externally advertised port to use
451 * @param timeout delay after which the test should be aborted
452 * @param report function to call with the result of the test
453 * @param report_cls closure for @a report
454 * @return handle to cancel NAT test or NULL. The error is always indicated via the report callback
455 */
456struct GNUNET_NAT_Test *
457GNUNET_NAT_test_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
458 int is_tcp,
459 uint16_t bnd_port,
460 uint16_t adv_port,
461 struct GNUNET_TIME_Relative timeout,
462 GNUNET_NAT_TestCallback report,
463 void *report_cls)
464{
465 struct GNUNET_NAT_Test *nh;
466 struct sockaddr_in sa;
467 const struct sockaddr *addrs[] = {
468 (const struct sockaddr *) &sa
469 };
470 const socklen_t addrlens[] = {
471 sizeof (sa)
472 };
473
474 memset (&sa, 0, sizeof (sa));
475 sa.sin_family = AF_INET;
476 sa.sin_port = htons (bnd_port);
477#if HAVE_SOCKADDR_IN_SIN_LEN
478 sa.sin_len = sizeof (sa);
479#endif
480
481 nh = GNUNET_new (struct GNUNET_NAT_Test);
482 nh->cfg = cfg;
483 nh->is_tcp = is_tcp;
484 nh->data = bnd_port;
485 nh->adv_port = adv_port;
486 nh->report = report;
487 nh->report_cls = report_cls;
488 nh->status = GNUNET_NAT_ERROR_SUCCESS;
489 if (0 == bnd_port)
490 {
491 nh->nat
492 = GNUNET_NAT_register (cfg,
493 is_tcp,
494 0,
495 0,
496 NULL,
497 NULL,
498 &addr_cb,
499 &reversal_cb,
500 nh,
501 NULL);
502 }
503 else
504 {
505 nh->lsock =
506 GNUNET_NETWORK_socket_create (AF_INET,
507 (is_tcp ==
508 GNUNET_YES) ? SOCK_STREAM : SOCK_DGRAM,
509 0);
510 if ((nh->lsock == NULL) ||
511 (GNUNET_OK !=
512 GNUNET_NETWORK_socket_bind (nh->lsock,
513 (const struct sockaddr *) &sa,
514 sizeof (sa))))
515 {
516 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
517 _("Failed to create listen socket bound to `%s' for NAT test: %s\n"),
518 GNUNET_a2s ((const struct sockaddr *) &sa,
519 sizeof (sa)),
520 STRERROR (errno));
521 if (NULL != nh->lsock)
522 {
523 GNUNET_NETWORK_socket_close (nh->lsock);
524 nh->lsock = NULL;
525 }
526 nh->status = GNUNET_NAT_ERROR_INTERNAL_NETWORK_ERROR;
527 nh->ttask = GNUNET_SCHEDULER_add_now (&do_timeout,
528 nh);
529 return nh;
530 }
531 if (GNUNET_YES == is_tcp)
532 {
533 GNUNET_break (GNUNET_OK ==
534 GNUNET_NETWORK_socket_listen (nh->lsock,
535 5));
536 nh->ltask =
537 GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
538 nh->lsock,
539 &do_accept,
540 nh);
541 }
542 else
543 {
544 nh->ltask =
545 GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
546 nh->lsock,
547 &do_udp_read,
548 nh);
549 }
550 LOG (GNUNET_ERROR_TYPE_INFO,
551 "NAT test listens on port %u (%s)\n",
552 bnd_port,
553 (GNUNET_YES == is_tcp) ? "tcp" : "udp");
554 nh->nat = GNUNET_NAT_register (cfg,
555 is_tcp,
556 adv_port,
557 1,
558 addrs,
559 addrlens,
560 &addr_cb,
561 NULL,
562 nh,
563 NULL);
564 if (NULL == nh->nat)
565 {
566 LOG (GNUNET_ERROR_TYPE_INFO,
567 _("NAT test failed to start NAT library\n"));
568 if (NULL != nh->ltask)
569 {
570 GNUNET_SCHEDULER_cancel (nh->ltask);
571 nh->ltask = NULL;
572 }
573 if (NULL != nh->lsock)
574 {
575 GNUNET_NETWORK_socket_close (nh->lsock);
576 nh->lsock = NULL;
577 }
578 nh->status = GNUNET_NAT_ERROR_NAT_REGISTER_FAILED;
579 nh->ttask = GNUNET_SCHEDULER_add_now (&do_timeout,
580 nh);
581 return nh;
582 }
583 }
584 nh->ttask = GNUNET_SCHEDULER_add_delayed (timeout,
585 &do_timeout,
586 nh);
587 return nh;
588}
589
590
591/**
592 * Stop an active NAT test.
593 *
594 * @param tst test to stop.
595 */
596void
597GNUNET_NAT_test_stop (struct GNUNET_NAT_Test *tst)
598{
599 struct NatActivity *pos;
600 struct ClientActivity *cpos;
601
602 LOG (GNUNET_ERROR_TYPE_DEBUG,
603 "Stopping NAT test\n");
604 while (NULL != (cpos = tst->ca_head))
605 {
606 GNUNET_CONTAINER_DLL_remove (tst->ca_head,
607 tst->ca_tail,
608 cpos);
609 GNUNET_MQ_destroy (cpos->mq);
610 GNUNET_free (cpos);
611 }
612 while (NULL != (pos = tst->na_head))
613 {
614 GNUNET_CONTAINER_DLL_remove (tst->na_head,
615 tst->na_tail,
616 pos);
617 GNUNET_SCHEDULER_cancel (pos->rtask);
618 GNUNET_NETWORK_socket_close (pos->sock);
619 GNUNET_free (pos);
620 }
621 if (NULL != tst->ttask)
622 {
623 GNUNET_SCHEDULER_cancel (tst->ttask);
624 tst->ttask = NULL;
625 }
626 if (NULL != tst->ltask)
627 {
628 GNUNET_SCHEDULER_cancel (tst->ltask);
629 tst->ltask = NULL;
630 }
631 if (NULL != tst->lsock)
632 {
633 GNUNET_NETWORK_socket_close (tst->lsock);
634 tst->lsock = NULL;
635 }
636 if (NULL != tst->nat)
637 {
638 GNUNET_NAT_unregister (tst->nat);
639 tst->nat = NULL;
640 }
641 GNUNET_free (tst);
642}
643
644/* end of nat_test.c */