diff options
Diffstat (limited to 'src/pt')
-rw-r--r-- | src/pt/.gitignore | 6 | ||||
-rw-r--r-- | src/pt/Makefile.am | 114 | ||||
-rw-r--r-- | src/pt/gnunet-daemon-pt.c | 1325 | ||||
-rw-r--r-- | src/pt/pt.conf | 12 | ||||
-rw-r--r-- | src/pt/test_gns_vpn.c | 865 | ||||
-rw-r--r-- | src/pt/test_gns_vpn.conf | 74 | ||||
-rw-r--r-- | src/pt/test_gnunet_vpn.c | 519 | ||||
-rw-r--r-- | src/pt/test_gnunet_vpn.conf | 48 |
8 files changed, 0 insertions, 2963 deletions
diff --git a/src/pt/.gitignore b/src/pt/.gitignore deleted file mode 100644 index ea678ffe5..000000000 --- a/src/pt/.gitignore +++ /dev/null | |||
@@ -1,6 +0,0 @@ | |||
1 | gnunet-daemon-pt | ||
2 | test_gns_vpn | ||
3 | test_gnunet_vpn-4_over | ||
4 | test_gnunet_vpn-4_to_6 | ||
5 | test_gnunet_vpn-6_over | ||
6 | test_gnunet_vpn-6_to_4 | ||
diff --git a/src/pt/Makefile.am b/src/pt/Makefile.am deleted file mode 100644 index 10ae04931..000000000 --- a/src/pt/Makefile.am +++ /dev/null | |||
@@ -1,114 +0,0 @@ | |||
1 | # This Makefile.am is in the public domain | ||
2 | AM_CPPFLAGS = -I$(top_srcdir)/src/include | ||
3 | |||
4 | if USE_COVERAGE | ||
5 | AM_CFLAGS = --coverage -O0 | ||
6 | endif | ||
7 | |||
8 | pkgcfgdir= $(pkgdatadir)/config.d/ | ||
9 | |||
10 | libexecdir= $(pkglibdir)/libexec/ | ||
11 | |||
12 | plugindir = $(libdir)/gnunet | ||
13 | |||
14 | dist_pkgcfg_DATA = \ | ||
15 | pt.conf | ||
16 | |||
17 | libexec_PROGRAMS = \ | ||
18 | gnunet-daemon-pt | ||
19 | |||
20 | gnunet_daemon_pt_SOURCES = \ | ||
21 | gnunet-daemon-pt.c | ||
22 | gnunet_daemon_pt_LDADD = \ | ||
23 | $(top_builddir)/src/vpn/libgnunetvpn.la \ | ||
24 | $(top_builddir)/src/cadet/libgnunetcadet.la \ | ||
25 | $(top_builddir)/src/dht/libgnunetdht.la \ | ||
26 | $(top_builddir)/src/dns/libgnunetdns.la \ | ||
27 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ | ||
28 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
29 | $(GN_LIBINTL) | ||
30 | |||
31 | if HAVE_TESTING | ||
32 | |||
33 | if HAVE_LIBGNURL | ||
34 | LIB_GNURL=@LIBGNURL@ | ||
35 | CPP_GNURL=@LIBGNURL_CPPFLAGS@ | ||
36 | if LINUX | ||
37 | VPN_TEST = \ | ||
38 | test_gnunet_vpn-4_to_6 \ | ||
39 | test_gnunet_vpn-6_to_4 \ | ||
40 | test_gnunet_vpn-6_over \ | ||
41 | test_gnunet_vpn-4_over \ | ||
42 | test_gns_vpn | ||
43 | endif | ||
44 | else | ||
45 | if HAVE_LIBCURL | ||
46 | LIB_GNURL=@LIBCURL@ | ||
47 | CPP_GNURL=@LIBCURL_CPPFLAGS@ | ||
48 | if LINUX | ||
49 | VPN_TEST = \ | ||
50 | test_gnunet_vpn-4_to_6 \ | ||
51 | test_gnunet_vpn-6_to_4 \ | ||
52 | test_gnunet_vpn-6_over \ | ||
53 | test_gnunet_vpn-4_over \ | ||
54 | test_gns_vpn | ||
55 | endif | ||
56 | endif | ||
57 | endif | ||
58 | |||
59 | endif | ||
60 | |||
61 | check_PROGRAMS = $(VPN_TEST) | ||
62 | |||
63 | if ENABLE_TEST_RUN | ||
64 | AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME; | ||
65 | TESTS = $(check_PROGRAMS) | ||
66 | endif | ||
67 | |||
68 | EXTRA_DIST = \ | ||
69 | test_gnunet_vpn.conf \ | ||
70 | test_gns_vpn.conf | ||
71 | |||
72 | |||
73 | |||
74 | test_gns_vpn_SOURCES = \ | ||
75 | test_gns_vpn.c | ||
76 | test_gns_vpn_LDADD = $(MHD_LIBS) $(LIB_GNURL) \ | ||
77 | $(top_builddir)/src/namestore/libgnunetnamestore.la \ | ||
78 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
79 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | ||
80 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
81 | $(top_builddir)/src/util/libgnunetutil.la | ||
82 | test_gns_vpn_CFLAGS = $(MHD_CFLAGS) $(CPP_GNURL) $(AM_CFLAGS) | ||
83 | |||
84 | test_gnunet_vpn_4_over_SOURCES = \ | ||
85 | test_gnunet_vpn.c | ||
86 | test_gnunet_vpn_4_over_LDADD = $(MHD_LIBS) $(LIB_GNURL) \ | ||
87 | $(top_builddir)/src/vpn/libgnunetvpn.la \ | ||
88 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
89 | $(top_builddir)/src/util/libgnunetutil.la | ||
90 | test_gnunet_vpn_4_over_CFLAGS = $(MHD_CFLAGS) $(CPP_GNURL) $(AM_CFLAGS) | ||
91 | |||
92 | test_gnunet_vpn_6_over_SOURCES = \ | ||
93 | test_gnunet_vpn.c | ||
94 | test_gnunet_vpn_6_over_LDADD = $(MHD_LIBS) $(LIB_GNURL) \ | ||
95 | $(top_builddir)/src/vpn/libgnunetvpn.la \ | ||
96 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
97 | $(top_builddir)/src/util/libgnunetutil.la | ||
98 | test_gnunet_vpn_6_over_CFLAGS = $(MHD_CFLAGS) $(CPP_GNURL) $(AM_CFLAGS) | ||
99 | |||
100 | test_gnunet_vpn_4_to_6_SOURCES = \ | ||
101 | test_gnunet_vpn.c | ||
102 | test_gnunet_vpn_4_to_6_LDADD = $(MHD_LIBS) $(LIB_GNURL) \ | ||
103 | $(top_builddir)/src/vpn/libgnunetvpn.la \ | ||
104 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
105 | $(top_builddir)/src/util/libgnunetutil.la | ||
106 | test_gnunet_vpn_4_to_6_CFLAGS = $(MHD_CFLAGS) $(CPP_GNURL) $(AM_CFLAGS) | ||
107 | |||
108 | test_gnunet_vpn_6_to_4_SOURCES = \ | ||
109 | test_gnunet_vpn.c | ||
110 | test_gnunet_vpn_6_to_4_LDADD = $(MHD_LIBS) $(LIB_GNURL) \ | ||
111 | $(top_builddir)/src/vpn/libgnunetvpn.la \ | ||
112 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
113 | $(top_builddir)/src/util/libgnunetutil.la | ||
114 | test_gnunet_vpn_6_to_4_CFLAGS = $(MHD_CFLAGS) $(CPP_GNURL) $(AM_CFLAGS) | ||
diff --git a/src/pt/gnunet-daemon-pt.c b/src/pt/gnunet-daemon-pt.c deleted file mode 100644 index da4374223..000000000 --- a/src/pt/gnunet-daemon-pt.c +++ /dev/null | |||
@@ -1,1325 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2010, 2012, 2017 Christian Grothoff | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | /** | ||
21 | * @file pt/gnunet-daemon-pt.c | ||
22 | * @brief tool to manipulate DNS and VPN services to perform protocol translation (IPvX over GNUnet) | ||
23 | * @author Christian Grothoff | ||
24 | */ | ||
25 | #include "platform.h" | ||
26 | #include "gnunet_util_lib.h" | ||
27 | #include "gnunet_dns_service.h" | ||
28 | #include "gnunet_dnsparser_lib.h" | ||
29 | #include "gnunet_cadet_service.h" | ||
30 | #include "gnunet_tun_lib.h" | ||
31 | #include "gnunet_dht_service.h" | ||
32 | #include "gnunet_vpn_service.h" | ||
33 | #include "gnunet_statistics_service.h" | ||
34 | #include "gnunet_applications.h" | ||
35 | #include "block_dns.h" | ||
36 | |||
37 | |||
38 | /** | ||
39 | * After how long do we time out if we could not get an IP from VPN or CADET? | ||
40 | */ | ||
41 | #define TIMEOUT GNUNET_TIME_UNIT_MINUTES | ||
42 | |||
43 | /** | ||
44 | * How many bytes of payload do we allow at most for a DNS reply? | ||
45 | * Given that this is pretty much limited to loopback, we can be | ||
46 | * pretty high (Linux loopback defaults to 16k, most local UDP packets | ||
47 | * should survive up to 9k (NFS), so 8k should be pretty safe in | ||
48 | * general). | ||
49 | */ | ||
50 | #define MAX_DNS_SIZE (8 * 1024) | ||
51 | |||
52 | /** | ||
53 | * How many channels do we open at most at the same time? | ||
54 | */ | ||
55 | #define MAX_OPEN_TUNNELS 4 | ||
56 | |||
57 | |||
58 | /** | ||
59 | * Which group of DNS records are we currently processing? | ||
60 | */ | ||
61 | enum RequestGroup | ||
62 | { | ||
63 | /** | ||
64 | * DNS answers | ||
65 | */ | ||
66 | ANSWERS = 0, | ||
67 | |||
68 | /** | ||
69 | * DNS authority records | ||
70 | */ | ||
71 | AUTHORITY_RECORDS = 1, | ||
72 | |||
73 | /** | ||
74 | * DNS additional records | ||
75 | */ | ||
76 | ADDITIONAL_RECORDS = 2, | ||
77 | |||
78 | /** | ||
79 | * We're done processing. | ||
80 | */ | ||
81 | END = 3 | ||
82 | }; | ||
83 | |||
84 | |||
85 | /** | ||
86 | * Information tracked per DNS reply that we are processing. | ||
87 | */ | ||
88 | struct ReplyContext | ||
89 | { | ||
90 | /** | ||
91 | * Handle to submit the final result. | ||
92 | */ | ||
93 | struct GNUNET_DNS_RequestHandle *rh; | ||
94 | |||
95 | /** | ||
96 | * DNS packet that is being modified. | ||
97 | */ | ||
98 | struct GNUNET_DNSPARSER_Packet *dns; | ||
99 | |||
100 | /** | ||
101 | * Active redirection request with the VPN. | ||
102 | */ | ||
103 | struct GNUNET_VPN_RedirectionRequest *rr; | ||
104 | |||
105 | /** | ||
106 | * Record for which we have an active redirection request. | ||
107 | */ | ||
108 | struct GNUNET_DNSPARSER_Record *rec; | ||
109 | |||
110 | /** | ||
111 | * Offset in the current record group that is being modified. | ||
112 | */ | ||
113 | unsigned int offset; | ||
114 | |||
115 | /** | ||
116 | * Group that is being modified | ||
117 | */ | ||
118 | enum RequestGroup group; | ||
119 | }; | ||
120 | |||
121 | |||
122 | /** | ||
123 | * Handle to a peer that advertised that it is willing to serve | ||
124 | * as a DNS exit. We try to keep a few channels open and a few | ||
125 | * peers in reserve. | ||
126 | */ | ||
127 | struct CadetExit | ||
128 | { | ||
129 | /** | ||
130 | * Kept in a DLL. | ||
131 | */ | ||
132 | struct CadetExit *next; | ||
133 | |||
134 | /** | ||
135 | * Kept in a DLL. | ||
136 | */ | ||
137 | struct CadetExit *prev; | ||
138 | |||
139 | /** | ||
140 | * Channel we use for DNS requests over CADET, NULL if we did | ||
141 | * not initialize a channel to this peer yet. | ||
142 | */ | ||
143 | struct GNUNET_CADET_Channel *cadet_channel; | ||
144 | |||
145 | /** | ||
146 | * At what time did the peer's advertisement expire? | ||
147 | */ | ||
148 | struct GNUNET_TIME_Absolute expiration; | ||
149 | |||
150 | /** | ||
151 | * Head of DLL of requests waiting for a response. | ||
152 | */ | ||
153 | struct RequestContext *receive_queue_head; | ||
154 | |||
155 | /** | ||
156 | * Tail of DLL of requests waiting for a response. | ||
157 | */ | ||
158 | struct RequestContext *receive_queue_tail; | ||
159 | |||
160 | /** | ||
161 | * Identity of the peer that is providing the exit for us. | ||
162 | */ | ||
163 | struct GNUNET_PeerIdentity peer; | ||
164 | |||
165 | /** | ||
166 | * How many DNS requests did we transmit via this channel? | ||
167 | */ | ||
168 | unsigned int num_transmitted; | ||
169 | |||
170 | /** | ||
171 | * How many DNS requests were answered via this channel? | ||
172 | */ | ||
173 | unsigned int num_answered; | ||
174 | |||
175 | /** | ||
176 | * Size of the window, 0 if we are busy. | ||
177 | */ | ||
178 | /* unsigned */ int idle; | ||
179 | }; | ||
180 | |||
181 | |||
182 | /** | ||
183 | * State we keep for a request that is going out via CADET. | ||
184 | */ | ||
185 | struct RequestContext | ||
186 | { | ||
187 | /** | ||
188 | * We keep these in a DLL. | ||
189 | */ | ||
190 | struct RequestContext *next; | ||
191 | |||
192 | /** | ||
193 | * We keep these in a DLL. | ||
194 | */ | ||
195 | struct RequestContext *prev; | ||
196 | |||
197 | /** | ||
198 | * Exit that was chosen for this request. | ||
199 | */ | ||
200 | struct CadetExit *exit; | ||
201 | |||
202 | /** | ||
203 | * Handle for interaction with DNS service. | ||
204 | */ | ||
205 | struct GNUNET_DNS_RequestHandle *rh; | ||
206 | |||
207 | /** | ||
208 | * Envelope with the request we are transmitting. | ||
209 | */ | ||
210 | struct GNUNET_MQ_Envelope *env; | ||
211 | |||
212 | /** | ||
213 | * Task used to abort this operation with timeout. | ||
214 | */ | ||
215 | struct GNUNET_SCHEDULER_Task *timeout_task; | ||
216 | |||
217 | /** | ||
218 | * Length of the request message that follows this struct. | ||
219 | */ | ||
220 | uint16_t mlen; | ||
221 | |||
222 | /** | ||
223 | * ID of the original DNS request (used to match the reply). | ||
224 | */ | ||
225 | uint16_t dns_id; | ||
226 | }; | ||
227 | |||
228 | |||
229 | /** | ||
230 | * Head of DLL of cadet exits. Cadet exits with an open channel are | ||
231 | * always at the beginning (so we do not have to traverse the entire | ||
232 | * list to find them). | ||
233 | */ | ||
234 | static struct CadetExit *exit_head; | ||
235 | |||
236 | /** | ||
237 | * Tail of DLL of cadet exits. | ||
238 | */ | ||
239 | static struct CadetExit *exit_tail; | ||
240 | |||
241 | /** | ||
242 | * The handle to the configuration used throughout the process | ||
243 | */ | ||
244 | static const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
245 | |||
246 | /** | ||
247 | * The handle to the VPN | ||
248 | */ | ||
249 | static struct GNUNET_VPN_Handle *vpn_handle; | ||
250 | |||
251 | /** | ||
252 | * The handle to the CADET service | ||
253 | */ | ||
254 | static struct GNUNET_CADET_Handle *cadet_handle; | ||
255 | |||
256 | /** | ||
257 | * Statistics. | ||
258 | */ | ||
259 | static struct GNUNET_STATISTICS_Handle *stats; | ||
260 | |||
261 | /** | ||
262 | * The handle to DNS post-resolution modifications. | ||
263 | */ | ||
264 | static struct GNUNET_DNS_Handle *dns_post_handle; | ||
265 | |||
266 | /** | ||
267 | * The handle to DNS pre-resolution modifications. | ||
268 | */ | ||
269 | static struct GNUNET_DNS_Handle *dns_pre_handle; | ||
270 | |||
271 | /** | ||
272 | * Handle to access the DHT. | ||
273 | */ | ||
274 | static struct GNUNET_DHT_Handle *dht; | ||
275 | |||
276 | /** | ||
277 | * Our DHT GET operation to find DNS exits. | ||
278 | */ | ||
279 | static struct GNUNET_DHT_GetHandle *dht_get; | ||
280 | |||
281 | /** | ||
282 | * Are we doing IPv4-pt? | ||
283 | */ | ||
284 | static int ipv4_pt; | ||
285 | |||
286 | /** | ||
287 | * Are we doing IPv6-pt? | ||
288 | */ | ||
289 | static int ipv6_pt; | ||
290 | |||
291 | /** | ||
292 | * Are we channeling DNS queries? | ||
293 | */ | ||
294 | static int dns_channel; | ||
295 | |||
296 | /** | ||
297 | * Number of DNS exit peers we currently have in the cadet channel. | ||
298 | * Used to see if using the cadet channel makes any sense right now, | ||
299 | * as well as to decide if we should open new channels. | ||
300 | */ | ||
301 | static unsigned int dns_exit_available; | ||
302 | |||
303 | |||
304 | /** | ||
305 | * We are short on cadet exits, try to open another one. | ||
306 | */ | ||
307 | static void | ||
308 | try_open_exit (void); | ||
309 | |||
310 | |||
311 | /** | ||
312 | * Compute the weight of the given exit. The higher the weight, | ||
313 | * the more likely it will be that the channel will be chosen. | ||
314 | * A weigt of zero means that we should close the channel as it | ||
315 | * is so bad, that we should not use it. | ||
316 | * | ||
317 | * @param exit exit to calculate the weight for | ||
318 | * @return weight of the channel | ||
319 | */ | ||
320 | static uint32_t | ||
321 | get_channel_weight (struct CadetExit *exit) | ||
322 | { | ||
323 | uint32_t dropped; | ||
324 | uint32_t drop_percent; | ||
325 | uint32_t good_percent; | ||
326 | |||
327 | GNUNET_assert (exit->num_transmitted >= exit->num_answered); | ||
328 | dropped = exit->num_transmitted - exit->num_answered; | ||
329 | if (exit->num_transmitted > 0) | ||
330 | drop_percent = (uint32_t) ((100LL * dropped) / exit->num_transmitted); | ||
331 | else | ||
332 | drop_percent = 50; /* no data */ | ||
333 | if ((exit->num_transmitted > 20) && | ||
334 | (drop_percent > 25)) | ||
335 | return 0; /* statistically significant, and > 25% loss, die */ | ||
336 | good_percent = 100 - drop_percent; | ||
337 | GNUNET_assert (0 != good_percent); | ||
338 | if (UINT32_MAX / good_percent / good_percent < exit->num_transmitted) | ||
339 | return UINT32_MAX; /* formula below would overflow */ | ||
340 | return 1 + good_percent * good_percent * exit->num_transmitted; | ||
341 | } | ||
342 | |||
343 | |||
344 | /** | ||
345 | * Choose a cadet exit for a DNS request. We try to use a channel | ||
346 | * that is reliable and currently available. All existing | ||
347 | * channels are given a base weight of 1, plus a score relating | ||
348 | * to the total number of queries answered in relation to the | ||
349 | * total number of queries we sent to that channel. That | ||
350 | * score is doubled if the channel is currently idle. | ||
351 | * | ||
352 | * @return NULL if no exit is known, otherwise the | ||
353 | * exit that we should use to queue a message with | ||
354 | */ | ||
355 | static struct CadetExit * | ||
356 | choose_exit () | ||
357 | { | ||
358 | struct CadetExit *pos; | ||
359 | uint64_t total_transmitted; | ||
360 | uint64_t selected_offset; | ||
361 | uint32_t channel_weight; | ||
362 | |||
363 | total_transmitted = 0; | ||
364 | for (pos = exit_head; NULL != pos; pos = pos->next) | ||
365 | { | ||
366 | if (NULL == pos->cadet_channel) | ||
367 | break; | ||
368 | channel_weight = get_channel_weight (pos); | ||
369 | total_transmitted += channel_weight; | ||
370 | /* double weight for idle channels */ | ||
371 | if (0 != pos->idle) | ||
372 | total_transmitted += channel_weight; | ||
373 | } | ||
374 | if (0 == total_transmitted) | ||
375 | { | ||
376 | /* no channels available, or only a very bad one... */ | ||
377 | return exit_head; | ||
378 | } | ||
379 | selected_offset = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, | ||
380 | total_transmitted); | ||
381 | total_transmitted = 0; | ||
382 | for (pos = exit_head; NULL != pos; pos = pos->next) | ||
383 | { | ||
384 | if (NULL == pos->cadet_channel) | ||
385 | break; | ||
386 | channel_weight = get_channel_weight (pos); | ||
387 | total_transmitted += channel_weight; | ||
388 | /* double weight for idle channels */ | ||
389 | if (0 != pos->idle) | ||
390 | total_transmitted += channel_weight; | ||
391 | if (total_transmitted > selected_offset) | ||
392 | return pos; | ||
393 | } | ||
394 | GNUNET_break (0); | ||
395 | return NULL; | ||
396 | } | ||
397 | |||
398 | |||
399 | /** | ||
400 | * We're done modifying all records in the response. Submit the reply | ||
401 | * and free the resources of the rc. | ||
402 | * | ||
403 | * @param rc context to process | ||
404 | */ | ||
405 | static void | ||
406 | finish_request (struct ReplyContext *rc) | ||
407 | { | ||
408 | char *buf; | ||
409 | size_t buf_len; | ||
410 | |||
411 | if (GNUNET_SYSERR == | ||
412 | GNUNET_DNSPARSER_pack (rc->dns, | ||
413 | MAX_DNS_SIZE, | ||
414 | &buf, | ||
415 | &buf_len)) | ||
416 | { | ||
417 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
418 | _ ("Failed to pack DNS request. Dropping.\n")); | ||
419 | GNUNET_DNS_request_drop (rc->rh); | ||
420 | } | ||
421 | else | ||
422 | { | ||
423 | GNUNET_STATISTICS_update (stats, | ||
424 | gettext_noop ("# DNS requests mapped to VPN"), | ||
425 | 1, GNUNET_NO); | ||
426 | GNUNET_DNS_request_answer (rc->rh, | ||
427 | buf_len, | ||
428 | buf); | ||
429 | GNUNET_free (buf); | ||
430 | } | ||
431 | GNUNET_DNSPARSER_free_packet (rc->dns); | ||
432 | GNUNET_free (rc); | ||
433 | } | ||
434 | |||
435 | |||
436 | /** | ||
437 | * Process the next record of the given request context. | ||
438 | * When done, submit the reply and free the resources of | ||
439 | * the rc. | ||
440 | * | ||
441 | * @param rc context to process | ||
442 | */ | ||
443 | static void | ||
444 | submit_request (struct ReplyContext *rc); | ||
445 | |||
446 | |||
447 | /** | ||
448 | * Callback invoked from the VPN service once a redirection is | ||
449 | * available. Provides the IP address that can now be used to | ||
450 | * reach the requested destination. We substitute the active | ||
451 | * record and then continue with 'submit_request' to look at | ||
452 | * the other records. | ||
453 | * | ||
454 | * @param cls our `struct ReplyContext` | ||
455 | * @param af address family, AF_INET or AF_INET6; AF_UNSPEC on error; | ||
456 | * will match 'result_af' from the request | ||
457 | * @param address IP address (struct in_addr or struct in_addr6, depending on 'af') | ||
458 | * that the VPN allocated for the redirection; | ||
459 | * traffic to this IP will now be redirected to the | ||
460 | * specified target peer; NULL on error | ||
461 | */ | ||
462 | static void | ||
463 | vpn_allocation_callback (void *cls, | ||
464 | int af, | ||
465 | const void *address) | ||
466 | { | ||
467 | struct ReplyContext *rc = cls; | ||
468 | |||
469 | rc->rr = NULL; | ||
470 | if (af == AF_UNSPEC) | ||
471 | { | ||
472 | GNUNET_DNS_request_drop (rc->rh); | ||
473 | GNUNET_DNSPARSER_free_packet (rc->dns); | ||
474 | GNUNET_free (rc); | ||
475 | return; | ||
476 | } | ||
477 | GNUNET_STATISTICS_update (stats, | ||
478 | gettext_noop ("# DNS records modified"), | ||
479 | 1, | ||
480 | GNUNET_NO); | ||
481 | switch (rc->rec->type) | ||
482 | { | ||
483 | case GNUNET_DNSPARSER_TYPE_A: | ||
484 | GNUNET_assert (AF_INET == af); | ||
485 | GNUNET_memcpy (rc->rec->data.raw.data, | ||
486 | address, | ||
487 | sizeof(struct in_addr)); | ||
488 | break; | ||
489 | |||
490 | case GNUNET_DNSPARSER_TYPE_AAAA: | ||
491 | GNUNET_assert (AF_INET6 == af); | ||
492 | GNUNET_memcpy (rc->rec->data.raw.data, | ||
493 | address, | ||
494 | sizeof(struct in6_addr)); | ||
495 | break; | ||
496 | |||
497 | default: | ||
498 | GNUNET_assert (0); | ||
499 | return; | ||
500 | } | ||
501 | rc->rec = NULL; | ||
502 | submit_request (rc); | ||
503 | } | ||
504 | |||
505 | |||
506 | /** | ||
507 | * Modify the given DNS record by asking VPN to create a channel | ||
508 | * to the given address. When done, continue with submitting | ||
509 | * other records from the request context ('submit_request' is | ||
510 | * our continuation). | ||
511 | * | ||
512 | * @param rc context to process | ||
513 | * @param rec record to modify | ||
514 | */ | ||
515 | static void | ||
516 | modify_address (struct ReplyContext *rc, | ||
517 | struct GNUNET_DNSPARSER_Record *rec) | ||
518 | { | ||
519 | int af; | ||
520 | |||
521 | switch (rec->type) | ||
522 | { | ||
523 | case GNUNET_DNSPARSER_TYPE_A: | ||
524 | af = AF_INET; | ||
525 | GNUNET_assert (rec->data.raw.data_len == sizeof(struct in_addr)); | ||
526 | break; | ||
527 | |||
528 | case GNUNET_DNSPARSER_TYPE_AAAA: | ||
529 | af = AF_INET6; | ||
530 | GNUNET_assert (rec->data.raw.data_len == sizeof(struct in6_addr)); | ||
531 | break; | ||
532 | |||
533 | default: | ||
534 | GNUNET_assert (0); | ||
535 | return; | ||
536 | } | ||
537 | rc->rec = rec; | ||
538 | rc->rr = GNUNET_VPN_redirect_to_ip (vpn_handle, | ||
539 | af, | ||
540 | af, | ||
541 | rec->data.raw.data, | ||
542 | GNUNET_TIME_relative_to_absolute ( | ||
543 | TIMEOUT), | ||
544 | &vpn_allocation_callback, | ||
545 | rc); | ||
546 | } | ||
547 | |||
548 | |||
549 | /** | ||
550 | * Process the next record of the given request context. | ||
551 | * When done, submit the reply and free the resources of | ||
552 | * the rc. | ||
553 | * | ||
554 | * @param rc context to process | ||
555 | */ | ||
556 | static void | ||
557 | submit_request (struct ReplyContext *rc) | ||
558 | { | ||
559 | struct GNUNET_DNSPARSER_Record *ra; | ||
560 | unsigned int ra_len; | ||
561 | unsigned int i; | ||
562 | |||
563 | while (1) | ||
564 | { | ||
565 | switch (rc->group) | ||
566 | { | ||
567 | case ANSWERS: | ||
568 | ra = rc->dns->answers; | ||
569 | ra_len = rc->dns->num_answers; | ||
570 | break; | ||
571 | |||
572 | case AUTHORITY_RECORDS: | ||
573 | ra = rc->dns->authority_records; | ||
574 | ra_len = rc->dns->num_authority_records; | ||
575 | break; | ||
576 | |||
577 | case ADDITIONAL_RECORDS: | ||
578 | ra = rc->dns->additional_records; | ||
579 | ra_len = rc->dns->num_additional_records; | ||
580 | break; | ||
581 | |||
582 | case END: | ||
583 | finish_request (rc); | ||
584 | return; | ||
585 | |||
586 | default: | ||
587 | GNUNET_assert (0); | ||
588 | } | ||
589 | for (i = rc->offset; i < ra_len; i++) | ||
590 | { | ||
591 | switch (ra[i].type) | ||
592 | { | ||
593 | case GNUNET_DNSPARSER_TYPE_A: | ||
594 | if (ipv4_pt) | ||
595 | { | ||
596 | rc->offset = i + 1; | ||
597 | modify_address (rc, | ||
598 | &ra[i]); | ||
599 | return; | ||
600 | } | ||
601 | break; | ||
602 | |||
603 | case GNUNET_DNSPARSER_TYPE_AAAA: | ||
604 | if (ipv6_pt) | ||
605 | { | ||
606 | rc->offset = i + 1; | ||
607 | modify_address (rc, | ||
608 | &ra[i]); | ||
609 | return; | ||
610 | } | ||
611 | break; | ||
612 | } | ||
613 | } | ||
614 | rc->group++; | ||
615 | } | ||
616 | } | ||
617 | |||
618 | |||
619 | /** | ||
620 | * Test if any of the given records need protocol-translation work. | ||
621 | * | ||
622 | * @param ra array of records | ||
623 | * @param ra_len number of entries in @a ra | ||
624 | * @return #GNUNET_YES if any of the given records require protocol-translation | ||
625 | */ | ||
626 | static int | ||
627 | work_test (const struct GNUNET_DNSPARSER_Record *ra, | ||
628 | unsigned int ra_len) | ||
629 | { | ||
630 | unsigned int i; | ||
631 | |||
632 | for (i = 0; i < ra_len; i++) | ||
633 | { | ||
634 | switch (ra[i].type) | ||
635 | { | ||
636 | case GNUNET_DNSPARSER_TYPE_A: | ||
637 | if (ipv4_pt) | ||
638 | return GNUNET_YES; | ||
639 | break; | ||
640 | |||
641 | case GNUNET_DNSPARSER_TYPE_AAAA: | ||
642 | if (ipv6_pt) | ||
643 | return GNUNET_YES; | ||
644 | break; | ||
645 | } | ||
646 | } | ||
647 | return GNUNET_NO; | ||
648 | } | ||
649 | |||
650 | |||
651 | /** | ||
652 | * This function is called AFTER we got an IP address for a | ||
653 | * DNS request. Now, the PT daemon has the chance to substitute | ||
654 | * the IP address with one from the VPN range to channel requests | ||
655 | * destined for this IP address via VPN and CADET. | ||
656 | * | ||
657 | * @param cls closure | ||
658 | * @param rh request handle to user for reply | ||
659 | * @param request_length number of bytes in request | ||
660 | * @param request udp payload of the DNS request | ||
661 | */ | ||
662 | static void | ||
663 | dns_post_request_handler (void *cls, | ||
664 | struct GNUNET_DNS_RequestHandle *rh, | ||
665 | size_t request_length, | ||
666 | const char *request) | ||
667 | { | ||
668 | struct GNUNET_DNSPARSER_Packet *dns; | ||
669 | struct ReplyContext *rc; | ||
670 | int work; | ||
671 | |||
672 | GNUNET_STATISTICS_update (stats, | ||
673 | gettext_noop ("# DNS replies intercepted"), | ||
674 | 1, GNUNET_NO); | ||
675 | dns = GNUNET_DNSPARSER_parse (request, | ||
676 | request_length); | ||
677 | if (NULL == dns) | ||
678 | { | ||
679 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
680 | _ ("Failed to parse DNS request. Dropping.\n")); | ||
681 | GNUNET_DNS_request_drop (rh); | ||
682 | return; | ||
683 | } | ||
684 | work = GNUNET_NO; | ||
685 | work |= work_test (dns->answers, | ||
686 | dns->num_answers); | ||
687 | work |= work_test (dns->authority_records, | ||
688 | dns->num_authority_records); | ||
689 | work |= work_test (dns->additional_records, | ||
690 | dns->num_additional_records); | ||
691 | if (! work) | ||
692 | { | ||
693 | GNUNET_DNS_request_forward (rh); | ||
694 | GNUNET_DNSPARSER_free_packet (dns); | ||
695 | return; | ||
696 | } | ||
697 | rc = GNUNET_new (struct ReplyContext); | ||
698 | rc->rh = rh; | ||
699 | rc->dns = dns; | ||
700 | rc->offset = 0; | ||
701 | rc->group = ANSWERS; | ||
702 | submit_request (rc); | ||
703 | } | ||
704 | |||
705 | |||
706 | /** | ||
707 | * Task run if the time to answer a DNS request via CADET is over. | ||
708 | * | ||
709 | * @param cls the `struct RequestContext` to abort | ||
710 | */ | ||
711 | static void | ||
712 | timeout_request (void *cls) | ||
713 | { | ||
714 | struct RequestContext *rc = cls; | ||
715 | struct CadetExit *exit = rc->exit; | ||
716 | |||
717 | GNUNET_STATISTICS_update (stats, | ||
718 | gettext_noop ("# DNS requests dropped (timeout)"), | ||
719 | 1, | ||
720 | GNUNET_NO); | ||
721 | GNUNET_DNS_request_drop (rc->rh); | ||
722 | GNUNET_free (rc); | ||
723 | if ((0 == get_channel_weight (exit)) && | ||
724 | (NULL == exit->receive_queue_head)) | ||
725 | { | ||
726 | /* this straw broke the camel's back: this channel now has | ||
727 | such a low score that it will not be used; close it! */ | ||
728 | GNUNET_CADET_channel_destroy (exit->cadet_channel); | ||
729 | exit->cadet_channel = NULL; | ||
730 | GNUNET_CONTAINER_DLL_remove (exit_head, | ||
731 | exit_tail, | ||
732 | exit); | ||
733 | GNUNET_CONTAINER_DLL_insert_tail (exit_head, | ||
734 | exit_tail, | ||
735 | exit); | ||
736 | /* go back to semi-innocent: mark as not great, but | ||
737 | avoid a prohibitively negative score (see | ||
738 | #get_channel_weight(), which checks for a certain | ||
739 | minimum number of transmissions before making | ||
740 | up an opinion) */exit->num_transmitted = 5; | ||
741 | exit->num_answered = 0; | ||
742 | dns_exit_available--; | ||
743 | /* now try to open an alternative exit */ | ||
744 | try_open_exit (); | ||
745 | } | ||
746 | } | ||
747 | |||
748 | |||
749 | /** | ||
750 | * This function is called *before* the DNS request has been | ||
751 | * given to a "local" DNS resolver. Channeling for DNS requests | ||
752 | * was enabled, so we now need to send the request via some CADET | ||
753 | * channel to a DNS EXIT for resolution. | ||
754 | * | ||
755 | * @param cls closure | ||
756 | * @param rh request handle to user for reply | ||
757 | * @param request_length number of bytes in request | ||
758 | * @param request udp payload of the DNS request | ||
759 | */ | ||
760 | static void | ||
761 | dns_pre_request_handler (void *cls, | ||
762 | struct GNUNET_DNS_RequestHandle *rh, | ||
763 | size_t request_length, | ||
764 | const char *request) | ||
765 | { | ||
766 | struct RequestContext *rc; | ||
767 | struct GNUNET_MQ_Envelope *env; | ||
768 | struct GNUNET_MessageHeader *hdr; | ||
769 | struct GNUNET_TUN_DnsHeader dns; | ||
770 | struct CadetExit *exit; | ||
771 | |||
772 | GNUNET_STATISTICS_update (stats, | ||
773 | gettext_noop ("# DNS requests intercepted"), | ||
774 | 1, GNUNET_NO); | ||
775 | if (0 == dns_exit_available) | ||
776 | { | ||
777 | GNUNET_STATISTICS_update (stats, | ||
778 | gettext_noop ( | ||
779 | "# DNS requests dropped (DNS cadet channel down)"), | ||
780 | 1, GNUNET_NO); | ||
781 | GNUNET_DNS_request_drop (rh); | ||
782 | return; | ||
783 | } | ||
784 | if (request_length < sizeof(dns)) | ||
785 | { | ||
786 | GNUNET_STATISTICS_update (stats, | ||
787 | gettext_noop ( | ||
788 | "# DNS requests dropped (malformed)"), | ||
789 | 1, GNUNET_NO); | ||
790 | GNUNET_DNS_request_drop (rh); | ||
791 | return; | ||
792 | } | ||
793 | exit = choose_exit (); | ||
794 | GNUNET_assert (NULL != exit); | ||
795 | GNUNET_assert (NULL != exit->cadet_channel); | ||
796 | |||
797 | env = GNUNET_MQ_msg_extra (hdr, | ||
798 | request_length, | ||
799 | GNUNET_MESSAGE_TYPE_VPN_DNS_TO_INTERNET); | ||
800 | GNUNET_memcpy (&hdr[1], | ||
801 | request, | ||
802 | request_length); | ||
803 | rc = GNUNET_new (struct RequestContext); | ||
804 | rc->exit = exit; | ||
805 | rc->rh = rh; | ||
806 | rc->timeout_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, | ||
807 | &timeout_request, | ||
808 | rc); | ||
809 | GNUNET_memcpy (&dns, | ||
810 | request, | ||
811 | sizeof(dns)); | ||
812 | rc->dns_id = dns.id; | ||
813 | rc->env = env; | ||
814 | GNUNET_CONTAINER_DLL_remove (exit->receive_queue_head, | ||
815 | exit->receive_queue_tail, | ||
816 | rc); | ||
817 | if (0 < exit->idle) | ||
818 | exit->idle--; | ||
819 | exit->num_transmitted++; | ||
820 | GNUNET_MQ_send (GNUNET_CADET_get_mq (exit->cadet_channel), | ||
821 | GNUNET_MQ_env_copy (env)); | ||
822 | } | ||
823 | |||
824 | |||
825 | GNUNET_NETWORK_STRUCT_BEGIN | ||
826 | |||
827 | /** | ||
828 | * Message with a DNS response. | ||
829 | */ | ||
830 | struct DnsResponseMessage | ||
831 | { | ||
832 | /** | ||
833 | * GNUnet header, of type #GNUNET_MESSAGE_TYPE_VPN_DNS_FROM_INTERNET | ||
834 | */ | ||
835 | struct GNUNET_MessageHeader header; | ||
836 | |||
837 | /** | ||
838 | * DNS header. | ||
839 | */ | ||
840 | struct GNUNET_TUN_DnsHeader dns; | ||
841 | |||
842 | /* Followed by more DNS payload */ | ||
843 | }; | ||
844 | |||
845 | GNUNET_NETWORK_STRUCT_END | ||
846 | |||
847 | /** | ||
848 | * Process a request via cadet to perform a DNS query. | ||
849 | * | ||
850 | * @param cls the `struct CadetExit` which got the message | ||
851 | * @param msg the actual message | ||
852 | * @return #GNUNET_OK to keep the connection open, | ||
853 | * #GNUNET_SYSERR to close it (signal serious error) | ||
854 | */ | ||
855 | static int | ||
856 | check_dns_response (void *cls, | ||
857 | const struct DnsResponseMessage *msg) | ||
858 | { | ||
859 | return GNUNET_OK; /* all OK */ | ||
860 | } | ||
861 | |||
862 | |||
863 | /** | ||
864 | * Process a request via cadet to perform a DNS query. | ||
865 | * | ||
866 | * @param cls the `struct CadetExit` which got the message | ||
867 | * @param msg the actual message | ||
868 | */ | ||
869 | static void | ||
870 | handle_dns_response (void *cls, | ||
871 | const struct DnsResponseMessage *msg) | ||
872 | { | ||
873 | struct CadetExit *exit = cls; | ||
874 | size_t mlen; | ||
875 | struct RequestContext *rc; | ||
876 | |||
877 | mlen = ntohs (msg->header.size) - sizeof(*msg); | ||
878 | for (rc = exit->receive_queue_head; NULL != rc; rc = rc->next) | ||
879 | { | ||
880 | if (msg->dns.id == rc->dns_id) | ||
881 | { | ||
882 | GNUNET_STATISTICS_update (stats, | ||
883 | gettext_noop ("# DNS replies received"), | ||
884 | 1, | ||
885 | GNUNET_NO); | ||
886 | GNUNET_DNS_request_answer (rc->rh, | ||
887 | mlen + sizeof(struct GNUNET_TUN_DnsHeader), | ||
888 | (const void *) &msg->dns); | ||
889 | GNUNET_CONTAINER_DLL_remove (exit->receive_queue_head, | ||
890 | exit->receive_queue_tail, | ||
891 | rc); | ||
892 | GNUNET_SCHEDULER_cancel (rc->timeout_task); | ||
893 | GNUNET_MQ_discard (rc->env); | ||
894 | GNUNET_free (rc); | ||
895 | exit->num_answered++; | ||
896 | return; | ||
897 | } | ||
898 | } | ||
899 | GNUNET_STATISTICS_update (stats, | ||
900 | gettext_noop ("# DNS replies dropped (too late?)"), | ||
901 | 1, GNUNET_NO); | ||
902 | } | ||
903 | |||
904 | |||
905 | /** | ||
906 | * Abort all pending DNS requests with the given cadet exit. | ||
907 | * | ||
908 | * @param exit cadet exit to abort requests for | ||
909 | */ | ||
910 | static void | ||
911 | abort_all_requests (struct CadetExit *exit) | ||
912 | { | ||
913 | struct RequestContext *rc; | ||
914 | |||
915 | while (NULL != (rc = exit->receive_queue_head)) | ||
916 | { | ||
917 | GNUNET_CONTAINER_DLL_remove (exit->receive_queue_head, | ||
918 | exit->receive_queue_tail, | ||
919 | rc); | ||
920 | GNUNET_DNS_request_drop (rc->rh); | ||
921 | GNUNET_SCHEDULER_cancel (rc->timeout_task); | ||
922 | GNUNET_MQ_discard (rc->env); | ||
923 | GNUNET_free (rc); | ||
924 | } | ||
925 | } | ||
926 | |||
927 | |||
928 | /** | ||
929 | * Function scheduled as very last function, cleans up after us | ||
930 | * | ||
931 | * @param cls closure, NULL | ||
932 | */ | ||
933 | static void | ||
934 | cleanup (void *cls) | ||
935 | { | ||
936 | struct CadetExit *exit; | ||
937 | |||
938 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
939 | "Protocol translation daemon is shutting down now\n"); | ||
940 | if (NULL != vpn_handle) | ||
941 | { | ||
942 | GNUNET_VPN_disconnect (vpn_handle); | ||
943 | vpn_handle = NULL; | ||
944 | } | ||
945 | while (NULL != (exit = exit_head)) | ||
946 | { | ||
947 | GNUNET_CONTAINER_DLL_remove (exit_head, | ||
948 | exit_tail, | ||
949 | exit); | ||
950 | if (NULL != exit->cadet_channel) | ||
951 | { | ||
952 | GNUNET_CADET_channel_destroy (exit->cadet_channel); | ||
953 | exit->cadet_channel = NULL; | ||
954 | } | ||
955 | abort_all_requests (exit); | ||
956 | GNUNET_free (exit); | ||
957 | } | ||
958 | if (NULL != cadet_handle) | ||
959 | { | ||
960 | GNUNET_CADET_disconnect (cadet_handle); | ||
961 | cadet_handle = NULL; | ||
962 | } | ||
963 | if (NULL != dns_post_handle) | ||
964 | { | ||
965 | GNUNET_DNS_disconnect (dns_post_handle); | ||
966 | dns_post_handle = NULL; | ||
967 | } | ||
968 | if (NULL != dns_pre_handle) | ||
969 | { | ||
970 | GNUNET_DNS_disconnect (dns_pre_handle); | ||
971 | dns_pre_handle = NULL; | ||
972 | } | ||
973 | if (NULL != stats) | ||
974 | { | ||
975 | GNUNET_STATISTICS_destroy (stats, GNUNET_YES); | ||
976 | stats = NULL; | ||
977 | } | ||
978 | if (NULL != dht_get) | ||
979 | { | ||
980 | GNUNET_DHT_get_stop (dht_get); | ||
981 | dht_get = NULL; | ||
982 | } | ||
983 | if (NULL != dht) | ||
984 | { | ||
985 | GNUNET_DHT_disconnect (dht); | ||
986 | dht = NULL; | ||
987 | } | ||
988 | } | ||
989 | |||
990 | |||
991 | /** | ||
992 | * Function called whenever a channel is destroyed. Should clean up | ||
993 | * the associated state and attempt to build a new one. | ||
994 | * | ||
995 | * It must NOT call #GNUNET_CADET_channel_destroy on the channel. | ||
996 | * | ||
997 | * @param cls closure (the `struct CadetExit` set from #GNUNET_CADET_connect) | ||
998 | * @param channel connection to the other end (henceforth invalid) | ||
999 | * @param channel_ctx place where local state associated | ||
1000 | * with the channel is stored | ||
1001 | */ | ||
1002 | static void | ||
1003 | cadet_channel_end_cb (void *cls, | ||
1004 | const struct GNUNET_CADET_Channel *channel) | ||
1005 | { | ||
1006 | struct CadetExit *exit = cls; | ||
1007 | struct CadetExit *alt; | ||
1008 | struct RequestContext *rc; | ||
1009 | |||
1010 | exit->cadet_channel = NULL; | ||
1011 | dns_exit_available--; | ||
1012 | /* open alternative channels */ | ||
1013 | /* our channel is now closed, move our requests to an alternative | ||
1014 | channel */ | ||
1015 | alt = choose_exit (); | ||
1016 | while (NULL != (rc = exit->receive_queue_head)) | ||
1017 | { | ||
1018 | GNUNET_CONTAINER_DLL_remove (exit->receive_queue_head, | ||
1019 | exit->receive_queue_tail, | ||
1020 | rc); | ||
1021 | rc->exit = alt; | ||
1022 | GNUNET_CONTAINER_DLL_insert (alt->receive_queue_head, | ||
1023 | alt->receive_queue_tail, | ||
1024 | rc); | ||
1025 | GNUNET_MQ_send (GNUNET_CADET_get_mq (alt->cadet_channel), | ||
1026 | GNUNET_MQ_env_copy (rc->env)); | ||
1027 | } | ||
1028 | try_open_exit (); | ||
1029 | } | ||
1030 | |||
1031 | |||
1032 | /** | ||
1033 | * Function called whenever a channel has excess capacity. | ||
1034 | * | ||
1035 | * @param cls the `struct CadetExit` | ||
1036 | * @param channel connection to the other end | ||
1037 | * @param window_size how much capacity do we have | ||
1038 | */ | ||
1039 | static void | ||
1040 | channel_idle_notify_cb (void *cls, | ||
1041 | const struct GNUNET_CADET_Channel *channel, | ||
1042 | int window_size) | ||
1043 | { | ||
1044 | struct CadetExit *pos = cls; | ||
1045 | |||
1046 | pos->idle = window_size; | ||
1047 | } | ||
1048 | |||
1049 | |||
1050 | /** | ||
1051 | * We are short on cadet exits, try to open another one. | ||
1052 | */ | ||
1053 | static void | ||
1054 | try_open_exit () | ||
1055 | { | ||
1056 | struct CadetExit *pos; | ||
1057 | uint32_t candidate_count; | ||
1058 | uint32_t candidate_selected; | ||
1059 | struct GNUNET_HashCode port; | ||
1060 | |||
1061 | GNUNET_CRYPTO_hash (GNUNET_APPLICATION_PORT_INTERNET_RESOLVER, | ||
1062 | strlen (GNUNET_APPLICATION_PORT_INTERNET_RESOLVER), | ||
1063 | &port); | ||
1064 | candidate_count = 0; | ||
1065 | for (pos = exit_head; NULL != pos; pos = pos->next) | ||
1066 | if (NULL == pos->cadet_channel) | ||
1067 | candidate_count++; | ||
1068 | if (0 == candidate_count) | ||
1069 | { | ||
1070 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
1071 | "No DNS exits available yet.\n"); | ||
1072 | return; | ||
1073 | } | ||
1074 | candidate_selected = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, | ||
1075 | candidate_count); | ||
1076 | candidate_count = 0; | ||
1077 | for (pos = exit_head; NULL != pos; pos = pos->next) | ||
1078 | if (NULL == pos->cadet_channel) | ||
1079 | { | ||
1080 | candidate_count++; | ||
1081 | if (candidate_selected < candidate_count) | ||
1082 | { | ||
1083 | struct GNUNET_MQ_MessageHandler cadet_handlers[] = { | ||
1084 | GNUNET_MQ_hd_var_size (dns_response, | ||
1085 | GNUNET_MESSAGE_TYPE_VPN_DNS_FROM_INTERNET, | ||
1086 | struct DnsResponseMessage, | ||
1087 | pos), | ||
1088 | GNUNET_MQ_handler_end () | ||
1089 | }; | ||
1090 | |||
1091 | |||
1092 | /* move to the head of the DLL */ | ||
1093 | pos->cadet_channel | ||
1094 | = GNUNET_CADET_channel_create (cadet_handle, | ||
1095 | pos, | ||
1096 | &pos->peer, | ||
1097 | &port, | ||
1098 | &channel_idle_notify_cb, | ||
1099 | &cadet_channel_end_cb, | ||
1100 | cadet_handlers); | ||
1101 | if (NULL == pos->cadet_channel) | ||
1102 | { | ||
1103 | GNUNET_break (0); | ||
1104 | continue; | ||
1105 | } | ||
1106 | GNUNET_CONTAINER_DLL_remove (exit_head, | ||
1107 | exit_tail, | ||
1108 | pos); | ||
1109 | GNUNET_CONTAINER_DLL_insert (exit_head, | ||
1110 | exit_tail, | ||
1111 | pos); | ||
1112 | dns_exit_available++; | ||
1113 | return; | ||
1114 | } | ||
1115 | } | ||
1116 | GNUNET_assert (NULL == exit_head); | ||
1117 | } | ||
1118 | |||
1119 | |||
1120 | /** | ||
1121 | * Function called whenever we find an advertisement for a | ||
1122 | * DNS exit in the DHT. If we don't have a cadet channel, | ||
1123 | * we should build one; otherwise, we should save the | ||
1124 | * advertisement for later use. | ||
1125 | * | ||
1126 | * @param cls closure | ||
1127 | * @param exp when will this value expire | ||
1128 | * @param key key of the result | ||
1129 | * @param get_path peers on reply path (or NULL if not recorded) | ||
1130 | * [0] = datastore's first neighbor, [length - 1] = local peer | ||
1131 | * @param get_path_length number of entries in @a get_path | ||
1132 | * @param put_path peers on the PUT path (or NULL if not recorded) | ||
1133 | * [0] = origin, [length - 1] = datastore | ||
1134 | * @param put_path_length number of entries in @a put_path | ||
1135 | * @param type type of the result | ||
1136 | * @param size number of bytes in @a data | ||
1137 | * @param data pointer to the result data | ||
1138 | */ | ||
1139 | static void | ||
1140 | handle_dht_result (void *cls, | ||
1141 | struct GNUNET_TIME_Absolute exp, | ||
1142 | const struct GNUNET_HashCode *key, | ||
1143 | const struct GNUNET_PeerIdentity *get_path, | ||
1144 | unsigned int get_path_length, | ||
1145 | const struct GNUNET_PeerIdentity *put_path, | ||
1146 | unsigned int put_path_length, | ||
1147 | enum GNUNET_BLOCK_Type type, | ||
1148 | size_t size, const void *data) | ||
1149 | { | ||
1150 | const struct GNUNET_DNS_Advertisement *ad; | ||
1151 | struct CadetExit *exit; | ||
1152 | |||
1153 | if (sizeof(struct GNUNET_DNS_Advertisement) != size) | ||
1154 | { | ||
1155 | GNUNET_break (0); | ||
1156 | return; | ||
1157 | } | ||
1158 | ad = data; | ||
1159 | for (exit = exit_head; NULL != exit; exit = exit->next) | ||
1160 | if (0 == GNUNET_memcmp (&ad->peer, | ||
1161 | &exit->peer)) | ||
1162 | break; | ||
1163 | if (NULL == exit) | ||
1164 | { | ||
1165 | exit = GNUNET_new (struct CadetExit); | ||
1166 | exit->peer = ad->peer; | ||
1167 | /* channel is closed, so insert at the end */ | ||
1168 | GNUNET_CONTAINER_DLL_insert_tail (exit_head, | ||
1169 | exit_tail, | ||
1170 | exit); | ||
1171 | } | ||
1172 | exit->expiration = GNUNET_TIME_absolute_max (exit->expiration, | ||
1173 | GNUNET_TIME_absolute_ntoh ( | ||
1174 | ad->expiration_time)); | ||
1175 | if (dns_exit_available < MAX_OPEN_TUNNELS) | ||
1176 | try_open_exit (); | ||
1177 | } | ||
1178 | |||
1179 | |||
1180 | /** | ||
1181 | * @brief Main function that will be run by the scheduler. | ||
1182 | * | ||
1183 | * @param cls closure | ||
1184 | * @param args remaining command-line arguments | ||
1185 | * @param cfgfile name of the configuration file used (for saving, can be NULL!) | ||
1186 | * @param cfg_ configuration | ||
1187 | */ | ||
1188 | static void | ||
1189 | run (void *cls, char *const *args GNUNET_UNUSED, | ||
1190 | const char *cfgfile GNUNET_UNUSED, | ||
1191 | const struct GNUNET_CONFIGURATION_Handle *cfg_) | ||
1192 | { | ||
1193 | struct GNUNET_HashCode dns_key; | ||
1194 | |||
1195 | cfg = cfg_; | ||
1196 | stats = GNUNET_STATISTICS_create ("pt", | ||
1197 | cfg); | ||
1198 | ipv4_pt = GNUNET_CONFIGURATION_get_value_yesno (cfg, | ||
1199 | "pt", | ||
1200 | "TUNNEL_IPV4"); | ||
1201 | ipv6_pt = GNUNET_CONFIGURATION_get_value_yesno (cfg, | ||
1202 | "pt", | ||
1203 | "TUNNEL_IPV6"); | ||
1204 | dns_channel = GNUNET_CONFIGURATION_get_value_yesno (cfg, | ||
1205 | "pt", | ||
1206 | "TUNNEL_DNS"); | ||
1207 | if (! (ipv4_pt || ipv6_pt || dns_channel)) | ||
1208 | { | ||
1209 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1210 | _ ("No useful service enabled. Exiting.\n")); | ||
1211 | GNUNET_SCHEDULER_shutdown (); | ||
1212 | return; | ||
1213 | } | ||
1214 | GNUNET_SCHEDULER_add_shutdown (&cleanup, cls); | ||
1215 | if (ipv4_pt || ipv6_pt) | ||
1216 | { | ||
1217 | dns_post_handle | ||
1218 | = GNUNET_DNS_connect (cfg, | ||
1219 | GNUNET_DNS_FLAG_POST_RESOLUTION, | ||
1220 | &dns_post_request_handler, | ||
1221 | NULL); | ||
1222 | if (NULL == dns_post_handle) | ||
1223 | { | ||
1224 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1225 | _ ("Failed to connect to %s service. Exiting.\n"), | ||
1226 | "DNS"); | ||
1227 | GNUNET_SCHEDULER_shutdown (); | ||
1228 | return; | ||
1229 | } | ||
1230 | vpn_handle = GNUNET_VPN_connect (cfg); | ||
1231 | if (NULL == vpn_handle) | ||
1232 | { | ||
1233 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1234 | _ ("Failed to connect to %s service. Exiting.\n"), | ||
1235 | "VPN"); | ||
1236 | GNUNET_SCHEDULER_shutdown (); | ||
1237 | return; | ||
1238 | } | ||
1239 | } | ||
1240 | if (dns_channel) | ||
1241 | { | ||
1242 | dns_pre_handle | ||
1243 | = GNUNET_DNS_connect (cfg, | ||
1244 | GNUNET_DNS_FLAG_PRE_RESOLUTION, | ||
1245 | &dns_pre_request_handler, | ||
1246 | NULL); | ||
1247 | if (NULL == dns_pre_handle) | ||
1248 | { | ||
1249 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1250 | _ ("Failed to connect to %s service. Exiting.\n"), | ||
1251 | "DNS"); | ||
1252 | GNUNET_SCHEDULER_shutdown (); | ||
1253 | return; | ||
1254 | } | ||
1255 | cadet_handle = GNUNET_CADET_connect (cfg); | ||
1256 | if (NULL == cadet_handle) | ||
1257 | { | ||
1258 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1259 | _ ("Failed to connect to %s service. Exiting.\n"), | ||
1260 | "CADET"); | ||
1261 | GNUNET_SCHEDULER_shutdown (); | ||
1262 | return; | ||
1263 | } | ||
1264 | dht = GNUNET_DHT_connect (cfg, 1); | ||
1265 | if (NULL == dht) | ||
1266 | { | ||
1267 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1268 | _ ("Failed to connect to %s service. Exiting.\n"), | ||
1269 | "DHT"); | ||
1270 | GNUNET_SCHEDULER_shutdown (); | ||
1271 | return; | ||
1272 | } | ||
1273 | GNUNET_CRYPTO_hash ("dns", | ||
1274 | strlen ("dns"), | ||
1275 | &dns_key); | ||
1276 | dht_get = GNUNET_DHT_get_start (dht, | ||
1277 | GNUNET_BLOCK_TYPE_DNS, | ||
1278 | &dns_key, | ||
1279 | 1, | ||
1280 | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, | ||
1281 | NULL, 0, | ||
1282 | &handle_dht_result, | ||
1283 | NULL); | ||
1284 | } | ||
1285 | } | ||
1286 | |||
1287 | |||
1288 | /** | ||
1289 | * The main function | ||
1290 | * | ||
1291 | * @param argc number of arguments from the command line | ||
1292 | * @param argv command line arguments | ||
1293 | * @return 0 ok, 1 on error | ||
1294 | */ | ||
1295 | int | ||
1296 | main (int argc, | ||
1297 | char *const *argv) | ||
1298 | { | ||
1299 | static const struct GNUNET_GETOPT_CommandLineOption options[] = { | ||
1300 | GNUNET_GETOPT_OPTION_END | ||
1301 | }; | ||
1302 | int ret; | ||
1303 | |||
1304 | if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, | ||
1305 | argv, | ||
1306 | &argc, | ||
1307 | &argv)) | ||
1308 | return 2; | ||
1309 | ret = (GNUNET_OK == | ||
1310 | GNUNET_PROGRAM_run (argc, | ||
1311 | argv, | ||
1312 | "gnunet-daemon-pt", | ||
1313 | gettext_noop ( | ||
1314 | "Daemon to run to perform IP protocol translation to GNUnet"), | ||
1315 | options, | ||
1316 | &run, | ||
1317 | NULL)) | ||
1318 | ? 0 | ||
1319 | : 1; | ||
1320 | GNUNET_free_nz ((void *) argv); | ||
1321 | return ret; | ||
1322 | } | ||
1323 | |||
1324 | |||
1325 | /* end of gnunet-daemon-pt.c */ | ||
diff --git a/src/pt/pt.conf b/src/pt/pt.conf deleted file mode 100644 index 2c8c93c81..000000000 --- a/src/pt/pt.conf +++ /dev/null | |||
@@ -1,12 +0,0 @@ | |||
1 | [pt] | ||
2 | BINARY = gnunet-daemon-pt | ||
3 | NOARMBIND = YES | ||
4 | |||
5 | # Set this to YES to tunnel IPv4 traffic over GNUnet | ||
6 | TUNNEL_IPV4 = NO | ||
7 | |||
8 | # Set this to YES to tunnel IPv6 traffic over GNUnet | ||
9 | TUNNEL_IPV6 = NO | ||
10 | |||
11 | # Set this to YES to tunnel DNS traffic over GNUnet | ||
12 | TUNNEL_DNS = NO | ||
diff --git a/src/pt/test_gns_vpn.c b/src/pt/test_gns_vpn.c deleted file mode 100644 index d2d28d7c7..000000000 --- a/src/pt/test_gns_vpn.c +++ /dev/null | |||
@@ -1,865 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | Copyright (C) 2007, 2009, 2011, 2012, 2015, 2017 Christian Grothoff | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file test_gns_vpn.c | ||
23 | * @brief testcase for accessing VPN services via GNS | ||
24 | * @author Martin Schanzenbach | ||
25 | * @author Christian Grothoff | ||
26 | * | ||
27 | * This test requires libcurl/libgnurl *with* support for C-ARES. | ||
28 | * This is NOT the default on most platforms, which means the test | ||
29 | * will be skipped in many cases. Compile libcurl/libgnurl with | ||
30 | * "--enable-ares" to get this test to pass. | ||
31 | * | ||
32 | * Furthermore, the test relies on gnunet-dns2gns being able to bind | ||
33 | * to port 53. This means that 'setcap' has to have worked during | ||
34 | * 'make install'. If this failed, but everything else is OK, the | ||
35 | * test may FAIL hard even though it is just an installation issue (we | ||
36 | * cannot conveniently test for the setcap to have worked). However, | ||
37 | * you should get a warning that gnunet-dns2gns failed to 'bind'. | ||
38 | */ | ||
39 | #include "platform.h" | ||
40 | /* Just included for the right curl.h */ | ||
41 | #include "gnunet_curl_lib.h" | ||
42 | #include <microhttpd.h> | ||
43 | #include "gnunet_identity_service.h" | ||
44 | #include "gnunet_namestore_service.h" | ||
45 | #include "gnunet_gnsrecord_lib.h" | ||
46 | #include "gnunet_gns_service.h" | ||
47 | #include "gnunet_testing_lib.h" | ||
48 | #include "gnunet_mhd_compat.h" | ||
49 | |||
50 | #define PORT 8080 | ||
51 | #define TEST_DOMAIN "www.gnu" | ||
52 | |||
53 | #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30) | ||
54 | |||
55 | /** | ||
56 | * Return value for #main(). | ||
57 | */ | ||
58 | static int global_ret; | ||
59 | |||
60 | static struct GNUNET_NAMESTORE_Handle *namestore; | ||
61 | |||
62 | static struct MHD_Daemon *mhd; | ||
63 | |||
64 | static struct GNUNET_SCHEDULER_Task *mhd_task_id; | ||
65 | |||
66 | static struct GNUNET_SCHEDULER_Task *curl_task_id; | ||
67 | |||
68 | static struct GNUNET_SCHEDULER_Task *timeout_task; | ||
69 | |||
70 | static struct GNUNET_IDENTITY_Handle *identity; | ||
71 | |||
72 | static struct GNUNET_NAMESTORE_QueueEntry *qe; | ||
73 | |||
74 | static CURL *curl; | ||
75 | |||
76 | static CURLM *multi; | ||
77 | |||
78 | static char *url; | ||
79 | |||
80 | static struct GNUNET_PeerIdentity id; | ||
81 | |||
82 | /** | ||
83 | * IP address of the ultimate destination. | ||
84 | */ | ||
85 | static const char *dest_ip; | ||
86 | |||
87 | /** | ||
88 | * Address family of the dest_ip. | ||
89 | */ | ||
90 | static int dest_af; | ||
91 | |||
92 | /** | ||
93 | * Address family to use by the curl client. | ||
94 | */ | ||
95 | static int src_af; | ||
96 | |||
97 | static int use_v6; | ||
98 | |||
99 | |||
100 | struct CBC | ||
101 | { | ||
102 | char buf[1024]; | ||
103 | size_t pos; | ||
104 | }; | ||
105 | |||
106 | static struct CBC cbc; | ||
107 | |||
108 | |||
109 | static size_t | ||
110 | copy_buffer (void *ptr, | ||
111 | size_t size, | ||
112 | size_t nmemb, | ||
113 | void *ctx) | ||
114 | { | ||
115 | struct CBC *cbc = ctx; | ||
116 | |||
117 | if (cbc->pos + size * nmemb > sizeof(cbc->buf)) | ||
118 | return 0; /* overflow */ | ||
119 | GNUNET_memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb); | ||
120 | cbc->pos += size * nmemb; | ||
121 | return size * nmemb; | ||
122 | } | ||
123 | |||
124 | |||
125 | static MHD_RESULT | ||
126 | mhd_ahc (void *cls, | ||
127 | struct MHD_Connection *connection, | ||
128 | const char *url, | ||
129 | const char *method, | ||
130 | const char *version, | ||
131 | const char *upload_data, size_t *upload_data_size, | ||
132 | void **unused) | ||
133 | { | ||
134 | static int ptr; | ||
135 | struct MHD_Response *response; | ||
136 | int ret; | ||
137 | |||
138 | if (0 != strcmp ("GET", method)) | ||
139 | return MHD_NO; /* unexpected method */ | ||
140 | if (&ptr != *unused) | ||
141 | { | ||
142 | *unused = &ptr; | ||
143 | return MHD_YES; | ||
144 | } | ||
145 | *unused = NULL; | ||
146 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
147 | "MHD sends response for request to URL `%s'\n", url); | ||
148 | response = MHD_create_response_from_buffer (strlen (url), | ||
149 | (void *) url, | ||
150 | MHD_RESPMEM_MUST_COPY); | ||
151 | ret = MHD_queue_response (connection, MHD_HTTP_OK, response); | ||
152 | MHD_destroy_response (response); | ||
153 | if (ret == MHD_NO) | ||
154 | abort (); | ||
155 | return ret; | ||
156 | } | ||
157 | |||
158 | |||
159 | static void | ||
160 | do_shutdown (void *cls) | ||
161 | { | ||
162 | if (NULL != mhd_task_id) | ||
163 | { | ||
164 | GNUNET_SCHEDULER_cancel (mhd_task_id); | ||
165 | mhd_task_id = NULL; | ||
166 | } | ||
167 | if (NULL != curl_task_id) | ||
168 | { | ||
169 | GNUNET_SCHEDULER_cancel (curl_task_id); | ||
170 | curl_task_id = NULL; | ||
171 | } | ||
172 | if (NULL != timeout_task) | ||
173 | { | ||
174 | GNUNET_SCHEDULER_cancel (timeout_task); | ||
175 | timeout_task = NULL; | ||
176 | } | ||
177 | if (NULL != mhd) | ||
178 | { | ||
179 | MHD_stop_daemon (mhd); | ||
180 | mhd = NULL; | ||
181 | } | ||
182 | if (NULL != identity) | ||
183 | { | ||
184 | GNUNET_IDENTITY_disconnect (identity); | ||
185 | identity = NULL; | ||
186 | } | ||
187 | if (NULL != qe) | ||
188 | { | ||
189 | GNUNET_NAMESTORE_cancel (qe); | ||
190 | qe = NULL; | ||
191 | } | ||
192 | if (NULL != namestore) | ||
193 | { | ||
194 | GNUNET_NAMESTORE_disconnect (namestore); | ||
195 | namestore = NULL; | ||
196 | } | ||
197 | GNUNET_free (url); | ||
198 | url = NULL; | ||
199 | } | ||
200 | |||
201 | |||
202 | static void | ||
203 | do_timeout (void *cls) | ||
204 | { | ||
205 | timeout_task = NULL; | ||
206 | GNUNET_SCHEDULER_shutdown (); | ||
207 | } | ||
208 | |||
209 | |||
210 | /** | ||
211 | * Function to run the HTTP client. | ||
212 | */ | ||
213 | static void | ||
214 | curl_main (void); | ||
215 | |||
216 | |||
217 | static void | ||
218 | curl_task (void *cls) | ||
219 | { | ||
220 | curl_task_id = NULL; | ||
221 | curl_main (); | ||
222 | } | ||
223 | |||
224 | |||
225 | static void | ||
226 | curl_main () | ||
227 | { | ||
228 | fd_set rs; | ||
229 | fd_set ws; | ||
230 | fd_set es; | ||
231 | int max; | ||
232 | struct GNUNET_NETWORK_FDSet nrs; | ||
233 | struct GNUNET_NETWORK_FDSet nws; | ||
234 | struct GNUNET_TIME_Relative delay; | ||
235 | long timeout; | ||
236 | int running; | ||
237 | struct CURLMsg *msg; | ||
238 | |||
239 | max = 0; | ||
240 | FD_ZERO (&rs); | ||
241 | FD_ZERO (&ws); | ||
242 | FD_ZERO (&es); | ||
243 | curl_multi_perform (multi, &running); | ||
244 | if (running == 0) | ||
245 | { | ||
246 | GNUNET_assert (NULL != (msg = curl_multi_info_read (multi, &running))); | ||
247 | if (msg->msg == CURLMSG_DONE) | ||
248 | { | ||
249 | if (msg->data.result != CURLE_OK) | ||
250 | { | ||
251 | fprintf (stderr, | ||
252 | "%s failed at %s:%d: `%s'\n", | ||
253 | "curl_multi_perform", | ||
254 | __FILE__, | ||
255 | __LINE__, curl_easy_strerror (msg->data.result)); | ||
256 | global_ret = 1; | ||
257 | } | ||
258 | } | ||
259 | curl_multi_remove_handle (multi, curl); | ||
260 | curl_multi_cleanup (multi); | ||
261 | curl_easy_cleanup (curl); | ||
262 | curl = NULL; | ||
263 | multi = NULL; | ||
264 | if (cbc.pos != strlen ("/hello_world")) | ||
265 | { | ||
266 | GNUNET_break (0); | ||
267 | global_ret = 2; | ||
268 | } | ||
269 | if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world"))) | ||
270 | { | ||
271 | GNUNET_break (0); | ||
272 | global_ret = 3; | ||
273 | } | ||
274 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
275 | "Download complete, shutting down!\n"); | ||
276 | GNUNET_SCHEDULER_shutdown (); | ||
277 | return; | ||
278 | } | ||
279 | GNUNET_assert (CURLM_OK == curl_multi_fdset (multi, &rs, &ws, &es, &max)); | ||
280 | if ((CURLM_OK != curl_multi_timeout (multi, &timeout)) || | ||
281 | (-1 == timeout)) | ||
282 | delay = GNUNET_TIME_UNIT_SECONDS; | ||
283 | else | ||
284 | delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, | ||
285 | (unsigned int) timeout); | ||
286 | GNUNET_NETWORK_fdset_copy_native (&nrs, | ||
287 | &rs, | ||
288 | max + 1); | ||
289 | GNUNET_NETWORK_fdset_copy_native (&nws, | ||
290 | &ws, | ||
291 | max + 1); | ||
292 | curl_task_id = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT, | ||
293 | delay, | ||
294 | &nrs, | ||
295 | &nws, | ||
296 | &curl_task, | ||
297 | NULL); | ||
298 | } | ||
299 | |||
300 | |||
301 | static void | ||
302 | start_curl (void *cls) | ||
303 | { | ||
304 | CURLcode ec; | ||
305 | |||
306 | curl_task_id = NULL; | ||
307 | GNUNET_asprintf (&url, | ||
308 | "http://%s/hello_world", | ||
309 | TEST_DOMAIN); | ||
310 | curl = curl_easy_init (); | ||
311 | curl_easy_setopt (curl, CURLOPT_URL, url); | ||
312 | curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, ©_buffer); | ||
313 | curl_easy_setopt (curl, CURLOPT_WRITEDATA, &cbc); | ||
314 | curl_easy_setopt (curl, CURLOPT_FAILONERROR, 1); | ||
315 | curl_easy_setopt (curl, CURLOPT_TIMEOUT, 150L); | ||
316 | curl_easy_setopt (curl, CURLOPT_CONNECTTIMEOUT, 150L); | ||
317 | curl_easy_setopt (curl, CURLOPT_NOSIGNAL, 1); | ||
318 | if (CURLE_OK != | ||
319 | (ec = curl_easy_setopt (curl, | ||
320 | CURLOPT_DNS_SERVERS, | ||
321 | "127.0.0.1:53"))) | ||
322 | { | ||
323 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
324 | "curl build without support for CURLOPT_DNS_SERVERS (%s), cannot run test\n", | ||
325 | curl_easy_strerror (ec)); | ||
326 | global_ret = 77; | ||
327 | GNUNET_SCHEDULER_shutdown (); | ||
328 | return; | ||
329 | } | ||
330 | multi = curl_multi_init (); | ||
331 | GNUNET_assert (multi != NULL); | ||
332 | GNUNET_assert (CURLM_OK == curl_multi_add_handle (multi, curl)); | ||
333 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
334 | "Beginning HTTP download from `%s'\n", | ||
335 | url); | ||
336 | curl_main (); | ||
337 | } | ||
338 | |||
339 | |||
340 | /** | ||
341 | * Callback invoked from the namestore service once record is | ||
342 | * created. | ||
343 | * | ||
344 | * @param cls closure | ||
345 | * @param af address family, AF_INET or AF_INET6; AF_UNSPEC on error; | ||
346 | * will match 'result_af' from the request | ||
347 | * @param address IP address (struct in_addr or struct in_addr6, depending on 'af') | ||
348 | * that the VPN allocated for the redirection; | ||
349 | * traffic to this IP will now be redirected to the | ||
350 | * specified target peer; NULL on error | ||
351 | */ | ||
352 | static void | ||
353 | commence_testing (void *cls, | ||
354 | int32_t success, | ||
355 | const char *emsg) | ||
356 | { | ||
357 | qe = NULL; | ||
358 | if ((NULL != emsg) && | ||
359 | (GNUNET_YES != success)) | ||
360 | { | ||
361 | fprintf (stderr, | ||
362 | "NS failed to create record %s\n", | ||
363 | emsg); | ||
364 | GNUNET_SCHEDULER_shutdown (); | ||
365 | return; | ||
366 | } | ||
367 | |||
368 | /* wait a little bit before downloading, as we just created the record */ | ||
369 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
370 | "Launching cURL request\n"); | ||
371 | curl_task_id | ||
372 | = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, | ||
373 | &start_curl, | ||
374 | NULL); | ||
375 | } | ||
376 | |||
377 | |||
378 | /** | ||
379 | * Function to keep the HTTP server running. | ||
380 | */ | ||
381 | static void | ||
382 | mhd_main (void); | ||
383 | |||
384 | |||
385 | static void | ||
386 | mhd_task (void *cls) | ||
387 | { | ||
388 | mhd_task_id = NULL; | ||
389 | MHD_run (mhd); | ||
390 | mhd_main (); | ||
391 | } | ||
392 | |||
393 | |||
394 | static void | ||
395 | mhd_main () | ||
396 | { | ||
397 | struct GNUNET_NETWORK_FDSet nrs; | ||
398 | struct GNUNET_NETWORK_FDSet nws; | ||
399 | fd_set rs; | ||
400 | fd_set ws; | ||
401 | fd_set es; | ||
402 | int max_fd; | ||
403 | unsigned MHD_LONG_LONG timeout; | ||
404 | struct GNUNET_TIME_Relative delay; | ||
405 | |||
406 | GNUNET_assert (NULL == mhd_task_id); | ||
407 | FD_ZERO (&rs); | ||
408 | FD_ZERO (&ws); | ||
409 | FD_ZERO (&es); | ||
410 | max_fd = -1; | ||
411 | GNUNET_assert (MHD_YES == | ||
412 | MHD_get_fdset (mhd, &rs, &ws, &es, &max_fd)); | ||
413 | if (MHD_YES == MHD_get_timeout (mhd, &timeout)) | ||
414 | delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, | ||
415 | (unsigned int) timeout); | ||
416 | else | ||
417 | delay = GNUNET_TIME_UNIT_FOREVER_REL; | ||
418 | GNUNET_NETWORK_fdset_copy_native (&nrs, | ||
419 | &rs, | ||
420 | max_fd + 1); | ||
421 | GNUNET_NETWORK_fdset_copy_native (&nws, | ||
422 | &ws, | ||
423 | max_fd + 1); | ||
424 | mhd_task_id = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT, | ||
425 | delay, | ||
426 | &nrs, | ||
427 | &nws, | ||
428 | &mhd_task, | ||
429 | NULL); | ||
430 | } | ||
431 | |||
432 | |||
433 | /** | ||
434 | * Open '/dev/null' and make the result the given | ||
435 | * file descriptor. | ||
436 | * | ||
437 | * @param target_fd desired FD to point to /dev/null | ||
438 | * @param flags open flags (O_RDONLY, O_WRONLY) | ||
439 | */ | ||
440 | static void | ||
441 | open_dev_null (int target_fd, | ||
442 | int flags) | ||
443 | { | ||
444 | int fd; | ||
445 | |||
446 | fd = open ("/dev/null", flags); | ||
447 | if (-1 == fd) | ||
448 | abort (); | ||
449 | if (fd == target_fd) | ||
450 | return; | ||
451 | if (-1 == dup2 (fd, target_fd)) | ||
452 | { | ||
453 | (void) close (fd); | ||
454 | abort (); | ||
455 | } | ||
456 | (void) close (fd); | ||
457 | } | ||
458 | |||
459 | |||
460 | /** | ||
461 | * Run the given command and wait for it to complete. | ||
462 | * | ||
463 | * @param file name of the binary to run | ||
464 | * @param cmd command line arguments (as given to 'execv') | ||
465 | * @return 0 on success, 1 on any error | ||
466 | */ | ||
467 | static int | ||
468 | fork_and_exec (const char *file, | ||
469 | char *const cmd[]) | ||
470 | { | ||
471 | int status; | ||
472 | pid_t pid; | ||
473 | pid_t ret; | ||
474 | |||
475 | pid = fork (); | ||
476 | if (-1 == pid) | ||
477 | { | ||
478 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, | ||
479 | "fork"); | ||
480 | return 1; | ||
481 | } | ||
482 | if (0 == pid) | ||
483 | { | ||
484 | /* we are the child process */ | ||
485 | /* close stdin/stdout to not cause interference | ||
486 | with the helper's main protocol! */ | ||
487 | (void) close (0); | ||
488 | open_dev_null (0, O_RDONLY); | ||
489 | (void) close (1); | ||
490 | open_dev_null (1, O_WRONLY); | ||
491 | (void) execv (file, cmd); | ||
492 | /* can only get here on error */ | ||
493 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, | ||
494 | "exec", | ||
495 | file); | ||
496 | _exit (1); | ||
497 | } | ||
498 | /* keep running waitpid as long as the only error we get is 'EINTR' */ | ||
499 | while ((-1 == (ret = waitpid (pid, &status, 0))) && | ||
500 | (errno == EINTR)) | ||
501 | ; | ||
502 | if (-1 == ret) | ||
503 | { | ||
504 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, | ||
505 | "waitpid"); | ||
506 | return 1; | ||
507 | } | ||
508 | if (! (WIFEXITED (status) && | ||
509 | (0 == WEXITSTATUS (status)))) | ||
510 | { | ||
511 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
512 | "Process `%s` returned status code %d/%d.\n", | ||
513 | file, | ||
514 | WIFEXITED (status), | ||
515 | WEXITSTATUS (status)); | ||
516 | return 1; | ||
517 | } | ||
518 | /* child process completed and returned success, we're happy */ | ||
519 | return 0; | ||
520 | } | ||
521 | |||
522 | |||
523 | /** | ||
524 | * Method called to inform about the egos of this peer. | ||
525 | * | ||
526 | * When used with #GNUNET_IDENTITY_connect, this function is | ||
527 | * initially called for all egos and then again whenever a | ||
528 | * ego's name changes or if it is deleted. At the end of | ||
529 | * the initial pass over all egos, the function is once called | ||
530 | * with 'NULL' for @a ego. That does NOT mean that the callback won't | ||
531 | * be invoked in the future or that there was an error. | ||
532 | * | ||
533 | * When used with #GNUNET_IDENTITY_create or #GNUNET_IDENTITY_get, this | ||
534 | * function is only called ONCE, and 'NULL' being passed in @a ego does | ||
535 | * indicate an error (for example because name is taken or no default value is | ||
536 | * known). If @a ego is non-NULL and if '*ctx' is set in those callbacks, the | ||
537 | * value WILL be passed to a subsequent call to the identity callback of | ||
538 | * #GNUNET_IDENTITY_connect (if that one was not NULL). | ||
539 | * | ||
540 | * When an identity is renamed, this function is called with the | ||
541 | * (known) @a ego but the NEW @a name. | ||
542 | * | ||
543 | * When an identity is deleted, this function is called with the | ||
544 | * (known) ego and "NULL" for the @a name. In this case, | ||
545 | * the @a ego is henceforth invalid (and the @a ctx should also be | ||
546 | * cleaned up). | ||
547 | * | ||
548 | * @param cls closure | ||
549 | * @param ego ego handle | ||
550 | * @param ctx context for application to store data for this ego | ||
551 | * (during the lifetime of this process, initially NULL) | ||
552 | * @param name name assigned by the user for this ego, | ||
553 | * NULL if the user just deleted the ego and it | ||
554 | * must thus no longer be used | ||
555 | */ | ||
556 | static void | ||
557 | identity_cb (void *cls, | ||
558 | struct GNUNET_IDENTITY_Ego *ego, | ||
559 | void **ctx, | ||
560 | const char *name) | ||
561 | { | ||
562 | const struct GNUNET_IDENTITY_PrivateKey *zone_key; | ||
563 | struct GNUNET_GNSRECORD_Data rd; | ||
564 | char *rd_string; | ||
565 | char *peername; | ||
566 | |||
567 | if (NULL == name) | ||
568 | return; | ||
569 | if (NULL == ego) | ||
570 | { | ||
571 | if (NULL == qe) | ||
572 | { | ||
573 | fprintf (stderr, | ||
574 | "Failed to find master-zone ego\n"); | ||
575 | GNUNET_SCHEDULER_shutdown (); | ||
576 | return; | ||
577 | } | ||
578 | GNUNET_IDENTITY_disconnect (identity); | ||
579 | identity = NULL; | ||
580 | return; | ||
581 | } | ||
582 | GNUNET_assert (NULL != name); | ||
583 | if (0 != strcmp (name, | ||
584 | "master-zone")) | ||
585 | { | ||
586 | fprintf (stderr, | ||
587 | "Unexpected name %s\n", | ||
588 | name); | ||
589 | return; | ||
590 | } | ||
591 | zone_key = GNUNET_IDENTITY_ego_get_private_key (ego); | ||
592 | rd.expiration_time = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us; | ||
593 | peername = GNUNET_strdup (GNUNET_i2s_full (&id)); | ||
594 | GNUNET_asprintf (&rd_string, | ||
595 | "6 %s %s", | ||
596 | peername, | ||
597 | "www"); | ||
598 | GNUNET_free (peername); | ||
599 | GNUNET_assert (GNUNET_OK == | ||
600 | GNUNET_GNSRECORD_string_to_value (GNUNET_GNSRECORD_TYPE_VPN, | ||
601 | rd_string, | ||
602 | (void **) &rd.data, | ||
603 | &rd.data_size)); | ||
604 | rd.record_type = GNUNET_GNSRECORD_TYPE_VPN; | ||
605 | |||
606 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
607 | "Creating `www` record\n"); | ||
608 | qe = GNUNET_NAMESTORE_records_store (namestore, | ||
609 | zone_key, | ||
610 | "www", | ||
611 | 1, &rd, | ||
612 | &commence_testing, | ||
613 | NULL); | ||
614 | GNUNET_free_nz ((void **) rd.data); | ||
615 | GNUNET_free (rd_string); | ||
616 | } | ||
617 | |||
618 | |||
619 | static void | ||
620 | run (void *cls, | ||
621 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
622 | struct GNUNET_TESTING_Peer *peer) | ||
623 | { | ||
624 | enum MHD_FLAG flags; | ||
625 | |||
626 | char *bin; | ||
627 | char *bin_identity; | ||
628 | char *bin_gns; | ||
629 | char *bin_arm; | ||
630 | char *config; | ||
631 | |||
632 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
633 | "Test logic starting...\n"); | ||
634 | if (GNUNET_OK != | ||
635 | GNUNET_CONFIGURATION_get_value_string (cfg, | ||
636 | "arm", | ||
637 | "CONFIG", | ||
638 | &config)) | ||
639 | { | ||
640 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
641 | "Failed to locate configuration file. Skipping test.\n"); | ||
642 | GNUNET_SCHEDULER_shutdown (); | ||
643 | return; | ||
644 | } | ||
645 | |||
646 | char *const identity_args[] = { | ||
647 | "gnunet-identity", | ||
648 | "-C", "master-zone", | ||
649 | "-c", config, | ||
650 | NULL | ||
651 | }; | ||
652 | char *const identity2_args[] = { | ||
653 | "gnunet-identity", | ||
654 | "-e", "master-zone", | ||
655 | "-s", "gns-master", | ||
656 | "-c", config, | ||
657 | NULL | ||
658 | }; | ||
659 | char *const identity3_args[] = { | ||
660 | "gnunet-identity", | ||
661 | "-e", "master-zone", | ||
662 | "-s", "dns2gns", | ||
663 | "-c", config, | ||
664 | NULL | ||
665 | }; | ||
666 | char *const arm_args[] = { | ||
667 | "gnunet-arm", | ||
668 | "-i", "dns2gns", | ||
669 | "-c", config, | ||
670 | NULL | ||
671 | }; | ||
672 | char *const gns_args[] = { | ||
673 | "gnunet-gns", | ||
674 | "-u", "www.gnu", | ||
675 | "-c", config, | ||
676 | NULL | ||
677 | }; | ||
678 | |||
679 | GNUNET_TESTING_peer_get_identity (peer, | ||
680 | &id); | ||
681 | GNUNET_SCHEDULER_add_shutdown (&do_shutdown, | ||
682 | NULL); | ||
683 | timeout_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, | ||
684 | &do_timeout, | ||
685 | NULL); | ||
686 | bin = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_BINDIR); | ||
687 | GNUNET_asprintf (&bin_identity, | ||
688 | "%s/%s", | ||
689 | bin, | ||
690 | "gnunet-identity"); | ||
691 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
692 | "Creating `master-zone` ego\n"); | ||
693 | if (0 != fork_and_exec (bin_identity, identity_args)) | ||
694 | { | ||
695 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
696 | "Failed to run `gnunet-identity -C`. Skipping test.\n"); | ||
697 | GNUNET_SCHEDULER_shutdown (); | ||
698 | GNUNET_free (bin_identity); | ||
699 | GNUNET_free (config); | ||
700 | GNUNET_free (bin); | ||
701 | return; | ||
702 | } | ||
703 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
704 | "Setting `master-zone` ego as default for `gns-master` and `dns2gns`\n"); | ||
705 | if (0 != fork_and_exec (bin_identity, identity2_args)) | ||
706 | { | ||
707 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
708 | "Failed to run `gnunet-identity -e`. Skipping test.\n"); | ||
709 | GNUNET_SCHEDULER_shutdown (); | ||
710 | GNUNET_free (bin_identity); | ||
711 | GNUNET_free (config); | ||
712 | GNUNET_free (bin); | ||
713 | return; | ||
714 | } | ||
715 | if (0 != fork_and_exec (bin_identity, identity3_args)) | ||
716 | { | ||
717 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
718 | "Failed to run `gnunet-identity -e`. Skipping test.\n"); | ||
719 | GNUNET_SCHEDULER_shutdown (); | ||
720 | GNUNET_free (bin_identity); | ||
721 | GNUNET_free (config); | ||
722 | GNUNET_free (bin); | ||
723 | return; | ||
724 | } | ||
725 | GNUNET_free (bin_identity); | ||
726 | |||
727 | /* do lookup just to launch GNS service */ | ||
728 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
729 | "Resolving `www.gnu` zone entry to launch GNS (will yield no answer yet)\n"); | ||
730 | GNUNET_asprintf (&bin_gns, | ||
731 | "%s/%s", | ||
732 | bin, | ||
733 | "gnunet-gns"); | ||
734 | if (0 != fork_and_exec (bin_gns, | ||
735 | gns_args)) | ||
736 | { | ||
737 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
738 | "Failed to run `gnunet-gns -u. Skipping test.\n"); | ||
739 | GNUNET_SCHEDULER_shutdown (); | ||
740 | GNUNET_free (bin_gns); | ||
741 | GNUNET_free (config); | ||
742 | GNUNET_free (bin); | ||
743 | return; | ||
744 | } | ||
745 | GNUNET_free (bin_gns); | ||
746 | |||
747 | GNUNET_asprintf (&bin_arm, | ||
748 | "%s/%s", | ||
749 | bin, | ||
750 | "gnunet-arm"); | ||
751 | if (0 != fork_and_exec (bin_arm, | ||
752 | arm_args)) | ||
753 | { | ||
754 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
755 | "Failed to run `gnunet-arm -i dns2gns. Skipping test.\n"); | ||
756 | GNUNET_SCHEDULER_shutdown (); | ||
757 | GNUNET_free (bin_arm); | ||
758 | GNUNET_free (config); | ||
759 | GNUNET_free (bin); | ||
760 | return; | ||
761 | } | ||
762 | GNUNET_free (bin_arm); | ||
763 | |||
764 | GNUNET_free (config); | ||
765 | GNUNET_free (bin); | ||
766 | sleep (1); /* give dns2gns chance to really run */ | ||
767 | |||
768 | namestore = GNUNET_NAMESTORE_connect (cfg); | ||
769 | GNUNET_assert (NULL != namestore); | ||
770 | flags = MHD_USE_DEBUG; | ||
771 | if (GNUNET_YES == use_v6) | ||
772 | flags |= MHD_USE_DUAL_STACK; | ||
773 | mhd = MHD_start_daemon (flags, | ||
774 | PORT, | ||
775 | NULL, NULL, | ||
776 | &mhd_ahc, NULL, | ||
777 | MHD_OPTION_END); | ||
778 | GNUNET_assert (NULL != mhd); | ||
779 | mhd_main (); | ||
780 | |||
781 | identity = GNUNET_IDENTITY_connect (cfg, | ||
782 | &identity_cb, | ||
783 | NULL); | ||
784 | } | ||
785 | |||
786 | |||
787 | int | ||
788 | main (int argc, | ||
789 | char *const *argv) | ||
790 | { | ||
791 | char *bin_vpn; | ||
792 | char *bin_exit; | ||
793 | |||
794 | GNUNET_log_setup ("test-gns-vpn", | ||
795 | "WARNING", | ||
796 | NULL); | ||
797 | if (0 != access ("/dev/net/tun", R_OK)) | ||
798 | { | ||
799 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, | ||
800 | "access", | ||
801 | "/dev/net/tun"); | ||
802 | fprintf (stderr, | ||
803 | "WARNING: System unable to run test, skipping.\n"); | ||
804 | return 77; | ||
805 | } | ||
806 | |||
807 | bin_vpn = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-vpn"); | ||
808 | bin_exit = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-exit"); | ||
809 | if ((0 != geteuid ()) && | ||
810 | ((GNUNET_YES != | ||
811 | GNUNET_OS_check_helper_binary (bin_vpn, | ||
812 | GNUNET_YES, | ||
813 | "-d gnunet-vpn - - 169.1.3.3.7 255.255.255.0")) | ||
814 | || // ipv4 only please! | ||
815 | (GNUNET_YES != | ||
816 | GNUNET_OS_check_helper_binary (bin_exit, | ||
817 | GNUNET_YES, | ||
818 | "-d gnunet-vpn - - - 169.1.3.3.7 255.255.255.0")))) // no nat, ipv4 only | ||
819 | { | ||
820 | fprintf (stderr, | ||
821 | "WARNING: gnunet-helper-{exit,vpn} binaries in $PATH are not SUID, refusing to run test (as it would have to fail).\n"); | ||
822 | fprintf (stderr, | ||
823 | "Change $PATH ('.' in $PATH before $GNUNET_PREFIX/bin is problematic) or permissions (run 'make install' as root) to fix this!\n"); | ||
824 | GNUNET_free (bin_vpn); | ||
825 | GNUNET_free (bin_exit); | ||
826 | return 77; | ||
827 | } | ||
828 | GNUNET_free (bin_vpn); | ||
829 | GNUNET_free (bin_exit); | ||
830 | |||
831 | dest_ip = "169.254.86.1"; | ||
832 | dest_af = AF_INET; | ||
833 | src_af = AF_INET; | ||
834 | |||
835 | if (GNUNET_OK == GNUNET_NETWORK_test_pf (PF_INET6)) | ||
836 | use_v6 = GNUNET_YES; | ||
837 | else | ||
838 | use_v6 = GNUNET_NO; | ||
839 | |||
840 | if ((GNUNET_OK != GNUNET_NETWORK_test_pf (src_af)) || | ||
841 | (GNUNET_OK != GNUNET_NETWORK_test_pf (dest_af))) | ||
842 | { | ||
843 | fprintf (stderr, | ||
844 | "Required address families not supported by this system, skipping test.\n"); | ||
845 | return 77; | ||
846 | } | ||
847 | if (0 != curl_global_init (CURL_GLOBAL_WIN32)) | ||
848 | { | ||
849 | fprintf (stderr, "failed to initialize curl\n"); | ||
850 | return 2; | ||
851 | } | ||
852 | |||
853 | |||
854 | if (0 != | ||
855 | GNUNET_TESTING_peer_run ("test_gns_vpn", | ||
856 | "test_gns_vpn.conf", | ||
857 | &run, | ||
858 | NULL)) | ||
859 | return 1; | ||
860 | GNUNET_DISK_directory_remove ("/tmp/gnunet-test-vpn"); | ||
861 | return global_ret; | ||
862 | } | ||
863 | |||
864 | |||
865 | /* end of test_gns_vpn.c */ | ||
diff --git a/src/pt/test_gns_vpn.conf b/src/pt/test_gns_vpn.conf deleted file mode 100644 index 9277aa3c3..000000000 --- a/src/pt/test_gns_vpn.conf +++ /dev/null | |||
@@ -1,74 +0,0 @@ | |||
1 | [PATHS] | ||
2 | GNUNET_TEST_HOME = $GNUNET_TMP/gnunet-test-gns-vpn/ | ||
3 | |||
4 | [transport] | ||
5 | PLUGINS = tcp | ||
6 | |||
7 | [arm] | ||
8 | PORT = 0 | ||
9 | ALLOW_SHUTDOWN = YES | ||
10 | |||
11 | [exit] | ||
12 | IMMEDIATE_START = YES | ||
13 | IPV6ADDR = FC5A:04E1:C2BA::1 | ||
14 | IPV6PREFIX = 96 | ||
15 | IPV4ADDR = 169.254.86.1 | ||
16 | IPV4MASK = 255.255.255.0 | ||
17 | |||
18 | EXIT_IPV4 = YES | ||
19 | EXIT_IPV6 = YES | ||
20 | |||
21 | # FIXME: can we use 'lo'? | ||
22 | EXIT_IFNAME = eth1 | ||
23 | |||
24 | [dns] | ||
25 | DNS_EXIT = 8.8.8.8 | ||
26 | IMMEDIATE_START = YES | ||
27 | |||
28 | [identity] | ||
29 | START_ON_DEMAND = YES | ||
30 | IMMEDIATE_START = YES | ||
31 | |||
32 | [hostlist] | ||
33 | START_ON_DEMAND = NO | ||
34 | IMMEDIATE_START = NO | ||
35 | |||
36 | [zonemaster] | ||
37 | START_ON_DEMAND = YES | ||
38 | IMMEDIATE_START = YES | ||
39 | |||
40 | #[vpn] | ||
41 | #PREFIX = valgrind | ||
42 | |||
43 | [nse] | ||
44 | WORKBITS = 1 | ||
45 | |||
46 | # repeating some values from the default configurations | ||
47 | # here as the respective network addresses are also | ||
48 | # hard-wired in the tests and the MUST match (!) | ||
49 | [vpn] | ||
50 | IPV6ADDR = FC2D:FDAA:6A26::1 | ||
51 | IPV6PREFIX = 64 | ||
52 | IPV4ADDR = 169.254.20.1 | ||
53 | IPV4MASK = 255.255.255.0 | ||
54 | #PREFIX = valgrind | ||
55 | |||
56 | |||
57 | [www.gnunet.] | ||
58 | TCP_REDIRECTS = 80:localhost4:8080 | ||
59 | TTL = 3600000 | ||
60 | |||
61 | [gns] | ||
62 | START_ON_DEMAND = YES | ||
63 | ZONEKEY = $GNUNET_TEST_HOME/.zonekey | ||
64 | |||
65 | # Delays starting of GNS, as we need to first | ||
66 | # setup the identity subsystem properly. | ||
67 | IMMEDIATE_START = NO | ||
68 | |||
69 | [namestore] | ||
70 | START_ON_DEMAND = YES | ||
71 | |||
72 | [nat] | ||
73 | USE_LOCALADDR = YES | ||
74 | RETURN_LOCAL_ADDRESSES = YES | ||
diff --git a/src/pt/test_gnunet_vpn.c b/src/pt/test_gnunet_vpn.c deleted file mode 100644 index ab197b60d..000000000 --- a/src/pt/test_gnunet_vpn.c +++ /dev/null | |||
@@ -1,519 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | Copyright (C) 2007, 2009, 2011, 2012 Christian Grothoff | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file test_gnunet_vpn.c | ||
23 | * @brief testcase for tunneling HTTP over the GNUnet VPN | ||
24 | * @author Christian Grothoff | ||
25 | */ | ||
26 | #include "platform.h" | ||
27 | /* Just included for the right curl.h */ | ||
28 | #include "gnunet_curl_lib.h" | ||
29 | #include <microhttpd.h> | ||
30 | #include "gnunet_vpn_service.h" | ||
31 | #include "gnunet_testing_lib.h" | ||
32 | #include "gnunet_mhd_compat.h" | ||
33 | |||
34 | #define PORT 48080 | ||
35 | |||
36 | #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 300) | ||
37 | |||
38 | |||
39 | /** | ||
40 | * Return value for 'main'. | ||
41 | */ | ||
42 | static int global_ret; | ||
43 | |||
44 | static struct GNUNET_VPN_Handle *vpn; | ||
45 | |||
46 | static struct MHD_Daemon *mhd; | ||
47 | |||
48 | static struct GNUNET_SCHEDULER_Task *mhd_task_id; | ||
49 | |||
50 | static struct GNUNET_SCHEDULER_Task *curl_task_id; | ||
51 | |||
52 | static struct GNUNET_SCHEDULER_Task *timeout_task_id; | ||
53 | |||
54 | static struct GNUNET_VPN_RedirectionRequest *rr; | ||
55 | |||
56 | static CURL *curl; | ||
57 | |||
58 | static CURLM *multi; | ||
59 | |||
60 | static char *url; | ||
61 | |||
62 | /** | ||
63 | * IP address of the ultimate destination. | ||
64 | */ | ||
65 | static const char *dest_ip; | ||
66 | |||
67 | /** | ||
68 | * Address family of the dest_ip. | ||
69 | */ | ||
70 | static int dest_af; | ||
71 | |||
72 | /** | ||
73 | * Address family to use by the curl client. | ||
74 | */ | ||
75 | static int src_af; | ||
76 | |||
77 | |||
78 | struct CBC | ||
79 | { | ||
80 | char buf[1024]; | ||
81 | size_t pos; | ||
82 | }; | ||
83 | |||
84 | static struct CBC cbc; | ||
85 | |||
86 | |||
87 | static size_t | ||
88 | copy_buffer (void *ptr, size_t size, size_t nmemb, void *ctx) | ||
89 | { | ||
90 | struct CBC *cbc = ctx; | ||
91 | |||
92 | if (cbc->pos + size * nmemb > sizeof(cbc->buf)) | ||
93 | return 0; /* overflow */ | ||
94 | GNUNET_memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb); | ||
95 | cbc->pos += size * nmemb; | ||
96 | return size * nmemb; | ||
97 | } | ||
98 | |||
99 | |||
100 | static MHD_RESULT | ||
101 | mhd_ahc (void *cls, | ||
102 | struct MHD_Connection *connection, | ||
103 | const char *url, | ||
104 | const char *method, | ||
105 | const char *version, | ||
106 | const char *upload_data, | ||
107 | size_t *upload_data_size, | ||
108 | void **unused) | ||
109 | { | ||
110 | static int ptr; | ||
111 | struct MHD_Response *response; | ||
112 | int ret; | ||
113 | |||
114 | if (0 != strcmp ("GET", method)) | ||
115 | return MHD_NO; /* unexpected method */ | ||
116 | if (&ptr != *unused) | ||
117 | { | ||
118 | *unused = &ptr; | ||
119 | return MHD_YES; | ||
120 | } | ||
121 | *unused = NULL; | ||
122 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
123 | "MHD sends response for request to URL `%s'\n", url); | ||
124 | response = | ||
125 | MHD_create_response_from_buffer (strlen (url), (void *) url, | ||
126 | MHD_RESPMEM_MUST_COPY); | ||
127 | ret = MHD_queue_response (connection, MHD_HTTP_OK, response); | ||
128 | MHD_destroy_response (response); | ||
129 | if (ret == MHD_NO) | ||
130 | abort (); | ||
131 | return ret; | ||
132 | } | ||
133 | |||
134 | |||
135 | static void | ||
136 | do_shutdown (void *cls) | ||
137 | { | ||
138 | if (NULL != mhd_task_id) | ||
139 | { | ||
140 | GNUNET_SCHEDULER_cancel (mhd_task_id); | ||
141 | mhd_task_id = NULL; | ||
142 | } | ||
143 | if (NULL != curl_task_id) | ||
144 | { | ||
145 | GNUNET_SCHEDULER_cancel (curl_task_id); | ||
146 | curl_task_id = NULL; | ||
147 | } | ||
148 | if (NULL != timeout_task_id) | ||
149 | { | ||
150 | GNUNET_SCHEDULER_cancel (timeout_task_id); | ||
151 | timeout_task_id = NULL; | ||
152 | } | ||
153 | if (NULL != mhd) | ||
154 | { | ||
155 | MHD_stop_daemon (mhd); | ||
156 | mhd = NULL; | ||
157 | } | ||
158 | if (NULL != rr) | ||
159 | { | ||
160 | GNUNET_VPN_cancel_request (rr); | ||
161 | rr = NULL; | ||
162 | } | ||
163 | if (NULL != vpn) | ||
164 | { | ||
165 | GNUNET_VPN_disconnect (vpn); | ||
166 | vpn = NULL; | ||
167 | } | ||
168 | GNUNET_free (url); | ||
169 | url = NULL; | ||
170 | } | ||
171 | |||
172 | |||
173 | /** | ||
174 | * Function to run the HTTP client. | ||
175 | */ | ||
176 | static void | ||
177 | curl_main (void *cls) | ||
178 | { | ||
179 | fd_set rs; | ||
180 | fd_set ws; | ||
181 | fd_set es; | ||
182 | int max; | ||
183 | struct GNUNET_NETWORK_FDSet nrs; | ||
184 | struct GNUNET_NETWORK_FDSet nws; | ||
185 | struct GNUNET_TIME_Relative delay; | ||
186 | long timeout; | ||
187 | int running; | ||
188 | struct CURLMsg *msg; | ||
189 | |||
190 | curl_task_id = NULL; | ||
191 | max = 0; | ||
192 | FD_ZERO (&rs); | ||
193 | FD_ZERO (&ws); | ||
194 | FD_ZERO (&es); | ||
195 | curl_multi_perform (multi, &running); | ||
196 | if (running == 0) | ||
197 | { | ||
198 | GNUNET_assert (NULL != (msg = curl_multi_info_read (multi, &running))); | ||
199 | if (msg->msg == CURLMSG_DONE) | ||
200 | { | ||
201 | if (msg->data.result != CURLE_OK) | ||
202 | { | ||
203 | fprintf (stderr, "%s failed at %s:%d: `%s'\n", "curl_multi_perform", | ||
204 | __FILE__, __LINE__, curl_easy_strerror (msg->data.result)); | ||
205 | global_ret = 1; | ||
206 | } | ||
207 | } | ||
208 | curl_multi_remove_handle (multi, curl); | ||
209 | curl_multi_cleanup (multi); | ||
210 | curl_easy_cleanup (curl); | ||
211 | curl = NULL; | ||
212 | multi = NULL; | ||
213 | if (cbc.pos != strlen ("/hello_world")) | ||
214 | { | ||
215 | GNUNET_break (0); | ||
216 | global_ret = 2; | ||
217 | } | ||
218 | if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world"))) | ||
219 | { | ||
220 | GNUNET_break (0); | ||
221 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
222 | "You might want to check if your host-based firewall is blocking the connections.\n"); | ||
223 | global_ret = 3; | ||
224 | } | ||
225 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Download complete, shutting down!\n"); | ||
226 | GNUNET_SCHEDULER_shutdown (); | ||
227 | return; | ||
228 | } | ||
229 | GNUNET_assert (CURLM_OK == curl_multi_fdset (multi, &rs, &ws, &es, &max)); | ||
230 | if ((CURLM_OK != curl_multi_timeout (multi, &timeout)) || (-1 == timeout)) | ||
231 | delay = GNUNET_TIME_UNIT_SECONDS; | ||
232 | else | ||
233 | delay = | ||
234 | GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, | ||
235 | (unsigned int) timeout); | ||
236 | GNUNET_NETWORK_fdset_copy_native (&nrs, &rs, max + 1); | ||
237 | GNUNET_NETWORK_fdset_copy_native (&nws, &ws, max + 1); | ||
238 | curl_task_id = | ||
239 | GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT, delay, | ||
240 | &nrs, &nws, &curl_main, NULL); | ||
241 | } | ||
242 | |||
243 | |||
244 | /** | ||
245 | * Callback invoked from the VPN service once a redirection is | ||
246 | * available. Provides the IP address that can now be used to | ||
247 | * reach the requested destination (in our case, the MHD server) | ||
248 | * | ||
249 | * @param cls closure | ||
250 | * @param af address family, AF_INET or AF_INET6; AF_UNSPEC on error; | ||
251 | * will match 'result_af' from the request | ||
252 | * @param address IP address (struct in_addr or struct in_addr6, depending on 'af') | ||
253 | * that the VPN allocated for the redirection; | ||
254 | * traffic to this IP will now be redirected to the | ||
255 | * specified target peer; NULL on error | ||
256 | */ | ||
257 | static void | ||
258 | allocation_cb (void *cls, int af, const void *address) | ||
259 | { | ||
260 | char ips[INET6_ADDRSTRLEN]; | ||
261 | |||
262 | rr = NULL; | ||
263 | if (src_af != af) | ||
264 | { | ||
265 | fprintf (stderr, | ||
266 | "VPN failed to allocate appropriate address\n"); | ||
267 | GNUNET_SCHEDULER_shutdown (); | ||
268 | return; | ||
269 | } | ||
270 | if (AF_INET6 == af) | ||
271 | GNUNET_asprintf (&url, | ||
272 | "http://[%s]:%u/hello_world", | ||
273 | inet_ntop (af, | ||
274 | address, | ||
275 | ips, | ||
276 | sizeof(ips)), | ||
277 | (unsigned int) PORT); | ||
278 | else | ||
279 | GNUNET_asprintf (&url, | ||
280 | "http://%s:%u/hello_world", | ||
281 | inet_ntop (af, | ||
282 | address, | ||
283 | ips, | ||
284 | sizeof(ips)), | ||
285 | (unsigned int) PORT); | ||
286 | curl = curl_easy_init (); | ||
287 | curl_easy_setopt (curl, CURLOPT_URL, url); | ||
288 | curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, ©_buffer); | ||
289 | curl_easy_setopt (curl, CURLOPT_WRITEDATA, &cbc); | ||
290 | curl_easy_setopt (curl, CURLOPT_FAILONERROR, 1); | ||
291 | curl_easy_setopt (curl, CURLOPT_TIMEOUT, 150L); | ||
292 | curl_easy_setopt (curl, CURLOPT_CONNECTTIMEOUT, 15L); | ||
293 | curl_easy_setopt (curl, CURLOPT_NOSIGNAL, 1); | ||
294 | curl_easy_setopt (curl, CURLOPT_VERBOSE, 0); | ||
295 | |||
296 | multi = curl_multi_init (); | ||
297 | GNUNET_assert (multi != NULL); | ||
298 | GNUNET_assert (CURLM_OK == curl_multi_add_handle (multi, curl)); | ||
299 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
300 | "Beginning HTTP download from `%s'\n", | ||
301 | url); | ||
302 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, | ||
303 | &curl_main, | ||
304 | NULL); | ||
305 | } | ||
306 | |||
307 | |||
308 | /** | ||
309 | * Function to keep the HTTP server running. | ||
310 | */ | ||
311 | static void | ||
312 | mhd_main (void); | ||
313 | |||
314 | |||
315 | static void | ||
316 | mhd_task (void *cls) | ||
317 | { | ||
318 | mhd_task_id = NULL; | ||
319 | MHD_run (mhd); | ||
320 | mhd_main (); | ||
321 | } | ||
322 | |||
323 | |||
324 | static void | ||
325 | do_timeout (void *cls) | ||
326 | { | ||
327 | timeout_task_id = NULL; | ||
328 | GNUNET_SCHEDULER_shutdown (); | ||
329 | GNUNET_break (0); | ||
330 | global_ret = 1; | ||
331 | } | ||
332 | |||
333 | |||
334 | static void | ||
335 | mhd_main () | ||
336 | { | ||
337 | struct GNUNET_NETWORK_FDSet nrs; | ||
338 | struct GNUNET_NETWORK_FDSet nws; | ||
339 | fd_set rs; | ||
340 | fd_set ws; | ||
341 | fd_set es; | ||
342 | int max_fd; | ||
343 | unsigned MHD_LONG_LONG timeout; | ||
344 | struct GNUNET_TIME_Relative delay; | ||
345 | |||
346 | GNUNET_assert (NULL == mhd_task_id); | ||
347 | FD_ZERO (&rs); | ||
348 | FD_ZERO (&ws); | ||
349 | FD_ZERO (&es); | ||
350 | max_fd = -1; | ||
351 | GNUNET_assert (MHD_YES == MHD_get_fdset (mhd, &rs, &ws, &es, &max_fd)); | ||
352 | if (MHD_YES == MHD_get_timeout (mhd, &timeout)) | ||
353 | delay = | ||
354 | GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, | ||
355 | (unsigned int) timeout); | ||
356 | else | ||
357 | delay = GNUNET_TIME_UNIT_FOREVER_REL; | ||
358 | GNUNET_NETWORK_fdset_copy_native (&nrs, &rs, max_fd + 1); | ||
359 | GNUNET_NETWORK_fdset_copy_native (&nws, &ws, max_fd + 1); | ||
360 | mhd_task_id = | ||
361 | GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT, delay, | ||
362 | &nrs, &nws, &mhd_task, NULL); | ||
363 | } | ||
364 | |||
365 | |||
366 | static void | ||
367 | run (void *cls, | ||
368 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
369 | struct GNUNET_TESTING_Peer *peer) | ||
370 | { | ||
371 | struct in_addr v4; | ||
372 | struct in6_addr v6; | ||
373 | void *addr; | ||
374 | enum MHD_FLAG flags; | ||
375 | |||
376 | vpn = GNUNET_VPN_connect (cfg); | ||
377 | GNUNET_assert (NULL != vpn); | ||
378 | flags = MHD_USE_DEBUG; | ||
379 | if (AF_INET6 == dest_af) | ||
380 | flags |= MHD_USE_IPv6; | ||
381 | mhd = | ||
382 | MHD_start_daemon (flags, PORT, NULL, NULL, &mhd_ahc, NULL, | ||
383 | MHD_OPTION_END); | ||
384 | |||
385 | |||
386 | GNUNET_assert (NULL != mhd); | ||
387 | mhd_main (); | ||
388 | addr = NULL; | ||
389 | switch (dest_af) | ||
390 | { | ||
391 | case AF_INET: | ||
392 | GNUNET_assert (1 == inet_pton (dest_af, dest_ip, &v4)); | ||
393 | addr = &v4; | ||
394 | break; | ||
395 | |||
396 | case AF_INET6: | ||
397 | GNUNET_assert (1 == inet_pton (dest_af, dest_ip, &v6)); | ||
398 | addr = &v6; | ||
399 | break; | ||
400 | |||
401 | default: | ||
402 | GNUNET_assert (0); | ||
403 | } | ||
404 | rr = GNUNET_VPN_redirect_to_ip (vpn, src_af, dest_af, addr, | ||
405 | GNUNET_TIME_UNIT_FOREVER_ABS, &allocation_cb, | ||
406 | NULL); | ||
407 | timeout_task_id = | ||
408 | GNUNET_SCHEDULER_add_delayed (TIMEOUT, | ||
409 | &do_timeout, | ||
410 | NULL); | ||
411 | GNUNET_SCHEDULER_add_shutdown (&do_shutdown, | ||
412 | NULL); | ||
413 | } | ||
414 | |||
415 | |||
416 | int | ||
417 | main (int argc, char *const *argv) | ||
418 | { | ||
419 | const char *type; | ||
420 | const char *bin; | ||
421 | char *vpn_binary; | ||
422 | char *exit_binary; | ||
423 | int ret = 0; | ||
424 | |||
425 | if (0 != access ("/dev/net/tun", R_OK)) | ||
426 | { | ||
427 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, | ||
428 | "access", | ||
429 | "/dev/net/tun"); | ||
430 | fprintf (stderr, | ||
431 | "WARNING: System unable to run test, skipping.\n"); | ||
432 | return 77; | ||
433 | } | ||
434 | |||
435 | vpn_binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-vpn"); | ||
436 | exit_binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-exit"); | ||
437 | if ((GNUNET_YES != (ret = GNUNET_OS_check_helper_binary (vpn_binary, | ||
438 | GNUNET_YES, | ||
439 | "-d gnunet-vpn - - 169.1.3.3.7 255.255.255.0"))) | ||
440 | || // ipv4 only please! | ||
441 | (GNUNET_YES != (ret = GNUNET_OS_check_helper_binary (exit_binary, | ||
442 | GNUNET_YES, | ||
443 | "-d gnunet-vpn - - - 169.1.3.3.7 255.255.255.0")))) // no nat, ipv4 only | ||
444 | { | ||
445 | GNUNET_free (vpn_binary); | ||
446 | GNUNET_free (exit_binary); | ||
447 | fprintf (stderr, | ||
448 | "WARNING: gnunet-helper-{exit,vpn} binaries are not SUID, refusing to run test (as it would have to fail). %d\n", | ||
449 | ret); | ||
450 | return 77; | ||
451 | } | ||
452 | |||
453 | GNUNET_free (vpn_binary); | ||
454 | GNUNET_free (exit_binary); | ||
455 | bin = argv[0]; | ||
456 | if (NULL != strstr (bin, "lt-")) | ||
457 | bin = strstr (bin, "lt-") + 4; | ||
458 | type = strstr (bin, "-"); | ||
459 | if (NULL == type) | ||
460 | { | ||
461 | fprintf (stderr, | ||
462 | "invalid binary name\n"); | ||
463 | return 1; | ||
464 | } | ||
465 | type++; | ||
466 | /* on Windows, .exe is suffixed to these binaries, | ||
467 | * thus cease comparison after the 6th char. | ||
468 | */ | ||
469 | if (0 == strncmp (type, "4_to_6", 6)) | ||
470 | { | ||
471 | dest_ip = "FC5A:04E1:C2BA::1"; | ||
472 | dest_af = AF_INET6; | ||
473 | src_af = AF_INET; | ||
474 | } | ||
475 | else if (0 == strncmp (type, "6_to_4", 6)) | ||
476 | { | ||
477 | dest_ip = "169.254.86.1"; | ||
478 | dest_af = AF_INET; | ||
479 | src_af = AF_INET6; | ||
480 | } | ||
481 | else if (0 == strncmp (type, "4_over", 6)) | ||
482 | { | ||
483 | dest_ip = "169.254.86.1"; | ||
484 | dest_af = AF_INET; | ||
485 | src_af = AF_INET; | ||
486 | } | ||
487 | else if (0 == strncmp (type, "6_over", 6)) | ||
488 | { | ||
489 | dest_ip = "FC5A:04E1:C2BA::1"; | ||
490 | dest_af = AF_INET6; | ||
491 | src_af = AF_INET6; | ||
492 | } | ||
493 | else | ||
494 | { | ||
495 | fprintf (stderr, "invalid binary suffix `%s'\n", type); | ||
496 | return 1; | ||
497 | } | ||
498 | if ((GNUNET_OK != GNUNET_NETWORK_test_pf (src_af)) || | ||
499 | (GNUNET_OK != GNUNET_NETWORK_test_pf (dest_af))) | ||
500 | { | ||
501 | fprintf (stderr, | ||
502 | "Required address families not supported by this system, skipping test.\n"); | ||
503 | return 0; | ||
504 | } | ||
505 | if (0 != curl_global_init (CURL_GLOBAL_WIN32)) | ||
506 | { | ||
507 | fprintf (stderr, "failed to initialize curl\n"); | ||
508 | return 2; | ||
509 | } | ||
510 | if (0 != | ||
511 | GNUNET_TESTING_peer_run ("test-gnunet-vpn", "test_gnunet_vpn.conf", &run, | ||
512 | NULL)) | ||
513 | return 1; | ||
514 | GNUNET_DISK_directory_remove ("/tmp/gnunet-test-vpn"); | ||
515 | return global_ret; | ||
516 | } | ||
517 | |||
518 | |||
519 | /* end of test_gnunet_vpn.c */ | ||
diff --git a/src/pt/test_gnunet_vpn.conf b/src/pt/test_gnunet_vpn.conf deleted file mode 100644 index 9bee93e02..000000000 --- a/src/pt/test_gnunet_vpn.conf +++ /dev/null | |||
@@ -1,48 +0,0 @@ | |||
1 | [PATHS] | ||
2 | GNUNET_TEST_HOME = $GNUNET_TMP/gnunet-test-vpn/ | ||
3 | |||
4 | [transport] | ||
5 | PLUGINS = tcp | ||
6 | |||
7 | [arm] | ||
8 | PORT = 0 | ||
9 | ALLOW_SHUTDOWN = YES | ||
10 | |||
11 | [exit] | ||
12 | IMMEDIATE_START = YES | ||
13 | EXIT_IPV4 = YES | ||
14 | EXIT_IPV6 = YES | ||
15 | IPV6ADDR = FC5A:04E1:C2BA::1 | ||
16 | IPV6PREFIX = 96 | ||
17 | IPV4ADDR = 169.254.86.1 | ||
18 | IPV4MASK = 255.255.255.0 | ||
19 | |||
20 | # FIXME: can we use 'lo'? | ||
21 | EXIT_IFNAME = eth1 | ||
22 | |||
23 | [hostlist] | ||
24 | START_ON_DEMAND = NO | ||
25 | IMMEDIATE_START = NO | ||
26 | |||
27 | [nse] | ||
28 | WORKBITS = 1 | ||
29 | |||
30 | # repeating some values from the default configurations | ||
31 | # here as the respective network addresses are also | ||
32 | # hard-wired in the tests and the MUST match (!) | ||
33 | [vpn] | ||
34 | IPV6ADDR = FC2D:FDAA:6A26::1 | ||
35 | IPV6PREFIX = 64 | ||
36 | IPV4ADDR = 169.254.20.1 | ||
37 | IPV4MASK = 255.255.255.0 | ||
38 | |||
39 | |||
40 | [gns] | ||
41 | START_ON_DEMAND = NO | ||
42 | |||
43 | [nat] | ||
44 | USE_LOCALADDR = YES | ||
45 | RETURN_LOCAL_ADDRESSES = YES | ||
46 | |||
47 | [consensus] | ||
48 | START_ON_DEMAND = NO | ||