test_gns_vpn.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865
  1. /*
  2. This file is part of GNUnet
  3. Copyright (C) 2007, 2009, 2011, 2012, 2015, 2017 Christian Grothoff
  4. GNUnet is free software: you can redistribute it and/or modify it
  5. under the terms of the GNU Affero General Public License as published
  6. by the Free Software Foundation, either version 3 of the License,
  7. or (at your option) any later version.
  8. GNUnet is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Affero General Public License for more details.
  12. You should have received a copy of the GNU Affero General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. SPDX-License-Identifier: AGPL3.0-or-later
  15. */
  16. /**
  17. * @file test_gns_vpn.c
  18. * @brief testcase for accessing VPN services via GNS
  19. * @author Martin Schanzenbach
  20. * @author Christian Grothoff
  21. *
  22. * This test requires libcurl/libgnurl *with* support for C-ARES.
  23. * This is NOT the default on most platforms, which means the test
  24. * will be skipped in many cases. Compile libcurl/libgnurl with
  25. * "--enable-ares" to get this test to pass.
  26. *
  27. * Furthermore, the test relies on gnunet-dns2gns being able to bind
  28. * to port 53. This means that 'setcap' has to have worked during
  29. * 'make install'. If this failed, but everything else is OK, the
  30. * test may FAIL hard even though it is just an installation issue (we
  31. * cannot conveniently test for the setcap to have worked). However,
  32. * you should get a warning that gnunet-dns2gns failed to 'bind'.
  33. */
  34. #include "platform.h"
  35. /* Just included for the right curl.h */
  36. #include "gnunet_curl_lib.h"
  37. #include <microhttpd.h>
  38. #include "gnunet_identity_service.h"
  39. #include "gnunet_namestore_service.h"
  40. #include "gnunet_gnsrecord_lib.h"
  41. #include "gnunet_gns_service.h"
  42. #include "gnunet_testing_lib.h"
  43. #define PORT 8080
  44. #define TEST_DOMAIN "www.gnu"
  45. #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
  46. /**
  47. * Return value for #main().
  48. */
  49. static int global_ret;
  50. static struct GNUNET_NAMESTORE_Handle *namestore;
  51. static struct MHD_Daemon *mhd;
  52. static struct GNUNET_SCHEDULER_Task *mhd_task_id;
  53. static struct GNUNET_SCHEDULER_Task *curl_task_id;
  54. static struct GNUNET_SCHEDULER_Task *timeout_task;
  55. static struct GNUNET_IDENTITY_Handle *identity;
  56. static struct GNUNET_NAMESTORE_QueueEntry *qe;
  57. static CURL *curl;
  58. static CURLM *multi;
  59. static char *url;
  60. static struct GNUNET_PeerIdentity id;
  61. /**
  62. * IP address of the ultimate destination.
  63. */
  64. static const char *dest_ip;
  65. /**
  66. * Address family of the dest_ip.
  67. */
  68. static int dest_af;
  69. /**
  70. * Address family to use by the curl client.
  71. */
  72. static int src_af;
  73. static int use_v6;
  74. struct CBC
  75. {
  76. char buf[1024];
  77. size_t pos;
  78. };
  79. static struct CBC cbc;
  80. static size_t
  81. copy_buffer (void *ptr,
  82. size_t size,
  83. size_t nmemb,
  84. void *ctx)
  85. {
  86. struct CBC *cbc = ctx;
  87. if (cbc->pos + size * nmemb > sizeof(cbc->buf))
  88. return 0; /* overflow */
  89. GNUNET_memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb);
  90. cbc->pos += size * nmemb;
  91. return size * nmemb;
  92. }
  93. static int
  94. mhd_ahc (void *cls,
  95. struct MHD_Connection *connection,
  96. const char *url,
  97. const char *method,
  98. const char *version,
  99. const char *upload_data, size_t *upload_data_size,
  100. void **unused)
  101. {
  102. static int ptr;
  103. struct MHD_Response *response;
  104. int ret;
  105. if (0 != strcmp ("GET", method))
  106. return MHD_NO; /* unexpected method */
  107. if (&ptr != *unused)
  108. {
  109. *unused = &ptr;
  110. return MHD_YES;
  111. }
  112. *unused = NULL;
  113. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  114. "MHD sends respose for request to URL `%s'\n", url);
  115. response = MHD_create_response_from_buffer (strlen (url),
  116. (void *) url,
  117. MHD_RESPMEM_MUST_COPY);
  118. ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
  119. MHD_destroy_response (response);
  120. if (ret == MHD_NO)
  121. abort ();
  122. return ret;
  123. }
  124. static void
  125. do_shutdown (void *cls)
  126. {
  127. if (NULL != mhd_task_id)
  128. {
  129. GNUNET_SCHEDULER_cancel (mhd_task_id);
  130. mhd_task_id = NULL;
  131. }
  132. if (NULL != curl_task_id)
  133. {
  134. GNUNET_SCHEDULER_cancel (curl_task_id);
  135. curl_task_id = NULL;
  136. }
  137. if (NULL != timeout_task)
  138. {
  139. GNUNET_SCHEDULER_cancel (timeout_task);
  140. timeout_task = NULL;
  141. }
  142. if (NULL != mhd)
  143. {
  144. MHD_stop_daemon (mhd);
  145. mhd = NULL;
  146. }
  147. if (NULL != identity)
  148. {
  149. GNUNET_IDENTITY_disconnect (identity);
  150. identity = NULL;
  151. }
  152. if (NULL != qe)
  153. {
  154. GNUNET_NAMESTORE_cancel (qe);
  155. qe = NULL;
  156. }
  157. if (NULL != namestore)
  158. {
  159. GNUNET_NAMESTORE_disconnect (namestore);
  160. namestore = NULL;
  161. }
  162. GNUNET_free_non_null (url);
  163. url = NULL;
  164. }
  165. static void
  166. do_timeout (void *cls)
  167. {
  168. timeout_task = NULL;
  169. GNUNET_SCHEDULER_shutdown ();
  170. }
  171. /**
  172. * Function to run the HTTP client.
  173. */
  174. static void
  175. curl_main (void);
  176. static void
  177. curl_task (void *cls)
  178. {
  179. curl_task_id = NULL;
  180. curl_main ();
  181. }
  182. static void
  183. curl_main ()
  184. {
  185. fd_set rs;
  186. fd_set ws;
  187. fd_set es;
  188. int max;
  189. struct GNUNET_NETWORK_FDSet nrs;
  190. struct GNUNET_NETWORK_FDSet nws;
  191. struct GNUNET_TIME_Relative delay;
  192. long timeout;
  193. int running;
  194. struct CURLMsg *msg;
  195. max = 0;
  196. FD_ZERO (&rs);
  197. FD_ZERO (&ws);
  198. FD_ZERO (&es);
  199. curl_multi_perform (multi, &running);
  200. if (running == 0)
  201. {
  202. GNUNET_assert (NULL != (msg = curl_multi_info_read (multi, &running)));
  203. if (msg->msg == CURLMSG_DONE)
  204. {
  205. if (msg->data.result != CURLE_OK)
  206. {
  207. fprintf (stderr,
  208. "%s failed at %s:%d: `%s'\n",
  209. "curl_multi_perform",
  210. __FILE__,
  211. __LINE__, curl_easy_strerror (msg->data.result));
  212. global_ret = 1;
  213. }
  214. }
  215. curl_multi_remove_handle (multi, curl);
  216. curl_multi_cleanup (multi);
  217. curl_easy_cleanup (curl);
  218. curl = NULL;
  219. multi = NULL;
  220. if (cbc.pos != strlen ("/hello_world"))
  221. {
  222. GNUNET_break (0);
  223. global_ret = 2;
  224. }
  225. if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
  226. {
  227. GNUNET_break (0);
  228. global_ret = 3;
  229. }
  230. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  231. "Download complete, shutting down!\n");
  232. GNUNET_SCHEDULER_shutdown ();
  233. return;
  234. }
  235. GNUNET_assert (CURLM_OK == curl_multi_fdset (multi, &rs, &ws, &es, &max));
  236. if ((CURLM_OK != curl_multi_timeout (multi, &timeout)) ||
  237. (-1 == timeout))
  238. delay = GNUNET_TIME_UNIT_SECONDS;
  239. else
  240. delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS,
  241. (unsigned int) timeout);
  242. GNUNET_NETWORK_fdset_copy_native (&nrs,
  243. &rs,
  244. max + 1);
  245. GNUNET_NETWORK_fdset_copy_native (&nws,
  246. &ws,
  247. max + 1);
  248. curl_task_id = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
  249. delay,
  250. &nrs,
  251. &nws,
  252. &curl_task,
  253. NULL);
  254. }
  255. static void
  256. start_curl (void *cls)
  257. {
  258. CURLcode ec;
  259. curl_task_id = NULL;
  260. GNUNET_asprintf (&url,
  261. "http://%s/hello_world",
  262. TEST_DOMAIN);
  263. curl = curl_easy_init ();
  264. curl_easy_setopt (curl, CURLOPT_URL, url);
  265. curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, &copy_buffer);
  266. curl_easy_setopt (curl, CURLOPT_WRITEDATA, &cbc);
  267. curl_easy_setopt (curl, CURLOPT_FAILONERROR, 1);
  268. curl_easy_setopt (curl, CURLOPT_TIMEOUT, 150L);
  269. curl_easy_setopt (curl, CURLOPT_CONNECTTIMEOUT, 150L);
  270. curl_easy_setopt (curl, CURLOPT_NOSIGNAL, 1);
  271. if (CURLE_OK !=
  272. (ec = curl_easy_setopt (curl,
  273. CURLOPT_DNS_SERVERS,
  274. "127.0.0.1:53")))
  275. {
  276. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  277. "curl build without support for CURLOPT_DNS_SERVERS (%s), cannot run test\n",
  278. curl_easy_strerror (ec));
  279. global_ret = 77;
  280. GNUNET_SCHEDULER_shutdown ();
  281. return;
  282. }
  283. multi = curl_multi_init ();
  284. GNUNET_assert (multi != NULL);
  285. GNUNET_assert (CURLM_OK == curl_multi_add_handle (multi, curl));
  286. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  287. "Beginning HTTP download from `%s'\n",
  288. url);
  289. curl_main ();
  290. }
  291. /**
  292. * Callback invoked from the namestore service once record is
  293. * created.
  294. *
  295. * @param cls closure
  296. * @param af address family, AF_INET or AF_INET6; AF_UNSPEC on error;
  297. * will match 'result_af' from the request
  298. * @param address IP address (struct in_addr or struct in_addr6, depending on 'af')
  299. * that the VPN allocated for the redirection;
  300. * traffic to this IP will now be redirected to the
  301. * specified target peer; NULL on error
  302. */
  303. static void
  304. commence_testing (void *cls,
  305. int32_t success,
  306. const char *emsg)
  307. {
  308. qe = NULL;
  309. if ((NULL != emsg) &&
  310. (GNUNET_YES != success))
  311. {
  312. fprintf (stderr,
  313. "NS failed to create record %s\n",
  314. emsg);
  315. GNUNET_SCHEDULER_shutdown ();
  316. return;
  317. }
  318. /* wait a little bit before downloading, as we just created the record */
  319. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  320. "Launching cURL request\n");
  321. curl_task_id
  322. = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
  323. &start_curl,
  324. NULL);
  325. }
  326. /**
  327. * Function to keep the HTTP server running.
  328. */
  329. static void
  330. mhd_main (void);
  331. static void
  332. mhd_task (void *cls)
  333. {
  334. mhd_task_id = NULL;
  335. MHD_run (mhd);
  336. mhd_main ();
  337. }
  338. static void
  339. mhd_main ()
  340. {
  341. struct GNUNET_NETWORK_FDSet nrs;
  342. struct GNUNET_NETWORK_FDSet nws;
  343. fd_set rs;
  344. fd_set ws;
  345. fd_set es;
  346. int max_fd;
  347. unsigned MHD_LONG_LONG timeout;
  348. struct GNUNET_TIME_Relative delay;
  349. GNUNET_assert (NULL == mhd_task_id);
  350. FD_ZERO (&rs);
  351. FD_ZERO (&ws);
  352. FD_ZERO (&es);
  353. max_fd = -1;
  354. GNUNET_assert (MHD_YES ==
  355. MHD_get_fdset (mhd, &rs, &ws, &es, &max_fd));
  356. if (MHD_YES == MHD_get_timeout (mhd, &timeout))
  357. delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS,
  358. (unsigned int) timeout);
  359. else
  360. delay = GNUNET_TIME_UNIT_FOREVER_REL;
  361. GNUNET_NETWORK_fdset_copy_native (&nrs,
  362. &rs,
  363. max_fd + 1);
  364. GNUNET_NETWORK_fdset_copy_native (&nws,
  365. &ws,
  366. max_fd + 1);
  367. mhd_task_id = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
  368. delay,
  369. &nrs,
  370. &nws,
  371. &mhd_task,
  372. NULL);
  373. }
  374. /**
  375. * Open '/dev/null' and make the result the given
  376. * file descriptor.
  377. *
  378. * @param target_fd desired FD to point to /dev/null
  379. * @param flags open flags (O_RDONLY, O_WRONLY)
  380. */
  381. static void
  382. open_dev_null (int target_fd,
  383. int flags)
  384. {
  385. int fd;
  386. fd = open ("/dev/null", flags);
  387. if (-1 == fd)
  388. abort ();
  389. if (fd == target_fd)
  390. return;
  391. if (-1 == dup2 (fd, target_fd))
  392. {
  393. (void) close (fd);
  394. abort ();
  395. }
  396. (void) close (fd);
  397. }
  398. /**
  399. * Run the given command and wait for it to complete.
  400. *
  401. * @param file name of the binary to run
  402. * @param cmd command line arguments (as given to 'execv')
  403. * @return 0 on success, 1 on any error
  404. */
  405. static int
  406. fork_and_exec (const char *file,
  407. char *const cmd[])
  408. {
  409. int status;
  410. pid_t pid;
  411. pid_t ret;
  412. pid = fork ();
  413. if (-1 == pid)
  414. {
  415. GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
  416. "fork");
  417. return 1;
  418. }
  419. if (0 == pid)
  420. {
  421. /* we are the child process */
  422. /* close stdin/stdout to not cause interference
  423. with the helper's main protocol! */
  424. (void) close (0);
  425. open_dev_null (0, O_RDONLY);
  426. (void) close (1);
  427. open_dev_null (1, O_WRONLY);
  428. (void) execv (file, cmd);
  429. /* can only get here on error */
  430. GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
  431. "exec",
  432. file);
  433. _exit (1);
  434. }
  435. /* keep running waitpid as long as the only error we get is 'EINTR' */
  436. while ((-1 == (ret = waitpid (pid, &status, 0))) &&
  437. (errno == EINTR))
  438. ;
  439. if (-1 == ret)
  440. {
  441. GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
  442. "waitpid");
  443. return 1;
  444. }
  445. if (! (WIFEXITED (status) &&
  446. (0 == WEXITSTATUS (status))))
  447. {
  448. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  449. "Process `%s` returned status code %d/%d.\n",
  450. file,
  451. WIFEXITED (status),
  452. WEXITSTATUS (status));
  453. return 1;
  454. }
  455. /* child process completed and returned success, we're happy */
  456. return 0;
  457. }
  458. /**
  459. * Method called to inform about the egos of this peer.
  460. *
  461. * When used with #GNUNET_IDENTITY_connect, this function is
  462. * initially called for all egos and then again whenever a
  463. * ego's name changes or if it is deleted. At the end of
  464. * the initial pass over all egos, the function is once called
  465. * with 'NULL' for @a ego. That does NOT mean that the callback won't
  466. * be invoked in the future or that there was an error.
  467. *
  468. * When used with #GNUNET_IDENTITY_create or #GNUNET_IDENTITY_get,
  469. * this function is only called ONCE, and 'NULL' being passed in
  470. * @a ego does indicate an error (i.e. name is taken or no default
  471. * value is known). If @a ego is non-NULL and if '*ctx'
  472. * is set in those callbacks, the value WILL be passed to a subsequent
  473. * call to the identity callback of #GNUNET_IDENTITY_connect (if
  474. * that one was not NULL).
  475. *
  476. * When an identity is renamed, this function is called with the
  477. * (known) @a ego but the NEW @a name.
  478. *
  479. * When an identity is deleted, this function is called with the
  480. * (known) ego and "NULL" for the @a name. In this case,
  481. * the @a ego is henceforth invalid (and the @a ctx should also be
  482. * cleaned up).
  483. *
  484. * @param cls closure
  485. * @param ego ego handle
  486. * @param ctx context for application to store data for this ego
  487. * (during the lifetime of this process, initially NULL)
  488. * @param name name assigned by the user for this ego,
  489. * NULL if the user just deleted the ego and it
  490. * must thus no longer be used
  491. */
  492. static void
  493. identity_cb (void *cls,
  494. struct GNUNET_IDENTITY_Ego *ego,
  495. void **ctx,
  496. const char *name)
  497. {
  498. const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key;
  499. struct GNUNET_GNSRECORD_Data rd;
  500. char *rd_string;
  501. char *peername;
  502. if (NULL == name)
  503. return;
  504. if (NULL == ego)
  505. {
  506. if (NULL == qe)
  507. {
  508. fprintf (stderr,
  509. "Failed to find master-zone ego\n");
  510. GNUNET_SCHEDULER_shutdown ();
  511. return;
  512. }
  513. GNUNET_IDENTITY_disconnect (identity);
  514. identity = NULL;
  515. return;
  516. }
  517. GNUNET_assert (NULL != name);
  518. if (0 != strcmp (name,
  519. "master-zone"))
  520. {
  521. fprintf (stderr,
  522. "Unexpected name %s\n",
  523. name);
  524. return;
  525. }
  526. zone_key = GNUNET_IDENTITY_ego_get_private_key (ego);
  527. rd.expiration_time = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us;
  528. peername = GNUNET_strdup (GNUNET_i2s_full (&id));
  529. GNUNET_asprintf (&rd_string,
  530. "6 %s %s",
  531. peername,
  532. "www");
  533. GNUNET_free (peername);
  534. GNUNET_assert (GNUNET_OK ==
  535. GNUNET_GNSRECORD_string_to_value (GNUNET_GNSRECORD_TYPE_VPN,
  536. rd_string,
  537. (void **) &rd.data,
  538. &rd.data_size));
  539. rd.record_type = GNUNET_GNSRECORD_TYPE_VPN;
  540. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  541. "Creating `www` record\n");
  542. qe = GNUNET_NAMESTORE_records_store (namestore,
  543. zone_key,
  544. "www",
  545. 1, &rd,
  546. &commence_testing,
  547. NULL);
  548. GNUNET_free ((void **) rd.data);
  549. GNUNET_free (rd_string);
  550. }
  551. static void
  552. run (void *cls,
  553. const struct GNUNET_CONFIGURATION_Handle *cfg,
  554. struct GNUNET_TESTING_Peer *peer)
  555. {
  556. enum MHD_FLAG flags;
  557. char *bin;
  558. char *bin_identity;
  559. char *bin_gns;
  560. char *bin_arm;
  561. char *config;
  562. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  563. "Test logic starting...\n");
  564. if (GNUNET_OK !=
  565. GNUNET_CONFIGURATION_get_value_string (cfg,
  566. "arm",
  567. "CONFIG",
  568. &config))
  569. {
  570. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  571. "Failed to locate configuration file. Skipping test.\n");
  572. GNUNET_SCHEDULER_shutdown ();
  573. return;
  574. }
  575. char *const identity_args[] = {
  576. "gnunet-identity",
  577. "-C", "master-zone",
  578. "-c", config,
  579. NULL
  580. };
  581. char *const identity2_args[] = {
  582. "gnunet-identity",
  583. "-e", "master-zone",
  584. "-s", "gns-master",
  585. "-c", config,
  586. NULL
  587. };
  588. char *const identity3_args[] = {
  589. "gnunet-identity",
  590. "-e", "master-zone",
  591. "-s", "dns2gns",
  592. "-c", config,
  593. NULL
  594. };
  595. char *const arm_args[] = {
  596. "gnunet-arm",
  597. "-i", "dns2gns",
  598. "-c", config,
  599. NULL
  600. };
  601. char *const gns_args[] = {
  602. "gnunet-gns",
  603. "-u", "www.gnu",
  604. "-c", config,
  605. NULL
  606. };
  607. GNUNET_TESTING_peer_get_identity (peer,
  608. &id);
  609. GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
  610. NULL);
  611. timeout_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
  612. &do_timeout,
  613. NULL);
  614. bin = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_BINDIR);
  615. GNUNET_asprintf (&bin_identity,
  616. "%s/%s",
  617. bin,
  618. "gnunet-identity");
  619. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  620. "Creating `master-zone` ego\n");
  621. if (0 != fork_and_exec (bin_identity, identity_args))
  622. {
  623. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  624. "Failed to run `gnunet-identity -C`. Skipping test.\n");
  625. GNUNET_SCHEDULER_shutdown ();
  626. GNUNET_free (bin_identity);
  627. GNUNET_free (config);
  628. GNUNET_free (bin);
  629. return;
  630. }
  631. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  632. "Setting `master-zone` ego as default for `gns-master` and `dns2gns`\n");
  633. if (0 != fork_and_exec (bin_identity, identity2_args))
  634. {
  635. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  636. "Failed to run `gnunet-identity -e`. Skipping test.\n");
  637. GNUNET_SCHEDULER_shutdown ();
  638. GNUNET_free (bin_identity);
  639. GNUNET_free (config);
  640. GNUNET_free (bin);
  641. return;
  642. }
  643. if (0 != fork_and_exec (bin_identity, identity3_args))
  644. {
  645. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  646. "Failed to run `gnunet-identity -e`. Skipping test.\n");
  647. GNUNET_SCHEDULER_shutdown ();
  648. GNUNET_free (bin_identity);
  649. GNUNET_free (config);
  650. GNUNET_free (bin);
  651. return;
  652. }
  653. GNUNET_free (bin_identity);
  654. /* do lookup just to launch GNS service */
  655. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  656. "Resolving `www.gnu` zone entry to launch GNS (will yield no answer yet)\n");
  657. GNUNET_asprintf (&bin_gns,
  658. "%s/%s",
  659. bin,
  660. "gnunet-gns");
  661. if (0 != fork_and_exec (bin_gns,
  662. gns_args))
  663. {
  664. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  665. "Failed to run `gnunet-gns -u. Skipping test.\n");
  666. GNUNET_SCHEDULER_shutdown ();
  667. GNUNET_free (bin_gns);
  668. GNUNET_free (config);
  669. GNUNET_free (bin);
  670. return;
  671. }
  672. GNUNET_free (bin_gns);
  673. GNUNET_asprintf (&bin_arm,
  674. "%s/%s",
  675. bin,
  676. "gnunet-arm");
  677. if (0 != fork_and_exec (bin_arm,
  678. arm_args))
  679. {
  680. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  681. "Failed to run `gnunet-arm -i dns2gns. Skipping test.\n");
  682. GNUNET_SCHEDULER_shutdown ();
  683. GNUNET_free (bin_arm);
  684. GNUNET_free (config);
  685. GNUNET_free (bin);
  686. return;
  687. }
  688. GNUNET_free (bin_arm);
  689. GNUNET_free (config);
  690. GNUNET_free (bin);
  691. sleep (1); /* give dns2gns chance to really run */
  692. namestore = GNUNET_NAMESTORE_connect (cfg);
  693. GNUNET_assert (NULL != namestore);
  694. flags = MHD_USE_DEBUG;
  695. if (GNUNET_YES == use_v6)
  696. flags |= MHD_USE_DUAL_STACK;
  697. mhd = MHD_start_daemon (flags,
  698. PORT,
  699. NULL, NULL,
  700. &mhd_ahc, NULL,
  701. MHD_OPTION_END);
  702. GNUNET_assert (NULL != mhd);
  703. mhd_main ();
  704. identity = GNUNET_IDENTITY_connect (cfg,
  705. &identity_cb,
  706. NULL);
  707. }
  708. int
  709. main (int argc,
  710. char *const *argv)
  711. {
  712. char *bin_vpn;
  713. char *bin_exit;
  714. GNUNET_log_setup ("test-gns-vpn",
  715. "WARNING",
  716. NULL);
  717. if (0 != access ("/dev/net/tun", R_OK))
  718. {
  719. GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
  720. "access",
  721. "/dev/net/tun");
  722. fprintf (stderr,
  723. "WARNING: System unable to run test, skipping.\n");
  724. return 77;
  725. }
  726. bin_vpn = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-vpn");
  727. bin_exit = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-exit");
  728. if ((0 != geteuid ()) &&
  729. ((GNUNET_YES !=
  730. GNUNET_OS_check_helper_binary (bin_vpn,
  731. GNUNET_YES,
  732. "-d gnunet-vpn - - 169.1.3.3.7 255.255.255.0"))
  733. || // ipv4 only please!
  734. (GNUNET_YES !=
  735. GNUNET_OS_check_helper_binary (bin_exit,
  736. GNUNET_YES,
  737. "-d gnunet-vpn - - - 169.1.3.3.7 255.255.255.0")))) // no nat, ipv4 only
  738. {
  739. fprintf (stderr,
  740. "WARNING: gnunet-helper-{exit,vpn} binaries in $PATH are not SUID, refusing to run test (as it would have to fail).\n");
  741. fprintf (stderr,
  742. "Change $PATH ('.' in $PATH before $GNUNET_PREFIX/bin is problematic) or permissions (run 'make install' as root) to fix this!\n");
  743. GNUNET_free (bin_vpn);
  744. GNUNET_free (bin_exit);
  745. return 77;
  746. }
  747. GNUNET_free (bin_vpn);
  748. GNUNET_free (bin_exit);
  749. dest_ip = "169.254.86.1";
  750. dest_af = AF_INET;
  751. src_af = AF_INET;
  752. if (GNUNET_OK == GNUNET_NETWORK_test_pf (PF_INET6))
  753. use_v6 = GNUNET_YES;
  754. else
  755. use_v6 = GNUNET_NO;
  756. if ((GNUNET_OK != GNUNET_NETWORK_test_pf (src_af)) ||
  757. (GNUNET_OK != GNUNET_NETWORK_test_pf (dest_af)))
  758. {
  759. fprintf (stderr,
  760. "Required address families not supported by this system, skipping test.\n");
  761. return 77;
  762. }
  763. if (0 != curl_global_init (CURL_GLOBAL_WIN32))
  764. {
  765. fprintf (stderr, "failed to initialize curl\n");
  766. return 2;
  767. }
  768. if (0 !=
  769. GNUNET_TESTING_peer_run ("test_gns_vpn",
  770. "test_gns_vpn.conf",
  771. &run,
  772. NULL))
  773. return 1;
  774. GNUNET_DISK_directory_remove ("/tmp/gnunet-test-vpn");
  775. return global_ret;
  776. }
  777. /* end of test_gns_vpn.c */