gnunet-helper-exit.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817
  1. /*
  2. This file is part of GNUnet.
  3. Copyright (C) 2010, 2011, 2012 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 exit/gnunet-helper-exit.c
  18. *
  19. * @brief the helper for exit nodes. Opens a virtual
  20. * network-interface, sends data received on the if to stdout, sends
  21. * data received on stdin to the interface. The code also enables
  22. * IPv4/IPv6 forwarding and NAT on the current system (the latter on
  23. * an interface specified on the command-line); these changes to the
  24. * network configuration are NOT automatically undone when the program
  25. * is stopped (this is because we cannot be sure that some other
  26. * application didn't enable them before or after us; also, these
  27. * changes should be mostly harmless as it simply turns the system
  28. * into a router).
  29. *
  30. * @author Philipp Tölke
  31. * @author Christian Grothoff
  32. *
  33. * The following list of people have reviewed this code and considered
  34. * it safe since the last modification (if you reviewed it, please
  35. * have your name added to the list):
  36. *
  37. * - Philipp Tölke
  38. */
  39. #include "platform.h"
  40. #include <linux/if_tun.h>
  41. /**
  42. * Need 'struct GNUNET_MessageHeader'.
  43. */
  44. #include "gnunet_crypto_lib.h"
  45. #include "gnunet_common.h"
  46. /**
  47. * Need VPN message types.
  48. */
  49. #include "gnunet_protocols.h"
  50. /**
  51. * Should we print (interesting|debug) messages that can happen during
  52. * normal operation?
  53. */
  54. #define DEBUG GNUNET_NO
  55. /**
  56. * Maximum size of a GNUnet message (GNUNET_MAX_MESSAGE_SIZE)
  57. */
  58. #define MAX_SIZE 65536
  59. /**
  60. * Path to 'sysctl' binary.
  61. */
  62. static const char *sbin_sysctl;
  63. /**
  64. * Path to 'iptables' binary.
  65. */
  66. static const char *sbin_iptables;
  67. #ifndef _LINUX_IN6_H
  68. /**
  69. * This is in linux/include/net/ipv6.h, but not always exported...
  70. */
  71. struct in6_ifreq
  72. {
  73. struct in6_addr ifr6_addr;
  74. uint32_t ifr6_prefixlen; /* __u32 in the original */
  75. int ifr6_ifindex;
  76. };
  77. #endif
  78. /**
  79. * Open '/dev/null' and make the result the given
  80. * file descriptor.
  81. *
  82. * @param target_fd desired FD to point to /dev/null
  83. * @param flags open flags (O_RDONLY, O_WRONLY)
  84. */
  85. static void
  86. open_dev_null (int target_fd,
  87. int flags)
  88. {
  89. int fd;
  90. fd = open ("/dev/null", flags);
  91. if (-1 == fd)
  92. abort ();
  93. if (fd == target_fd)
  94. return;
  95. if (-1 == dup2 (fd, target_fd))
  96. {
  97. (void) close (fd);
  98. abort ();
  99. }
  100. (void) close (fd);
  101. }
  102. /**
  103. * Run the given command and wait for it to complete.
  104. *
  105. * @param file name of the binary to run
  106. * @param cmd command line arguments (as given to 'execv')
  107. * @return 0 on success, 1 on any error
  108. */
  109. static int
  110. fork_and_exec (const char *file,
  111. char *const cmd[])
  112. {
  113. int status;
  114. pid_t pid;
  115. pid_t ret;
  116. pid = fork ();
  117. if (-1 == pid)
  118. {
  119. fprintf (stderr,
  120. "fork failed: %s\n",
  121. strerror (errno));
  122. return 1;
  123. }
  124. if (0 == pid)
  125. {
  126. /* we are the child process */
  127. /* close stdin/stdout to not cause interference
  128. with the helper's main protocol! */
  129. (void) close (0);
  130. open_dev_null (0, O_RDONLY);
  131. (void) close (1);
  132. open_dev_null (1, O_WRONLY);
  133. (void) execv (file, cmd);
  134. /* can only get here on error */
  135. fprintf (stderr,
  136. "exec `%s' failed: %s\n",
  137. file,
  138. strerror (errno));
  139. _exit (1);
  140. }
  141. /* keep running waitpid as long as the only error we get is 'EINTR' */
  142. while ( (-1 == (ret = waitpid (pid, &status, 0))) &&
  143. (errno == EINTR) );
  144. if (-1 == ret)
  145. {
  146. fprintf (stderr,
  147. "waitpid failed: %s\n",
  148. strerror (errno));
  149. return 1;
  150. }
  151. if (! (WIFEXITED (status) && (0 == WEXITSTATUS (status))))
  152. return 1;
  153. /* child process completed and returned success, we're happy */
  154. return 0;
  155. }
  156. /**
  157. * Creates a tun-interface called dev;
  158. *
  159. * @param dev is asumed to point to a char[IFNAMSIZ]
  160. * if *dev == '\\0', uses the name supplied by the kernel;
  161. * @return the fd to the tun or -1 on error
  162. */
  163. static int
  164. init_tun (char *dev)
  165. {
  166. struct ifreq ifr;
  167. int fd;
  168. if (NULL == dev)
  169. {
  170. errno = EINVAL;
  171. return -1;
  172. }
  173. if (-1 == (fd = open ("/dev/net/tun", O_RDWR)))
  174. {
  175. fprintf (stderr, "Error opening `%s': %s\n", "/dev/net/tun",
  176. strerror (errno));
  177. return -1;
  178. }
  179. if (fd >= FD_SETSIZE)
  180. {
  181. fprintf (stderr, "File descriptor to large: %d", fd);
  182. (void) close (fd);
  183. return -1;
  184. }
  185. memset (&ifr, 0, sizeof (ifr));
  186. ifr.ifr_flags = IFF_TUN;
  187. if ('\0' != *dev)
  188. strncpy (ifr.ifr_name, dev, IFNAMSIZ);
  189. if (-1 == ioctl (fd, TUNSETIFF, (void *) &ifr))
  190. {
  191. fprintf (stderr,
  192. "Error with ioctl on `%s': %s\n", "/dev/net/tun",
  193. strerror (errno));
  194. (void) close (fd);
  195. return -1;
  196. }
  197. strcpy (dev, ifr.ifr_name);
  198. return fd;
  199. }
  200. /**
  201. * @brief Sets the IPv6-Address given in address on the interface dev
  202. *
  203. * @param dev the interface to configure
  204. * @param address the IPv6-Address
  205. * @param prefix_len the length of the network-prefix
  206. */
  207. static void
  208. set_address6 (const char *dev, const char *address, unsigned long prefix_len)
  209. {
  210. struct ifreq ifr;
  211. struct sockaddr_in6 sa6;
  212. int fd;
  213. struct in6_ifreq ifr6;
  214. /*
  215. * parse the new address
  216. */
  217. memset (&sa6, 0, sizeof (struct sockaddr_in6));
  218. sa6.sin6_family = AF_INET6;
  219. if (1 != inet_pton (AF_INET6, address, &sa6.sin6_addr))
  220. {
  221. fprintf (stderr, "Failed to parse address `%s': %s\n", address,
  222. strerror (errno));
  223. exit (1);
  224. }
  225. if (-1 == (fd = socket (PF_INET6, SOCK_DGRAM, 0)))
  226. {
  227. fprintf (stderr, "Error creating socket: %s\n", strerror (errno));
  228. exit (1);
  229. }
  230. memset (&ifr, 0, sizeof (struct ifreq));
  231. /*
  232. * Get the index of the if
  233. */
  234. strncpy (ifr.ifr_name, dev, IFNAMSIZ);
  235. if (-1 == ioctl (fd, SIOGIFINDEX, &ifr))
  236. {
  237. fprintf (stderr, "ioctl failed at %d: %s\n", __LINE__, strerror (errno));
  238. (void) close (fd);
  239. exit (1);
  240. }
  241. memset (&ifr6, 0, sizeof (struct in6_ifreq));
  242. ifr6.ifr6_addr = sa6.sin6_addr;
  243. ifr6.ifr6_ifindex = ifr.ifr_ifindex;
  244. ifr6.ifr6_prefixlen = prefix_len;
  245. /*
  246. * Set the address
  247. */
  248. if (-1 == ioctl (fd, SIOCSIFADDR, &ifr6))
  249. {
  250. fprintf (stderr, "ioctl failed at line %d: %s\n", __LINE__,
  251. strerror (errno));
  252. (void) close (fd);
  253. exit (1);
  254. }
  255. /*
  256. * Get the flags
  257. */
  258. if (-1 == ioctl (fd, SIOCGIFFLAGS, &ifr))
  259. {
  260. fprintf (stderr, "ioctl failed at line %d: %s\n", __LINE__,
  261. strerror (errno));
  262. (void) close (fd);
  263. exit (1);
  264. }
  265. /*
  266. * Add the UP and RUNNING flags
  267. */
  268. ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
  269. if (-1 == ioctl (fd, SIOCSIFFLAGS, &ifr))
  270. {
  271. fprintf (stderr, "ioctl failed at line %d: %s\n", __LINE__,
  272. strerror (errno));
  273. (void) close (fd);
  274. exit (1);
  275. }
  276. if (0 != close (fd))
  277. {
  278. fprintf (stderr, "close failed: %s\n", strerror (errno));
  279. exit (1);
  280. }
  281. }
  282. /**
  283. * @brief Sets the IPv4-Address given in address on the interface dev
  284. *
  285. * @param dev the interface to configure
  286. * @param address the IPv4-Address
  287. * @param mask the netmask
  288. */
  289. static void
  290. set_address4 (const char *dev, const char *address, const char *mask)
  291. {
  292. int fd;
  293. struct sockaddr_in *addr;
  294. struct ifreq ifr;
  295. memset (&ifr, 0, sizeof (struct ifreq));
  296. addr = (struct sockaddr_in *) &(ifr.ifr_addr);
  297. addr->sin_family = AF_INET;
  298. /*
  299. * Parse the address
  300. */
  301. if (1 != inet_pton (AF_INET, address, &addr->sin_addr.s_addr))
  302. {
  303. fprintf (stderr, "Failed to parse address `%s': %s\n", address,
  304. strerror (errno));
  305. exit (1);
  306. }
  307. if (-1 == (fd = socket (PF_INET, SOCK_DGRAM, 0)))
  308. {
  309. fprintf (stderr, "Error creating socket: %s\n", strerror (errno));
  310. exit (1);
  311. }
  312. strncpy (ifr.ifr_name, dev, IFNAMSIZ);
  313. /*
  314. * Set the address
  315. */
  316. if (-1 == ioctl (fd, SIOCSIFADDR, &ifr))
  317. {
  318. fprintf (stderr, "ioctl failed at %d: %s\n", __LINE__, strerror (errno));
  319. (void) close (fd);
  320. exit (1);
  321. }
  322. /*
  323. * Parse the netmask
  324. */
  325. addr = (struct sockaddr_in *) &(ifr.ifr_netmask);
  326. if (1 != inet_pton (AF_INET, mask, &addr->sin_addr.s_addr))
  327. {
  328. fprintf (stderr, "Failed to parse address `%s': %s\n", mask,
  329. strerror (errno));
  330. (void) close (fd);
  331. exit (1);
  332. }
  333. /*
  334. * Set the netmask
  335. */
  336. if (-1 == ioctl (fd, SIOCSIFNETMASK, &ifr))
  337. {
  338. fprintf (stderr, "ioctl failed at line %d: %s\n", __LINE__,
  339. strerror (errno));
  340. (void) close (fd);
  341. exit (1);
  342. }
  343. /*
  344. * Get the flags
  345. */
  346. if (-1 == ioctl (fd, SIOCGIFFLAGS, &ifr))
  347. {
  348. fprintf (stderr, "ioctl failed at line %d: %s\n", __LINE__,
  349. strerror (errno));
  350. (void) close (fd);
  351. exit (1);
  352. }
  353. /*
  354. * Add the UP and RUNNING flags
  355. */
  356. ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
  357. if (-1 == ioctl (fd, SIOCSIFFLAGS, &ifr))
  358. {
  359. fprintf (stderr, "ioctl failed at line %d: %s\n", __LINE__,
  360. strerror (errno));
  361. (void) close (fd);
  362. exit (1);
  363. }
  364. if (0 != close (fd))
  365. {
  366. fprintf (stderr, "close failed: %s\n", strerror (errno));
  367. (void) close (fd);
  368. exit (1);
  369. }
  370. }
  371. /**
  372. * Start forwarding to and from the tunnel.
  373. *
  374. * @param fd_tun tunnel FD
  375. */
  376. static void
  377. run (int fd_tun)
  378. {
  379. /*
  380. * The buffer filled by reading from fd_tun
  381. */
  382. unsigned char buftun[MAX_SIZE];
  383. ssize_t buftun_size = 0;
  384. unsigned char *buftun_read = NULL;
  385. /*
  386. * The buffer filled by reading from stdin
  387. */
  388. unsigned char bufin[MAX_SIZE];
  389. ssize_t bufin_size = 0;
  390. size_t bufin_rpos = 0;
  391. unsigned char *bufin_read = NULL;
  392. fd_set fds_w;
  393. fd_set fds_r;
  394. /* read refers to reading from fd_tun, writing to stdout */
  395. int read_open = 1;
  396. /* write refers to reading from stdin, writing to fd_tun */
  397. int write_open = 1;
  398. while ((1 == read_open) && (1 == write_open))
  399. {
  400. FD_ZERO (&fds_w);
  401. FD_ZERO (&fds_r);
  402. /*
  403. * We are supposed to read and the buffer is empty
  404. * -> select on read from tun
  405. */
  406. if (read_open && (0 == buftun_size))
  407. FD_SET (fd_tun, &fds_r);
  408. /*
  409. * We are supposed to read and the buffer is not empty
  410. * -> select on write to stdout
  411. */
  412. if (read_open && (0 != buftun_size))
  413. FD_SET (1, &fds_w);
  414. /*
  415. * We are supposed to write and the buffer is empty
  416. * -> select on read from stdin
  417. */
  418. if (write_open && (NULL == bufin_read))
  419. FD_SET (0, &fds_r);
  420. /*
  421. * We are supposed to write and the buffer is not empty
  422. * -> select on write to tun
  423. */
  424. if (write_open && (NULL != bufin_read))
  425. FD_SET (fd_tun, &fds_w);
  426. int r = select (fd_tun + 1, &fds_r, &fds_w, NULL, NULL);
  427. if (-1 == r)
  428. {
  429. if (EINTR == errno)
  430. continue;
  431. fprintf (stderr, "select failed: %s\n", strerror (errno));
  432. exit (1);
  433. }
  434. if (r > 0)
  435. {
  436. if (FD_ISSET (fd_tun, &fds_r))
  437. {
  438. buftun_size =
  439. read (fd_tun, buftun + sizeof (struct GNUNET_MessageHeader),
  440. MAX_SIZE - sizeof (struct GNUNET_MessageHeader));
  441. if (-1 == buftun_size)
  442. {
  443. fprintf (stderr,
  444. "read-error: %s\n",
  445. strerror (errno));
  446. shutdown (fd_tun, SHUT_RD);
  447. shutdown (1, SHUT_WR);
  448. read_open = 0;
  449. buftun_size = 0;
  450. }
  451. else if (0 == buftun_size)
  452. {
  453. #if DEBUG
  454. fprintf (stderr, "EOF on tun\n");
  455. #endif
  456. shutdown (fd_tun, SHUT_RD);
  457. shutdown (1, SHUT_WR);
  458. read_open = 0;
  459. buftun_size = 0;
  460. }
  461. else
  462. {
  463. buftun_read = buftun;
  464. struct GNUNET_MessageHeader *hdr =
  465. (struct GNUNET_MessageHeader *) buftun;
  466. buftun_size += sizeof (struct GNUNET_MessageHeader);
  467. hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
  468. hdr->size = htons (buftun_size);
  469. }
  470. }
  471. else if (FD_ISSET (1, &fds_w))
  472. {
  473. ssize_t written = write (1, buftun_read, buftun_size);
  474. if (-1 == written)
  475. {
  476. #if !DEBUG
  477. if (errno != EPIPE)
  478. #endif
  479. fprintf (stderr,
  480. "write-error to stdout: %s\n",
  481. strerror (errno));
  482. shutdown (fd_tun, SHUT_RD);
  483. shutdown (1, SHUT_WR);
  484. read_open = 0;
  485. buftun_size = 0;
  486. }
  487. else if (0 == written)
  488. {
  489. fprintf (stderr, "write returned 0!?\n");
  490. exit (1);
  491. }
  492. else
  493. {
  494. buftun_size -= written;
  495. buftun_read += written;
  496. }
  497. }
  498. if (FD_ISSET (0, &fds_r))
  499. {
  500. bufin_size = read (0, bufin + bufin_rpos, MAX_SIZE - bufin_rpos);
  501. if (-1 == bufin_size)
  502. {
  503. fprintf (stderr, "read-error: %s\n", strerror (errno));
  504. shutdown (0, SHUT_RD);
  505. shutdown (fd_tun, SHUT_WR);
  506. write_open = 0;
  507. bufin_size = 0;
  508. }
  509. else if (0 == bufin_size)
  510. {
  511. #if DEBUG
  512. fprintf (stderr, "EOF on stdin\n");
  513. #endif
  514. shutdown (0, SHUT_RD);
  515. shutdown (fd_tun, SHUT_WR);
  516. write_open = 0;
  517. bufin_size = 0;
  518. }
  519. else
  520. {
  521. struct GNUNET_MessageHeader *hdr;
  522. PROCESS_BUFFER:
  523. bufin_rpos += bufin_size;
  524. if (bufin_rpos < sizeof (struct GNUNET_MessageHeader))
  525. continue;
  526. hdr = (struct GNUNET_MessageHeader *) bufin;
  527. if (ntohs (hdr->type) != GNUNET_MESSAGE_TYPE_VPN_HELPER)
  528. {
  529. fprintf (stderr, "protocol violation!\n");
  530. exit (1);
  531. }
  532. if (ntohs (hdr->size) > bufin_rpos)
  533. continue;
  534. bufin_read = bufin + sizeof (struct GNUNET_MessageHeader);
  535. bufin_size = ntohs (hdr->size) - sizeof (struct GNUNET_MessageHeader);
  536. bufin_rpos -= bufin_size + sizeof (struct GNUNET_MessageHeader);
  537. }
  538. }
  539. else if (FD_ISSET (fd_tun, &fds_w))
  540. {
  541. ssize_t written = write (fd_tun, bufin_read, bufin_size);
  542. if (-1 == written)
  543. {
  544. fprintf (stderr, "write-error to tun: %s\n", strerror (errno));
  545. shutdown (0, SHUT_RD);
  546. shutdown (fd_tun, SHUT_WR);
  547. write_open = 0;
  548. bufin_size = 0;
  549. }
  550. else if (0 == written)
  551. {
  552. fprintf (stderr, "write returned 0!?\n");
  553. exit (1);
  554. }
  555. else
  556. {
  557. bufin_size -= written;
  558. bufin_read += written;
  559. if (0 == bufin_size)
  560. {
  561. memmove (bufin, bufin_read, bufin_rpos);
  562. bufin_read = NULL; /* start reading again */
  563. bufin_size = 0;
  564. goto PROCESS_BUFFER;
  565. }
  566. }
  567. }
  568. }
  569. }
  570. }
  571. /**
  572. * Open VPN tunnel interface.
  573. *
  574. * @param argc must be 6
  575. * @param argv 0: binary name ("gnunet-helper-exit")
  576. * 1: tunnel interface name ("gnunet-exit")
  577. * 2: "physical" interface name ("eth0"), or "-" to not setup NAT
  578. * and routing
  579. * 3: IPv6 address ("::1"), or "-" to skip IPv6
  580. * 4: IPv6 netmask length in bits ("64") [ignored if #4 is "-"]
  581. * 5: IPv4 address ("1.2.3.4"), or "-" to skip IPv4
  582. * 6: IPv4 netmask ("255.255.0.0") [ignored if #4 is "-"]
  583. */
  584. int
  585. main (int argc, char **argv)
  586. {
  587. char dev[IFNAMSIZ];
  588. int fd_tun;
  589. int global_ret;
  590. if (7 != argc)
  591. {
  592. fprintf (stderr, "Fatal: must supply 6 arguments!\n");
  593. return 1;
  594. }
  595. if ( (0 == strcmp (argv[3], "-")) &&
  596. (0 == strcmp (argv[5], "-")) )
  597. {
  598. fprintf (stderr, "Fatal: disabling both IPv4 and IPv6 makes no sense.\n");
  599. return 1;
  600. }
  601. if (0 != strcmp (argv[2], "-"))
  602. {
  603. #ifdef IPTABLES
  604. if (0 == access (IPTABLES, X_OK))
  605. sbin_iptables = IPTABLES;
  606. else
  607. #endif
  608. if (0 == access ("/sbin/iptables", X_OK))
  609. sbin_iptables = "/sbin/iptables";
  610. else if (0 == access ("/usr/sbin/iptables", X_OK))
  611. sbin_iptables = "/usr/sbin/iptables";
  612. else
  613. {
  614. fprintf (stderr,
  615. "Fatal: executable iptables not found in approved directories: %s\n",
  616. strerror (errno));
  617. return 1;
  618. }
  619. #ifdef SYSCTL
  620. if (0 == access (SYSCTL, X_OK))
  621. sbin_sysctl = SYSCTL;
  622. else
  623. #endif
  624. if (0 == access ("/sbin/sysctl", X_OK))
  625. sbin_sysctl = "/sbin/sysctl";
  626. else if (0 == access ("/usr/sbin/sysctl", X_OK))
  627. sbin_sysctl = "/usr/sbin/sysctl";
  628. else
  629. {
  630. fprintf (stderr,
  631. "Fatal: executable sysctl not found in approved directories: %s\n",
  632. strerror (errno));
  633. return 1;
  634. }
  635. }
  636. strncpy (dev, argv[1], IFNAMSIZ);
  637. dev[IFNAMSIZ - 1] = '\0';
  638. if (-1 == (fd_tun = init_tun (dev)))
  639. {
  640. fprintf (stderr,
  641. "Fatal: could not initialize tun-interface `%s' with IPv6 %s/%s and IPv4 %s/%s\n",
  642. dev,
  643. argv[3],
  644. argv[4],
  645. argv[5],
  646. argv[6]);
  647. return 1;
  648. }
  649. if (0 != strcmp (argv[3], "-"))
  650. {
  651. {
  652. const char *address = argv[3];
  653. long prefix_len = atol (argv[4]);
  654. if ((prefix_len < 1) || (prefix_len > 127))
  655. {
  656. fprintf (stderr, "Fatal: prefix_len out of range\n");
  657. return 1;
  658. }
  659. set_address6 (dev, address, prefix_len);
  660. }
  661. if (0 != strcmp (argv[2], "-"))
  662. {
  663. char *const sysctl_args[] =
  664. {
  665. "sysctl", "-w", "net.ipv6.conf.all.forwarding=1", NULL
  666. };
  667. if (0 != fork_and_exec (sbin_sysctl,
  668. sysctl_args))
  669. {
  670. fprintf (stderr,
  671. "Failed to enable IPv6 forwarding. Will continue anyway.\n");
  672. }
  673. }
  674. }
  675. if (0 != strcmp (argv[5], "-"))
  676. {
  677. {
  678. const char *address = argv[5];
  679. const char *mask = argv[6];
  680. set_address4 (dev, address, mask);
  681. }
  682. if (0 != strcmp (argv[2], "-"))
  683. {
  684. {
  685. char *const sysctl_args[] =
  686. {
  687. "sysctl", "-w", "net.ipv4.ip_forward=1", NULL
  688. };
  689. if (0 != fork_and_exec (sbin_sysctl,
  690. sysctl_args))
  691. {
  692. fprintf (stderr,
  693. "Failed to enable IPv4 forwarding. Will continue anyway.\n");
  694. }
  695. }
  696. {
  697. char *const iptables_args[] =
  698. {
  699. "iptables", "-t", "nat", "-A", "POSTROUTING", "-o", argv[2], "-j", "MASQUERADE", NULL
  700. };
  701. if (0 != fork_and_exec (sbin_iptables,
  702. iptables_args))
  703. {
  704. fprintf (stderr,
  705. "Failed to enable IPv4 masquerading (NAT). Will continue anyway.\n");
  706. }
  707. }
  708. }
  709. }
  710. uid_t uid = getuid ();
  711. #ifdef HAVE_SETRESUID
  712. if (0 != setresuid (uid, uid, uid))
  713. {
  714. fprintf (stderr, "Failed to setresuid: %s\n", strerror (errno));
  715. global_ret = 2;
  716. goto cleanup;
  717. }
  718. #else
  719. if (0 != (setuid (uid) | seteuid (uid)))
  720. {
  721. fprintf (stderr, "Failed to setuid: %s\n", strerror (errno));
  722. global_ret = 2;
  723. goto cleanup;
  724. }
  725. #endif
  726. if (SIG_ERR == signal (SIGPIPE, SIG_IGN))
  727. {
  728. fprintf (stderr, "Failed to protect against SIGPIPE: %s\n",
  729. strerror (errno));
  730. /* no exit, we might as well die with SIGPIPE should it ever happen */
  731. }
  732. run (fd_tun);
  733. global_ret = 0;
  734. cleanup:
  735. (void) close (fd_tun);
  736. return global_ret;
  737. }
  738. /* end of gnunet-helper-exit.c */