aboutsummaryrefslogtreecommitdiff
path: root/src/service/pt/test_gns_vpn.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/service/pt/test_gns_vpn.c')
-rw-r--r--src/service/pt/test_gns_vpn.c864
1 files changed, 864 insertions, 0 deletions
diff --git a/src/service/pt/test_gns_vpn.c b/src/service/pt/test_gns_vpn.c
new file mode 100644
index 000000000..4db7bf274
--- /dev/null
+++ b/src/service/pt/test_gns_vpn.c
@@ -0,0 +1,864 @@
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 */
58static int global_ret;
59
60static struct GNUNET_NAMESTORE_Handle *namestore;
61
62static struct MHD_Daemon *mhd;
63
64static struct GNUNET_SCHEDULER_Task *mhd_task_id;
65
66static struct GNUNET_SCHEDULER_Task *curl_task_id;
67
68static struct GNUNET_SCHEDULER_Task *timeout_task;
69
70static struct GNUNET_IDENTITY_Handle *identity;
71
72static struct GNUNET_NAMESTORE_QueueEntry *qe;
73
74static CURL *curl;
75
76static CURLM *multi;
77
78static char *url;
79
80static struct GNUNET_PeerIdentity id;
81
82/**
83 * IP address of the ultimate destination.
84 */
85static const char *dest_ip;
86
87/**
88 * Address family of the dest_ip.
89 */
90static int dest_af;
91
92/**
93 * Address family to use by the curl client.
94 */
95static int src_af;
96
97static int use_v6;
98
99
100struct CBC
101{
102 char buf[1024];
103 size_t pos;
104};
105
106static struct CBC cbc;
107
108
109static size_t
110copy_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
125static MHD_RESULT
126mhd_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
159static void
160do_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
202static void
203do_timeout (void *cls)
204{
205 timeout_task = NULL;
206 GNUNET_SCHEDULER_shutdown ();
207}
208
209
210/**
211 * Function to run the HTTP client.
212 */
213static void
214curl_main (void);
215
216
217static void
218curl_task (void *cls)
219{
220 curl_task_id = NULL;
221 curl_main ();
222}
223
224
225static void
226curl_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
301static void
302start_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, &copy_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 */
352static void
353commence_testing (void *cls,
354 enum GNUNET_ErrorCode ec)
355{
356 qe = NULL;
357 if (GNUNET_EC_NONE != ec)
358 {
359 fprintf (stderr,
360 "NS failed to create record %s\n",
361 GNUNET_ErrorCode_get_hint (ec));
362 GNUNET_SCHEDULER_shutdown ();
363 return;
364 }
365
366 /* wait a little bit before downloading, as we just created the record */
367 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
368 "Launching cURL request\n");
369 curl_task_id
370 = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
371 &start_curl,
372 NULL);
373}
374
375
376/**
377 * Function to keep the HTTP server running.
378 */
379static void
380mhd_main (void);
381
382
383static void
384mhd_task (void *cls)
385{
386 mhd_task_id = NULL;
387 MHD_run (mhd);
388 mhd_main ();
389}
390
391
392static void
393mhd_main ()
394{
395 struct GNUNET_NETWORK_FDSet nrs;
396 struct GNUNET_NETWORK_FDSet nws;
397 fd_set rs;
398 fd_set ws;
399 fd_set es;
400 int max_fd;
401 unsigned MHD_LONG_LONG timeout;
402 struct GNUNET_TIME_Relative delay;
403
404 GNUNET_assert (NULL == mhd_task_id);
405 FD_ZERO (&rs);
406 FD_ZERO (&ws);
407 FD_ZERO (&es);
408 max_fd = -1;
409 GNUNET_assert (MHD_YES ==
410 MHD_get_fdset (mhd, &rs, &ws, &es, &max_fd));
411 if (MHD_YES == MHD_get_timeout (mhd, &timeout))
412 delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS,
413 (unsigned int) timeout);
414 else
415 delay = GNUNET_TIME_UNIT_FOREVER_REL;
416 GNUNET_NETWORK_fdset_copy_native (&nrs,
417 &rs,
418 max_fd + 1);
419 GNUNET_NETWORK_fdset_copy_native (&nws,
420 &ws,
421 max_fd + 1);
422 mhd_task_id = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
423 delay,
424 &nrs,
425 &nws,
426 &mhd_task,
427 NULL);
428}
429
430
431/**
432 * Open '/dev/null' and make the result the given
433 * file descriptor.
434 *
435 * @param target_fd desired FD to point to /dev/null
436 * @param flags open flags (O_RDONLY, O_WRONLY)
437 */
438static void
439open_dev_null (int target_fd,
440 int flags)
441{
442 int fd;
443
444 fd = open ("/dev/null", flags);
445 if (-1 == fd)
446 abort ();
447 if (fd == target_fd)
448 return;
449 if (-1 == dup2 (fd, target_fd))
450 {
451 (void) close (fd);
452 abort ();
453 }
454 (void) close (fd);
455}
456
457
458/**
459 * Run the given command and wait for it to complete.
460 *
461 * @param file name of the binary to run
462 * @param cmd command line arguments (as given to 'execv')
463 * @return 0 on success, 1 on any error
464 */
465static int
466fork_and_exec (const char *file,
467 char *const cmd[])
468{
469 int status;
470 pid_t pid;
471 pid_t ret;
472
473 pid = fork ();
474 if (-1 == pid)
475 {
476 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
477 "fork");
478 return 1;
479 }
480 if (0 == pid)
481 {
482 /* we are the child process */
483 /* close stdin/stdout to not cause interference
484 with the helper's main protocol! */
485 (void) close (0);
486 open_dev_null (0, O_RDONLY);
487 (void) close (1);
488 open_dev_null (1, O_WRONLY);
489 (void) execv (file, cmd);
490 /* can only get here on error */
491 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
492 "exec",
493 file);
494 _exit (1);
495 }
496 /* keep running waitpid as long as the only error we get is 'EINTR' */
497 while ((-1 == (ret = waitpid (pid, &status, 0))) &&
498 (errno == EINTR))
499 ;
500 if (-1 == ret)
501 {
502 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
503 "waitpid");
504 return 1;
505 }
506 if (! (WIFEXITED (status) &&
507 (0 == WEXITSTATUS (status))))
508 {
509 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
510 "Process `%s` returned status code %d/%d.\n",
511 file,
512 WIFEXITED (status),
513 WEXITSTATUS (status));
514 return 1;
515 }
516 /* child process completed and returned success, we're happy */
517 return 0;
518}
519
520
521/**
522 * Method called to inform about the egos of this peer.
523 *
524 * When used with #GNUNET_IDENTITY_connect, this function is
525 * initially called for all egos and then again whenever a
526 * ego's name changes or if it is deleted. At the end of
527 * the initial pass over all egos, the function is once called
528 * with 'NULL' for @a ego. That does NOT mean that the callback won't
529 * be invoked in the future or that there was an error.
530 *
531 * When used with #GNUNET_IDENTITY_create or #GNUNET_IDENTITY_get, this
532 * function is only called ONCE, and 'NULL' being passed in @a ego does
533 * indicate an error (for example because name is taken or no default value is
534 * known). If @a ego is non-NULL and if '*ctx' is set in those callbacks, the
535 * value WILL be passed to a subsequent call to the identity callback of
536 * #GNUNET_IDENTITY_connect (if that one was not NULL).
537 *
538 * When an identity is renamed, this function is called with the
539 * (known) @a ego but the NEW @a name.
540 *
541 * When an identity is deleted, this function is called with the
542 * (known) ego and "NULL" for the @a name. In this case,
543 * the @a ego is henceforth invalid (and the @a ctx should also be
544 * cleaned up).
545 *
546 * @param cls closure
547 * @param ego ego handle
548 * @param ctx context for application to store data for this ego
549 * (during the lifetime of this process, initially NULL)
550 * @param name name assigned by the user for this ego,
551 * NULL if the user just deleted the ego and it
552 * must thus no longer be used
553 */
554static void
555identity_cb (void *cls,
556 struct GNUNET_IDENTITY_Ego *ego,
557 void **ctx,
558 const char *name)
559{
560 const struct GNUNET_CRYPTO_PrivateKey *zone_key;
561 struct GNUNET_GNSRECORD_Data rd;
562 char *rd_string;
563 char *peername;
564
565 if (NULL == name)
566 return;
567 if (NULL == ego)
568 {
569 if (NULL == qe)
570 {
571 fprintf (stderr,
572 "Failed to find master-zone ego\n");
573 GNUNET_SCHEDULER_shutdown ();
574 return;
575 }
576 GNUNET_IDENTITY_disconnect (identity);
577 identity = NULL;
578 return;
579 }
580 GNUNET_assert (NULL != name);
581 if (0 != strcmp (name,
582 "master-zone"))
583 {
584 fprintf (stderr,
585 "Unexpected name %s\n",
586 name);
587 return;
588 }
589 zone_key = GNUNET_IDENTITY_ego_get_private_key (ego);
590 rd.expiration_time = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us;
591 peername = GNUNET_strdup (GNUNET_i2s_full (&id));
592 GNUNET_asprintf (&rd_string,
593 "6 %s %s",
594 peername,
595 "www");
596 GNUNET_free (peername);
597 GNUNET_assert (GNUNET_OK ==
598 GNUNET_GNSRECORD_string_to_value (GNUNET_GNSRECORD_TYPE_VPN,
599 rd_string,
600 (void **) &rd.data,
601 &rd.data_size));
602 rd.record_type = GNUNET_GNSRECORD_TYPE_VPN;
603
604 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
605 "Creating `www` record\n");
606 qe = GNUNET_NAMESTORE_records_store (namestore,
607 zone_key,
608 "www",
609 1, &rd,
610 &commence_testing,
611 NULL);
612 GNUNET_free_nz ((void **) rd.data);
613 GNUNET_free (rd_string);
614}
615
616
617static void
618run (void *cls,
619 const struct GNUNET_CONFIGURATION_Handle *cfg,
620 struct GNUNET_TESTING_Peer *peer)
621{
622 enum MHD_FLAG flags;
623
624 char *bin;
625 char *bin_identity;
626 char *bin_gns;
627 char *bin_arm;
628 char *config;
629
630 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
631 "Test logic starting...\n");
632 if (GNUNET_OK !=
633 GNUNET_CONFIGURATION_get_value_string (cfg,
634 "arm",
635 "CONFIG",
636 &config))
637 {
638 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
639 "Failed to locate configuration file. Skipping test.\n");
640 GNUNET_SCHEDULER_shutdown ();
641 return;
642 }
643
644 char *const identity_args[] = {
645 "gnunet-identity",
646 "-C", "master-zone",
647 "-c", config,
648 NULL
649 };
650 char *const identity2_args[] = {
651 "gnunet-identity",
652 "-e", "master-zone",
653 "-s", "gns-master",
654 "-c", config,
655 NULL
656 };
657 char *const identity3_args[] = {
658 "gnunet-identity",
659 "-e", "master-zone",
660 "-s", "dns2gns",
661 "-c", config,
662 NULL
663 };
664 char *const arm_args[] = {
665 "gnunet-arm",
666 "-i", "dns2gns",
667 "-c", config,
668 NULL
669 };
670 char *const gns_args[] = {
671 "gnunet-gns",
672 "-u", "www.gnu",
673 "-c", config,
674 NULL
675 };
676
677 GNUNET_TESTING_peer_get_identity (peer,
678 &id);
679 GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
680 NULL);
681 timeout_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
682 &do_timeout,
683 NULL);
684 bin = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_BINDIR);
685 GNUNET_asprintf (&bin_identity,
686 "%s/%s",
687 bin,
688 "gnunet-identity");
689 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
690 "Creating `master-zone` ego\n");
691 if (0 != fork_and_exec (bin_identity, identity_args))
692 {
693 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
694 "Failed to run `gnunet-identity -C`. Skipping test.\n");
695 GNUNET_SCHEDULER_shutdown ();
696 GNUNET_free (bin_identity);
697 GNUNET_free (config);
698 GNUNET_free (bin);
699 return;
700 }
701 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
702 "Setting `master-zone` ego as default for `gns-master` and `dns2gns`\n");
703 if (0 != fork_and_exec (bin_identity, identity2_args))
704 {
705 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
706 "Failed to run `gnunet-identity -e`. Skipping test.\n");
707 GNUNET_SCHEDULER_shutdown ();
708 GNUNET_free (bin_identity);
709 GNUNET_free (config);
710 GNUNET_free (bin);
711 return;
712 }
713 if (0 != fork_and_exec (bin_identity, identity3_args))
714 {
715 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
716 "Failed to run `gnunet-identity -e`. Skipping test.\n");
717 GNUNET_SCHEDULER_shutdown ();
718 GNUNET_free (bin_identity);
719 GNUNET_free (config);
720 GNUNET_free (bin);
721 return;
722 }
723 GNUNET_free (bin_identity);
724
725 /* do lookup just to launch GNS service */
726 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
727 "Resolving `www.gnu` zone entry to launch GNS (will yield no answer yet)\n");
728 GNUNET_asprintf (&bin_gns,
729 "%s/%s",
730 bin,
731 "gnunet-gns");
732 if (0 != fork_and_exec (bin_gns,
733 gns_args))
734 {
735 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
736 "Failed to run `gnunet-gns -u. Skipping test.\n");
737 GNUNET_SCHEDULER_shutdown ();
738 GNUNET_free (bin_gns);
739 GNUNET_free (config);
740 GNUNET_free (bin);
741 return;
742 }
743 GNUNET_free (bin_gns);
744
745 GNUNET_asprintf (&bin_arm,
746 "%s/%s",
747 bin,
748 "gnunet-arm");
749 if (0 != fork_and_exec (bin_arm,
750 arm_args))
751 {
752 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
753 "Failed to run `gnunet-arm -i dns2gns. Skipping test.\n");
754 GNUNET_SCHEDULER_shutdown ();
755 GNUNET_free (bin_arm);
756 GNUNET_free (config);
757 GNUNET_free (bin);
758 return;
759 }
760 GNUNET_free (bin_arm);
761
762 GNUNET_free (config);
763 GNUNET_free (bin);
764 sleep (1); /* give dns2gns chance to really run */
765
766 namestore = GNUNET_NAMESTORE_connect (cfg);
767 GNUNET_assert (NULL != namestore);
768 flags = MHD_USE_DEBUG;
769 if (GNUNET_YES == use_v6)
770 flags |= MHD_USE_DUAL_STACK;
771 mhd = MHD_start_daemon (flags,
772 PORT,
773 NULL, NULL,
774 &mhd_ahc, NULL,
775 MHD_OPTION_END);
776 GNUNET_assert (NULL != mhd);
777 mhd_main ();
778
779 identity = GNUNET_IDENTITY_connect (cfg,
780 &identity_cb,
781 NULL);
782}
783
784
785int
786main (int argc,
787 char *const *argv)
788{
789 char *bin_vpn;
790 char *bin_exit;
791
792 GNUNET_log_setup ("test-gns-vpn",
793 "WARNING",
794 NULL);
795 if (0 != access ("/dev/net/tun", R_OK))
796 {
797 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
798 "access",
799 "/dev/net/tun");
800 fprintf (stderr,
801 "WARNING: System unable to run test, skipping.\n");
802 return 77;
803 }
804
805 bin_vpn = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-vpn");
806 bin_exit = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-exit");
807 if ((0 != geteuid ()) &&
808 ((GNUNET_YES !=
809 GNUNET_OS_check_helper_binary (bin_vpn,
810 GNUNET_YES,
811 "-d gnunet-vpn - - 169.1.3.3.7 255.255.255.0"))
812 || // ipv4 only please!
813 (GNUNET_YES !=
814 GNUNET_OS_check_helper_binary (bin_exit,
815 GNUNET_YES,
816 "-d gnunet-vpn - - - 169.1.3.3.7 255.255.255.0")))) // no nat, ipv4 only
817 {
818 fprintf (stderr,
819 "WARNING: gnunet-helper-{exit,vpn} binaries in $PATH are not SUID, refusing to run test (as it would have to fail).\n");
820 fprintf (stderr,
821 "Change $PATH ('.' in $PATH before $GNUNET_PREFIX/bin is problematic) or permissions (run 'make install' as root) to fix this!\n");
822 GNUNET_free (bin_vpn);
823 GNUNET_free (bin_exit);
824 return 77;
825 }
826 GNUNET_free (bin_vpn);
827 GNUNET_free (bin_exit);
828
829 dest_ip = "169.254.86.1";
830 dest_af = AF_INET;
831 src_af = AF_INET;
832
833 if (GNUNET_OK == GNUNET_NETWORK_test_pf (PF_INET6))
834 use_v6 = GNUNET_YES;
835 else
836 use_v6 = GNUNET_NO;
837
838 if ((GNUNET_OK != GNUNET_NETWORK_test_pf (src_af)) ||
839 (GNUNET_OK != GNUNET_NETWORK_test_pf (dest_af)))
840 {
841 fprintf (stderr,
842 "Required address families not supported by this system, skipping test.\n");
843 return 77;
844 }
845 if (0 != curl_global_init (CURL_GLOBAL_WIN32))
846 {
847 fprintf (stderr, "failed to initialize curl\n");
848 return 2;
849 }
850
851
852 if (0 !=
853 GNUNET_TESTING_peer_run ("test_gns_vpn",
854 "test_gns_vpn.conf",
855 &run,
856 NULL))
857 return 1;
858 GNUNET_DISK_purge_cfg_dir ("test_gns_vpn.conf",
859 "GNUNET_TEST_HOME");
860 return global_ret;
861}
862
863
864/* end of test_gns_vpn.c */