aboutsummaryrefslogtreecommitdiff
path: root/src
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
parent1b7f6eea0a06abab9b75b30f021aa6313fccfcd4 (diff)
downloadgnunet-80e1315b56f559db60499f5373e90c293c5ab065.tar.gz
gnunet-80e1315b56f559db60499f5373e90c293c5ab065.zip
separate service for autoconfiguration from NAT traversal
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am1
-rw-r--r--src/include/Makefile.am1
-rw-r--r--src/include/gnunet_nat_auto_service.h224
-rw-r--r--src/include/gnunet_nat_service.h407
-rw-r--r--src/include/gnunet_protocols.h2
-rw-r--r--src/nat-auto/.gitignore3
-rw-r--r--src/nat-auto/Makefile.am58
-rw-r--r--src/nat-auto/gnunet-nat-auto.c428
-rw-r--r--src/nat-auto/gnunet-nat-server.c (renamed from src/nat/gnunet-nat-server.c)2
-rw-r--r--src/nat-auto/gnunet-service-nat-auto.c481
-rw-r--r--src/nat-auto/nat-auto.conf.in15
-rw-r--r--src/nat-auto/nat-auto.h110
-rw-r--r--src/nat-auto/nat_auto_api.c (renamed from src/nat/nat_api_auto.c)8
-rw-r--r--src/nat-auto/nat_auto_api_test.c (renamed from src/nat/nat_api_test.c)4
-rw-r--r--src/nat/Makefile.am9
-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
19 files changed, 1459 insertions, 972 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 6925788d5..d04cba9dd 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -85,6 +85,7 @@ SUBDIRS = \
85 template \ 85 template \
86 ats \ 86 ats \
87 nat \ 87 nat \
88 nat-auto \
88 fragmentation \ 89 fragmentation \
89 transport \ 90 transport \
90 ats-tool \ 91 ats-tool \
diff --git a/src/include/Makefile.am b/src/include/Makefile.am
index f27fd6e36..639d3bfd7 100644
--- a/src/include/Makefile.am
+++ b/src/include/Makefile.am
@@ -79,6 +79,7 @@ gnunetinclude_HEADERS = \
79 gnunet_namestore_plugin.h \ 79 gnunet_namestore_plugin.h \
80 gnunet_namestore_service.h \ 80 gnunet_namestore_service.h \
81 gnunet_nat_lib.h \ 81 gnunet_nat_lib.h \
82 gnunet_nat_auto_service.h \
82 gnunet_nat_service.h \ 83 gnunet_nat_service.h \
83 gnunet_nc_lib.h \ 84 gnunet_nc_lib.h \
84 gnunet_network_lib.h \ 85 gnunet_network_lib.h \
diff --git a/src/include/gnunet_nat_auto_service.h b/src/include/gnunet_nat_auto_service.h
new file mode 100644
index 000000000..90115ff8c
--- /dev/null
+++ b/src/include/gnunet_nat_auto_service.h
@@ -0,0 +1,224 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2007-2017 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 * @author Christian Grothoff
23 * @author Milan Bouchet-Valat
24 *
25 * @file
26 * Service for testing and autoconfiguration of
27 * NAT traversal functionality
28 *
29 * @defgroup nat NAT testing library
30 *
31 * @{
32 */
33
34#ifndef GNUNET_NAT_AUTO_SERVICE_H
35#define GNUNET_NAT_AUTO_SERVICE_H
36
37#include "gnunet_util_lib.h"
38
39
40/**
41 * Handle to a NAT test.
42 */
43struct GNUNET_NAT_Test;
44
45
46/**
47 * Function called to report success or failure for
48 * NAT configuration test.
49 *
50 * @param cls closure
51 * @param result #GNUNET_NAT_ERROR_SUCCESS on success, otherwise the specific error code
52 */
53typedef void
54(*GNUNET_NAT_TestCallback) (void *cls,
55 enum GNUNET_NAT_StatusCode result);
56
57
58/**
59 * Handle an incoming STUN message. This function is useful as
60 * some GNUnet service may be listening on a UDP port and might
61 * thus receive STUN messages while trying to receive other data.
62 * In this case, this function can be used to process replies
63 * to STUN requests.
64 *
65 * The function does some basic sanity checks on packet size and
66 * content, try to extract a bit of information.
67 *
68 * At the moment this only processes BIND requests, and returns the
69 * externally visible address of the request to the rest of the
70 * NAT logic.
71 *
72 * @param nh handle to the NAT service
73 * @param sender_addr address from which we got @a data
74 * @param sender_addr_len number of bytes in @a sender_addr
75 * @param data the packet
76 * @param data_size number of bytes in @a data
77 * @return #GNUNET_OK on success
78 * #GNUNET_NO if the packet is not a STUN packet
79 * #GNUNET_SYSERR on internal error handling the packet
80 */
81int
82GNUNET_NAT_stun_handle_packet (struct GNUNET_NAT_Handle *nh,
83 const struct sockaddr *sender_addr,
84 size_t sender_addr_len,
85 const void *data,
86 size_t data_size);
87
88
89/**
90 * Handle to a request given to the resolver. Can be used to cancel
91 * the request prior to the timeout or successful execution. Also
92 * used to track our internal state for the request.
93 */
94struct GNUNET_NAT_STUN_Handle;
95
96
97/**
98 * Make Generic STUN request. Sends a generic stun request to the
99 * server specified using the specified socket. If we do this,
100 * we need to watch for possible responses and call
101 * #GNUNET_NAT_stun_handle_packet() on incoming packets.
102 *
103 * @param server the address of the stun server
104 * @param port port of the stun server, in host byte order
105 * @param sock the socket used to send the request, must be a
106 * UDP socket
107 * @param cb callback in case of error
108 * @param cb_cls closure for @a cb
109 * @return NULL on error
110 */
111struct GNUNET_NAT_STUN_Handle *
112GNUNET_NAT_stun_make_request (const char *server,
113 uint16_t port,
114 struct GNUNET_NETWORK_Handle *sock,
115 GNUNET_NAT_TestCallback cb,
116 void *cb_cls);
117
118
119/**
120 * Cancel active STUN request. Frees associated resources
121 * and ensures that the callback is no longer invoked.
122 *
123 * @param rh request to cancel
124 */
125void
126GNUNET_NAT_stun_make_request_cancel (struct GNUNET_NAT_STUN_Handle *rh);
127
128
129/**
130 * Start testing if NAT traversal works using the given configuration
131 * (IPv4-only). The transport adapters should be down while using
132 * this function.
133 *
134 * @param cfg configuration for the NAT traversal
135 * @param proto protocol to test, i.e. IPPROTO_TCP or IPPROTO_UDP
136 * @param bind_ip IPv4 address to bind to
137 * @param bnd_port port to bind to, 0 to test connection reversal
138 * @param extern_ip IPv4 address to externally advertise
139 * @param extern_port externally advertised port to use
140 * @param report function to call with the result of the test
141 * @param report_cls closure for @a report
142 * @return handle to cancel NAT test
143 */
144struct GNUNET_NAT_Test *
145GNUNET_NAT_test_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
146 uint8_t proto,
147 struct in_addr bind_ip,
148 uint16_t bnd_port,
149 struct in_addr extern_ip,
150 uint16_t extern_port,
151 GNUNET_NAT_TestCallback report,
152 void *report_cls);
153
154
155/**
156 * Stop an active NAT test.
157 *
158 * @param tst test to stop.
159 */
160void
161GNUNET_NAT_test_stop (struct GNUNET_NAT_Test *tst);
162
163
164/**
165 * Handle to auto-configuration in progress.
166 */
167struct GNUNET_NAT_AutoHandle;
168
169
170/**
171 * Converts `enum GNUNET_NAT_StatusCode` to string
172 *
173 * @param err error code to resolve to a string
174 * @return point to a static string containing the error code
175 */
176const char *
177GNUNET_NAT_status2string (enum GNUNET_NAT_StatusCode err);
178
179
180/**
181 * Function called with the result from the autoconfiguration.
182 *
183 * @param cls closure
184 * @param diff minimal suggested changes to the original configuration
185 * to make it work (as best as we can)
186 * @param result #GNUNET_NAT_ERROR_SUCCESS on success, otherwise the specific error code
187 * @param type what the situation of the NAT
188 */
189typedef void
190(*GNUNET_NAT_AutoResultCallback)(void *cls,
191 const struct GNUNET_CONFIGURATION_Handle *diff,
192 enum GNUNET_NAT_StatusCode result,
193 enum GNUNET_NAT_Type type);
194
195
196/**
197 * Start auto-configuration routine. The transport adapters should
198 * be stopped while this function is called.
199 *
200 * @param cfg initial configuration
201 * @param cb function to call with autoconfiguration result
202 * @param cb_cls closure for @a cb
203 * @return handle to cancel operation
204 */
205struct GNUNET_NAT_AutoHandle *
206GNUNET_NAT_autoconfig_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
207 GNUNET_NAT_AutoResultCallback cb,
208 void *cb_cls);
209
210
211/**
212 * Abort autoconfiguration.
213 *
214 * @param ah handle for operation to abort
215 */
216void
217GNUNET_NAT_autoconfig_cancel (struct GNUNET_NAT_AutoHandle *ah);
218
219
220#endif
221
222/** @} */ /* end of group */
223
224/* end of gnunet_nat_auto_service.h */
diff --git a/src/include/gnunet_nat_service.h b/src/include/gnunet_nat_service.h
index 6b9650306..94f8a8555 100644
--- a/src/include/gnunet_nat_service.h
+++ b/src/include/gnunet_nat_service.h
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2007-2016 GNUnet e.V. 3 Copyright (C) 2007-2017 GNUnet e.V.
4 4
5 GNUnet is free software; you can redistribute it and/or modify 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 6 it under the terms of the GNU General Public License as published
@@ -137,132 +137,6 @@ enum GNUNET_NAT_AddressClass
137 137
138 138
139/** 139/**
140 * Signature of the callback passed to #GNUNET_NAT_register() for
141 * a function to call whenever our set of 'valid' addresses changes.
142 *
143 * @param cls closure
144 * @param add_remove #GNUNET_YES to add a new public IP address,
145 * #GNUNET_NO to remove a previous (now invalid) one
146 * @param ac address class the address belongs to
147 * @param addr either the previous or the new public IP address
148 * @param addrlen actual length of the @a addr
149 */
150typedef void
151(*GNUNET_NAT_AddressCallback) (void *cls,
152 int add_remove,
153 enum GNUNET_NAT_AddressClass ac,
154 const struct sockaddr *addr,
155 socklen_t addrlen);
156
157
158/**
159 * Signature of the callback passed to #GNUNET_NAT_register().
160 * for a function to call whenever someone asks us to do connection
161 * reversal.
162 *
163 * @param cls closure
164 * @param remote_addr public IP address of the other peer
165 * @param remote_addrlen actual length of the @a remote_addr
166 */
167typedef void
168(*GNUNET_NAT_ReversalCallback) (void *cls,
169 const struct sockaddr *remote_addr,
170 socklen_t remote_addrlen);
171
172
173/**
174 * Handle for active NAT registrations.
175 */
176struct GNUNET_NAT_Handle;
177
178
179/**
180 * Attempt to enable port redirection and detect public IP address
181 * contacting UPnP or NAT-PMP routers on the local network. Use @a
182 * addr to specify to which of the local host's addresses should the
183 * external port be mapped. The port is taken from the corresponding
184 * sockaddr_in[6] field. The NAT module should call the given @a
185 * address_callback for any 'plausible' external address.
186 *
187 * @param cfg configuration to use
188 * @param config_section name of the configuration section for optionsx
189 * @param proto protocol this is about, IPPROTO_TCP or IPPROTO_UDP
190 * @param num_addrs number of addresses in @a addrs
191 * @param addrs list of local addresses packets should be redirected to
192 * @param addrlens actual lengths of the addresses in @a addrs
193 * @param address_callback function to call everytime the public IP address changes
194 * @param reversal_callback function to call if someone wants connection reversal from us,
195 * NULL if connection reversal is not supported
196 * @param callback_cls closure for callbacks
197 * @return NULL on error, otherwise handle that can be used to unregister
198 */
199struct GNUNET_NAT_Handle *
200GNUNET_NAT_register (const struct GNUNET_CONFIGURATION_Handle *cfg,
201 const char *config_section,
202 uint8_t proto,
203 unsigned int num_addrs,
204 const struct sockaddr **addrs,
205 const socklen_t *addrlens,
206 GNUNET_NAT_AddressCallback address_callback,
207 GNUNET_NAT_ReversalCallback reversal_callback,
208 void *callback_cls);
209
210
211/**
212 * Test if the given address is (currently) a plausible IP address for
213 * this peer. Mostly a convenience function so that clients do not
214 * have to explicitly track all IPs that the #GNUNET_NAT_AddressCallback
215 * has returned so far.
216 *
217 * @param nh the handle returned by register
218 * @param addr IP address to test (IPv4 or IPv6)
219 * @param addrlen number of bytes in @a addr
220 * @return #GNUNET_YES if the address is plausible,
221 * #GNUNET_NO if the address is not plausible,
222 * #GNUNET_SYSERR if the address is malformed
223 */
224int
225GNUNET_NAT_test_address (struct GNUNET_NAT_Handle *nh,
226 const void *addr,
227 socklen_t addrlen);
228
229
230/**
231 * We learned about a peer (possibly behind NAT) so run the
232 * gnunet-nat-client to send dummy ICMP responses to cause
233 * that peer to connect to us (connection reversal).
234 *
235 * @param nh handle (used for configuration)
236 * @param local_sa our local address of the peer (IPv4-only)
237 * @param remote_sa the remote address of the peer (IPv4-only)
238 * @return #GNUNET_SYSERR on error,
239 * #GNUNET_NO if connection reversal is unavailable,
240 * #GNUNET_OK otherwise (presumably in progress)
241 */
242int
243GNUNET_NAT_request_reversal (struct GNUNET_NAT_Handle *nh,
244 const struct sockaddr_in *local_sa,
245 const struct sockaddr_in *remote_sa);
246
247
248/**
249 * Stop port redirection and public IP address detection for the given
250 * handle. This frees the handle, after having sent the needed
251 * commands to close open ports.
252 *
253 * @param nh the handle to unregister
254 */
255void
256GNUNET_NAT_unregister (struct GNUNET_NAT_Handle *nh);
257
258
259/**
260 * Handle to a NAT test.
261 */
262struct GNUNET_NAT_Test;
263
264
265/**
266 * Error Types for the NAT subsystem (which can then later be converted/resolved to a string) 140 * Error Types for the NAT subsystem (which can then later be converted/resolved to a string)
267 */ 141 */
268enum GNUNET_NAT_StatusCode 142enum GNUNET_NAT_StatusCode
@@ -365,129 +239,6 @@ enum GNUNET_NAT_StatusCode
365}; 239};
366 240
367 241
368/**
369 * Function called to report success or failure for
370 * NAT configuration test.
371 *
372 * @param cls closure
373 * @param result #GNUNET_NAT_ERROR_SUCCESS on success, otherwise the specific error code
374 */
375typedef void
376(*GNUNET_NAT_TestCallback) (void *cls,
377 enum GNUNET_NAT_StatusCode result);
378
379
380/**
381 * Handle an incoming STUN message. This function is useful as
382 * some GNUnet service may be listening on a UDP port and might
383 * thus receive STUN messages while trying to receive other data.
384 * In this case, this function can be used to process replies
385 * to STUN requests.
386 *
387 * The function does some basic sanity checks on packet size and
388 * content, try to extract a bit of information.
389 *
390 * At the moment this only processes BIND requests, and returns the
391 * externally visible address of the request to the rest of the
392 * NAT logic.
393 *
394 * @param nh handle to the NAT service
395 * @param sender_addr address from which we got @a data
396 * @param sender_addr_len number of bytes in @a sender_addr
397 * @param data the packet
398 * @param data_size number of bytes in @a data
399 * @return #GNUNET_OK on success
400 * #GNUNET_NO if the packet is not a STUN packet
401 * #GNUNET_SYSERR on internal error handling the packet
402 */
403int
404GNUNET_NAT_stun_handle_packet (struct GNUNET_NAT_Handle *nh,
405 const struct sockaddr *sender_addr,
406 size_t sender_addr_len,
407 const void *data,
408 size_t data_size);
409
410
411/**
412 * Handle to a request given to the resolver. Can be used to cancel
413 * the request prior to the timeout or successful execution. Also
414 * used to track our internal state for the request.
415 */
416struct GNUNET_NAT_STUN_Handle;
417
418
419/**
420 * Make Generic STUN request. Sends a generic stun request to the
421 * server specified using the specified socket. If we do this,
422 * we need to watch for possible responses and call
423 * #GNUNET_NAT_stun_handle_packet() on incoming packets.
424 *
425 * @param server the address of the stun server
426 * @param port port of the stun server, in host byte order
427 * @param sock the socket used to send the request, must be a
428 * UDP socket
429 * @param cb callback in case of error
430 * @param cb_cls closure for @a cb
431 * @return NULL on error
432 */
433struct GNUNET_NAT_STUN_Handle *
434GNUNET_NAT_stun_make_request (const char *server,
435 uint16_t port,
436 struct GNUNET_NETWORK_Handle *sock,
437 GNUNET_NAT_TestCallback cb,
438 void *cb_cls);
439
440
441/**
442 * Cancel active STUN request. Frees associated resources
443 * and ensures that the callback is no longer invoked.
444 *
445 * @param rh request to cancel
446 */
447void
448GNUNET_NAT_stun_make_request_cancel (struct GNUNET_NAT_STUN_Handle *rh);
449
450
451/**
452 * Start testing if NAT traversal works using the given configuration
453 * (IPv4-only). The transport adapters should be down while using
454 * this function.
455 *
456 * @param cfg configuration for the NAT traversal
457 * @param proto protocol to test, i.e. IPPROTO_TCP or IPPROTO_UDP
458 * @param bind_ip IPv4 address to bind to
459 * @param bnd_port port to bind to, 0 to test connection reversal
460 * @param extern_ip IPv4 address to externally advertise
461 * @param extern_port externally advertised port to use
462 * @param report function to call with the result of the test
463 * @param report_cls closure for @a report
464 * @return handle to cancel NAT test
465 */
466struct GNUNET_NAT_Test *
467GNUNET_NAT_test_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
468 uint8_t proto,
469 struct in_addr bind_ip,
470 uint16_t bnd_port,
471 struct in_addr extern_ip,
472 uint16_t extern_port,
473 GNUNET_NAT_TestCallback report,
474 void *report_cls);
475
476
477/**
478 * Stop an active NAT test.
479 *
480 * @param tst test to stop.
481 */
482void
483GNUNET_NAT_test_stop (struct GNUNET_NAT_Test *tst);
484
485
486/**
487 * Handle to auto-configuration in progress.
488 */
489struct GNUNET_NAT_AutoHandle;
490
491 242
492/** 243/**
493 * What the situation of the NAT connectivity 244 * What the situation of the NAT connectivity
@@ -522,54 +273,156 @@ enum GNUNET_NAT_Type
522}; 273};
523 274
524 275
276
525/** 277/**
526 * Converts `enum GNUNET_NAT_StatusCode` to string 278 * Signature of the callback passed to #GNUNET_NAT_register() for
279 * a function to call whenever our set of 'valid' addresses changes.
527 * 280 *
528 * @param err error code to resolve to a string 281 * @param cls closure
529 * @return point to a static string containing the error code 282 * @param add_remove #GNUNET_YES to add a new public IP address,
283 * #GNUNET_NO to remove a previous (now invalid) one
284 * @param ac address class the address belongs to
285 * @param addr either the previous or the new public IP address
286 * @param addrlen actual length of the @a addr
530 */ 287 */
531const char * 288typedef void
532GNUNET_NAT_status2string (enum GNUNET_NAT_StatusCode err); 289(*GNUNET_NAT_AddressCallback) (void *cls,
290 int add_remove,
291 enum GNUNET_NAT_AddressClass ac,
292 const struct sockaddr *addr,
293 socklen_t addrlen);
533 294
534 295
535/** 296/**
536 * Function called with the result from the autoconfiguration. 297 * Signature of the callback passed to #GNUNET_NAT_register().
298 * for a function to call whenever someone asks us to do connection
299 * reversal.
537 * 300 *
538 * @param cls closure 301 * @param cls closure
539 * @param diff minimal suggested changes to the original configuration 302 * @param remote_addr public IP address of the other peer
540 * to make it work (as best as we can) 303 * @param remote_addrlen actual length of the @a remote_addr
541 * @param result #GNUNET_NAT_ERROR_SUCCESS on success, otherwise the specific error code
542 * @param type what the situation of the NAT
543 */ 304 */
544typedef void 305typedef void
545(*GNUNET_NAT_AutoResultCallback)(void *cls, 306(*GNUNET_NAT_ReversalCallback) (void *cls,
546 const struct GNUNET_CONFIGURATION_Handle *diff, 307 const struct sockaddr *remote_addr,
547 enum GNUNET_NAT_StatusCode result, 308 socklen_t remote_addrlen);
548 enum GNUNET_NAT_Type type); 309
310
311/**
312 * Handle for active NAT registrations.
313 */
314struct GNUNET_NAT_Handle;
549 315
550 316
551/** 317/**
552 * Start auto-configuration routine. The transport adapters should 318 * Attempt to enable port redirection and detect public IP address
553 * be stopped while this function is called. 319 * contacting UPnP or NAT-PMP routers on the local network. Use @a
320 * addr to specify to which of the local host's addresses should the
321 * external port be mapped. The port is taken from the corresponding
322 * sockaddr_in[6] field. The NAT module should call the given @a
323 * address_callback for any 'plausible' external address.
554 * 324 *
555 * @param cfg initial configuration 325 * @param cfg configuration to use
556 * @param cb function to call with autoconfiguration result 326 * @param config_section name of the configuration section for options
557 * @param cb_cls closure for @a cb 327 * @param proto protocol this is about, IPPROTO_TCP or IPPROTO_UDP
558 * @return handle to cancel operation 328 * @param num_addrs number of addresses in @a addrs
329 * @param addrs list of local addresses packets should be redirected to
330 * @param addrlens actual lengths of the addresses in @a addrs
331 * @param address_callback function to call everytime the public IP address changes
332 * @param reversal_callback function to call if someone wants connection reversal from us,
333 * NULL if connection reversal is not supported
334 * @param callback_cls closure for callbacks
335 * @return NULL on error, otherwise handle that can be used to unregister
559 */ 336 */
560struct GNUNET_NAT_AutoHandle * 337struct GNUNET_NAT_Handle *
561GNUNET_NAT_autoconfig_start (const struct GNUNET_CONFIGURATION_Handle *cfg, 338GNUNET_NAT_register (const struct GNUNET_CONFIGURATION_Handle *cfg,
562 GNUNET_NAT_AutoResultCallback cb, 339 const char *config_section,
563 void *cb_cls); 340 uint8_t proto,
341 unsigned int num_addrs,
342 const struct sockaddr **addrs,
343 const socklen_t *addrlens,
344 GNUNET_NAT_AddressCallback address_callback,
345 GNUNET_NAT_ReversalCallback reversal_callback,
346 void *callback_cls);
347
348
349/**
350 * Test if the given address is (currently) a plausible IP address for
351 * this peer. Mostly a convenience function so that clients do not
352 * have to explicitly track all IPs that the #GNUNET_NAT_AddressCallback
353 * has returned so far.
354 *
355 * @param nh the handle returned by register
356 * @param addr IP address to test (IPv4 or IPv6)
357 * @param addrlen number of bytes in @a addr
358 * @return #GNUNET_YES if the address is plausible,
359 * #GNUNET_NO if the address is not plausible,
360 * #GNUNET_SYSERR if the address is malformed
361 */
362int
363GNUNET_NAT_test_address (struct GNUNET_NAT_Handle *nh,
364 const void *addr,
365 socklen_t addrlen);
564 366
565 367
566/** 368/**
567 * Abort autoconfiguration. 369 * We learned about a peer (possibly behind NAT) so run the
370 * gnunet-nat-client to send dummy ICMP responses to cause
371 * that peer to connect to us (connection reversal).
568 * 372 *
569 * @param ah handle for operation to abort 373 * @param nh handle (used for configuration)
374 * @param local_sa our local address of the peer (IPv4-only)
375 * @param remote_sa the remote address of the peer (IPv4-only)
376 * @return #GNUNET_SYSERR on error,
377 * #GNUNET_NO if connection reversal is unavailable,
378 * #GNUNET_OK otherwise (presumably in progress)
379 */
380int
381GNUNET_NAT_request_reversal (struct GNUNET_NAT_Handle *nh,
382 const struct sockaddr_in *local_sa,
383 const struct sockaddr_in *remote_sa);
384
385
386/**
387 * Stop port redirection and public IP address detection for the given
388 * handle. This frees the handle, after having sent the needed
389 * commands to close open ports.
390 *
391 * @param nh the handle to unregister
570 */ 392 */
571void 393void
572GNUNET_NAT_autoconfig_cancel (struct GNUNET_NAT_AutoHandle *ah); 394GNUNET_NAT_unregister (struct GNUNET_NAT_Handle *nh);
395
396
397/**
398 * Handle an incoming STUN message. This function is useful as
399 * some GNUnet service may be listening on a UDP port and might
400 * thus receive STUN messages while trying to receive other data.
401 * In this case, this function can be used to process replies
402 * to STUN requests.
403 *
404 * The function does some basic sanity checks on packet size and
405 * content, try to extract a bit of information.
406 *
407 * At the moment this only processes BIND requests, and returns the
408 * externally visible address of the request to the rest of the
409 * NAT logic.
410 *
411 * @param nh handle to the NAT service
412 * @param sender_addr address from which we got @a data
413 * @param sender_addr_len number of bytes in @a sender_addr
414 * @param data the packet
415 * @param data_size number of bytes in @a data
416 * @return #GNUNET_OK on success
417 * #GNUNET_NO if the packet is not a STUN packet
418 * #GNUNET_SYSERR on internal error handling the packet
419 */
420int
421GNUNET_NAT_stun_handle_packet (struct GNUNET_NAT_Handle *nh,
422 const struct sockaddr *sender_addr,
423 size_t sender_addr_len,
424 const void *data,
425 size_t data_size);
573 426
574 427
575#endif 428#endif
diff --git a/src/include/gnunet_protocols.h b/src/include/gnunet_protocols.h
index f9b7d3cb8..fdabfee18 100644
--- a/src/include/gnunet_protocols.h
+++ b/src/include/gnunet_protocols.h
@@ -2820,7 +2820,7 @@ extern "C"
2820/** 2820/**
2821 * Message to ask NAT service to request autoconfiguration. 2821 * Message to ask NAT service to request autoconfiguration.
2822 */ 2822 */
2823#define GNUNET_MESSAGE_TYPE_NAT_REQUEST_AUTO_CFG 1067 2823#define GNUNET_MESSAGE_TYPE_NAT_AUTO_REQUEST_CFG 1067
2824 2824
2825/** 2825/**
2826 * Message from NAT service with the autoconfiguration result. 2826 * Message from NAT service with the autoconfiguration result.
diff --git a/src/nat-auto/.gitignore b/src/nat-auto/.gitignore
new file mode 100644
index 000000000..6ba53d72f
--- /dev/null
+++ b/src/nat-auto/.gitignore
@@ -0,0 +1,3 @@
1gnunet-service-nat-auto
2gnunet-nat-auto
3gnunet-nat-server
diff --git a/src/nat-auto/Makefile.am b/src/nat-auto/Makefile.am
new file mode 100644
index 000000000..dbe910306
--- /dev/null
+++ b/src/nat-auto/Makefile.am
@@ -0,0 +1,58 @@
1# This Makefile.am is in the public domain
2AM_CPPFLAGS = -I$(top_srcdir)/src/include
3
4libexecdir= $(pkglibdir)/libexec/
5
6pkgcfgdir= $(pkgdatadir)/config.d/
7
8pkgcfg_DATA = \
9 nat-auto.conf
10
11bin_PROGRAMS = \
12 gnunet-nat-auto \
13 gnunet-nat-server
14
15libexec_PROGRAMS = \
16 gnunet-service-nat-auto
17
18gnunet_nat_server_SOURCES = \
19 gnunet-nat-server.c nat-auto.h
20gnunet_nat_server_LDADD = \
21 $(top_builddir)/src/nat/libgnunetnat.la \
22 $(top_builddir)/src/util/libgnunetutil.la
23
24gnunet_nat_auto_SOURCES = \
25 gnunet-nat-auto.c nat-auto.h
26gnunet_nat_auto_LDADD = \
27 libgnunetnatauto.la \
28 $(top_builddir)/src/util/libgnunetutil.la
29
30
31if USE_COVERAGE
32 AM_CFLAGS = -fprofile-arcs -ftest-coverage
33endif
34
35lib_LTLIBRARIES = \
36 libgnunetnatauto.la
37
38libgnunetnatauto_la_SOURCES = \
39 nat_auto_api.c \
40 nat_auto_api_test.c
41libgnunetnatauto_la_LIBADD = \
42 $(top_builddir)/src/nat/libgnunetnatnew.la \
43 $(top_builddir)/src/util/libgnunetutil.la \
44 $(GN_LIBINTL) @EXT_LIBS@
45libgnunetnatauto_la_LDFLAGS = \
46 $(GN_LIB_LDFLAGS) $(WINFLAGS) \
47 -version-info 0:0:0
48
49gnunet_service_nat_auto_SOURCES = \
50 gnunet-service-nat-auto.c
51gnunet_service_nat_auto_LDADD = \
52 $(top_builddir)/src/util/libgnunetutil.la \
53 $(top_builddir)/src/statistics/libgnunetstatistics.la \
54 $(top_builddir)/src/nat/libgnunetnatnew.la \
55 $(LIBGCRYPT_LIBS) \
56 -lgcrypt \
57 $(GN_LIBINTL)
58
diff --git a/src/nat-auto/gnunet-nat-auto.c b/src/nat-auto/gnunet-nat-auto.c
new file mode 100644
index 000000000..3b9a5fa94
--- /dev/null
+++ b/src/nat-auto/gnunet-nat-auto.c
@@ -0,0 +1,428 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2015, 2016, 2017 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-auto.c
23 * @brief Command-line tool for testing and autoconfiguration of NAT traversal
24 * @author Christian Grothoff
25 * @author Bruno Cabral
26 */
27#include "platform.h"
28#include "gnunet_util_lib.h"
29#include "gnunet_nat_service.h"
30#include "gnunet_nat_auto_service.h"
31
32/**
33 * Value to return from #main().
34 */
35static int global_ret;
36
37/**
38 * Handle to ongoing autoconfiguration.
39 */
40static struct GNUNET_NAT_AutoHandle *ah;
41
42/**
43 * If we do auto-configuration, should we write the result
44 * to a file?
45 */
46static int write_cfg;
47
48/**
49 * Configuration filename.
50 */
51static const char *cfg_file;
52
53/**
54 * Original configuration.
55 */
56static const struct GNUNET_CONFIGURATION_Handle *cfg;
57
58/**
59 * Address we are bound to (in test), or should bind to
60 * (if #do_stun is set).
61 */
62static char *bind_addr;
63
64/**
65 * External IP address and port to use for the test.
66 * If not set, use #bind_addr.
67 */
68static char *extern_addr;
69
70/**
71 * Should we run autoconfiguration?
72 */
73static unsigned int do_auto;
74
75/**
76 * Handle to a NAT test operation.
77 */
78static struct GNUNET_NAT_Test *nt;
79
80/**
81 * Flag set to 1 if we use IPPROTO_UDP.
82 */
83static int use_udp;
84
85/**
86 * Flag set to 1 if we use IPPROTO_TCP.
87 */
88static int use_tcp;
89
90/**
91 * Protocol to use.
92 */
93static uint8_t proto;
94
95/**
96 * Test if all activities have finished, and if so,
97 * terminate.
98 */
99static void
100test_finished ()
101{
102 if (NULL != ah)
103 return;
104 if (NULL != nt)
105 return;
106 GNUNET_SCHEDULER_shutdown ();
107}
108
109
110/**
111 * Function to iterate over sugested changes options
112 *
113 * @param cls closure
114 * @param section name of the section
115 * @param option name of the option
116 * @param value value of the option
117 */
118static void
119auto_conf_iter (void *cls,
120 const char *section,
121 const char *option,
122 const char *value)
123{
124 struct GNUNET_CONFIGURATION_Handle *new_cfg = cls;
125
126 PRINTF ("%s: %s\n",
127 option,
128 value);
129 if (NULL != new_cfg)
130 GNUNET_CONFIGURATION_set_value_string (new_cfg,
131 section,
132 option,
133 value);
134}
135
136
137/**
138 * Function called with the result from the autoconfiguration.
139 *
140 * @param cls closure
141 * @param diff minimal suggested changes to the original configuration
142 * to make it work (as best as we can)
143 * @param result #GNUNET_NAT_ERROR_SUCCESS on success, otherwise the specific error code
144 * @param type what the situation of the NAT
145 */
146static void
147auto_config_cb (void *cls,
148 const struct GNUNET_CONFIGURATION_Handle *diff,
149 enum GNUNET_NAT_StatusCode result,
150 enum GNUNET_NAT_Type type)
151{
152 const char *nat_type;
153 char unknown_type[64];
154 struct GNUNET_CONFIGURATION_Handle *new_cfg;
155
156 ah = NULL;
157 switch (type)
158 {
159 case GNUNET_NAT_TYPE_NO_NAT:
160 nat_type = "NO NAT";
161 break;
162 case GNUNET_NAT_TYPE_UNREACHABLE_NAT:
163 nat_type = "NAT but we can traverse";
164 break;
165 case GNUNET_NAT_TYPE_STUN_PUNCHED_NAT:
166 nat_type = "NAT but STUN is able to identify the correct information";
167 break;
168 case GNUNET_NAT_TYPE_UPNP_NAT:
169 nat_type = "NAT but UPNP opened the ports";
170 break;
171 default:
172 SPRINTF (unknown_type,
173 "NAT unknown, type %u",
174 type);
175 nat_type = unknown_type;
176 break;
177 }
178
179 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
180 "NAT status: %s/%s\n",
181 GNUNET_NAT_status2string (result),
182 nat_type);
183
184 /* Shortcut: if there are no changes suggested, bail out early. */
185 if (GNUNET_NO ==
186 GNUNET_CONFIGURATION_is_dirty (diff))
187 {
188 test_finished ();
189 return;
190 }
191
192 /* Apply diff to original configuration and show changes
193 to the user */
194 new_cfg = write_cfg ? GNUNET_CONFIGURATION_dup (cfg) : NULL;
195
196 if (NULL != diff)
197 {
198 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
199 _("Suggested configuration changes:\n"));
200 GNUNET_CONFIGURATION_iterate_section_values (diff,
201 "nat",
202 &auto_conf_iter,
203 new_cfg);
204 }
205
206 /* If desired, write configuration to file; we write only the
207 changes to the defaults to keep things compact. */
208 if ( (write_cfg) &&
209 (NULL != diff) )
210 {
211 struct GNUNET_CONFIGURATION_Handle *def_cfg;
212
213 GNUNET_CONFIGURATION_set_value_string (new_cfg,
214 "ARM",
215 "CONFIG",
216 NULL);
217 def_cfg = GNUNET_CONFIGURATION_create ();
218 GNUNET_break (GNUNET_OK ==
219 GNUNET_CONFIGURATION_load (def_cfg,
220 NULL));
221 if (GNUNET_OK !=
222 GNUNET_CONFIGURATION_write_diffs (def_cfg,
223 new_cfg,
224 cfg_file))
225 {
226 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
227 _("Failed to write configuration to `%s'\n"),
228 cfg_file);
229 global_ret = 1;
230 }
231 else
232 {
233 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
234 _("Wrote updated configuration to `%s'\n"),
235 cfg_file);
236 }
237 GNUNET_CONFIGURATION_destroy (def_cfg);
238 }
239
240 if (NULL != new_cfg)
241 GNUNET_CONFIGURATION_destroy (new_cfg);
242 test_finished ();
243}
244
245
246/**
247 * Function called to report success or failure for
248 * NAT configuration test.
249 *
250 * @param cls closure
251 * @param result #GNUNET_NAT_ERROR_SUCCESS on success, otherwise the specific error code
252 */
253static void
254test_report_cb (void *cls,
255 enum GNUNET_NAT_StatusCode result)
256{
257 nt = NULL;
258 PRINTF ("NAT test result: %s\n",
259 GNUNET_NAT_status2string (result));
260 test_finished ();
261}
262
263
264/**
265 * Task run on shutdown.
266 *
267 * @param cls NULL
268 */
269static void
270do_shutdown (void *cls)
271{
272 if (NULL != ah)
273 {
274 GNUNET_NAT_autoconfig_cancel (ah);
275 ah = NULL;
276 }
277 if (NULL != nt)
278 {
279 GNUNET_NAT_test_stop (nt);
280 nt = NULL;
281 }
282}
283
284
285/**
286 * Main function that will be run.
287 *
288 * @param cls closure
289 * @param args remaining command-line arguments
290 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
291 * @param c configuration
292 */
293static void
294run (void *cls,
295 char *const *args,
296 const char *cfgfile,
297 const struct GNUNET_CONFIGURATION_Handle *c)
298{
299 struct sockaddr_in bind_sa;
300 struct sockaddr_in extern_sa;
301
302 cfg_file = cfgfile;
303 cfg = c;
304
305 GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
306 NULL);
307
308 if (do_auto)
309 {
310 ah = GNUNET_NAT_autoconfig_start (c,
311 &auto_config_cb,
312 NULL);
313 }
314
315 if (use_tcp && use_udp)
316 {
317 if (do_auto)
318 return;
319 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
320 "Cannot use TCP and UDP\n");
321 global_ret = 1;
322 return;
323 }
324 proto = 0;
325 if (use_tcp)
326 proto = IPPROTO_TCP;
327 if (use_udp)
328 proto = IPPROTO_UDP;
329
330 if (NULL != bind_addr)
331 {
332 if (GNUNET_OK !=
333 GNUNET_STRINGS_to_address_ipv4 (bind_addr,
334 strlen (bind_addr),
335 &bind_sa))
336 {
337 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
338 "Invalid socket address `%s'\n",
339 bind_addr);
340 global_ret = 1;
341 return;
342 }
343 }
344 if (NULL != extern_addr)
345 {
346 if (GNUNET_OK !=
347 GNUNET_STRINGS_to_address_ipv4 (extern_addr,
348 strlen (extern_addr),
349 &extern_sa))
350 {
351 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
352 "Invalid socket address `%s'\n",
353 extern_addr);
354 global_ret = 1;
355 return;
356 }
357 }
358
359 if (NULL != bind_addr)
360 {
361 if (NULL == extern_addr)
362 extern_sa = bind_sa;
363 nt = GNUNET_NAT_test_start (c,
364 proto,
365 bind_sa.sin_addr,
366 ntohs (bind_sa.sin_port),
367 extern_sa.sin_addr,
368 ntohs (extern_sa.sin_port),
369 &test_report_cb,
370 NULL);
371 }
372 test_finished ();
373}
374
375
376/**
377 * Main function of gnunet-nat
378 *
379 * @param argc number of command-line arguments
380 * @param argv command line
381 * @return 0 on success, -1 on error
382 */
383int
384main (int argc,
385 char *const argv[])
386{
387 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
388 {'a', "auto", NULL,
389 gettext_noop ("run autoconfiguration"),
390 GNUNET_NO, &GNUNET_GETOPT_set_one, &do_auto },
391 {'b', "bind", "ADDRESS",
392 gettext_noop ("which IP and port are we bound to"),
393 GNUNET_YES, &GNUNET_GETOPT_set_string, &bind_addr },
394 {'e', "external", "ADDRESS",
395 gettext_noop ("which external IP and port should be used to test"),
396 GNUNET_YES, &GNUNET_GETOPT_set_string, &extern_addr },
397 {'t', "tcp", NULL,
398 gettext_noop ("use TCP"),
399 GNUNET_NO, &GNUNET_GETOPT_set_one, &use_tcp },
400 {'u', "udp", NULL,
401 gettext_noop ("use UDP"),
402 GNUNET_NO, &GNUNET_GETOPT_set_one, &use_udp },
403 {'w', "write", NULL,
404 gettext_noop ("write configuration file (for autoconfiguration)"),
405 GNUNET_NO, &GNUNET_GETOPT_set_one, &write_cfg },
406 GNUNET_GETOPT_OPTION_END
407 };
408
409 if (GNUNET_OK !=
410 GNUNET_STRINGS_get_utf8_args (argc, argv,
411 &argc, &argv))
412 return 2;
413 if (GNUNET_OK !=
414 GNUNET_PROGRAM_run (argc, argv,
415 "gnunet-nat-auto [options]",
416 _("GNUnet NAT traversal autoconfiguration"),
417 options,
418 &run,
419 NULL))
420 {
421 global_ret = 1;
422 }
423 GNUNET_free ((void*) argv);
424 return global_ret;
425}
426
427
428/* end of gnunet-nat-auto.c */
diff --git a/src/nat/gnunet-nat-server.c b/src/nat-auto/gnunet-nat-server.c
index 1692a8ef1..93352f5f0 100644
--- a/src/nat/gnunet-nat-server.c
+++ b/src/nat-auto/gnunet-nat-server.c
@@ -27,7 +27,7 @@
27#include "gnunet_util_lib.h" 27#include "gnunet_util_lib.h"
28#include "gnunet_nat_lib.h" 28#include "gnunet_nat_lib.h"
29#include "gnunet_protocols.h" 29#include "gnunet_protocols.h"
30#include "nat.h" 30#include "nat-auto.h"
31 31
32 32
33/** 33/**
diff --git a/src/nat-auto/gnunet-service-nat-auto.c b/src/nat-auto/gnunet-service-nat-auto.c
new file mode 100644
index 000000000..897d6feb2
--- /dev/null
+++ b/src/nat-auto/gnunet-service-nat-auto.c
@@ -0,0 +1,481 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2016, 2017 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 nat-auto/gnunet-service-nat-auto.c
23 * @brief NAT autoconfiguration service
24 * @author Christian Grothoff
25 *
26 * TODO:
27 * - merge client handle and autoconfig context
28 * - implement "more" autoconfig:
29 * + re-work gnunet-nat-server & integrate!
30 * + test manually punched NAT (how?)
31 */
32#include "platform.h"
33#include <math.h>
34#include "gnunet_util_lib.h"
35#include "gnunet_protocols.h"
36#include "gnunet_signatures.h"
37#include "gnunet_nat_service.h"
38#include "gnunet_statistics_service.h"
39#include "gnunet_resolver_service.h"
40#include "nat-auto.h"
41#include <gcrypt.h>
42
43
44/**
45 * How long do we wait until we forcefully terminate autoconfiguration?
46 */
47#define AUTOCONFIG_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
48
49
50/**
51 * Internal data structure we track for each of our clients.
52 */
53struct ClientHandle
54{
55
56 /**
57 * Kept in a DLL.
58 */
59 struct ClientHandle *next;
60
61 /**
62 * Kept in a DLL.
63 */
64 struct ClientHandle *prev;
65
66 /**
67 * Underlying handle for this client with the service.
68 */
69 struct GNUNET_SERVICE_Client *client;
70
71 /**
72 * Message queue for communicating with the client.
73 */
74 struct GNUNET_MQ_Handle *mq;
75};
76
77
78/**
79 * Context for autoconfiguration operations.
80 */
81struct AutoconfigContext
82{
83 /**
84 * Kept in a DLL.
85 */
86 struct AutoconfigContext *prev;
87
88 /**
89 * Kept in a DLL.
90 */
91 struct AutoconfigContext *next;
92
93 /**
94 * Which client asked the question.
95 */
96 struct ClientHandle *ch;
97
98 /**
99 * Configuration we are creating.
100 */
101 struct GNUNET_CONFIGURATION_Handle *c;
102
103 /**
104 * Original configuration (for diffing).
105 */
106 struct GNUNET_CONFIGURATION_Handle *orig;
107
108 /**
109 * Timeout task to force termination.
110 */
111 struct GNUNET_SCHEDULER_Task *timeout_task;
112
113 /**
114 * #GNUNET_YES if upnpc should be used,
115 * #GNUNET_NO if upnpc should not be used,
116 * #GNUNET_SYSERR if we should simply not change the option.
117 */
118 int enable_upnpc;
119
120 /**
121 * Status code to return to the client.
122 */
123 enum GNUNET_NAT_StatusCode status_code;
124
125 /**
126 * NAT type to return to the client.
127 */
128 enum GNUNET_NAT_Type type;
129};
130
131
132/**
133 * Head of client DLL.
134 */
135static struct ClientHandle *ch_head;
136
137/**
138 * Tail of client DLL.
139 */
140static struct ClientHandle *ch_tail;
141
142/**
143 * DLL of our autoconfiguration operations.
144 */
145static struct AutoconfigContext *ac_head;
146
147/**
148 * DLL of our autoconfiguration operations.
149 */
150static struct AutoconfigContext *ac_tail;
151
152/**
153 * Handle to our current configuration.
154 */
155static const struct GNUNET_CONFIGURATION_Handle *cfg;
156
157/**
158 * Handle to the statistics service.
159 */
160static struct GNUNET_STATISTICS_Handle *stats;
161
162
163/**
164 * Check validity of #GNUNET_MESSAGE_TYPE_NAT_REQUEST_AUTO_CFG message
165 * from client.
166 *
167 * @param cls client who sent the message
168 * @param message the message received
169 * @return #GNUNET_OK if message is well-formed
170 */
171static int
172check_autoconfig_request (void *cls,
173 const struct GNUNET_NAT_AutoconfigRequestMessage *message)
174{
175 return GNUNET_OK; /* checked later */
176}
177
178
179/**
180 * Stop all pending activities with respect to the @a ac
181 *
182 * @param ac autoconfiguration to terminate activities for
183 */
184static void
185terminate_ac_activities (struct AutoconfigContext *ac)
186{
187 if (NULL != ac->timeout_task)
188 {
189 GNUNET_SCHEDULER_cancel (ac->timeout_task);
190 ac->timeout_task = NULL;
191 }
192}
193
194
195/**
196 * Finish handling the autoconfiguration request and send
197 * the response to the client.
198 *
199 * @param cls the `struct AutoconfigContext` to conclude
200 */
201static void
202conclude_autoconfig_request (void *cls)
203{
204 struct AutoconfigContext *ac = cls;
205 struct ClientHandle *ch = ac->ch;
206 struct GNUNET_NAT_AutoconfigResultMessage *arm;
207 struct GNUNET_MQ_Envelope *env;
208 size_t c_size;
209 char *buf;
210 struct GNUNET_CONFIGURATION_Handle *diff;
211
212 ac->timeout_task = NULL;
213 terminate_ac_activities (ac);
214
215 /* Send back response */
216 diff = GNUNET_CONFIGURATION_get_diff (ac->orig,
217 ac->c);
218 buf = GNUNET_CONFIGURATION_serialize (diff,
219 &c_size);
220 GNUNET_CONFIGURATION_destroy (diff);
221 env = GNUNET_MQ_msg_extra (arm,
222 c_size,
223 GNUNET_MESSAGE_TYPE_NAT_AUTO_CFG_RESULT);
224 arm->status_code = htonl ((uint32_t) ac->status_code);
225 arm->type = htonl ((uint32_t) ac->type);
226 GNUNET_memcpy (&arm[1],
227 buf,
228 c_size);
229 GNUNET_free (buf);
230 GNUNET_MQ_send (ch->mq,
231 env);
232
233 /* clean up */
234 GNUNET_CONFIGURATION_destroy (ac->orig);
235 GNUNET_CONFIGURATION_destroy (ac->c);
236 GNUNET_CONTAINER_DLL_remove (ac_head,
237 ac_tail,
238 ac);
239 GNUNET_free (ac);
240 GNUNET_SERVICE_client_continue (ch->client);
241}
242
243
244/**
245 * Check if all autoconfiguration operations have concluded,
246 * and if they have, send the result back to the client.
247 *
248 * @param ac autoconfiguation context to check
249 */
250static void
251check_autoconfig_finished (struct AutoconfigContext *ac)
252{
253 GNUNET_SCHEDULER_cancel (ac->timeout_task);
254 ac->timeout_task
255 = GNUNET_SCHEDULER_add_now (&conclude_autoconfig_request,
256 ac);
257}
258
259
260/**
261 * Update ENABLE_UPNPC configuration option.
262 *
263 * @param ac autoconfiguration to update
264 */
265static void
266update_enable_upnpc_option (struct AutoconfigContext *ac)
267{
268 switch (ac->enable_upnpc)
269 {
270 case GNUNET_YES:
271 GNUNET_CONFIGURATION_set_value_string (ac->c,
272 "NAT",
273 "ENABLE_UPNP",
274 "YES");
275 break;
276 case GNUNET_NO:
277 GNUNET_CONFIGURATION_set_value_string (ac->c,
278 "NAT",
279 "ENABLE_UPNP",
280 "NO");
281 break;
282 case GNUNET_SYSERR:
283 /* We are unsure, do not change option */
284 break;
285 }
286}
287
288
289/**
290 * Handler for #GNUNET_MESSAGE_TYPE_NAT_REQUEST_AUTO_CFG message from
291 * client.
292 *
293 * @param cls client who sent the message
294 * @param message the message received
295 */
296static void
297handle_autoconfig_request (void *cls,
298 const struct GNUNET_NAT_AutoconfigRequestMessage *message)
299{
300 struct ClientHandle *ch = cls;
301 size_t left = ntohs (message->header.size) - sizeof (*message);
302 struct AutoconfigContext *ac;
303
304 ac = GNUNET_new (struct AutoconfigContext);
305 ac->status_code = GNUNET_NAT_ERROR_SUCCESS;
306 ac->ch = ch;
307 ac->c = GNUNET_CONFIGURATION_create ();
308 if (GNUNET_OK !=
309 GNUNET_CONFIGURATION_deserialize (ac->c,
310 (const char *) &message[1],
311 left,
312 GNUNET_NO))
313 {
314 GNUNET_break (0);
315 GNUNET_SERVICE_client_drop (ch->client);
316 GNUNET_CONFIGURATION_destroy (ac->c);
317 GNUNET_free (ac);
318 return;
319 }
320 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
321 "Received REQUEST_AUTO_CONFIG message from client\n");
322
323 GNUNET_CONTAINER_DLL_insert (ac_head,
324 ac_tail,
325 ac);
326 ac->orig
327 = GNUNET_CONFIGURATION_dup (ac->c);
328 ac->timeout_task
329 = GNUNET_SCHEDULER_add_delayed (AUTOCONFIG_TIMEOUT,
330 &conclude_autoconfig_request,
331 ac);
332 ac->enable_upnpc = GNUNET_SYSERR; /* undecided */
333
334 /* Probe for upnpc */
335 if (GNUNET_SYSERR ==
336 GNUNET_OS_check_helper_binary ("upnpc",
337 GNUNET_NO,
338 NULL))
339 {
340 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
341 _("UPnP client `upnpc` command not found, disabling UPnP\n"));
342 ac->enable_upnpc = GNUNET_NO;
343 }
344 else
345 {
346 /* We might at some point be behind NAT, try upnpc */
347 ac->enable_upnpc = GNUNET_YES;
348 }
349 update_enable_upnpc_option (ac);
350
351 /* Finally, check if we are already done */
352 check_autoconfig_finished (ac);
353}
354
355
356/**
357 * Task run during shutdown.
358 *
359 * @param cls unused
360 */
361static void
362shutdown_task (void *cls)
363{
364 struct AutoconfigContext *ac;
365
366 while (NULL != (ac = ac_head))
367 {
368 GNUNET_CONTAINER_DLL_remove (ac_head,
369 ac_tail,
370 ac);
371 terminate_ac_activities (ac);
372 GNUNET_free (ac);
373 }
374 if (NULL != stats)
375 {
376 GNUNET_STATISTICS_destroy (stats,
377 GNUNET_NO);
378 stats = NULL;
379 }
380}
381
382
383/**
384 * Setup NAT service.
385 *
386 * @param cls closure
387 * @param c configuration to use
388 * @param service the initialized service
389 */
390static void
391run (void *cls,
392 const struct GNUNET_CONFIGURATION_Handle *c,
393 struct GNUNET_SERVICE_Handle *service)
394{
395 cfg = c;
396 GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
397 NULL);
398 stats = GNUNET_STATISTICS_create ("nat-auto",
399 cfg);
400}
401
402
403/**
404 * Callback called when a client connects to the service.
405 *
406 * @param cls closure for the service
407 * @param c the new client that connected to the service
408 * @param mq the message queue used to send messages to the client
409 * @return a `struct ClientHandle`
410 */
411static void *
412client_connect_cb (void *cls,
413 struct GNUNET_SERVICE_Client *c,
414 struct GNUNET_MQ_Handle *mq)
415{
416 struct ClientHandle *ch;
417
418 ch = GNUNET_new (struct ClientHandle);
419 ch->mq = mq;
420 ch->client = c;
421 GNUNET_CONTAINER_DLL_insert (ch_head,
422 ch_tail,
423 ch);
424 return ch;
425}
426
427
428/**
429 * Callback called when a client disconnected from the service
430 *
431 * @param cls closure for the service
432 * @param c the client that disconnected
433 * @param internal_cls a `struct ClientHandle *`
434 */
435static void
436client_disconnect_cb (void *cls,
437 struct GNUNET_SERVICE_Client *c,
438 void *internal_cls)
439{
440 struct ClientHandle *ch = internal_cls;
441
442 GNUNET_CONTAINER_DLL_remove (ch_head,
443 ch_tail,
444 ch);
445 GNUNET_free (ch);
446}
447
448
449/**
450 * Define "main" method using service macro.
451 */
452GNUNET_SERVICE_MAIN
453("nat",
454 GNUNET_SERVICE_OPTION_NONE,
455 &run,
456 &client_connect_cb,
457 &client_disconnect_cb,
458 NULL,
459 GNUNET_MQ_hd_var_size (autoconfig_request,
460 GNUNET_MESSAGE_TYPE_NAT_AUTO_REQUEST_CFG,
461 struct GNUNET_NAT_AutoconfigRequestMessage,
462 NULL),
463 GNUNET_MQ_handler_end ());
464
465
466#if defined(LINUX) && defined(__GLIBC__)
467#include <malloc.h>
468
469/**
470 * MINIMIZE heap size (way below 128k) since this process doesn't need much.
471 */
472void __attribute__ ((constructor))
473GNUNET_ARM_memory_init ()
474{
475 mallopt (M_TRIM_THRESHOLD, 4 * 1024);
476 mallopt (M_TOP_PAD, 1 * 1024);
477 malloc_trim (0);
478}
479#endif
480
481/* end of gnunet-service-nat.c */
diff --git a/src/nat-auto/nat-auto.conf.in b/src/nat-auto/nat-auto.conf.in
new file mode 100644
index 000000000..daa3e389d
--- /dev/null
+++ b/src/nat-auto/nat-auto.conf.in
@@ -0,0 +1,15 @@
1[nat]
2AUTOSTART = @AUTOSTART@
3@UNIXONLY@ PORT = 2124
4HOSTNAME = localhost
5BINARY = gnunet-service-nat-auto
6ACCEPT_FROM = 127.0.0.1;
7ACCEPT_FROM6 = ::1;
8UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-nat-auto.sock
9UNIX_MATCH_UID = YES
10UNIX_MATCH_GID = YES
11
12[gnunet-nat-server]
13HOSTNAME = gnunet.org
14PORT = 5724
15NOARMBIND = YES
diff --git a/src/nat-auto/nat-auto.h b/src/nat-auto/nat-auto.h
new file mode 100644
index 000000000..150dc32c2
--- /dev/null
+++ b/src/nat-auto/nat-auto.h
@@ -0,0 +1,110 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2011, 2016, 2017 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-auto/nat-auto.h
23 * @brief Messages for interaction with gnunet-nat-auto-service
24 * @author Christian Grothoff
25 *
26 */
27#ifndef NAT_AUTO_H
28#define NAT_AUTO_H
29#include "gnunet_util_lib.h"
30
31
32
33GNUNET_NETWORK_STRUCT_BEGIN
34
35/**
36 * Request to test NAT traversal, sent to the gnunet-nat-server
37 * (not the service!).
38 */
39struct GNUNET_NAT_TestMessage
40{
41 /**
42 * Header with type #GNUNET_MESSAGE_TYPE_NAT_TEST
43 */
44 struct GNUNET_MessageHeader header;
45
46 /**
47 * IPv4 target IP address
48 */
49 uint32_t dst_ipv4;
50
51 /**
52 * Port to use, 0 to send dummy ICMP response.
53 */
54 uint16_t dport;
55
56 /**
57 * Data to send OR advertised-port (in NBO) to use for dummy ICMP.
58 */
59 uint16_t data;
60
61 /**
62 * #GNUNET_YES for TCP, #GNUNET_NO for UDP.
63 */
64 int32_t is_tcp;
65
66};
67
68
69/**
70 * Client requesting automatic configuration.
71 */
72struct GNUNET_NAT_AutoconfigRequestMessage
73{
74 /**
75 * Header with type #GNUNET_MESSAGE_TYPE_NAT_REQUEST_AUTO_CFG
76 */
77 struct GNUNET_MessageHeader header;
78
79 /* Followed by configuration (diff, serialized, compressed) */
80
81};
82
83
84/**
85 * Service responding with proposed configuration.
86 */
87struct GNUNET_NAT_AutoconfigResultMessage
88{
89 /**
90 * Header with type #GNUNET_MESSAGE_TYPE_NAT_AUTO_CFG_RESULT
91 */
92 struct GNUNET_MessageHeader header;
93
94 /**
95 * An `enum GNUNET_NAT_StatusCode` in NBO.
96 */
97 int32_t status_code GNUNET_PACKED;
98
99 /**
100 * An `enum GNUNET_NAT_Type` in NBO.
101 */
102 int32_t type GNUNET_PACKED;
103
104 /* Followed by configuration (diff, serialized, compressed) */
105};
106
107
108GNUNET_NETWORK_STRUCT_END
109
110#endif
diff --git a/src/nat/nat_api_auto.c b/src/nat-auto/nat_auto_api.c
index c5c5fa67a..e6b0512c6 100644
--- a/src/nat/nat_api_auto.c
+++ b/src/nat-auto/nat_auto_api.c
@@ -23,13 +23,13 @@
23 * @author Christian Grothoff 23 * @author Christian Grothoff
24 * @author Milan Bouchet-Valat 24 * @author Milan Bouchet-Valat
25 * 25 *
26 * @file nat/nat_api_auto.c 26 * @file nat/nat_auto_api.c
27 * Routines for NAT auto configuration. 27 * Routines for NAT auto configuration.
28 */ 28 */
29#include "platform.h" 29#include "platform.h"
30#include "gnunet_nat_service.h" 30#include "gnunet_nat_service.h"
31#include "nat.h" 31#include "gnunet_nat_auto_service.h"
32#include "nat_stun.h" 32#include "nat-auto.h"
33 33
34 34
35 35
@@ -248,7 +248,7 @@ GNUNET_NAT_autoconfig_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
248 } 248 }
249 env = GNUNET_MQ_msg_extra (req, 249 env = GNUNET_MQ_msg_extra (req,
250 size, 250 size,
251 GNUNET_MESSAGE_TYPE_NAT_REQUEST_AUTO_CFG); 251 GNUNET_MESSAGE_TYPE_NAT_AUTO_REQUEST_CFG);
252 GNUNET_memcpy (&req[1], 252 GNUNET_memcpy (&req[1],
253 buf, 253 buf,
254 size); 254 size);
diff --git a/src/nat/nat_api_test.c b/src/nat-auto/nat_auto_api_test.c
index d47c14094..056d2a2bf 100644
--- a/src/nat/nat_api_test.c
+++ b/src/nat-auto/nat_auto_api_test.c
@@ -18,14 +18,14 @@
18 Boston, MA 02110-1301, USA. 18 Boston, MA 02110-1301, USA.
19*/ 19*/
20/** 20/**
21 * @file nat/nat_api_test.c 21 * @file nat/nat_auto_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) 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 23 * @author Christian Grothoff
24 */ 24 */
25#include "platform.h" 25#include "platform.h"
26#include "gnunet_util_lib.h" 26#include "gnunet_util_lib.h"
27#include "gnunet_nat_lib.h" 27#include "gnunet_nat_lib.h"
28#include "nat.h" 28#include "nat-auto.h"
29 29
30#define LOG(kind,...) GNUNET_log_from (kind, "nat", __VA_ARGS__) 30#define LOG(kind,...) GNUNET_log_from (kind, "nat", __VA_ARGS__)
31 31
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.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