test_gns_vpn.c 21 KB

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