diff options
author | Christian Grothoff <christian@grothoff.org> | 2012-12-12 19:23:08 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2012-12-12 19:23:08 +0000 |
commit | 6401897402591c23caa12ecf9258dc179368cdc3 (patch) | |
tree | ebf74870b34d26c0e5883acdc679ce1a32bc524f /src/nat | |
parent | e7e67e04dc6afb06cf752c774a4b98a575da5db9 (diff) | |
download | gnunet-6401897402591c23caa12ecf9258dc179368cdc3.tar.gz gnunet-6401897402591c23caa12ecf9258dc179368cdc3.zip |
-starting to move nat autotest code over
Diffstat (limited to 'src/nat')
-rw-r--r-- | src/nat/nat_auto.c | 568 |
1 files changed, 568 insertions, 0 deletions
diff --git a/src/nat/nat_auto.c b/src/nat/nat_auto.c new file mode 100644 index 000000000..50c6c1121 --- /dev/null +++ b/src/nat/nat_auto.c | |||
@@ -0,0 +1,568 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2012 Christian Grothoff (and other contributing authors) | ||
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., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file nat/nat_auto.c | ||
23 | * @brief functions for auto-configuration of the network | ||
24 | * @author Christian Grothoff | ||
25 | */ | ||
26 | #include "platform.h" | ||
27 | #include "gnunet_util_lib.h" | ||
28 | #include "gnunet_nat_lib.h" | ||
29 | #include "nat.h" | ||
30 | |||
31 | #define LOG(kind,...) GNUNET_log_from (kind, "nat", __VA_ARGS__) | ||
32 | |||
33 | |||
34 | /** | ||
35 | * How long do we wait for the NAT test to report success? | ||
36 | */ | ||
37 | #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15) | ||
38 | |||
39 | /** | ||
40 | * Phases of the auto configuration. | ||
41 | */ | ||
42 | enum AutoPhase | ||
43 | { | ||
44 | /** | ||
45 | * Initial start value. | ||
46 | */ | ||
47 | AUTO_INIT = 0, | ||
48 | |||
49 | /** | ||
50 | * Test if we are online. | ||
51 | */ | ||
52 | AUTO_ONLINE = 1, | ||
53 | |||
54 | /** | ||
55 | * Test our external IP. | ||
56 | */ | ||
57 | AUTO_EXTERNAL_IP, | ||
58 | |||
59 | /** | ||
60 | * Test our internal IP. | ||
61 | */ | ||
62 | AUTO_LOCAL_IP, | ||
63 | |||
64 | /** | ||
65 | * Test if NAT was punched. | ||
66 | */ | ||
67 | AUTO_NAT_PUNCHED, | ||
68 | |||
69 | /** | ||
70 | * Test if UPnP is working. | ||
71 | */ | ||
72 | AUTO_UPNPC, | ||
73 | |||
74 | /** | ||
75 | * Test if ICMP server works. | ||
76 | */ | ||
77 | AUTO_ICMP_SERVER, | ||
78 | |||
79 | /** | ||
80 | * Test if ICMP client works. | ||
81 | */ | ||
82 | AUTO_ICMP_CLIENT, | ||
83 | |||
84 | /** | ||
85 | * Last phase, we're done. | ||
86 | */ | ||
87 | AUTO_DONE | ||
88 | |||
89 | }; | ||
90 | |||
91 | |||
92 | /** | ||
93 | * Handle to auto-configuration in progress. | ||
94 | */ | ||
95 | struct GNUNET_NAT_AutoHandle | ||
96 | { | ||
97 | |||
98 | /** | ||
99 | * Handle to the active NAT test. | ||
100 | */ | ||
101 | struct GNUNET_NAT_Test *tst; | ||
102 | |||
103 | /** | ||
104 | * Function to call when done. | ||
105 | */ | ||
106 | GNUNET_NAT_AutoResultCallback fin_cb; | ||
107 | |||
108 | /** | ||
109 | * Closure for 'fin_cb'. | ||
110 | */ | ||
111 | void *fin_cb_cls; | ||
112 | |||
113 | /** | ||
114 | * Handle for active 'GNUNET_NAT_mini_get_external_ipv4'-operation. | ||
115 | */ | ||
116 | struct GNUNET_NAT_ExternalHandle *eh; | ||
117 | |||
118 | /** | ||
119 | * Current configuration (with updates from previous phases) | ||
120 | */ | ||
121 | struct GNUNET_CONFIGURATION_Handle *cfg; | ||
122 | |||
123 | /** | ||
124 | * Original configuration (used to calculate differences) | ||
125 | */ | ||
126 | struct GNUNET_CONFIGURATION_Handle *initial_cfg; | ||
127 | |||
128 | /** | ||
129 | * Task identifier for the timeout. | ||
130 | */ | ||
131 | GNUNET_SCHEDULER_TaskIdentifier tsk; | ||
132 | |||
133 | /** | ||
134 | * Where are we in the test? | ||
135 | */ | ||
136 | enum AutoPhase phase; | ||
137 | |||
138 | }; | ||
139 | |||
140 | |||
141 | /** | ||
142 | * Run the next phase of the auto test. | ||
143 | * | ||
144 | * @param ac auto test handle | ||
145 | */ | ||
146 | static void | ||
147 | next_phase (struct GNUNET_NAT_AutoHandle *ac); | ||
148 | |||
149 | |||
150 | |||
151 | GNUNET_break (0); | ||
152 | return; | ||
153 | } | ||
154 | gtk_toggle_button_set_active (button, on ? TRUE : FALSE); | ||
155 | } | ||
156 | |||
157 | |||
158 | |||
159 | /** | ||
160 | * Function called if NAT failed to confirm success. | ||
161 | * Clean up and update GUI (with failure). | ||
162 | * | ||
163 | * @param cls closure with setup context | ||
164 | * @param tc scheduler callback | ||
165 | */ | ||
166 | static void | ||
167 | fail_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
168 | { | ||
169 | struct GNUNET_NAT_AutoHandle *ac = cls; | ||
170 | |||
171 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
172 | _("NAT traversal with ICMP Server timed out.\n")); | ||
173 | GNUNET_assert (NULL != ac->tst); | ||
174 | ac->tsk = GNUNET_SCHEDULER_NO_TASK; | ||
175 | GNUNET_NAT_test_stop (ac->tst); | ||
176 | ac->tst = NULL; | ||
177 | update_icmp_server_enable_button (GNUNET_NO); | ||
178 | if (NULL != cfg) | ||
179 | GNUNET_CONFIGURATION_set_value_string (cfg, "nat", "ENABLE_ICMP_SERVER", "NO"); | ||
180 | next_phase (ac); | ||
181 | } | ||
182 | |||
183 | |||
184 | /** | ||
185 | * Main function for the connection reversal test. | ||
186 | * | ||
187 | * @param cls the 'int*' for the result | ||
188 | * @param tc scheduler context | ||
189 | */ | ||
190 | static void | ||
191 | reversal_test (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
192 | { | ||
193 | struct GNUNET_NAT_AutoHandle *ac = cls; | ||
194 | |||
195 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
196 | _("Testing connection reversal with ICMP server.\n")); | ||
197 | GNUNET_assert (NULL != cfg); | ||
198 | GNUNET_RESOLVER_connect (cfg); | ||
199 | ac->tst = GNUNET_NAT_test_start (cfg, GNUNET_YES, 0, 0, &result_callback, ac); | ||
200 | if (NULL == ac->tst) | ||
201 | { | ||
202 | next_phase (ac); | ||
203 | return; | ||
204 | } | ||
205 | ac->tsk = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &fail_timeout, ac); | ||
206 | } | ||
207 | |||
208 | |||
209 | /** | ||
210 | * Test if we are online at all. | ||
211 | * | ||
212 | * @param ac auto setup context | ||
213 | */ | ||
214 | static void | ||
215 | test_online (struct GNUNET_NAT_AutoHandle *ac) | ||
216 | { | ||
217 | // FIXME: not implemented | ||
218 | next_phase (ac); | ||
219 | } | ||
220 | |||
221 | |||
222 | /** | ||
223 | * Set our external IPv4 address. | ||
224 | * | ||
225 | * @param cls closure with our setup context | ||
226 | * @param addr the address, NULL on errors | ||
227 | */ | ||
228 | static void | ||
229 | set_external_ipv4 (void *cls, const struct in_addr *addr) | ||
230 | { | ||
231 | struct GNUNET_NAT_AutoHandle *ac = cls; | ||
232 | char buf[INET_ADDRSTRLEN]; | ||
233 | GObject *o; | ||
234 | |||
235 | ac->eh = NULL; | ||
236 | if (NULL == addr) | ||
237 | { | ||
238 | next_phase (ac); | ||
239 | return; | ||
240 | } | ||
241 | /* enable 'behind nat' */ | ||
242 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
243 | _("Detected external IP `%s'\n"), | ||
244 | inet_ntop (AF_INET, | ||
245 | addr, | ||
246 | buf, | ||
247 | sizeof (buf))); | ||
248 | if (NULL != cfg) | ||
249 | GNUNET_CONFIGURATION_set_value_string (cfg, "nat", "BEHIND_NAT", "YES"); | ||
250 | o = GNUNET_SETUP_get_object ("GNUNET_setup_transport_nat_checkbutton"); | ||
251 | gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (o), TRUE); | ||
252 | |||
253 | /* set external IP address */ | ||
254 | if (NULL == inet_ntop (AF_INET, addr, buf, sizeof (buf))) | ||
255 | { | ||
256 | GNUNET_break (0); | ||
257 | next_phase (ac); | ||
258 | return; | ||
259 | } | ||
260 | if (NULL != cfg) | ||
261 | GNUNET_CONFIGURATION_set_value_string (cfg, "nat", "EXTERNAL_ADDRESS", | ||
262 | buf); | ||
263 | o = GNUNET_SETUP_get_object ("GNUNET_setup_transport_external_ip_address_entry"); | ||
264 | gtk_entry_set_text (GTK_ENTRY (o), buf); | ||
265 | next_phase (ac); | ||
266 | } | ||
267 | |||
268 | |||
269 | /** | ||
270 | * Determine our external IPv4 address. | ||
271 | * | ||
272 | * @param ac auto setup context | ||
273 | */ | ||
274 | static void | ||
275 | test_external_ip (struct GNUNET_NAT_AutoHandle *ac) | ||
276 | { | ||
277 | // FIXME: CPS? | ||
278 | /* try to detect external IP */ | ||
279 | ac->eh = GNUNET_NAT_mini_get_external_ipv4 (TIMEOUT, | ||
280 | &set_external_ipv4, ac); | ||
281 | } | ||
282 | |||
283 | |||
284 | /** | ||
285 | * Process list of local IP addresses. Find and set the | ||
286 | * one of the default interface. | ||
287 | * | ||
288 | * @param cls pointer to int to store if we have a non-local IPv6 address | ||
289 | * @param name name of the interface (can be NULL for unknown) | ||
290 | * @param isDefault is this presumably the default interface | ||
291 | * @param addr address of this interface (can be NULL for unknown or unassigned) | ||
292 | * @param broadcast_addr the broadcast address (can be NULL for unknown or unassigned) | ||
293 | * @param netmask the network mask (can be NULL for unknown or unassigned)) | ||
294 | * @param addrlen length of the address | ||
295 | * @return GNUNET_OK to continue iteration, GNUNET_SYSERR to abort | ||
296 | */ | ||
297 | static int | ||
298 | nipo (void *cls, const char *name, int isDefault, const struct sockaddr *addr, | ||
299 | const struct sockaddr *broadcast_addr, const struct sockaddr *netmask, | ||
300 | socklen_t addrlen) | ||
301 | { | ||
302 | int *have_v6 = cls; | ||
303 | const struct sockaddr_in *in; | ||
304 | char buf[INET_ADDRSTRLEN]; | ||
305 | GtkEntry *entry; | ||
306 | |||
307 | if (!isDefault) | ||
308 | return GNUNET_OK; | ||
309 | if ( (sizeof (struct sockaddr_in6) == addrlen) && | ||
310 | (0 != memcmp (&in6addr_loopback, addr, | ||
311 | addrlen)) && | ||
312 | (! IN6_IS_ADDR_LINKLOCAL(addr)) ) | ||
313 | { | ||
314 | *have_v6 = GNUNET_YES; | ||
315 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
316 | _("This system has a global IPv6 address, setting IPv6 to supported.\n")); | ||
317 | return GNUNET_OK; | ||
318 | } | ||
319 | if (addrlen != sizeof (struct sockaddr_in)) | ||
320 | return GNUNET_OK; | ||
321 | in = (const struct sockaddr_in *) addr; | ||
322 | |||
323 | /* set internal IP address */ | ||
324 | if (NULL == inet_ntop (AF_INET, &in->sin_addr, buf, sizeof (buf))) | ||
325 | { | ||
326 | GNUNET_break (0); | ||
327 | return GNUNET_OK; | ||
328 | } | ||
329 | GNUNET_CONFIGURATION_set_value_string (cfg, "nat", "INTERNAL_ADDRESS", buf); | ||
330 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
331 | _("Detected internal network address `%s'.\n"), | ||
332 | buf); | ||
333 | entry = | ||
334 | GTK_ENTRY (GNUNET_SETUP_get_object | ||
335 | ("GNUNET_setup_transport_internal_ip_entry")); | ||
336 | gtk_entry_set_text (entry, buf); | ||
337 | /* no need to continue iteration */ | ||
338 | return GNUNET_SYSERR; | ||
339 | } | ||
340 | |||
341 | |||
342 | /** | ||
343 | * Determine our local IP addresses; detect internal IP & IPv6-support | ||
344 | * | ||
345 | * @param ac auto setup context | ||
346 | */ | ||
347 | static void | ||
348 | test_local_ip (struct GNUNET_NAT_AutoHandle *ac) | ||
349 | { | ||
350 | GtkToggleButton *button; | ||
351 | int have_v6; | ||
352 | |||
353 | have_v6 = GNUNET_NO; | ||
354 | GNUNET_OS_network_interfaces_list (&nipo, &have_v6); | ||
355 | button = GTK_TOGGLE_BUTTON (GNUNET_SETUP_get_object ("GNUNET_setup_transport_disable_ipv6_checkbutton")); | ||
356 | gtk_toggle_button_set_active (button, | ||
357 | (GNUNET_YES == have_v6) ? FALSE : TRUE); | ||
358 | if (NULL != cfg) | ||
359 | GNUNET_CONFIGURATION_set_value_string (cfg, "nat", "DISABLEV6", | ||
360 | (GNUNET_YES == have_v6) ? "NO" : "YES"); | ||
361 | next_phase (ac); | ||
362 | } | ||
363 | |||
364 | |||
365 | /** | ||
366 | * Test if NAT has been punched | ||
367 | * | ||
368 | * @param ac auto setup context | ||
369 | */ | ||
370 | static void | ||
371 | test_nat_punched (struct GNUNET_NAT_AutoHandle *ac) | ||
372 | { | ||
373 | // FIXME: not implemented | ||
374 | next_phase (ac); | ||
375 | } | ||
376 | |||
377 | |||
378 | /** | ||
379 | * Test if UPnPC works. | ||
380 | * | ||
381 | * @param ac auto setup context | ||
382 | */ | ||
383 | static void | ||
384 | test_upnpc (struct GNUNET_NAT_AutoHandle *ac) | ||
385 | { | ||
386 | int have_upnpc; | ||
387 | GtkToggleButton *button; | ||
388 | |||
389 | /* test if upnpc is available */ | ||
390 | button = GTK_TOGGLE_BUTTON (GNUNET_SETUP_get_object ("GNUNET_setup_transport_upnp_enable_checkbutton")); | ||
391 | have_upnpc = (GNUNET_SYSERR != | ||
392 | GNUNET_OS_check_helper_binary ("upnpc")); | ||
393 | /* FIXME: test if upnpc is actually working, that is, if transports | ||
394 | start to work once we use UPnP */ | ||
395 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
396 | (have_upnpc) | ||
397 | ? _("upnpc found, enabling its use\n") | ||
398 | : _("upnpc not found\n")); | ||
399 | gtk_toggle_button_set_active (button, | ||
400 | have_upnpc | ||
401 | ? TRUE | ||
402 | : FALSE); | ||
403 | if (NULL != cfg) | ||
404 | GNUNET_CONFIGURATION_set_value_string (cfg, "nat", "ENABLE_UPNP", | ||
405 | (GNUNET_YES == have_upnpc) ? "YES" : "NO"); | ||
406 | next_phase (ac); | ||
407 | } | ||
408 | |||
409 | |||
410 | /** | ||
411 | * Test if ICMP server is working | ||
412 | * | ||
413 | * @param ac auto setup context | ||
414 | */ | ||
415 | static void | ||
416 | test_icmp_server (struct GNUNET_NAT_AutoHandle *ac) | ||
417 | { | ||
418 | int hns; | ||
419 | char *tmp; | ||
420 | char *binary; | ||
421 | |||
422 | tmp = NULL; | ||
423 | binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-nat-server"); | ||
424 | hns = | ||
425 | ((GNUNET_OK == | ||
426 | GNUNET_CONFIGURATION_get_value_string (cfg, "nat", "EXTERNAL_ADDRESS", | ||
427 | &tmp)) && (0 < strlen (tmp)) && | ||
428 | (GNUNET_YES == | ||
429 | GNUNET_CONFIGURATION_get_value_yesno (cfg, "nat", "BEHIND_NAT")) && | ||
430 | (GNUNET_YES == | ||
431 | GNUNET_OS_check_helper_binary (binary))); | ||
432 | GNUNET_free_non_null (tmp); | ||
433 | GNUNET_free (binary); | ||
434 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
435 | (hns) | ||
436 | ? _("gnunet-helper-nat-server found, testing it\n") | ||
437 | : _("No working gnunet-helper-nat-server found\n")); | ||
438 | if (hns) | ||
439 | GNUNET_SCHEDULER_add_now (&reversal_test, ac); | ||
440 | else | ||
441 | next_phase (ac); | ||
442 | } | ||
443 | |||
444 | |||
445 | /** | ||
446 | * Test if ICMP client is working | ||
447 | * | ||
448 | * @param ac auto setup context | ||
449 | */ | ||
450 | static void | ||
451 | test_icmp_client (struct GNUNET_NAT_AutoHandle *ac) | ||
452 | { | ||
453 | GtkToggleButton *button; | ||
454 | int hnc; | ||
455 | char *tmp; | ||
456 | char *binary; | ||
457 | |||
458 | tmp = NULL; | ||
459 | binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-nat-client"); | ||
460 | hnc = | ||
461 | ((GNUNET_OK == | ||
462 | GNUNET_CONFIGURATION_get_value_string (cfg, "nat", "INTERNAL_ADDRESS", | ||
463 | &tmp)) && (0 < strlen (tmp)) && | ||
464 | (GNUNET_YES != | ||
465 | GNUNET_CONFIGURATION_get_value_yesno (cfg, "nat", "BEHIND_NAT")) && | ||
466 | (GNUNET_YES == | ||
467 | GNUNET_OS_check_helper_binary (binary))); | ||
468 | GNUNET_free_non_null (tmp); | ||
469 | GNUNET_free (binary); | ||
470 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
471 | (hnc) | ||
472 | ? _("gnunet-helper-nat-client found, enabling it\n") | ||
473 | : _("gnunet-helper-nat-client not found or behind NAT, disabling it\n")); | ||
474 | button = | ||
475 | GTK_TOGGLE_BUTTON (GNUNET_SETUP_get_object | ||
476 | ("GNUNET_setup_transport_icmp_client_enable_checkbutton")); | ||
477 | gtk_toggle_button_set_active (button, hnc ? TRUE : FALSE); | ||
478 | next_phase (ac); | ||
479 | } | ||
480 | |||
481 | |||
482 | /** | ||
483 | * Run the next phase of the auto test. | ||
484 | */ | ||
485 | static void | ||
486 | next_phase (struct GNUNET_NAT_AutoHandle *ac) | ||
487 | { | ||
488 | ac->phase++; | ||
489 | switch (ac->phase) | ||
490 | { | ||
491 | case AUTO_INIT: | ||
492 | GNUNET_assert (0); | ||
493 | break; | ||
494 | case AUTO_ONLINE: | ||
495 | test_online (ac); | ||
496 | break; | ||
497 | case AUTO_EXTERNAL_IP: | ||
498 | test_external_ip (ac); | ||
499 | break; | ||
500 | case AUTO_LOCAL_IP: | ||
501 | test_local_ip (ac); | ||
502 | break; | ||
503 | case AUTO_NAT_PUNCHED: | ||
504 | test_nat_punched (ac); | ||
505 | break; | ||
506 | case AUTO_UPNPC: | ||
507 | test_upnpc (ac); | ||
508 | break; | ||
509 | case AUTO_ICMP_SERVER: | ||
510 | test_icmp_server (ac); | ||
511 | break; | ||
512 | case AUTO_ICMP_CLIENT: | ||
513 | test_icmp_client (ac); | ||
514 | break; | ||
515 | case AUTO_DONE: | ||
516 | ac->fin_cb (ac->fin_cb_cls); | ||
517 | GNUNET_free (ac); | ||
518 | return; | ||
519 | } | ||
520 | } | ||
521 | |||
522 | |||
523 | |||
524 | /** | ||
525 | * Start auto-configuration routine. The resolver service should | ||
526 | * be available when this function is called. | ||
527 | * | ||
528 | * @param cfg initial configuration | ||
529 | * @param cb function to call with autoconfiguration result | ||
530 | * @param cb_cls closure for cb | ||
531 | * @return handle to cancel operation | ||
532 | */ | ||
533 | struct GNUNET_NAT_AutoHandle * | ||
534 | GNUNET_NAT_autoconfig_start (const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
535 | GNUNET_NAT_AutoResultCallback cb, | ||
536 | void *cb_cls) | ||
537 | { | ||
538 | struct GNUNET_NAT_AutoHandle *ac; | ||
539 | |||
540 | ac = GNUNET_malloc (sizeof (struct GNUNET_NAT_AutoHandle)); | ||
541 | ac->fin_cb = cb; | ||
542 | ac->fin_cb_cls = cb_cls; | ||
543 | ac->cfg = GNUNET_CONFIGURATION_dup (cfg); | ||
544 | ac->init_cfg = GNUNET_CONFIGURATION_dup (cfg); | ||
545 | |||
546 | /* never use loopback addresses if user wanted autoconfiguration */ | ||
547 | GNUNET_CONFIGURATION_set_value_string (ac->cfg, "nat", | ||
548 | "USE_LOCALADDR", | ||
549 | "NO"); | ||
550 | next_phase (ac); | ||
551 | return ac; | ||
552 | } | ||
553 | |||
554 | |||
555 | |||
556 | /** | ||
557 | * Abort autoconfiguration. | ||
558 | * | ||
559 | * @param ah handle for operation to abort | ||
560 | */ | ||
561 | void | ||
562 | GNUNET_NAT_autoconfig_cancel (struct GNUNET_NAT_AutoHandle *ah) | ||
563 | { | ||
564 | } | ||
565 | |||
566 | |||
567 | |||
568 | /* end of nat_auto.c */ | ||