diff options
Diffstat (limited to 'src/nat')
-rw-r--r-- | src/nat/Makefile.am | 9 | ||||
-rw-r--r-- | src/nat/gnunet-nat-server.c | 384 | ||||
-rw-r--r-- | src/nat/gnunet-nat.c | 279 | ||||
-rw-r--r-- | src/nat/gnunet-service-nat.c | 355 | ||||
-rw-r--r-- | src/nat/nat.conf.in | 5 | ||||
-rw-r--r-- | src/nat/nat.h | 39 | ||||
-rw-r--r-- | src/nat/nat_api_auto.c | 274 | ||||
-rw-r--r-- | src/nat/nat_api_test.c | 644 |
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: | |||
34 | endif | 34 | endif |
35 | 35 | ||
36 | bin_PROGRAMS = \ | 36 | bin_PROGRAMS = \ |
37 | gnunet-nat-server \ | ||
38 | gnunet-nat | 37 | gnunet-nat |
39 | 38 | ||
40 | libexec_PROGRAMS = \ | 39 | libexec_PROGRAMS = \ |
@@ -42,12 +41,6 @@ libexec_PROGRAMS = \ | |||
42 | gnunet-service-nat | 41 | gnunet-service-nat |
43 | 42 | ||
44 | 43 | ||
45 | gnunet_nat_server_SOURCES = \ | ||
46 | gnunet-nat-server.c nat.h | ||
47 | gnunet_nat_server_LDADD = \ | ||
48 | libgnunetnat.la \ | ||
49 | $(top_builddir)/src/util/libgnunetutil.la | ||
50 | |||
51 | gnunet_helper_nat_server_SOURCES = \ | 44 | gnunet_helper_nat_server_SOURCES = \ |
52 | $(NATSERVER) | 45 | $(NATSERVER) |
53 | 46 | ||
@@ -85,9 +78,7 @@ libgnunetnat_la_LDFLAGS = \ | |||
85 | 78 | ||
86 | libgnunetnatnew_la_SOURCES = \ | 79 | libgnunetnatnew_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 |
92 | libgnunetnatnew_la_LIBADD = \ | 83 | libgnunetnatnew_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 | */ | ||
36 | static struct GNUNET_SERVER_Handle *server; | ||
37 | |||
38 | /** | ||
39 | * Our configuration. | ||
40 | */ | ||
41 | static 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 | */ | ||
51 | static void | ||
52 | try_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 | */ | ||
82 | struct 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 | */ | ||
102 | static void | ||
103 | tcp_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 | */ | ||
132 | static void | ||
133 | try_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 | */ | ||
190 | static void | ||
191 | try_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 | */ | ||
238 | static void | ||
239 | test (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 | */ | ||
272 | static void | ||
273 | shutdown_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 | */ | ||
288 | static void | ||
289 | run (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 | */ | ||
355 | int | ||
356 | main (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 @@ | |||
34 | static int global_ret; | 34 | static int global_ret; |
35 | 35 | ||
36 | /** | 36 | /** |
37 | * Handle to ongoing autoconfiguration. | ||
38 | */ | ||
39 | static 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; | |||
60 | static int use_tcp; | 55 | static int use_tcp; |
61 | 56 | ||
62 | /** | 57 | /** |
63 | * If we do auto-configuration, should we write the result | ||
64 | * to a file? | ||
65 | */ | ||
66 | static int write_cfg; | ||
67 | |||
68 | /** | ||
69 | * Configuration filename. | ||
70 | */ | ||
71 | static const char *cfg_file; | ||
72 | |||
73 | /** | ||
74 | * Original configuration. | ||
75 | */ | ||
76 | static const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
77 | |||
78 | /** | ||
79 | * Protocol to use. | 58 | * Protocol to use. |
80 | */ | 59 | */ |
81 | static uint8_t proto; | 60 | static 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 | */ | ||
87 | static char *bind_addr; | ||
88 | |||
89 | /** | ||
90 | * External IP address and port to use for the test. | ||
91 | * If not set, use #bind_addr. | ||
92 | */ | ||
93 | static 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 | */ |
98 | static char *local_addr; | 65 | static char *local_addr; |
@@ -108,16 +75,6 @@ static char *remote_addr; | |||
108 | static unsigned int do_stun; | 75 | static unsigned int do_stun; |
109 | 76 | ||
110 | /** | 77 | /** |
111 | * Should we run autoconfiguration? | ||
112 | */ | ||
113 | static unsigned int do_auto; | ||
114 | |||
115 | /** | ||
116 | * Handle to a NAT test operation. | ||
117 | */ | ||
118 | static struct GNUNET_NAT_Test *nt; | ||
119 | |||
120 | /** | ||
121 | * Handle to NAT operation. | 78 | * Handle to NAT operation. |
122 | */ | 79 | */ |
123 | static struct GNUNET_NAT_Handle *nh; | 80 | static struct GNUNET_NAT_Handle *nh; |
@@ -140,10 +97,6 @@ static struct GNUNET_SCHEDULER_Task *rtask; | |||
140 | static void | 97 | static void |
141 | test_finished () | 98 | test_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 | */ | ||
163 | static void | ||
164 | auto_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 | */ | ||
191 | static void | ||
192 | auto_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 | */ | ||
298 | static void | ||
299 | test_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, | |||
362 | static void | 161 | static void |
363 | do_shutdown (void *cls) | 162 | do_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 | */ | ||
289 | struct 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 | */ | ||
353 | static struct AutoconfigContext *ac_head; | ||
354 | |||
355 | /** | ||
356 | * DLL of our autoconfiguration operations. | ||
357 | */ | ||
358 | static 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 | */ |
363 | static struct GNUNET_TIME_Relative stun_stale_timeout; | 289 | static 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 | */ | ||
1930 | static int | ||
1931 | check_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 | */ | ||
1943 | static void | ||
1944 | terminate_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 | */ | ||
1965 | static void | ||
1966 | conclude_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 | */ | ||
2015 | static void | ||
2016 | check_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 | */ | ||
2032 | static void | ||
2033 | update_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 | */ | ||
2064 | static void | ||
2065 | auto_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 | */ | ||
2102 | static void | ||
2103 | handle_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 | |||
2196 | shutdown_task (void *cls) | 1854 | shutdown_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? |
68 | STUN_STALE = 60 min | 68 | STUN_STALE = 60 min |
69 | 69 | ||
70 | |||
71 | [gnunet-nat-server] | ||
72 | HOSTNAME = gnunet.org | ||
73 | PORT = 5724 | ||
74 | NOARMBIND = 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 | */ | ||
230 | struct 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 | */ | ||
245 | struct 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 | |||
266 | GNUNET_NETWORK_STRUCT_END | 227 | GNUNET_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 | */ | ||
39 | struct 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 | */ | ||
71 | const char * | ||
72 | GNUNET_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 | */ | ||
127 | static int | ||
128 | check_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 | */ | ||
141 | static void | ||
142 | handle_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 | */ | ||
185 | static void | ||
186 | ah_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 | */ | ||
208 | struct GNUNET_NAT_AutoHandle * | ||
209 | GNUNET_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 | */ | ||
267 | void | ||
268 | GNUNET_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 | */ | ||
37 | struct 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 | */ | ||
69 | struct 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 | */ | ||
97 | struct 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 | */ | ||
185 | static void | ||
186 | reversal_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 | */ | ||
214 | static void | ||
215 | do_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 | */ | ||
254 | static void | ||
255 | do_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 | */ | ||
297 | static void | ||
298 | do_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 | */ | ||
340 | static void | ||
341 | mq_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 | */ | ||
364 | static void | ||
365 | addr_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 | */ | ||
428 | static void | ||
429 | do_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 | */ | ||
456 | struct GNUNET_NAT_Test * | ||
457 | GNUNET_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 | */ | ||
596 | void | ||
597 | GNUNET_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 */ | ||