aboutsummaryrefslogtreecommitdiff
path: root/src/vpn
diff options
context:
space:
mode:
authorMartin Schanzenbach <mschanzenbach@posteo.de>2012-06-26 15:55:55 +0000
committerMartin Schanzenbach <mschanzenbach@posteo.de>2012-06-26 15:55:55 +0000
commit44d10fe5cea875a05a31059bf2b2da25ee0cd5c0 (patch)
tree9b0f29826c35f80e7c98a528e7129e2f79f53ea2 /src/vpn
parentdfb93f8cbf257d1744cd59abd4d05ab06c9138c2 (diff)
downloadgnunet-44d10fe5cea875a05a31059bf2b2da25ee0cd5c0.tar.gz
gnunet-44d10fe5cea875a05a31059bf2b2da25ee0cd5c0.zip
-added vpn gns test, fixes
Diffstat (limited to 'src/vpn')
-rw-r--r--src/vpn/Makefile.am12
-rw-r--r--src/vpn/test_gns_vpn.c525
-rw-r--r--src/vpn/test_gns_vpn.conf52
3 files changed, 588 insertions, 1 deletions
diff --git a/src/vpn/Makefile.am b/src/vpn/Makefile.am
index 8cc546b36..91cb95640 100644
--- a/src/vpn/Makefile.am
+++ b/src/vpn/Makefile.am
@@ -26,6 +26,7 @@ if HAVE_MHD
26 test_gnunet_vpn-6_to_4 \ 26 test_gnunet_vpn-6_to_4 \
27 test_gnunet_vpn-6_over \ 27 test_gnunet_vpn-6_over \
28 test_gnunet_vpn-4_over 28 test_gnunet_vpn-4_over
29 #test_gns_vpn
29endif 30endif
30else 31else
31install-exec-hook: 32install-exec-hook:
@@ -48,7 +49,8 @@ TESTS = $(check_PROGRAMS)
48endif 49endif
49 50
50EXTRA_DIST = \ 51EXTRA_DIST = \
51 test_gnunet_vpn.conf 52 test_gnunet_vpn.conf \
53 test_gns_vpn.conf
52 54
53gnunet_helper_vpn_SOURCES = \ 55gnunet_helper_vpn_SOURCES = \
54 gnunet-helper-vpn.c 56 gnunet-helper-vpn.c
@@ -80,6 +82,14 @@ libgnunetvpn_la_LIBADD = \
80libgnunetvpn_la_LDFLAGS = \ 82libgnunetvpn_la_LDFLAGS = \
81 $(GN_LIB_LDFLAGS) 83 $(GN_LIB_LDFLAGS)
82 84
85#test_gns_vpn_SOURCES = \
86# test_gns_vpn.c
87#test_gns_vpn_LDADD = -lmicrohttpd @LIBCURL@ \
88# $(top_builddir)/src/namestore/libgnunetnamestore.la \
89# $(top_builddir)/src/testing/libgnunettesting.la \
90# $(top_builddir)/src/util/libgnunetutil.la
91#test_gnunet_vpn_4_over_CPPFLAGS = \
92# @LIBCURL_CPPFLAGS@
83 93
84test_gnunet_vpn_4_over_SOURCES = \ 94test_gnunet_vpn_4_over_SOURCES = \
85 test_gnunet_vpn.c 95 test_gnunet_vpn.c
diff --git a/src/vpn/test_gns_vpn.c b/src/vpn/test_gns_vpn.c
new file mode 100644
index 000000000..fb498cd83
--- /dev/null
+++ b/src/vpn/test_gns_vpn.c
@@ -0,0 +1,525 @@
1/*
2 This file is part of GNUnet
3 (C) 2007, 2009, 2011, 2012 Christian Grothoff
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 2, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file test_gns_vpn.c
23 * @brief testcase for accessing VPN services via GNS
24 * @author Martin Schanzenbach
25 */
26#include "platform.h"
27#include <curl/curl.h>
28#include <microhttpd.h>
29#include "gnunet_namestore_service.h"
30#include "gnunet_gns_service.h"
31#include "gnunet_testing_lib-new.h"
32
33#define PORT 8080
34#define TEST_DOMAIN "www.gnunet"
35
36#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 300)
37
38/**
39 * Return value for 'main'.
40 */
41static int global_ret;
42
43static struct GNUNET_NAMESTORE_Handle *namestore;
44
45static struct MHD_Daemon *mhd;
46
47static GNUNET_SCHEDULER_TaskIdentifier mhd_task_id;
48
49static GNUNET_SCHEDULER_TaskIdentifier curl_task_id;
50
51static GNUNET_SCHEDULER_TaskIdentifier ctrl_c_task_id;
52
53static CURL *curl;
54
55static CURLM *multi;
56
57static char *url;
58
59/**
60 * IP address of the ultimate destination.
61 */
62static const char *dest_ip;
63
64/**
65 * Address family of the dest_ip.
66 */
67static int dest_af;
68
69/**
70 * Address family to use by the curl client.
71 */
72static int src_af;
73
74static int use_v6;
75
76
77struct CBC
78{
79 char buf[1024];
80 size_t pos;
81};
82
83static struct CBC cbc;
84
85
86static size_t
87copy_buffer (void *ptr, size_t size, size_t nmemb, void *ctx)
88{
89 struct CBC *cbc = ctx;
90
91 if (cbc->pos + size * nmemb > sizeof(cbc->buf))
92 return 0; /* overflow */
93 memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb);
94 cbc->pos += size * nmemb;
95 return size * nmemb;
96}
97
98
99static int
100mhd_ahc (void *cls,
101 struct MHD_Connection *connection,
102 const char *url,
103 const char *method,
104 const char *version,
105 const char *upload_data, size_t *upload_data_size,
106 void **unused)
107{
108 static int ptr;
109 struct MHD_Response *response;
110 int ret;
111
112 if (0 != strcmp ("GET", method))
113 return MHD_NO; /* unexpected method */
114 if (&ptr != *unused)
115 {
116 *unused = &ptr;
117 return MHD_YES;
118 }
119 *unused = NULL;
120 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MHD sends respose for request to URL `%s'\n", url);
121 response = MHD_create_response_from_buffer (strlen (url),
122 (void *) url,
123 MHD_RESPMEM_MUST_COPY);
124 ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
125 MHD_destroy_response (response);
126 if (ret == MHD_NO)
127 abort ();
128 return ret;
129}
130
131
132static void
133do_shutdown ()
134{
135 if (mhd_task_id != GNUNET_SCHEDULER_NO_TASK)
136 {
137 GNUNET_SCHEDULER_cancel (mhd_task_id);
138 mhd_task_id = GNUNET_SCHEDULER_NO_TASK;
139 }
140 if (curl_task_id != GNUNET_SCHEDULER_NO_TASK)
141 {
142 GNUNET_SCHEDULER_cancel (curl_task_id);
143 curl_task_id = GNUNET_SCHEDULER_NO_TASK;
144 }
145 if (ctrl_c_task_id != GNUNET_SCHEDULER_NO_TASK)
146 {
147 GNUNET_SCHEDULER_cancel (ctrl_c_task_id);
148 ctrl_c_task_id = GNUNET_SCHEDULER_NO_TASK;
149 }
150 if (NULL != mhd)
151 {
152 MHD_stop_daemon (mhd);
153 mhd = NULL;
154 }
155 GNUNET_free_non_null (url);
156 url = NULL;
157}
158
159
160/**
161 * Function to run the HTTP client.
162 */
163static void
164curl_main (void);
165
166
167static void
168curl_task (void *cls,
169 const struct GNUNET_SCHEDULER_TaskContext *tc)
170{
171 curl_task_id = GNUNET_SCHEDULER_NO_TASK;
172 curl_main ();
173}
174
175
176static void
177curl_main ()
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 max = 0;
191 FD_ZERO (&rs);
192 FD_ZERO (&ws);
193 FD_ZERO (&es);
194 curl_multi_perform (multi, &running);
195 if (running == 0)
196 {
197 GNUNET_assert (NULL != (msg = curl_multi_info_read (multi, &running)));
198 if (msg->msg == CURLMSG_DONE)
199 {
200 if (msg->data.result != CURLE_OK)
201 {
202 fprintf (stderr,
203 "%s failed at %s:%d: `%s'\n",
204 "curl_multi_perform",
205 __FILE__,
206 __LINE__, curl_easy_strerror (msg->data.result));
207 global_ret = 1;
208 }
209 }
210 curl_multi_remove_handle (multi, curl);
211 curl_multi_cleanup (multi);
212 curl_easy_cleanup (curl);
213 curl = NULL;
214 multi = NULL;
215 if (cbc.pos != strlen ("/hello_world"))
216 {
217 GNUNET_break (0);
218 global_ret = 2;
219 }
220 if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
221 {
222 GNUNET_break (0);
223 global_ret = 3;
224 }
225 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Download complete, shutting down!\n");
226 do_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)) ||
231 (-1 == timeout) )
232 delay = GNUNET_TIME_UNIT_SECONDS;
233 else
234 delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, (unsigned int) timeout);
235 GNUNET_NETWORK_fdset_copy_native (&nrs,
236 &rs,
237 max + 1);
238 GNUNET_NETWORK_fdset_copy_native (&nws,
239 &ws,
240 max + 1);
241 curl_task_id = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
242 delay,
243 &nrs,
244 &nws,
245 &curl_task,
246 NULL);
247}
248
249static void
250start_curl (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
251{
252 GNUNET_asprintf (&url,
253 "http://%s/hello_world",
254 TEST_DOMAIN);
255 curl = curl_easy_init ();
256 curl_easy_setopt (curl, CURLOPT_URL, url);
257 curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, &copy_buffer);
258 curl_easy_setopt (curl, CURLOPT_WRITEDATA, &cbc);
259 curl_easy_setopt (curl, CURLOPT_FAILONERROR, 1);
260 curl_easy_setopt (curl, CURLOPT_TIMEOUT, 150L);
261 curl_easy_setopt (curl, CURLOPT_CONNECTTIMEOUT, 15L);
262 curl_easy_setopt (curl, CURLOPT_NOSIGNAL, 1);
263
264 multi = curl_multi_init ();
265 GNUNET_assert (multi != NULL);
266 GNUNET_assert (CURLM_OK == curl_multi_add_handle (multi, curl));
267 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Beginning HTTP download from `%s'\n", url);
268 curl_main ();
269}
270
271/**
272 * Callback invoked from the namestore service once record is
273 * created.
274 *
275 * @param cls closure
276 * @param af address family, AF_INET or AF_INET6; AF_UNSPEC on error;
277 * will match 'result_af' from the request
278 * @param address IP address (struct in_addr or struct in_addr6, depending on 'af')
279 * that the VPN allocated for the redirection;
280 * traffic to this IP will now be redirected to the
281 * specified target peer; NULL on error
282 */
283static void
284commence_testing (void *cls, int32_t success, const char *emsg)
285{
286 GNUNET_NAMESTORE_disconnect (namestore);
287
288 if ((emsg != NULL) && (GNUNET_YES != success))
289 {
290 fprintf (stderr,
291 "NS failed to create record %s\n", emsg);
292 GNUNET_SCHEDULER_shutdown ();
293 return;
294 }
295
296 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10), start_curl, NULL);
297
298}
299
300
301
302
303/**
304 * Function to keep the HTTP server running.
305 */
306static void
307mhd_main (void);
308
309
310static void
311mhd_task (void *cls,
312 const struct GNUNET_SCHEDULER_TaskContext *tc)
313{
314 mhd_task_id = GNUNET_SCHEDULER_NO_TASK;
315 MHD_run (mhd);
316 mhd_main ();
317}
318
319
320static void
321ctrl_c_shutdown (void *cls,
322 const struct GNUNET_SCHEDULER_TaskContext *tc)
323{
324 ctrl_c_task_id = GNUNET_SCHEDULER_NO_TASK;
325 do_shutdown ();
326 GNUNET_break (0);
327 global_ret = 1;
328}
329
330
331static void
332mhd_main ()
333{
334 struct GNUNET_NETWORK_FDSet nrs;
335 struct GNUNET_NETWORK_FDSet nws;
336 fd_set rs;
337 fd_set ws;
338 fd_set es;
339 int max_fd;
340 unsigned MHD_LONG_LONG timeout;
341 struct GNUNET_TIME_Relative delay;
342
343 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == mhd_task_id);
344 FD_ZERO (&rs);
345 FD_ZERO (&ws);
346 FD_ZERO (&es);
347 max_fd = -1;
348 GNUNET_assert (MHD_YES ==
349 MHD_get_fdset (mhd, &rs, &ws, &es, &max_fd));
350 if (MHD_YES == MHD_get_timeout (mhd, &timeout))
351 delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS,
352 (unsigned int) timeout);
353 else
354 delay = GNUNET_TIME_UNIT_FOREVER_REL;
355 GNUNET_NETWORK_fdset_copy_native (&nrs,
356 &rs,
357 max_fd + 1);
358 GNUNET_NETWORK_fdset_copy_native (&nws,
359 &ws,
360 max_fd + 1);
361 mhd_task_id = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
362 delay,
363 &nrs,
364 &nws,
365 &mhd_task,
366 NULL);
367}
368
369#include "../dns/dnsparser.h"
370
371static void
372run (void *cls,
373 const struct GNUNET_CONFIGURATION_Handle *cfg,
374 struct GNUNET_TESTING_Peer *peer)
375{
376 enum MHD_FLAG flags;
377 struct GNUNET_PeerIdentity id;
378 struct GNUNET_CRYPTO_HashAsciiEncoded peername;
379 struct GNUNET_CRYPTO_RsaPrivateKey *host_key;
380 struct GNUNET_NAMESTORE_RecordData rd;
381 char *rd_string;
382 char *zone_keyfile;
383
384 GNUNET_TESTING_peer_get_identity (peer, &id);
385 GNUNET_CRYPTO_hash_to_enc ((struct GNUNET_HashCode*)&id, &peername);
386
387 namestore = GNUNET_NAMESTORE_connect (cfg);
388 GNUNET_assert (NULL != namestore);
389 flags = MHD_USE_DEBUG;
390 //if (GNUNET_YES == use_v6)
391 // flags |= MHD_USE_IPv6;
392 mhd = MHD_start_daemon (flags,
393 PORT,
394 NULL, NULL,
395 &mhd_ahc, NULL,
396 MHD_OPTION_END);
397 GNUNET_assert (NULL != mhd);
398 mhd_main ();
399 /*rr = GNUNET_VPN_redirect_to_ip (vpn,
400 src_af,
401 dest_af,
402 addr,
403 GNUNET_YES,
404 GNUNET_TIME_UNIT_FOREVER_ABS,
405 &allocation_cb, NULL);
406 ctrl_c_task_id = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
407 &ctrl_c_shutdown,
408 NULL);*/
409 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "gns",
410 "ZONEKEY",
411 &zone_keyfile))
412 {
413 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to get key from cfg\n");
414 return;
415 }
416
417 host_key = GNUNET_CRYPTO_rsa_key_create_from_file (zone_keyfile);
418 rd.expiration_time = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value;
419 GNUNET_asprintf (&rd_string, "6 %s %s", (char*)&peername, "localhost4");
420 GNUNET_assert (GNUNET_OK == GNUNET_NAMESTORE_string_to_value (GNUNET_GNS_RECORD_VPN,
421 rd_string,
422 (void**)&rd.data,
423 &rd.data_size));
424 rd.record_type = GNUNET_GNS_RECORD_VPN;
425
426 struct vpn_data* vpn = (struct vpn_data*)rd.data;
427
428 printf ("%hu %s %s\n", ntohs (vpn->proto), GNUNET_h2s (&vpn->peer),
429 (char*)&vpn[1]);
430
431 GNUNET_NAMESTORE_record_create (namestore,
432 host_key,
433 "www",
434 &rd,
435 &commence_testing,
436 NULL);
437 GNUNET_free ((void**)rd.data);
438 GNUNET_free (rd_string);
439 GNUNET_free (zone_keyfile);
440 GNUNET_CRYPTO_rsa_key_free (host_key);
441}
442
443
444/**
445 * Test if the given AF is supported by this system.
446 *
447 * @param af to test
448 * @return GNUNET_OK if the AF is supported
449 */
450static int
451test_af (int af)
452{
453 int s;
454
455 s = socket (af, SOCK_STREAM, 0);
456 if (-1 == s)
457 {
458 if (EAFNOSUPPORT == errno)
459 return GNUNET_NO;
460 fprintf (stderr, "Failed to create test socket: %s\n", STRERROR (errno));
461 return GNUNET_SYSERR;
462 }
463 close (s);
464 return GNUNET_OK;
465}
466
467
468int
469main (int argc, char *const *argv)
470{
471 if (0 != ACCESS ("/dev/net/tun", R_OK))
472 {
473 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
474 "access",
475 "/dev/net/tun");
476 fprintf (stderr,
477 "WARNING: System unable to run test, skipping.\n");
478 return 0;
479 }
480 if ( (GNUNET_YES !=
481 GNUNET_OS_check_helper_binary ("gnunet-helper-vpn")) ||
482 (GNUNET_YES !=
483 GNUNET_OS_check_helper_binary ("gnunet-helper-exit")) ||
484 (GNUNET_YES !=
485 GNUNET_OS_check_helper_binary ("gnunet-helper-dns")))
486 {
487 fprintf (stderr,
488 "WARNING: gnunet-helper-{exit,vpn,dns} binaries in $PATH are not SUID, refusing to run test (as it would have to fail).\n");
489 fprintf (stderr,
490 "Change $PATH ('.' in $PATH before $GNUNET_PREFIX/bin is problematic) or permissions (run 'make install' as root) to fix this!\n");
491 return 0;
492 }
493 GNUNET_CRYPTO_setup_hostkey ("test_gns_vpn.conf");
494
495 dest_ip = "169.254.86.1";
496 dest_af = AF_INET;
497 src_af = AF_INET;
498
499 if (GNUNET_OK == test_af (AF_INET6))
500 use_v6 = GNUNET_YES;
501 else
502 use_v6 = GNUNET_NO;
503
504 if ( (GNUNET_OK != test_af (src_af)) ||
505 (GNUNET_OK != test_af (dest_af)) )
506 {
507 fprintf (stderr,
508 "Required address families not supported by this system, skipping test.\n");
509 return 0;
510 }
511 if (0 != curl_global_init (CURL_GLOBAL_WIN32))
512 {
513 fprintf (stderr, "failed to initialize curl\n");
514 return 2;
515 }
516 if (0 != GNUNET_TESTING_peer_run ("test-gnunet-vpn",
517 "test_gns_vpn.conf",
518 &run, NULL))
519 return 1;
520 GNUNET_DISK_directory_remove ("/tmp/gnunet-test-vpn");
521 return global_ret;
522}
523
524/* end of test_gns_vpn.c */
525
diff --git a/src/vpn/test_gns_vpn.conf b/src/vpn/test_gns_vpn.conf
new file mode 100644
index 000000000..4c1425793
--- /dev/null
+++ b/src/vpn/test_gns_vpn.conf
@@ -0,0 +1,52 @@
1[PATHS]
2SERVICEHOME = /tmp/gnunet-test-vpn/
3DEFAULTCONFIG = test_gnunet_vpn.conf
4
5[transport]
6PLUGINS = tcp
7
8[arm]
9DEFAULTSERVICES = statistics exit mesh vpn namestore gns
10PORT = 0
11ALLOW_SHUTDOWN = YES
12
13[exit]
14EXIT_IPV4 = YES
15EXIT_IPV6 = YES
16
17# FIXME: can we use 'lo'?
18EXIT_IFNAME = eth1
19
20[testing]
21WEAKRANDOM = YES
22HOSTKEYSFILE = ../../contrib/testing_hostkeys.dat
23
24[nse]
25WORKBITS = 1
26
27# repeating some values from the default configurations
28# here as the respective network addresses are also
29# hard-wired in the tests and the MUST match (!)
30[vpn]
31IPV6ADDR = FC2D:FDAA:6A26::1
32IPV6PREFIX = 64
33IPV4ADDR = 169.254.20.1
34IPV4MASK = 255.255.255.0
35
36[exit]
37IPV6ADDR = FC5A:04E1:C2BA::1
38IPV6PREFIX = 96
39IPV4ADDR = 169.254.86.1
40IPV4MASK = 255.255.255.0
41
42[www.gnunet.]
43TCP_REDIRECTS = 80:localhost4:8080
44TTL = 3600000
45
46[gns]
47AUTOSTART = YES
48ZONEKEY = $SERVICEHOME/hostkey
49HIJACK_DNS = YES
50
51[namestore]
52AUTOSTART = YES